/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "Engine/StdH.h" #include #include #include #include #include #include template class CDynamicArray; template class CDynamicStackArray; #include template class CStaticStackArray; const char *CTFileName::convertFromWin32(const char *src) { #if (defined PLATFORM_WIN32) return(src); #else static const char *dirsep = NULL; static size_t seplen = 0; static char buf[MAX_PATH]; // This is NOT thread safe, fyi. char *dest; if (src == NULL) { buf[0] = '\0'; return(buf); } if (dirsep == NULL) { dirsep = CFileSystem::GetDirSeparator(); seplen = strlen(dirsep); } for (dest = buf; *src != '\0'; src++) { if (*src == '\\') { strcpy(dest, dirsep); dest += seplen; } else { *(dest++) = *src; } } *dest = '\0'; return(buf); #endif } const char *CTFileName::convertToWin32(const char *src) { #if (defined PLATFORM_WIN32) return(src); #else static const char *dirsep = NULL; static size_t seplen = 0; static char buf[MAX_PATH]; // This is NOT thread safe, fyi. char *dest; if (src == NULL) { buf[0] = '\0'; return(buf); } if (dirsep == NULL) { dirsep = CFileSystem::GetDirSeparator(); seplen = strlen(dirsep); } for (dest = buf; *src != '\0'; src++) { if ((*src == *dirsep) && (strncmp(src, dirsep, seplen) == 0)) { *(dest++) = '\\'; src += (seplen - 1); } else { *(dest++) = *src; } } *dest = '\0'; return(buf); #endif } #define USE_ABSTRACT_CTFILENAME 1 /* * Get directory part of a filename. */ CTFileName CTFileName::FileDir() const { ASSERT(IsValid()); // make a temporary copy of string CTFileName strPath(*this); // find last backlash in it #ifdef USE_ABSTRACT_CTFILENAME const char *dirsep = CFileSystem::GetDirSeparator(); char *pPathBackSlash = strstr( strPath.str_String, dirsep); // if there is no backslash if( pPathBackSlash == NULL) { // return emptystring as directory return( CTFileName("")); } for (char *p = pPathBackSlash; (p = strstr(p + 1, dirsep)) != NULL; pPathBackSlash = p) { // (*yawn*). } // set end of string after where the backslash was pPathBackSlash[strlen(dirsep)] = 0; #else char *pPathBackSlash = strrchr( strPath.str_String, '\\'); pPathBackSlash[1] = 0; #endif // return a copy of temporary string return( CTFileName( strPath)); } CTFileName &CTFileName::operator=(const char *strCharString) { ASSERTALWAYS( "Use CTFILENAME for conversion from char *!"); return *this; } /* * Get name part of a filename. */ CTFileName CTFileName::FileName() const { ASSERT(IsValid()); // make a temporary copy of string CTFileName strPath(*this); // find last backlash in what's left #ifdef USE_ABSTRACT_CTFILENAME const char *dirsep = CFileSystem::GetDirSeparator(); char *pBackSlash = strstr( strPath.str_String, dirsep); // if there is no backslash if( pBackSlash == NULL) { // return it all as filename pBackSlash = strPath.str_String; } else { for (char *p = pBackSlash; (p = strstr(p + 1, dirsep)) != NULL; pBackSlash = p) { // (*yawn*). } pBackSlash += strlen(dirsep); } // find last dot in it char *pDot = strrchr(pBackSlash, '.'); // if there is a dot if( pDot != NULL) { // set end of string there *pDot = '\0'; } // return a copy of temporary string, starting after the backslash return( CTFileName( pBackSlash )); #else char *pBackSlash = strrchr( strPath.str_String, '\\'); // if there is no backslash if( pBackSlash == NULL) { // return it all as filename return( CTFileName(strPath)); } // return a copy of temporary string, starting after the backslash return( CTFileName( pBackSlash+1)); #endif } /* * Get extension part of a filename. */ CTFileName CTFileName::FileExt() const { ASSERT(IsValid()); // find last dot in the string char *pExtension = strrchr( str_String, '.'); // if there is no dot if( pExtension == NULL) { // return no extension return( CTFileName("")); } // return a copy of the extension part, together with the dot return( CTFileName( pExtension)); } CTFileName CTFileName::NoExt() const { return FileDir()+FileName(); } /* * Remove application path from a file name. */ void CTFileName::RemoveApplicationPath_t(void) // throws char * { // remove the path string from beginning of the string BOOL bHadRightPath = RemovePrefix(_fnmApplicationPath); if (_fnmMod!="") { RemovePrefix(_fnmApplicationPath+_fnmMod); } // if it had wrong path if (!bHadRightPath) { // throw error ThrowF_t(TRANS("File '%s' has got wrong path!\nAll files must reside in directory '%s'."), str_String, (const char *) (CTString&)_fnmApplicationPath); } } /* * Read from stream. */ CTStream &operator>>(CTStream &strmStream, CTFileName &fnmFileName) { // if dictionary is enabled if (strmStream.strm_dmDictionaryMode == CTStream::DM_ENABLED) { // read the index in dictionary INDEX iFileName; strmStream>>iFileName; // get that file from the dictionary fnmFileName = strmStream.strm_afnmDictionary[iFileName]; // if dictionary is processing or not active } else { char strTag[] = "_FNM"; strTag[0] = 'D'; // must create tag at run-time! // skip dependency catcher header strmStream.ExpectID_t(strTag); // data filename // read the string #ifdef PLATFORM_WIN32 strmStream>>(CTString &)fnmFileName; #else CTString ctstr; strmStream>>ctstr; fnmFileName = CTString(CTFileName::convertFromWin32(ctstr)); // converts from win32 paths. #endif fnmFileName.fnm_pserPreloaded = NULL; } return strmStream; } /* * Write to stream. */ CTStream &operator<<(CTStream &strmStream, const CTFileName &fnmFileName) { // if dictionary is enabled if (strmStream.strm_dmDictionaryMode == CTStream::DM_ENABLED) { // try to find the filename in dictionary CTFileName *pfnmExisting = strmStream.strm_ntDictionary.Find(fnmFileName); // if not existing if (pfnmExisting==NULL) { // add it pfnmExisting = &strmStream.strm_afnmDictionary.Push(); *pfnmExisting = fnmFileName; strmStream.strm_ntDictionary.Add(pfnmExisting); } // write its index strmStream<