1*74a4d8c2SCharles.Forsyth #include "lib9.h"
2*74a4d8c2SCharles.Forsyth #include <flate.h>
3*74a4d8c2SCharles.Forsyth
4*74a4d8c2SCharles.Forsyth typedef struct Chain Chain;
5*74a4d8c2SCharles.Forsyth typedef struct Chains Chains;
6*74a4d8c2SCharles.Forsyth typedef struct Dyncode Dyncode;
7*74a4d8c2SCharles.Forsyth typedef struct Huff Huff;
8*74a4d8c2SCharles.Forsyth typedef struct LZblock LZblock;
9*74a4d8c2SCharles.Forsyth typedef struct LZstate LZstate;
10*74a4d8c2SCharles.Forsyth
11*74a4d8c2SCharles.Forsyth enum
12*74a4d8c2SCharles.Forsyth {
13*74a4d8c2SCharles.Forsyth /*
14*74a4d8c2SCharles.Forsyth * deflate format paramaters
15*74a4d8c2SCharles.Forsyth */
16*74a4d8c2SCharles.Forsyth DeflateUnc = 0, /* uncompressed block */
17*74a4d8c2SCharles.Forsyth DeflateFix = 1, /* fixed huffman codes */
18*74a4d8c2SCharles.Forsyth DeflateDyn = 2, /* dynamic huffman codes */
19*74a4d8c2SCharles.Forsyth
20*74a4d8c2SCharles.Forsyth DeflateEob = 256, /* end of block code in lit/len book */
21*74a4d8c2SCharles.Forsyth DeflateMaxBlock = 64*1024-1, /* maximum size of uncompressed block */
22*74a4d8c2SCharles.Forsyth
23*74a4d8c2SCharles.Forsyth DeflateMaxExp = 10, /* maximum expansion for a block */
24*74a4d8c2SCharles.Forsyth
25*74a4d8c2SCharles.Forsyth LenStart = 257, /* start of length codes in litlen */
26*74a4d8c2SCharles.Forsyth Nlitlen = 288, /* number of litlen codes */
27*74a4d8c2SCharles.Forsyth Noff = 30, /* number of offset codes */
28*74a4d8c2SCharles.Forsyth Nclen = 19, /* number of codelen codes */
29*74a4d8c2SCharles.Forsyth
30*74a4d8c2SCharles.Forsyth MaxOff = 32*1024,
31*74a4d8c2SCharles.Forsyth MinMatch = 3, /* shortest match possible */
32*74a4d8c2SCharles.Forsyth MaxMatch = 258, /* longest match possible */
33*74a4d8c2SCharles.Forsyth
34*74a4d8c2SCharles.Forsyth /*
35*74a4d8c2SCharles.Forsyth * huffman code paramaters
36*74a4d8c2SCharles.Forsyth */
37*74a4d8c2SCharles.Forsyth MaxLeaf = Nlitlen,
38*74a4d8c2SCharles.Forsyth MaxHuffBits = 16, /* max bits in a huffman code */
39*74a4d8c2SCharles.Forsyth ChainMem = 2 * (MaxHuffBits - 1) * MaxHuffBits,
40*74a4d8c2SCharles.Forsyth
41*74a4d8c2SCharles.Forsyth /*
42*74a4d8c2SCharles.Forsyth * coding of the lz parse
43*74a4d8c2SCharles.Forsyth */
44*74a4d8c2SCharles.Forsyth LenFlag = 1 << 3,
45*74a4d8c2SCharles.Forsyth LenShift = 4, /* leaves enough space for MinMatchMaxOff */
46*74a4d8c2SCharles.Forsyth MaxLitRun = LenFlag - 1,
47*74a4d8c2SCharles.Forsyth
48*74a4d8c2SCharles.Forsyth /*
49*74a4d8c2SCharles.Forsyth * internal lz paramaters
50*74a4d8c2SCharles.Forsyth */
51*74a4d8c2SCharles.Forsyth DeflateOut = 4096, /* output buffer size */
52*74a4d8c2SCharles.Forsyth BlockSize = 8192, /* attempted input read quanta */
53*74a4d8c2SCharles.Forsyth DeflateBlock = DeflateMaxBlock & ~(BlockSize - 1),
54*74a4d8c2SCharles.Forsyth MinMatchMaxOff = 4096, /* max profitable offset for small match;
55*74a4d8c2SCharles.Forsyth * assumes 8 bits for len, 5+10 for offset
56*74a4d8c2SCharles.Forsyth * DONT CHANGE WITHOUT CHANGING LZPARSE CONSTANTS
57*74a4d8c2SCharles.Forsyth */
58*74a4d8c2SCharles.Forsyth HistSlop = 512, /* must be at lead MaxMatch */
59*74a4d8c2SCharles.Forsyth HistBlock = 64*1024,
60*74a4d8c2SCharles.Forsyth HistSize = HistBlock + HistSlop,
61*74a4d8c2SCharles.Forsyth
62*74a4d8c2SCharles.Forsyth HashLog = 13,
63*74a4d8c2SCharles.Forsyth HashSize = 1<<HashLog,
64*74a4d8c2SCharles.Forsyth
65*74a4d8c2SCharles.Forsyth MaxOffCode = 256, /* biggest offset looked up in direct table */
66*74a4d8c2SCharles.Forsyth
67*74a4d8c2SCharles.Forsyth EstLitBits = 8,
68*74a4d8c2SCharles.Forsyth EstLenBits = 4,
69*74a4d8c2SCharles.Forsyth EstOffBits = 5,
70*74a4d8c2SCharles.Forsyth };
71*74a4d8c2SCharles.Forsyth
72*74a4d8c2SCharles.Forsyth /*
73*74a4d8c2SCharles.Forsyth * knuth vol. 3 multiplicative hashing
74*74a4d8c2SCharles.Forsyth * each byte x chosen according to rules
75*74a4d8c2SCharles.Forsyth * 1/4 < x < 3/10, 1/3 x < < 3/7, 4/7 < x < 2/3, 7/10 < x < 3/4
76*74a4d8c2SCharles.Forsyth * with reasonable spread between the bytes & their complements
77*74a4d8c2SCharles.Forsyth *
78*74a4d8c2SCharles.Forsyth * the 3 byte value appears to be as almost good as the 4 byte value,
79*74a4d8c2SCharles.Forsyth * and might be faster on some machines
80*74a4d8c2SCharles.Forsyth */
81*74a4d8c2SCharles.Forsyth /*
82*74a4d8c2SCharles.Forsyth #define hashit(c) (((ulong)(c) * 0x6b43a9) >> (24 - HashLog))
83*74a4d8c2SCharles.Forsyth */
84*74a4d8c2SCharles.Forsyth #define hashit(c) ((((ulong)(c) & 0xffffff) * 0x6b43a9b5) >> (32 - HashLog))
85*74a4d8c2SCharles.Forsyth
86*74a4d8c2SCharles.Forsyth /*
87*74a4d8c2SCharles.Forsyth * lempel-ziv style compression state
88*74a4d8c2SCharles.Forsyth */
89*74a4d8c2SCharles.Forsyth struct LZstate
90*74a4d8c2SCharles.Forsyth {
91*74a4d8c2SCharles.Forsyth uchar hist[HistSize];
92*74a4d8c2SCharles.Forsyth ulong pos; /* current location in history buffer */
93*74a4d8c2SCharles.Forsyth ulong avail; /* data available after pos */
94*74a4d8c2SCharles.Forsyth int eof;
95*74a4d8c2SCharles.Forsyth ushort hash[HashSize]; /* hash chains */
96*74a4d8c2SCharles.Forsyth ushort nexts[MaxOff];
97*74a4d8c2SCharles.Forsyth int now; /* pos in hash chains */
98*74a4d8c2SCharles.Forsyth int dot; /* dawn of time in history */
99*74a4d8c2SCharles.Forsyth int prevlen; /* lazy matching state */
100*74a4d8c2SCharles.Forsyth int prevoff;
101*74a4d8c2SCharles.Forsyth int maxcheck; /* compressor tuning */
102*74a4d8c2SCharles.Forsyth
103*74a4d8c2SCharles.Forsyth uchar obuf[DeflateOut];
104*74a4d8c2SCharles.Forsyth uchar *out; /* current position in the output buffer */
105*74a4d8c2SCharles.Forsyth uchar *eout;
106*74a4d8c2SCharles.Forsyth ulong bits; /* bit shift register */
107*74a4d8c2SCharles.Forsyth int nbits;
108*74a4d8c2SCharles.Forsyth int rbad; /* got an error reading the buffer */
109*74a4d8c2SCharles.Forsyth int wbad; /* got an error writing the buffer */
110*74a4d8c2SCharles.Forsyth int (*w)(void*, void*, int);
111*74a4d8c2SCharles.Forsyth void *wr;
112*74a4d8c2SCharles.Forsyth
113*74a4d8c2SCharles.Forsyth ulong totr; /* total input size */
114*74a4d8c2SCharles.Forsyth ulong totw; /* total output size */
115*74a4d8c2SCharles.Forsyth int debug;
116*74a4d8c2SCharles.Forsyth };
117*74a4d8c2SCharles.Forsyth
118*74a4d8c2SCharles.Forsyth struct LZblock
119*74a4d8c2SCharles.Forsyth {
120*74a4d8c2SCharles.Forsyth ushort parse[DeflateMaxBlock / 2 + 1];
121*74a4d8c2SCharles.Forsyth int lastv; /* value being constucted for parse */
122*74a4d8c2SCharles.Forsyth ulong litlencount[Nlitlen];
123*74a4d8c2SCharles.Forsyth ulong offcount[Noff];
124*74a4d8c2SCharles.Forsyth ushort *eparse; /* limit for parse table */
125*74a4d8c2SCharles.Forsyth int bytes; /* consumed from the input */
126*74a4d8c2SCharles.Forsyth int excost; /* cost of encoding extra len & off bits */
127*74a4d8c2SCharles.Forsyth };
128*74a4d8c2SCharles.Forsyth
129*74a4d8c2SCharles.Forsyth /*
130*74a4d8c2SCharles.Forsyth * huffman code table
131*74a4d8c2SCharles.Forsyth */
132*74a4d8c2SCharles.Forsyth struct Huff
133*74a4d8c2SCharles.Forsyth {
134*74a4d8c2SCharles.Forsyth short bits; /* length of the code */
135*74a4d8c2SCharles.Forsyth ushort encode; /* the code */
136*74a4d8c2SCharles.Forsyth };
137*74a4d8c2SCharles.Forsyth
138*74a4d8c2SCharles.Forsyth /*
139*74a4d8c2SCharles.Forsyth * encoding of dynamic huffman trees
140*74a4d8c2SCharles.Forsyth */
141*74a4d8c2SCharles.Forsyth struct Dyncode
142*74a4d8c2SCharles.Forsyth {
143*74a4d8c2SCharles.Forsyth int nlit;
144*74a4d8c2SCharles.Forsyth int noff;
145*74a4d8c2SCharles.Forsyth int nclen;
146*74a4d8c2SCharles.Forsyth int ncode;
147*74a4d8c2SCharles.Forsyth Huff codetab[Nclen];
148*74a4d8c2SCharles.Forsyth uchar codes[Nlitlen+Noff];
149*74a4d8c2SCharles.Forsyth uchar codeaux[Nlitlen+Noff];
150*74a4d8c2SCharles.Forsyth };
151*74a4d8c2SCharles.Forsyth
152*74a4d8c2SCharles.Forsyth static int deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int));
153*74a4d8c2SCharles.Forsyth static int lzcomp(LZstate*, LZblock*, uchar*, ushort*, int finish);
154*74a4d8c2SCharles.Forsyth static void wrblock(LZstate*, int, ushort*, ushort*, Huff*, Huff*);
155*74a4d8c2SCharles.Forsyth static int bitcost(Huff*, ulong*, int);
156*74a4d8c2SCharles.Forsyth static int huffcodes(Dyncode*, Huff*, Huff*);
157*74a4d8c2SCharles.Forsyth static void wrdyncode(LZstate*, Dyncode*);
158*74a4d8c2SCharles.Forsyth static void lzput(LZstate*, ulong bits, int nbits);
159*74a4d8c2SCharles.Forsyth static void lzflushbits(LZstate*);
160*74a4d8c2SCharles.Forsyth static void lzflush(LZstate *lz);
161*74a4d8c2SCharles.Forsyth static void lzwrite(LZstate *lz, void *buf, int n);
162*74a4d8c2SCharles.Forsyth
163*74a4d8c2SCharles.Forsyth static int hufftabinit(Huff*, int, ulong*, int);
164*74a4d8c2SCharles.Forsyth static int mkgzprecode(Huff*, ulong *, int, int);
165*74a4d8c2SCharles.Forsyth
166*74a4d8c2SCharles.Forsyth static int mkprecode(Huff*, ulong *, int, int, ulong*);
167*74a4d8c2SCharles.Forsyth static void nextchain(Chains*, int);
168*74a4d8c2SCharles.Forsyth static void leafsort(ulong*, ushort*, int, int);
169*74a4d8c2SCharles.Forsyth
170*74a4d8c2SCharles.Forsyth /* conversion from len to code word */
171*74a4d8c2SCharles.Forsyth static int lencode[MaxMatch];
172*74a4d8c2SCharles.Forsyth
173*74a4d8c2SCharles.Forsyth /*
174*74a4d8c2SCharles.Forsyth * conversion from off to code word
175*74a4d8c2SCharles.Forsyth * off <= MaxOffCode ? offcode[off] : bigoffcode[off >> 7]
176*74a4d8c2SCharles.Forsyth */
177*74a4d8c2SCharles.Forsyth static int offcode[MaxOffCode];
178*74a4d8c2SCharles.Forsyth static int bigoffcode[256];
179*74a4d8c2SCharles.Forsyth
180*74a4d8c2SCharles.Forsyth /* litlen code words LenStart-285 extra bits */
181*74a4d8c2SCharles.Forsyth static int litlenbase[Nlitlen-LenStart];
182*74a4d8c2SCharles.Forsyth static int litlenextra[Nlitlen-LenStart] =
183*74a4d8c2SCharles.Forsyth {
184*74a4d8c2SCharles.Forsyth /* 257 */ 0, 0, 0,
185*74a4d8c2SCharles.Forsyth /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
186*74a4d8c2SCharles.Forsyth /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
187*74a4d8c2SCharles.Forsyth /* 280 */ 4, 5, 5, 5, 5, 0, 0, 0
188*74a4d8c2SCharles.Forsyth };
189*74a4d8c2SCharles.Forsyth
190*74a4d8c2SCharles.Forsyth /* offset code word extra bits */
191*74a4d8c2SCharles.Forsyth static int offbase[Noff];
192*74a4d8c2SCharles.Forsyth static int offextra[] =
193*74a4d8c2SCharles.Forsyth {
194*74a4d8c2SCharles.Forsyth 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
195*74a4d8c2SCharles.Forsyth 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
196*74a4d8c2SCharles.Forsyth 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
197*74a4d8c2SCharles.Forsyth 0, 0,
198*74a4d8c2SCharles.Forsyth };
199*74a4d8c2SCharles.Forsyth
200*74a4d8c2SCharles.Forsyth /* order code lengths */
201*74a4d8c2SCharles.Forsyth static int clenorder[Nclen] =
202*74a4d8c2SCharles.Forsyth {
203*74a4d8c2SCharles.Forsyth 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
204*74a4d8c2SCharles.Forsyth };
205*74a4d8c2SCharles.Forsyth
206*74a4d8c2SCharles.Forsyth /* static huffman tables */
207*74a4d8c2SCharles.Forsyth static Huff litlentab[Nlitlen];
208*74a4d8c2SCharles.Forsyth static Huff offtab[Noff];
209*74a4d8c2SCharles.Forsyth static Huff hofftab[Noff];
210*74a4d8c2SCharles.Forsyth
211*74a4d8c2SCharles.Forsyth /* bit reversal for brain dead endian swap in huffman codes */
212*74a4d8c2SCharles.Forsyth static uchar revtab[256];
213*74a4d8c2SCharles.Forsyth static ulong nlits;
214*74a4d8c2SCharles.Forsyth static ulong nmatches;
215*74a4d8c2SCharles.Forsyth
216*74a4d8c2SCharles.Forsyth int
deflateinit(void)217*74a4d8c2SCharles.Forsyth deflateinit(void)
218*74a4d8c2SCharles.Forsyth {
219*74a4d8c2SCharles.Forsyth ulong bitcount[MaxHuffBits];
220*74a4d8c2SCharles.Forsyth int i, j, ci, n;
221*74a4d8c2SCharles.Forsyth
222*74a4d8c2SCharles.Forsyth /* byte reverse table */
223*74a4d8c2SCharles.Forsyth for(i=0; i<256; i++)
224*74a4d8c2SCharles.Forsyth for(j=0; j<8; j++)
225*74a4d8c2SCharles.Forsyth if(i & (1<<j))
226*74a4d8c2SCharles.Forsyth revtab[i] |= 0x80 >> j;
227*74a4d8c2SCharles.Forsyth
228*74a4d8c2SCharles.Forsyth /* static Litlen bit lengths */
229*74a4d8c2SCharles.Forsyth for(i=0; i<144; i++)
230*74a4d8c2SCharles.Forsyth litlentab[i].bits = 8;
231*74a4d8c2SCharles.Forsyth for(i=144; i<256; i++)
232*74a4d8c2SCharles.Forsyth litlentab[i].bits = 9;
233*74a4d8c2SCharles.Forsyth for(i=256; i<280; i++)
234*74a4d8c2SCharles.Forsyth litlentab[i].bits = 7;
235*74a4d8c2SCharles.Forsyth for(i=280; i<Nlitlen; i++)
236*74a4d8c2SCharles.Forsyth litlentab[i].bits = 8;
237*74a4d8c2SCharles.Forsyth
238*74a4d8c2SCharles.Forsyth memset(bitcount, 0, sizeof(bitcount));
239*74a4d8c2SCharles.Forsyth bitcount[8] += 144 - 0;
240*74a4d8c2SCharles.Forsyth bitcount[9] += 256 - 144;
241*74a4d8c2SCharles.Forsyth bitcount[7] += 280 - 256;
242*74a4d8c2SCharles.Forsyth bitcount[8] += Nlitlen - 280;
243*74a4d8c2SCharles.Forsyth
244*74a4d8c2SCharles.Forsyth if(!hufftabinit(litlentab, Nlitlen, bitcount, 9))
245*74a4d8c2SCharles.Forsyth return FlateInternal;
246*74a4d8c2SCharles.Forsyth
247*74a4d8c2SCharles.Forsyth /* static offset bit lengths */
248*74a4d8c2SCharles.Forsyth for(i = 0; i < Noff; i++)
249*74a4d8c2SCharles.Forsyth offtab[i].bits = 5;
250*74a4d8c2SCharles.Forsyth
251*74a4d8c2SCharles.Forsyth memset(bitcount, 0, sizeof(bitcount));
252*74a4d8c2SCharles.Forsyth bitcount[5] = Noff;
253*74a4d8c2SCharles.Forsyth
254*74a4d8c2SCharles.Forsyth if(!hufftabinit(offtab, Noff, bitcount, 5))
255*74a4d8c2SCharles.Forsyth return FlateInternal;
256*74a4d8c2SCharles.Forsyth
257*74a4d8c2SCharles.Forsyth bitcount[0] = 0;
258*74a4d8c2SCharles.Forsyth bitcount[1] = 0;
259*74a4d8c2SCharles.Forsyth if(!mkgzprecode(hofftab, bitcount, 2, MaxHuffBits))
260*74a4d8c2SCharles.Forsyth return FlateInternal;
261*74a4d8c2SCharles.Forsyth
262*74a4d8c2SCharles.Forsyth /* conversion tables for lens & offs to codes */
263*74a4d8c2SCharles.Forsyth ci = 0;
264*74a4d8c2SCharles.Forsyth for(i = LenStart; i < 286; i++){
265*74a4d8c2SCharles.Forsyth n = ci + (1 << litlenextra[i - LenStart]);
266*74a4d8c2SCharles.Forsyth litlenbase[i - LenStart] = ci;
267*74a4d8c2SCharles.Forsyth for(; ci < n; ci++)
268*74a4d8c2SCharles.Forsyth lencode[ci] = i;
269*74a4d8c2SCharles.Forsyth }
270*74a4d8c2SCharles.Forsyth /* patch up special case for len MaxMatch */
271*74a4d8c2SCharles.Forsyth lencode[MaxMatch-MinMatch] = 285;
272*74a4d8c2SCharles.Forsyth litlenbase[285-LenStart] = MaxMatch-MinMatch;
273*74a4d8c2SCharles.Forsyth
274*74a4d8c2SCharles.Forsyth ci = 0;
275*74a4d8c2SCharles.Forsyth for(i = 0; i < 16; i++){
276*74a4d8c2SCharles.Forsyth n = ci + (1 << offextra[i]);
277*74a4d8c2SCharles.Forsyth offbase[i] = ci;
278*74a4d8c2SCharles.Forsyth for(; ci < n; ci++)
279*74a4d8c2SCharles.Forsyth offcode[ci] = i;
280*74a4d8c2SCharles.Forsyth }
281*74a4d8c2SCharles.Forsyth
282*74a4d8c2SCharles.Forsyth ci = ci >> 7;
283*74a4d8c2SCharles.Forsyth for(; i < 30; i++){
284*74a4d8c2SCharles.Forsyth n = ci + (1 << (offextra[i] - 7));
285*74a4d8c2SCharles.Forsyth offbase[i] = ci << 7;
286*74a4d8c2SCharles.Forsyth for(; ci < n; ci++)
287*74a4d8c2SCharles.Forsyth bigoffcode[ci] = i;
288*74a4d8c2SCharles.Forsyth }
289*74a4d8c2SCharles.Forsyth return FlateOk;
290*74a4d8c2SCharles.Forsyth }
291*74a4d8c2SCharles.Forsyth
292*74a4d8c2SCharles.Forsyth static void
deflatereset(LZstate * lz,int level,int debug)293*74a4d8c2SCharles.Forsyth deflatereset(LZstate *lz, int level, int debug)
294*74a4d8c2SCharles.Forsyth {
295*74a4d8c2SCharles.Forsyth memset(lz->nexts, 0, sizeof lz->nexts);
296*74a4d8c2SCharles.Forsyth memset(lz->hash, 0, sizeof lz->hash);
297*74a4d8c2SCharles.Forsyth lz->totr = 0;
298*74a4d8c2SCharles.Forsyth lz->totw = 0;
299*74a4d8c2SCharles.Forsyth lz->pos = 0;
300*74a4d8c2SCharles.Forsyth lz->avail = 0;
301*74a4d8c2SCharles.Forsyth lz->out = lz->obuf;
302*74a4d8c2SCharles.Forsyth lz->eout = &lz->obuf[DeflateOut];
303*74a4d8c2SCharles.Forsyth lz->prevlen = MinMatch - 1;
304*74a4d8c2SCharles.Forsyth lz->prevoff = 0;
305*74a4d8c2SCharles.Forsyth lz->now = MaxOff + 1;
306*74a4d8c2SCharles.Forsyth lz->dot = lz->now;
307*74a4d8c2SCharles.Forsyth lz->bits = 0;
308*74a4d8c2SCharles.Forsyth lz->nbits = 0;
309*74a4d8c2SCharles.Forsyth lz->maxcheck = (1 << level);
310*74a4d8c2SCharles.Forsyth lz->maxcheck -= lz->maxcheck >> 2;
311*74a4d8c2SCharles.Forsyth if(lz->maxcheck < 2)
312*74a4d8c2SCharles.Forsyth lz->maxcheck = 2;
313*74a4d8c2SCharles.Forsyth else if(lz->maxcheck > 1024)
314*74a4d8c2SCharles.Forsyth lz->maxcheck = 1024;
315*74a4d8c2SCharles.Forsyth
316*74a4d8c2SCharles.Forsyth lz->debug = debug;
317*74a4d8c2SCharles.Forsyth }
318*74a4d8c2SCharles.Forsyth
319*74a4d8c2SCharles.Forsyth int
deflate(void * wr,int (* w)(void *,void *,int),void * rr,int (* r)(void *,void *,int),int level,int debug)320*74a4d8c2SCharles.Forsyth deflate(void *wr, int (*w)(void*, void*, int), void *rr, int (*r)(void*, void*, int), int level, int debug)
321*74a4d8c2SCharles.Forsyth {
322*74a4d8c2SCharles.Forsyth LZstate *lz;
323*74a4d8c2SCharles.Forsyth LZblock *lzb;
324*74a4d8c2SCharles.Forsyth int ok;
325*74a4d8c2SCharles.Forsyth
326*74a4d8c2SCharles.Forsyth lz = malloc(sizeof *lz + sizeof *lzb);
327*74a4d8c2SCharles.Forsyth if(lz == nil)
328*74a4d8c2SCharles.Forsyth return FlateNoMem;
329*74a4d8c2SCharles.Forsyth lzb = (LZblock*)&lz[1];
330*74a4d8c2SCharles.Forsyth
331*74a4d8c2SCharles.Forsyth deflatereset(lz, level, debug);
332*74a4d8c2SCharles.Forsyth lz->w = w;
333*74a4d8c2SCharles.Forsyth lz->wr = wr;
334*74a4d8c2SCharles.Forsyth lz->wbad = 0;
335*74a4d8c2SCharles.Forsyth lz->rbad = 0;
336*74a4d8c2SCharles.Forsyth lz->eof = 0;
337*74a4d8c2SCharles.Forsyth ok = FlateOk;
338*74a4d8c2SCharles.Forsyth while(!lz->eof || lz->avail){
339*74a4d8c2SCharles.Forsyth ok = deflateb(lz, lzb, rr, r);
340*74a4d8c2SCharles.Forsyth if(ok != FlateOk)
341*74a4d8c2SCharles.Forsyth break;
342*74a4d8c2SCharles.Forsyth }
343*74a4d8c2SCharles.Forsyth if(ok == FlateOk && lz->rbad)
344*74a4d8c2SCharles.Forsyth ok = FlateInputFail;
345*74a4d8c2SCharles.Forsyth if(ok == FlateOk && lz->wbad)
346*74a4d8c2SCharles.Forsyth ok = FlateOutputFail;
347*74a4d8c2SCharles.Forsyth free(lz);
348*74a4d8c2SCharles.Forsyth return ok;
349*74a4d8c2SCharles.Forsyth }
350*74a4d8c2SCharles.Forsyth
351*74a4d8c2SCharles.Forsyth static int
deflateb(LZstate * lz,LZblock * lzb,void * rr,int (* r)(void *,void *,int))352*74a4d8c2SCharles.Forsyth deflateb(LZstate *lz, LZblock *lzb, void *rr, int (*r)(void*, void*, int))
353*74a4d8c2SCharles.Forsyth {
354*74a4d8c2SCharles.Forsyth Dyncode dyncode, hdyncode;
355*74a4d8c2SCharles.Forsyth Huff dlitlentab[Nlitlen], dofftab[Noff], hlitlentab[Nlitlen];
356*74a4d8c2SCharles.Forsyth ulong litcount[Nlitlen];
357*74a4d8c2SCharles.Forsyth long nunc, ndyn, nfix, nhuff;
358*74a4d8c2SCharles.Forsyth uchar *slop, *hslop;
359*74a4d8c2SCharles.Forsyth ulong ep;
360*74a4d8c2SCharles.Forsyth int i, n, m, mm, nslop;
361*74a4d8c2SCharles.Forsyth
362*74a4d8c2SCharles.Forsyth memset(lzb->litlencount, 0, sizeof lzb->litlencount);
363*74a4d8c2SCharles.Forsyth memset(lzb->offcount, 0, sizeof lzb->offcount);
364*74a4d8c2SCharles.Forsyth lzb->litlencount[DeflateEob]++;
365*74a4d8c2SCharles.Forsyth
366*74a4d8c2SCharles.Forsyth lzb->bytes = 0;
367*74a4d8c2SCharles.Forsyth lzb->eparse = lzb->parse;
368*74a4d8c2SCharles.Forsyth lzb->lastv = 0;
369*74a4d8c2SCharles.Forsyth lzb->excost = 0;
370*74a4d8c2SCharles.Forsyth
371*74a4d8c2SCharles.Forsyth slop = &lz->hist[lz->pos];
372*74a4d8c2SCharles.Forsyth n = lz->avail;
373*74a4d8c2SCharles.Forsyth while(n < DeflateBlock && (!lz->eof || lz->avail)){
374*74a4d8c2SCharles.Forsyth /*
375*74a4d8c2SCharles.Forsyth * fill the buffer as much as possible,
376*74a4d8c2SCharles.Forsyth * while leaving room for MaxOff history behind lz->pos,
377*74a4d8c2SCharles.Forsyth * and not reading more than we can handle.
378*74a4d8c2SCharles.Forsyth *
379*74a4d8c2SCharles.Forsyth * make sure we read at least HistSlop bytes.
380*74a4d8c2SCharles.Forsyth */
381*74a4d8c2SCharles.Forsyth if(!lz->eof){
382*74a4d8c2SCharles.Forsyth ep = lz->pos + lz->avail;
383*74a4d8c2SCharles.Forsyth if(ep >= HistBlock)
384*74a4d8c2SCharles.Forsyth ep -= HistBlock;
385*74a4d8c2SCharles.Forsyth m = HistBlock - MaxOff - lz->avail;
386*74a4d8c2SCharles.Forsyth if(m > HistBlock - n)
387*74a4d8c2SCharles.Forsyth m = HistBlock - n;
388*74a4d8c2SCharles.Forsyth if(m > (HistBlock + HistSlop) - ep)
389*74a4d8c2SCharles.Forsyth m = (HistBlock + HistSlop) - ep;
390*74a4d8c2SCharles.Forsyth if(m & ~(BlockSize - 1))
391*74a4d8c2SCharles.Forsyth m &= ~(BlockSize - 1);
392*74a4d8c2SCharles.Forsyth
393*74a4d8c2SCharles.Forsyth /*
394*74a4d8c2SCharles.Forsyth * be nice to the caller: stop reads that are too small.
395*74a4d8c2SCharles.Forsyth * can only get here when we've already filled the buffer some
396*74a4d8c2SCharles.Forsyth */
397*74a4d8c2SCharles.Forsyth if(m < HistSlop){
398*74a4d8c2SCharles.Forsyth if(!m || !lzb->bytes)
399*74a4d8c2SCharles.Forsyth return FlateInternal;
400*74a4d8c2SCharles.Forsyth break;
401*74a4d8c2SCharles.Forsyth }
402*74a4d8c2SCharles.Forsyth
403*74a4d8c2SCharles.Forsyth mm = (*r)(rr, &lz->hist[ep], m);
404*74a4d8c2SCharles.Forsyth if(mm > 0){
405*74a4d8c2SCharles.Forsyth /*
406*74a4d8c2SCharles.Forsyth * wrap data to end if we're read it from the beginning
407*74a4d8c2SCharles.Forsyth * this way, we don't have to wrap searches.
408*74a4d8c2SCharles.Forsyth *
409*74a4d8c2SCharles.Forsyth * wrap reads past the end to the beginning.
410*74a4d8c2SCharles.Forsyth * this way, we can guarantee minimum size reads.
411*74a4d8c2SCharles.Forsyth */
412*74a4d8c2SCharles.Forsyth if(ep < HistSlop)
413*74a4d8c2SCharles.Forsyth memmove(&lz->hist[ep + HistBlock], &lz->hist[ep], HistSlop - ep);
414*74a4d8c2SCharles.Forsyth else if(ep + mm > HistBlock)
415*74a4d8c2SCharles.Forsyth memmove(&lz->hist[0], &lz->hist[HistBlock], ep + mm - HistBlock);
416*74a4d8c2SCharles.Forsyth
417*74a4d8c2SCharles.Forsyth lz->totr += mm;
418*74a4d8c2SCharles.Forsyth n += mm;
419*74a4d8c2SCharles.Forsyth lz->avail += mm;
420*74a4d8c2SCharles.Forsyth }else{
421*74a4d8c2SCharles.Forsyth if(mm < 0)
422*74a4d8c2SCharles.Forsyth lz->rbad = 1;
423*74a4d8c2SCharles.Forsyth lz->eof = 1;
424*74a4d8c2SCharles.Forsyth }
425*74a4d8c2SCharles.Forsyth }
426*74a4d8c2SCharles.Forsyth ep = lz->pos + lz->avail;
427*74a4d8c2SCharles.Forsyth if(ep > HistSize)
428*74a4d8c2SCharles.Forsyth ep = HistSize;
429*74a4d8c2SCharles.Forsyth if(lzb->bytes + ep - lz->pos > DeflateMaxBlock)
430*74a4d8c2SCharles.Forsyth ep = lz->pos + DeflateMaxBlock - lzb->bytes;
431*74a4d8c2SCharles.Forsyth m = lzcomp(lz, lzb, &lz->hist[ep], lzb->eparse, lz->eof);
432*74a4d8c2SCharles.Forsyth lzb->bytes += m;
433*74a4d8c2SCharles.Forsyth lz->pos = (lz->pos + m) & (HistBlock - 1);
434*74a4d8c2SCharles.Forsyth lz->avail -= m;
435*74a4d8c2SCharles.Forsyth }
436*74a4d8c2SCharles.Forsyth if(lzb->lastv)
437*74a4d8c2SCharles.Forsyth *lzb->eparse++ = lzb->lastv;
438*74a4d8c2SCharles.Forsyth if(lzb->eparse > lzb->parse + nelem(lzb->parse))
439*74a4d8c2SCharles.Forsyth return FlateInternal;
440*74a4d8c2SCharles.Forsyth nunc = lzb->bytes;
441*74a4d8c2SCharles.Forsyth
442*74a4d8c2SCharles.Forsyth if(!mkgzprecode(dlitlentab, lzb->litlencount, Nlitlen, MaxHuffBits)
443*74a4d8c2SCharles.Forsyth || !mkgzprecode(dofftab, lzb->offcount, Noff, MaxHuffBits))
444*74a4d8c2SCharles.Forsyth return FlateInternal;
445*74a4d8c2SCharles.Forsyth
446*74a4d8c2SCharles.Forsyth ndyn = huffcodes(&dyncode, dlitlentab, dofftab);
447*74a4d8c2SCharles.Forsyth if(ndyn < 0)
448*74a4d8c2SCharles.Forsyth return FlateInternal;
449*74a4d8c2SCharles.Forsyth ndyn += bitcost(dlitlentab, lzb->litlencount, Nlitlen)
450*74a4d8c2SCharles.Forsyth + bitcost(dofftab, lzb->offcount, Noff)
451*74a4d8c2SCharles.Forsyth + lzb->excost;
452*74a4d8c2SCharles.Forsyth
453*74a4d8c2SCharles.Forsyth memset(litcount, 0, sizeof litcount);
454*74a4d8c2SCharles.Forsyth
455*74a4d8c2SCharles.Forsyth nslop = nunc;
456*74a4d8c2SCharles.Forsyth if(nslop > &lz->hist[HistSize] - slop)
457*74a4d8c2SCharles.Forsyth nslop = &lz->hist[HistSize] - slop;
458*74a4d8c2SCharles.Forsyth
459*74a4d8c2SCharles.Forsyth for(i = 0; i < nslop; i++)
460*74a4d8c2SCharles.Forsyth litcount[slop[i]]++;
461*74a4d8c2SCharles.Forsyth hslop = &lz->hist[HistSlop - nslop];
462*74a4d8c2SCharles.Forsyth for(; i < nunc; i++)
463*74a4d8c2SCharles.Forsyth litcount[hslop[i]]++;
464*74a4d8c2SCharles.Forsyth litcount[DeflateEob]++;
465*74a4d8c2SCharles.Forsyth
466*74a4d8c2SCharles.Forsyth if(!mkgzprecode(hlitlentab, litcount, Nlitlen, MaxHuffBits))
467*74a4d8c2SCharles.Forsyth return FlateInternal;
468*74a4d8c2SCharles.Forsyth nhuff = huffcodes(&hdyncode, hlitlentab, hofftab);
469*74a4d8c2SCharles.Forsyth if(nhuff < 0)
470*74a4d8c2SCharles.Forsyth return FlateInternal;
471*74a4d8c2SCharles.Forsyth nhuff += bitcost(hlitlentab, litcount, Nlitlen);
472*74a4d8c2SCharles.Forsyth
473*74a4d8c2SCharles.Forsyth nfix = bitcost(litlentab, lzb->litlencount, Nlitlen)
474*74a4d8c2SCharles.Forsyth + bitcost(offtab, lzb->offcount, Noff)
475*74a4d8c2SCharles.Forsyth + lzb->excost;
476*74a4d8c2SCharles.Forsyth
477*74a4d8c2SCharles.Forsyth lzput(lz, lz->eof && !lz->avail, 1);
478*74a4d8c2SCharles.Forsyth
479*74a4d8c2SCharles.Forsyth if(lz->debug){
480*74a4d8c2SCharles.Forsyth fprint(2, "block: bytes=%lud entries=%ld extra bits=%d\n\tuncompressed=%lud fixed=%lud dynamic=%lud huffman=%lud\n",
481*74a4d8c2SCharles.Forsyth nunc, lzb->eparse - lzb->parse, lzb->excost, (nunc + 4) * 8, nfix, ndyn, nhuff);
482*74a4d8c2SCharles.Forsyth fprint(2, "\tnlit=%lud matches=%lud eof=%d\n", nlits, nmatches, lz->eof && !lz->avail);
483*74a4d8c2SCharles.Forsyth }
484*74a4d8c2SCharles.Forsyth
485*74a4d8c2SCharles.Forsyth if((nunc + 4) * 8 < ndyn && (nunc + 4) * 8 < nfix && (nunc + 4) * 8 < nhuff){
486*74a4d8c2SCharles.Forsyth lzput(lz, DeflateUnc, 2);
487*74a4d8c2SCharles.Forsyth lzflushbits(lz);
488*74a4d8c2SCharles.Forsyth
489*74a4d8c2SCharles.Forsyth lzput(lz, nunc & 0xff, 8);
490*74a4d8c2SCharles.Forsyth lzput(lz, (nunc >> 8) & 0xff, 8);
491*74a4d8c2SCharles.Forsyth lzput(lz, ~nunc & 0xff, 8);
492*74a4d8c2SCharles.Forsyth lzput(lz, (~nunc >> 8) & 0xff, 8);
493*74a4d8c2SCharles.Forsyth lzflush(lz);
494*74a4d8c2SCharles.Forsyth
495*74a4d8c2SCharles.Forsyth lzwrite(lz, slop, nslop);
496*74a4d8c2SCharles.Forsyth lzwrite(lz, &lz->hist[HistSlop], nunc - nslop);
497*74a4d8c2SCharles.Forsyth }else if(ndyn < nfix && ndyn < nhuff){
498*74a4d8c2SCharles.Forsyth lzput(lz, DeflateDyn, 2);
499*74a4d8c2SCharles.Forsyth
500*74a4d8c2SCharles.Forsyth wrdyncode(lz, &dyncode);
501*74a4d8c2SCharles.Forsyth wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, dlitlentab, dofftab);
502*74a4d8c2SCharles.Forsyth lzput(lz, dlitlentab[DeflateEob].encode, dlitlentab[DeflateEob].bits);
503*74a4d8c2SCharles.Forsyth }else if(nhuff < nfix){
504*74a4d8c2SCharles.Forsyth lzput(lz, DeflateDyn, 2);
505*74a4d8c2SCharles.Forsyth
506*74a4d8c2SCharles.Forsyth wrdyncode(lz, &hdyncode);
507*74a4d8c2SCharles.Forsyth
508*74a4d8c2SCharles.Forsyth m = 0;
509*74a4d8c2SCharles.Forsyth for(i = nunc; i > MaxLitRun; i -= MaxLitRun)
510*74a4d8c2SCharles.Forsyth lzb->parse[m++] = MaxLitRun;
511*74a4d8c2SCharles.Forsyth lzb->parse[m++] = i;
512*74a4d8c2SCharles.Forsyth
513*74a4d8c2SCharles.Forsyth wrblock(lz, slop - lz->hist, lzb->parse, lzb->parse + m, hlitlentab, hofftab);
514*74a4d8c2SCharles.Forsyth lzput(lz, hlitlentab[DeflateEob].encode, hlitlentab[DeflateEob].bits);
515*74a4d8c2SCharles.Forsyth }else{
516*74a4d8c2SCharles.Forsyth lzput(lz, DeflateFix, 2);
517*74a4d8c2SCharles.Forsyth
518*74a4d8c2SCharles.Forsyth wrblock(lz, slop - lz->hist, lzb->parse, lzb->eparse, litlentab, offtab);
519*74a4d8c2SCharles.Forsyth lzput(lz, litlentab[DeflateEob].encode, litlentab[DeflateEob].bits);
520*74a4d8c2SCharles.Forsyth }
521*74a4d8c2SCharles.Forsyth
522*74a4d8c2SCharles.Forsyth if(lz->eof && !lz->avail){
523*74a4d8c2SCharles.Forsyth lzflushbits(lz);
524*74a4d8c2SCharles.Forsyth lzflush(lz);
525*74a4d8c2SCharles.Forsyth }
526*74a4d8c2SCharles.Forsyth return FlateOk;
527*74a4d8c2SCharles.Forsyth }
528*74a4d8c2SCharles.Forsyth
529*74a4d8c2SCharles.Forsyth static void
lzwrite(LZstate * lz,void * buf,int n)530*74a4d8c2SCharles.Forsyth lzwrite(LZstate *lz, void *buf, int n)
531*74a4d8c2SCharles.Forsyth {
532*74a4d8c2SCharles.Forsyth int nw;
533*74a4d8c2SCharles.Forsyth
534*74a4d8c2SCharles.Forsyth if(n && lz->w){
535*74a4d8c2SCharles.Forsyth nw = (*lz->w)(lz->wr, buf, n);
536*74a4d8c2SCharles.Forsyth if(nw != n){
537*74a4d8c2SCharles.Forsyth lz->w = nil;
538*74a4d8c2SCharles.Forsyth lz->wbad = 1;
539*74a4d8c2SCharles.Forsyth }else
540*74a4d8c2SCharles.Forsyth lz->totw += n;
541*74a4d8c2SCharles.Forsyth }
542*74a4d8c2SCharles.Forsyth }
543*74a4d8c2SCharles.Forsyth
544*74a4d8c2SCharles.Forsyth static void
lzflush(LZstate * lz)545*74a4d8c2SCharles.Forsyth lzflush(LZstate *lz)
546*74a4d8c2SCharles.Forsyth {
547*74a4d8c2SCharles.Forsyth lzwrite(lz, lz->obuf, lz->out - lz->obuf);
548*74a4d8c2SCharles.Forsyth lz->out = lz->obuf;
549*74a4d8c2SCharles.Forsyth }
550*74a4d8c2SCharles.Forsyth
551*74a4d8c2SCharles.Forsyth static void
lzput(LZstate * lz,ulong bits,int nbits)552*74a4d8c2SCharles.Forsyth lzput(LZstate *lz, ulong bits, int nbits)
553*74a4d8c2SCharles.Forsyth {
554*74a4d8c2SCharles.Forsyth bits = (bits << lz->nbits) | lz->bits;
555*74a4d8c2SCharles.Forsyth for(nbits += lz->nbits; nbits >= 8; nbits -= 8){
556*74a4d8c2SCharles.Forsyth *lz->out++ = bits;
557*74a4d8c2SCharles.Forsyth if(lz->out == lz->eout)
558*74a4d8c2SCharles.Forsyth lzflush(lz);
559*74a4d8c2SCharles.Forsyth bits >>= 8;
560*74a4d8c2SCharles.Forsyth }
561*74a4d8c2SCharles.Forsyth lz->bits = bits;
562*74a4d8c2SCharles.Forsyth lz->nbits = nbits;
563*74a4d8c2SCharles.Forsyth }
564*74a4d8c2SCharles.Forsyth
565*74a4d8c2SCharles.Forsyth static void
lzflushbits(LZstate * lz)566*74a4d8c2SCharles.Forsyth lzflushbits(LZstate *lz)
567*74a4d8c2SCharles.Forsyth {
568*74a4d8c2SCharles.Forsyth if(lz->nbits)
569*74a4d8c2SCharles.Forsyth lzput(lz, 0, 8 - (lz->nbits & 7));
570*74a4d8c2SCharles.Forsyth }
571*74a4d8c2SCharles.Forsyth
572*74a4d8c2SCharles.Forsyth /*
573*74a4d8c2SCharles.Forsyth * write out a block of n samples,
574*74a4d8c2SCharles.Forsyth * given lz encoding and counts for huffman tables
575*74a4d8c2SCharles.Forsyth */
576*74a4d8c2SCharles.Forsyth static void
wrblock(LZstate * out,int litoff,ushort * soff,ushort * eoff,Huff * litlentab,Huff * offtab)577*74a4d8c2SCharles.Forsyth wrblock(LZstate *out, int litoff, ushort *soff, ushort *eoff, Huff *litlentab, Huff *offtab)
578*74a4d8c2SCharles.Forsyth {
579*74a4d8c2SCharles.Forsyth ushort *off;
580*74a4d8c2SCharles.Forsyth int i, run, offset, lit, len, c;
581*74a4d8c2SCharles.Forsyth
582*74a4d8c2SCharles.Forsyth if(out->debug > 2){
583*74a4d8c2SCharles.Forsyth for(off = soff; off < eoff; ){
584*74a4d8c2SCharles.Forsyth offset = *off++;
585*74a4d8c2SCharles.Forsyth run = offset & MaxLitRun;
586*74a4d8c2SCharles.Forsyth if(run){
587*74a4d8c2SCharles.Forsyth for(i = 0; i < run; i++){
588*74a4d8c2SCharles.Forsyth lit = out->hist[litoff & (HistBlock - 1)];
589*74a4d8c2SCharles.Forsyth litoff++;
590*74a4d8c2SCharles.Forsyth fprint(2, "\tlit %.2ux %c\n", lit, lit);
591*74a4d8c2SCharles.Forsyth }
592*74a4d8c2SCharles.Forsyth if(!(offset & LenFlag))
593*74a4d8c2SCharles.Forsyth continue;
594*74a4d8c2SCharles.Forsyth len = offset >> LenShift;
595*74a4d8c2SCharles.Forsyth offset = *off++;
596*74a4d8c2SCharles.Forsyth }else if(offset & LenFlag){
597*74a4d8c2SCharles.Forsyth len = offset >> LenShift;
598*74a4d8c2SCharles.Forsyth offset = *off++;
599*74a4d8c2SCharles.Forsyth }else{
600*74a4d8c2SCharles.Forsyth len = 0;
601*74a4d8c2SCharles.Forsyth offset >>= LenShift;
602*74a4d8c2SCharles.Forsyth }
603*74a4d8c2SCharles.Forsyth litoff += len + MinMatch;
604*74a4d8c2SCharles.Forsyth fprint(2, "\t<%d, %d>\n", offset + 1, len + MinMatch);
605*74a4d8c2SCharles.Forsyth }
606*74a4d8c2SCharles.Forsyth }
607*74a4d8c2SCharles.Forsyth
608*74a4d8c2SCharles.Forsyth for(off = soff; off < eoff; ){
609*74a4d8c2SCharles.Forsyth offset = *off++;
610*74a4d8c2SCharles.Forsyth run = offset & MaxLitRun;
611*74a4d8c2SCharles.Forsyth if(run){
612*74a4d8c2SCharles.Forsyth for(i = 0; i < run; i++){
613*74a4d8c2SCharles.Forsyth lit = out->hist[litoff & (HistBlock - 1)];
614*74a4d8c2SCharles.Forsyth litoff++;
615*74a4d8c2SCharles.Forsyth lzput(out, litlentab[lit].encode, litlentab[lit].bits);
616*74a4d8c2SCharles.Forsyth }
617*74a4d8c2SCharles.Forsyth if(!(offset & LenFlag))
618*74a4d8c2SCharles.Forsyth continue;
619*74a4d8c2SCharles.Forsyth len = offset >> LenShift;
620*74a4d8c2SCharles.Forsyth offset = *off++;
621*74a4d8c2SCharles.Forsyth }else if(offset & LenFlag){
622*74a4d8c2SCharles.Forsyth len = offset >> LenShift;
623*74a4d8c2SCharles.Forsyth offset = *off++;
624*74a4d8c2SCharles.Forsyth }else{
625*74a4d8c2SCharles.Forsyth len = 0;
626*74a4d8c2SCharles.Forsyth offset >>= LenShift;
627*74a4d8c2SCharles.Forsyth }
628*74a4d8c2SCharles.Forsyth litoff += len + MinMatch;
629*74a4d8c2SCharles.Forsyth c = lencode[len];
630*74a4d8c2SCharles.Forsyth lzput(out, litlentab[c].encode, litlentab[c].bits);
631*74a4d8c2SCharles.Forsyth c -= LenStart;
632*74a4d8c2SCharles.Forsyth if(litlenextra[c])
633*74a4d8c2SCharles.Forsyth lzput(out, len - litlenbase[c], litlenextra[c]);
634*74a4d8c2SCharles.Forsyth
635*74a4d8c2SCharles.Forsyth if(offset < MaxOffCode)
636*74a4d8c2SCharles.Forsyth c = offcode[offset];
637*74a4d8c2SCharles.Forsyth else
638*74a4d8c2SCharles.Forsyth c = bigoffcode[offset >> 7];
639*74a4d8c2SCharles.Forsyth lzput(out, offtab[c].encode, offtab[c].bits);
640*74a4d8c2SCharles.Forsyth if(offextra[c])
641*74a4d8c2SCharles.Forsyth lzput(out, offset - offbase[c], offextra[c]);
642*74a4d8c2SCharles.Forsyth }
643*74a4d8c2SCharles.Forsyth }
644*74a4d8c2SCharles.Forsyth
645*74a4d8c2SCharles.Forsyth /*
646*74a4d8c2SCharles.Forsyth * look for the longest, closest string which matches
647*74a4d8c2SCharles.Forsyth * the next prefix. the clever part here is looking for
648*74a4d8c2SCharles.Forsyth * a string 1 longer than the previous best match.
649*74a4d8c2SCharles.Forsyth *
650*74a4d8c2SCharles.Forsyth * follows the recommendation of limiting number of chains
651*74a4d8c2SCharles.Forsyth * which are checked. this appears to be the best heuristic.
652*74a4d8c2SCharles.Forsyth */
653*74a4d8c2SCharles.Forsyth static int
lzmatch(int now,int then,uchar * p,uchar * es,ushort * nexts,uchar * hist,int runlen,int check,int * m)654*74a4d8c2SCharles.Forsyth lzmatch(int now, int then, uchar *p, uchar *es, ushort *nexts, uchar *hist, int runlen, int check, int *m)
655*74a4d8c2SCharles.Forsyth {
656*74a4d8c2SCharles.Forsyth uchar *s, *t;
657*74a4d8c2SCharles.Forsyth int ml, off, last;
658*74a4d8c2SCharles.Forsyth
659*74a4d8c2SCharles.Forsyth ml = check;
660*74a4d8c2SCharles.Forsyth if(runlen >= 8)
661*74a4d8c2SCharles.Forsyth check >>= 2;
662*74a4d8c2SCharles.Forsyth *m = 0;
663*74a4d8c2SCharles.Forsyth if(p + runlen >= es)
664*74a4d8c2SCharles.Forsyth return runlen;
665*74a4d8c2SCharles.Forsyth last = 0;
666*74a4d8c2SCharles.Forsyth for(; check-- > 0; then = nexts[then & (MaxOff-1)]){
667*74a4d8c2SCharles.Forsyth off = (ushort)(now - then);
668*74a4d8c2SCharles.Forsyth if(off <= last || off > MaxOff)
669*74a4d8c2SCharles.Forsyth break;
670*74a4d8c2SCharles.Forsyth s = p + runlen;
671*74a4d8c2SCharles.Forsyth t = hist + (((p - hist) - off) & (HistBlock-1));
672*74a4d8c2SCharles.Forsyth t += runlen;
673*74a4d8c2SCharles.Forsyth for(; s >= p; s--){
674*74a4d8c2SCharles.Forsyth if(*s != *t)
675*74a4d8c2SCharles.Forsyth goto matchloop;
676*74a4d8c2SCharles.Forsyth t--;
677*74a4d8c2SCharles.Forsyth }
678*74a4d8c2SCharles.Forsyth
679*74a4d8c2SCharles.Forsyth /*
680*74a4d8c2SCharles.Forsyth * we have a new best match.
681*74a4d8c2SCharles.Forsyth * extend it to it's maximum length
682*74a4d8c2SCharles.Forsyth */
683*74a4d8c2SCharles.Forsyth t += runlen + 2;
684*74a4d8c2SCharles.Forsyth s += runlen + 2;
685*74a4d8c2SCharles.Forsyth for(; s < es; s++){
686*74a4d8c2SCharles.Forsyth if(*s != *t)
687*74a4d8c2SCharles.Forsyth break;
688*74a4d8c2SCharles.Forsyth t++;
689*74a4d8c2SCharles.Forsyth }
690*74a4d8c2SCharles.Forsyth runlen = s - p;
691*74a4d8c2SCharles.Forsyth *m = off - 1;
692*74a4d8c2SCharles.Forsyth if(s == es || runlen > ml)
693*74a4d8c2SCharles.Forsyth break;
694*74a4d8c2SCharles.Forsyth matchloop:;
695*74a4d8c2SCharles.Forsyth last = off;
696*74a4d8c2SCharles.Forsyth }
697*74a4d8c2SCharles.Forsyth return runlen;
698*74a4d8c2SCharles.Forsyth }
699*74a4d8c2SCharles.Forsyth
700*74a4d8c2SCharles.Forsyth static int
lzcomp(LZstate * lz,LZblock * lzb,uchar * ep,ushort * parse,int finish)701*74a4d8c2SCharles.Forsyth lzcomp(LZstate *lz, LZblock *lzb, uchar *ep, ushort *parse, int finish)
702*74a4d8c2SCharles.Forsyth {
703*74a4d8c2SCharles.Forsyth ulong cont, excost, *litlencount, *offcount;
704*74a4d8c2SCharles.Forsyth uchar *p, *q, *s, *es;
705*74a4d8c2SCharles.Forsyth ushort *nexts, *hash;
706*74a4d8c2SCharles.Forsyth int v, i, h, runlen, n, now, then, m, prevlen, prevoff, maxdefer;
707*74a4d8c2SCharles.Forsyth
708*74a4d8c2SCharles.Forsyth litlencount = lzb->litlencount;
709*74a4d8c2SCharles.Forsyth offcount = lzb->offcount;
710*74a4d8c2SCharles.Forsyth nexts = lz->nexts;
711*74a4d8c2SCharles.Forsyth hash = lz->hash;
712*74a4d8c2SCharles.Forsyth now = lz->now;
713*74a4d8c2SCharles.Forsyth
714*74a4d8c2SCharles.Forsyth p = &lz->hist[lz->pos];
715*74a4d8c2SCharles.Forsyth if(lz->prevlen != MinMatch - 1)
716*74a4d8c2SCharles.Forsyth p++;
717*74a4d8c2SCharles.Forsyth
718*74a4d8c2SCharles.Forsyth /*
719*74a4d8c2SCharles.Forsyth * hash in the links for any hanging link positions,
720*74a4d8c2SCharles.Forsyth * and calculate the hash for the current position.
721*74a4d8c2SCharles.Forsyth */
722*74a4d8c2SCharles.Forsyth n = MinMatch;
723*74a4d8c2SCharles.Forsyth if(n > ep - p)
724*74a4d8c2SCharles.Forsyth n = ep - p;
725*74a4d8c2SCharles.Forsyth cont = 0;
726*74a4d8c2SCharles.Forsyth for(i = 0; i < n - 1; i++){
727*74a4d8c2SCharles.Forsyth m = now - ((MinMatch-1) - i);
728*74a4d8c2SCharles.Forsyth if(m < lz->dot)
729*74a4d8c2SCharles.Forsyth continue;
730*74a4d8c2SCharles.Forsyth s = lz->hist + (((p - lz->hist) - (now - m)) & (HistBlock-1));
731*74a4d8c2SCharles.Forsyth
732*74a4d8c2SCharles.Forsyth cont = (s[0] << 16) | (s[1] << 8) | s[2];
733*74a4d8c2SCharles.Forsyth h = hashit(cont);
734*74a4d8c2SCharles.Forsyth prevoff = 0;
735*74a4d8c2SCharles.Forsyth for(then = hash[h]; ; then = nexts[then & (MaxOff-1)]){
736*74a4d8c2SCharles.Forsyth v = (ushort)(now - then);
737*74a4d8c2SCharles.Forsyth if(v <= prevoff || v >= (MinMatch-1) - i)
738*74a4d8c2SCharles.Forsyth break;
739*74a4d8c2SCharles.Forsyth prevoff = v;
740*74a4d8c2SCharles.Forsyth }
741*74a4d8c2SCharles.Forsyth if(then == (ushort)m)
742*74a4d8c2SCharles.Forsyth continue;
743*74a4d8c2SCharles.Forsyth nexts[m & (MaxOff-1)] = hash[h];
744*74a4d8c2SCharles.Forsyth hash[h] = m;
745*74a4d8c2SCharles.Forsyth }
746*74a4d8c2SCharles.Forsyth for(i = 0; i < n; i++)
747*74a4d8c2SCharles.Forsyth cont = (cont << 8) | p[i];
748*74a4d8c2SCharles.Forsyth
749*74a4d8c2SCharles.Forsyth /*
750*74a4d8c2SCharles.Forsyth * now must point to the index in the nexts array
751*74a4d8c2SCharles.Forsyth * corresponding to p's position in the history
752*74a4d8c2SCharles.Forsyth */
753*74a4d8c2SCharles.Forsyth prevlen = lz->prevlen;
754*74a4d8c2SCharles.Forsyth prevoff = lz->prevoff;
755*74a4d8c2SCharles.Forsyth maxdefer = lz->maxcheck >> 2;
756*74a4d8c2SCharles.Forsyth excost = 0;
757*74a4d8c2SCharles.Forsyth v = lzb->lastv;
758*74a4d8c2SCharles.Forsyth for(;;){
759*74a4d8c2SCharles.Forsyth es = p + MaxMatch;
760*74a4d8c2SCharles.Forsyth if(es > ep){
761*74a4d8c2SCharles.Forsyth if(!finish || p >= ep)
762*74a4d8c2SCharles.Forsyth break;
763*74a4d8c2SCharles.Forsyth es = ep;
764*74a4d8c2SCharles.Forsyth }
765*74a4d8c2SCharles.Forsyth
766*74a4d8c2SCharles.Forsyth h = hashit(cont);
767*74a4d8c2SCharles.Forsyth runlen = lzmatch(now, hash[h], p, es, nexts, lz->hist, prevlen, lz->maxcheck, &m);
768*74a4d8c2SCharles.Forsyth
769*74a4d8c2SCharles.Forsyth /*
770*74a4d8c2SCharles.Forsyth * back out of small matches too far in the past
771*74a4d8c2SCharles.Forsyth */
772*74a4d8c2SCharles.Forsyth if(runlen == MinMatch && m >= MinMatchMaxOff){
773*74a4d8c2SCharles.Forsyth runlen = MinMatch - 1;
774*74a4d8c2SCharles.Forsyth m = 0;
775*74a4d8c2SCharles.Forsyth }
776*74a4d8c2SCharles.Forsyth
777*74a4d8c2SCharles.Forsyth /*
778*74a4d8c2SCharles.Forsyth * record the encoding and increment counts for huffman trees
779*74a4d8c2SCharles.Forsyth * if we get a match, defer selecting it until we check for
780*74a4d8c2SCharles.Forsyth * a longer match at the next position.
781*74a4d8c2SCharles.Forsyth */
782*74a4d8c2SCharles.Forsyth if(prevlen >= runlen && prevlen != MinMatch - 1){
783*74a4d8c2SCharles.Forsyth /*
784*74a4d8c2SCharles.Forsyth * old match at least as good; use that one
785*74a4d8c2SCharles.Forsyth */
786*74a4d8c2SCharles.Forsyth n = prevlen - MinMatch;
787*74a4d8c2SCharles.Forsyth if(v || n){
788*74a4d8c2SCharles.Forsyth *parse++ = v | LenFlag | (n << LenShift);
789*74a4d8c2SCharles.Forsyth *parse++ = prevoff;
790*74a4d8c2SCharles.Forsyth }else
791*74a4d8c2SCharles.Forsyth *parse++ = prevoff << LenShift;
792*74a4d8c2SCharles.Forsyth v = 0;
793*74a4d8c2SCharles.Forsyth
794*74a4d8c2SCharles.Forsyth n = lencode[n];
795*74a4d8c2SCharles.Forsyth litlencount[n]++;
796*74a4d8c2SCharles.Forsyth excost += litlenextra[n - LenStart];
797*74a4d8c2SCharles.Forsyth
798*74a4d8c2SCharles.Forsyth if(prevoff < MaxOffCode)
799*74a4d8c2SCharles.Forsyth n = offcode[prevoff];
800*74a4d8c2SCharles.Forsyth else
801*74a4d8c2SCharles.Forsyth n = bigoffcode[prevoff >> 7];
802*74a4d8c2SCharles.Forsyth offcount[n]++;
803*74a4d8c2SCharles.Forsyth excost += offextra[n];
804*74a4d8c2SCharles.Forsyth
805*74a4d8c2SCharles.Forsyth runlen = prevlen - 1;
806*74a4d8c2SCharles.Forsyth prevlen = MinMatch - 1;
807*74a4d8c2SCharles.Forsyth nmatches++;
808*74a4d8c2SCharles.Forsyth }else if(runlen == MinMatch - 1){
809*74a4d8c2SCharles.Forsyth /*
810*74a4d8c2SCharles.Forsyth * no match; just put out the literal
811*74a4d8c2SCharles.Forsyth */
812*74a4d8c2SCharles.Forsyth if(++v == MaxLitRun){
813*74a4d8c2SCharles.Forsyth *parse++ = v;
814*74a4d8c2SCharles.Forsyth v = 0;
815*74a4d8c2SCharles.Forsyth }
816*74a4d8c2SCharles.Forsyth litlencount[*p]++;
817*74a4d8c2SCharles.Forsyth nlits++;
818*74a4d8c2SCharles.Forsyth runlen = 1;
819*74a4d8c2SCharles.Forsyth }else{
820*74a4d8c2SCharles.Forsyth if(prevlen != MinMatch - 1){
821*74a4d8c2SCharles.Forsyth /*
822*74a4d8c2SCharles.Forsyth * longer match now. output previous literal,
823*74a4d8c2SCharles.Forsyth * update current match, and try again
824*74a4d8c2SCharles.Forsyth */
825*74a4d8c2SCharles.Forsyth if(++v == MaxLitRun){
826*74a4d8c2SCharles.Forsyth *parse++ = v;
827*74a4d8c2SCharles.Forsyth v = 0;
828*74a4d8c2SCharles.Forsyth }
829*74a4d8c2SCharles.Forsyth litlencount[p[-1]]++;
830*74a4d8c2SCharles.Forsyth nlits++;
831*74a4d8c2SCharles.Forsyth }
832*74a4d8c2SCharles.Forsyth
833*74a4d8c2SCharles.Forsyth prevoff = m;
834*74a4d8c2SCharles.Forsyth
835*74a4d8c2SCharles.Forsyth if(runlen < maxdefer){
836*74a4d8c2SCharles.Forsyth prevlen = runlen;
837*74a4d8c2SCharles.Forsyth runlen = 1;
838*74a4d8c2SCharles.Forsyth }else{
839*74a4d8c2SCharles.Forsyth n = runlen - MinMatch;
840*74a4d8c2SCharles.Forsyth if(v || n){
841*74a4d8c2SCharles.Forsyth *parse++ = v | LenFlag | (n << LenShift);
842*74a4d8c2SCharles.Forsyth *parse++ = prevoff;
843*74a4d8c2SCharles.Forsyth }else
844*74a4d8c2SCharles.Forsyth *parse++ = prevoff << LenShift;
845*74a4d8c2SCharles.Forsyth v = 0;
846*74a4d8c2SCharles.Forsyth
847*74a4d8c2SCharles.Forsyth n = lencode[n];
848*74a4d8c2SCharles.Forsyth litlencount[n]++;
849*74a4d8c2SCharles.Forsyth excost += litlenextra[n - LenStart];
850*74a4d8c2SCharles.Forsyth
851*74a4d8c2SCharles.Forsyth if(prevoff < MaxOffCode)
852*74a4d8c2SCharles.Forsyth n = offcode[prevoff];
853*74a4d8c2SCharles.Forsyth else
854*74a4d8c2SCharles.Forsyth n = bigoffcode[prevoff >> 7];
855*74a4d8c2SCharles.Forsyth offcount[n]++;
856*74a4d8c2SCharles.Forsyth excost += offextra[n];
857*74a4d8c2SCharles.Forsyth
858*74a4d8c2SCharles.Forsyth prevlen = MinMatch - 1;
859*74a4d8c2SCharles.Forsyth nmatches++;
860*74a4d8c2SCharles.Forsyth }
861*74a4d8c2SCharles.Forsyth }
862*74a4d8c2SCharles.Forsyth
863*74a4d8c2SCharles.Forsyth /*
864*74a4d8c2SCharles.Forsyth * update the hash for the newly matched data
865*74a4d8c2SCharles.Forsyth * this is constructed so the link for the old
866*74a4d8c2SCharles.Forsyth * match in this position must be at the end of a chain,
867*74a4d8c2SCharles.Forsyth * and will expire when this match is added, ie it will
868*74a4d8c2SCharles.Forsyth * never be examined by the match loop.
869*74a4d8c2SCharles.Forsyth * add to the hash chain only if we have the real hash data.
870*74a4d8c2SCharles.Forsyth */
871*74a4d8c2SCharles.Forsyth for(q = p + runlen; p != q; p++){
872*74a4d8c2SCharles.Forsyth if(p + MinMatch <= ep){
873*74a4d8c2SCharles.Forsyth h = hashit(cont);
874*74a4d8c2SCharles.Forsyth nexts[now & (MaxOff-1)] = hash[h];
875*74a4d8c2SCharles.Forsyth hash[h] = now;
876*74a4d8c2SCharles.Forsyth if(p + MinMatch < ep)
877*74a4d8c2SCharles.Forsyth cont = (cont << 8) | p[MinMatch];
878*74a4d8c2SCharles.Forsyth }
879*74a4d8c2SCharles.Forsyth now++;
880*74a4d8c2SCharles.Forsyth }
881*74a4d8c2SCharles.Forsyth }
882*74a4d8c2SCharles.Forsyth
883*74a4d8c2SCharles.Forsyth /*
884*74a4d8c2SCharles.Forsyth * we can just store away the lazy state and
885*74a4d8c2SCharles.Forsyth * pick it up next time. the last block will have finish set
886*74a4d8c2SCharles.Forsyth * so we won't have any pending matches
887*74a4d8c2SCharles.Forsyth * however, we need to correct for how much we've encoded
888*74a4d8c2SCharles.Forsyth */
889*74a4d8c2SCharles.Forsyth if(prevlen != MinMatch - 1)
890*74a4d8c2SCharles.Forsyth p--;
891*74a4d8c2SCharles.Forsyth
892*74a4d8c2SCharles.Forsyth lzb->excost += excost;
893*74a4d8c2SCharles.Forsyth lzb->eparse = parse;
894*74a4d8c2SCharles.Forsyth lzb->lastv = v;
895*74a4d8c2SCharles.Forsyth
896*74a4d8c2SCharles.Forsyth lz->now = now;
897*74a4d8c2SCharles.Forsyth lz->prevlen = prevlen;
898*74a4d8c2SCharles.Forsyth lz->prevoff = prevoff;
899*74a4d8c2SCharles.Forsyth
900*74a4d8c2SCharles.Forsyth return p - &lz->hist[lz->pos];
901*74a4d8c2SCharles.Forsyth }
902*74a4d8c2SCharles.Forsyth
903*74a4d8c2SCharles.Forsyth /*
904*74a4d8c2SCharles.Forsyth * make up the dynamic code tables, and return the number of bits
905*74a4d8c2SCharles.Forsyth * needed to transmit them.
906*74a4d8c2SCharles.Forsyth */
907*74a4d8c2SCharles.Forsyth static int
huffcodes(Dyncode * dc,Huff * littab,Huff * offtab)908*74a4d8c2SCharles.Forsyth huffcodes(Dyncode *dc, Huff *littab, Huff *offtab)
909*74a4d8c2SCharles.Forsyth {
910*74a4d8c2SCharles.Forsyth Huff *codetab;
911*74a4d8c2SCharles.Forsyth uchar *codes, *codeaux;
912*74a4d8c2SCharles.Forsyth ulong codecount[Nclen], excost;
913*74a4d8c2SCharles.Forsyth int i, n, m, v, c, nlit, noff, ncode, nclen;
914*74a4d8c2SCharles.Forsyth
915*74a4d8c2SCharles.Forsyth codetab = dc->codetab;
916*74a4d8c2SCharles.Forsyth codes = dc->codes;
917*74a4d8c2SCharles.Forsyth codeaux = dc->codeaux;
918*74a4d8c2SCharles.Forsyth
919*74a4d8c2SCharles.Forsyth /*
920*74a4d8c2SCharles.Forsyth * trim the sizes of the tables
921*74a4d8c2SCharles.Forsyth */
922*74a4d8c2SCharles.Forsyth for(nlit = Nlitlen; nlit > 257 && littab[nlit-1].bits == 0; nlit--)
923*74a4d8c2SCharles.Forsyth ;
924*74a4d8c2SCharles.Forsyth for(noff = Noff; noff > 1 && offtab[noff-1].bits == 0; noff--)
925*74a4d8c2SCharles.Forsyth ;
926*74a4d8c2SCharles.Forsyth
927*74a4d8c2SCharles.Forsyth /*
928*74a4d8c2SCharles.Forsyth * make the code-length code
929*74a4d8c2SCharles.Forsyth */
930*74a4d8c2SCharles.Forsyth for(i = 0; i < nlit; i++)
931*74a4d8c2SCharles.Forsyth codes[i] = littab[i].bits;
932*74a4d8c2SCharles.Forsyth for(i = 0; i < noff; i++)
933*74a4d8c2SCharles.Forsyth codes[i + nlit] = offtab[i].bits;
934*74a4d8c2SCharles.Forsyth
935*74a4d8c2SCharles.Forsyth /*
936*74a4d8c2SCharles.Forsyth * run-length compress the code-length code
937*74a4d8c2SCharles.Forsyth */
938*74a4d8c2SCharles.Forsyth excost = 0;
939*74a4d8c2SCharles.Forsyth c = 0;
940*74a4d8c2SCharles.Forsyth ncode = nlit+noff;
941*74a4d8c2SCharles.Forsyth for(i = 0; i < ncode; ){
942*74a4d8c2SCharles.Forsyth n = i + 1;
943*74a4d8c2SCharles.Forsyth v = codes[i];
944*74a4d8c2SCharles.Forsyth while(n < ncode && v == codes[n])
945*74a4d8c2SCharles.Forsyth n++;
946*74a4d8c2SCharles.Forsyth n -= i;
947*74a4d8c2SCharles.Forsyth i += n;
948*74a4d8c2SCharles.Forsyth if(v == 0){
949*74a4d8c2SCharles.Forsyth while(n >= 11){
950*74a4d8c2SCharles.Forsyth m = n;
951*74a4d8c2SCharles.Forsyth if(m > 138)
952*74a4d8c2SCharles.Forsyth m = 138;
953*74a4d8c2SCharles.Forsyth codes[c] = 18;
954*74a4d8c2SCharles.Forsyth codeaux[c++] = m - 11;
955*74a4d8c2SCharles.Forsyth n -= m;
956*74a4d8c2SCharles.Forsyth excost += 7;
957*74a4d8c2SCharles.Forsyth }
958*74a4d8c2SCharles.Forsyth if(n >= 3){
959*74a4d8c2SCharles.Forsyth codes[c] = 17;
960*74a4d8c2SCharles.Forsyth codeaux[c++] = n - 3;
961*74a4d8c2SCharles.Forsyth n = 0;
962*74a4d8c2SCharles.Forsyth excost += 3;
963*74a4d8c2SCharles.Forsyth }
964*74a4d8c2SCharles.Forsyth }
965*74a4d8c2SCharles.Forsyth while(n--){
966*74a4d8c2SCharles.Forsyth codes[c++] = v;
967*74a4d8c2SCharles.Forsyth while(n >= 3){
968*74a4d8c2SCharles.Forsyth m = n;
969*74a4d8c2SCharles.Forsyth if(m > 6)
970*74a4d8c2SCharles.Forsyth m = 6;
971*74a4d8c2SCharles.Forsyth codes[c] = 16;
972*74a4d8c2SCharles.Forsyth codeaux[c++] = m - 3;
973*74a4d8c2SCharles.Forsyth n -= m;
974*74a4d8c2SCharles.Forsyth excost += 3;
975*74a4d8c2SCharles.Forsyth }
976*74a4d8c2SCharles.Forsyth }
977*74a4d8c2SCharles.Forsyth }
978*74a4d8c2SCharles.Forsyth
979*74a4d8c2SCharles.Forsyth memset(codecount, 0, sizeof codecount);
980*74a4d8c2SCharles.Forsyth for(i = 0; i < c; i++)
981*74a4d8c2SCharles.Forsyth codecount[codes[i]]++;
982*74a4d8c2SCharles.Forsyth if(!mkgzprecode(codetab, codecount, Nclen, 8))
983*74a4d8c2SCharles.Forsyth return -1;
984*74a4d8c2SCharles.Forsyth
985*74a4d8c2SCharles.Forsyth for(nclen = Nclen; nclen > 4 && codetab[clenorder[nclen-1]].bits == 0; nclen--)
986*74a4d8c2SCharles.Forsyth ;
987*74a4d8c2SCharles.Forsyth
988*74a4d8c2SCharles.Forsyth dc->nlit = nlit;
989*74a4d8c2SCharles.Forsyth dc->noff = noff;
990*74a4d8c2SCharles.Forsyth dc->nclen = nclen;
991*74a4d8c2SCharles.Forsyth dc->ncode = c;
992*74a4d8c2SCharles.Forsyth
993*74a4d8c2SCharles.Forsyth return 5 + 5 + 4 + nclen * 3 + bitcost(codetab, codecount, Nclen) + excost;
994*74a4d8c2SCharles.Forsyth }
995*74a4d8c2SCharles.Forsyth
996*74a4d8c2SCharles.Forsyth static void
wrdyncode(LZstate * out,Dyncode * dc)997*74a4d8c2SCharles.Forsyth wrdyncode(LZstate *out, Dyncode *dc)
998*74a4d8c2SCharles.Forsyth {
999*74a4d8c2SCharles.Forsyth Huff *codetab;
1000*74a4d8c2SCharles.Forsyth uchar *codes, *codeaux;
1001*74a4d8c2SCharles.Forsyth int i, v, c;
1002*74a4d8c2SCharles.Forsyth
1003*74a4d8c2SCharles.Forsyth /*
1004*74a4d8c2SCharles.Forsyth * write out header, then code length code lengths,
1005*74a4d8c2SCharles.Forsyth * and code lengths
1006*74a4d8c2SCharles.Forsyth */
1007*74a4d8c2SCharles.Forsyth lzput(out, dc->nlit-257, 5);
1008*74a4d8c2SCharles.Forsyth lzput(out, dc->noff-1, 5);
1009*74a4d8c2SCharles.Forsyth lzput(out, dc->nclen-4, 4);
1010*74a4d8c2SCharles.Forsyth
1011*74a4d8c2SCharles.Forsyth codetab = dc->codetab;
1012*74a4d8c2SCharles.Forsyth for(i = 0; i < dc->nclen; i++)
1013*74a4d8c2SCharles.Forsyth lzput(out, codetab[clenorder[i]].bits, 3);
1014*74a4d8c2SCharles.Forsyth
1015*74a4d8c2SCharles.Forsyth codes = dc->codes;
1016*74a4d8c2SCharles.Forsyth codeaux = dc->codeaux;
1017*74a4d8c2SCharles.Forsyth c = dc->ncode;
1018*74a4d8c2SCharles.Forsyth for(i = 0; i < c; i++){
1019*74a4d8c2SCharles.Forsyth v = codes[i];
1020*74a4d8c2SCharles.Forsyth lzput(out, codetab[v].encode, codetab[v].bits);
1021*74a4d8c2SCharles.Forsyth if(v >= 16){
1022*74a4d8c2SCharles.Forsyth if(v == 16)
1023*74a4d8c2SCharles.Forsyth lzput(out, codeaux[i], 2);
1024*74a4d8c2SCharles.Forsyth else if(v == 17)
1025*74a4d8c2SCharles.Forsyth lzput(out, codeaux[i], 3);
1026*74a4d8c2SCharles.Forsyth else /* v == 18 */
1027*74a4d8c2SCharles.Forsyth lzput(out, codeaux[i], 7);
1028*74a4d8c2SCharles.Forsyth }
1029*74a4d8c2SCharles.Forsyth }
1030*74a4d8c2SCharles.Forsyth }
1031*74a4d8c2SCharles.Forsyth
1032*74a4d8c2SCharles.Forsyth static int
bitcost(Huff * tab,ulong * count,int n)1033*74a4d8c2SCharles.Forsyth bitcost(Huff *tab, ulong *count, int n)
1034*74a4d8c2SCharles.Forsyth {
1035*74a4d8c2SCharles.Forsyth ulong tot;
1036*74a4d8c2SCharles.Forsyth int i;
1037*74a4d8c2SCharles.Forsyth
1038*74a4d8c2SCharles.Forsyth tot = 0;
1039*74a4d8c2SCharles.Forsyth for(i = 0; i < n; i++)
1040*74a4d8c2SCharles.Forsyth tot += count[i] * tab[i].bits;
1041*74a4d8c2SCharles.Forsyth return tot;
1042*74a4d8c2SCharles.Forsyth }
1043*74a4d8c2SCharles.Forsyth
1044*74a4d8c2SCharles.Forsyth static int
mkgzprecode(Huff * tab,ulong * count,int n,int maxbits)1045*74a4d8c2SCharles.Forsyth mkgzprecode(Huff *tab, ulong *count, int n, int maxbits)
1046*74a4d8c2SCharles.Forsyth {
1047*74a4d8c2SCharles.Forsyth ulong bitcount[MaxHuffBits];
1048*74a4d8c2SCharles.Forsyth int i, nbits;
1049*74a4d8c2SCharles.Forsyth
1050*74a4d8c2SCharles.Forsyth nbits = mkprecode(tab, count, n, maxbits, bitcount);
1051*74a4d8c2SCharles.Forsyth for(i = 0; i < n; i++){
1052*74a4d8c2SCharles.Forsyth if(tab[i].bits == -1)
1053*74a4d8c2SCharles.Forsyth tab[i].bits = 0;
1054*74a4d8c2SCharles.Forsyth else if(tab[i].bits == 0){
1055*74a4d8c2SCharles.Forsyth if(nbits != 0 || bitcount[0] != 1)
1056*74a4d8c2SCharles.Forsyth return 0;
1057*74a4d8c2SCharles.Forsyth bitcount[1] = 1;
1058*74a4d8c2SCharles.Forsyth bitcount[0] = 0;
1059*74a4d8c2SCharles.Forsyth nbits = 1;
1060*74a4d8c2SCharles.Forsyth tab[i].bits = 1;
1061*74a4d8c2SCharles.Forsyth }
1062*74a4d8c2SCharles.Forsyth }
1063*74a4d8c2SCharles.Forsyth if(bitcount[0] != 0)
1064*74a4d8c2SCharles.Forsyth return 0;
1065*74a4d8c2SCharles.Forsyth return hufftabinit(tab, n, bitcount, nbits);
1066*74a4d8c2SCharles.Forsyth }
1067*74a4d8c2SCharles.Forsyth
1068*74a4d8c2SCharles.Forsyth static int
hufftabinit(Huff * tab,int n,ulong * bitcount,int nbits)1069*74a4d8c2SCharles.Forsyth hufftabinit(Huff *tab, int n, ulong *bitcount, int nbits)
1070*74a4d8c2SCharles.Forsyth {
1071*74a4d8c2SCharles.Forsyth ulong code, nc[MaxHuffBits];
1072*74a4d8c2SCharles.Forsyth int i, bits;
1073*74a4d8c2SCharles.Forsyth
1074*74a4d8c2SCharles.Forsyth code = 0;
1075*74a4d8c2SCharles.Forsyth for(bits = 1; bits <= nbits; bits++){
1076*74a4d8c2SCharles.Forsyth code = (code + bitcount[bits-1]) << 1;
1077*74a4d8c2SCharles.Forsyth nc[bits] = code;
1078*74a4d8c2SCharles.Forsyth }
1079*74a4d8c2SCharles.Forsyth
1080*74a4d8c2SCharles.Forsyth for(i = 0; i < n; i++){
1081*74a4d8c2SCharles.Forsyth bits = tab[i].bits;
1082*74a4d8c2SCharles.Forsyth if(bits){
1083*74a4d8c2SCharles.Forsyth code = nc[bits]++ << (16 - bits);
1084*74a4d8c2SCharles.Forsyth if(code & ~0xffff)
1085*74a4d8c2SCharles.Forsyth return 0;
1086*74a4d8c2SCharles.Forsyth tab[i].encode = revtab[code >> 8] | (revtab[code & 0xff] << 8);
1087*74a4d8c2SCharles.Forsyth }
1088*74a4d8c2SCharles.Forsyth }
1089*74a4d8c2SCharles.Forsyth return 1;
1090*74a4d8c2SCharles.Forsyth }
1091*74a4d8c2SCharles.Forsyth
1092*74a4d8c2SCharles.Forsyth
1093*74a4d8c2SCharles.Forsyth /*
1094*74a4d8c2SCharles.Forsyth * this should be in a library
1095*74a4d8c2SCharles.Forsyth */
1096*74a4d8c2SCharles.Forsyth struct Chain
1097*74a4d8c2SCharles.Forsyth {
1098*74a4d8c2SCharles.Forsyth ulong count; /* occurances of everything in the chain */
1099*74a4d8c2SCharles.Forsyth ushort leaf; /* leaves to the left of chain, or leaf value */
1100*74a4d8c2SCharles.Forsyth char col; /* ref count for collecting unused chains */
1101*74a4d8c2SCharles.Forsyth char gen; /* need to generate chains for next lower level */
1102*74a4d8c2SCharles.Forsyth Chain *up; /* Chain up in the lists */
1103*74a4d8c2SCharles.Forsyth };
1104*74a4d8c2SCharles.Forsyth
1105*74a4d8c2SCharles.Forsyth struct Chains
1106*74a4d8c2SCharles.Forsyth {
1107*74a4d8c2SCharles.Forsyth Chain *lists[(MaxHuffBits - 1) * 2];
1108*74a4d8c2SCharles.Forsyth ulong leafcount[MaxLeaf]; /* sorted list of leaf counts */
1109*74a4d8c2SCharles.Forsyth ushort leafmap[MaxLeaf]; /* map to actual leaf number */
1110*74a4d8c2SCharles.Forsyth int nleaf; /* number of leaves */
1111*74a4d8c2SCharles.Forsyth Chain chains[ChainMem];
1112*74a4d8c2SCharles.Forsyth Chain *echains;
1113*74a4d8c2SCharles.Forsyth Chain *free;
1114*74a4d8c2SCharles.Forsyth char col;
1115*74a4d8c2SCharles.Forsyth int nlists;
1116*74a4d8c2SCharles.Forsyth };
1117*74a4d8c2SCharles.Forsyth
1118*74a4d8c2SCharles.Forsyth /*
1119*74a4d8c2SCharles.Forsyth * fast, low space overhead algorithm for max depth huffman type codes
1120*74a4d8c2SCharles.Forsyth *
1121*74a4d8c2SCharles.Forsyth * J. Katajainen, A. Moffat and A. Turpin, "A fast and space-economical
1122*74a4d8c2SCharles.Forsyth * algorithm for length-limited coding," Proc. Intl. Symp. on Algorithms
1123*74a4d8c2SCharles.Forsyth * and Computation, Cairns, Australia, Dec. 1995, Lecture Notes in Computer
1124*74a4d8c2SCharles.Forsyth * Science, Vol 1004, J. Staples, P. Eades, N. Katoh, and A. Moffat, eds.,
1125*74a4d8c2SCharles.Forsyth * pp 12-21, Springer Verlag, New York, 1995.
1126*74a4d8c2SCharles.Forsyth */
1127*74a4d8c2SCharles.Forsyth static int
mkprecode(Huff * tab,ulong * count,int n,int maxbits,ulong * bitcount)1128*74a4d8c2SCharles.Forsyth mkprecode(Huff *tab, ulong *count, int n, int maxbits, ulong *bitcount)
1129*74a4d8c2SCharles.Forsyth {
1130*74a4d8c2SCharles.Forsyth Chains cs;
1131*74a4d8c2SCharles.Forsyth Chain *c;
1132*74a4d8c2SCharles.Forsyth int i, m, em, bits;
1133*74a4d8c2SCharles.Forsyth
1134*74a4d8c2SCharles.Forsyth /*
1135*74a4d8c2SCharles.Forsyth * set up the sorted list of leaves
1136*74a4d8c2SCharles.Forsyth */
1137*74a4d8c2SCharles.Forsyth m = 0;
1138*74a4d8c2SCharles.Forsyth for(i = 0; i < n; i++){
1139*74a4d8c2SCharles.Forsyth tab[i].bits = -1;
1140*74a4d8c2SCharles.Forsyth tab[i].encode = 0;
1141*74a4d8c2SCharles.Forsyth if(count[i] != 0){
1142*74a4d8c2SCharles.Forsyth cs.leafcount[m] = count[i];
1143*74a4d8c2SCharles.Forsyth cs.leafmap[m] = i;
1144*74a4d8c2SCharles.Forsyth m++;
1145*74a4d8c2SCharles.Forsyth }
1146*74a4d8c2SCharles.Forsyth }
1147*74a4d8c2SCharles.Forsyth if(m < 2){
1148*74a4d8c2SCharles.Forsyth if(m != 0){
1149*74a4d8c2SCharles.Forsyth tab[cs.leafmap[0]].bits = 0;
1150*74a4d8c2SCharles.Forsyth bitcount[0] = 1;
1151*74a4d8c2SCharles.Forsyth }else
1152*74a4d8c2SCharles.Forsyth bitcount[0] = 0;
1153*74a4d8c2SCharles.Forsyth return 0;
1154*74a4d8c2SCharles.Forsyth }
1155*74a4d8c2SCharles.Forsyth cs.nleaf = m;
1156*74a4d8c2SCharles.Forsyth leafsort(cs.leafcount, cs.leafmap, 0, m);
1157*74a4d8c2SCharles.Forsyth
1158*74a4d8c2SCharles.Forsyth for(i = 0; i < m; i++)
1159*74a4d8c2SCharles.Forsyth cs.leafcount[i] = count[cs.leafmap[i]];
1160*74a4d8c2SCharles.Forsyth
1161*74a4d8c2SCharles.Forsyth /*
1162*74a4d8c2SCharles.Forsyth * set up free list
1163*74a4d8c2SCharles.Forsyth */
1164*74a4d8c2SCharles.Forsyth cs.free = &cs.chains[2];
1165*74a4d8c2SCharles.Forsyth cs.echains = &cs.chains[ChainMem];
1166*74a4d8c2SCharles.Forsyth cs.col = 1;
1167*74a4d8c2SCharles.Forsyth
1168*74a4d8c2SCharles.Forsyth /*
1169*74a4d8c2SCharles.Forsyth * initialize chains for each list
1170*74a4d8c2SCharles.Forsyth */
1171*74a4d8c2SCharles.Forsyth c = &cs.chains[0];
1172*74a4d8c2SCharles.Forsyth c->count = cs.leafcount[0];
1173*74a4d8c2SCharles.Forsyth c->leaf = 1;
1174*74a4d8c2SCharles.Forsyth c->col = cs.col;
1175*74a4d8c2SCharles.Forsyth c->up = nil;
1176*74a4d8c2SCharles.Forsyth c->gen = 0;
1177*74a4d8c2SCharles.Forsyth cs.chains[1] = cs.chains[0];
1178*74a4d8c2SCharles.Forsyth cs.chains[1].leaf = 2;
1179*74a4d8c2SCharles.Forsyth cs.chains[1].count = cs.leafcount[1];
1180*74a4d8c2SCharles.Forsyth for(i = 0; i < maxbits-1; i++){
1181*74a4d8c2SCharles.Forsyth cs.lists[i * 2] = &cs.chains[0];
1182*74a4d8c2SCharles.Forsyth cs.lists[i * 2 + 1] = &cs.chains[1];
1183*74a4d8c2SCharles.Forsyth }
1184*74a4d8c2SCharles.Forsyth
1185*74a4d8c2SCharles.Forsyth cs.nlists = 2 * (maxbits - 1);
1186*74a4d8c2SCharles.Forsyth m = 2 * m - 2;
1187*74a4d8c2SCharles.Forsyth for(i = 2; i < m; i++)
1188*74a4d8c2SCharles.Forsyth nextchain(&cs, cs.nlists - 2);
1189*74a4d8c2SCharles.Forsyth
1190*74a4d8c2SCharles.Forsyth bits = 0;
1191*74a4d8c2SCharles.Forsyth bitcount[0] = cs.nleaf;
1192*74a4d8c2SCharles.Forsyth for(c = cs.lists[cs.nlists - 1]; c != nil; c = c->up){
1193*74a4d8c2SCharles.Forsyth m = c->leaf;
1194*74a4d8c2SCharles.Forsyth bitcount[bits++] -= m;
1195*74a4d8c2SCharles.Forsyth bitcount[bits] = m;
1196*74a4d8c2SCharles.Forsyth }
1197*74a4d8c2SCharles.Forsyth m = 0;
1198*74a4d8c2SCharles.Forsyth for(i = bits; i >= 0; i--)
1199*74a4d8c2SCharles.Forsyth for(em = m + bitcount[i]; m < em; m++)
1200*74a4d8c2SCharles.Forsyth tab[cs.leafmap[m]].bits = i;
1201*74a4d8c2SCharles.Forsyth
1202*74a4d8c2SCharles.Forsyth return bits;
1203*74a4d8c2SCharles.Forsyth }
1204*74a4d8c2SCharles.Forsyth
1205*74a4d8c2SCharles.Forsyth /*
1206*74a4d8c2SCharles.Forsyth * calculate the next chain on the list
1207*74a4d8c2SCharles.Forsyth * we can always toss out the old chain
1208*74a4d8c2SCharles.Forsyth */
1209*74a4d8c2SCharles.Forsyth static void
nextchain(Chains * cs,int list)1210*74a4d8c2SCharles.Forsyth nextchain(Chains *cs, int list)
1211*74a4d8c2SCharles.Forsyth {
1212*74a4d8c2SCharles.Forsyth Chain *c, *oc;
1213*74a4d8c2SCharles.Forsyth int i, nleaf, sumc;
1214*74a4d8c2SCharles.Forsyth
1215*74a4d8c2SCharles.Forsyth oc = cs->lists[list + 1];
1216*74a4d8c2SCharles.Forsyth cs->lists[list] = oc;
1217*74a4d8c2SCharles.Forsyth if(oc == nil)
1218*74a4d8c2SCharles.Forsyth return;
1219*74a4d8c2SCharles.Forsyth
1220*74a4d8c2SCharles.Forsyth /*
1221*74a4d8c2SCharles.Forsyth * make sure we have all chains needed to make sumc
1222*74a4d8c2SCharles.Forsyth * note it is possible to generate only one of these,
1223*74a4d8c2SCharles.Forsyth * use twice that value for sumc, and then generate
1224*74a4d8c2SCharles.Forsyth * the second if that preliminary sumc would be chosen.
1225*74a4d8c2SCharles.Forsyth * however, this appears to be slower on current tests
1226*74a4d8c2SCharles.Forsyth */
1227*74a4d8c2SCharles.Forsyth if(oc->gen){
1228*74a4d8c2SCharles.Forsyth nextchain(cs, list - 2);
1229*74a4d8c2SCharles.Forsyth nextchain(cs, list - 2);
1230*74a4d8c2SCharles.Forsyth oc->gen = 0;
1231*74a4d8c2SCharles.Forsyth }
1232*74a4d8c2SCharles.Forsyth
1233*74a4d8c2SCharles.Forsyth /*
1234*74a4d8c2SCharles.Forsyth * pick up the chain we're going to add;
1235*74a4d8c2SCharles.Forsyth * collect unused chains no free ones are left
1236*74a4d8c2SCharles.Forsyth */
1237*74a4d8c2SCharles.Forsyth for(c = cs->free; ; c++){
1238*74a4d8c2SCharles.Forsyth if(c >= cs->echains){
1239*74a4d8c2SCharles.Forsyth cs->col++;
1240*74a4d8c2SCharles.Forsyth for(i = 0; i < cs->nlists; i++)
1241*74a4d8c2SCharles.Forsyth for(c = cs->lists[i]; c != nil; c = c->up)
1242*74a4d8c2SCharles.Forsyth c->col = cs->col;
1243*74a4d8c2SCharles.Forsyth c = cs->chains;
1244*74a4d8c2SCharles.Forsyth }
1245*74a4d8c2SCharles.Forsyth if(c->col != cs->col)
1246*74a4d8c2SCharles.Forsyth break;
1247*74a4d8c2SCharles.Forsyth }
1248*74a4d8c2SCharles.Forsyth
1249*74a4d8c2SCharles.Forsyth /*
1250*74a4d8c2SCharles.Forsyth * pick the cheapest of
1251*74a4d8c2SCharles.Forsyth * 1) the next package from the previous list
1252*74a4d8c2SCharles.Forsyth * 2) the next leaf
1253*74a4d8c2SCharles.Forsyth */
1254*74a4d8c2SCharles.Forsyth nleaf = oc->leaf;
1255*74a4d8c2SCharles.Forsyth sumc = 0;
1256*74a4d8c2SCharles.Forsyth if(list > 0 && cs->lists[list-1] != nil)
1257*74a4d8c2SCharles.Forsyth sumc = cs->lists[list-2]->count + cs->lists[list-1]->count;
1258*74a4d8c2SCharles.Forsyth if(sumc != 0 && (nleaf >= cs->nleaf || cs->leafcount[nleaf] > sumc)){
1259*74a4d8c2SCharles.Forsyth c->count = sumc;
1260*74a4d8c2SCharles.Forsyth c->leaf = oc->leaf;
1261*74a4d8c2SCharles.Forsyth c->up = cs->lists[list-1];
1262*74a4d8c2SCharles.Forsyth c->gen = 1;
1263*74a4d8c2SCharles.Forsyth }else if(nleaf >= cs->nleaf){
1264*74a4d8c2SCharles.Forsyth cs->lists[list + 1] = nil;
1265*74a4d8c2SCharles.Forsyth return;
1266*74a4d8c2SCharles.Forsyth }else{
1267*74a4d8c2SCharles.Forsyth c->leaf = nleaf + 1;
1268*74a4d8c2SCharles.Forsyth c->count = cs->leafcount[nleaf];
1269*74a4d8c2SCharles.Forsyth c->up = oc->up;
1270*74a4d8c2SCharles.Forsyth c->gen = 0;
1271*74a4d8c2SCharles.Forsyth }
1272*74a4d8c2SCharles.Forsyth cs->free = c + 1;
1273*74a4d8c2SCharles.Forsyth
1274*74a4d8c2SCharles.Forsyth cs->lists[list + 1] = c;
1275*74a4d8c2SCharles.Forsyth c->col = cs->col;
1276*74a4d8c2SCharles.Forsyth }
1277*74a4d8c2SCharles.Forsyth
1278*74a4d8c2SCharles.Forsyth static int
pivot(ulong * c,int a,int n)1279*74a4d8c2SCharles.Forsyth pivot(ulong *c, int a, int n)
1280*74a4d8c2SCharles.Forsyth {
1281*74a4d8c2SCharles.Forsyth int j, pi, pj, pk;
1282*74a4d8c2SCharles.Forsyth
1283*74a4d8c2SCharles.Forsyth j = n/6;
1284*74a4d8c2SCharles.Forsyth pi = a + j; /* 1/6 */
1285*74a4d8c2SCharles.Forsyth j += j;
1286*74a4d8c2SCharles.Forsyth pj = pi + j; /* 1/2 */
1287*74a4d8c2SCharles.Forsyth pk = pj + j; /* 5/6 */
1288*74a4d8c2SCharles.Forsyth if(c[pi] < c[pj]){
1289*74a4d8c2SCharles.Forsyth if(c[pi] < c[pk]){
1290*74a4d8c2SCharles.Forsyth if(c[pj] < c[pk])
1291*74a4d8c2SCharles.Forsyth return pj;
1292*74a4d8c2SCharles.Forsyth return pk;
1293*74a4d8c2SCharles.Forsyth }
1294*74a4d8c2SCharles.Forsyth return pi;
1295*74a4d8c2SCharles.Forsyth }
1296*74a4d8c2SCharles.Forsyth if(c[pj] < c[pk]){
1297*74a4d8c2SCharles.Forsyth if(c[pi] < c[pk])
1298*74a4d8c2SCharles.Forsyth return pi;
1299*74a4d8c2SCharles.Forsyth return pk;
1300*74a4d8c2SCharles.Forsyth }
1301*74a4d8c2SCharles.Forsyth return pj;
1302*74a4d8c2SCharles.Forsyth }
1303*74a4d8c2SCharles.Forsyth
1304*74a4d8c2SCharles.Forsyth static void
leafsort(ulong * leafcount,ushort * leafmap,int a,int n)1305*74a4d8c2SCharles.Forsyth leafsort(ulong *leafcount, ushort *leafmap, int a, int n)
1306*74a4d8c2SCharles.Forsyth {
1307*74a4d8c2SCharles.Forsyth ulong t;
1308*74a4d8c2SCharles.Forsyth int j, pi, pj, pn;
1309*74a4d8c2SCharles.Forsyth
1310*74a4d8c2SCharles.Forsyth while(n > 1){
1311*74a4d8c2SCharles.Forsyth if(n > 10){
1312*74a4d8c2SCharles.Forsyth pi = pivot(leafcount, a, n);
1313*74a4d8c2SCharles.Forsyth }else
1314*74a4d8c2SCharles.Forsyth pi = a + (n>>1);
1315*74a4d8c2SCharles.Forsyth
1316*74a4d8c2SCharles.Forsyth t = leafcount[pi];
1317*74a4d8c2SCharles.Forsyth leafcount[pi] = leafcount[a];
1318*74a4d8c2SCharles.Forsyth leafcount[a] = t;
1319*74a4d8c2SCharles.Forsyth t = leafmap[pi];
1320*74a4d8c2SCharles.Forsyth leafmap[pi] = leafmap[a];
1321*74a4d8c2SCharles.Forsyth leafmap[a] = t;
1322*74a4d8c2SCharles.Forsyth pi = a;
1323*74a4d8c2SCharles.Forsyth pn = a + n;
1324*74a4d8c2SCharles.Forsyth pj = pn;
1325*74a4d8c2SCharles.Forsyth for(;;){
1326*74a4d8c2SCharles.Forsyth do
1327*74a4d8c2SCharles.Forsyth pi++;
1328*74a4d8c2SCharles.Forsyth while(pi < pn && (leafcount[pi] < leafcount[a] || leafcount[pi] == leafcount[a] && leafmap[pi] > leafmap[a]));
1329*74a4d8c2SCharles.Forsyth do
1330*74a4d8c2SCharles.Forsyth pj--;
1331*74a4d8c2SCharles.Forsyth while(pj > a && (leafcount[pj] > leafcount[a] || leafcount[pj] == leafcount[a] && leafmap[pj] < leafmap[a]));
1332*74a4d8c2SCharles.Forsyth if(pj < pi)
1333*74a4d8c2SCharles.Forsyth break;
1334*74a4d8c2SCharles.Forsyth t = leafcount[pi];
1335*74a4d8c2SCharles.Forsyth leafcount[pi] = leafcount[pj];
1336*74a4d8c2SCharles.Forsyth leafcount[pj] = t;
1337*74a4d8c2SCharles.Forsyth t = leafmap[pi];
1338*74a4d8c2SCharles.Forsyth leafmap[pi] = leafmap[pj];
1339*74a4d8c2SCharles.Forsyth leafmap[pj] = t;
1340*74a4d8c2SCharles.Forsyth }
1341*74a4d8c2SCharles.Forsyth t = leafcount[a];
1342*74a4d8c2SCharles.Forsyth leafcount[a] = leafcount[pj];
1343*74a4d8c2SCharles.Forsyth leafcount[pj] = t;
1344*74a4d8c2SCharles.Forsyth t = leafmap[a];
1345*74a4d8c2SCharles.Forsyth leafmap[a] = leafmap[pj];
1346*74a4d8c2SCharles.Forsyth leafmap[pj] = t;
1347*74a4d8c2SCharles.Forsyth j = pj - a;
1348*74a4d8c2SCharles.Forsyth
1349*74a4d8c2SCharles.Forsyth n = n-j-1;
1350*74a4d8c2SCharles.Forsyth if(j >= n){
1351*74a4d8c2SCharles.Forsyth leafsort(leafcount, leafmap, a, j);
1352*74a4d8c2SCharles.Forsyth a += j+1;
1353*74a4d8c2SCharles.Forsyth }else{
1354*74a4d8c2SCharles.Forsyth leafsort(leafcount, leafmap, a + (j+1), n);
1355*74a4d8c2SCharles.Forsyth n = j;
1356*74a4d8c2SCharles.Forsyth }
1357*74a4d8c2SCharles.Forsyth }
1358*74a4d8c2SCharles.Forsyth }
1359