mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-28 19:13:49 +02:00
211 lines
4.9 KiB
Objective-C
211 lines
4.9 KiB
Objective-C
/*
|
|
* XADLZXHandle.m
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#import "XADLZXHandle.h"
|
|
#import "XADException.h"
|
|
|
|
@implementation XADLZXHandle
|
|
|
|
-(id)initWithHandle:(CSHandle *)handle length:(off_t)length
|
|
{
|
|
if((self=[super initWithInputBufferForHandle:[[[XADLZXSwapHandle alloc] initWithHandle:handle] autorelease]
|
|
length:length windowSize:65536]))
|
|
{
|
|
maincode=offsetcode=nil;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)dealloc
|
|
{
|
|
[maincode release];
|
|
[offsetcode release];
|
|
[super dealloc];
|
|
}
|
|
|
|
-(void)resetLZSSHandle
|
|
{
|
|
lastoffs=1;
|
|
blockend=0;
|
|
memset(mainlengths,0,sizeof(mainlengths));
|
|
}
|
|
|
|
-(int)nextLiteralOrOffset:(int *)offset andLength:(int *)length atPosition:(off_t)pos
|
|
{
|
|
static const unsigned char AdditionalBitsTable[32]=
|
|
{
|
|
0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
|
|
};
|
|
|
|
static const unsigned int BaseTable[32]=
|
|
{
|
|
0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
|
|
1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152
|
|
};
|
|
|
|
if(pos>=blockend) [self readBlockHeaderAtPosition:pos];
|
|
|
|
int symbol=CSInputNextSymbolUsingCodeLE(input,maincode);
|
|
if(symbol<256) return symbol;
|
|
|
|
int offsclass=symbol&31;
|
|
int offs=BaseTable[offsclass];
|
|
int offsbits=AdditionalBitsTable[offsclass];
|
|
|
|
if(offs==0)
|
|
{
|
|
offs=lastoffs;
|
|
}
|
|
else if(blocktype==3 && offsbits>=3)
|
|
{
|
|
offs+=CSInputNextBitStringLE(input,offsbits-3)<<3;
|
|
offs+=CSInputNextSymbolUsingCodeLE(input,offsetcode);
|
|
}
|
|
else
|
|
{
|
|
offs+=CSInputNextBitStringLE(input,offsbits);
|
|
}
|
|
|
|
int lenclass=((symbol-256)>>5)&15;
|
|
int len=BaseTable[lenclass]+3;
|
|
int lenbits=AdditionalBitsTable[lenclass];
|
|
len+=CSInputNextBitStringLE(input,lenbits);
|
|
|
|
*offset=offs;
|
|
*length=len;
|
|
lastoffs=offs;
|
|
|
|
return XADLZSSMatch;
|
|
}
|
|
|
|
-(void)readBlockHeaderAtPosition:(off_t)pos
|
|
{
|
|
[maincode release];
|
|
[offsetcode release];
|
|
maincode=offsetcode=nil;
|
|
|
|
blocktype=CSInputNextBitStringLE(input,3);
|
|
if(blocktype<1||blocktype>3) [XADException raiseIllegalDataException];
|
|
|
|
if(blocktype==1) [XADException raiseNotSupportedException]; // Never encountered one of these?
|
|
|
|
if(blocktype==3)
|
|
{
|
|
int codelengths[8];
|
|
for(int i=0;i<8;i++) codelengths[i]=CSInputNextBitStringLE(input,3);
|
|
|
|
offsetcode=[[XADPrefixCode alloc] initWithLengths:codelengths
|
|
numberOfSymbols:8 maximumLength:7 shortestCodeIsZeros:YES];
|
|
}
|
|
|
|
int blocksize=CSInputNextBitStringLE(input,8)<<16;
|
|
blocksize|=CSInputNextBitStringLE(input,8)<<8;
|
|
blocksize|=CSInputNextBitStringLE(input,8);
|
|
|
|
blockend=pos+blocksize;
|
|
|
|
if(blocktype!=1)
|
|
{
|
|
[self readDeltaLengths:&mainlengths[0] count:256 alternateMode:NO];
|
|
[self readDeltaLengths:&mainlengths[256] count:512 alternateMode:YES];
|
|
|
|
maincode=[[XADPrefixCode alloc] initWithLengths:mainlengths
|
|
numberOfSymbols:768 maximumLength:16 shortestCodeIsZeros:YES];
|
|
}
|
|
}
|
|
|
|
-(void)readDeltaLengths:(int *)lengths count:(int)count alternateMode:(BOOL)altmode;
|
|
{
|
|
XADPrefixCode *precode=nil;
|
|
int fix=altmode?1:0;
|
|
|
|
@try
|
|
{
|
|
int prelengths[20];
|
|
for(int i=0;i<20;i++) prelengths[i]=CSInputNextBitStringLE(input,4);
|
|
|
|
precode=[[XADPrefixCode alloc] initWithLengths:prelengths
|
|
numberOfSymbols:20 maximumLength:15 shortestCodeIsZeros:YES];
|
|
|
|
int i=0;
|
|
while(i<count)
|
|
{
|
|
int val=CSInputNextSymbolUsingCodeLE(input,precode);
|
|
int n,length;
|
|
|
|
if(val<=16)
|
|
{
|
|
n=1;
|
|
length=(lengths[i]+17-val)%17;
|
|
}
|
|
else if(val==17)
|
|
{
|
|
n=CSInputNextBitStringLE(input,4)+4-fix;
|
|
length=0;
|
|
}
|
|
else if(val==18)
|
|
{
|
|
n=CSInputNextBitStringLE(input,5+fix)+20-fix;
|
|
length=0;
|
|
}
|
|
else if(val==19)
|
|
{
|
|
n=CSInputNextBitStringLE(input,1)+4-fix;
|
|
int newval=CSInputNextSymbolUsingCodeLE(input,precode);
|
|
length=(lengths[i]+17-newval)%17;
|
|
}
|
|
|
|
if(i+n>count) [XADException raiseDecrunchException];
|
|
for(int j=0;j<n;j++) lengths[i+j]=length;
|
|
i+=n;
|
|
}
|
|
|
|
[precode release];
|
|
}
|
|
@catch(id e)
|
|
{
|
|
[precode release];
|
|
@throw;
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation XADLZXSwapHandle
|
|
|
|
-(id)initWithHandle:(CSHandle *)handle
|
|
{
|
|
return [super initWithInputBufferForHandle:handle];
|
|
}
|
|
|
|
-(uint8_t)produceByteAtOffset:(off_t)pos
|
|
{
|
|
if(pos&1) return otherbyte;
|
|
|
|
if(CSInputAtEOF(input)) CSByteStreamEOF(self);
|
|
otherbyte=CSInputNextByte(input);
|
|
if(CSInputAtEOF(input)) CSByteStreamEOF(self);
|
|
return CSInputNextByte(input);
|
|
}
|
|
|
|
@end
|
|
|