00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_LOAD_FORM_H
00027 #define NL_LOAD_FORM_H
00028
00029 #include "nel/misc/types_nl.h"
00030
00031 #include <map>
00032 #include <string>
00033 #include <vector>
00034
00035 #include "nel/misc/path.h"
00036 #include "nel/misc/file.h"
00037
00038 #include "nel/georges/u_form_loader.h"
00039 #include "nel/georges/u_form.h"
00040 #include "nel/misc/sheet_id.h"
00041
00099 template <class T>
00100 void loadForm (const std::string &sheetFilter, const std::string &packedFilename, std::map<NLMISC::CSheetId, T> &container, bool updatePackedSheet=true)
00101 {
00102 std::vector<std::string> vs;
00103 vs.push_back(sheetFilter);
00104 loadForm(vs, packedFilename, container, updatePackedSheet);
00105 }
00106
00112 template <class T>
00113 void loadForm (const std::vector<std::string> &sheetFilters, const std::string &packedFilename, std::map<NLMISC::CSheetId, T> &container, bool updatePackedSheet=true)
00114 {
00115
00116 nlassert (packedFilename.find (".packed_sheets") != std::string::npos);
00117
00118 std::string packedFilenamePath = NLMISC::CPath::lookup(packedFilename, false);
00119 if (packedFilenamePath.empty())
00120 {
00121 packedFilenamePath = packedFilename;
00122 }
00123
00124
00125 NLMISC::CSheetId::init(updatePackedSheet);
00126
00127 bool olde, newe;
00128 NLMISC::CIFile::getVersionException(olde, newe);
00129
00130 try
00131 {
00132 NLMISC::CIFile ifile;
00133 ifile.setCacheFileOnOpen(true);
00134 ifile.open (packedFilenamePath);
00135
00136
00137 nlinfo ("loadForm(): Loading packed file '%s'", packedFilename.c_str());
00138
00139 uint32 nbEntries;
00140 ifile.serial (nbEntries);
00141 ifile.setVersionException (true, true);
00142 uint ver = T::getVersion ();
00143 ifile.serialVersion(ver);
00144 ifile.serialCont (container);
00145 ifile.close ();
00146 }
00147 catch (NLMISC::Exception &e)
00148 {
00149 nlinfo ("loadForm(): Exception during reading the packed file, I'll reconstruct it (%s)", e.what());
00150
00151 container.clear ();
00152 }
00153 NLMISC::CIFile::setVersionException(olde, newe);
00154
00155
00156 if (!updatePackedSheet)
00157 {
00158 nlinfo ("Don't update the packed sheet with real sheet");
00159 return;
00160 }
00161
00162
00163 std::vector<NLMISC::CSheetId> sheetIds;
00164 std::vector<std::string> filenames;
00165 for (uint i = 0; i < sheetFilters.size(); i++)
00166 NLMISC::CSheetId::buildIdVector(sheetIds, filenames, sheetFilters[i]);
00167
00168
00169 if (sheetIds.empty())
00170 return;
00171
00172
00173 std::map<NLMISC::CSheetId, bool> sheetToRemove;
00174 for (typename std::map<NLMISC::CSheetId, T>::iterator it = container.begin(); it != container.end(); it++)
00175 {
00176 sheetToRemove.insert (make_pair((*it).first, true));
00177 }
00178
00179
00180 uint32 packedFiledate = NLMISC::CFile::getFileModificationDate(packedFilenamePath);
00181
00182 bool containerChanged = false;
00183
00184 NLGEORGES::UFormLoader *formLoader = NULL;
00185
00186 std::vector<uint> NeededToRecompute;
00187
00188 for (uint k = 0; k < filenames.size(); k++)
00189 {
00190 std::string p = NLMISC::CPath::lookup (filenames[k], false, false);
00191 if (p.empty()) continue;
00192 uint32 d = NLMISC::CFile::getFileModificationDate(p);
00193
00194
00195 sheetToRemove[sheetIds[k]] = false;
00196
00197 if( d > packedFiledate || container.find (sheetIds[k]) == container.end())
00198 {
00199 NeededToRecompute.push_back(k);
00200 }
00201 }
00202
00203 nlinfo ("%d sheets checked, %d need to be recomputed", filenames.size(), NeededToRecompute.size());
00204
00205 NLMISC::TTime last = NLMISC::CTime::getLocalTime ();
00206 NLMISC::TTime start = NLMISC::CTime::getLocalTime ();
00207
00208 NLMISC::CSmartPtr<NLGEORGES::UForm> form;
00209
00210 for (uint j = 0; j < NeededToRecompute.size(); j++)
00211 {
00212 if(NLMISC::CTime::getLocalTime () > last + 5000)
00213 {
00214 last = NLMISC::CTime::getLocalTime ();
00215 if(j>0)
00216 nlinfo ("%.0f%% completed (%d/%d), %d seconds remaining", (float)j*100.0/NeededToRecompute.size(),j,NeededToRecompute.size(), (NeededToRecompute.size()-j)*(last-start)/j/1000);
00217 }
00218
00219
00220 if (formLoader == NULL)
00221 {
00222 WarningLog->addNegativeFilter("CFormLoader: Can't open the form file");
00223 formLoader = NLGEORGES::UFormLoader::createLoader ();
00224 }
00225
00226
00227 form = formLoader->loadForm (sheetIds[NeededToRecompute[j]].toString().c_str ());
00228 if (form)
00229 {
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 typedef typename std::map<NLMISC::CSheetId, T>::iterator TType1;
00240 typedef typename std::pair<TType1, bool> TType2;
00241 TType2 res = container.insert(std::make_pair(sheetIds[NeededToRecompute[j]],T()));
00242
00243 (*res.first).second.readGeorges (form, sheetIds[NeededToRecompute[j]]);
00244 containerChanged = true;
00245 }
00246 }
00247
00248 nlinfo ("%d seconds to recompute %d sheets", (uint32)(NLMISC::CTime::getLocalTime()-start)/1000, NeededToRecompute.size());
00249
00250
00251 if (formLoader != NULL)
00252 {
00253 NLGEORGES::UFormLoader::releaseLoader (formLoader);
00254 WarningLog->removeFilter ("CFormLoader: Can't open the form file");
00255 }
00256
00257
00258 for (std::map<NLMISC::CSheetId, bool>::iterator it2 = sheetToRemove.begin(); it2 != sheetToRemove.end(); it2++)
00259 {
00260 if((*it2).second)
00261 {
00262 nlinfo ("the sheet '%s' is not in the directory, remove it from container", (*it2).first.toString().c_str());
00263 container.erase((*it2).first);
00264 containerChanged = true;
00265 }
00266 }
00267
00268
00269 try
00270 {
00271 if(containerChanged)
00272 {
00273 NLMISC::COFile ofile;
00274 ofile.open(packedFilenamePath);
00275 uint ver = T::getVersion ();
00276 uint32 nbEntries = sheetIds.size();
00277 ofile.serial (nbEntries);
00278 ofile.serialVersion(ver);
00279 ofile.serialCont(container);
00280 ofile.close ();
00281 }
00282 }
00283 catch (NLMISC::Exception &e)
00284 {
00285 nlinfo ("loadForm(): Exception during saving the packed file, it will be recreated next launch (%s)", e.what());
00286 }
00287
00288
00289 sheetIds.clear ();
00290 filenames.clear ();
00291 }
00292
00293
00299 template <class T>
00300 void loadForm (const std::string &sheetFilter, const std::string &packedFilename, std::map<std::string, T> &container, bool updatePackedSheet=true)
00301 {
00302 std::vector<std::string> vs;
00303 vs.push_back(sheetFilter);
00304 loadForm(vs, packedFilename, container, updatePackedSheet);
00305 }
00306
00307
00313 template <class T>
00314 void loadForm (const std::vector<std::string> &sheetFilters, const std::string &packedFilename, std::map<std::string, T> &container, bool updatePackedSheet=true)
00315 {
00316
00317 nlassert (packedFilename.find (".packed_sheets") != std::string::npos);
00318
00319 std::string packedFilenamePath = NLMISC::CPath::lookup(packedFilename, false);
00320 if (packedFilenamePath.empty())
00321 {
00322 packedFilenamePath = packedFilename;
00323 }
00324
00325
00326
00327
00328 bool olde, newe;
00329 NLMISC::CIFile::getVersionException(olde, newe);
00330
00331 try
00332 {
00333 NLMISC::CIFile ifile;
00334 ifile.setCacheFileOnOpen(true);
00335 ifile.open (packedFilenamePath);
00336
00337
00338 nlinfo ("loadForm(): Loading packed file '%s'", packedFilename.c_str());
00339
00340 uint32 nbEntries;
00341 ifile.serial (nbEntries);
00342 ifile.setVersionException (true, true);
00343 uint ver = T::getVersion ();
00344 ifile.serialVersion(ver);
00345 ifile.serialCont (container);
00346 ifile.close ();
00347 }
00348 catch (NLMISC::Exception &e)
00349 {
00350 nlinfo ("loadForm(): Exception during reading the packed file, I'll reconstruct it (%s)", e.what());
00351
00352 container.clear ();
00353 }
00354 NLMISC::CIFile::setVersionException(olde, newe);
00355
00356
00357 if (!updatePackedSheet)
00358 {
00359 nlinfo ("Don't update the packed sheet with real sheet");
00360 return;
00361 }
00362
00363
00364
00365 std::vector<std::string> sheetNames;
00366
00367
00368 {
00369 std::vector<std::string>::const_iterator first(sheetFilters.begin()), last(sheetFilters.end());
00370 for (; first != last; ++first)
00371 NLMISC::CPath::getFileList(*first, sheetNames);
00372
00373 }
00374
00375
00376 if (sheetNames.empty())
00377 return;
00378
00379
00380 std::map<std::string, bool> sheetToRemove;
00381 for (typename std::map<std::string, T>::iterator it = container.begin(); it != container.end(); ++it)
00382 {
00383 sheetToRemove.insert (make_pair((*it).first, true));
00384 }
00385
00386
00387 uint32 packedFiledate = NLMISC::CFile::getFileModificationDate(packedFilenamePath);
00388
00389 bool containerChanged = false;
00390
00391 NLGEORGES::UFormLoader *formLoader = NULL;
00392
00393 std::vector<uint> NeededToRecompute;
00394
00395 for (uint k = 0; k < sheetNames.size(); k++)
00396 {
00397 std::string p = NLMISC::CPath::lookup (sheetNames[k], false, false);
00398 if (p.empty()) continue;
00399 uint32 d = NLMISC::CFile::getFileModificationDate(p);
00400
00401
00402 sheetToRemove[sheetNames[k]] = false;
00403
00404 if( d > packedFiledate || container.find (sheetNames[k]) == container.end())
00405 {
00406 NeededToRecompute.push_back(k);
00407 }
00408 }
00409
00410 nlinfo ("%d sheets checked, %d need to be recomputed", sheetNames.size(), NeededToRecompute.size());
00411
00412 NLMISC::TTime lastTime = NLMISC::CTime::getLocalTime ();
00413 NLMISC::TTime start = NLMISC::CTime::getLocalTime ();
00414
00415 NLMISC::CSmartPtr<NLGEORGES::UForm> form;
00416
00417 for (uint j = 0; j < NeededToRecompute.size(); j++)
00418 {
00419 if(NLMISC::CTime::getLocalTime () > lastTime + 5000)
00420 {
00421 lastTime = NLMISC::CTime::getLocalTime ();
00422 if(j>0)
00423 nlinfo ("%.0f%% completed (%d/%d), %d seconds remaining", (float)j*100.0/NeededToRecompute.size(),j,NeededToRecompute.size(), (NeededToRecompute.size()-j)*(lastTime-start)/j/1000);
00424 }
00425
00426
00427 if (formLoader == NULL)
00428 {
00429 WarningLog->addNegativeFilter("CFormLoader: Can't open the form file");
00430 formLoader = NLGEORGES::UFormLoader::createLoader ();
00431 }
00432
00433
00434 form = formLoader->loadForm (sheetNames[NeededToRecompute[j]].c_str ());
00435 if (form)
00436 {
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 typedef typename std::map<std::string, T>::iterator TType1;
00447 typedef typename std::pair<TType1, bool> TType2;
00448 TType2 res = container.insert(std::make_pair(sheetNames[NeededToRecompute[j]],T()));
00449
00450 (*res.first).second.readGeorges (form, sheetNames[NeededToRecompute[j]]);
00451 containerChanged = true;
00452 }
00453 }
00454
00455 nlinfo ("%d seconds to recompute %d sheets", (uint32)(NLMISC::CTime::getLocalTime()-start)/1000, NeededToRecompute.size());
00456
00457
00458 if (formLoader != NULL)
00459 {
00460 NLGEORGES::UFormLoader::releaseLoader (formLoader);
00461 WarningLog->removeFilter ("CFormLoader: Can't open the form file");
00462 }
00463
00464
00465 for (std::map<std::string, bool>::iterator it2 = sheetToRemove.begin(); it2 != sheetToRemove.end(); it2++)
00466 {
00467 if((*it2).second)
00468 {
00469 nlinfo ("the sheet '%s' is not in the directory, remove it from container", (*it2).first.c_str());
00470
00471 container.find((*it2).first)->second.removed();
00472 container.erase((*it2).first);
00473 containerChanged = true;
00474 }
00475 }
00476
00477
00478 try
00479 {
00480 if(containerChanged)
00481 {
00482 NLMISC::COFile ofile;
00483 ofile.open(packedFilenamePath);
00484 uint ver = T::getVersion ();
00485 uint32 nbEntries = sheetNames.size();
00486 ofile.serial (nbEntries);
00487 ofile.serialVersion(ver);
00488 ofile.serialCont(container);
00489 ofile.close ();
00490 }
00491 }
00492 catch (NLMISC::Exception &e)
00493 {
00494 nlinfo ("loadForm(): Exception during saving the packed file, it will be recreated next launch (%s)", e.what());
00495 }
00496
00497
00498
00499 sheetNames.clear ();
00500 }
00501 #endif // NL_LOAD_FORM_H
00502
00503