File: XAD7ZipBCJ2Handle.m

package info (click to toggle)
unar 1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,664 kB
  • sloc: ansic: 52,939; objc: 39,563; cpp: 4,074; makefile: 99; perl: 10
file content (119 lines) | stat: -rw-r--r-- 2,213 bytes parent folder | download
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
#import "XAD7ZipBCJ2Handle.h"

#define NumTopBits 24
#define TopValue (1<<NumTopBits)

#define BitModelTotalBits 11
#define BitModelTotal (1<<BitModelTotalBits)
#define NumMoveBits 5


@implementation XAD7ZipBCJ2Handle

static inline BOOL IsJ(int b0,int b1)
{
	if((b1&0xfe)==0xe8) return YES;
	if(b0==0x0f&&(b1&0xf0)==0x80) return YES;
	return NO;
}

static inline int NextRangeBit(XAD7ZipBCJ2Handle *self,uint16_t *prob)
{
	int res;
	uint32_t bound=(self->range>>BitModelTotalBits)**prob;
	if(self->code<bound)
	{
		res=0;
		self->range=bound;
		*prob=*prob+((BitModelTotal-*prob)>>NumMoveBits);
	}
	else
	{
		res=1;
		self->range-=bound;
		self->code-=bound;
		*prob=*prob-(*prob>>NumMoveBits);
	}

	// Normalize
	if(self->range<TopValue)
	{
		self->range<<=8;
		self->code=(self->code<<8)|[self->ranges readUInt8];
	}

	return res;
}

-(id)initWithHandle:(CSHandle *)handle callHandle:(CSHandle *)callhandle
jumpHandle:(CSHandle *)jumphandle rangeHandle:(CSHandle *)rangehandle length:(off_t)length
{
	if((self=[super initWithHandle:handle length:length]))
	{
		calls=[callhandle retain];
		jumps=[jumphandle retain];
		ranges=[rangehandle retain];
		callstart=[calls offsetInFile];
		jumpstart=[jumps offsetInFile];
		rangestart=[ranges offsetInFile];
	}
	return self;
}

-(void)dealloc
{
	[calls release];
	[jumps release];
	[ranges release];
	[super dealloc];
}

-(void)resetByteStream
{
	[calls seekToFileOffset:callstart];
	[jumps seekToFileOffset:jumpstart];
	[ranges seekToFileOffset:rangestart];

	code=0;
	range=0xffffffff;
	for(int i=0;i<5;i++) code=(code<<8)|[ranges readUInt8];
	for(int i=0;i<258;i++) probabilities[i]=BitModelTotal/2;

	prevbyte=0;
	valbyte=4;
}

-(uint8_t)produceByteAtOffset:(off_t)pos
{
	if(valbyte<4)
	{
		prevbyte=(val>>valbyte*8)&0xff;
		valbyte++;
		return prevbyte;
	}

	uint8_t b=CSInputNextByte(input);

	if(IsJ(prevbyte,b))
	{
		uint16_t *prob;
		if(b==0xe8) prob=&probabilities[prevbyte];
		else if (b==0xe9) prob=&probabilities[256];
		else prob=&probabilities[257];

		if(NextRangeBit(self,prob)==1)
		{
			CSHandle *handle;
			if(b==0xe8) handle=calls;
			else handle=jumps;

			val=[handle readUInt32BE]-(pos+5);
			valbyte=0;
		}
	}

	return prevbyte=b;
}

@end