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; ulToMove > 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;
1434 ResizedChunks.push_back(reinterpret_cast<Chunk*>(
new std::set<Chunk*>));
1441 #elif defined(WIN32)
1443 path.c_str(), GENERIC_READ,
1444 FILE_SHARE_READ | FILE_SHARE_WRITE,
1445 NULL, OPEN_EXISTING,
1446 FILE_ATTRIBUTE_NORMAL |
1447 FILE_FLAG_RANDOM_ACCESS, NULL
1449 if (
hFileRead == INVALID_HANDLE_VALUE) {
1489 if (NewMode != Mode) {
1499 #elif defined(WIN32)
1503 FILE_SHARE_READ | FILE_SHARE_WRITE,
1504 NULL, OPEN_EXISTING,
1505 FILE_ATTRIBUTE_NORMAL |
1506 FILE_FLAG_RANDOM_ACCESS,
1509 if (
hFileRead == INVALID_HANDLE_VALUE) {
1528 #elif defined(WIN32)
1532 GENERIC_READ | GENERIC_WRITE,
1535 FILE_ATTRIBUTE_NORMAL |
1536 FILE_FLAG_RANDOM_ACCESS,
1539 if (
hFileRead == INVALID_HANDLE_VALUE) {
1542 FILE_SHARE_READ | FILE_SHARE_WRITE,
1543 NULL, OPEN_EXISTING,
1544 FILE_ATTRIBUTE_NORMAL |
1545 FILE_FLAG_RANDOM_ACCESS,
1548 throw Exception(
"Could not (re)open file \"" +
Filename +
"\" in read+write mode");
1564 #elif defined(WIN32)
1574 throw Exception(
"Unknown file access mode");
1624 unsigned long ulPositiveSizeDiff = 0;
1626 for (std::set<Chunk*>::const_iterator iter = resizedChunks->begin(), end = resizedChunks->end(); iter != end; ++iter) {
1627 if ((*iter)->GetNewSize() == 0) {
1628 throw Exception(
"There is at least one empty chunk (zero size): " + __resolveChunkPath(*iter));
1630 unsigned long newSizePadded = (*iter)->GetNewSize() + (*iter)->GetNewSize() % 2;
1631 unsigned long oldSizePadded = (*iter)->GetSize() + (*iter)->GetSize() % 2;
1632 if (newSizePadded > oldSizePadded) ulPositiveSizeDiff += newSizePadded - oldSizePadded;
1635 unsigned long ulWorkingFileSize = GetFileSize();
1638 if (ulPositiveSizeDiff > 0) {
1640 ulWorkingFileSize += ulPositiveSizeDiff;
1641 ResizeFile(ulWorkingFileSize);
1643 int8_t* pCopyBuffer =
new int8_t[4096];
1646 DWORD iBytesMoved = 1;
1648 int iBytesMoved = 1;
1650 for (
unsigned long ulPos = ulFileSize; iBytesMoved > 0; ) {
1652 ulPos -= iBytesMoved;
1655 iBytesMoved = read(
hFileRead, pCopyBuffer, iBytesMoved);
1657 iBytesMoved = write(
hFileWrite, pCopyBuffer, iBytesMoved);
1658 #elif defined(WIN32)
1660 ReadFile(
hFileRead, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
1661 SetFilePointer(
hFileWrite,
ulPos + ulPositiveSizeDiff, NULL, FILE_BEGIN);
1662 WriteFile(
hFileWrite, pCopyBuffer, iBytesMoved, &iBytesMoved, NULL);
1665 iBytesMoved = fread(pCopyBuffer, 1, iBytesMoved,
hFileRead);
1667 iBytesMoved = fwrite(pCopyBuffer, 1, iBytesMoved,
hFileWrite);
1670 delete[] pCopyBuffer;
1671 if (iBytesMoved < 0)
throw Exception(
"Could not modify file while trying to enlarge it");
1675 unsigned long ulTotalSize =
WriteChunk(0, ulPositiveSizeDiff);
1676 unsigned long ulActualSize = __GetFileSize(
hFileWrite);
1679 if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1682 resizedChunks->clear();
1707 hFileWrite = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
1710 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1712 #elif defined(WIN32)
1714 path.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
1715 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL |
1716 FILE_FLAG_RANDOM_ACCESS, NULL
1720 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1726 throw Exception(
"Could not open file \"" + path +
"\" for writing");
1732 unsigned long ulTotalSize =
WriteChunk(0, 0);
1733 unsigned long ulActualSize = __GetFileSize(
hFileWrite);
1736 if (ulTotalSize < ulActualSize) ResizeFile(ulTotalSize);
1743 #elif defined(WIN32)
1756 void File::ResizeFile(
unsigned long ulNewSize) {
1760 #elif defined(WIN32)
1762 SetFilePointer(
hFileWrite, ulNewSize, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ||
1766 # error Sorry, this version of libgig only supports POSIX and Windows systems yet.
1767 # error Reason: portable implementation of RIFF::File::ResizeFile() is missing (yet)!
1773 std::cout <<
"File::~File()" << std::endl;
1778 void File::Cleanup() {
1781 #elif defined(WIN32)
1800 unsigned long File::GetFileSize() {
1805 unsigned long File::__GetFileSize(
int hFile) {
1806 struct stat filestat;
1807 fstat(hFile, &filestat);
1808 long size = filestat.st_size;
1811 #elif defined(WIN32)
1812 unsigned long File::__GetFileSize(HANDLE hFile) {
1813 DWORD dwSize = ::GetFileSize(hFile, NULL );
1814 if (dwSize == INVALID_FILE_SIZE)
1815 throw Exception(
"Windows FS error: could not determine file size");
1818 #else // standard C functions
1819 unsigned long File::__GetFileSize(FILE* hFile) {
1820 long curpos = ftell(hFile);
1821 fseek(hFile, 0, SEEK_END);
1822 long size = ftell(hFile);
1823 fseek(hFile, curpos, SEEK_SET);
1833 std::cout <<
"RIFF::Exception: " <<
Message << std::endl;