sheet_id.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2002 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 /* This class is case unsensitive. It means that you can call build() and
00025  * buildIdVector() with string with anycase, it'll work.
00026  */
00027 
00028 #include "stdmisc.h"
00029 
00030 #include "nel/misc/file.h"
00031 #include "nel/misc/path.h"
00032 
00033 #include "nel/misc/sheet_id.h"
00034 #include "nel/misc/common.h"
00035 #include "nel/misc/hierarchical_timer.h"
00036 
00037 using namespace std;
00038 
00039 namespace NLMISC {
00040 
00041 CSheetId::CChar CSheetId::_AllStrings;
00042 CStaticMap<uint32,CSheetId::CChar> CSheetId::_SheetIdToName;
00043 CStaticMap<CSheetId::CChar,uint32, CSheetId::CCharComp> CSheetId::_SheetNameToId;
00044 //map<uint32,std::string> CSheetId::_SheetIdToName;
00045 //map<std::string,uint32> CSheetId::_SheetNameToId;
00046 vector<std::string> CSheetId::_FileExtensions;
00047 bool CSheetId::_Initialised=false;
00048 bool CSheetId::_RemoveUnknownSheet=true;
00049 bool CSheetId::_DontHaveSheetKnowledge = false;
00050 
00051 const CSheetId CSheetId::Unknown(0);
00052 
00053 void CSheetId::cbFileChange (const std::string &filename)
00054 {
00055     nlinfo ("SHEETID: %s changed, reload it", filename.c_str());
00056 
00057     loadSheetId();
00058 }
00059 
00060 //-----------------------------------------------
00061 //  CSheetId
00062 //
00063 //-----------------------------------------------
00064 CSheetId::CSheetId( uint32 sheetRef)
00065 {
00066     _Id.Id = sheetRef;
00067 
00068 #ifdef NL_DEBUG_SHEET_ID
00069     // Yoyo: don't access the static map, because of order of static ctor call.
00070     // For now, all static CSheetId are 0 (eg: CSheetId::Unknown)
00071     if(sheetRef)
00072     {
00073         CStaticMap<uint32, CChar>::iterator it(_SheetIdToName.find(sheetRef));
00074         if (it != _SheetIdToName.end())
00075         {
00076             _DebugSheetName = it->second.Ptr;
00077         }
00078         else
00079             _DebugSheetName = NULL;
00080     }
00081     else
00082     {
00083         _DebugSheetName = NULL;
00084     }
00085 #endif
00086 }
00087 
00088 
00089 //-----------------------------------------------
00090 //  CSheetId
00091 //
00092 //-----------------------------------------------
00093 CSheetId::CSheetId( const string& sheetName )
00094 {
00095     if (!buildSheetId(sheetName))
00096     {
00097         if(sheetName.empty())
00098             nlwarning("SHEETID: Try to create an CSheetId with empty name. TODO: check why.");
00099         else
00100             nlwarning("SHEETID: The sheet '%s' is not in sheet_id.bin, setting it to Unknown",sheetName.c_str());
00101         //std::string stack;
00102         //NLMISC::getCallStack(stack);
00103         //std::vector<std::string> contexts;
00104         //NLMISC::explode(stack, string("\n"), contexts);
00105         //nldebug("Dumping callstack :");
00106         //for (uint i=0; i<contexts.size(); ++i)
00107         //  nldebug("  %3u : %s", i, contexts[i].c_str());
00108         *this = Unknown;
00109     }
00110 
00111 } // CSheetId //
00112 
00113 
00114 //-----------------------------------------------
00115 //  Build
00116 //
00117 //-----------------------------------------------
00118 bool CSheetId::buildSheetId(const std::string& sheetName)
00119 {
00120     nlassert(_Initialised);
00121     nlassert(!_DontHaveSheetKnowledge);
00122 
00123     // try looking up the sheet name in _SheetNameToId
00124     CStaticMap<CChar,uint32,CCharComp>::const_iterator itId;
00125     CChar c;
00126     c.Ptr = new char [sheetName.size()+1];
00127     strcpy(c.Ptr, sheetName.c_str());
00128     toLower(c.Ptr);
00129 
00130     itId = _SheetNameToId.find (c);
00131     delete [] c.Ptr;
00132     if( itId != _SheetNameToId.end() )
00133     {
00134         _Id.Id = itId->second;
00135 #ifdef NL_DEBUG_SHEET_ID
00136         // store debug info
00137         _DebugSheetName = itId->first.Ptr;
00138 #endif
00139         return true;
00140     }
00141 
00142     // we failed to find the sheet name in the sheetname map so see if the string is numeric
00143     if (sheetName.size()>1 && sheetName[0]=='#')
00144     {
00145         uint32 numericId;
00146         NLMISC::fromString((const char*)(sheetName.c_str()+1), numericId);
00147         if (NLMISC::toString("#%u",numericId)==sheetName)
00148         {
00149             _Id.Id= numericId;
00150             return true;
00151         }
00152     }
00153     return false;
00154 }
00155 
00156 void CSheetId::loadSheetId ()
00157 {
00158     H_AUTO(CSheetIdInit);
00159     nldebug("Loading sheet_id.bin");
00160 
00161     // Open the sheet id to sheet file name association
00162     CIFile file;
00163     std::string path = CPath::lookup("sheet_id.bin", false, false);
00164     if(!path.empty() && file.open(path))
00165     {
00166         // clear entries
00167         _FileExtensions.clear ();
00168         _SheetIdToName.clear ();
00169         _SheetNameToId.clear ();
00170 
00171         // reserve space for the vector of file extensions
00172         _FileExtensions.resize(1 << (NL_SHEET_ID_TYPE_BITS));
00173 
00174         // Get the map from the file
00175         map<uint32,string> tempMap;
00176         contReset(tempMap);
00177         file.serialCont(tempMap);
00178         file.close();
00179 
00180         if (_RemoveUnknownSheet)
00181         {
00182             uint32 removednbfiles = 0;
00183             uint32 nbfiles = tempMap.size();
00184 
00185             // now we remove all files that not available
00186             map<uint32,string>::iterator itStr2;
00187             for( itStr2 = tempMap.begin(); itStr2 != tempMap.end(); )
00188             {
00189                 if (CPath::exists ((*itStr2).second))
00190                 {
00191                     ++itStr2;
00192                 }
00193                 else
00194                 {
00195                     map<uint32,string>::iterator olditStr = itStr2;
00196                     //nldebug ("Removing file '%s' from CSheetId because the file not exists", (*olditStr).second.c_str ());
00197                     itStr2++;
00198                     tempMap.erase (olditStr);
00199                     removednbfiles++;
00200                 }
00201             }
00202             nlinfo ("SHEETID: Removed %d files on %d from CSheetId because these files doesn't exists", removednbfiles, nbfiles);
00203         }
00204 
00205         // Convert the map to one big string and 1 static map (id to name)
00206         {
00207             // Get the number and size of all strings
00208             vector<CChar> tempVec; // Used to initialise the first map
00209             uint32 nNb = 0;
00210             uint32 nSize = 0;
00211             map<uint32,string>::const_iterator it = tempMap.begin();
00212             while (it != tempMap.end())
00213             {
00214                 nSize += it->second.size()+1;
00215                 nNb++;
00216                 it++;
00217             }
00218 
00219             // Make the big string (composed of all strings) and a vector referencing each string
00220             tempVec.resize(nNb);
00221             _AllStrings.Ptr = new char[nSize];
00222             it = tempMap.begin();
00223             nSize = 0;
00224             nNb = 0;
00225             while (it != tempMap.end())
00226             {
00227                 tempVec[nNb].Ptr = _AllStrings.Ptr+nSize;
00228                 strcpy(_AllStrings.Ptr+nSize, it->second.c_str());
00229                 toLower(_AllStrings.Ptr+nSize);
00230                 nSize += it->second.size()+1;
00231                 nNb++;
00232                 it++;
00233             }
00234 
00235             // Finally build the static map (id to name)
00236             _SheetIdToName.reserve(tempVec.size());
00237             it = tempMap.begin();
00238             nNb = 0;
00239             while (it != tempMap.end())
00240             {
00241                 _SheetIdToName.add(pair<uint32, CChar>::pair(it->first, CChar(tempVec[nNb])));
00242 
00243                 nNb++;
00244                 it++;
00245             }
00246 
00247             // The vector of all small string is not needed anymore we have all the info in
00248             // the static map and with the pointer AllStrings referencing the beginning.
00249         }
00250 
00251         // Build the invert map (Name to Id) & file extension vector
00252         {
00253             uint32 nSize = _SheetIdToName.size();
00254             _SheetNameToId.reserve(nSize);
00255             CStaticMap<uint32,CChar>::iterator itStr;
00256             for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00257             {
00258                 // add entry to the inverse map
00259                 _SheetNameToId.add( make_pair((*itStr).second, (*itStr).first) );
00260 
00261                 // work out the type value for this entry in the map
00262                 TSheetId sheetId;
00263                 sheetId.Id=(*itStr).first;
00264                 uint32 type = sheetId.IdInfos.Type;
00265 
00266                 // check whether we need to add an entry to the file extensions vector
00267                 if (_FileExtensions[type].empty())
00268                 {
00269                     // find the file extension part of the given file name
00270                     _FileExtensions[type] = toLower(CFile::getExtension((*itStr).second.Ptr));
00271                 }
00272                 nSize--;
00273             }
00274             _SheetNameToId.endAdd();
00275         }
00276     }
00277     else
00278     {
00279         nlerror("<CSheetId::init> Can't open the file sheet_id.bin");
00280     }
00281     nldebug("Finished loading sheet_id.bin: %u entries read",_SheetIdToName.size());
00282 }
00283 
00284 
00285 //-----------------------------------------------
00286 //  init
00287 //
00288 //-----------------------------------------------
00289 void CSheetId::init(bool removeUnknownSheet)
00290 {
00291     // allow multiple calls to init in case libraries depending on sheetid call this init from their own
00292     if (_Initialised)
00293         return;
00294 
00295 //  CFile::addFileChangeCallback ("sheet_id.bin", cbFileChange);
00296 
00297     _RemoveUnknownSheet = removeUnknownSheet;
00298 
00299     loadSheetId ();
00300     _Initialised=true;
00301 
00302 
00303 } // init //
00304 
00305 void CSheetId::initWithoutSheet()
00306 {
00307     _Initialised = true;
00308     _DontHaveSheetKnowledge = true;
00309 }
00310 
00311 
00312 
00313 //-----------------------------------------------
00314 //  uninit
00315 //
00316 //-----------------------------------------------
00317 void CSheetId::uninit()
00318 {
00319     delete [] _AllStrings.Ptr;
00320 } // uninit //
00321 
00322 //-----------------------------------------------
00323 //  operator=
00324 //
00325 //-----------------------------------------------
00326 CSheetId& CSheetId::operator=( const CSheetId& sheetId )
00327 {
00328     if (!_Initialised) init(false);
00329 
00330     if(this == &sheetId)
00331     {
00332         return *this;
00333     }
00334 
00335     _Id.Id = sheetId.asInt();
00336 
00337 #ifdef NL_DEBUG_SHEET_ID
00338     _DebugSheetName = sheetId._DebugSheetName;
00339 #endif
00340 
00341     return *this;
00342 
00343 
00344 } // operator= //
00345 
00346 
00347 //-----------------------------------------------
00348 //  operator=
00349 //
00350 //-----------------------------------------------
00351 CSheetId& CSheetId::operator=( const string& sheetName )
00352 {
00353     nlassert(_Initialised);
00354     nlassert(!_DontHaveSheetKnowledge);
00355 
00356     CStaticMap<CChar,uint32,CCharComp>::const_iterator itId;
00357     CChar c;
00358     c.Ptr = new char [sheetName.size()+1];
00359     strcpy(c.Ptr, sheetName.c_str());
00360     toLower(c.Ptr);
00361 
00362     itId = _SheetNameToId.find (c);
00363     delete [] c.Ptr;
00364     if( itId != _SheetNameToId.end() )
00365     {
00366         _Id.Id = (*itId).second;
00367         return *this;
00368     }
00369     *this = Unknown;
00370     return *this;
00371 
00372 } // operator= //
00373 
00374 
00375 //-----------------------------------------------
00376 //  operator=
00377 //
00378 //-----------------------------------------------
00379 CSheetId& CSheetId::operator=( uint32 sheetRef )
00380 {
00381     if (!_Initialised) init(false);
00382 
00383     _Id.Id = sheetRef;
00384 
00385     return *this;
00386 
00387 } // operator= //
00388 
00389 
00390 
00391 //-----------------------------------------------
00392 //  operator<
00393 //
00394 //-----------------------------------------------
00395 bool CSheetId::operator < (const CSheetId& sheetRef ) const
00396 {
00397     if (!_Initialised) init(false);
00398 
00399     if (_Id.Id < sheetRef.asInt())
00400     {
00401         return true;
00402     }
00403 
00404     return false;
00405 
00406 } // operator< //
00407 
00408 
00409 
00410 //-----------------------------------------------
00411 //  toString
00412 //
00413 //-----------------------------------------------
00414 string CSheetId::toString(bool ifNotFoundUseNumericId) const
00415 {
00416     if (!_Initialised) init(false);
00417 
00418     CStaticMap<uint32,CChar>::const_iterator itStr = _SheetIdToName.find (_Id.Id);
00419     if( itStr != _SheetIdToName.end() )
00420     {
00421         return string((*itStr).second.Ptr);
00422     }
00423     else
00424     {
00425         // This nlwarning is commented out because the loggers are mutexed, therefore
00426         // you couldn't use toString() within a nlwarning().
00427         //nlwarning("<CSheetId::toString> The sheet %08x is not in sheet_id.bin",_Id.Id);
00428         if (ifNotFoundUseNumericId)
00429         {
00430             return NLMISC::toString( "#%u", _Id.Id );
00431         }
00432         else
00433         {
00434             return NLMISC::toString( "<Sheet %d not found in sheet_id.bin>", _Id.Id );
00435         }
00436     }
00437 
00438 } // toString //
00439 
00440 void CSheetId::serial(NLMISC::IStream   &f) throw(NLMISC::EStream)
00441 {
00442     f.serial( _Id.Id );
00443 
00444 #ifdef NL_DEBUG_SHEET_ID
00445     CStaticMap<uint32, CChar>::iterator it(_SheetIdToName.find(_Id.Id));
00446     if (it != _SheetIdToName.end())
00447         _DebugSheetName = it->second.Ptr;
00448     else
00449         _DebugSheetName = NULL;
00450 #endif
00451 }
00452 
00453 
00454 
00455 //-----------------------------------------------
00456 //  display
00457 //
00458 //-----------------------------------------------
00459 void CSheetId::display()
00460 {
00461     if (!_Initialised) init(false);
00462 
00463     CStaticMap<uint32,CChar>::const_iterator itStr;
00464     for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00465     {
00466         //nlinfo("%d %s",(*itStr).first,(*itStr).second.c_str());
00467         nlinfo("SHEETID: (%08x %d) %s",(*itStr).first,(*itStr).first,(*itStr).second.Ptr);
00468     }
00469 
00470 } // display //
00471 
00472 
00473 
00474 //-----------------------------------------------
00475 //  display
00476 //
00477 //-----------------------------------------------
00478 void CSheetId::display(uint32 type)
00479 {
00480     if (!_Initialised) init(false);
00481 
00482     CStaticMap<uint32,CChar>::const_iterator itStr;
00483     for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00484     {
00485         // work out the type value for this entry in the map
00486         TSheetId sheetId;
00487         sheetId.Id=(*itStr).first;
00488 
00489         // decide whether or not to display the entry
00490         if (type==sheetId.IdInfos.Type)
00491         {
00492             //nlinfo("%d %s",(*itStr).first,(*itStr).second.c_str());
00493             nlinfo("SHEETID: (%08x %d) %s",(*itStr).first,(*itStr).first,(*itStr).second.Ptr);
00494         }
00495     }
00496 
00497 } // display //
00498 
00499 
00500 
00501 //-----------------------------------------------
00502 //  buildIdVector
00503 //
00504 //-----------------------------------------------
00505 void CSheetId::buildIdVector(std::vector <CSheetId> &result)
00506 {
00507     if (!_Initialised) init(false);
00508 
00509     CStaticMap<uint32,CChar>::const_iterator itStr;
00510     for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00511     {
00512         result.push_back( (CSheetId)(*itStr).first );
00513     }
00514 
00515 } // buildIdVector //
00516 
00517 
00518 //-----------------------------------------------
00519 //  buildIdVector
00520 //
00521 //-----------------------------------------------
00522 void CSheetId::buildIdVector(std::vector <CSheetId> &result, uint32 type)
00523 {
00524     if (!_Initialised) init(false);
00525     nlassert(type < (1 << (NL_SHEET_ID_TYPE_BITS)));
00526 
00527     CStaticMap<uint32,CChar>::const_iterator itStr;
00528     for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00529     {
00530         // work out the type value for this entry in the map
00531         TSheetId sheetId;
00532         sheetId.Id=(*itStr).first;
00533 
00534         // decide whether or not to use the entry
00535         if (type==sheetId.IdInfos.Type)
00536         {
00537             result.push_back( (CSheetId)sheetId.Id );
00538         }
00539     }
00540 
00541 } // buildIdVector //
00542 
00543 //-----------------------------------------------
00544 //  buildIdVector
00545 //
00546 //-----------------------------------------------
00547 void CSheetId::buildIdVector(std::vector <CSheetId> &result, std::vector <std::string> &resultFilenames,uint32 type)
00548 {
00549     if (!_Initialised) init(false);
00550     nlassert(type < (1 << (NL_SHEET_ID_TYPE_BITS)));
00551 
00552     CStaticMap<uint32,CChar>::const_iterator itStr;
00553     for( itStr = _SheetIdToName.begin(); itStr != _SheetIdToName.end(); ++itStr )
00554     {
00555         // work out the type value for this entry in the map
00556         TSheetId sheetId;
00557         sheetId.Id=(*itStr).first;
00558 
00559         // decide whether or not to use the entry
00560         if (type==sheetId.IdInfos.Type)
00561         {
00562             result.push_back( (CSheetId)sheetId.Id );
00563             resultFilenames.push_back( (*itStr).second.Ptr );
00564         }
00565     }
00566 
00567 } // buildIdVector //
00568 
00569 //-----------------------------------------------
00570 //  buildIdVector
00571 //
00572 //-----------------------------------------------
00573 void CSheetId::buildIdVector(std::vector <CSheetId> &result,const std::string &fileExtension)
00574 {
00575     uint32 type=typeFromFileExtension(fileExtension);
00576     if (type!=(uint32)~0)
00577         buildIdVector(result, type);
00578 
00579 } // buildIdVector //
00580 
00581 //-----------------------------------------------
00582 //  buildIdVector
00583 //
00584 //-----------------------------------------------
00585 void CSheetId::buildIdVector(std::vector <CSheetId> &result, std::vector <std::string> &resultFilenames,const std::string &fileExtension)
00586 {
00587     uint32 type=typeFromFileExtension(fileExtension);
00588     if (type != (uint32)~0)
00589         buildIdVector(result,resultFilenames, type);
00590 
00591 } // buildIdVector //
00592 
00593 
00594 //-----------------------------------------------
00595 //  typeFromFileExtension
00596 //
00597 //-----------------------------------------------
00598 uint32 CSheetId::typeFromFileExtension(const std::string &fileExtension)
00599 {
00600     if (!_Initialised) init(false);
00601 
00602     unsigned i;
00603     for (i=0;i<_FileExtensions.size();i++)
00604         if (toLower(fileExtension)==_FileExtensions[i])
00605             return i;
00606 
00607     return ~0;
00608 } // typeFromFileExtension //
00609 
00610 
00611 //-----------------------------------------------
00612 //  fileExtensionFromType
00613 //
00614 //-----------------------------------------------
00615 const std::string &CSheetId::fileExtensionFromType(uint32 type)
00616 {
00617     if (!_Initialised) init(false);
00618     nlassert(type < (1<<(NL_SHEET_ID_TYPE_BITS)));
00619 
00620     return _FileExtensions[type];
00621 
00622 } // fileExtensionFromType //
00623 
00624 //-----------------------------------------------
00625 //  build
00626 //
00627 //-----------------------------------------------
00628 void    CSheetId::buildSheetId(uint32 shortId, uint32 type)
00629 {
00630     nlassert(shortId < (1<<NL_SHEET_ID_ID_BITS));
00631     nlassert(type < (1<<(NL_SHEET_ID_TYPE_BITS)));
00632 
00633     _Id.IdInfos.Id= shortId;
00634     _Id.IdInfos.Type= type;
00635 
00636 #ifdef NL_DEBUG_SHEET_ID
00637     CStaticMap<uint32, CChar>::iterator it(_SheetIdToName.find(_Id.Id));
00638     if (it != _SheetIdToName.end())
00639     {
00640         _DebugSheetName = it->second.Ptr;
00641     }
00642     else
00643         _DebugSheetName = NULL;
00644 #endif
00645 
00646 }
00647 
00648 } // NLMISC

Generated on Thu Jan 7 08:26:34 2010 for NeL by  doxygen 1.6.1