/[svn]/libgig/trunk/src/RIFF.cpp
ViewVC logotype

Diff of /libgig/trunk/src/RIFF.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 798 by schoenebeck, Thu Nov 3 23:49:11 2005 UTC revision 800 by schoenebeck, Wed Nov 9 20:04:11 2005 UTC
# Line 22  Line 22 
22   ***************************************************************************/   ***************************************************************************/
23    
24  #include <string.h>  #include <string.h>
 #include <sstream>  
25    
26  #include "RIFF.h"  #include "RIFF.h"
27    
28  namespace RIFF {  #include "helper.h"
   
 // *************** Helper Functions **************  
 // *  
   
     template<class T> inline String ToString(T o) {  
         std::stringstream ss;  
         ss << o;  
         return ss.str();  
     }  
   
29    
30    namespace RIFF {
31    
32  // *************** Chunk **************  // *************** Chunk **************
33  // *  // *
# Line 49  namespace RIFF { Line 39  namespace RIFF {
39          ulPos      = 0;          ulPos      = 0;
40          pParent    = NULL;          pParent    = NULL;
41          pChunkData = NULL;          pChunkData = NULL;
42            ulChunkDataSize = 0;
43          ChunkID    = CHUNK_ID_RIFF;          ChunkID    = CHUNK_ID_RIFF;
44          this->pFile = pFile;          this->pFile = pFile;
45      }      }
# Line 62  namespace RIFF { Line 53  namespace RIFF {
53          pParent       = Parent;          pParent       = Parent;
54          ulPos         = 0;          ulPos         = 0;
55          pChunkData    = NULL;          pChunkData    = NULL;
56            ulChunkDataSize = 0;
57          ReadHeader(StartPos);          ReadHeader(StartPos);
58      }      }
59    
# Line 71  namespace RIFF { Line 63  namespace RIFF {
63          this->pParent    = pParent;          this->pParent    = pParent;
64          ulPos            = 0;          ulPos            = 0;
65          pChunkData       = NULL;          pChunkData       = NULL;
66            ulChunkDataSize  = 0;
67          ChunkID          = uiChunkID;          ChunkID          = uiChunkID;
68          CurrentChunkSize = 0;          CurrentChunkSize = 0;
69          NewChunkSize     = uiBodySize;          NewChunkSize     = uiBodySize;
# Line 668  namespace RIFF { Line 661  namespace RIFF {
661       *       *
662       * <b>Caution:</b> the buffer pointer will be invalidated once       * <b>Caution:</b> the buffer pointer will be invalidated once
663       * File::Save() was called. You have to call LoadChunkData() again to       * File::Save() was called. You have to call LoadChunkData() again to
664       * get a new pointer whenever File::Save() was called.       * get a new, valid pointer whenever File::Save() was called.
665         *
666         * You can call LoadChunkData() again if you previously scheduled to
667         * enlarge this chunk with a Resize() call. In that case the buffer will
668         * be enlarged to the new, scheduled chunk size and you can already
669         * place the new chunk data to the buffer and finally call File::Save()
670         * to enlarge the chunk physically and write the new data in one rush.
671         * This approach is definitely recommended if you have to enlarge and
672         * write new data to a lot of chunks.
673       *       *
674       * @returns a pointer to the data in RAM on success, NULL otherwise       * @returns a pointer to the data in RAM on success, NULL otherwise
675         * @throws Exception if data buffer could not be enlarged
676       * @see ReleaseChunkData()       * @see ReleaseChunkData()
677       */       */
678      void* Chunk::LoadChunkData() {      void* Chunk::LoadChunkData() {
679          if (!pChunkData) {          if (!pChunkData) {
680              #if POSIX              #if POSIX
681              if (lseek(pFile->hFileRead, ulStartPos, SEEK_SET) == -1) return NULL;              if (lseek(pFile->hFileRead, ulStartPos, SEEK_SET) == -1) return NULL;
             pChunkData = new uint8_t[GetSize()];  
             if (!pChunkData) return NULL;  
             unsigned long readWords = read(pFile->hFileRead, pChunkData, GetSize());  
682              #else              #else
683              if (fseek(pFile->hFileRead, ulStartPos, SEEK_SET)) return NULL;              if (fseek(pFile->hFileRead, ulStartPos, SEEK_SET)) return NULL;
684              pChunkData = new uint8_t[GetSize()];              #endif // POSIX
685                unsigned long ulBufferSize = (CurrentChunkSize > NewChunkSize) ? CurrentChunkSize : NewChunkSize;
686                pChunkData = new uint8_t[ulBufferSize];
687              if (!pChunkData) return NULL;              if (!pChunkData) return NULL;
688                memset(pChunkData, 0, ulBufferSize);
689                #if POSIX
690                unsigned long readWords = read(pFile->hFileRead, pChunkData, GetSize());
691                #else
692              unsigned long readWords = fread(pChunkData, 1, GetSize(), pFile->hFileRead);              unsigned long readWords = fread(pChunkData, 1, GetSize(), pFile->hFileRead);
693              #endif // POSIX              #endif // POSIX
694              if (readWords != GetSize()) {              if (readWords != GetSize()) {
695                  delete[] pChunkData;                  delete[] pChunkData;
696                  return (pChunkData = NULL);                  return (pChunkData = NULL);
697              }              }
698                ulChunkDataSize = ulBufferSize;
699            } else if (NewChunkSize > ulChunkDataSize) {
700                uint8_t* pNewBuffer = new uint8_t[NewChunkSize];
701                if (!pNewBuffer) throw Exception("Could not enlarge chunk data buffer to " + ToString(NewChunkSize) + " bytes");
702                memset(pNewBuffer, 0 , NewChunkSize);
703                memcpy(pNewBuffer, pChunkData, ulChunkDataSize);
704                delete[] pChunkData;
705                pChunkData      = pNewBuffer;
706                ulChunkDataSize = NewChunkSize;
707          }          }
708          return pChunkData;          return pChunkData;
709      }      }
# Line 719  namespace RIFF { Line 733  namespace RIFF {
733       *       *
734       * <b>Caution:</b> You cannot directly write to enlarged chunks before       * <b>Caution:</b> You cannot directly write to enlarged chunks before
735       * calling File::Save() as this might exceed the current chunk's body       * calling File::Save() as this might exceed the current chunk's body
736       * boundary.       * boundary!
737       *       *
738       * @param iNewSize - new chunk body size in bytes (must be greater than zero)       * @param iNewSize - new chunk body size in bytes (must be greater than zero)
739       * @throws RIFF::Exception  if \a iNewSize is less than 1       * @throws RIFF::Exception  if \a iNewSize is less than 1
# Line 727  namespace RIFF { Line 741  namespace RIFF {
741       */       */
742      void Chunk::Resize(int iNewSize) {      void Chunk::Resize(int iNewSize) {
743          if (iNewSize <= 0) throw Exception("Chunk size must be at least one byte");          if (iNewSize <= 0) throw Exception("Chunk size must be at least one byte");
744            if (NewChunkSize == iNewSize) return;
745          NewChunkSize = iNewSize;          NewChunkSize = iNewSize;
746          pFile->LogAsResized(this);          pFile->LogAsResized(this);
747      }      }
# Line 752  namespace RIFF { Line 767  namespace RIFF {
767    
768          // if the whole chunk body was loaded into RAM          // if the whole chunk body was loaded into RAM
769          if (pChunkData) {          if (pChunkData) {
770              // in case the chunk size was changed, reallocate the data in RAM with the chunk's new size              // make sure chunk data buffer in RAM is at least as large as the new chunk size
771              if (NewChunkSize != CurrentChunkSize) {              LoadChunkData();
                 uint8_t* pNewBuffer = new uint8_t[NewChunkSize];  
                 if (NewChunkSize > CurrentChunkSize) {  
                     memcpy(pNewBuffer, pChunkData, CurrentChunkSize);  
                     memset(pNewBuffer + CurrentChunkSize, 0, NewChunkSize - CurrentChunkSize);  
                 } else {  
                     memcpy(pNewBuffer, pChunkData, NewChunkSize);  
                 }  
                 delete[] pChunkData;  
                 pChunkData = pNewBuffer;  
             }  
   
772              // write chunk data from RAM persistently to the file              // write chunk data from RAM persistently to the file
773              #if POSIX              #if POSIX
774              lseek(pFile->hFileWrite, ulWritePos, SEEK_SET);              lseek(pFile->hFileWrite, ulWritePos, SEEK_SET);

Legend:
Removed from v.798  
changed lines
  Added in v.800

  ViewVC Help
Powered by ViewVC