00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdmisc.h"
00027
00028 #include "nel/misc/file.h"
00029 #include "nel/misc/debug.h"
00030 #include "nel/misc/big_file.h"
00031
00032 using namespace std;
00033
00034 namespace NLMISC
00035 {
00036
00037 uint32 CIFile::_NbBytesSerialized = 0;
00038 uint32 CIFile::_NbBytesLoaded = 0;
00039
00040
00041 CIFile::CIFile() : IStream(true)
00042 {
00043 _F = NULL;
00044 _Cache = NULL;
00045 _ReadPos = 0;
00046 _FileSize = 0;
00047 _BigFileOffset = 0;
00048 _IsInBigFile = false;
00049 _CacheFileOnOpen = false;
00050 _IsAsyncLoading = false;
00051 _AllowBNPCacheFileOnOpen= true;
00052 }
00053
00054
00055 CIFile::CIFile(const std::string &path, bool text) : IStream(true)
00056 {
00057 _F=NULL;
00058 _Cache = NULL;
00059 _ReadPos = 0;
00060 _FileSize = 0;
00061 _BigFileOffset = 0;
00062 _IsInBigFile = false;
00063 _CacheFileOnOpen = false;
00064 _IsAsyncLoading = false;
00065 _AllowBNPCacheFileOnOpen= true;
00066 open(path, text);
00067 }
00068
00069
00070 CIFile::~CIFile()
00071 {
00072 close();
00073 }
00074
00075
00076
00077 void CIFile::loadIntoCache()
00078 {
00079 const uint32 READPACKETSIZE = 64 * 1024;
00080 const uint32 INTERPACKETSLEEP = 5;
00081
00082 _Cache = new uint8[_FileSize];
00083 if(!_IsAsyncLoading)
00084 {
00085 fread (_Cache, _FileSize, 1, _F);
00086 }
00087 else
00088 {
00089 uint index= 0;
00090 while(index<_FileSize)
00091 {
00092 if( _NbBytesLoaded + (_FileSize-index) > READPACKETSIZE )
00093 {
00094 sint n= READPACKETSIZE-_NbBytesLoaded;
00095 n= max(n, 1);
00096 fread (_Cache+index, n, 1, _F);
00097 index+= n;
00098
00099 nlSleep (INTERPACKETSLEEP);
00100 _NbBytesLoaded= 0;
00101 }
00102 else
00103 {
00104 uint n= _FileSize-index;
00105 fread (_Cache+index, n, 1, _F);
00106 _NbBytesLoaded+= n;
00107 index+= n;
00108 }
00109 }
00110 }
00111 }
00112
00113
00114
00115 bool CIFile::open(const std::string &path, bool text)
00116 {
00117 close();
00118
00119
00120 if(path.empty ())
00121 return false;
00122
00123 char mode[3];
00124 mode[0] = 'r';
00125 mode[1] = (text)?'\0':'b';
00126 mode[2] = '\0';
00127
00128 _FileName = path;
00129 _ReadPos = 0;
00130
00131
00132 if (path.find('@') != string::npos)
00133 {
00134 _IsInBigFile = true;
00135 if(_AllowBNPCacheFileOnOpen)
00136 {
00137 _F = CBigFile::getInstance().getFile (path, _FileSize, _BigFileOffset, _CacheFileOnOpen, _AlwaysOpened);
00138 }
00139 else
00140 {
00141 bool dummy;
00142 _F = CBigFile::getInstance().getFile (path, _FileSize, _BigFileOffset, dummy, _AlwaysOpened);
00143 }
00144 if(_F != NULL)
00145 {
00146
00147 fseek (_F, _BigFileOffset, SEEK_SET);
00148
00149
00150 if (_CacheFileOnOpen)
00151 {
00152
00153 loadIntoCache();
00154
00155 if (!_AlwaysOpened)
00156 {
00157 fclose (_F);
00158 _F = NULL;
00159 }
00160 return (_Cache != NULL);
00161 }
00162 }
00163 }
00164 else
00165 {
00166 _IsInBigFile = false;
00167 _BigFileOffset = 0;
00168 _AlwaysOpened = false;
00169 _F = fopen (path.c_str(), mode);
00170 if (_F != NULL)
00171 {
00172 fseek (_F, 0, SEEK_END);
00173 _FileSize = ftell(_F);
00174 fseek (_F, 0, SEEK_SET);
00175 }
00176 else
00177 {
00178 _FileSize = 0;
00179 }
00180
00181 if ((_CacheFileOnOpen) && (_F != NULL))
00182 {
00183
00184 loadIntoCache();
00185
00186 fclose (_F);
00187 _F = NULL;
00188 return (_Cache != NULL);
00189 }
00190 }
00191
00192 return (_F != NULL);
00193 }
00194
00195
00196 void CIFile::setCacheFileOnOpen (bool newState)
00197 {
00198 _CacheFileOnOpen = newState;
00199 }
00200
00201
00202 void CIFile::setAsyncLoading (bool newState)
00203 {
00204 _IsAsyncLoading = true;
00205 }
00206
00207
00208
00209 void CIFile::close()
00210 {
00211 if (_CacheFileOnOpen)
00212 {
00213 if (_Cache)
00214 {
00215 delete _Cache;
00216 _Cache = NULL;
00217 }
00218 }
00219 else
00220 {
00221 if (_IsInBigFile)
00222 {
00223 if (!_AlwaysOpened)
00224 {
00225 if (_F)
00226 {
00227 fclose (_F);
00228 _F = NULL;
00229 }
00230 }
00231 }
00232 else
00233 {
00234 if (_F)
00235 {
00236 fclose (_F);
00237 _F = NULL;
00238 }
00239 }
00240 }
00241 resetPtrTable();
00242 }
00243
00244
00245 void CIFile::flush()
00246 {
00247 if (_CacheFileOnOpen)
00248 {
00249 }
00250 else
00251 {
00252 if (_F)
00253 {
00254 fflush (_F);
00255 }
00256 }
00257 }
00258
00259
00260 void CIFile::getline (char *buffer, uint32 bufferSize)
00261 {
00262 if (bufferSize == 0)
00263 return;
00264
00265 uint read = 0;
00266 while (true)
00267 {
00268 if (read == bufferSize -1)
00269 {
00270 *buffer = '\0';
00271 return;
00272 }
00273
00274 try
00275 {
00276
00277 serialBuffer ((uint8 *)buffer, 1);
00278 }
00279 catch (EFile &)
00280 {
00281 *buffer = '\0';
00282 return;
00283 }
00284
00285 if (*buffer == '\n')
00286 {
00287 *buffer = '\0';
00288 return;
00289 }
00290
00291
00292 if (*buffer != '\r')
00293 buffer++;
00294 }
00295
00296 }
00297
00298
00299
00300 bool CIFile::eof ()
00301 {
00302 return _ReadPos >= (sint32)_FileSize;
00303 }
00304
00305
00306 void CIFile::serialBuffer(uint8 *buf, uint len) throw(EReadError)
00307 {
00308
00309 if ((_ReadPos < 0) || ((_ReadPos+len) > _FileSize))
00310 throw EReadError (_FileName);
00311 if ((_CacheFileOnOpen) && (_Cache == NULL))
00312 throw EFileNotOpened (_FileName);
00313 if ((!_CacheFileOnOpen) && (_F == NULL))
00314 throw EFileNotOpened (_FileName);
00315
00316 if (_IsAsyncLoading)
00317 {
00318 _NbBytesSerialized += len;
00319 if (_NbBytesSerialized > 64 * 1024)
00320 {
00321 nlSleep (5);
00322 _NbBytesSerialized = 0;
00323 }
00324 }
00325
00326 if (_CacheFileOnOpen)
00327 {
00328 memcpy (buf, _Cache + _ReadPos, len);
00329 _ReadPos += len;
00330 }
00331 else
00332 {
00333 if (fread(buf, 1, len, _F) < len)
00334 throw EReadError(_FileName);
00335 _ReadPos += len;
00336 }
00337 }
00338
00339
00340 void CIFile::serialBit(bool &bit) throw(EReadError)
00341 {
00342
00343 uint8 v=bit;
00344 serialBuffer(&v, 1);
00345 bit=(v!=0);
00346 }
00347
00348
00349 bool CIFile::seek (sint32 offset, IStream::TSeekOrigin origin) throw(EStream)
00350 {
00351 if ((_CacheFileOnOpen) && (_Cache == NULL))
00352 return false;
00353 if ((!_CacheFileOnOpen) && (_F == NULL))
00354 return false;
00355
00356 switch (origin)
00357 {
00358 case IStream::begin:
00359 _ReadPos = offset;
00360 break;
00361 case IStream::current:
00362 _ReadPos = _ReadPos + offset;
00363 break;
00364 case IStream::end:
00365 _ReadPos = _FileSize + offset;
00366 break;
00367 default:
00368 nlstop;
00369 }
00370
00371 if (_CacheFileOnOpen)
00372 return true;
00373
00374
00375 if (fseek(_F, _BigFileOffset+_ReadPos, SEEK_SET) != 0)
00376 return false;
00377 return true;
00378 }
00379
00380
00381 sint32 CIFile::getPos () throw(EStream)
00382 {
00383 return _ReadPos;
00384 }
00385
00386
00387
00388 std::string CIFile::getStreamName() const
00389 {
00390 return _FileName;
00391 }
00392
00393
00394
00395 void CIFile::allowBNPCacheFileOnOpen(bool newState)
00396 {
00397 _AllowBNPCacheFileOnOpen= newState;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407 COFile::COFile() : IStream(false)
00408 {
00409 _F=NULL;
00410 _FileName = "";
00411 }
00412
00413
00414 COFile::COFile(const std::string &path, bool append, bool text) : IStream(false)
00415 {
00416 _F=NULL;
00417 open(path, append, text);
00418 }
00419
00420
00421 COFile::~COFile()
00422 {
00423 close();
00424 }
00425
00426 bool COFile::open(const std::string &path, bool append, bool text)
00427 {
00428 close();
00429
00430
00431 if(path.empty ())
00432 return false;
00433
00434 char mode[3];
00435 mode[0] = (append)?'a':'w';
00436 mode[1] = (text)?'\0':'b';
00437 mode[2] = '\0';
00438
00439 _F=fopen(path.c_str(), mode);
00440 _FileName = path;
00441
00442 return _F!=NULL;
00443 }
00444
00445 void COFile::close()
00446 {
00447 if(_F)
00448 {
00449 fclose(_F);
00450 _F=NULL;
00451 }
00452 resetPtrTable();
00453 }
00454
00455 void COFile::flush()
00456 {
00457 if(_F)
00458 {
00459 fflush(_F);
00460 }
00461 }
00462
00463
00464
00465 void COFile::serialBuffer(uint8 *buf, uint len) throw(EWriteError)
00466 {
00467 if(!_F)
00468 throw EFileNotOpened(_FileName);
00469 if(fwrite(buf, 1, len, _F) < len)
00470 throw EWriteError(_FileName);
00471 }
00472
00473 void COFile::serialBit(bool &bit) throw(EWriteError)
00474 {
00475
00476 uint8 v=bit;
00477 serialBuffer(&v, 1);
00478 }
00479
00480 bool COFile::seek (sint32 offset, IStream::TSeekOrigin origin) throw(EStream)
00481 {
00482 if (_F)
00483 {
00484 int origin_c = SEEK_SET;
00485 switch (origin)
00486 {
00487 case IStream::begin:
00488 origin_c=SEEK_SET;
00489 break;
00490 case IStream::current:
00491 origin_c=SEEK_CUR;
00492 break;
00493 case IStream::end:
00494 origin_c=SEEK_END;
00495 break;
00496 default:
00497 nlstop;
00498 }
00499
00500 if (fseek (_F, offset, origin_c)!=0)
00501 return false;
00502 return true;
00503 }
00504 return false;
00505 }
00506
00507 sint32 COFile::getPos () throw(EStream)
00508 {
00509 if (_F)
00510 {
00511 return ftell (_F);
00512 }
00513 return 0;
00514 }
00515
00516
00517 std::string COFile::getStreamName() const
00518 {
00519 return _FileName;
00520 }
00521
00522
00523 }