71 |
fread(&ChunkID, 4, 1, hFile); |
fread(&ChunkID, 4, 1, hFile); |
72 |
fread(&ChunkSize, 4, 1, hFile); |
fread(&ChunkSize, 4, 1, hFile); |
73 |
#endif // POSIX |
#endif // POSIX |
|
#if DEBUG |
|
|
std::cout << "ckID=" << convertToString(ChunkID) << " "; |
|
|
std::cout << "ckSize=" << ChunkSize << std::endl; |
|
|
#endif // DEBUG |
|
74 |
#if WORDS_BIGENDIAN |
#if WORDS_BIGENDIAN |
75 |
if (ChunkID == CHUNK_ID_RIFF) { |
if (ChunkID == CHUNK_ID_RIFF) { |
76 |
bEndianNative = false; |
bEndianNative = false; |
82 |
} |
} |
83 |
#endif // WORDS_BIGENDIAN |
#endif // WORDS_BIGENDIAN |
84 |
if (!bEndianNative) { |
if (!bEndianNative) { |
85 |
swapBytes_32(&ChunkID); |
//swapBytes_32(&ChunkID); |
86 |
swapBytes_32(&ChunkSize); |
swapBytes_32(&ChunkSize); |
87 |
} |
} |
88 |
|
#if DEBUG |
89 |
|
std::cout << "ckID=" << convertToString(ChunkID) << " "; |
90 |
|
std::cout << "ckSize=" << ChunkSize << " "; |
91 |
|
std::cout << "bEndianNative=" << bEndianNative << std::endl; |
92 |
|
#endif // DEBUG |
93 |
} |
} |
94 |
} |
} |
95 |
|
|
96 |
|
/** |
97 |
|
* Returns the String representation of the chunk's ID (e.g. "RIFF", |
98 |
|
* "LIST"). |
99 |
|
*/ |
100 |
String Chunk::GetChunkIDString() { |
String Chunk::GetChunkIDString() { |
101 |
return convertToString(ChunkID); |
return convertToString(ChunkID); |
102 |
} |
} |
103 |
|
|
104 |
|
/** |
105 |
|
* Sets the position within the chunk body, thus within the data portion |
106 |
|
* of the chunk (in bytes). |
107 |
|
* |
108 |
|
* @param Where - position offset (in bytes) |
109 |
|
* @param Whence - optional: defines to what <i>\a Where</i> relates to, |
110 |
|
* if omitted \a Where relates to beginning of the chunk |
111 |
|
* data |
112 |
|
*/ |
113 |
unsigned long Chunk::SetPos(unsigned long Where, stream_whence_t Whence) { |
unsigned long Chunk::SetPos(unsigned long Where, stream_whence_t Whence) { |
114 |
#if DEBUG |
#if DEBUG |
115 |
std::cout << "Chunk::SetPos(ulong)" << std::endl; |
std::cout << "Chunk::SetPos(ulong)" << std::endl; |
132 |
return ulPos; |
return ulPos; |
133 |
} |
} |
134 |
|
|
135 |
|
/** |
136 |
|
* Returns the number of bytes left to read in the chunk body. |
137 |
|
* When reading data from the chunk using the Read*() Methods, the |
138 |
|
* position within the chunk data (that is the chunk body) will be |
139 |
|
* incremented by the number of read bytes and RemainingBytes() returns |
140 |
|
* how much data is left to read from the current position to the end |
141 |
|
* of the chunk data. |
142 |
|
* |
143 |
|
* @returns number of bytes left to read |
144 |
|
*/ |
145 |
unsigned long Chunk::RemainingBytes() { |
unsigned long Chunk::RemainingBytes() { |
146 |
#if DEBUG |
#if DEBUG |
147 |
std::cout << "Chunk::Remainingbytes()=" << ChunkSize - ulPos << std::endl; |
std::cout << "Chunk::Remainingbytes()=" << ChunkSize - ulPos << std::endl; |
149 |
return ChunkSize - ulPos; |
return ChunkSize - ulPos; |
150 |
} |
} |
151 |
|
|
152 |
|
/** |
153 |
|
* Returns the current state of the chunk object. |
154 |
|
* Following values are possible: |
155 |
|
* - RIFF::stream_ready : |
156 |
|
* chunk data can be read (this is the usual case) |
157 |
|
* - RIFF::stream_closed : |
158 |
|
* the data stream was closed somehow, no more reading possible |
159 |
|
* - RIFF::stream_end_reached : |
160 |
|
* alreaady reached the end of the chunk data, no more reading |
161 |
|
* possible without SetPos() |
162 |
|
*/ |
163 |
stream_state_t Chunk::GetState() { |
stream_state_t Chunk::GetState() { |
164 |
#if DEBUG |
#if DEBUG |
165 |
std::cout << "Chunk::GetState()" << std::endl; |
std::cout << "Chunk::GetState()" << std::endl; |
192 |
#if DEBUG |
#if DEBUG |
193 |
std::cout << "Chunk::Read(void*,ulong,ulong)" << std::endl; |
std::cout << "Chunk::Read(void*,ulong,ulong)" << std::endl; |
194 |
#endif // DEBUG |
#endif // DEBUG |
195 |
if (ChunkSize - ulPos <= 0) return 0; |
if (ulPos >= ChunkSize) return 0; |
196 |
if (ulPos + WordCount * WordSize >= ChunkSize) WordCount = (ChunkSize - ulPos) / WordSize; |
if (ulPos + WordCount * WordSize >= ChunkSize) WordCount = (ChunkSize - ulPos) / WordSize; |
197 |
#if POSIX |
#if POSIX |
198 |
if (lseek(hFile, ulStartPos + ulPos, SEEK_SET) < 0) return 0; |
if (lseek(hFile, ulStartPos + ulPos, SEEK_SET) < 0) return 0; |
515 |
if (pSubChunksMap) delete pSubChunksMap; |
if (pSubChunksMap) delete pSubChunksMap; |
516 |
} |
} |
517 |
|
|
518 |
|
/** |
519 |
|
* Returns subchunk with chunk ID <i>\a ChunkID</i> within this chunk |
520 |
|
* list. Use this method if you expect only one subchunk of that type in |
521 |
|
* the list. It there are more than one, it's undetermined which one of |
522 |
|
* them will be returned! If there are no subchunks with that desired |
523 |
|
* chunk ID, NULL will be returned. |
524 |
|
* |
525 |
|
* @param ChunkID - chunk ID of the sought subchunk |
526 |
|
* @returns pointer to the subchunk or NULL if there is none of |
527 |
|
* that ID |
528 |
|
*/ |
529 |
Chunk* List::GetSubChunk(uint32_t ChunkID) { |
Chunk* List::GetSubChunk(uint32_t ChunkID) { |
530 |
#if DEBUG |
#if DEBUG |
531 |
std::cout << "List::GetSubChunk(uint32_t)" << std::endl; |
std::cout << "List::GetSubChunk(uint32_t)" << std::endl; |
534 |
return (*pSubChunksMap)[ChunkID]; |
return (*pSubChunksMap)[ChunkID]; |
535 |
} |
} |
536 |
|
|
537 |
|
/** |
538 |
|
* Returns sublist chunk with list type <i>\a ListType</i> within this |
539 |
|
* chunk list. Use this method if you expect only one sublist chunk of |
540 |
|
* that type in the list. It there are more than one, it's undetermined |
541 |
|
* which one of them will be returned! If there are no sublists with |
542 |
|
* that desired list type, NULL will be returned. |
543 |
|
* |
544 |
|
* @param ListType - list type of the sought sublist |
545 |
|
* @returns pointer to the sublist or NULL if there is none of |
546 |
|
* that type |
547 |
|
*/ |
548 |
List* List::GetSubList(uint32_t ListType) { |
List* List::GetSubList(uint32_t ListType) { |
549 |
#if DEBUG |
#if DEBUG |
550 |
std::cout << "List::GetSubList(uint32_t)" << std::endl; |
std::cout << "List::GetSubList(uint32_t)" << std::endl; |
562 |
return NULL; |
return NULL; |
563 |
} |
} |
564 |
|
|
565 |
|
/** |
566 |
|
* Returns the first subchunk within the list. You have to call this |
567 |
|
* method before you can call GetNextSubChunk(). Recall it when you want |
568 |
|
* to start from the beginning of the list again. |
569 |
|
* |
570 |
|
* @returns pointer to the first subchunk within the list, NULL |
571 |
|
* otherwise |
572 |
|
*/ |
573 |
Chunk* List::GetFirstSubChunk() { |
Chunk* List::GetFirstSubChunk() { |
574 |
#if DEBUG |
#if DEBUG |
575 |
std::cout << "List::GetFirstSubChunk()" << std::endl; |
std::cout << "List::GetFirstSubChunk()" << std::endl; |
579 |
return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL; |
return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL; |
580 |
} |
} |
581 |
|
|
582 |
|
/** |
583 |
|
* Returns the next subchunk within the list. You have to call |
584 |
|
* GetFirstSubChunk() before you can use this method! |
585 |
|
* |
586 |
|
* @returns pointer to the next subchunk within the list or NULL if |
587 |
|
* end of list is reached |
588 |
|
*/ |
589 |
Chunk* List::GetNextSubChunk() { |
Chunk* List::GetNextSubChunk() { |
590 |
#if DEBUG |
#if DEBUG |
591 |
std::cout << "List::GetNextSubChunk()" << std::endl; |
std::cout << "List::GetNextSubChunk()" << std::endl; |
595 |
return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL; |
return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL; |
596 |
} |
} |
597 |
|
|
598 |
|
/** |
599 |
|
* Returns the first sublist within the list (that is a subchunk with |
600 |
|
* chunk ID "LIST"). You have to call this method before you can call |
601 |
|
* GetNextSubList(). Recall it when you want to start from the beginning |
602 |
|
* of the list again. |
603 |
|
* |
604 |
|
* @returns pointer to the first sublist within the list, NULL |
605 |
|
* otherwise |
606 |
|
*/ |
607 |
List* List::GetFirstSubList() { |
List* List::GetFirstSubList() { |
608 |
#if DEBUG |
#if DEBUG |
609 |
std::cout << "List::GetFirstSubList()" << std::endl; |
std::cout << "List::GetFirstSubList()" << std::endl; |
618 |
return NULL; |
return NULL; |
619 |
} |
} |
620 |
|
|
621 |
|
/** |
622 |
|
* Returns the next sublist (that is a subchunk with chunk ID "LIST") |
623 |
|
* within the list. You have to call GetFirstSubList() before you can |
624 |
|
* use this method! |
625 |
|
* |
626 |
|
* @returns pointer to the next sublist within the list, NULL if |
627 |
|
* end of list is reached |
628 |
|
*/ |
629 |
List* List::GetNextSubList() { |
List* List::GetNextSubList() { |
630 |
#if DEBUG |
#if DEBUG |
631 |
std::cout << "List::GetNextSubList()" << std::endl; |
std::cout << "List::GetNextSubList()" << std::endl; |
641 |
return NULL; |
return NULL; |
642 |
} |
} |
643 |
|
|
644 |
|
/** |
645 |
|
* Returns number subchunks within the list. |
646 |
|
*/ |
647 |
unsigned int List::CountSubChunks() { |
unsigned int List::CountSubChunks() { |
648 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
649 |
return pSubChunks->size(); |
return pSubChunks->size(); |
650 |
} |
} |
651 |
|
|
652 |
|
/** |
653 |
|
* Returns number of subchunks within the list with chunk ID |
654 |
|
* <i>\a ChunkId</i>. |
655 |
|
*/ |
656 |
unsigned int List::CountSubChunks(uint32_t ChunkID) { |
unsigned int List::CountSubChunks(uint32_t ChunkID) { |
657 |
unsigned int result = 0; |
unsigned int result = 0; |
658 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
667 |
return result; |
return result; |
668 |
} |
} |
669 |
|
|
670 |
|
/** |
671 |
|
* Returns number of sublists within the list. |
672 |
|
*/ |
673 |
unsigned int List::CountSubLists() { |
unsigned int List::CountSubLists() { |
674 |
return CountSubChunks(CHUNK_ID_LIST); |
return CountSubChunks(CHUNK_ID_LIST); |
675 |
} |
} |
676 |
|
|
677 |
|
/** |
678 |
|
* Returns number of sublists within the list with list type |
679 |
|
* <i>\a ListType</i> |
680 |
|
*/ |
681 |
unsigned int List::CountSubLists(uint32_t ListType) { |
unsigned int List::CountSubLists(uint32_t ListType) { |
682 |
unsigned int result = 0; |
unsigned int result = 0; |
683 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
710 |
std::cout << "listType=" << convertToString(ListType) << std::endl; |
std::cout << "listType=" << convertToString(ListType) << std::endl; |
711 |
#endif // DEBUG |
#endif // DEBUG |
712 |
if (!bEndianNative) { |
if (!bEndianNative) { |
713 |
swapBytes_32(&ListType); |
//swapBytes_32(&ListType); |
714 |
} |
} |
715 |
} |
} |
716 |
|
|
723 |
pSubChunksMap = new ChunkMap(); |
pSubChunksMap = new ChunkMap(); |
724 |
while (RemainingBytes() >= CHUNK_HEADER_SIZE) { |
while (RemainingBytes() >= CHUNK_HEADER_SIZE) { |
725 |
Chunk* ck; |
Chunk* ck; |
726 |
uint32_t ckid = ReadUint32(); |
uint32_t ckid; |
727 |
|
Read(&ckid, 4, 1); |
728 |
#if DEBUG |
#if DEBUG |
729 |
std::cout << " ckid=" << convertToString(ckid) << std::endl; |
std::cout << " ckid=" << convertToString(ckid) << std::endl; |
730 |
#endif // DEBUG |
#endif // DEBUG |
743 |
} |
} |
744 |
} |
} |
745 |
|
|
746 |
|
/** |
747 |
|
* Returns string representation of the lists's id |
748 |
|
*/ |
749 |
String List::GetListTypeString() { |
String List::GetListTypeString() { |
750 |
return convertToString(ListType); |
return convertToString(ListType); |
751 |
} |
} |