# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

file.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // can't open empty filename
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         // Bigfile access requested ?
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                         // Start to load the bigfile at the file offset.
00147                         fseek (_F, _BigFileOffset, SEEK_SET);
00148 
00149                         // Load into cache ?
00150                         if (_CacheFileOnOpen)
00151                         {
00152                                 // load file in the cache
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                         // load file in the cache
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                         // read one byte
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                 // skip '\r' char
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         // Check the read pos
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         // Simple for now.
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         // seek in the file. NB: if not in bigfile, _BigFileOffset==0.
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         // can't open empty filename
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         // Simple for now.
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 }