mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-28 19:13:49 +02:00
546 lines
20 KiB
Objective-C
546 lines
20 KiB
Objective-C
/*
|
|
* XADRAR15Handle.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 "XADRAR15Handle.h"
|
|
#import "XADException.h"
|
|
|
|
static BOOL GetFlagBit(XADRAR15Handle *self);
|
|
static void EmitLiteral(XADRAR15Handle *self,off_t *posptr);
|
|
static void EmitLongMatch(XADRAR15Handle *self,off_t *posptr);
|
|
static void EmitShortMatch(XADRAR15Handle *self,off_t *posptr);
|
|
static int LookupByte(int *table,int *reverse,int limit,int index);
|
|
static void ResetTable(int *table,int *reverse);
|
|
|
|
@implementation XADRAR15Handle
|
|
|
|
-(id)initWithRARParser:(XADRARParser *)parentparser files:(NSArray *)filearray
|
|
{
|
|
if((self=[super initWithParentHandle:[parentparser handle] windowSize:0x10000]))
|
|
{
|
|
parser=parentparser;
|
|
files=[filearray retain];
|
|
|
|
lengthcode1=[[XADPrefixCode alloc] initWithLengths:(int[256]){
|
|
2,2,3,4,4,5,5,6,6,6,6,7,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,10,10,10,10,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
} numberOfSymbols:256 maximumLength:12 shortestCodeIsZeros:YES];
|
|
|
|
lengthcode2=[[XADPrefixCode alloc] initWithLengths:(int[256]){
|
|
3,3,3,3,3,4,4,5,5,6,6,6,6,7,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,
|
|
11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
} numberOfSymbols:256 maximumLength:12 shortestCodeIsZeros:YES];
|
|
|
|
huffmancode0=[[XADPrefixCode alloc] initWithLengths:(int[257]){
|
|
4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,
|
|
} numberOfSymbols:257 maximumLength:12 shortestCodeIsZeros:YES];
|
|
|
|
huffmancode1=[[XADPrefixCode alloc] initWithLengths:(int[257]){
|
|
5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
|
6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,
|
|
9,9,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
|
|
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
|
} numberOfSymbols:257 maximumLength:12 shortestCodeIsZeros:YES];
|
|
|
|
huffmancode2=[[XADPrefixCode alloc] initWithLengths:(int[257]){
|
|
5,5,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,
|
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
|
} numberOfSymbols:257 maximumLength:10 shortestCodeIsZeros:YES];
|
|
|
|
huffmancode3=[[XADPrefixCode alloc] initWithLengths:(int[257]){
|
|
6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,
|
|
} numberOfSymbols:257 maximumLength:10 shortestCodeIsZeros:YES];
|
|
|
|
huffmancode4=[[XADPrefixCode alloc] initWithLengths:(int[257]){
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,
|
|
} numberOfSymbols:257 maximumLength:9 shortestCodeIsZeros:YES];
|
|
|
|
shortmatchcode0=[[XADPrefixCode alloc] init];
|
|
[shortmatchcode0 addValue:0 forCodeWithHighBitFirst:0x00 length:1];
|
|
[shortmatchcode0 addValue:1 forCodeWithHighBitFirst:0x0a length:4];
|
|
[shortmatchcode0 addValue:2 forCodeWithHighBitFirst:0x0d length:4];
|
|
[shortmatchcode0 addValue:3 forCodeWithHighBitFirst:0x0e length:4];
|
|
[shortmatchcode0 addValue:4 forCodeWithHighBitFirst:0x1e length:5];
|
|
[shortmatchcode0 addValue:5 forCodeWithHighBitFirst:0x3e length:6];
|
|
[shortmatchcode0 addValue:6 forCodeWithHighBitFirst:0x7e length:7];
|
|
[shortmatchcode0 addValue:7 forCodeWithHighBitFirst:0xfe length:8];
|
|
[shortmatchcode0 addValue:8 forCodeWithHighBitFirst:0xff length:8];
|
|
[shortmatchcode0 addValue:9 forCodeWithHighBitFirst:0x0c length:4];
|
|
[shortmatchcode0 addValue:10 forCodeWithHighBitFirst:0x08 length:4];
|
|
[shortmatchcode0 addValue:11 forCodeWithHighBitFirst:0x12 length:5];
|
|
[shortmatchcode0 addValue:12 forCodeWithHighBitFirst:0x26 length:6];
|
|
[shortmatchcode0 addValue:13 forCodeWithHighBitFirst:0x27 length:6];
|
|
[shortmatchcode0 addValue:14 forCodeWithHighBitFirst:0x0b length:4];
|
|
|
|
shortmatchcode1=[[XADPrefixCode alloc] init];
|
|
[shortmatchcode1 addValue:0 forCodeWithHighBitFirst:0x00 length:1];
|
|
[shortmatchcode1 addValue:1 forCodeWithHighBitFirst:0x05 length:3];
|
|
[shortmatchcode1 addValue:2 forCodeWithHighBitFirst:0x0d length:4];
|
|
[shortmatchcode1 addValue:3 forCodeWithHighBitFirst:0x0e length:4];
|
|
[shortmatchcode1 addValue:4 forCodeWithHighBitFirst:0x1e length:5];
|
|
[shortmatchcode1 addValue:5 forCodeWithHighBitFirst:0x3e length:6];
|
|
[shortmatchcode1 addValue:6 forCodeWithHighBitFirst:0x7e length:7];
|
|
[shortmatchcode1 addValue:7 forCodeWithHighBitFirst:0xfe length:8];
|
|
[shortmatchcode1 addValue:8 forCodeWithHighBitFirst:0xff length:8];
|
|
[shortmatchcode1 addValue:9 forCodeWithHighBitFirst:0x0c length:4];
|
|
[shortmatchcode1 addValue:10 forCodeWithHighBitFirst:0x08 length:4];
|
|
[shortmatchcode1 addValue:11 forCodeWithHighBitFirst:0x12 length:5];
|
|
[shortmatchcode1 addValue:12 forCodeWithHighBitFirst:0x26 length:6];
|
|
[shortmatchcode1 addValue:13 forCodeWithHighBitFirst:0x27 length:6];
|
|
|
|
shortmatchcode2=[[XADPrefixCode alloc] init];
|
|
[shortmatchcode2 addValue:0 forCodeWithHighBitFirst:0x00 length:2];
|
|
[shortmatchcode2 addValue:1 forCodeWithHighBitFirst:0x02 length:3];
|
|
[shortmatchcode2 addValue:2 forCodeWithHighBitFirst:0x03 length:3];
|
|
[shortmatchcode2 addValue:3 forCodeWithHighBitFirst:0x0a length:4];
|
|
[shortmatchcode2 addValue:4 forCodeWithHighBitFirst:0x0d length:4];
|
|
[shortmatchcode2 addValue:5 forCodeWithHighBitFirst:0x3e length:4];
|
|
[shortmatchcode2 addValue:6 forCodeWithHighBitFirst:0x1e length:5];
|
|
[shortmatchcode2 addValue:7 forCodeWithHighBitFirst:0x3e length:6];
|
|
[shortmatchcode2 addValue:8 forCodeWithHighBitFirst:0x3f length:6];
|
|
[shortmatchcode2 addValue:9 forCodeWithHighBitFirst:0x0c length:4];
|
|
[shortmatchcode2 addValue:10 forCodeWithHighBitFirst:0x08 length:4];
|
|
[shortmatchcode2 addValue:11 forCodeWithHighBitFirst:0x12 length:5];
|
|
[shortmatchcode2 addValue:12 forCodeWithHighBitFirst:0x26 length:6];
|
|
[shortmatchcode2 addValue:13 forCodeWithHighBitFirst:0x27 length:6];
|
|
[shortmatchcode2 addValue:14 forCodeWithHighBitFirst:0x0b length:4];
|
|
|
|
shortmatchcode3=[[XADPrefixCode alloc] init];
|
|
[shortmatchcode3 addValue:0 forCodeWithHighBitFirst:0x00 length:2];
|
|
[shortmatchcode3 addValue:1 forCodeWithHighBitFirst:0x02 length:3];
|
|
[shortmatchcode3 addValue:2 forCodeWithHighBitFirst:0x03 length:3];
|
|
[shortmatchcode3 addValue:3 forCodeWithHighBitFirst:0x05 length:3];
|
|
[shortmatchcode3 addValue:4 forCodeWithHighBitFirst:0x0d length:4];
|
|
[shortmatchcode3 addValue:5 forCodeWithHighBitFirst:0x3e length:4];
|
|
[shortmatchcode3 addValue:6 forCodeWithHighBitFirst:0x1e length:5];
|
|
[shortmatchcode3 addValue:7 forCodeWithHighBitFirst:0x3e length:6];
|
|
[shortmatchcode3 addValue:8 forCodeWithHighBitFirst:0x3f length:6];
|
|
[shortmatchcode3 addValue:9 forCodeWithHighBitFirst:0x0c length:4];
|
|
[shortmatchcode3 addValue:10 forCodeWithHighBitFirst:0x08 length:4];
|
|
[shortmatchcode3 addValue:11 forCodeWithHighBitFirst:0x12 length:5];
|
|
[shortmatchcode3 addValue:12 forCodeWithHighBitFirst:0x26 length:6];
|
|
[shortmatchcode3 addValue:13 forCodeWithHighBitFirst:0x27 length:6];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(void)dealloc
|
|
{
|
|
[lengthcode1 release];
|
|
[lengthcode2 release];
|
|
[huffmancode0 release];
|
|
[huffmancode1 release];
|
|
[huffmancode2 release];
|
|
[huffmancode3 release];
|
|
[huffmancode4 release];
|
|
[shortmatchcode0 release];
|
|
[shortmatchcode1 release];
|
|
[shortmatchcode2 release];
|
|
[shortmatchcode3 release];
|
|
[super dealloc];
|
|
}
|
|
|
|
-(void)resetLZSSHandle
|
|
{
|
|
file=0;
|
|
endpos=0;
|
|
|
|
numrepeatedliterals=0;
|
|
bugfixflag=NO;
|
|
|
|
runningaverageselector=0;
|
|
runningaverageliteral=0x3500;
|
|
runningaveragelength=0;
|
|
runningaverageoffset=0;
|
|
runningaveragebelowmaximum=0;
|
|
|
|
maximumoffset=0x2001;
|
|
literalweight=matchweight=0x80;
|
|
|
|
for(int i=0;i<256;i++)
|
|
{
|
|
flagtable[i]=((-i)&0xff)<<8;
|
|
literaltable[i]=i<<8;
|
|
offsettable[i]=i<<8;
|
|
shortoffsettable[i]=i;
|
|
}
|
|
memset(flagreverse,0,sizeof(flagreverse));
|
|
memset(literalreverse,0,sizeof(literalreverse));
|
|
|
|
ResetTable(offsettable,offsetreverse);
|
|
|
|
lastoffset=0;
|
|
lastlength=0;
|
|
memset(oldoffset,0,sizeof(oldoffset));
|
|
oldoffsetindex=0;
|
|
|
|
[self startNextFile];
|
|
}
|
|
|
|
-(void)startNextFile
|
|
{
|
|
flagbits=0;
|
|
storedblock=NO;
|
|
numrepeatedlastmatches=0;
|
|
|
|
CSInputBuffer *buf=[parser inputBufferForFileWithIndex:file files:files];
|
|
off_t partlength=[parser outputLengthOfFileWithIndex:file files:files];
|
|
file++;
|
|
|
|
[self setInputBuffer:buf];
|
|
endpos+=partlength;
|
|
}
|
|
|
|
-(void)expandFromPosition:(off_t)pos
|
|
{
|
|
while(XADLZSSShouldKeepExpanding(self))
|
|
{
|
|
if(pos==endpos) [self startNextFile];
|
|
|
|
if(storedblock)
|
|
{
|
|
EmitLiteral(self,&pos);
|
|
}
|
|
else
|
|
{
|
|
BOOL expectingmatch=matchweight>literalweight;
|
|
if(GetFlagBit(self))
|
|
{
|
|
// The expected case.
|
|
if(expectingmatch) EmitLongMatch(self,&pos);
|
|
else EmitLiteral(self,&pos);
|
|
}
|
|
else if(GetFlagBit(self))
|
|
{
|
|
// The unexpected case.
|
|
if(!expectingmatch) EmitLongMatch(self,&pos);
|
|
else EmitLiteral(self,&pos);
|
|
}
|
|
else
|
|
{
|
|
EmitShortMatch(self,&pos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static BOOL GetFlagBit(XADRAR15Handle *self)
|
|
{
|
|
if(self->flagbits==0)
|
|
{
|
|
int index=CSInputNextSymbolUsingCode(self->input,self->huffmancode2);
|
|
if(index==256) [XADException raiseIllegalDataException];
|
|
self->flags=LookupByte(self->flagtable,self->flagreverse,0xff,index);
|
|
self->flagbits=8;
|
|
}
|
|
|
|
self->flagbits--;
|
|
return (self->flags>>self->flagbits)&1;
|
|
}
|
|
|
|
static void EmitLiteral(XADRAR15Handle *self,off_t *posptr)
|
|
{
|
|
int index;
|
|
if(self->runningaverageliteral<0xe00) index=CSInputNextSymbolUsingCode(self->input,self->huffmancode0);
|
|
else if(self->runningaverageliteral<0x3600) index=CSInputNextSymbolUsingCode(self->input,self->huffmancode1);
|
|
else if(self->runningaverageliteral<0x5e00) index=CSInputNextSymbolUsingCode(self->input,self->huffmancode2);
|
|
else if(self->runningaverageliteral<0x7600) index=CSInputNextSymbolUsingCode(self->input,self->huffmancode3);
|
|
else index=CSInputNextSymbolUsingCode(self->input,self->huffmancode4);
|
|
|
|
if(self->storedblock)
|
|
{
|
|
// This differs slightly from what RAR does, but is sane.
|
|
// (RAR masks away 0x100 before this part, and restores it clumsily).
|
|
if(index==0)
|
|
{
|
|
if(CSInputNextBit(self->input))
|
|
{
|
|
self->storedblock=NO;
|
|
self->numrepeatedliterals=0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
int length;
|
|
if(CSInputNextBit(self->input)) length=4;
|
|
else length=3;
|
|
|
|
int offset=CSInputNextSymbolUsingCode(self->input,self->huffmancode2)<<5;
|
|
offset|=CSInputNextBitString(self->input,5);
|
|
|
|
XADEmitLZSSMatch(self,offset,length,posptr);
|
|
return;
|
|
}
|
|
}
|
|
else index--;
|
|
}
|
|
else
|
|
{
|
|
index&=0xff;
|
|
if(self->numrepeatedliterals++>=16&&self->flagbits==0) self->storedblock=YES;
|
|
}
|
|
|
|
self->runningaverageliteral+=index;
|
|
self->runningaverageliteral-=self->runningaverageliteral>>8;
|
|
|
|
self->literalweight+=16;
|
|
if(self->literalweight>0xff)
|
|
{
|
|
self->literalweight=0x90;
|
|
self->matchweight>>=1;
|
|
}
|
|
|
|
uint8_t byte=LookupByte(self->literaltable,self->literalreverse,0xa1,index);
|
|
XADEmitLZSSLiteral(self,byte,posptr);
|
|
}
|
|
|
|
static void EmitLongMatch(XADRAR15Handle *self,off_t *posptr)
|
|
{
|
|
self->numrepeatedliterals=0;
|
|
self->matchweight+=16;
|
|
if(self->matchweight>0xff)
|
|
{
|
|
self->matchweight=0x90;
|
|
self->literalweight>>=1;
|
|
}
|
|
|
|
int rawlength;
|
|
if(self->runningaveragelength>=122) rawlength=CSInputNextSymbolUsingCode(self->input,self->lengthcode2);
|
|
else if(self->runningaveragelength>=64) rawlength=CSInputNextSymbolUsingCode(self->input,self->lengthcode1);
|
|
else
|
|
{
|
|
rawlength=0;
|
|
while(rawlength<8 && CSInputNextBit(self->input)==0) rawlength++;
|
|
|
|
if(rawlength==8) rawlength=CSInputNextBitString(self->input,8);
|
|
}
|
|
|
|
int offsetindex;
|
|
if(self->runningaverageoffset<0x700) offsetindex=CSInputNextSymbolUsingCode(self->input,self->huffmancode0);
|
|
else if(self->runningaverageoffset<0x2900) offsetindex=CSInputNextSymbolUsingCode(self->input,self->huffmancode1);
|
|
else offsetindex=CSInputNextSymbolUsingCode(self->input,self->huffmancode2);
|
|
|
|
if(offsetindex==0x100) [XADException raiseIllegalDataException];
|
|
|
|
int offset=LookupByte(self->offsettable,self->offsetreverse,0xff,offsetindex)<<7;
|
|
offset|=CSInputNextBitString(self->input,7);
|
|
|
|
int length=rawlength+3;
|
|
|
|
if(offset>=self->maximumoffset) length++;
|
|
if(offset<=256) length+=8;
|
|
|
|
unsigned int oldMaximumOffset = self->maximumoffset;
|
|
if(self->runningaveragebelowmaximum>0xb0 || (self->runningaverageliteral>=0x2a00
|
|
&& self->runningaveragelength<0x40)) self->maximumoffset=0x7f00;
|
|
else self->maximumoffset=0x2001;
|
|
|
|
|
|
self->runningaveragelength+=rawlength;
|
|
self->runningaveragelength-=self->runningaveragelength>>5;
|
|
|
|
self->runningaverageoffset+=offsetindex;
|
|
self->runningaverageoffset-=self->runningaverageoffset>>8;
|
|
|
|
if (rawlength == 0 && offset <= oldMaximumOffset)
|
|
{
|
|
self->runningaveragebelowmaximum++;
|
|
self->runningaveragebelowmaximum-=self->runningaveragebelowmaximum>>8;
|
|
}
|
|
else if(rawlength!=1&&rawlength!=4)
|
|
{
|
|
if(self->runningaveragebelowmaximum>0) self->runningaveragebelowmaximum--;
|
|
}
|
|
|
|
|
|
|
|
self->lastoffset=self->oldoffset[self->oldoffsetindex++&3]=offset;
|
|
self->lastlength=length;
|
|
|
|
XADEmitLZSSMatch(self,self->lastoffset,self->lastlength,posptr);
|
|
}
|
|
|
|
static void EmitShortMatch(XADRAR15Handle *self,off_t *posptr)
|
|
{
|
|
self->numrepeatedliterals=0;
|
|
|
|
if(self->numrepeatedlastmatches==2)
|
|
{
|
|
if(CSInputNextBit(self->input))
|
|
{
|
|
XADEmitLZSSMatch(self,self->lastoffset,self->lastlength,posptr);
|
|
return;
|
|
}
|
|
else self->numrepeatedlastmatches=0;
|
|
}
|
|
|
|
unsigned int selector;
|
|
if(self->runningaverageselector<37)
|
|
{
|
|
if(self->bugfixflag) selector=CSInputNextSymbolUsingCode(self->input,self->shortmatchcode0);
|
|
else selector=CSInputNextSymbolUsingCode(self->input,self->shortmatchcode1);
|
|
}
|
|
else
|
|
{
|
|
if(self->bugfixflag) selector=CSInputNextSymbolUsingCode(self->input,self->shortmatchcode2);
|
|
else selector=CSInputNextSymbolUsingCode(self->input,self->shortmatchcode3);
|
|
}
|
|
|
|
if(selector<9)
|
|
{
|
|
self->numrepeatedlastmatches=0;
|
|
|
|
self->runningaverageselector+=selector;
|
|
self->runningaverageselector-=self->runningaverageselector>>4;
|
|
|
|
int offsetindex=CSInputNextSymbolUsingCode(self->input,self->huffmancode2)&0xff;
|
|
|
|
int offset=self->shortoffsettable[offsetindex];
|
|
if(offsetindex!=0)
|
|
{
|
|
self->shortoffsettable[offsetindex]=self->shortoffsettable[offsetindex-1];
|
|
self->shortoffsettable[offsetindex-1]=offset;
|
|
}
|
|
offset++;
|
|
|
|
int length=selector+2;
|
|
|
|
self->lastoffset=self->oldoffset[self->oldoffsetindex++&3]=offset;
|
|
self->lastlength=length;
|
|
|
|
XADEmitLZSSMatch(self,offset,length,posptr);
|
|
}
|
|
else if(selector==9)
|
|
{
|
|
self->numrepeatedlastmatches++;
|
|
|
|
XADEmitLZSSMatch(self,self->lastoffset,self->lastlength,posptr);
|
|
}
|
|
else if(selector<14)
|
|
{
|
|
self->numrepeatedlastmatches=0;
|
|
|
|
int offset=self->oldoffset[(self->oldoffsetindex-(selector-9))&3];
|
|
|
|
int length=CSInputNextSymbolUsingCode(self->input,self->lengthcode1)+2;
|
|
if(length==0x101 && selector==10)
|
|
{
|
|
self->bugfixflag=!self->bugfixflag;
|
|
return;
|
|
}
|
|
|
|
if(offset>256) length++;
|
|
if(offset>=self->maximumoffset) length++;
|
|
|
|
self->lastoffset=self->oldoffset[self->oldoffsetindex++&3]=offset;
|
|
self->lastlength=length;
|
|
|
|
XADEmitLZSSMatch(self,offset,length,posptr);
|
|
}
|
|
else //if(length==14)
|
|
{
|
|
self->numrepeatedlastmatches=0;
|
|
|
|
int length=CSInputNextSymbolUsingCode(self->input,self->lengthcode2)+5;
|
|
int offset=CSInputNextBitString(self->input,15)+0x8000;
|
|
|
|
self->lastoffset=offset;
|
|
self->lastlength=length;
|
|
|
|
XADEmitLZSSMatch(self,offset,length,posptr);
|
|
}
|
|
}
|
|
|
|
static int LookupByte(int *table,int *reverse,int limit,int index)
|
|
{
|
|
int val=table[index];
|
|
int newindex=reverse[val&0xff]++;
|
|
|
|
if((val&0xff)>=limit)
|
|
{
|
|
ResetTable(table,reverse);
|
|
val=table[index];
|
|
newindex=reverse[val&0xff]++;
|
|
}
|
|
|
|
table[index]=table[newindex];
|
|
table[newindex]=val+1;
|
|
|
|
return val>>8;
|
|
}
|
|
|
|
static void ResetTable(int *table,int *reverse)
|
|
{
|
|
for(int i=0;i<8;i++)
|
|
for(int j=0;j<32;j++)
|
|
table[i*32+j]=(table[i*32+j]&~0xff)|(7-i);
|
|
|
|
memset(reverse,0,sizeof(int)*256);
|
|
for(int i=0;i<7;i++) reverse[i]=(7-i)*32;
|
|
}
|
|
|
|
@end
|
|
|