// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // misc #include #include #include #include // std #include #include #include using namespace NLMISC; using namespace std; #ifndef NL_MK_SH_ID_CFG #define NL_MK_SH_ID_CFG "." #endif // NL_MK_SH_ID_CFG /** * TFormId */ union TFormId { uint32 Id; struct { uint32 Type : 8; uint32 Id : 24; } FormIDInfos; void serial(NLMISC::IStream &f) { f.serial(Id); }; }; bool operator<(const TFormId& fid1, const TFormId& fid2) { return fid1.Id FormToId; map IdToForm; map FileTypeToId; map IdToFileType; map TypeToLastId; set ExtensionsAllowed; // stat uint32 NbTypesAdded = 0; uint32 NbFilesAdded = 0; uint32 NbFilesAlreadyAdded = 0; uint32 NbFilesUnknownType = 0; uint32 NbFilesDiscarded = 0; //manageFile //void manageFile( WIN32_FIND_DATA& findFileData, list& dirs, string& currentDir ); // addId void addId( string fileName ); // getFileType bool getFileType( string& fileName, string& fileType ); // displayHelp void displayHelp(); // main int main( int argc, char ** argv ); //----------------------------------------------- // displayHelp // //----------------------------------------------- void displayHelp() { printf("This tool associates an ID to the files in the given directory\n\n"); printf("Usage: make_sheet_id -c -o [-k] [-e] [] [] ...\n"); printf("-k : clean unwanted types from input\n"); printf("-e : dump the list of extensions\n"); } // displayHelp // //----------------------------------------------- // getFirstFreeFileTypeId // //----------------------------------------------- sint16 getFirstFreeFileTypeId() { for( sint16 id=0; id<256; ++id ) { if( IdToFileType.find((uint8)id) == IdToFileType.end() ) { return id; } } return -1; } // getFirstFreeFileTypeId // //----------------------------------------------- // readFormId // //----------------------------------------------- void readFormId( string& outputFileName ) { CIFile f; if( f.open( outputFileName ) ) { f.serialCont( IdToForm ); } // insert an unknown entry TFormId formId; formId.Id = 0; IdToForm.insert( make_pair( formId, string("unknown.unknown") ) ); // remove integer file extensions (created by CVS) and init FileTypeToId (associates the form type to the form type id) map::iterator itIF; for( itIF = IdToForm.begin(); itIF != IdToForm.end(); ) { // get the file type from form name TFormId fid = (*itIF).first; string fileType; if((*itIF).second.empty() || (*itIF).second=="." || (*itIF).second==".." || (*itIF).second[0]=='_' || (*itIF).second.find(".#")==0) { map::iterator itErase = itIF; ++itIF; IdToForm.erase(itErase); } else { if( getFileType( (*itIF).second, fileType ) ) { // insert the association (file type/file type id) map::iterator itFT = FileTypeToId.find(fileType); if( itFT == FileTypeToId.end() ) { FileTypeToId.insert( make_pair(fileType,fid.FormIDInfos.Type) ); } } else { nlwarning("Unknown file type for the file : %s",(*itIF).second.c_str()); } ++itIF; } } // init FormToId (associates the form name to its id ) for( itIF = IdToForm.begin(); itIF != IdToForm.end(); ++itIF ) { FormToId.insert( make_pair((*itIF).second,(*itIF).first) ); } // init IdToFileType (associates the form type id to the form type name) map::iterator itIFT; for( itIFT = FileTypeToId.begin(); itIFT != FileTypeToId.end(); ++itIFT ) { IdToFileType.insert( make_pair((*itIFT).second,(*itIFT).first) ); } // init TypeToLastId (associates the type id to the last index used for this type) for( itIF = IdToForm.begin(); itIF != IdToForm.end(); ++itIF ) { uint8 type = (*itIF).first.FormIDInfos.Type; uint32 id = (*itIF).first.FormIDInfos.Id; map::iterator itTLI = TypeToLastId.find( type ); if( itTLI != TypeToLastId.end() ) { if( (*itTLI).second < id ) { (*itTLI).second = id; } } else { TypeToLastId.insert( make_pair(type,id) ); } } } // readFormId // //----------------------------------------------- // makeId // //----------------------------------------------- void makeId( list& dirs ) { list::const_iterator itDir; for( itDir = dirs.begin(); itDir != dirs.end(); ++itDir ) { nlinfo ("Searching files in directory '%s'...", (*itDir).c_str()); vector files; CPath::getPathContent(*itDir,true,false,true,files); nlinfo ("Found %d files in directory '%s'", files.size(), (*itDir).c_str()); for(uint i = 0; i < files.size(); i++) { addId(CFile::getFilename(files[i])); } /* WIN32_FIND_DATA findFileData; HANDLE hFind; hFind = FindFirstFile((*itDir+"\\*").c_str(), &findFileData ); string currentDir(*itDir); if( hFind == INVALID_HANDLE_VALUE ) { nlwarning ("Invalid File Handle"); } else { do { manageFile( findFileData, dirs, currentDir ); } while( FindNextFile( hFind, &findFileData ) ); FindClose( hFind ); }*/ } } // makeId // //----------------------------------------------- // manageFile // //----------------------------------------------- /*void manageFile( WIN32_FIND_DATA& findFileData, list& dirs, string& currentDir ) { if( strcmp(".",findFileData.cFileName) && strcmp("..",findFileData.cFileName) && strcmp("CVS",findFileData.cFileName)) { if( findFileData.cFileName[0] != '_' ) { if( findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { //cout<<"(D)"<::iterator itFI = FormToId.find( fileName ); if( itFI == FormToId.end() ) { // double check : if file not found we check with lower case version of filename map::iterator itFILwr = FormToId.find( toLower(fileName) ); if( itFILwr != FormToId.end() ) { nlwarning("Trying to add %s but the file %s is already known ! becareful with lower case and upper case.", fileName.c_str(), toLower(fileName).c_str()); NbFilesDiscarded++; return; } string fileType; if( getFileType( fileName, fileType ) ) { map::iterator itFTI = FileTypeToId.find( fileType ); TFormId fid; // if the type of this file is a new type if( itFTI == FileTypeToId.end() ) { sint16 firstFreeFileTypeId = getFirstFreeFileTypeId(); if( firstFreeFileTypeId == -1 ) { nlwarning("MORE THAN 256 FILE TYPES!!!!"); } else { FileTypeToId.insert( make_pair(fileType,(uint8)firstFreeFileTypeId) ); IdToFileType.insert( make_pair((uint8)firstFreeFileTypeId,fileType) ); TypeToLastId.insert( make_pair((uint8)firstFreeFileTypeId,0) ); fid.FormIDInfos.Type = (uint8)firstFreeFileTypeId; fid.FormIDInfos.Id = 0; nlinfo("Adding file type '%s' with id %d", fileType.c_str(), firstFreeFileTypeId); NbTypesAdded++; } } // else the file type already exist else { // id of the file type uint8 fileTypeId = (*itFTI).second; // last id used for this file type map::iterator itTLI = TypeToLastId.find(fileTypeId); nlassert(itTLI != TypeToLastId.end()); (*itTLI).second++; // add the new association fid.FormIDInfos.Type = fileTypeId; fid.FormIDInfos.Id = (*itTLI).second; } FormToId.insert( make_pair(fileName,fid) ); IdToForm.insert( make_pair(fid,fileName) ); nlinfo("Adding file '%s' id %d with type '%s' id %d", fileName.c_str(), fid.FormIDInfos.Id, fileType.c_str(), fid.FormIDInfos.Type); NbFilesAdded++; } else { //nlinfo("Unknown file type for the file : '%s' --> not added",fileName.c_str()); NbFilesUnknownType++; } } else { //nlinfo("Skipping file '%s', already in the file", fileName.c_str()); NbFilesAlreadyAdded++; } } // addId // //----------------------------------------------- // getFileType // //----------------------------------------------- bool getFileType( string& fileName, string& fileType ) { fileType = CFile::getExtension(CFile::getFilename(fileName)); return !fileType.empty(); } // getFileType // //----------------------------------------------- // display // //----------------------------------------------- void display() { nldebug ("Output :"); map::iterator it1; for( it1 = IdToForm.begin(); it1 != IdToForm.end(); ++it1 ) { nldebug("type: %d id: %d file: %s", (*it1).first.FormIDInfos.Type, (*it1).first.FormIDInfos.Id, (*it1).second.c_str()); } } // display // //----------------------------------------------- // MAIN // //----------------------------------------------- int main( int argc, char ** argv ) { // Create an application context. NLMISC::CApplicationContext appContext; #ifdef NL_OS_UNIX NLMISC::CPath::addSearchPath(NLMISC::CPath::getApplicationDirectory("NeL")); #endif // NL_OS_UNIX NLMISC::CPath::addSearchPath(NL_MK_SH_ID_CFG); // read args if( argc < 2 ) { displayHelp(); return EXIT_FAILURE; } if( strcmp(argv[1],"/?") == 0 ) { displayHelp(); return EXIT_FAILURE; } string configFileName; string outputFileName; bool clean = false; bool dumpExtensions = false; list inputDirs; if( argc < 3 ) inputDirs.push_back("."); else { for ( uint i=1; (sint)isize(); ++i ) { ExtensionsAllowed.insert( varPtr->asString(i) ); } } } // get the current associations (read the sheet_id and fill the working structures) readFormId( outputFileName ); // output path sint lastSeparator = CFile::getLastSeparator(outputFileName); string ouputPath; if( lastSeparator != -1 ) { ouputPath = outputFileName.substr(0,lastSeparator+1); } // erase the unwanted extensions from map (modify the map, save it, and quit) if( clean ) { if( ExtensionsAllowed.empty() ) nlwarning("None extension list provided, the input will not be cleaned"); else { map::iterator itSheets; for( itSheets = IdToForm.begin(); itSheets != IdToForm.end(); ) { string extStr = CFile::getExtension( (*itSheets).second ); if( !extStr.empty() ) { if( ExtensionsAllowed.find(extStr) == ExtensionsAllowed.end() ) { map::iterator itDel = itSheets++; IdToForm.erase( itDel ); } else ++itSheets; } } COFile f( outputFileName ); f.serialCont( IdToForm ); } nlinfo("The file has been cleaned"); return 0; } // dump the list of extensions in a txt file if( dumpExtensions ) { FILE * extListOutput; string extListFileName = ouputPath + "sheet_ext.txt"; if( !(extListOutput = fopen(extListFileName.c_str(),"w")) ) { nlwarning("Can't open output file %s",extListFileName.c_str()); return 1; } set extensions; map::iterator itSheets; for( itSheets = IdToForm.begin(); itSheets != IdToForm.end(); ++itSheets ) { string extStr = CFile::getExtension( (*itSheets).second ); if( !extStr.empty() ) { extensions.insert( extStr ); } } set::iterator itExt; for( itExt = extensions.begin(); itExt != extensions.end(); ++itExt ) { fprintf(extListOutput,"%s\n",(*itExt).c_str()); } fclose(extListOutput); return 0; } nlinfo("Generating '%s' file...", outputFileName.c_str()); // make the ids makeId( inputDirs ); // save the new map COFile f( outputFileName ); f.serialCont( IdToForm ); // display the map //display(); string sheetListFileName = ouputPath + "sheets.txt"; COFile output; if( !output.open(sheetListFileName,false,true) ) { nlwarning("Can't open output file %s",sheetListFileName.c_str()); return 1; } map::iterator it1; for( it1 = IdToForm.begin(); it1 != IdToForm.end(); ++it1 ) { //string outputLine = "type: " + toString((*it1).first.FormIDInfos.Type) +" id: " + toString((*it1).first.FormIDInfos.Id) + " file: " + (*it1).second +"\n"; string outputLine = " id: " + toString((*it1).first.Id) + " file: " + (*it1).second +"\n"; output.serialBuffer((uint8*)(const_cast(outputLine.data())),(uint)outputLine.size()); } nlinfo ("------------- results ----------------"); nlinfo ("%d files added in '%s'", NbFilesAdded, outputFileName.c_str()); nlinfo ("%d files discarded because they are empty, begin with .# _ and so on", NbFilesDiscarded); nlinfo ("%d files skipped because don't have extension", NbFilesUnknownType); nlinfo ("%d types added in '%s'", NbTypesAdded, outputFileName.c_str()); nlinfo ("%d supported file types :",FileTypeToId.size()); for ( map::iterator it = FileTypeToId.begin(); it != FileTypeToId.end(); ++it ) { nlinfo("%s",(*it).first.c_str()); } return EXIT_SUCCESS; } // main //