AaronCameron.net
Not Left, nor right. Just correct.
Not a Member? - Login or Create an Account
Wednesday the 23rd of May 2012 @ 11:29pm
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cVfsFile.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2003  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "cVfsFile.h"
00026 
00027 #include "vfsUtilities.h"
00028 #include "cVfsOpenException.h"
00029 #include "cVfsReadException.h"
00030 #include "cVfsWriteException.h"
00031 #include "cVfsNoPermissionException.h"
00032 
00033 #include "SDL.h"
00034 
00035 #include <vector>
00036 
00037 #include <stdio.h>
00038 
00039 using namespace std;
00040 
00041 namespace n2l
00042 {
00043     const tUint cVfsFile::FirstLineMaxLength( 8096 );
00044 
00045 
00046     /* ************************************************************ */
00047     cVfsFile::cVfsFile( const tFsNodeName & iName ) :
00048         mFsNodeName(iName),
00049         mStat(iName),
00050         mBufferCached(false),
00051         mBufferFirstLineCached(false),
00052         mSizeCached(false)
00053     {
00054         if (!mStat.isFile())
00055             throw cVfsOpenException("cVfsFile::cVfsFile",
00056                                     "Not a file node",
00057                                     iName);
00058         // File names are always the last part of the vfs name
00059         vector<tVfsNodeName> temp = splitVfsPathBlocks(convertFsLiteralNameToVfs(iName));
00060         if (temp.empty())   // Whoah... that shouldn't happen
00061             throw cVfsOpenException("cVfsFile::cVfsFile",
00062                                     "No leaf node?",
00063                                     iName);
00064         mVfsNodeName = temp[temp.size()-1];
00065     }
00066 
00067 
00068     /* ************************************************************ */
00069     cVfsFile::~cVfsFile()
00070     {
00071     }
00072 
00073 
00074     /* ************************************************************ */
00075     const tVfsNodeName & cVfsFile::name() const
00076     {
00077         return mVfsNodeName;
00078     }
00079 
00080     
00081     /* ************************************************************ */
00082     const tUint cVfsFile::permissions() const
00083     {
00084         return mStat.permissions();
00085     }
00086 
00087     /* ************************************************************ */
00088     const tBool cVfsFile::isSymLink() const
00089     {
00090         return mStat.isSymLink();
00091     }
00092 
00093     /* ************************************************************ */
00094     const tFsNodeName cVfsFile::readLink() const
00095     {
00096         return mStat.readLink();
00097     }
00098 
00099     /* ************************************************************ */
00100     const tVfsFileBuffer & cVfsFile::buffer() const
00101     {
00102         if (!mBufferCached) readBuffer();
00103         return mBuffer;
00104     }
00105 
00106     /* ************************************************************ */
00107     void cVfsFile::buffer( const tVfsFileBuffer &iBuffer ) const
00108     {
00109         if (!mStat.writeable())
00110             throw cVfsNoPermissionException( "cVfsFile::buffer",
00111                 "No write permission to node", mVfsNodeName );
00112         mBuffer = iBuffer;
00113         mBufferCached = true;
00114 
00115         mBufferFirstLineCached = false;
00116         mBufferFirstLine.clear();
00117 
00118         mSizeCached = false;
00119 
00120         // Write the buffer
00121         writeBufferToDisk();
00122     }
00123 
00124     /* ************************************************************ */
00125     void cVfsFile::getBuffer( tVfsFileBuffer & oBuffer ) const
00126     {
00127         if (mBufferCached) oBuffer = mBuffer;
00128         else getFsNodeDump( mFsNodeName,oBuffer );
00129     }
00130 
00131     /* ************************************************************ */
00132     const tVfsFileBuffer & cVfsFile::firstLine() const
00133     {
00134         if (!mBufferFirstLineCached) readFirstLine();
00135         return mBufferFirstLine;
00136     }
00137 
00138 
00139     /* ************************************************************ */
00140     SDL_RWops * cVfsFile::getRWops() const
00141     {
00142         const tVfsFileBuffer & TheBuffer = buffer();
00143         return SDL_RWFromMem( (void*)(TheBuffer.data()), TheBuffer.size() );
00144     }
00145 
00146     /* ************************************************************ */
00147     const tUint cVfsFile::size() const
00148     {
00149         if (!mSizeCached) {
00150             mFileSize = getFsNodeSize(mFsNodeName);
00151             mSizeCached = true;
00152          }
00153         return mFileSize;
00154     }
00155 
00156 
00157     /* ************************************************************ */
00158     void cVfsFile::readBuffer() const
00159     {
00160         mBuffer.clear();
00161         try
00162         {
00163             getFsNodeDump(mFsNodeName,mBuffer);
00164             mBufferCached = true;
00165         }
00166         catch (cException & iException)
00167         {
00168             // We're going to rethrow a more appropriate exception instead
00169             throw cVfsReadException("cVfsFile::readBuffer",
00170                                     "Couldn\'t read the file buffer",
00171                                     mFsNodeName);
00172         }
00173     }
00174 
00175     /* ************************************************************ */
00176     void cVfsFile::writeBufferToDisk() const
00177     {
00178         try
00179         {
00180             FILE *fp = fopen( mFsNodeName.c_str(), "wb" );
00181             if (0==fp) 
00182                 throw cVfsReadException( "cVfsFile::writeBufferToDisk",
00183                     "Open failed", mFsNodeName );
00184             if (mBuffer.empty()) {
00185                 fclose(fp);
00186                 return;
00187             }
00188             if (1!=fwrite( (void*)(mBuffer.data()), mBuffer.size(), 1, fp ))
00189                 throw cVfsWriteException( "cVfsFile::writeBufferToDisk",
00190                     "Write failed, shortfall", mFsNodeName );
00191             fclose(fp);
00192         }
00193         catch (cVfsReadException &iE)
00194         {
00195             iE.rethrow();
00196         }
00197         catch (cVfsWriteException &iE)
00198         {
00199             iE.rethrow();
00200         }
00201         catch ( ... )
00202         {
00203             // We're going to rethrow a more appropriate exception instead
00204             throw cVfsWriteException("cVfsFile::writeBufferToDisk",
00205                 "Couldn\'t write the file buffer.", mFsNodeName);
00206         }
00207     }
00208 
00209     /* ************************************************************ */
00210     void cVfsFile::readFirstLine() const
00211     {
00212         static char smFirstLineBuffer[ FirstLineMaxLength ];
00213         mBufferFirstLine.clear();
00214 
00215         FILE * fp = fopen( mFsNodeName.c_str(), "r" );
00216         if (0==fp) 
00217             throw cVfsReadException("cVfsFile::readFirstLine","Open failed",mFsNodeName);
00218         
00219         fgets( smFirstLineBuffer, FirstLineMaxLength, fp );
00220         const tUint Len = strlen(smFirstLineBuffer);
00221         if (Len>0) smFirstLineBuffer[Len-1] = '\0';
00222 
00223         mBufferFirstLine = smFirstLineBuffer;
00224         mBufferFirstLineCached = true;
00225     }
00226 
00227 
00228     /* ************************************************************ */
00229     const tBool cVfsFile::supportsFsName() const
00230     {
00231         return true;
00232     }
00233 
00234 
00235     /* ************************************************************ */
00236     const tFsNodeName cVfsFile::fsName() const
00237     {
00238         return mFsNodeName;
00239     }
00240 
00241     /* ************************************************************ */
00242     void cVfsFile::clearCache() const
00243     {
00244         mBufferCached = false;
00245         mBuffer = "";
00246         
00247         mBufferFirstLineCached = false;
00248         mBufferFirstLine = "";
00249         
00250         mSizeCached = false;
00251     }
00252 
00253     /* ************************************************************ */
00254     void cVfsFile::clear()
00255     {
00256         mFsNodeName.clear();
00257         mVfsNodeName.clear();
00258         mBuffer.clear();
00259     }
00260 
00261 } // namespace
©2012 Aaron Cameron