# 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  

load_form.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 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 #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         // check the extension (i know that file like "foo.packed_sheetsbar" will be accepted but this check is enough...)
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         // make sure the CSheetId singleton has been properly initialised
00125         NLMISC::CSheetId::init(updatePackedSheet);
00126 
00127         bool olde, newe;
00128         NLMISC::CIFile::getVersionException(olde, newe);
00129         // load the packed sheet if exists
00130         try
00131         {
00132                 NLMISC::CIFile ifile;
00133                 ifile.setCacheFileOnOpen(true);
00134                 ifile.open (packedFilenamePath);
00135                 // an exception will be launch if the file is not the good version or if the file is not found
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                 // clear the container because it can contains partially loaded sheet so we must clean it before continue
00151                 container.clear ();
00152         }
00153         NLMISC::CIFile::setVersionException(olde, newe);
00154 
00155         // if we don't want to update packed sheet, we nothing more to do
00156         if (!updatePackedSheet)
00157         {
00158                 nlinfo ("Don't update the packed sheet with real sheet");
00159                 return;
00160         }
00161 
00162         // build a vector of the sheetFilters sheet ids (ie: "item")
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         // if there s no file, nothing to do
00169         if (sheetIds.empty())
00170                 return;
00171 
00172         // set up the current sheet in container to remove sheet that are in the container and not in the directory anymore
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         // check if we need to create a new .pitems or just read it
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                 // no need to remove this sheet
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                 // create the georges loader if necessary
00220                 if (formLoader == NULL)
00221                 {
00222                         WarningLog->addNegativeFilter("CFormLoader: Can't open the form file");
00223                         formLoader = NLGEORGES::UFormLoader::createLoader ();
00224                 }
00225 
00226                 // Load the form with given sheet id
00227                 form = formLoader->loadForm (sheetIds[NeededToRecompute[j]].toString().c_str ());
00228                 if (form)
00229                 {
00230 /*                      if (packedFiledate > 0)
00231                         {
00232                                 if (d > packedFiledate)
00233                                         nlinfo ("loadForm(): the sheet '%s' is newer than the packed one, I reload it", p.c_str());
00234                                 else
00235                                         nlinfo ("loadForm(): the sheet '%s' is not in the packed sheets, I load it", p.c_str());
00236                         }*/
00237                         
00238                         // add the new creature, it could be already loaded by the packed sheets but will be overwrite with the new one
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         // free the georges loader if necessary
00251         if (formLoader != NULL)
00252         {
00253                 NLGEORGES::UFormLoader::releaseLoader (formLoader);
00254                 WarningLog->removeFilter ("CFormLoader: Can't open the form file");
00255         }
00256 
00257         // we have now to remove sheet that are in the container and not exist anymore in the sheet directories
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         // now, save the new container in the packedfile
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         // housekeeping
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         // check the extension (i know that file like "foo.packed_sheetsbar" will be accepted but this check is enough...)
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         // make sure the CSheetId singleton has been properly initialised
00326 //      NLMISC::CSheetId::init(updatePackedSheet);
00327 
00328         bool olde, newe;
00329         NLMISC::CIFile::getVersionException(olde, newe);
00330         // load the packed sheet if exists
00331         try
00332         {
00333                 NLMISC::CIFile ifile;
00334                 ifile.setCacheFileOnOpen(true);
00335                 ifile.open (packedFilenamePath);
00336                 // an exception will be launch if the file is not the good version or if the file is not found
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                 // clear the container because it can contains partially loaded sheet so we must clean it before continue
00352                 container.clear ();
00353         }
00354         NLMISC::CIFile::setVersionException(olde, newe);
00355 
00356         // if we don't want to update packed sheet, we nothing more to do
00357         if (!updatePackedSheet)
00358         {
00359                 nlinfo ("Don't update the packed sheet with real sheet");
00360                 return;
00361         }
00362 
00363         // build a vector of the sheetFilters sheet ids (ie: "item")
00364 //      std::vector<std::string> sheetNames;
00365         std::vector<std::string> sheetNames;
00366 //      for (uint i = 0; i < sheetFilters.size(); i++)
00367 //              NLMISC::CSheetId::buildIdVector(sheetIds, filenames, sheetFilters[i]);
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         // if there s no file, nothing to do
00376         if (sheetNames.empty())
00377                 return;
00378 
00379         // set up the current sheet in container to remove sheet that are in the container and not in the directory anymore
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         // check if we need to create a new .pitems or just read it
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                 // no need to remove this sheet
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                 // create the georges loader if necessary
00427                 if (formLoader == NULL)
00428                 {
00429                         WarningLog->addNegativeFilter("CFormLoader: Can't open the form file");
00430                         formLoader = NLGEORGES::UFormLoader::createLoader ();
00431                 }
00432 
00433                 // Load the form with given sheet id
00434                 form = formLoader->loadForm (sheetNames[NeededToRecompute[j]].c_str ());
00435                 if (form)
00436                 {
00437 /*                      if (packedFiledate > 0)
00438                         {
00439                                 if (d > packedFiledate)
00440                                         nlinfo ("loadForm(): the sheet '%s' is newer than the packed one, I reload it", p.c_str());
00441                                 else
00442                                         nlinfo ("loadForm(): the sheet '%s' is not in the packed sheets, I load it", p.c_str());
00443                         }*/
00444                         
00445                         // add the new creature, it could be already loaded by the packed sheets but will be overwrite with the new one
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         // free the georges loader if necessary
00458         if (formLoader != NULL)
00459         {
00460                 NLGEORGES::UFormLoader::releaseLoader (formLoader);
00461                 WarningLog->removeFilter ("CFormLoader: Can't open the form file");
00462         }
00463 
00464         // we have now to remove sheet that are in the container and not exist anymore in the sheet directories
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                         // informe the contained object that it is no more needed.
00471                         container.find((*it2).first)->second.removed();
00472                         container.erase((*it2).first);
00473                         containerChanged = true;
00474                 }
00475         }
00476 
00477         // now, save the new container in the packedfile
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         // housekeeping
00498 //      sheetIds.clear ();
00499         sheetNames.clear ();
00500 }
00501 #endif // NL_LOAD_FORM_H
00502 
00503 /* End of load_form.h */