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/big_file.h"
00029 #include "nel/misc/path.h"
00030
00031 using namespace std;
00032
00033 namespace NLMISC {
00034
00035 CBigFile *CBigFile::_Singleton = NULL;
00036
00037
00038
00039 CBigFile::CThreadFileArray::CThreadFileArray()
00040 {
00041 _CurrentId= 0;
00042 }
00043
00044 uint32 CBigFile::CThreadFileArray::allocate()
00045 {
00046 return _CurrentId++;
00047 }
00048
00049 CBigFile::CHandleFile &CBigFile::CThreadFileArray::get(uint32 index)
00050 {
00051
00052 vector<CHandleFile> *ptr= (vector<CHandleFile>*)_TDS.getPointer();
00053 if(ptr==NULL)
00054 {
00055 ptr= new vector<CHandleFile>;
00056 _TDS.setPointer(ptr);
00057 }
00058
00059
00060 if(index>=ptr->size())
00061 {
00062 ptr->resize(index+1);
00063 }
00064
00065 return (*ptr)[index];
00066 }
00067
00068
00069
00070 CBigFile::CBigFile ()
00071 {
00072 }
00073
00074
00075 CBigFile &CBigFile::getInstance ()
00076 {
00077 if (_Singleton == NULL)
00078 {
00079 _Singleton = new CBigFile();
00080 }
00081 return *_Singleton;
00082 }
00083
00084
00085 bool CBigFile::add (const std::string &sBigFileName, uint32 nOptions)
00086 {
00087 BNP bnpTmp;
00088
00089 bnpTmp.BigFileName= sBigFileName;
00090
00091
00092 string bigfilenamealone = CFile::getFilename (sBigFileName);
00093 if (_BNPs.find(bigfilenamealone) != _BNPs.end())
00094 return false;
00095
00096
00097 bnpTmp.ThreadFileId= _ThreadFileArray.allocate();
00098
00099
00100 CHandleFile &handle= _ThreadFileArray.get(bnpTmp.ThreadFileId);
00101
00102 handle.File = fopen (sBigFileName.c_str(), "rb");
00103 if (handle.File == NULL)
00104 return false;
00105 fseek (handle.File, 0, SEEK_END);
00106 uint32 nFileSize = ftell (handle.File);
00107 fseek (handle.File, nFileSize-4, SEEK_SET);
00108 uint32 nOffsetFromBegining;
00109 fread (&nOffsetFromBegining, sizeof(uint32), 1, handle.File);
00110 fseek (handle.File, nOffsetFromBegining, SEEK_SET);
00111 uint32 nNbFile;
00112 fread (&nNbFile, sizeof(uint32), 1, handle.File);
00113 for (uint32 i = 0; i < nNbFile; ++i)
00114 {
00115 char FileName[256];
00116 uint8 nStringSize;
00117 fread (&nStringSize, 1, 1, handle.File);
00118 fread (FileName, 1, nStringSize, handle.File);
00119 FileName[nStringSize] = 0;
00120 uint32 nFileSize;
00121 fread (&nFileSize, sizeof(uint32), 1, handle.File);
00122 uint32 nFilePos;
00123 fread (&nFilePos, sizeof(uint32), 1, handle.File);
00124 BNPFile bnpfTmp;
00125 bnpfTmp.Pos = nFilePos;
00126 bnpfTmp.Size = nFileSize;
00127 bnpTmp.Files.insert (make_pair(strlwr(string(FileName)), bnpfTmp));
00128 }
00129 fseek (handle.File, 0, SEEK_SET);
00130
00131 if (nOptions&BF_CACHE_FILE_ON_OPEN)
00132 bnpTmp.CacheFileOnOpen = true;
00133 else
00134 bnpTmp.CacheFileOnOpen = false;
00135
00136 if (!(nOptions&BF_ALWAYS_OPENED))
00137 {
00138 fclose (handle.File);
00139 handle.File = NULL;
00140 bnpTmp.AlwaysOpened = false;
00141 }
00142 else
00143 {
00144 bnpTmp.AlwaysOpened = true;
00145 }
00146
00147 _BNPs.insert (make_pair(strlwr(bigfilenamealone), bnpTmp));
00148
00149 return true;
00150 }
00151
00152
00153 void CBigFile::remove (const std::string &sBigFileName)
00154 {
00155 if (_BNPs.find (sBigFileName) != _BNPs.end())
00156 {
00157 map<string, BNP>::iterator it = _BNPs.find (sBigFileName);
00158 BNP &rbnp = it->second;
00159
00160
00161
00162
00163
00164
00165 CHandleFile &handle= _ThreadFileArray.get(rbnp.ThreadFileId);
00166
00167 if (handle.File != NULL)
00168 {
00169 fclose (handle.File);
00170 handle.File= NULL;
00171 }
00172 _BNPs.erase (it);
00173 }
00174 }
00175
00176
00177 bool CBigFile::isBigFileAdded(const std::string &sBigFileName)
00178 {
00179
00180 string bigfilenamealone = CFile::getFilename (sBigFileName);
00181 return _BNPs.find(bigfilenamealone) != _BNPs.end();
00182 }
00183
00184
00185 void CBigFile::list (const std::string &sBigFileName, std::vector<std::string> &vAllFiles)
00186 {
00187 string lwrFileName = strlwr (sBigFileName);
00188 if (_BNPs.find (lwrFileName) == _BNPs.end())
00189 return;
00190 vAllFiles.clear ();
00191 BNP &rbnp = _BNPs.find (lwrFileName)->second;
00192 map<string,BNPFile>::iterator it = rbnp.Files.begin();
00193 while (it != rbnp.Files.end())
00194 {
00195 vAllFiles.push_back (it->first);
00196 ++it;
00197 }
00198 }
00199
00200
00201 void CBigFile::removeAll ()
00202 {
00203 while (_BNPs.begin() != _BNPs.end())
00204 {
00205 remove (_BNPs.begin()->first);
00206 }
00207 }
00208
00209
00210 FILE* CBigFile::getFile (const std::string &sFileName, uint32 &rFileSize,
00211 uint32 &rBigFileOffset, bool &rCacheFileOnOpen, bool &rAlwaysOpened)
00212 {
00213 string zeFileName, zeBigFileName, lwrFileName = strlwr (sFileName);
00214 uint32 i, nPos = sFileName.find ('@');
00215 if (nPos == string::npos)
00216 {
00217 nlwarning ("Couldn't load '%s'", sFileName.c_str());
00218 return NULL;
00219 }
00220
00221 for (i = 0; i < nPos; ++i)
00222 zeBigFileName += lwrFileName[i];
00223 ++i;
00224 for (; i < lwrFileName.size(); ++i)
00225 zeFileName += lwrFileName[i];
00226
00227 if (_BNPs.find (zeBigFileName) == _BNPs.end())
00228 {
00229 nlwarning ("Couldn't load '%s'", sFileName.c_str());
00230 return NULL;
00231 }
00232
00233 BNP &rbnp = _BNPs.find (zeBigFileName)->second;
00234 if (rbnp.Files.find (zeFileName) == rbnp.Files.end())
00235 {
00236 nlwarning ("Couldn't load '%s'", sFileName.c_str());
00237 return NULL;
00238 }
00239
00240 BNPFile &rbnpfile = rbnp.Files.find (zeFileName)->second;
00241
00242
00243 CHandleFile &handle= _ThreadFileArray.get(rbnp.ThreadFileId);
00244
00245
00246
00247 if(handle.File== NULL)
00248 {
00249 handle.File = fopen (rbnp.BigFileName.c_str(), "rb");
00250 if (handle.File == NULL)
00251 return NULL;
00252 }
00253
00254 rCacheFileOnOpen = rbnp.CacheFileOnOpen;
00255 rAlwaysOpened = rbnp.AlwaysOpened;
00256 rBigFileOffset = rbnpfile.Pos;
00257 rFileSize = rbnpfile.Size;
00258 return handle.File;
00259 }
00260
00261 }