#include <rifffile.h>
Public Member Functions | |
RIFFFile () | |
Constructor for the RIFFFile class. | |
~RIFFFile () | |
Destructor for the RIFFFile class. | |
FOURCC | Init (CCLexFile *File, BOOL NoHeader=FALSE) |
Initialises the class for reading in a RIFF file. If NoHeader is TRUE then the file has no header and a RIFF chunk is expected to start immediately. | |
BOOL | NextObject (void) |
Initialises the class for reading in a RIFF file. | |
BOOL | GetChunkData (ADDR Block, INT32 Size) |
Gets the all data from a RIFF chunk. | |
BOOL | GetChunkData (ADDR Block, INT32 Size, INT32 Offset) |
Gets a certain amount of the data from a RIFF chunk. ATM it's a bit inefficient. | |
BOOL | AquireChunkData (void) |
Gets the data from a RIFF chunk and puts it into a buffer maintained by the class. Any previous data is lost. | |
BOOL | SkipToListEnd (UINT32 Level) |
Skips to the end of a given level. ListEnd objects are not returned for the lists you skip. | |
BOOL | RepeatCurrent (void) |
Makes the next NextObject return the current object. | |
BOOL | GetListContents (ADDR *Block, INT32 *Size) |
gets the contents from a list. This is in the raw form from the RIFF file | |
BOOL | AquireListContents (INT32 *ListSize) |
Aquires the data of an entire list. Fills in ListSize to be the size of the data. | |
RIFFObjectType | GetObjType (void) |
FOURCC | GetObjChunkType (void) |
INT32 | GetObjSize (void) |
UINT32 | GetObjLevel (void) |
ADDR | GetAquiredData (void) |
INT32 | ProgressLimit (void) |
INT32 | ProgressNow (void) |
Static Public Member Functions | |
static FOURCC | CheckRIFFHeader (ADDR Header, DWORD FileSize) |
Checks to see if the header supplied is that of a valid RIFF form. Useful for HowCompatable functions in filter code. | |
static BOOL | FindChunkWithinListContents (ADDR ListContents, INT32 ListSize, FOURCC Type, INT32 Entry, ADDR *Chunk, INT32 *ChunkSize) |
Finds a chunk within a list. | |
Private Member Functions | |
CC_DECLARE_MEMDUMP (RIFFFile) | |
BOOL | EnsureAquiredSizeIsAtLeast (INT32 Size) |
Ensures that the aquired block is at least a certain size. | |
Private Attributes | |
CCLexFile * | File |
RIFFObjectType | ObjType |
FOURCC | ObjChunkType |
INT32 | ObjSize |
UINT32 | ObjLevel |
INT32 | ObjLocation |
UINT32 | CurrentLevel |
INT32 | Location |
INT32 | Size |
BOOL | GotData |
INT32 | AlignedObjectSize |
List | Levels |
BOOL | RepeatObject |
BOOL | Error |
BYTE * | AquiredData |
INT32 | AquiredDataSize |
Definition at line 159 of file rifffile.h.
|
Constructor for the RIFFFile class.
Definition at line 133 of file rifffile.cpp.
|
|
Destructor for the RIFFFile class.
Definition at line 154 of file rifffile.cpp. 00155 { 00156 // get rid of all the list entries in the file 00157 Levels.DeleteAll(); 00158 00159 // Get rid of the aquired object, if there is one 00160 if(AquiredData != 0) 00161 CCFree(AquiredData); 00162 }
|
|
Gets the data from a RIFF chunk and puts it into a buffer maintained by the class. Any previous data is lost.
Definition at line 653 of file rifffile.cpp. 00654 { 00655 // check to see if the current object is a chunk 00656 ERROR2IF(ObjType != RIFFOBJECTTYPE_CHUNK, FALSE, "Tried an AquiredChunkData on a non-chunk RIFF object\n"); 00657 00658 // ensure that AquiredData points at enough space for this to be hoopy 00659 if(!EnsureAquiredSizeIsAtLeast(ObjSize)) 00660 return FALSE; 00661 00662 // there is at enough space in AquiredData to store the current object 00663 // use GetChunkData on it 00664 00665 return GetChunkData(AquiredData, AquiredDataSize); 00666 }
|
|
Aquires the data of an entire list. Fills in ListSize to be the size of the data.
Definition at line 683 of file rifffile.cpp. 00684 { 00685 ERROR2IF(ObjType != RIFFOBJECTTYPE_LISTSTART, FALSE, "Tried an GetListContents on a non-list start RIFF object\n"); 00686 00687 // OK, first thing we need to do is to get the list's header... where is it? 00688 INT32 StartLocation = Location - sizeof(RIFFck) - sizeof(RIFFFile_List); 00689 00690 // seek there 00691 if(File->seek(StartLocation).bad()) 00692 { 00693 RIFFFILE_RETURNERR; 00694 } 00695 00696 // OK, get the chunk header (not the list header which gives it's type 00697 RIFFck ChunkHeader; 00698 00699 if(File->read(&ChunkHeader, sizeof(ChunkHeader)).bad()) 00700 { 00701 RIFFFILE_RETURNERR; 00702 } 00703 00704 // right then, we now know how much data we need to extract from the file... 00705 INT32 ContentsSize = RIFFDATA_DWORD(ChunkHeader.ckSize) + sizeof(RIFFck); 00706 00707 // now we need a block of data to get it into 00708 if(!EnsureAquiredSizeIsAtLeast(ContentsSize)) 00709 return FALSE; 00710 00711 // and getting it would be a cunning plan! seek to the beginning 00712 if(File->seek(StartLocation).bad()) 00713 { 00714 RIFFFILE_RETURNERR; 00715 } 00716 00717 // grab the data 00718 if(File->read(AquiredData, ContentsSize).bad()) 00719 { 00720 RIFFFILE_RETURNERR; 00721 } 00722 00723 // seek back to the location we were at the beginning 00724 if(File->seek(Location).bad()) 00725 { 00726 RIFFFILE_RETURNERR; 00727 } 00728 00729 // and set up the return values 00730 *ListSize = ContentsSize; 00731 00732 return TRUE; 00733 }
|
|
|
|
Checks to see if the header supplied is that of a valid RIFF form. Useful for HowCompatable functions in filter code.
Definition at line 235 of file rifffile.cpp. 00236 { 00237 PORTNOTE("byteorder", "TODO: Check byte ordering") 00238 RIFFFile_Header *Hdr = (RIFFFile_Header *)Header; 00239 00240 if(RIFFDATA_FOURCC(Hdr->CK.ckID) != RIFFTYPE_RIFF) 00241 return 0; // file doesn't start "RIFF" 00242 00243 if(RIFFDATA_DWORD(Hdr->CK.ckSize) > (Size - sizeof(RIFFFile_Header)) && 00244 RIFFDATA_DWORD(Hdr->CK.ckSize) < (Size - sizeof(RIFFFile_Header))) 00245 return 0; // Size doesn't match that in header. Be a bit relaxed about exact lengths 00246 00247 return Hdr->FormType; 00248 }
|
|
Ensures that the aquired block is at least a certain size.
Definition at line 619 of file rifffile.cpp. 00620 { 00621 if(AquiredData == 0 || AquiredDataSize < Size) 00622 { 00623 if(AquiredData != 0) 00624 { 00625 CCFree(AquiredData); 00626 AquiredData = 0; 00627 } 00628 00629 if((AquiredData = (BYTE *)CCMalloc(Size)) == 0) 00630 RIFFFILE_RETURNERR; 00631 00632 AquiredDataSize = Size; 00633 } 00634 00635 return TRUE; 00636 }
|
|
Finds a chunk within a list.
Definition at line 849 of file rifffile.cpp. 00851 { 00852 RIFFck *Header; 00853 INT32 OffsetWithin = sizeof(RIFFck) + sizeof(RIFFFile_List); 00854 00855 while(OffsetWithin < ListSize) 00856 { 00857 Header = (RIFFck *)(ListContents + OffsetWithin); 00858 00859 INT32 Size = RIFFDATA_DWORD(Header->ckSize); 00860 if(RIFFDATA_FOURCC(Header->ckID) == Type) 00861 { 00862 if(Entry <= 0) 00863 { 00864 // return this one... 00865 if(Chunk != 0) 00866 (*Chunk) = ListContents + OffsetWithin + sizeof(RIFFck); 00867 00868 if(ChunkSize != 0) 00869 (*ChunkSize) = Size; 00870 00871 return TRUE; 00872 } 00873 else 00874 { 00875 Entry--; 00876 } 00877 } 00878 OffsetWithin += Size + sizeof(RIFFck); 00879 } 00880 00881 return FALSE; 00882 }
|
|
Definition at line 187 of file rifffile.h. 00187 {return AquiredData;}
|
|
Gets a certain amount of the data from a RIFF chunk. ATM it's a bit inefficient.
Definition at line 505 of file rifffile.cpp. 00506 { 00507 // first of all, check to see if the caller has been a little bit silly 00508 if(ObjType != RIFFOBJECTTYPE_CHUNK) 00509 { 00510 Error = TRUE; // only chunks have getable data 00511 ERROR2(FALSE, "RIFFFile::GetChunkData called for a non-chunk object\n"); 00512 } 00513 00514 // check offset is OK 00515 if(Offset >= ObjSize) 00516 Offset = ObjSize - 1; 00517 00518 // check that we'll be grabbing a nice amount of data 00519 if((Offset + BSize) > ObjSize) 00520 BSize = ObjSize - Offset; 00521 00522 // don't do anything if there's no data to get 00523 if(BSize <= 0) 00524 return TRUE; 00525 00526 // where in the file do we wish to get data from? 00527 INT32 TargetLocation = ObjLocation + Offset; 00528 00529 // seek to the data we want, but only if it's necessary 00530 if(TargetLocation != Location) 00531 { 00532 if(File->seek(TargetLocation).bad()) 00533 RIFFFILE_RETURNERR; 00534 00535 Location = TargetLocation; 00536 } 00537 00538 // and get that data! 00539 if(File->read(Block, BSize).bad()) 00540 { 00541 TRACEUSER( "Ben", _T("RIFFFile: file error when reading chunk data\n")); 00542 RIFFFILE_RETURNERR; 00543 } 00544 00545 // update locations 00546 Location += BSize; 00547 00548 // and set an essential flag! 00549 GotData = TRUE; 00550 00551 return TRUE; 00552 }
|
|
Gets the all data from a RIFF chunk.
Definition at line 437 of file rifffile.cpp. 00438 { 00439 // first of all, check to see if the caller has been a little bit silly 00440 if(ObjType != RIFFOBJECTTYPE_CHUNK) 00441 { 00442 Error = TRUE; // only chunks have getable data 00443 ERROR2(FALSE, "RIFFFile::GetChunkData called for a non-chunk object\n"); 00444 } 00445 00446 if(BSize < ObjSize) 00447 { 00448 Error = TRUE; // wrong size... 00449 ERROR2(FALSE, "RIFFFile::GetChunkData called with a block which is just *too* small\n"); 00450 } 00451 00452 // has the data already been got for this object? 00453 if(GotData) 00454 { 00455 // yep, go back and get it again 00456 TRACEUSER( "Ben", _T("Chunk data asked for more than once\n")); 00457 if(File->seek(ObjLocation).bad()) 00458 RIFFFILE_RETURNERR; 00459 00460 Location = ObjLocation; 00461 } 00462 00463 // and get that data! 00464 if(File->read(Block, ObjSize).bad()) 00465 { 00466 TRACEUSER( "Ben", _T("RIFFFile: file error when reading chunk data\n")); 00467 RIFFFILE_RETURNERR; 00468 } 00469 00470 // ensure alignment is maintained within the file 00471 if(ObjSize != AlignedObjectSize) 00472 { 00473 // read a byte to align this to the correct position 00474 BYTE junk; 00475 00476 if(File->read(&junk, sizeof(junk)).bad()) 00477 RIFFFILE_RETURNERR; 00478 } 00479 00480 // update locations 00481 Location += AlignedObjectSize; 00482 00483 // and set an essential flag! 00484 GotData = TRUE; 00485 00486 return TRUE; 00487 }
|
|
gets the contents from a list. This is in the raw form from the RIFF file
Definition at line 775 of file rifffile.cpp. 00776 { 00777 ERROR2IF(ObjType != RIFFOBJECTTYPE_LISTSTART, FALSE, "Tried an GetListContents on a non-list start RIFF object\n"); 00778 00779 // OK, first thing we need to do is to get the list's header... where is it? 00780 INT32 StartLocation = Location - sizeof(RIFFck) - sizeof(RIFFFile_List); 00781 00782 // seek there 00783 if(File->seek(StartLocation).bad()) 00784 { 00785 RIFFFILE_RETURNERR; 00786 } 00787 00788 // OK, get the chunk header (not the list header which gives it's type 00789 RIFFck ChunkHeader; 00790 00791 if(File->read(&ChunkHeader, sizeof(ChunkHeader)).bad()) 00792 { 00793 RIFFFILE_RETURNERR; 00794 } 00795 00796 // right then, we now know how much data we need to extract from the file... 00797 INT32 ContentsSize = RIFFDATA_DWORD(ChunkHeader.ckSize) + sizeof(RIFFck); 00798 00799 // now we need a block of data to get it into 00800 ADDR Contents = (ADDR)CCMalloc(ContentsSize); 00801 00802 if(Contents == 0) 00803 return FALSE; 00804 00805 // and getting it would be a cunning plan! seek to the beginning 00806 if(File->seek(StartLocation).bad()) 00807 { 00808 RIFFFILE_RETURNERR; 00809 } 00810 00811 // grab the data 00812 if(File->read(Contents, ContentsSize).bad()) 00813 { 00814 RIFFFILE_RETURNERR; 00815 } 00816 00817 // seek back to the location we were at the beginning 00818 if(File->seek(Location).bad()) 00819 { 00820 RIFFFILE_RETURNERR; 00821 } 00822 00823 // and set up the return values 00824 *Block = Contents; 00825 *Size = ContentsSize; 00826 00827 return TRUE; 00828 }
|
|
Definition at line 184 of file rifffile.h. 00184 {return ObjChunkType;}
|
|
Definition at line 186 of file rifffile.h. 00186 {return ObjLevel;}
|
|
Definition at line 185 of file rifffile.h. 00185 {return ObjSize;}
|
|
Definition at line 183 of file rifffile.h. 00183 {return ObjType;}
|
|
Initialises the class for reading in a RIFF file. If NoHeader is TRUE then the file has no header and a RIFF chunk is expected to start immediately.
Definition at line 181 of file rifffile.cpp. 00182 { 00183 // store Mr. NiceCCFile 00184 File = pFile; 00185 00186 FOURCC FileType = 0; 00187 00188 // if this file has a header, check it and get the type 00189 if(!NoHeader) 00190 { 00191 // read in the header of the file 00192 RIFFFile_Header Header; 00193 00194 if(File->read(&Header, sizeof(Header)).bad()) 00195 return FALSE; 00196 00197 00198 // and check it for being a valid form 00199 FileType = CheckRIFFHeader((ADDR)&Header, File->Size()); 00200 00201 // and was it? 00202 if(FileType == 0) 00203 return 0; // not a RIFF form 00204 } 00205 00206 // OK, set up lots of nice variables for the funky business of RIFF reading 00207 ObjType = RIFFOBJECTTYPE_NONE; 00208 RepeatObject = FALSE; 00209 Error = FALSE; 00210 Location = NoHeader?0:sizeof(RIFFFile_Header); 00211 Size = File->Size(); 00212 GotData = FALSE; 00213 CurrentLevel = 0; 00214 AquiredData = 0; 00215 AlignedObjectSize = 0; 00216 00217 return FileType; 00218 }
|
|
Initialises the class for reading in a RIFF file.
Definition at line 264 of file rifffile.cpp. 00265 { 00266 if(Error) 00267 return FALSE; 00268 00269 // do we need to return the current object again? 00270 if(RepeatObject) 00271 { 00272 RepeatObject = FALSE; 00273 return TRUE; // all data nicely set up already 00274 } 00275 00276 // skip over any data it it hasn't already been got 00277 if(ObjType == RIFFOBJECTTYPE_CHUNK && (GotData == FALSE || Location != (ObjLocation + AlignedObjectSize))) 00278 { 00279 if(File->seek(ObjLocation + AlignedObjectSize).bad()) { 00280 TRACEUSER( "Ben", _T("RIFFFile: Error on seek when jumping object data\n")); 00281 RIFFFILE_RETURNERR; 00282 } 00283 00284 Location = ObjLocation + AlignedObjectSize; 00285 00286 // as we may come this way again... 00287 GotData = TRUE; 00288 } 00289 00290 // have we gone past the end of the file? 00291 if(Location >= Size) 00292 //if (File->eof()) 00293 { 00294 // Yes. Firstly, ensure that all the lists got the end list thingy - is the list empty? 00295 if(!Levels.IsEmpty()) 00296 { 00297 TRACEUSER( "Ben", _T("RIFFFile: Ending... terminating list\n")); 00298 RIFFFileLevel *Level = (RIFFFileLevel *)Levels.GetTail(); 00299 00300 ERROR3IF(Level == NULL, "List class returned a null tail for a non empty list! Help!"); 00301 00302 // set up a nice list end object 00303 ObjType = RIFFOBJECTTYPE_LISTEND; 00304 ObjChunkType = Level->Type; 00305 ObjLevel = CurrentLevel; 00306 ObjLocation = Location; 00307 GotData = TRUE; 00308 00309 // level down one 00310 CurrentLevel--; 00311 00312 // get rid of the last level on the list 00313 delete Levels.RemoveTail(); 00314 00315 return TRUE; 00316 } 00317 00318 // And if they all have, say that the file ended 00319 ObjType = RIFFOBJECTTYPE_FILEEND; 00320 ObjChunkType = 0; 00321 ObjSize = 0; 00322 ObjLevel = 0; 00323 ObjLocation = Location; 00324 GotData = TRUE; 00325 TRACEUSER( "Ben", _T("returning file end\n")); 00326 return TRUE; 00327 } 00328 00329 // check to see if the current list has ended 00330 if(!Levels.IsEmpty()) 00331 { 00332 RIFFFileLevel *Level = (RIFFFileLevel *)Levels.GetTail(); 00333 00334 ERROR3IF(Level == NULL, "List class returned a null tail for a non empty list! Help!"); 00335 00336 if(Location >= Level->End) 00337 { 00338 // RIFF list has ended 00339 ObjType = RIFFOBJECTTYPE_LISTEND; 00340 ObjChunkType = Level->Type; 00341 ObjLevel = CurrentLevel; 00342 ObjSize = 0; 00343 ObjLocation = Location; 00344 GotData = TRUE; 00345 00346 // down a level 00347 CurrentLevel--; 00348 00349 // delete the last entry in the list 00350 delete Levels.RemoveTail(); 00351 00352 return TRUE; 00353 } 00354 } 00355 00356 // right then, let's see what the next object in the file is. 00357 RIFFck ChunkHeader; 00358 00359 if(File->read(&ChunkHeader, sizeof(ChunkHeader)).bad()) 00360 { 00361 TRACEUSER( "Ben", _T("RIFFFile: file error on reading chunk header\n")); 00362 RIFFFILE_RETURNERR; 00363 } 00364 00365 Location += sizeof(ChunkHeader); 00366 00367 // is it a list chunk? 00368 if(RIFFDATA_FOURCC(ChunkHeader.ckID) == RIFFTYPE_LIST) 00369 { 00370 // yep... process it 00371 RIFFFile_List ListHdr; 00372 00373 // read in a list header 00374 if(File->read(&ListHdr, sizeof(ListHdr)).bad()) 00375 { 00376 TRACEUSER( "Ben", _T("RIFFFile: file error on reading list id\n")); 00377 RIFFFILE_RETURNERR; 00378 } 00379 00380 Location += sizeof(ListHdr); 00381 00382 // make a new entry in the list 00383 RIFFFileLevel *NewLevel; 00384 00385 if((NewLevel = new RIFFFileLevel) == 0) 00386 RIFFFILE_RETURNERR; 00387 00388 NewLevel->Start = Location; 00389 NewLevel->End = Location + ALIGNSIZE(RIFFDATA_DWORD(ChunkHeader.ckSize)) - sizeof(ListHdr); 00390 NewLevel->Type = RIFFDATA_FOURCC(ListHdr.ListType); 00391 00392 // and add it to the list 00393 Levels.AddTail(NewLevel); 00394 00395 // up a level 00396 CurrentLevel++; 00397 00398 // return a nice list start object 00399 ObjType = RIFFOBJECTTYPE_LISTSTART; 00400 ObjChunkType = RIFFDATA_FOURCC(ListHdr.ListType); 00401 ObjSize = 0; 00402 ObjLevel = CurrentLevel; 00403 ObjLocation = Location; 00404 GotData = TRUE; 00405 return TRUE; 00406 } 00407 00408 // and after all that excitement, if it was just a normal, boring chunk, return stuff about that 00409 ObjType = RIFFOBJECTTYPE_CHUNK; 00410 ObjChunkType = RIFFDATA_FOURCC(ChunkHeader.ckID); 00411 ObjSize = RIFFDATA_DWORD(ChunkHeader.ckSize); 00412 ObjLevel = CurrentLevel; 00413 ObjLocation = Location; 00414 00415 // set up some useful data 00416 GotData = FALSE; 00417 AlignedObjectSize = ALIGNSIZE(ObjSize); 00418 00419 // and that's all folks 00420 return TRUE; 00421 }
|
|
Definition at line 189 of file rifffile.h. 00189 {return Size;} // the last value progress will return
|
|
Definition at line 190 of file rifffile.h. 00190 {return Location;} // the current position for the progress bar
|
|
Makes the next NextObject return the current object.
Definition at line 749 of file rifffile.cpp. 00750 { 00751 if(RepeatObject == TRUE) 00752 { 00753 TRACEUSER( "Ben", _T("RepeatObject already set for this object...\n")); 00754 } 00755 00756 RepeatObject = TRUE; 00757 00758 return TRUE; 00759 }
|
|
Skips to the end of a given level. ListEnd objects are not returned for the lists you skip.
Definition at line 569 of file rifffile.cpp. 00570 { 00571 RIFFFileLevel *Level; 00572 RIFFFileLevel *Next; 00573 00574 TRACEUSER( "Ben", _T("SkipToListEnd called to level %d\n"), LevelNumber); 00575 Level = (RIFFFileLevel *)Levels.FindItem(LevelNumber - 1); 00576 // - 1 because level 0 doesn't have an entry as 00577 // it's the root level of the file 00578 00579 ERROR2IF(Level == 0, FALSE, "Couldn't find given level to jump to in list"); 00580 00581 // seek to the end of the level 00582 if(File->seek(Level->End).bad()) 00583 { 00584 TRACEUSER( "Ben", _T("RIFFFile: file error when seeking to end of level\n")); 00585 RIFFFILE_RETURNERR; 00586 } 00587 00588 // update the location 00589 Location = Level->End; 00590 00591 // update the level we're at 00592 CurrentLevel = LevelNumber - 1; 00593 00594 // remove the last few entries from the list, including this one 00595 while(Level != 0) 00596 { 00597 Next = (RIFFFileLevel *)Levels.GetNext(Level); 00598 delete Levels.RemoveItem(Level); 00599 Level = Next; 00600 } 00601 00602 return TRUE; 00603 }
|
|
Definition at line 209 of file rifffile.h. |
|
Definition at line 219 of file rifffile.h. |
|
Definition at line 220 of file rifffile.h. |
|
Definition at line 201 of file rifffile.h. |
|
Definition at line 217 of file rifffile.h. |
|
Definition at line 193 of file rifffile.h. |
|
Definition at line 206 of file rifffile.h. |
|
Definition at line 212 of file rifffile.h. |
|
Definition at line 203 of file rifffile.h. |
|
Definition at line 196 of file rifffile.h. |
|
Definition at line 198 of file rifffile.h. |
|
Definition at line 199 of file rifffile.h. |
|
Definition at line 197 of file rifffile.h. |
|
Definition at line 195 of file rifffile.h. |
|
Definition at line 216 of file rifffile.h. |
|
Definition at line 204 of file rifffile.h. |