XADMaster/XADRAR15Handle.m
2020-04-22 23:01:46 +03:00

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