29 |
|
|
30 |
namespace RIFF { |
namespace RIFF { |
31 |
|
|
32 |
|
// *************** Internal functions ************** |
33 |
|
// * |
34 |
|
|
35 |
|
/// Returns a human readable path of the given chunk. |
36 |
|
String __resolveChunkPath(Chunk* pCk) { |
37 |
|
String sPath; |
38 |
|
for (Chunk* pChunk = pCk; pChunk; pChunk = pChunk->GetParent()) { |
39 |
|
if (pChunk->GetChunkID() == CHUNK_ID_LIST) { |
40 |
|
List* pList = (List*) pChunk; |
41 |
|
sPath = "->'" + pList->GetListTypeString() + "'" + sPath; |
42 |
|
} else { |
43 |
|
sPath = "->'" + pChunk->GetChunkIDString() + "'" + sPath; |
44 |
|
} |
45 |
|
} |
46 |
|
return sPath; |
47 |
|
} |
48 |
|
|
49 |
|
|
50 |
|
|
51 |
// *************** Chunk ************** |
// *************** Chunk ************** |
52 |
// * |
// * |
53 |
|
|
794 |
* @see File::Save() |
* @see File::Save() |
795 |
*/ |
*/ |
796 |
void Chunk::Resize(int iNewSize) { |
void Chunk::Resize(int iNewSize) { |
797 |
if (iNewSize <= 0) throw Exception("Chunk size must be at least one byte"); |
if (iNewSize <= 0) |
798 |
|
throw Exception("There is at least one empty chunk (zero size): " + __resolveChunkPath(this)); |
799 |
if (NewChunkSize == iNewSize) return; |
if (NewChunkSize == iNewSize) return; |
800 |
NewChunkSize = iNewSize; |
NewChunkSize = iNewSize; |
801 |
pFile->LogAsResized(this); |
pFile->LogAsResized(this); |
1363 |
* Use this constructor if you want to create a new RIFF file completely |
* Use this constructor if you want to create a new RIFF file completely |
1364 |
* "from scratch". Note: there must be no empty chunks or empty list |
* "from scratch". Note: there must be no empty chunks or empty list |
1365 |
* chunks when trying to make the new RIFF file persistent with Save()! |
* chunks when trying to make the new RIFF file persistent with Save()! |
1366 |
|
* Note that this constructor will create a RIFX file on |
1367 |
|
* big-endian machines. |
1368 |
* |
* |
1369 |
* @param FileType - four-byte identifier of the RIFF file type |
* @param FileType - four-byte identifier of the RIFF file type |
1370 |
* @see AddSubChunk(), AddSubList() |
* @see AddSubChunk(), AddSubList() |
1381 |
ListType = FileType; |
ListType = FileType; |
1382 |
} |
} |
1383 |
|
|
1384 |
|
|
1385 |
|
/** @brief Create new RIFF file. |
1386 |
|
* |
1387 |
|
* Use this constructor if you want to create a new RIFF file |
1388 |
|
* completely "from scratch" and also want to specify |
1389 |
|
* endianess. Note: there must be no empty chunks or empty list |
1390 |
|
* chunks when trying to make the new RIFF file persistent with |
1391 |
|
* Save()! |
1392 |
|
* |
1393 |
|
* @param FileType - four-byte identifier of the RIFF file type |
1394 |
|
* @param Endian - endianess used in the new file. A value of |
1395 |
|
* endian_little will create a RIFF file, |
1396 |
|
* endian_big a RIFX file, endian_native will |
1397 |
|
* create a RIFF file on little-endian machines |
1398 |
|
* and RIFX on big-endian. |
1399 |
|
* @see AddSubChunk(), AddSubList() |
1400 |
|
*/ |
1401 |
|
File::File(uint32_t FileType, endian_t Endian) : List(this) { |
1402 |
|
#if defined(WIN32) |
1403 |
|
hFileRead = hFileWrite = INVALID_HANDLE_VALUE; |
1404 |
|
#else |
1405 |
|
hFileRead = hFileWrite = 0; |
1406 |
|
#endif |
1407 |
|
Mode = stream_mode_closed; |
1408 |
|
#if WORDS_BIGENDIAN |
1409 |
|
bEndianNative = Endian != endian_little; |
1410 |
|
#else |
1411 |
|
bEndianNative = Endian != endian_big; |
1412 |
|
#endif |
1413 |
|
ulStartPos = RIFF_HEADER_SIZE; |
1414 |
|
ListType = FileType; |
1415 |
|
} |
1416 |
|
|
1417 |
/** @brief Load existing RIFF file. |
/** @brief Load existing RIFF file. |
1418 |
* |
* |
1419 |
* Loads an existing RIFF file with all its chunks. |
* Loads an existing RIFF file with all its chunks. |
1590 |
unsigned long ulPositiveSizeDiff = 0; |
unsigned long ulPositiveSizeDiff = 0; |
1591 |
for (ChunkList::iterator iter = ResizedChunks.begin(), end = ResizedChunks.end(); iter != end; ++iter) { |
for (ChunkList::iterator iter = ResizedChunks.begin(), end = ResizedChunks.end(); iter != end; ++iter) { |
1592 |
if ((*iter)->GetNewSize() == 0) { |
if ((*iter)->GetNewSize() == 0) { |
1593 |
// just to make the exception message a bit more verbose: resolve the chunk's path |
throw Exception("There is at least one empty chunk (zero size): " + __resolveChunkPath(*iter)); |
|
String sChunkPath; |
|
|
for (Chunk* pChunk = *iter; pChunk; pChunk = pChunk->GetParent()) { |
|
|
if (pChunk->GetChunkID() == CHUNK_ID_LIST) { |
|
|
List* pList = (List*) pChunk; |
|
|
sChunkPath = "->'" + pList->GetListTypeString() + "'" + sChunkPath; |
|
|
} else { |
|
|
sChunkPath = "->'" + pChunk->GetChunkIDString() + "'" + sChunkPath; |
|
|
} |
|
|
} |
|
|
throw Exception("There is at least one empty chunk (zero size): " + sChunkPath); |
|
1594 |
} |
} |
1595 |
if ((*iter)->GetNewSize() + 1L > (*iter)->GetSize()) { |
if ((*iter)->GetNewSize() + 1L > (*iter)->GetSize()) { |
1596 |
unsigned long ulDiff = (*iter)->GetNewSize() - (*iter)->GetSize() + 1L; // +1 in case we have to add a pad byte |
unsigned long ulDiff = (*iter)->GetNewSize() - (*iter)->GetSize() + 1L; // +1 in case we have to add a pad byte |