/[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 780 by schoenebeck, Sun Sep 25 13:40:37 2005 UTC revision 933 by schoenebeck, Fri Nov 24 12:50:05 2006 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file loader library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2005 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2006 by Christian Schoenebeck                      *
6   *                              <cuse@users.sourceforge.net>               *   *                              <cuse@users.sourceforge.net>               *
7   *                                                                         *   *                                                                         *
8   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
# 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;
44          this->pFile = pFile;          this->pFile = pFile;
45      }      }
46    
# Line 61  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 70  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 94  namespace RIFF { Line 88  namespace RIFF {
88          #endif // POSIX          #endif // POSIX
89              #if WORDS_BIGENDIAN              #if WORDS_BIGENDIAN
90              if (ChunkID == CHUNK_ID_RIFF) {              if (ChunkID == CHUNK_ID_RIFF) {
91                  bEndianNative = false;                  pFile->bEndianNative = false;
92              }              }
93              #else // little endian              #else // little endian
94              if (ChunkID == CHUNK_ID_RIFX) {              if (ChunkID == CHUNK_ID_RIFX) {
# Line 293  namespace RIFF { Line 287  namespace RIFF {
287       *  @see Resize()       *  @see Resize()
288       */       */
289      unsigned long Chunk::Write(void* pData, unsigned long WordCount, unsigned long WordSize) {      unsigned long Chunk::Write(void* pData, unsigned long WordCount, unsigned long WordSize) {
290          if (pFile->Mode == stream_mode_read)          if (pFile->Mode != stream_mode_read_write)
291              throw Exception("Writing chunk data in read-only file access mode was attempted");              throw Exception("Cannot write data to chunk, file has to be opened in read+write mode first");
292          if (ulPos >= CurrentChunkSize || ulPos + WordCount * WordSize >= CurrentChunkSize)          if (ulPos >= CurrentChunkSize || ulPos + WordCount * WordSize > CurrentChunkSize)
293              throw Exception("End of chunk reached while trying to write data");              throw Exception("End of chunk reached while trying to write data");
294          if (!pFile->bEndianNative && WordSize != 1) {          if (!pFile->bEndianNative && WordSize != 1) {
295              switch (WordSize) {              switch (WordSize) {
# Line 667  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 && pFile->Filename != "") {
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 718  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 726  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 743  namespace RIFF { Line 759  namespace RIFF {
759       *          (including its header size of course)       *          (including its header size of course)
760       */       */
761      unsigned long Chunk::WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset) {      unsigned long Chunk::WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset) {
762          unsigned long ulOriginalPos = ulWritePos;          const unsigned long ulOriginalPos = ulWritePos;
763          ulWritePos += CHUNK_HEADER_SIZE;          ulWritePos += CHUNK_HEADER_SIZE;
764    
765            if (pFile->Mode != stream_mode_read_write)
766                throw Exception("Cannot write list chunk, file has to be opened in read+write mode");
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);
# Line 806  namespace RIFF { Line 814  namespace RIFF {
814    
815          // add pad byte if needed          // add pad byte if needed
816          if ((ulStartPos + NewChunkSize) % 2 != 0) {          if ((ulStartPos + NewChunkSize) % 2 != 0) {
817              char cPadByte = 0;              const char cPadByte = 0;
818              #if POSIX              #if POSIX
819                lseek(pFile->hFileWrite, ulStartPos + NewChunkSize, SEEK_SET);
820              write(pFile->hFileWrite, &cPadByte, 1);              write(pFile->hFileWrite, &cPadByte, 1);
821              #else              #else
822                fseek(pFile->hFileWrite, ulStartPos + NewChunkSize, SEEK_SET);
823              fwrite(&cPadByte, 1, 1, pFile->hFileWrite);              fwrite(&cPadByte, 1, 1, pFile->hFileWrite);
824              #endif              #endif
825              return ulStartPos + NewChunkSize + 1;              return ulStartPos + NewChunkSize + 1;
# Line 1063  namespace RIFF { Line 1073  namespace RIFF {
1073      Chunk* List::AddSubChunk(uint32_t uiChunkID, uint uiBodySize) {      Chunk* List::AddSubChunk(uint32_t uiChunkID, uint uiBodySize) {
1074          if (uiBodySize == 0) throw Exception("Chunk body size must be at least 1 byte");          if (uiBodySize == 0) throw Exception("Chunk body size must be at least 1 byte");
1075          if (!pSubChunks) LoadSubChunks();          if (!pSubChunks) LoadSubChunks();
1076          Chunk* pNewChunk = new Chunk(pFile, this, uiChunkID, uiBodySize);          Chunk* pNewChunk = new Chunk(pFile, this, uiChunkID, 0);
1077          pSubChunks->push_back(pNewChunk);          pSubChunks->push_back(pNewChunk);
1078          (*pSubChunksMap)[uiChunkID] = pNewChunk;          (*pSubChunksMap)[uiChunkID] = pNewChunk;
1079          pFile->ResizedChunks.push_back(pNewChunk);          pNewChunk->Resize(uiBodySize);
1080          return pNewChunk;          return pNewChunk;
1081      }      }
1082    
# Line 1182  namespace RIFF { Line 1192  namespace RIFF {
1192          }          }
1193      }      }
1194    
1195        void List::LoadSubChunksRecursively() {
1196            for (List* pList = GetFirstSubList(); pList; pList = GetNextSubList())
1197                pList->LoadSubChunksRecursively();
1198        }
1199    
1200      /** @brief Write list chunk persistently e.g. to disk.      /** @brief Write list chunk persistently e.g. to disk.
1201       *       *
1202       * Stores the list chunk persistently to its actual "physical" file. All       * Stores the list chunk persistently to its actual "physical" file. All
# Line 1197  namespace RIFF { Line 1212  namespace RIFF {
1212       *          (including its header size of course)       *          (including its header size of course)
1213       */       */
1214      unsigned long List::WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset) {      unsigned long List::WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset) {
1215          unsigned long ulOriginalPos = ulWritePos;          const unsigned long ulOriginalPos = ulWritePos;
1216          ulWritePos += LIST_HEADER_SIZE;          ulWritePos += LIST_HEADER_SIZE;
1217    
1218            if (pFile->Mode != stream_mode_read_write)
1219                throw Exception("Cannot write list chunk, file has to be opened in read+write mode");
1220    
1221          // write all subchunks (including sub list chunks) recursively          // write all subchunks (including sub list chunks) recursively
1222          if (pSubChunks) {          if (pSubChunks) {
1223              for (ChunkList::iterator iter = pSubChunks->begin(), end = pSubChunks->end(); iter != end; ++iter) {              for (ChunkList::iterator iter = pSubChunks->begin(), end = pSubChunks->end(); iter != end; ++iter) {
# Line 1211  namespace RIFF { Line 1229  namespace RIFF {
1229          CurrentChunkSize = NewChunkSize = ulWritePos - ulOriginalPos - LIST_HEADER_SIZE;          CurrentChunkSize = NewChunkSize = ulWritePos - ulOriginalPos - LIST_HEADER_SIZE;
1230          WriteHeader(ulOriginalPos);          WriteHeader(ulOriginalPos);
1231    
1232            // offset of this list chunk in new written file may have changed
1233            ulStartPos = ulOriginalPos + LIST_HEADER_SIZE;
1234    
1235          return ulWritePos;          return ulWritePos;
1236      }      }
1237    
# Line 1241  namespace RIFF { Line 1262  namespace RIFF {
1262       * "from scratch". Note: there must be no empty chunks or empty list       * "from scratch". Note: there must be no empty chunks or empty list
1263       * chunks when trying to make the new RIFF file persistent with Save()!       * chunks when trying to make the new RIFF file persistent with Save()!
1264       *       *
1265         * @param FileType - four-byte identifier of the RIFF file type
1266       * @see AddSubChunk(), AddSubList()       * @see AddSubChunk(), AddSubList()
1267       */       */
1268      File::File() : List(this) {      File::File(uint32_t FileType) : List(this) {
1269          hFileRead = hFileWrite = 0;          hFileRead = hFileWrite = 0;
1270            Mode = stream_mode_closed;
1271          bEndianNative = true;          bEndianNative = true;
1272          ulStartPos = RIFF_HEADER_SIZE;          ulStartPos = RIFF_HEADER_SIZE;
1273            ListType = FileType;
1274      }      }
1275    
1276      /** @brief Load existing RIFF file.      /** @brief Load existing RIFF file.
# Line 1272  namespace RIFF { Line 1296  namespace RIFF {
1296          hFileRead = hFileWrite = fopen(path.c_str(), "rb");          hFileRead = hFileWrite = fopen(path.c_str(), "rb");
1297          if (!hFile) throw RIFF::Exception("Can't open \"" + path + "\"");          if (!hFile) throw RIFF::Exception("Can't open \"" + path + "\"");
1298          #endif // POSIX          #endif // POSIX
1299            Mode = stream_mode_read;
1300          ulStartPos = RIFF_HEADER_SIZE;          ulStartPos = RIFF_HEADER_SIZE;
1301          ReadHeader(0);          ReadHeader(0);
1302          if (ChunkID != CHUNK_ID_RIFF) {          if (ChunkID != CHUNK_ID_RIFF) {
# Line 1314  namespace RIFF { Line 1339  namespace RIFF {
1339                      if (!hFileRead) throw Exception("Could not (re)open file \"" + Filename + "\" in read mode");                      if (!hFileRead) throw Exception("Could not (re)open file \"" + Filename + "\" in read mode");
1340                      #endif                      #endif
1341                      __resetPos(); // reset read/write position of ALL 'Chunk' objects                      __resetPos(); // reset read/write position of ALL 'Chunk' objects
1342                      return true;                      break;
1343                  case stream_mode_read_write:                  case stream_mode_read_write:
1344                      #if POSIX                      #if POSIX
1345                      if (hFileRead) close(hFileRead);                      if (hFileRead) close(hFileRead);
# Line 1332  namespace RIFF { Line 1357  namespace RIFF {
1357                      }                      }
1358                      #endif                      #endif
1359                      __resetPos(); // reset read/write position of ALL 'Chunk' objects                      __resetPos(); // reset read/write position of ALL 'Chunk' objects
1360                      return true;                      break;
1361                    case stream_mode_closed:
1362                        #if POSIX
1363                        if (hFileRead)  close(hFileRead);
1364                        if (hFileWrite) close(hFileWrite);
1365                        #else
1366                        if (hFileRead)  fclose(hFileRead);
1367                        if (hFileWrite) fclose(hFileWrite);
1368                        #endif
1369                        hFileRead = hFileWrite = 0;
1370                        break;
1371                  default:                  default:
1372                      throw Exception("Unknown file access mode");                      throw Exception("Unknown file access mode");
1373              }              }
1374                Mode = NewMode;
1375                return true;
1376          }          }
1377          return false;          return false;
1378      }      }
# Line 1351  namespace RIFF { Line 1388  namespace RIFF {
1388       *                         chunk or any kind of IO error occured       *                         chunk or any kind of IO error occured
1389       */       */
1390      void File::Save() {      void File::Save() {
1391            // make sure the RIFF tree is built (from the original file)
1392            LoadSubChunksRecursively();
1393    
1394          // reopen file in write mode          // reopen file in write mode
1395          bool bModeWasChanged = SetMode(stream_mode_read_write);          SetMode(stream_mode_read_write);
1396    
1397          // to be able to save the whole file without loading everything into          // to be able to save the whole file without loading everything into
1398          // RAM and without having to store the data in a temporary file, we          // RAM and without having to store the data in a temporary file, we
# Line 1365  namespace RIFF { Line 1405  namespace RIFF {
1405          unsigned long ulPositiveSizeDiff = 0;          unsigned long ulPositiveSizeDiff = 0;
1406          for (ChunkList::iterator iter = ResizedChunks.begin(), end = ResizedChunks.end(); iter != end; ++iter) {          for (ChunkList::iterator iter = ResizedChunks.begin(), end = ResizedChunks.end(); iter != end; ++iter) {
1407              if ((*iter)->GetNewSize() == 0) throw Exception("There is at least one empty chunk (zero size)");              if ((*iter)->GetNewSize() == 0) throw Exception("There is at least one empty chunk (zero size)");
1408              unsigned long ulDiff = (*iter)->GetNewSize() - (*iter)->GetSize() + 1L; // +1 in case we have to add a pad byte              if ((*iter)->GetNewSize() + 1L > (*iter)->GetSize()) {
1409              if (ulDiff > 0) ulPositiveSizeDiff += ulDiff;                  unsigned long ulDiff = (*iter)->GetNewSize() - (*iter)->GetSize() + 1L; // +1 in case we have to add a pad byte
1410                    ulPositiveSizeDiff += ulDiff;
1411                }
1412          }          }
1413    
1414          unsigned long ulWorkingFileSize = GetFileSize();          unsigned long ulWorkingFileSize = GetFileSize();
# Line 1400  namespace RIFF { Line 1442  namespace RIFF {
1442          }          }
1443    
1444          // rebuild / rewrite complete RIFF tree          // rebuild / rewrite complete RIFF tree
1445          unsigned long ulTotalSize = WriteChunk(0, ulPositiveSizeDiff);          unsigned long ulTotalSize  = WriteChunk(0, ulPositiveSizeDiff);
1446            unsigned long ulActualSize = __GetFileSize(hFileWrite);
1447    
1448          // resize file to the final size          // resize file to the final size
1449          if (ulTotalSize < ulWorkingFileSize) ResizeFile(ulTotalSize);          if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1450    
1451          // forget all resized chunks          // forget all resized chunks
1452          ResizedChunks.clear();          ResizedChunks.clear();
   
         // reopen file in read mode  
         if (bModeWasChanged) SetMode(stream_mode_read);  
1453      }      }
1454    
1455      /** @brief Save changes to another file.      /** @brief Save changes to another file.
# Line 1417  namespace RIFF { Line 1457  namespace RIFF {
1457       * Make all changes of all chunks persistent by writing them to another       * Make all changes of all chunks persistent by writing them to another
1458       * file. <b>Caution:</b> this method is optimized for writing to       * file. <b>Caution:</b> this method is optimized for writing to
1459       * <b>another</b> file, do not use it to save the changes to the same       * <b>another</b> file, do not use it to save the changes to the same
1460       * file! Use File::Save() in that case instead!       * file! Use File::Save() in that case instead! Ignoring this might
1461         * result in a corrupted file, especially in case chunks were resized!
1462       *       *
1463       * After calling this method, this File object will be associated with       * After calling this method, this File object will be associated with
1464       * the new file (given by \a path) afterwards.       * the new file (given by \a path) afterwards.
# Line 1425  namespace RIFF { Line 1466  namespace RIFF {
1466       * @param path - path and file name where everything should be written to       * @param path - path and file name where everything should be written to
1467       */       */
1468      void File::Save(const String& path) {      void File::Save(const String& path) {
1469            //TODO: we should make a check here if somebody tries to write to the same file and automatically call the other Save() method in that case
1470    
1471            // make sure the RIFF tree is built (from the original file)
1472            LoadSubChunksRecursively();
1473    
1474            if (Filename.length() > 0) SetMode(stream_mode_read);
1475          // open the other (new) file for writing and truncate it to zero size          // open the other (new) file for writing and truncate it to zero size
1476          #if POSIX          #if POSIX
1477          hFileWrite = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC);          hFileWrite = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
1478          if (hFileWrite < 0) {          if (hFileWrite < 0) {
1479              hFileWrite = hFileRead;              hFileWrite = hFileRead;
1480              throw Exception("Could not open file \"" + path + "\" for writing");              throw Exception("Could not open file \"" + path + "\" for writing");
# Line 1439  namespace RIFF { Line 1486  namespace RIFF {
1486              throw Exception("Could not open file \"" + path + "\" for writing");              throw Exception("Could not open file \"" + path + "\" for writing");
1487          }          }
1488          #endif // POSIX          #endif // POSIX
1489            Mode = stream_mode_read_write;
1490    
1491          // write complete RIFF tree to the other (new) file          // write complete RIFF tree to the other (new) file
1492          WriteChunk(0, 0);          unsigned long ulTotalSize  = WriteChunk(0, 0);
1493            unsigned long ulActualSize = __GetFileSize(hFileWrite);
1494    
1495            // resize file to the final size (if the file was originally larger)
1496            if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1497    
1498          // forget all resized chunks          // forget all resized chunks
1499          ResizedChunks.clear();          ResizedChunks.clear();
1500    
1501            if (Filename.length() > 0) {
1502                #if POSIX
1503                close(hFileWrite);
1504                #else
1505                fclose(hFileWrite);
1506                #endif
1507                hFileWrite = hFileRead;
1508            }
1509    
1510          // associate new file with this File object from now on          // associate new file with this File object from now on
1511          Filename = path;          Filename = path;
1512          stream_mode_t oldMode = Mode;          Mode = (stream_mode_t) -1;       // Just set it to an undefined mode ...
1513          Mode = (stream_mode_t) -1; // Just set it to an undefined mode ...          SetMode(stream_mode_read_write); // ... so SetMode() has to reopen the file handles.
         SetMode(oldMode);          // ... so SetMode() has to reopen the file handles.  
1514      }      }
1515    
1516      void File::ResizeFile(unsigned long ulNewSize) {      void File::ResizeFile(unsigned long ulNewSize) {
# Line 1459  namespace RIFF { Line 1519  namespace RIFF {
1519              throw Exception("Could not resize file \"" + Filename + "\"");              throw Exception("Could not resize file \"" + Filename + "\"");
1520          #else          #else
1521          # error Sorry, this version of libgig only supports POSIX systems yet.          # error Sorry, this version of libgig only supports POSIX systems yet.
1522          # error Reason: portable implementation of RIFF::File::ResizeFile() is missing!          # error Reason: portable implementation of RIFF::File::ResizeFile() is missing (yet)!
1523          #endif          #endif
1524      }      }
1525    
# Line 1479  namespace RIFF { Line 1539  namespace RIFF {
1539      }      }
1540    
1541      unsigned long File::GetFileSize() {      unsigned long File::GetFileSize() {
1542          #if POSIX          return __GetFileSize(hFileRead);
1543        }
1544    
1545        #if POSIX
1546        unsigned long File::__GetFileSize(int hFile) {
1547          struct stat filestat;          struct stat filestat;
1548          fstat(hFileRead, &filestat);          fstat(hFile, &filestat);
1549          long size = filestat.st_size;          long size = filestat.st_size;
         #else // standard C functions  
         long curpos = ftell(hFileRead);  
         fseek(hFileRead, 0, SEEK_END);  
         long size = ftell(hFileRead);  
         fseek(hFileRead, curpos, SEEK_SET);  
         #endif // POSIX  
1550          return size;          return size;
1551      }      }
1552        #else // standard C functions
1553        unsigned long File::__GetFileSize(FILE* hFile) {
1554            long curpos = ftell(hFile);
1555            fseek(hFile, 0, SEEK_END);
1556            long size = ftell(hFile);
1557            fseek(hFile, curpos, SEEK_SET);
1558            return size;
1559        }
1560        #endif
1561    
1562    
1563  // *************** Exception ***************  // *************** Exception ***************

Legend:
Removed from v.780  
changed lines
  Added in v.933

  ViewVC Help
Powered by ViewVC