1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#import "XADCABBlockReader.h"
#import "XADException.h"
@implementation XADCABBlockReader
-(id)initWithHandle:(CSHandle *)handle reservedBytes:(int)reserved
{
if((self=[super init]))
{
parent=[handle retain];
extbytes=reserved;
numfolders=0;
}
return self;
}
-(void)dealloc
{
[parent release];
[super dealloc];
}
-(void)addFolderAtOffset:(off_t)startoffs numberOfBlocks:(int)num
{
if(numfolders==sizeof(offsets)/sizeof(offsets[0])) [XADException raiseNotSupportedException];
offsets[numfolders]=startoffs;
numblocks[numfolders]=num;
numfolders++;
}
-(void)scanLengths
{
complen=0;
uncomplen=0;
for(int folder=0;folder<numfolders;folder++)
{
[parent seekToFileOffset:offsets[folder]];
for(int block=0;block<numblocks[folder];block++)
{
/*uint32_t check=*/[parent readUInt32LE];
int compbytes=[parent readUInt16LE];
int uncompbytes=[parent readUInt16LE];
[parent skipBytes:extbytes+compbytes];
complen+=compbytes;
uncomplen+=uncompbytes;
}
}
}
-(CSHandle *)handle { return parent; }
-(off_t)compressedLength { return complen; }
-(off_t)uncompressedLength { return uncomplen; }
-(void)restart
{
[parent seekToFileOffset:offsets[0]];
currentfolder=0;
currentblock=0;
}
-(BOOL)readNextBlockToBuffer:(uint8_t *)buffer compressedLength:(int *)compptr
uncompressedLength:(int *)uncompptr
{
if(currentfolder>=numfolders) [XADException raiseDecrunchException];
uint32_t check=[parent readUInt32LE];
int compbytes=[parent readUInt16LE];
int uncompbytes=[parent readUInt16LE];
[parent skipBytes:extbytes];
if(compbytes>32768+6144) [XADException raiseIllegalDataException];
[parent readBytes:compbytes toBuffer:buffer];
int totalbytes=compbytes;
while(uncompbytes==0)
{
currentblock=0;
currentfolder++;
if(currentfolder>=numfolders) [XADException raiseIllegalDataException];
[parent seekToFileOffset:offsets[currentfolder]];
check=[parent readUInt32LE];
compbytes=[parent readUInt16LE];
uncompbytes=[parent readUInt16LE];
[parent skipBytes:extbytes];
if(compbytes+totalbytes>32768+6144) [XADException raiseIllegalDataException];
[parent readBytes:compbytes toBuffer:&buffer[totalbytes]];
totalbytes+=compbytes;
}
currentblock++;
if(currentblock>=numblocks[currentfolder])
{
// Can this happen? Not sure, supporting it anyway.
currentblock=0;
currentfolder++;
[parent seekToFileOffset:offsets[currentfolder]];
}
if(compptr) *compptr=totalbytes;
if(uncompptr) *uncompptr=uncompbytes;
return currentfolder>=numfolders;
}
@end
|