Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CAT/CATFileSystem.h Source File

CATFileSystem.h

Go to the documentation of this file.
00001 //---------------------------------------------------------------------------
00002 /// \file CATFileSystem.h
00003 /// \brief File utility virtual interface
00004 /// \ingroup CAT
00005 /// 
00006 /// Copyright (c) 2003-2008 by Michael Ellison.
00007 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00008 ///
00009 // $Author: mikeellison $
00010 // $Date: 2008-01-21 08:33:12 -0600 (Mon, 21 Jan 2008) $
00011 // $Revision:   $
00012 // $NoKeywords: $
00013 
00014 #ifndef _CATFileSystem_H_
00015 #define _CATFileSystem_H_
00016 
00017 #include "CATInternal.h"
00018 #include "CATMutex.h"
00019 #include "CATPlatform.h"
00020 #include "CATStreamFile.h"
00021 
00022 typedef void* CATFINDHANDLE;
00023 
00024 /// \class CATFileSystem
00025 /// \brief File utility virtual interface. 
00026 ///
00027 /// Use CATPlatform::GetFileSystem() to acquire, and CATPlatform::Release()
00028 /// to release.
00029 ///
00030 /// Filesystem functions should be threadsafed using fFSLock.
00031 ///
00032 /// You must call Initialize() after receiving a file system from CATPlatform.
00033 class CATFileSystem
00034 {
00035    friend CATPlatform;
00036    public:     
00037       /// Initialize must be called prior to using CATFileSystem!
00038       /// \return CATResult - CAT_SUCCESS
00039       virtual CATResult Initialize() = 0;
00040 
00041       /// FileExists should return a successful result if the file exists,
00042       /// or an error otherwise.
00043       ///
00044       /// Note: FileExists() fails if a directory of that name is present.
00045       ///
00046       /// \param pathname - path to file to check for existance.
00047       /// \return CATResult - successful result if the file is found.
00048       virtual CATResult FileExists(  const CATString& pathname   )  = 0;
00049 
00050       /// DirExists should return a successful result if the dir exists,
00051       /// or an error otherwise.
00052       ///
00053       /// Note: DirExists() fails if a file of the specified name exists.
00054       ///
00055       /// \param pathname - path to dir to check for existance.
00056       /// \return CATResult - successful result if the file is found.
00057       virtual CATResult DirExists (  const CATString& pathname   )  = 0;
00058 
00059       /// CreateDir creates the directory if necessary.
00060       ///
00061       /// \param pathname - path to dir to check for existance and create if not
00062       ///                   present.
00063       /// \return CATResult - CAT_SUCCESS if successful.
00064       virtual CATResult CreateDir (  const CATString& pathname   )  = 0;
00065 
00066 
00067 
00068       /// PathExists should return a successful result if a dir or a file
00069       /// of that name exists.
00070       ///
00071       /// If it is a file, returns CAT_STAT_PATH_IS_FILE.
00072       /// IF it is a dir, returns CAT_STAT_PATH_IS_DIRECTORY
00073       ///
00074       /// \param pathname - path to dir to check for existance.
00075       /// \return CATResult - successful result if the file is found.
00076       virtual CATResult PathExists(  const CATString& pathname   )  = 0;
00077       
00078       /// FindFirst() finds the first matching file or directory and
00079       /// returns it in firstFile.  
00080       ///
00081       /// FindFirst *must* be called prior to FindNext().  You must call
00082       /// FindEnd() when done.
00083       ///
00084       /// \param searchMask - mask for performing searches with
00085       /// \param firstFile - ref to a string that receives the filename
00086       ///                    on success.
00087       /// \param findHandle - ref to handle returned on success. 
00088       /// \return CATResult - CAT_STAT_PATH_IS_DIRECTORY if entry is a directory.
00089       ///                    CAT_STAT_PATH_IS_FILE if it's a file.
00090       ///                    CAT_ERR_FIND_NO_MATCHES if no matches are found.
00091       virtual CATResult FindFirst (  const CATString& searchMask, 
00092                                     CATString&       firstFile,
00093                                     CATFINDHANDLE&   findHandle) = 0;      
00094 
00095       /// FindNext() finds the next matching file or directory and
00096       /// returns it in nextFile.
00097       ///
00098       /// You should pass the findHandle returned by a previous call
00099       /// to FindFirst().
00100       ///
00101       /// \param nextFile - ref to string to receive path of next file
00102       /// \param findHandle - handle for search.
00103       /// \return CATResult - CAT_STAT_PATH_IS_DIRECTORY if entry is a directory.
00104       ///                    CAT_STAT_PATH_IS_FILE if it's a file.
00105       ///                    CAT_ERR_FIND_END if no more files are available.
00106       virtual CATResult FindNext  (  CATString&       nextFile,
00107                                     CATFINDHANDLE    findHandle) = 0;
00108 
00109       /// FindEnd() ends a find operation and performs any necessary cleanup.
00110       ///
00111       /// The handle will be set to 0.
00112       ///
00113       /// \param findHandle - handle of find from FindFirst()
00114       /// \return CATResult - CAT_SUCCESS on success.
00115       virtual CATResult FindEnd (CATFINDHANDLE& findHandle) = 0;
00116                
00117 
00118       /// OpenFile() opens or creates a file.
00119       ///
00120       /// \param filename - path to file. 
00121       /// \param mode - open mode for the file      
00122       /// \param stream - ref to receive opened file stream
00123       /// \return CATResult - CAT_SUCCESS on success.
00124       /// \sa ReleaseStream()
00125       virtual CATResult OpenFile( const CATString&      filename, 
00126                                  CATStream::OPEN_MODE  mode,
00127                                  CATStream*&           stream) = 0;
00128 
00129       /// OpenCachedFile() opens a file into a memory stream if possible.
00130       /// By default, it just routes to OpenFile, but child classes
00131       /// may override.
00132       ///
00133       /// \param filename - path to file.       
00134       /// \param stream - ref to receive opened file stream
00135       /// \return CATResult - CAT_SUCCESS on success.
00136       /// \sa ReleaseStream()
00137       virtual CATResult OpenCachedFile( const CATString&      filename,                                  
00138                                        CATStream*&           stream)
00139       {
00140          return OpenFile(filename, CATStream::READ_ONLY,stream);
00141       }
00142 
00143       /// ReleaseFile() releases a stream opened with GetStream().
00144       /// 
00145       /// \param stream - reference to stream pointer. Set to 0 when closed.
00146       /// \return CATResult - CAT_SUCCESS on success.
00147       /// \sa GetStream()
00148       virtual CATResult ReleaseFile(CATStream*& stream) = 0;
00149 
00150         /// IsFileReadOnly() returns true if the file is read-only, and false
00151         /// if not or if it doesn't exist.
00152         virtual bool      IsFileReadOnly(const CATString& path) = 0;
00153 
00154       /// GetFullPath() gets the fully qualified path from a local path.
00155       ///
00156       /// IF we create the file system with a base path location, then this
00157       /// will convert from a subpath of the base path into a fully
00158       /// qualified path.
00159       ///
00160       CATString GetFullPath( const CATString& path )
00161       {
00162          return BuildPath(this->fBasePath, path);
00163       }
00164 
00165       /// BuildPath() combines a directory and a filename into a single path string.
00166       ///
00167       /// \param directory - directory path. May or may not be terminated with a seperator.
00168       /// \param filename - filename.extension for the path.
00169       /// \return CATString - combined path for the file
00170       /// \sa SplitPath()
00171       static CATString BuildPath (  const CATString&   directory,
00172                                    const CATString&   filename,
00173                                               bool  appendSep = false)
00174       {
00175          CATString fullPath;
00176                                   
00177          if (directory.IsEmpty() == false)
00178          {
00179             fullPath = directory;
00180             if ((directory.GetWChar(directory.LengthCalc() - 1) != CAT_PATHSEPERATOR) &&
00181                 ((filename.IsEmpty() == true) || (filename.GetWChar(0) != CAT_PATHSEPERATOR)))
00182             {
00183                fullPath << CAT_PATHSEPERATOR;
00184             }
00185          }
00186 
00187          fullPath << filename;
00188 
00189             if (appendSep)
00190             {
00191                 if (fullPath.GetWChar( fullPath.Length() - 1) != CAT_PATHSEPERATOR)
00192                 {
00193                     fullPath << CAT_PATHSEPERATOR;
00194                 }
00195             }
00196 
00197          return fullPath;
00198       }
00199 
00200         static CATString& EnsureTerminator(CATString& termPath)
00201         {
00202             if (termPath.IsEmpty() || (termPath.GetWChar( termPath.Length() - 1) != CAT_PATHSEPERATOR))
00203             {
00204                 termPath << CAT_PATHSEPERATOR;
00205             }
00206             return termPath;
00207         }
00208 
00209 
00210       /// GetFileExtension() retrieves the file extension of a file in a path.
00211       /// If none, the returned string is empty.
00212       static CATString GetFileExtension (const CATString& path)
00213       {  
00214          CATString extension;
00215          bool found = false;
00216 
00217          CATUInt32 offset = -1;
00218          if (path.ReverseFind(CAT_PATHSEPERATOR,offset))
00219          {
00220             // file extension marker has to be after last seperator.
00221             found = path.Find( '.',offset);            
00222          }
00223          else 
00224          {
00225             offset = 0;
00226             found = path.Find('.',offset);
00227          }
00228 
00229          if (found)
00230          {
00231             extension = path.Right(offset+1);
00232          }
00233          return extension;
00234       }
00235 
00236       /// StripFileExtension() returns the string w/o any file extension      
00237       static CATString StripFileExtension (const CATString& path)
00238       {  
00239          CATString noExtension = path;
00240 
00241          bool found = false;
00242 
00243          CATUInt32 offset = -1;
00244             CATUInt32 testOffset = -1;
00245 
00246          if (path.ReverseFind(CAT_PATHSEPERATOR,testOffset))
00247          {
00248             // file extension marker has to be after last seperator.
00249             while (path.Find('.',testOffset))
00250                 {
00251                     offset = testOffset;
00252                     found = true;
00253                     testOffset++;
00254                 }
00255          }
00256          else 
00257          {
00258             while (path.Find('.',testOffset))
00259                 {
00260                     offset = testOffset;
00261                     found = true;
00262                     testOffset++;
00263                 }
00264          }
00265 
00266          if (found)
00267          {
00268             noExtension = path.Left(offset);   
00269          }
00270          return noExtension;
00271       }
00272 
00273       /// SanitizeFilename() removes any illegal characters from
00274       /// a filename.
00275       static CATString SanitizeFilename( const CATString&  filename,
00276                                         bool       allowExtSep    = true,
00277                                         bool       allowPathSep   = false,
00278                                         bool       allowDriveSep  = false)
00279       {
00280          const CATUInt32 numChars = 6;
00281          wchar_t  illegalChars[numChars] = { '*','|','?','<','>','/' };
00282          
00283          CATString safeString;
00284          CATUInt32  nameLen = filename.LengthCalc();
00285 
00286          for (CATUInt32 i=0; i < nameLen; i++)
00287          {
00288             wchar_t curChar = filename.GetWChar(i);
00289             bool skipChar = false;
00290 
00291             for (CATUInt32 j=0; j<numChars; j++)
00292             {
00293                if (curChar == illegalChars[j])
00294                   skipChar = true;
00295             }
00296 
00297             // If !allowing extension seperator and it's a '.', skip it...
00298             skipChar |= ((curChar == '.') && (!allowExtSep));
00299             
00300             // Check for path/drive seperators...
00301             skipChar |= ((curChar == CAT_PATHSEPERATOR) && (!allowPathSep));
00302               
00303 #ifdef kDRIVESEPERATOR
00304             skipChar |= ((curChar == kDRIVESEPERATOR) && (!allowDriveSep));
00305 #endif
00306 
00307             if (!skipChar)
00308             {
00309                safeString << curChar;
00310             }
00311          }
00312 
00313          return safeString;
00314       }
00315 
00316 
00317 
00318       /// SplitPath splits the string into a directory and a base
00319       /// filename.
00320       ///
00321       /// This function may be somewhat platform independant, although
00322       /// the path seperator is predefined in GGConfig.
00323       ///
00324       /// \param fullPath - the path to split
00325       /// \param directory - ref to receive the base directory.
00326       ///        If keepTrailingSep is true, it will end in a seperator.
00327       /// \param filename - ref to receive the base filename w/o path.
00328       /// \param keepTrailingSep - if true, leaves a trailing seperator on the path.
00329       /// \return CATResult - CAT_SUCCESS on success.
00330       /// \sa BuildPath
00331       static CATResult SplitPath (  const CATString&   fullPath, 
00332                                     CATString&         directory, 
00333                                     CATString&         filename,                                     
00334                                     bool              keepTrailingSep = true)
00335       {
00336          CATResult result = CAT_SUCCESS;
00337          CATUInt32 offset  = -1;
00338          directory       = "";
00339          filename        = "";
00340 
00341          if (fullPath.IsEmpty())
00342          {
00343             return CATRESULT(CAT_ERR_PATH_EMPTY);
00344          }   
00345 
00346          if (fullPath.ReverseFind(CAT_PATHSEPERATOR,offset))
00347          {
00348             directory = fullPath.Left(offset + (keepTrailingSep ? 1 : 0));
00349             filename = fullPath.Right(offset + 1);
00350          }
00351          else
00352          {
00353 #ifdef kDRIVESEPERATOR
00354             offset = -1;
00355             if (fullPath.ReverseFind(kDRIVESEPERATOR, offset))
00356             {
00357                directory = fullPath.Left(offset + 1);
00358                filename = fullPath.Right(offset + 1);
00359             }
00360             else
00361 #endif
00362             {
00363                filename = fullPath;         
00364             }
00365          }
00366          
00367          if (directory.IsEmpty() != true)
00368          {
00369             if ( directory.GetWChar(directory.LengthCalc() - 1) !=  CAT_PATHSEPERATOR)
00370             {
00371                directory << CAT_PATHSEPERATOR;
00372             }
00373          }
00374            
00375          if (filename.IsEmpty())
00376          {
00377             result = CATRESULTFILE(CAT_STAT_PATH_NO_FILE, fullPath);
00378          }
00379          else if (directory.IsEmpty())
00380          {
00381             result = CATRESULTFILE(CAT_STAT_PATH_NO_DIRECTORY, fullPath);
00382          }
00383 
00384          return result;
00385 
00386       }
00387 
00388       /// GetBase() retrieves the base path of the system
00389       virtual CATString GetBase()
00390       {
00391          return fBasePath;
00392       }
00393 
00394    protected:
00395       /// Constructors and destructors are protected! Use CATPlatform
00396       /// to create / releaes!
00397 
00398       /// Constructor takes basePath as an argument -
00399       /// All file operations should be based off of this path.
00400       CATFileSystem(const CATString& basePath = "") 
00401       {
00402          fBasePath      = basePath;
00403         
00404          if ((fBasePath.IsEmpty() == false) && (fBasePath.GetWChar(fBasePath.Length() - 1) != CAT_PATHSEPERATOR))
00405          {
00406             fBasePath << CAT_PATHSEPERATOR;
00407          }
00408       }
00409 
00410      
00411       /// Destructor
00412       virtual ~CATFileSystem()  
00413       {
00414          // Wait for any pending commands.
00415          fFSLock.Wait();
00416          fFSLock.Release();
00417       }
00418 
00419       /// Remove fBasePath from a full path and return result.
00420       CATString RemoveBasePath(CATString& fullPath)
00421       {         
00422          if (fBasePath.CompareNoCase(fullPath,fBasePath.Length()) == 0)
00423          {
00424             return fullPath.Right(fBasePath.Length());
00425          }
00426          else
00427          {
00428             return fullPath;
00429          }
00430       }
00431 
00432       CATMutex        fFSLock;
00433       CATString       fBasePath;
00434 };
00435 
00436 
00437 #endif // _CATFileSystem_H_
00438 
00439 

Generated on Mon Feb 11 04:09:43 2008 for Game Accessibility Suite by doxygen 1.5.4