38 static String __resolveChunkPath(Chunk* pCk) {
40 for (Chunk* pChunk = pCk; pChunk; pChunk = pChunk->GetParent()) {
42 List* pList = (List*) pChunk;
43 sPath =
"->'" + pList->GetListTypeString() +
"'" + sPath;
45 sPath =
"->'" + pChunk->GetChunkIDString() +
"'" + sPath;
58 std::cout <<
"Chunk::Chunk(File* pFile)" << std::endl;
72 std::cout <<
"Chunk::Chunk(File*,ulong,bool,List*),StartPos=" << StartPos << std::endl;
104 std::cout <<
"Chunk::Readheader(" << fPos <<
") ";
113 if (SetFilePointer(
pFile->
hFileRead, fPos, NULL, FILE_BEGIN) != INVALID_SET_FILE_POINTER) {
126 #else // little endian
131 #endif // WORDS_BIGENDIAN
146 uint32_t uiNewChunkID =
ChunkID;
150 #else // little endian
152 #endif // WORDS_BIGENDIAN
166 if (SetFilePointer(
pFile->
hFileWrite, fPos, NULL, FILE_BEGIN) != INVALID_SET_FILE_POINTER) {
167 DWORD dwBytesWritten;
169 WriteFile(
pFile->
hFileWrite, &uiNewChunkSize, 4, &dwBytesWritten, NULL);
201 std::cout <<
"Chunk::SetPos(ulong)" << std::endl;
251 std::cout <<
"Chunk::GetState()" << std::endl;
255 #elif defined (WIN32)
280 unsigned long Chunk::Read(
void* pData,
unsigned long WordCount,
unsigned long WordSize) {
282 std::cout <<
"Chunk::Read(void*,ulong,ulong)" << std::endl;
289 unsigned long readWords = read(
pFile->
hFileRead, pData, WordCount * WordSize);
290 if (readWords < 1)
return 0;
291 readWords /= WordSize;
295 ReadFile(
pFile->
hFileRead, pData, WordCount * WordSize, &readWords, NULL);
296 if (readWords < 1)
return 0;
297 readWords /= WordSize;
298 #else // standard C functions
300 unsigned long readWords = fread(pData, WordSize, WordCount,
pFile->
hFileRead);
305 for (
unsigned long iWord = 0; iWord < readWords; iWord++)
309 for (
unsigned long iWord = 0; iWord < readWords; iWord++)
313 for (
unsigned long iWord = 0; iWord < readWords; iWord++)
314 swapBytes((uint8_t*) pData + iWord * WordSize, WordSize);
338 unsigned long Chunk::Write(
void* pData,
unsigned long WordCount,
unsigned long WordSize) {
340 throw Exception(
"Cannot write data to chunk, file has to be opened in read+write mode first");
342 throw Exception(
"End of chunk reached while trying to write data");
346 for (
unsigned long iWord = 0; iWord < WordCount; iWord++)
350 for (
unsigned long iWord = 0; iWord < WordCount; iWord++)
354 for (
unsigned long iWord = 0; iWord < WordCount; iWord++)
355 swapBytes((uint8_t*) pData + iWord * WordSize, WordSize);
364 unsigned long writtenWords = write(
pFile->
hFileWrite, pData, WordCount * WordSize);
365 if (writtenWords < 1)
throw Exception(
"POSIX IO Error while trying to write chunk data");
366 writtenWords /= WordSize;
373 WriteFile(
pFile->
hFileWrite, pData, WordCount * WordSize, &writtenWords, NULL);
374 if (writtenWords < 1)
throw Exception(
"Windows IO Error while trying to write chunk data");
375 writtenWords /= WordSize;
376 #else // standard C functions
381 unsigned long writtenWords = fwrite(pData, WordSize, WordCount,
pFile->
hFileWrite);
389 unsigned long readWords =
Read(pData, WordCount, WordSize);
390 if (readWords != WordCount)
throw RIFF::Exception(
"End of chunk data reached.");
407 std::cout <<
"Chunk::ReadInt8(int8_t*,ulong)" << std::endl;
427 return Write(pData, WordCount, 1);
444 std::cout <<
"Chunk::ReadUint8(uint8_t*,ulong)" << std::endl;
464 return Write(pData, WordCount, 1);
481 std::cout <<
"Chunk::ReadInt16(int16_t*,ulong)" << std::endl;
501 return Write(pData, WordCount, 2);
518 std::cout <<
"Chunk::ReadUint16(uint16_t*,ulong)" << std::endl;
538 return Write(pData, WordCount, 2);
555 std::cout <<
"Chunk::ReadInt32(int32_t*,ulong)" << std::endl;
575 return Write(pData, WordCount, 4);
592 std::cout <<
"Chunk::ReadUint32(uint32_t*,ulong)" << std::endl;
612 return Write(pData, WordCount, 4);
624 std::cout <<
"Chunk::ReadInt8()" << std::endl;
640 std::cout <<
"Chunk::ReadUint8()" << std::endl;
657 std::cout <<
"Chunk::ReadInt16()" << std::endl;
674 std::cout <<
"Chunk::ReadUint16()" << std::endl;
691 std::cout <<
"Chunk::ReadInt32()" << std::endl;
708 std::cout <<
"Chunk::ReadUint32()" << std::endl;
764 if (!pNewBuffer)
throw Exception(
"Could not enlarge chunk data buffer to " + ToString(
NewChunkSize) +
" bytes");
807 throw Exception(
"There is at least one empty chunk (zero size): " + __resolveChunkPath(
this));
826 const unsigned long ulOriginalPos = ulWritePos;
830 throw Exception(
"Cannot write list chunk, file has to be opened in read+write mode");
840 throw Exception(
"Writing Chunk data (from RAM) failed");
844 DWORD dwBytesWritten;
847 throw Exception(
"Writing Chunk data (from RAM) failed");
852 throw Exception(
"Writing Chunk data (from RAM) failed");
857 int8_t* pCopyBuffer =
new int8_t[4096];
860 DWORD iBytesMoved = 1;
864 for (
unsigned long ulOffset = 0; iBytesMoved > 0; ulOffset += iBytesMoved, ulToMove -= iBytesMoved) {
865 iBytesMoved = (ulToMove < 4096) ? ulToMove : 4096;
873 ReadFile(
pFile->
hFileRead, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
874 SetFilePointer(
pFile->
hFileWrite, ulWritePos + ulOffset, NULL, FILE_BEGIN);
875 WriteFile(
pFile->
hFileWrite, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
878 iBytesMoved = fread(pCopyBuffer, 1, iBytesMoved,
pFile->
hFileRead);
883 delete[] pCopyBuffer;
884 if (iBytesMoved < 0)
throw Exception(
"Writing Chunk data (from file) failed");
897 const char cPadByte = 0;
903 DWORD dwBytesWritten;
926 std::cout <<
"List::List(File* pFile)" << std::endl;
933 :
Chunk(pFile, StartPos, Parent) {
935 std::cout <<
"List::List(File*,ulong,bool,List*)" << std::endl;
952 std::cout <<
"List::~List()" << std::endl;
959 ChunkList::iterator iter =
pSubChunks->begin();
961 while (iter != end) {
987 std::cout <<
"List::GetSubChunk(uint32_t)" << std::endl;
1006 std::cout <<
"List::GetSubList(uint32_t)" << std::endl;
1009 ChunkList::iterator iter =
pSubChunks->begin();
1011 while (iter != end) {
1031 std::cout <<
"List::GetFirstSubChunk()" << std::endl;
1047 std::cout <<
"List::GetNextSubChunk()" << std::endl;
1065 std::cout <<
"List::GetFirstSubList()" << std::endl;
1087 std::cout <<
"List::GetNextSubList()" << std::endl;
1113 unsigned int result = 0;
1115 ChunkList::iterator iter =
pSubChunks->begin();
1117 while (iter != end) {
1118 if ((*iter)->GetChunkID() ==
ChunkID) {
1138 unsigned int result = 0;
1140 ChunkList::iterator iter =
pSubChunks->begin();
1142 while (iter != end) {
1166 if (uiBodySize == 0)
throw Exception(
"Chunk body size must be at least 1 byte");
1170 (*pSubChunksMap)[uiChunkID] = pNewChunk;
1171 pNewChunk->
Resize(uiBodySize);
1211 return pNewListChunk;
1230 ChunkList::iterator iter =
pSubChunks->begin();
1232 for (; iter != end; ++iter) {
1233 if ((*iter)->GetChunkID() == pSubChunk->
GetChunkID()) {
1234 (*pSubChunksMap)[pSubChunk->
GetChunkID()] = *iter;
1244 std::cout <<
"List::Readheader(ulong) ";
1252 #elif defined(WIN32)
1276 #elif defined(WIN32)
1278 DWORD dwBytesWritten;
1288 std::cout <<
"List::LoadSubChunks()";
1298 unsigned long uiOriginalPos =
GetPos();
1316 (*pSubChunksMap)[ckid] = ck;
1325 pList->LoadSubChunksRecursively();
1343 const unsigned long ulOriginalPos = ulWritePos;
1347 throw Exception(
"Cannot write list chunk, file has to be opened in read+write mode");
1351 for (ChunkList::iterator iter =
pSubChunks->begin(), end =
pSubChunks->end(); iter != end; ++iter) {
1352 ulWritePos = (*iter)->WriteChunk(ulWritePos, ulCurrentDataOffset);
1369 for (ChunkList::iterator iter =
pSubChunks->begin(), end =
pSubChunks->end(); iter != end; ++iter) {
1370 (*iter)->__resetPos();
1388 #define _GET_RESIZED_CHUNKS() \
1389 (reinterpret_cast<std::set<Chunk*>*>(ResizedChunks.front()))
1407 ResizedChunks.push_back(reinterpret_cast<Chunk*>(
new std::set<Chunk*>));
1429 std::cout <<
"File::File("<<path<<
")" << std::endl;
1433 ResizedChunks.push_back(reinterpret_cast<Chunk*>(
new std::set<Chunk*>));
1440 #elif defined(WIN32)
1442 path.c_str(), GENERIC_READ,
1443 FILE_SHARE_READ | FILE_SHARE_WRITE,
1444 NULL, OPEN_EXISTING,
1445 FILE_ATTRIBUTE_NORMAL |
1446 FILE_FLAG_RANDOM_ACCESS, NULL
1448 if (
hFileRead == INVALID_HANDLE_VALUE) {
1483 if (NewMode != Mode) {
1493 #elif defined(WIN32)
1497 FILE_SHARE_READ | FILE_SHARE_WRITE,
1498 NULL, OPEN_EXISTING,
1499 FILE_ATTRIBUTE_NORMAL |
1500 FILE_FLAG_RANDOM_ACCESS,
1503 if (
hFileRead == INVALID_HANDLE_VALUE) {
1522 #elif defined(WIN32)
1526 GENERIC_READ | GENERIC_WRITE,
1529 FILE_ATTRIBUTE_NORMAL |
1530 FILE_FLAG_RANDOM_ACCESS,
1533 if (
hFileRead == INVALID_HANDLE_VALUE) {
1536 FILE_SHARE_READ | FILE_SHARE_WRITE,
1537 NULL, OPEN_EXISTING,
1538 FILE_ATTRIBUTE_NORMAL |
1539 FILE_FLAG_RANDOM_ACCESS,
1542 throw Exception(
"Could not (re)open file \"" +
Filename +
"\" in read+write mode");
1558 #elif defined(WIN32)
1568 throw Exception(
"Unknown file access mode");
1618 unsigned long ulPositiveSizeDiff = 0;
1620 for (std::set<Chunk*>::const_iterator iter = resizedChunks->begin(), end = resizedChunks->end(); iter != end; ++iter) {
1621 if ((*iter)->GetNewSize() == 0) {
1622 throw Exception(
"There is at least one empty chunk (zero size): " + __resolveChunkPath(*iter));
1624 unsigned long newSizePadded = (*iter)->GetNewSize() + (*iter)->GetNewSize() % 2;
1625 unsigned long oldSizePadded = (*iter)->GetSize() + (*iter)->GetSize() % 2;
1626 if (newSizePadded > oldSizePadded) ulPositiveSizeDiff += newSizePadded - oldSizePadded;
1629 unsigned long ulWorkingFileSize = GetFileSize();
1632 if (ulPositiveSizeDiff > 0) {
1634 ulWorkingFileSize += ulPositiveSizeDiff;
1635 ResizeFile(ulWorkingFileSize);
1637 int8_t* pCopyBuffer =
new int8_t[4096];
1640 DWORD iBytesMoved = 1;
1642 int iBytesMoved = 1;
1644 for (
unsigned long ulPos = ulFileSize; iBytesMoved > 0; ) {
1646 ulPos -= iBytesMoved;
1649 iBytesMoved = read(
hFileRead, pCopyBuffer, iBytesMoved);
1651 iBytesMoved = write(
hFileWrite, pCopyBuffer, iBytesMoved);
1652 #elif defined(WIN32)
1654 ReadFile(
hFileRead, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
1655 SetFilePointer(
hFileWrite,
ulPos + ulPositiveSizeDiff, NULL, FILE_BEGIN);
1656 WriteFile(
hFileWrite, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
1659 iBytesMoved = fread(pCopyBuffer, 1, iBytesMoved,
hFileRead);
1661 iBytesMoved = fwrite(pCopyBuffer, 1, iBytesMoved,
hFileWrite);
1664 delete[] pCopyBuffer;
1665 if (iBytesMoved < 0)
throw Exception(
"Could not modify file while trying to enlarge it");
1669 unsigned long ulTotalSize =
WriteChunk(0, ulPositiveSizeDiff);
1670 unsigned long ulActualSize = __GetFileSize(
hFileWrite);
1673 if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1676 resizedChunks->clear();
1701 hFileWrite = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
1704 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1706 #elif defined(WIN32)
1708 path.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
1709 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL |
1710 FILE_FLAG_RANDOM_ACCESS, NULL
1714 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1720 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1726 unsigned long ulTotalSize =
WriteChunk(0, 0);
1727 unsigned long ulActualSize = __GetFileSize(
hFileWrite);
1730 if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1737 #elif defined(WIN32)
1750 void File::ResizeFile(
unsigned long ulNewSize) {
1754 #elif defined(WIN32)
1756 SetFilePointer(
hFileWrite, ulNewSize, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ||
1760 # error Sorry, this version of libgig only supports POSIX and Windows systems yet.
1761 # error Reason: portable implementation of RIFF::File::ResizeFile() is missing (yet)!
1767 std::cout <<
"File::~File()" << std::endl;
1771 #elif defined(WIN32)
1790 unsigned long File::GetFileSize() {
1795 unsigned long File::__GetFileSize(
int hFile) {
1796 struct stat filestat;
1797 fstat(hFile, &filestat);
1798 long size = filestat.st_size;
1801 #elif defined(WIN32)
1802 unsigned long File::__GetFileSize(HANDLE hFile) {
1803 DWORD dwSize = ::GetFileSize(hFile, NULL );
1804 if (dwSize == INVALID_FILE_SIZE)
1805 throw Exception(
"Windows FS error: could not determine file size");
1808 #else // standard C functions
1809 unsigned long File::__GetFileSize(FILE* hFile) {
1810 long curpos = ftell(hFile);
1811 fseek(hFile, 0, SEEK_END);
1812 long size = ftell(hFile);
1813 fseek(hFile, curpos, SEEK_SET);
1823 std::cout <<
"RIFF::Exception: " <<
Message << std::endl;