1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker * erofs-utils/lib/kite_deflate.c
4*33b1fccfSAndroid Build Coastguard Worker *
5*33b1fccfSAndroid Build Coastguard Worker * Copyright (C) 2023, Alibaba Cloud
6*33b1fccfSAndroid Build Coastguard Worker * Copyright (C) 2023, Gao Xiang <[email protected]>
7*33b1fccfSAndroid Build Coastguard Worker */
8*33b1fccfSAndroid Build Coastguard Worker #include "erofs/defs.h"
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
10*33b1fccfSAndroid Build Coastguard Worker #include <errno.h>
11*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
12*33b1fccfSAndroid Build Coastguard Worker #include <string.h>
13*33b1fccfSAndroid Build Coastguard Worker #include <ctype.h>
14*33b1fccfSAndroid Build Coastguard Worker #include <stdio.h>
15*33b1fccfSAndroid Build Coastguard Worker
16*33b1fccfSAndroid Build Coastguard Worker unsigned long erofs_memcmp2(const u8 *s1, const u8 *s2,
17*33b1fccfSAndroid Build Coastguard Worker unsigned long sz);
18*33b1fccfSAndroid Build Coastguard Worker
19*33b1fccfSAndroid Build Coastguard Worker #ifdef TEST
20*33b1fccfSAndroid Build Coastguard Worker #define kite_dbg(x, ...) fprintf(stderr, x "\n", ##__VA_ARGS__)
21*33b1fccfSAndroid Build Coastguard Worker #else
22*33b1fccfSAndroid Build Coastguard Worker #define kite_dbg(x, ...)
23*33b1fccfSAndroid Build Coastguard Worker #endif
24*33b1fccfSAndroid Build Coastguard Worker
25*33b1fccfSAndroid Build Coastguard Worker #define kHistorySize32 (1U << 15)
26*33b1fccfSAndroid Build Coastguard Worker
27*33b1fccfSAndroid Build Coastguard Worker #define kNumLenSymbols32 256
28*33b1fccfSAndroid Build Coastguard Worker #define kNumLenSymbolsMax kNumLenSymbols32
29*33b1fccfSAndroid Build Coastguard Worker
30*33b1fccfSAndroid Build Coastguard Worker #define kSymbolEndOfBlock 256
31*33b1fccfSAndroid Build Coastguard Worker #define kSymbolMatch (kSymbolEndOfBlock + 1)
32*33b1fccfSAndroid Build Coastguard Worker #define kNumLenSlots 29
33*33b1fccfSAndroid Build Coastguard Worker #define kMainTableSize (kSymbolMatch + kNumLenSlots)
34*33b1fccfSAndroid Build Coastguard Worker
35*33b1fccfSAndroid Build Coastguard Worker #define kFixedLenTableSize (kSymbolMatch + 31)
36*33b1fccfSAndroid Build Coastguard Worker #define FixedDistTableSize 32
37*33b1fccfSAndroid Build Coastguard Worker
38*33b1fccfSAndroid Build Coastguard Worker #define kMainTableSize (kSymbolMatch + kNumLenSlots)
39*33b1fccfSAndroid Build Coastguard Worker #define kDistTableSize32 30
40*33b1fccfSAndroid Build Coastguard Worker
41*33b1fccfSAndroid Build Coastguard Worker #define kNumLitLenCodesMin 257
42*33b1fccfSAndroid Build Coastguard Worker #define kNumDistCodesMin 1
43*33b1fccfSAndroid Build Coastguard Worker
44*33b1fccfSAndroid Build Coastguard Worker #define kNumLensCodesMin 4
45*33b1fccfSAndroid Build Coastguard Worker #define kLensTableSize 19
46*33b1fccfSAndroid Build Coastguard Worker
47*33b1fccfSAndroid Build Coastguard Worker #define kMatchMinLen 3
48*33b1fccfSAndroid Build Coastguard Worker #define kMatchMaxLen32 kNumLenSymbols32 + kMatchMinLen - 1
49*33b1fccfSAndroid Build Coastguard Worker
50*33b1fccfSAndroid Build Coastguard Worker #define kTableDirectLevels 16
51*33b1fccfSAndroid Build Coastguard Worker #define kBitLensRepNumber_3_6 kTableDirectLevels
52*33b1fccfSAndroid Build Coastguard Worker #define kBitLens0Number_3_10 (kBitLensRepNumber_3_6 + 1)
53*33b1fccfSAndroid Build Coastguard Worker #define kBitLens0Number_11_138 (kBitLens0Number_3_10 + 1)
54*33b1fccfSAndroid Build Coastguard Worker
55*33b1fccfSAndroid Build Coastguard Worker static u32 kstaticHuff_mainCodes[kFixedLenTableSize];
56*33b1fccfSAndroid Build Coastguard Worker static const u8 kstaticHuff_litLenLevels[kFixedLenTableSize] = {
57*33b1fccfSAndroid Build Coastguard Worker [0 ... 143] = 8, [144 ... 255] = 9,
58*33b1fccfSAndroid Build Coastguard Worker [256 ... 279] = 7, [280 ... 287] = 8,
59*33b1fccfSAndroid Build Coastguard Worker };
60*33b1fccfSAndroid Build Coastguard Worker static u32 kstaticHuff_distCodes[kFixedLenTableSize];
61*33b1fccfSAndroid Build Coastguard Worker
62*33b1fccfSAndroid Build Coastguard Worker const u8 kLenStart32[kNumLenSlots] =
63*33b1fccfSAndroid Build Coastguard Worker {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255};
64*33b1fccfSAndroid Build Coastguard Worker
65*33b1fccfSAndroid Build Coastguard Worker const u8 kLenExtraBits32[kNumLenSlots] =
66*33b1fccfSAndroid Build Coastguard Worker {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
67*33b1fccfSAndroid Build Coastguard Worker 5, 5, 5, 0};
68*33b1fccfSAndroid Build Coastguard Worker
69*33b1fccfSAndroid Build Coastguard Worker /* First normalized distance for each code (0 = distance of 1) */
70*33b1fccfSAndroid Build Coastguard Worker const u32 kDistStart[kDistTableSize32] =
71*33b1fccfSAndroid Build Coastguard Worker {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,
72*33b1fccfSAndroid Build Coastguard Worker 1024,1536,2048,3072,4096,6144,8192,12288,16384,24576};
73*33b1fccfSAndroid Build Coastguard Worker
74*33b1fccfSAndroid Build Coastguard Worker /* extra bits for each distance code */
75*33b1fccfSAndroid Build Coastguard Worker const u8 kDistExtraBits[kDistTableSize32] =
76*33b1fccfSAndroid Build Coastguard Worker {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
77*33b1fccfSAndroid Build Coastguard Worker
78*33b1fccfSAndroid Build Coastguard Worker const u8 kCodeLengthAlphabetOrder[kLensTableSize] =
79*33b1fccfSAndroid Build Coastguard Worker {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
80*33b1fccfSAndroid Build Coastguard Worker
81*33b1fccfSAndroid Build Coastguard Worker const u8 kLevelExtraBits[3] = {2, 3, 7};
82*33b1fccfSAndroid Build Coastguard Worker
83*33b1fccfSAndroid Build Coastguard Worker #define kStored 0
84*33b1fccfSAndroid Build Coastguard Worker #define kFixedHuffman 1
85*33b1fccfSAndroid Build Coastguard Worker #define kDynamicHuffman 2
86*33b1fccfSAndroid Build Coastguard Worker
87*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_symbol {
88*33b1fccfSAndroid Build Coastguard Worker u16 len, dist;
89*33b1fccfSAndroid Build Coastguard Worker };
90*33b1fccfSAndroid Build Coastguard Worker
91*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table {
92*33b1fccfSAndroid Build Coastguard Worker u32 mainCodes[kMainTableSize];
93*33b1fccfSAndroid Build Coastguard Worker u8 litLenLevels[kMainTableSize];
94*33b1fccfSAndroid Build Coastguard Worker u32 distCodes[kDistTableSize32];
95*33b1fccfSAndroid Build Coastguard Worker u8 distLevels[kDistTableSize32];
96*33b1fccfSAndroid Build Coastguard Worker u32 levelCodes[kLensTableSize];
97*33b1fccfSAndroid Build Coastguard Worker u8 levelLens[kLensTableSize];
98*33b1fccfSAndroid Build Coastguard Worker
99*33b1fccfSAndroid Build Coastguard Worker u8 numdistlens, numblcodes;
100*33b1fccfSAndroid Build Coastguard Worker u16 numlitlens;
101*33b1fccfSAndroid Build Coastguard Worker };
102*33b1fccfSAndroid Build Coastguard Worker
103*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate {
104*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table *tab;
105*33b1fccfSAndroid Build Coastguard Worker const u8 *in;
106*33b1fccfSAndroid Build Coastguard Worker u8 *out;
107*33b1fccfSAndroid Build Coastguard Worker
108*33b1fccfSAndroid Build Coastguard Worker u32 inlen, outlen;
109*33b1fccfSAndroid Build Coastguard Worker u32 pos_in, pos_out;
110*33b1fccfSAndroid Build Coastguard Worker u32 inflightbits;
111*33b1fccfSAndroid Build Coastguard Worker u8 bitpos;
112*33b1fccfSAndroid Build Coastguard Worker u8 numHuffBits;
113*33b1fccfSAndroid Build Coastguard Worker u32 symbols;
114*33b1fccfSAndroid Build Coastguard Worker
115*33b1fccfSAndroid Build Coastguard Worker u32 costbits, startpos;
116*33b1fccfSAndroid Build Coastguard Worker u8 encode_mode;
117*33b1fccfSAndroid Build Coastguard Worker bool freq_changed, lastblock;
118*33b1fccfSAndroid Build Coastguard Worker
119*33b1fccfSAndroid Build Coastguard Worker /* Previous match for lazy matching */
120*33b1fccfSAndroid Build Coastguard Worker bool prev_valid;
121*33b1fccfSAndroid Build Coastguard Worker u16 prev_longest;
122*33b1fccfSAndroid Build Coastguard Worker
123*33b1fccfSAndroid Build Coastguard Worker u32 mainFreqs[kMainTableSize];
124*33b1fccfSAndroid Build Coastguard Worker u32 distFreqs[kDistTableSize32];
125*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table tables[2];
126*33b1fccfSAndroid Build Coastguard Worker
127*33b1fccfSAndroid Build Coastguard Worker /* don't reset the following fields */
128*33b1fccfSAndroid Build Coastguard Worker struct kite_matchfinder *mf;
129*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_symbol *sym;
130*33b1fccfSAndroid Build Coastguard Worker u32 max_symbols;
131*33b1fccfSAndroid Build Coastguard Worker bool lazy_search;
132*33b1fccfSAndroid Build Coastguard Worker };
133*33b1fccfSAndroid Build Coastguard Worker
134*33b1fccfSAndroid Build Coastguard Worker #define ZLIB_DISTANCE_TOO_FAR 4096
135*33b1fccfSAndroid Build Coastguard Worker
136*33b1fccfSAndroid Build Coastguard Worker static u8 g_LenSlots[kNumLenSymbolsMax];
137*33b1fccfSAndroid Build Coastguard Worker
138*33b1fccfSAndroid Build Coastguard Worker #define kNumLogBits 9 // do not change it
139*33b1fccfSAndroid Build Coastguard Worker static u8 g_FastPos[1 << kNumLogBits];
140*33b1fccfSAndroid Build Coastguard Worker
writebits(struct kite_deflate * s,unsigned int v,u8 bits)141*33b1fccfSAndroid Build Coastguard Worker static void writebits(struct kite_deflate *s, unsigned int v, u8 bits)
142*33b1fccfSAndroid Build Coastguard Worker {
143*33b1fccfSAndroid Build Coastguard Worker unsigned int rem = sizeof(s->inflightbits) * 8 - s->bitpos;
144*33b1fccfSAndroid Build Coastguard Worker
145*33b1fccfSAndroid Build Coastguard Worker s->inflightbits |= (v << s->bitpos) & (!rem - 1);
146*33b1fccfSAndroid Build Coastguard Worker if (bits > rem) {
147*33b1fccfSAndroid Build Coastguard Worker u8 *out = s->out + s->pos_out;
148*33b1fccfSAndroid Build Coastguard Worker
149*33b1fccfSAndroid Build Coastguard Worker out[0] = s->inflightbits & 0xff;
150*33b1fccfSAndroid Build Coastguard Worker out[1] = (s->inflightbits >> 8) & 0xff;
151*33b1fccfSAndroid Build Coastguard Worker out[2] = (s->inflightbits >> 16) & 0xff;
152*33b1fccfSAndroid Build Coastguard Worker out[3] = (s->inflightbits >> 24) & 0xff;
153*33b1fccfSAndroid Build Coastguard Worker s->pos_out += 4;
154*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(s->pos_out > s->outlen);
155*33b1fccfSAndroid Build Coastguard Worker s->inflightbits = v >> rem;
156*33b1fccfSAndroid Build Coastguard Worker s->bitpos = bits - rem;
157*33b1fccfSAndroid Build Coastguard Worker return;
158*33b1fccfSAndroid Build Coastguard Worker }
159*33b1fccfSAndroid Build Coastguard Worker s->bitpos += bits;
160*33b1fccfSAndroid Build Coastguard Worker }
161*33b1fccfSAndroid Build Coastguard Worker
flushbits(struct kite_deflate * s)162*33b1fccfSAndroid Build Coastguard Worker static void flushbits(struct kite_deflate *s)
163*33b1fccfSAndroid Build Coastguard Worker {
164*33b1fccfSAndroid Build Coastguard Worker u8 *out = s->out + s->pos_out;
165*33b1fccfSAndroid Build Coastguard Worker
166*33b1fccfSAndroid Build Coastguard Worker if (!s->bitpos)
167*33b1fccfSAndroid Build Coastguard Worker return;
168*33b1fccfSAndroid Build Coastguard Worker out[0] = s->inflightbits & 0xff;
169*33b1fccfSAndroid Build Coastguard Worker if (s->bitpos >= 8) {
170*33b1fccfSAndroid Build Coastguard Worker out[1] = (s->inflightbits >> 8) & 0xff;
171*33b1fccfSAndroid Build Coastguard Worker if (s->bitpos >= 16) {
172*33b1fccfSAndroid Build Coastguard Worker out[2] = (s->inflightbits >> 16) & 0xff;
173*33b1fccfSAndroid Build Coastguard Worker if (s->bitpos >= 24)
174*33b1fccfSAndroid Build Coastguard Worker out[3] = (s->inflightbits >> 24) & 0xff;
175*33b1fccfSAndroid Build Coastguard Worker }
176*33b1fccfSAndroid Build Coastguard Worker }
177*33b1fccfSAndroid Build Coastguard Worker s->pos_out += round_up(s->bitpos, 8) >> 3;
178*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(s->pos_out > s->outlen);
179*33b1fccfSAndroid Build Coastguard Worker s->bitpos = 0;
180*33b1fccfSAndroid Build Coastguard Worker s->inflightbits = 0;
181*33b1fccfSAndroid Build Coastguard Worker }
182*33b1fccfSAndroid Build Coastguard Worker
183*33b1fccfSAndroid Build Coastguard Worker #define kMaxLen 16
184*33b1fccfSAndroid Build Coastguard Worker
deflate_genhuffcodes(const u8 * lens,u32 * p,unsigned int nr_codes,const u32 * bl_count)185*33b1fccfSAndroid Build Coastguard Worker static void deflate_genhuffcodes(const u8 *lens, u32 *p, unsigned int nr_codes,
186*33b1fccfSAndroid Build Coastguard Worker const u32 *bl_count)
187*33b1fccfSAndroid Build Coastguard Worker {
188*33b1fccfSAndroid Build Coastguard Worker u32 nextCodes[kMaxLen + 1]; /* next code value for each bit length */
189*33b1fccfSAndroid Build Coastguard Worker unsigned int code = 0; /* running code value */
190*33b1fccfSAndroid Build Coastguard Worker unsigned int bits, k;
191*33b1fccfSAndroid Build Coastguard Worker
192*33b1fccfSAndroid Build Coastguard Worker for (bits = 1; bits <= kMaxLen; ++bits) {
193*33b1fccfSAndroid Build Coastguard Worker code = (code + bl_count[bits - 1]) << 1;
194*33b1fccfSAndroid Build Coastguard Worker nextCodes[bits] = code;
195*33b1fccfSAndroid Build Coastguard Worker }
196*33b1fccfSAndroid Build Coastguard Worker
197*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(code + bl_count[kMaxLen] != 1 << kMaxLen);
198*33b1fccfSAndroid Build Coastguard Worker
199*33b1fccfSAndroid Build Coastguard Worker for (k = 0; k < nr_codes; ++k)
200*33b1fccfSAndroid Build Coastguard Worker p[k] = nextCodes[lens[k]]++;
201*33b1fccfSAndroid Build Coastguard Worker }
202*33b1fccfSAndroid Build Coastguard Worker
deflate_reversebits_one(u32 code,u8 bits)203*33b1fccfSAndroid Build Coastguard Worker static u32 deflate_reversebits_one(u32 code, u8 bits)
204*33b1fccfSAndroid Build Coastguard Worker {
205*33b1fccfSAndroid Build Coastguard Worker unsigned int x = code;
206*33b1fccfSAndroid Build Coastguard Worker
207*33b1fccfSAndroid Build Coastguard Worker x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1);
208*33b1fccfSAndroid Build Coastguard Worker x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2);
209*33b1fccfSAndroid Build Coastguard Worker x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4);
210*33b1fccfSAndroid Build Coastguard Worker
211*33b1fccfSAndroid Build Coastguard Worker return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)) >> (16 - bits);
212*33b1fccfSAndroid Build Coastguard Worker }
213*33b1fccfSAndroid Build Coastguard Worker
Huffman_ReverseBits(u32 * codes,const u8 * lens,unsigned int n)214*33b1fccfSAndroid Build Coastguard Worker static void Huffman_ReverseBits(u32 *codes, const u8 *lens, unsigned int n)
215*33b1fccfSAndroid Build Coastguard Worker {
216*33b1fccfSAndroid Build Coastguard Worker while (n) {
217*33b1fccfSAndroid Build Coastguard Worker u32 code = *codes;
218*33b1fccfSAndroid Build Coastguard Worker
219*33b1fccfSAndroid Build Coastguard Worker *codes++ = deflate_reversebits_one(code, *lens++);
220*33b1fccfSAndroid Build Coastguard Worker --n;
221*33b1fccfSAndroid Build Coastguard Worker }
222*33b1fccfSAndroid Build Coastguard Worker }
223*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_init_once(void)224*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_init_once(void)
225*33b1fccfSAndroid Build Coastguard Worker {
226*33b1fccfSAndroid Build Coastguard Worker static const u32 static_bl_count[kMaxLen + 1] = {
227*33b1fccfSAndroid Build Coastguard Worker [7] = 279 - 256 + 1,
228*33b1fccfSAndroid Build Coastguard Worker [8] = (143 + 1) + (287 - 280 + 1),
229*33b1fccfSAndroid Build Coastguard Worker [9] = 255 - 144 + 1,
230*33b1fccfSAndroid Build Coastguard Worker };
231*33b1fccfSAndroid Build Coastguard Worker unsigned int i, c, j, k;
232*33b1fccfSAndroid Build Coastguard Worker
233*33b1fccfSAndroid Build Coastguard Worker if (kstaticHuff_distCodes[31])
234*33b1fccfSAndroid Build Coastguard Worker return;
235*33b1fccfSAndroid Build Coastguard Worker deflate_genhuffcodes(kstaticHuff_litLenLevels, kstaticHuff_mainCodes,
236*33b1fccfSAndroid Build Coastguard Worker kFixedLenTableSize, static_bl_count);
237*33b1fccfSAndroid Build Coastguard Worker Huffman_ReverseBits(kstaticHuff_mainCodes, kstaticHuff_litLenLevels,
238*33b1fccfSAndroid Build Coastguard Worker kFixedLenTableSize);
239*33b1fccfSAndroid Build Coastguard Worker
240*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(kstaticHuff_distCodes); ++i)
241*33b1fccfSAndroid Build Coastguard Worker kstaticHuff_distCodes[i] = deflate_reversebits_one(i, 5);
242*33b1fccfSAndroid Build Coastguard Worker
243*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < kNumLenSlots; i++) {
244*33b1fccfSAndroid Build Coastguard Worker c = kLenStart32[i];
245*33b1fccfSAndroid Build Coastguard Worker j = 1 << kLenExtraBits32[i];
246*33b1fccfSAndroid Build Coastguard Worker
247*33b1fccfSAndroid Build Coastguard Worker for (k = 0; k < j; k++, c++)
248*33b1fccfSAndroid Build Coastguard Worker g_LenSlots[c] = (u8)i;
249*33b1fccfSAndroid Build Coastguard Worker }
250*33b1fccfSAndroid Build Coastguard Worker
251*33b1fccfSAndroid Build Coastguard Worker c = 0;
252*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < /*kFastSlots*/ kNumLogBits * 2; i++) {
253*33b1fccfSAndroid Build Coastguard Worker k = 1 << kDistExtraBits[i];
254*33b1fccfSAndroid Build Coastguard Worker for (j = 0; j < k; j++)
255*33b1fccfSAndroid Build Coastguard Worker g_FastPos[c++] = i;
256*33b1fccfSAndroid Build Coastguard Worker }
257*33b1fccfSAndroid Build Coastguard Worker }
258*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_scanlens(unsigned int numlens,u8 * lens,u32 * freqs)259*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_scanlens(unsigned int numlens, u8 *lens, u32 *freqs)
260*33b1fccfSAndroid Build Coastguard Worker {
261*33b1fccfSAndroid Build Coastguard Worker int n; /* iterates over all tree elements */
262*33b1fccfSAndroid Build Coastguard Worker int prevlen = -1; /* last emitted length */
263*33b1fccfSAndroid Build Coastguard Worker int curlen; /* length of current code */
264*33b1fccfSAndroid Build Coastguard Worker int nextlen = lens[0]; /* length of next code */
265*33b1fccfSAndroid Build Coastguard Worker int count = 0; /* repeat count of the current code */
266*33b1fccfSAndroid Build Coastguard Worker int max_count = 7; /* max repeat count */
267*33b1fccfSAndroid Build Coastguard Worker int min_count = 4; /* min repeat count */
268*33b1fccfSAndroid Build Coastguard Worker
269*33b1fccfSAndroid Build Coastguard Worker if (!nextlen)
270*33b1fccfSAndroid Build Coastguard Worker max_count = 138, min_count = 3;
271*33b1fccfSAndroid Build Coastguard Worker
272*33b1fccfSAndroid Build Coastguard Worker for (n = 0; n < numlens; n++) {
273*33b1fccfSAndroid Build Coastguard Worker curlen = nextlen;
274*33b1fccfSAndroid Build Coastguard Worker nextlen = n + 1 < numlens ? lens[n + 1] : -1;
275*33b1fccfSAndroid Build Coastguard Worker ++count;
276*33b1fccfSAndroid Build Coastguard Worker
277*33b1fccfSAndroid Build Coastguard Worker if (count < max_count && curlen == nextlen)
278*33b1fccfSAndroid Build Coastguard Worker continue;
279*33b1fccfSAndroid Build Coastguard Worker if (count < min_count) {
280*33b1fccfSAndroid Build Coastguard Worker freqs[curlen] += count;
281*33b1fccfSAndroid Build Coastguard Worker } else if (curlen != 0) {
282*33b1fccfSAndroid Build Coastguard Worker if (curlen != prevlen)
283*33b1fccfSAndroid Build Coastguard Worker freqs[curlen]++;
284*33b1fccfSAndroid Build Coastguard Worker freqs[kBitLensRepNumber_3_6]++;
285*33b1fccfSAndroid Build Coastguard Worker } else if (count <= 10) {
286*33b1fccfSAndroid Build Coastguard Worker freqs[kBitLens0Number_3_10]++;
287*33b1fccfSAndroid Build Coastguard Worker } else {
288*33b1fccfSAndroid Build Coastguard Worker freqs[kBitLens0Number_11_138]++;
289*33b1fccfSAndroid Build Coastguard Worker }
290*33b1fccfSAndroid Build Coastguard Worker
291*33b1fccfSAndroid Build Coastguard Worker count = 0;
292*33b1fccfSAndroid Build Coastguard Worker prevlen = curlen;
293*33b1fccfSAndroid Build Coastguard Worker if (!nextlen)
294*33b1fccfSAndroid Build Coastguard Worker max_count = 138, min_count = 3;
295*33b1fccfSAndroid Build Coastguard Worker else if (curlen == nextlen)
296*33b1fccfSAndroid Build Coastguard Worker max_count = 6, min_count = 3;
297*33b1fccfSAndroid Build Coastguard Worker else
298*33b1fccfSAndroid Build Coastguard Worker max_count = 7, min_count = 4;
299*33b1fccfSAndroid Build Coastguard Worker }
300*33b1fccfSAndroid Build Coastguard Worker }
301*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_sendtree(struct kite_deflate * s,const u8 * lens,unsigned int numlens)302*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_sendtree(struct kite_deflate *s, const u8 *lens,
303*33b1fccfSAndroid Build Coastguard Worker unsigned int numlens)
304*33b1fccfSAndroid Build Coastguard Worker {
305*33b1fccfSAndroid Build Coastguard Worker int n; /* iterates over all tree elements */
306*33b1fccfSAndroid Build Coastguard Worker int prevlen = -1; /* last emitted length */
307*33b1fccfSAndroid Build Coastguard Worker int curlen; /* length of current code */
308*33b1fccfSAndroid Build Coastguard Worker int nextlen = lens[0]; /* length of next code */
309*33b1fccfSAndroid Build Coastguard Worker int count = 0; /* repeat count of the current code */
310*33b1fccfSAndroid Build Coastguard Worker int max_count = 7; /* max repeat count */
311*33b1fccfSAndroid Build Coastguard Worker int min_count = 4; /* min repeat count */
312*33b1fccfSAndroid Build Coastguard Worker const u8 *bl_lens = s->tab->levelLens;
313*33b1fccfSAndroid Build Coastguard Worker const u32 *bl_codes = s->tab->levelCodes;
314*33b1fccfSAndroid Build Coastguard Worker
315*33b1fccfSAndroid Build Coastguard Worker if (!nextlen)
316*33b1fccfSAndroid Build Coastguard Worker max_count = 138, min_count = 3;
317*33b1fccfSAndroid Build Coastguard Worker
318*33b1fccfSAndroid Build Coastguard Worker for (n = 0; n < numlens; n++) {
319*33b1fccfSAndroid Build Coastguard Worker curlen = nextlen;
320*33b1fccfSAndroid Build Coastguard Worker nextlen = n + 1 < numlens ? lens[n + 1] : -1;
321*33b1fccfSAndroid Build Coastguard Worker ++count;
322*33b1fccfSAndroid Build Coastguard Worker
323*33b1fccfSAndroid Build Coastguard Worker if (count < max_count && curlen == nextlen)
324*33b1fccfSAndroid Build Coastguard Worker continue;
325*33b1fccfSAndroid Build Coastguard Worker if (count < min_count) {
326*33b1fccfSAndroid Build Coastguard Worker do {
327*33b1fccfSAndroid Build Coastguard Worker writebits(s, bl_codes[curlen], bl_lens[curlen]);
328*33b1fccfSAndroid Build Coastguard Worker } while (--count);
329*33b1fccfSAndroid Build Coastguard Worker } else if (curlen) {
330*33b1fccfSAndroid Build Coastguard Worker if (curlen != prevlen) {
331*33b1fccfSAndroid Build Coastguard Worker writebits(s, bl_codes[curlen], bl_lens[curlen]);
332*33b1fccfSAndroid Build Coastguard Worker count--;
333*33b1fccfSAndroid Build Coastguard Worker }
334*33b1fccfSAndroid Build Coastguard Worker writebits(s, bl_codes[kBitLensRepNumber_3_6],
335*33b1fccfSAndroid Build Coastguard Worker bl_lens[kBitLensRepNumber_3_6]);
336*33b1fccfSAndroid Build Coastguard Worker writebits(s, count - 3, 2);
337*33b1fccfSAndroid Build Coastguard Worker } else if (count <= 10) {
338*33b1fccfSAndroid Build Coastguard Worker writebits(s, bl_codes[kBitLens0Number_3_10],
339*33b1fccfSAndroid Build Coastguard Worker bl_lens[kBitLens0Number_3_10]);
340*33b1fccfSAndroid Build Coastguard Worker writebits(s, count - 3, 3);
341*33b1fccfSAndroid Build Coastguard Worker } else {
342*33b1fccfSAndroid Build Coastguard Worker writebits(s, bl_codes[kBitLens0Number_11_138],
343*33b1fccfSAndroid Build Coastguard Worker bl_lens[kBitLens0Number_11_138]);
344*33b1fccfSAndroid Build Coastguard Worker writebits(s, count - 11, 7);
345*33b1fccfSAndroid Build Coastguard Worker }
346*33b1fccfSAndroid Build Coastguard Worker
347*33b1fccfSAndroid Build Coastguard Worker count = 0;
348*33b1fccfSAndroid Build Coastguard Worker prevlen = curlen;
349*33b1fccfSAndroid Build Coastguard Worker if (!nextlen)
350*33b1fccfSAndroid Build Coastguard Worker max_count = 138, min_count = 3;
351*33b1fccfSAndroid Build Coastguard Worker else if (curlen == nextlen)
352*33b1fccfSAndroid Build Coastguard Worker max_count = 6, min_count = 3;
353*33b1fccfSAndroid Build Coastguard Worker else
354*33b1fccfSAndroid Build Coastguard Worker max_count = 7, min_count = 4;
355*33b1fccfSAndroid Build Coastguard Worker }
356*33b1fccfSAndroid Build Coastguard Worker }
357*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_setfixedtrees(struct kite_deflate * s)358*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_setfixedtrees(struct kite_deflate *s)
359*33b1fccfSAndroid Build Coastguard Worker {
360*33b1fccfSAndroid Build Coastguard Worker writebits(s, (kFixedHuffman << 1) + s->lastblock, 3);
361*33b1fccfSAndroid Build Coastguard Worker }
362*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_sendtrees(struct kite_deflate * s)363*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_sendtrees(struct kite_deflate *s)
364*33b1fccfSAndroid Build Coastguard Worker {
365*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table *t = s->tab;
366*33b1fccfSAndroid Build Coastguard Worker unsigned int i;
367*33b1fccfSAndroid Build Coastguard Worker
368*33b1fccfSAndroid Build Coastguard Worker writebits(s, (kDynamicHuffman << 1) + s->lastblock, 3);
369*33b1fccfSAndroid Build Coastguard Worker writebits(s, t->numlitlens - kNumLitLenCodesMin, 5);
370*33b1fccfSAndroid Build Coastguard Worker writebits(s, t->numdistlens - kNumDistCodesMin, 5);
371*33b1fccfSAndroid Build Coastguard Worker writebits(s, t->numblcodes - kNumLensCodesMin, 4);
372*33b1fccfSAndroid Build Coastguard Worker
373*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < t->numblcodes; i++)
374*33b1fccfSAndroid Build Coastguard Worker writebits(s, t->levelLens[kCodeLengthAlphabetOrder[i]], 3);
375*33b1fccfSAndroid Build Coastguard Worker
376*33b1fccfSAndroid Build Coastguard Worker Huffman_ReverseBits(t->levelCodes, t->levelLens, kLensTableSize);
377*33b1fccfSAndroid Build Coastguard Worker kite_deflate_sendtree(s, t->litLenLevels, t->numlitlens);
378*33b1fccfSAndroid Build Coastguard Worker kite_deflate_sendtree(s, t->distLevels, t->numdistlens);
379*33b1fccfSAndroid Build Coastguard Worker }
380*33b1fccfSAndroid Build Coastguard Worker
deflateDistSlot(unsigned int pos)381*33b1fccfSAndroid Build Coastguard Worker static inline unsigned int deflateDistSlot(unsigned int pos)
382*33b1fccfSAndroid Build Coastguard Worker {
383*33b1fccfSAndroid Build Coastguard Worker const unsigned int zz = (kNumLogBits - 1) &
384*33b1fccfSAndroid Build Coastguard Worker ((((1U << kNumLogBits) - 1) - pos) >> (31 - 3));
385*33b1fccfSAndroid Build Coastguard Worker
386*33b1fccfSAndroid Build Coastguard Worker return g_FastPos[pos >> zz] + (zz * 2);
387*33b1fccfSAndroid Build Coastguard Worker }
388*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_writeblock(struct kite_deflate * s,bool fixed)389*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_writeblock(struct kite_deflate *s, bool fixed)
390*33b1fccfSAndroid Build Coastguard Worker {
391*33b1fccfSAndroid Build Coastguard Worker int i;
392*33b1fccfSAndroid Build Coastguard Worker u32 *mainCodes, *distCodes;
393*33b1fccfSAndroid Build Coastguard Worker const u8 *litLenLevels, *distLevels;
394*33b1fccfSAndroid Build Coastguard Worker
395*33b1fccfSAndroid Build Coastguard Worker if (!fixed) {
396*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table *t = s->tab;
397*33b1fccfSAndroid Build Coastguard Worker
398*33b1fccfSAndroid Build Coastguard Worker mainCodes = t->mainCodes; distCodes = t->distCodes;
399*33b1fccfSAndroid Build Coastguard Worker litLenLevels = t->litLenLevels; distLevels = t->distLevels;
400*33b1fccfSAndroid Build Coastguard Worker
401*33b1fccfSAndroid Build Coastguard Worker Huffman_ReverseBits(mainCodes, litLenLevels, kMainTableSize);
402*33b1fccfSAndroid Build Coastguard Worker Huffman_ReverseBits(distCodes, distLevels, kDistTableSize32);
403*33b1fccfSAndroid Build Coastguard Worker } else {
404*33b1fccfSAndroid Build Coastguard Worker mainCodes = kstaticHuff_mainCodes;
405*33b1fccfSAndroid Build Coastguard Worker distCodes = kstaticHuff_distCodes;
406*33b1fccfSAndroid Build Coastguard Worker
407*33b1fccfSAndroid Build Coastguard Worker litLenLevels = kstaticHuff_litLenLevels;
408*33b1fccfSAndroid Build Coastguard Worker distLevels = NULL;
409*33b1fccfSAndroid Build Coastguard Worker }
410*33b1fccfSAndroid Build Coastguard Worker
411*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < s->symbols; ++i) {
412*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_symbol *sym = &s->sym[i];
413*33b1fccfSAndroid Build Coastguard Worker
414*33b1fccfSAndroid Build Coastguard Worker if (sym->len < kMatchMinLen) { /* literal */
415*33b1fccfSAndroid Build Coastguard Worker writebits(s, mainCodes[sym->dist],
416*33b1fccfSAndroid Build Coastguard Worker litLenLevels[sym->dist]);
417*33b1fccfSAndroid Build Coastguard Worker } else {
418*33b1fccfSAndroid Build Coastguard Worker unsigned int lenSlot, distSlot;
419*33b1fccfSAndroid Build Coastguard Worker unsigned int lc = sym->len - kMatchMinLen;
420*33b1fccfSAndroid Build Coastguard Worker
421*33b1fccfSAndroid Build Coastguard Worker lenSlot = g_LenSlots[lc];
422*33b1fccfSAndroid Build Coastguard Worker writebits(s, mainCodes[kSymbolMatch + lenSlot],
423*33b1fccfSAndroid Build Coastguard Worker litLenLevels[kSymbolMatch + lenSlot]);
424*33b1fccfSAndroid Build Coastguard Worker writebits(s, lc - kLenStart32[lenSlot],
425*33b1fccfSAndroid Build Coastguard Worker kLenExtraBits32[lenSlot]);
426*33b1fccfSAndroid Build Coastguard Worker
427*33b1fccfSAndroid Build Coastguard Worker distSlot = deflateDistSlot(sym->dist - 1);
428*33b1fccfSAndroid Build Coastguard Worker writebits(s, distCodes[distSlot],
429*33b1fccfSAndroid Build Coastguard Worker fixed ? 5 : distLevels[distSlot]);
430*33b1fccfSAndroid Build Coastguard Worker writebits(s, sym->dist - 1 - kDistStart[distSlot],
431*33b1fccfSAndroid Build Coastguard Worker kDistExtraBits[distSlot]);
432*33b1fccfSAndroid Build Coastguard Worker }
433*33b1fccfSAndroid Build Coastguard Worker }
434*33b1fccfSAndroid Build Coastguard Worker writebits(s, mainCodes[kSymbolEndOfBlock],
435*33b1fccfSAndroid Build Coastguard Worker litLenLevels[kSymbolEndOfBlock]);
436*33b1fccfSAndroid Build Coastguard Worker }
437*33b1fccfSAndroid Build Coastguard Worker
Huffman_GetPrice(const u32 * freqs,const u8 * lens,u32 num)438*33b1fccfSAndroid Build Coastguard Worker static u32 Huffman_GetPrice(const u32 *freqs, const u8 *lens, u32 num)
439*33b1fccfSAndroid Build Coastguard Worker {
440*33b1fccfSAndroid Build Coastguard Worker u32 price = 0;
441*33b1fccfSAndroid Build Coastguard Worker
442*33b1fccfSAndroid Build Coastguard Worker while (num) {
443*33b1fccfSAndroid Build Coastguard Worker price += (*lens++) * (*freqs++);
444*33b1fccfSAndroid Build Coastguard Worker --num;
445*33b1fccfSAndroid Build Coastguard Worker }
446*33b1fccfSAndroid Build Coastguard Worker return price;
447*33b1fccfSAndroid Build Coastguard Worker }
448*33b1fccfSAndroid Build Coastguard Worker
Huffman_GetPriceEx(const u32 * freqs,const u8 * lens,u32 num,const u8 * extraBits,u32 extraBase)449*33b1fccfSAndroid Build Coastguard Worker static u32 Huffman_GetPriceEx(const u32 *freqs, const u8 *lens, u32 num,
450*33b1fccfSAndroid Build Coastguard Worker const u8 *extraBits, u32 extraBase)
451*33b1fccfSAndroid Build Coastguard Worker {
452*33b1fccfSAndroid Build Coastguard Worker return Huffman_GetPrice(freqs, lens, num) +
453*33b1fccfSAndroid Build Coastguard Worker Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase);
454*33b1fccfSAndroid Build Coastguard Worker }
455*33b1fccfSAndroid Build Coastguard Worker
456*33b1fccfSAndroid Build Coastguard Worker /* Adapted from C/HuffEnc.c (7zip) for now */
457*33b1fccfSAndroid Build Coastguard Worker #define HeapSortDown(p, k, size, temp) \
458*33b1fccfSAndroid Build Coastguard Worker { for (;;) { \
459*33b1fccfSAndroid Build Coastguard Worker size_t s = (k << 1); \
460*33b1fccfSAndroid Build Coastguard Worker if (s > size) break; \
461*33b1fccfSAndroid Build Coastguard Worker if (s < size && p[s + 1] > p[s]) s++; \
462*33b1fccfSAndroid Build Coastguard Worker if (temp >= p[s]) break; \
463*33b1fccfSAndroid Build Coastguard Worker p[k] = p[s]; k = s; \
464*33b1fccfSAndroid Build Coastguard Worker } p[k] = temp; }
465*33b1fccfSAndroid Build Coastguard Worker
HeapSort(u32 * p,size_t size)466*33b1fccfSAndroid Build Coastguard Worker static void HeapSort(u32 *p, size_t size)
467*33b1fccfSAndroid Build Coastguard Worker {
468*33b1fccfSAndroid Build Coastguard Worker if (size <= 1)
469*33b1fccfSAndroid Build Coastguard Worker return;
470*33b1fccfSAndroid Build Coastguard Worker p--;
471*33b1fccfSAndroid Build Coastguard Worker {
472*33b1fccfSAndroid Build Coastguard Worker size_t i = size / 2;
473*33b1fccfSAndroid Build Coastguard Worker do
474*33b1fccfSAndroid Build Coastguard Worker {
475*33b1fccfSAndroid Build Coastguard Worker u32 temp = p[i];
476*33b1fccfSAndroid Build Coastguard Worker size_t k = i;
477*33b1fccfSAndroid Build Coastguard Worker HeapSortDown(p, k, size, temp)
478*33b1fccfSAndroid Build Coastguard Worker }
479*33b1fccfSAndroid Build Coastguard Worker while (--i != 0);
480*33b1fccfSAndroid Build Coastguard Worker }
481*33b1fccfSAndroid Build Coastguard Worker /*
482*33b1fccfSAndroid Build Coastguard Worker do
483*33b1fccfSAndroid Build Coastguard Worker {
484*33b1fccfSAndroid Build Coastguard Worker size_t k = 1;
485*33b1fccfSAndroid Build Coastguard Worker UInt32 temp = p[size];
486*33b1fccfSAndroid Build Coastguard Worker p[size--] = p[1];
487*33b1fccfSAndroid Build Coastguard Worker HeapSortDown(p, k, size, temp)
488*33b1fccfSAndroid Build Coastguard Worker }
489*33b1fccfSAndroid Build Coastguard Worker while (size > 1);
490*33b1fccfSAndroid Build Coastguard Worker */
491*33b1fccfSAndroid Build Coastguard Worker while (size > 3)
492*33b1fccfSAndroid Build Coastguard Worker {
493*33b1fccfSAndroid Build Coastguard Worker u32 temp = p[size];
494*33b1fccfSAndroid Build Coastguard Worker size_t k = (p[3] > p[2]) ? 3 : 2;
495*33b1fccfSAndroid Build Coastguard Worker p[size--] = p[1];
496*33b1fccfSAndroid Build Coastguard Worker p[1] = p[k];
497*33b1fccfSAndroid Build Coastguard Worker HeapSortDown(p, k, size, temp)
498*33b1fccfSAndroid Build Coastguard Worker }
499*33b1fccfSAndroid Build Coastguard Worker {
500*33b1fccfSAndroid Build Coastguard Worker u32 temp = p[size];
501*33b1fccfSAndroid Build Coastguard Worker p[size] = p[1];
502*33b1fccfSAndroid Build Coastguard Worker if (size > 2 && p[2] < temp)
503*33b1fccfSAndroid Build Coastguard Worker {
504*33b1fccfSAndroid Build Coastguard Worker p[1] = p[2];
505*33b1fccfSAndroid Build Coastguard Worker p[2] = temp;
506*33b1fccfSAndroid Build Coastguard Worker }
507*33b1fccfSAndroid Build Coastguard Worker else
508*33b1fccfSAndroid Build Coastguard Worker p[1] = temp;
509*33b1fccfSAndroid Build Coastguard Worker }
510*33b1fccfSAndroid Build Coastguard Worker }
511*33b1fccfSAndroid Build Coastguard Worker
512*33b1fccfSAndroid Build Coastguard Worker #define NUM_BITS 10
513*33b1fccfSAndroid Build Coastguard Worker #define MASK (((unsigned)1 << NUM_BITS) - 1)
514*33b1fccfSAndroid Build Coastguard Worker
Huffman_Generate(const u32 * freqs,u32 * p,u8 * lens,unsigned int numSymbols,unsigned int maxLen)515*33b1fccfSAndroid Build Coastguard Worker static void Huffman_Generate(const u32 *freqs, u32 *p, u8 *lens,
516*33b1fccfSAndroid Build Coastguard Worker unsigned int numSymbols, unsigned int maxLen)
517*33b1fccfSAndroid Build Coastguard Worker {
518*33b1fccfSAndroid Build Coastguard Worker u32 num, i;
519*33b1fccfSAndroid Build Coastguard Worker
520*33b1fccfSAndroid Build Coastguard Worker num = 0;
521*33b1fccfSAndroid Build Coastguard Worker /* if (maxLen > 10) maxLen = 10; */
522*33b1fccfSAndroid Build Coastguard Worker
523*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < numSymbols; i++) {
524*33b1fccfSAndroid Build Coastguard Worker u32 freq = freqs[i];
525*33b1fccfSAndroid Build Coastguard Worker
526*33b1fccfSAndroid Build Coastguard Worker if (!freq)
527*33b1fccfSAndroid Build Coastguard Worker lens[i] = 0;
528*33b1fccfSAndroid Build Coastguard Worker else
529*33b1fccfSAndroid Build Coastguard Worker p[num++] = i | (freq << NUM_BITS);
530*33b1fccfSAndroid Build Coastguard Worker }
531*33b1fccfSAndroid Build Coastguard Worker HeapSort(p, num);
532*33b1fccfSAndroid Build Coastguard Worker
533*33b1fccfSAndroid Build Coastguard Worker if (num < 2) {
534*33b1fccfSAndroid Build Coastguard Worker unsigned int minCode = 0, maxCode = 1;
535*33b1fccfSAndroid Build Coastguard Worker
536*33b1fccfSAndroid Build Coastguard Worker if (num == 1) {
537*33b1fccfSAndroid Build Coastguard Worker maxCode = (unsigned int)p[0] & MASK;
538*33b1fccfSAndroid Build Coastguard Worker if (!maxCode)
539*33b1fccfSAndroid Build Coastguard Worker maxCode++;
540*33b1fccfSAndroid Build Coastguard Worker }
541*33b1fccfSAndroid Build Coastguard Worker p[minCode] = 0;
542*33b1fccfSAndroid Build Coastguard Worker p[maxCode] = 1;
543*33b1fccfSAndroid Build Coastguard Worker lens[minCode] = lens[maxCode] = 1;
544*33b1fccfSAndroid Build Coastguard Worker return;
545*33b1fccfSAndroid Build Coastguard Worker }
546*33b1fccfSAndroid Build Coastguard Worker
547*33b1fccfSAndroid Build Coastguard Worker {
548*33b1fccfSAndroid Build Coastguard Worker u32 b, e, i;
549*33b1fccfSAndroid Build Coastguard Worker
550*33b1fccfSAndroid Build Coastguard Worker i = b = e = 0;
551*33b1fccfSAndroid Build Coastguard Worker do {
552*33b1fccfSAndroid Build Coastguard Worker u32 n, m, freq;
553*33b1fccfSAndroid Build Coastguard Worker
554*33b1fccfSAndroid Build Coastguard Worker n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
555*33b1fccfSAndroid Build Coastguard Worker freq = (p[n] & ~MASK);
556*33b1fccfSAndroid Build Coastguard Worker p[n] = (p[n] & MASK) | (e << NUM_BITS);
557*33b1fccfSAndroid Build Coastguard Worker m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
558*33b1fccfSAndroid Build Coastguard Worker freq += (p[m] & ~MASK);
559*33b1fccfSAndroid Build Coastguard Worker p[m] = (p[m] & MASK) | (e << NUM_BITS);
560*33b1fccfSAndroid Build Coastguard Worker p[e] = (p[e] & MASK) | freq;
561*33b1fccfSAndroid Build Coastguard Worker e++;
562*33b1fccfSAndroid Build Coastguard Worker } while (num - e > 1);
563*33b1fccfSAndroid Build Coastguard Worker
564*33b1fccfSAndroid Build Coastguard Worker {
565*33b1fccfSAndroid Build Coastguard Worker u32 lenCounters[kMaxLen + 1];
566*33b1fccfSAndroid Build Coastguard Worker
567*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i <= kMaxLen; i++)
568*33b1fccfSAndroid Build Coastguard Worker lenCounters[i] = 0;
569*33b1fccfSAndroid Build Coastguard Worker
570*33b1fccfSAndroid Build Coastguard Worker p[--e] &= MASK;
571*33b1fccfSAndroid Build Coastguard Worker lenCounters[1] = 2;
572*33b1fccfSAndroid Build Coastguard Worker while (e > 0) {
573*33b1fccfSAndroid Build Coastguard Worker u32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
574*33b1fccfSAndroid Build Coastguard Worker
575*33b1fccfSAndroid Build Coastguard Worker p[e] = (p[e] & MASK) | (len << NUM_BITS);
576*33b1fccfSAndroid Build Coastguard Worker if (len >= maxLen)
577*33b1fccfSAndroid Build Coastguard Worker for (len = maxLen - 1; lenCounters[len] == 0; len--);
578*33b1fccfSAndroid Build Coastguard Worker lenCounters[len]--;
579*33b1fccfSAndroid Build Coastguard Worker lenCounters[(size_t)len + 1] += 2;
580*33b1fccfSAndroid Build Coastguard Worker }
581*33b1fccfSAndroid Build Coastguard Worker
582*33b1fccfSAndroid Build Coastguard Worker {
583*33b1fccfSAndroid Build Coastguard Worker u32 len;
584*33b1fccfSAndroid Build Coastguard Worker
585*33b1fccfSAndroid Build Coastguard Worker i = 0;
586*33b1fccfSAndroid Build Coastguard Worker for (len = maxLen; len != 0; len--) {
587*33b1fccfSAndroid Build Coastguard Worker u32 k;
588*33b1fccfSAndroid Build Coastguard Worker for (k = lenCounters[len]; k != 0; k--)
589*33b1fccfSAndroid Build Coastguard Worker lens[p[i++] & MASK] = (u8)len;
590*33b1fccfSAndroid Build Coastguard Worker }
591*33b1fccfSAndroid Build Coastguard Worker }
592*33b1fccfSAndroid Build Coastguard Worker deflate_genhuffcodes(lens, p, numSymbols, lenCounters);
593*33b1fccfSAndroid Build Coastguard Worker }
594*33b1fccfSAndroid Build Coastguard Worker }
595*33b1fccfSAndroid Build Coastguard Worker }
596*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_fixdynblock(struct kite_deflate * s)597*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_fixdynblock(struct kite_deflate *s)
598*33b1fccfSAndroid Build Coastguard Worker {
599*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table *t = s->tab;
600*33b1fccfSAndroid Build Coastguard Worker unsigned int numlitlens, numdistlens, numblcodes;
601*33b1fccfSAndroid Build Coastguard Worker u32 levelFreqs[kLensTableSize] = {0};
602*33b1fccfSAndroid Build Coastguard Worker u32 opt_mainlen;
603*33b1fccfSAndroid Build Coastguard Worker
604*33b1fccfSAndroid Build Coastguard Worker if (!s->freq_changed)
605*33b1fccfSAndroid Build Coastguard Worker return;
606*33b1fccfSAndroid Build Coastguard Worker
607*33b1fccfSAndroid Build Coastguard Worker /* in order to match zlib */
608*33b1fccfSAndroid Build Coastguard Worker s->numHuffBits = kMaxLen;
609*33b1fccfSAndroid Build Coastguard Worker // s->numHuffBits = (s->symbols > 18000 ? 12 :
610*33b1fccfSAndroid Build Coastguard Worker // (s->symbols > 7000 ? 11 : (s->symbols > 2000 ? 10 : 9)));
611*33b1fccfSAndroid Build Coastguard Worker
612*33b1fccfSAndroid Build Coastguard Worker Huffman_Generate(s->mainFreqs, t->mainCodes, t->litLenLevels,
613*33b1fccfSAndroid Build Coastguard Worker kMainTableSize, s->numHuffBits);
614*33b1fccfSAndroid Build Coastguard Worker Huffman_Generate(s->distFreqs, t->distCodes, t->distLevels,
615*33b1fccfSAndroid Build Coastguard Worker kDistTableSize32, s->numHuffBits);
616*33b1fccfSAndroid Build Coastguard Worker
617*33b1fccfSAndroid Build Coastguard Worker /* code lengths for the literal/length alphabet */
618*33b1fccfSAndroid Build Coastguard Worker numlitlens = kMainTableSize;
619*33b1fccfSAndroid Build Coastguard Worker while (numlitlens > kNumLitLenCodesMin &&
620*33b1fccfSAndroid Build Coastguard Worker !t->litLenLevels[numlitlens - 1])
621*33b1fccfSAndroid Build Coastguard Worker --numlitlens;
622*33b1fccfSAndroid Build Coastguard Worker
623*33b1fccfSAndroid Build Coastguard Worker /* code lengths for the distance alphabet */
624*33b1fccfSAndroid Build Coastguard Worker numdistlens = kDistTableSize32;
625*33b1fccfSAndroid Build Coastguard Worker while (numdistlens > kNumDistCodesMin &&
626*33b1fccfSAndroid Build Coastguard Worker !t->distLevels[numdistlens - 1])
627*33b1fccfSAndroid Build Coastguard Worker --numdistlens;
628*33b1fccfSAndroid Build Coastguard Worker
629*33b1fccfSAndroid Build Coastguard Worker kite_deflate_scanlens(numlitlens, t->litLenLevels, levelFreqs);
630*33b1fccfSAndroid Build Coastguard Worker kite_deflate_scanlens(numdistlens, t->distLevels, levelFreqs);
631*33b1fccfSAndroid Build Coastguard Worker Huffman_Generate(levelFreqs, t->levelCodes, t->levelLens,
632*33b1fccfSAndroid Build Coastguard Worker kLensTableSize, 7);
633*33b1fccfSAndroid Build Coastguard Worker numblcodes = kLensTableSize;
634*33b1fccfSAndroid Build Coastguard Worker while (numblcodes > kNumLensCodesMin &&
635*33b1fccfSAndroid Build Coastguard Worker !t->levelLens[kCodeLengthAlphabetOrder[numblcodes - 1]])
636*33b1fccfSAndroid Build Coastguard Worker --numblcodes;
637*33b1fccfSAndroid Build Coastguard Worker
638*33b1fccfSAndroid Build Coastguard Worker t->numlitlens = numlitlens;
639*33b1fccfSAndroid Build Coastguard Worker t->numdistlens = numdistlens;
640*33b1fccfSAndroid Build Coastguard Worker t->numblcodes = numblcodes;
641*33b1fccfSAndroid Build Coastguard Worker
642*33b1fccfSAndroid Build Coastguard Worker opt_mainlen = Huffman_GetPriceEx(s->mainFreqs, t->litLenLevels,
643*33b1fccfSAndroid Build Coastguard Worker kMainTableSize, kLenExtraBits32, kSymbolMatch) +
644*33b1fccfSAndroid Build Coastguard Worker Huffman_GetPriceEx(s->distFreqs, t->distLevels,
645*33b1fccfSAndroid Build Coastguard Worker kDistTableSize32, kDistExtraBits, 0);
646*33b1fccfSAndroid Build Coastguard Worker s->costbits = 3 + 5 + 5 + 4 + 3 * numblcodes +
647*33b1fccfSAndroid Build Coastguard Worker Huffman_GetPriceEx(levelFreqs, t->levelLens,
648*33b1fccfSAndroid Build Coastguard Worker kLensTableSize, kLevelExtraBits, kTableDirectLevels) +
649*33b1fccfSAndroid Build Coastguard Worker opt_mainlen;
650*33b1fccfSAndroid Build Coastguard Worker s->freq_changed = false;
651*33b1fccfSAndroid Build Coastguard Worker }
652*33b1fccfSAndroid Build Coastguard Worker
653*33b1fccfSAndroid Build Coastguard Worker
654*33b1fccfSAndroid Build Coastguard Worker /*
655*33b1fccfSAndroid Build Coastguard Worker * an array used used by the LZ-based encoder to hold the length-distance pairs
656*33b1fccfSAndroid Build Coastguard Worker * found by LZ matchfinder.
657*33b1fccfSAndroid Build Coastguard Worker */
658*33b1fccfSAndroid Build Coastguard Worker struct kite_match {
659*33b1fccfSAndroid Build Coastguard Worker unsigned int len;
660*33b1fccfSAndroid Build Coastguard Worker unsigned int dist;
661*33b1fccfSAndroid Build Coastguard Worker };
662*33b1fccfSAndroid Build Coastguard Worker
663*33b1fccfSAndroid Build Coastguard Worker struct kite_matchfinder {
664*33b1fccfSAndroid Build Coastguard Worker /* pointer to buffer with data to be compressed */
665*33b1fccfSAndroid Build Coastguard Worker const u8 *buffer;
666*33b1fccfSAndroid Build Coastguard Worker
667*33b1fccfSAndroid Build Coastguard Worker /* indicate the first byte that doesn't contain valid input data */
668*33b1fccfSAndroid Build Coastguard Worker const u8 *end;
669*33b1fccfSAndroid Build Coastguard Worker
670*33b1fccfSAndroid Build Coastguard Worker /* LZ matchfinder hash chain representation */
671*33b1fccfSAndroid Build Coastguard Worker u32 *hash, *chain;
672*33b1fccfSAndroid Build Coastguard Worker
673*33b1fccfSAndroid Build Coastguard Worker u32 base;
674*33b1fccfSAndroid Build Coastguard Worker
675*33b1fccfSAndroid Build Coastguard Worker /* indicate the next byte to run through the match finder */
676*33b1fccfSAndroid Build Coastguard Worker u32 offset;
677*33b1fccfSAndroid Build Coastguard Worker
678*33b1fccfSAndroid Build Coastguard Worker u32 cyclic_pos;
679*33b1fccfSAndroid Build Coastguard Worker
680*33b1fccfSAndroid Build Coastguard Worker /* maximum length of a match that the matchfinder will try to find. */
681*33b1fccfSAndroid Build Coastguard Worker u16 nice_len;
682*33b1fccfSAndroid Build Coastguard Worker
683*33b1fccfSAndroid Build Coastguard Worker /* the total sliding window size */
684*33b1fccfSAndroid Build Coastguard Worker u16 wsiz;
685*33b1fccfSAndroid Build Coastguard Worker
686*33b1fccfSAndroid Build Coastguard Worker /* how many rounds a matchfinder searches on a hash chain for */
687*33b1fccfSAndroid Build Coastguard Worker u16 depth;
688*33b1fccfSAndroid Build Coastguard Worker
689*33b1fccfSAndroid Build Coastguard Worker /* do not perform lazy search no less than this match length */
690*33b1fccfSAndroid Build Coastguard Worker u16 max_lazy;
691*33b1fccfSAndroid Build Coastguard Worker
692*33b1fccfSAndroid Build Coastguard Worker /* reduce lazy search no less than this match length */
693*33b1fccfSAndroid Build Coastguard Worker u8 good_len;
694*33b1fccfSAndroid Build Coastguard Worker
695*33b1fccfSAndroid Build Coastguard Worker /* current match for lazy matching */
696*33b1fccfSAndroid Build Coastguard Worker struct kite_match *matches;
697*33b1fccfSAndroid Build Coastguard Worker struct kite_match matches_matrix[2][4];
698*33b1fccfSAndroid Build Coastguard Worker };
699*33b1fccfSAndroid Build Coastguard Worker
700*33b1fccfSAndroid Build Coastguard Worker /*
701*33b1fccfSAndroid Build Coastguard Worker * This mysterious table is just the CRC of each possible byte. It can be
702*33b1fccfSAndroid Build Coastguard Worker * computed using the standard bit-at-a-time methods. The polynomial can
703*33b1fccfSAndroid Build Coastguard Worker * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
704*33b1fccfSAndroid Build Coastguard Worker * Add the implicit x^16, and you have the standard CRC-CCITT.
705*33b1fccfSAndroid Build Coastguard Worker */
706*33b1fccfSAndroid Build Coastguard Worker u16 const crc_ccitt_table[256] __attribute__((__aligned__(128))) = {
707*33b1fccfSAndroid Build Coastguard Worker 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
708*33b1fccfSAndroid Build Coastguard Worker 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
709*33b1fccfSAndroid Build Coastguard Worker 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
710*33b1fccfSAndroid Build Coastguard Worker 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
711*33b1fccfSAndroid Build Coastguard Worker 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
712*33b1fccfSAndroid Build Coastguard Worker 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
713*33b1fccfSAndroid Build Coastguard Worker 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
714*33b1fccfSAndroid Build Coastguard Worker 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
715*33b1fccfSAndroid Build Coastguard Worker 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
716*33b1fccfSAndroid Build Coastguard Worker 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
717*33b1fccfSAndroid Build Coastguard Worker 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
718*33b1fccfSAndroid Build Coastguard Worker 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
719*33b1fccfSAndroid Build Coastguard Worker 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
720*33b1fccfSAndroid Build Coastguard Worker 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
721*33b1fccfSAndroid Build Coastguard Worker 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
722*33b1fccfSAndroid Build Coastguard Worker 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
723*33b1fccfSAndroid Build Coastguard Worker 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
724*33b1fccfSAndroid Build Coastguard Worker 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
725*33b1fccfSAndroid Build Coastguard Worker 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
726*33b1fccfSAndroid Build Coastguard Worker 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
727*33b1fccfSAndroid Build Coastguard Worker 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
728*33b1fccfSAndroid Build Coastguard Worker 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
729*33b1fccfSAndroid Build Coastguard Worker 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
730*33b1fccfSAndroid Build Coastguard Worker 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
731*33b1fccfSAndroid Build Coastguard Worker 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
732*33b1fccfSAndroid Build Coastguard Worker 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
733*33b1fccfSAndroid Build Coastguard Worker 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
734*33b1fccfSAndroid Build Coastguard Worker 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
735*33b1fccfSAndroid Build Coastguard Worker 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
736*33b1fccfSAndroid Build Coastguard Worker 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
737*33b1fccfSAndroid Build Coastguard Worker 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
738*33b1fccfSAndroid Build Coastguard Worker 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
739*33b1fccfSAndroid Build Coastguard Worker };
740*33b1fccfSAndroid Build Coastguard Worker
kite_mf_getmatches_hc3(struct kite_matchfinder * mf,u16 depth,u16 bestlen)741*33b1fccfSAndroid Build Coastguard Worker int kite_mf_getmatches_hc3(struct kite_matchfinder *mf, u16 depth, u16 bestlen)
742*33b1fccfSAndroid Build Coastguard Worker {
743*33b1fccfSAndroid Build Coastguard Worker const u8 *cur = mf->buffer + mf->offset;
744*33b1fccfSAndroid Build Coastguard Worker const u8 *qbase = mf->buffer - mf->base;
745*33b1fccfSAndroid Build Coastguard Worker u32 curMatch;
746*33b1fccfSAndroid Build Coastguard Worker unsigned int v, hv, i, k, p, wsiz;
747*33b1fccfSAndroid Build Coastguard Worker
748*33b1fccfSAndroid Build Coastguard Worker if (mf->end - cur < bestlen + 1)
749*33b1fccfSAndroid Build Coastguard Worker return -1;
750*33b1fccfSAndroid Build Coastguard Worker
751*33b1fccfSAndroid Build Coastguard Worker v = get_unaligned((u16 *)cur);
752*33b1fccfSAndroid Build Coastguard Worker hv = v ^ crc_ccitt_table[cur[2]];
753*33b1fccfSAndroid Build Coastguard Worker curMatch = mf->hash[hv];
754*33b1fccfSAndroid Build Coastguard Worker p = mf->base + mf->offset;
755*33b1fccfSAndroid Build Coastguard Worker mf->hash[hv] = p;
756*33b1fccfSAndroid Build Coastguard Worker mf->chain[mf->cyclic_pos] = curMatch;
757*33b1fccfSAndroid Build Coastguard Worker wsiz = mf->wsiz;
758*33b1fccfSAndroid Build Coastguard Worker k = 1;
759*33b1fccfSAndroid Build Coastguard Worker
760*33b1fccfSAndroid Build Coastguard Worker if (depth) {
761*33b1fccfSAndroid Build Coastguard Worker unsigned int wpos = wsiz + mf->cyclic_pos;
762*33b1fccfSAndroid Build Coastguard Worker
763*33b1fccfSAndroid Build Coastguard Worker hv = min_t(unsigned int, mf->nice_len, mf->end - cur);
764*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(hv > kMatchMaxLen32);
765*33b1fccfSAndroid Build Coastguard Worker do {
766*33b1fccfSAndroid Build Coastguard Worker unsigned int diff = p - curMatch;
767*33b1fccfSAndroid Build Coastguard Worker const u8 *q;
768*33b1fccfSAndroid Build Coastguard Worker
769*33b1fccfSAndroid Build Coastguard Worker if (diff >= wsiz)
770*33b1fccfSAndroid Build Coastguard Worker break;
771*33b1fccfSAndroid Build Coastguard Worker
772*33b1fccfSAndroid Build Coastguard Worker q = qbase + curMatch;
773*33b1fccfSAndroid Build Coastguard Worker curMatch = mf->chain[(wpos - diff) & (wsiz - 1)];
774*33b1fccfSAndroid Build Coastguard Worker if (v == get_unaligned((u16 *)q) && (bestlen < 3 || (
775*33b1fccfSAndroid Build Coastguard Worker get_unaligned((u16 *)(cur + bestlen - 1)) ==
776*33b1fccfSAndroid Build Coastguard Worker get_unaligned((u16 *)(q + bestlen - 1)) &&
777*33b1fccfSAndroid Build Coastguard Worker !memcmp(cur + 3, q + 3, bestlen - 3)))) {
778*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(cur[2] != q[2]);
779*33b1fccfSAndroid Build Coastguard Worker i = erofs_memcmp2(cur + bestlen + 1,
780*33b1fccfSAndroid Build Coastguard Worker q + bestlen + 1, hv - bestlen - 1);
781*33b1fccfSAndroid Build Coastguard Worker bestlen += 1 + i;
782*33b1fccfSAndroid Build Coastguard Worker
783*33b1fccfSAndroid Build Coastguard Worker k -= (k >= ARRAY_SIZE(mf->matches_matrix[0]));
784*33b1fccfSAndroid Build Coastguard Worker mf->matches[k++] = (struct kite_match) {
785*33b1fccfSAndroid Build Coastguard Worker .len = bestlen,
786*33b1fccfSAndroid Build Coastguard Worker .dist = diff,
787*33b1fccfSAndroid Build Coastguard Worker };
788*33b1fccfSAndroid Build Coastguard Worker if (bestlen >= hv)
789*33b1fccfSAndroid Build Coastguard Worker break;
790*33b1fccfSAndroid Build Coastguard Worker }
791*33b1fccfSAndroid Build Coastguard Worker } while (--depth);
792*33b1fccfSAndroid Build Coastguard Worker }
793*33b1fccfSAndroid Build Coastguard Worker mf->offset++;
794*33b1fccfSAndroid Build Coastguard Worker mf->cyclic_pos = (mf->cyclic_pos + 1) & (wsiz - 1);
795*33b1fccfSAndroid Build Coastguard Worker return k - 1;
796*33b1fccfSAndroid Build Coastguard Worker }
797*33b1fccfSAndroid Build Coastguard Worker
kite_mf_hc3_skip(struct kite_matchfinder * mf)798*33b1fccfSAndroid Build Coastguard Worker static void kite_mf_hc3_skip(struct kite_matchfinder *mf)
799*33b1fccfSAndroid Build Coastguard Worker {
800*33b1fccfSAndroid Build Coastguard Worker if (kite_mf_getmatches_hc3(mf, 0, 2) >= 0)
801*33b1fccfSAndroid Build Coastguard Worker return;
802*33b1fccfSAndroid Build Coastguard Worker mf->offset++;
803*33b1fccfSAndroid Build Coastguard Worker /* mf->cyclic_pos = (mf->cyclic_pos + 1) & (mf->wsiz - 1); */
804*33b1fccfSAndroid Build Coastguard Worker }
805*33b1fccfSAndroid Build Coastguard Worker
806*33b1fccfSAndroid Build Coastguard Worker /* let's align with zlib */
807*33b1fccfSAndroid Build Coastguard Worker static const struct kite_matchfinder_cfg {
808*33b1fccfSAndroid Build Coastguard Worker u16 good_length; /* reduce lazy search above this match length */
809*33b1fccfSAndroid Build Coastguard Worker u16 max_lazy; /* do not perform lazy search above this match length */
810*33b1fccfSAndroid Build Coastguard Worker u16 nice_length; /* quit search above this match length */
811*33b1fccfSAndroid Build Coastguard Worker u16 depth;
812*33b1fccfSAndroid Build Coastguard Worker bool lazy_search;
813*33b1fccfSAndroid Build Coastguard Worker } kite_mfcfg[10] = {
814*33b1fccfSAndroid Build Coastguard Worker /* good lazy nice depth */
815*33b1fccfSAndroid Build Coastguard Worker /* 0 */ {0, 0, 0, 0, false}, /* store only [unsupported] */
816*33b1fccfSAndroid Build Coastguard Worker /* 1 */ {4, 4, 8, 4, false}, /* maximum speed, no lazy matches */
817*33b1fccfSAndroid Build Coastguard Worker /* 2 */ {4, 5, 16, 8, false},
818*33b1fccfSAndroid Build Coastguard Worker /* 3 */ {4, 6, 32, 32, false},
819*33b1fccfSAndroid Build Coastguard Worker
820*33b1fccfSAndroid Build Coastguard Worker /* 4 */ {4, 4, 16, 16, true}, /* lazy matches */
821*33b1fccfSAndroid Build Coastguard Worker /* 5 */ {8, 16, 32, 32, true},
822*33b1fccfSAndroid Build Coastguard Worker /* 6 */ {8, 16, 128, 128, true},
823*33b1fccfSAndroid Build Coastguard Worker /* 7 */ {8, 32, 128, 256, true},
824*33b1fccfSAndroid Build Coastguard Worker /* 8 */ {32, 128, 258, 1024, true},
825*33b1fccfSAndroid Build Coastguard Worker /* 9 */ {32, 258, 258, 4096, true}, /* maximum compression */
826*33b1fccfSAndroid Build Coastguard Worker };
827*33b1fccfSAndroid Build Coastguard Worker
kite_mf_init(struct kite_matchfinder * mf,unsigned int wsiz,int level)828*33b1fccfSAndroid Build Coastguard Worker static int kite_mf_init(struct kite_matchfinder *mf, unsigned int wsiz,
829*33b1fccfSAndroid Build Coastguard Worker int level)
830*33b1fccfSAndroid Build Coastguard Worker {
831*33b1fccfSAndroid Build Coastguard Worker const struct kite_matchfinder_cfg *cfg;
832*33b1fccfSAndroid Build Coastguard Worker
833*33b1fccfSAndroid Build Coastguard Worker if (!level || level >= ARRAY_SIZE(kite_mfcfg))
834*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
835*33b1fccfSAndroid Build Coastguard Worker cfg = &kite_mfcfg[level];
836*33b1fccfSAndroid Build Coastguard Worker
837*33b1fccfSAndroid Build Coastguard Worker if (wsiz > kHistorySize32 || (1 << ilog2(wsiz)) != wsiz)
838*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
839*33b1fccfSAndroid Build Coastguard Worker
840*33b1fccfSAndroid Build Coastguard Worker mf->hash = calloc(0x10000, sizeof(mf->hash[0]));
841*33b1fccfSAndroid Build Coastguard Worker if (!mf->hash)
842*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
843*33b1fccfSAndroid Build Coastguard Worker
844*33b1fccfSAndroid Build Coastguard Worker mf->chain = malloc(sizeof(mf->chain[0]) * wsiz);
845*33b1fccfSAndroid Build Coastguard Worker if (!mf->chain) {
846*33b1fccfSAndroid Build Coastguard Worker free(mf->hash);
847*33b1fccfSAndroid Build Coastguard Worker mf->hash = NULL;
848*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
849*33b1fccfSAndroid Build Coastguard Worker }
850*33b1fccfSAndroid Build Coastguard Worker mf->wsiz = wsiz;
851*33b1fccfSAndroid Build Coastguard Worker
852*33b1fccfSAndroid Build Coastguard Worker mf->good_len = cfg->good_length;
853*33b1fccfSAndroid Build Coastguard Worker mf->nice_len = cfg->nice_length;
854*33b1fccfSAndroid Build Coastguard Worker mf->depth = cfg->depth;
855*33b1fccfSAndroid Build Coastguard Worker mf->max_lazy = cfg->max_lazy;
856*33b1fccfSAndroid Build Coastguard Worker return cfg->lazy_search;
857*33b1fccfSAndroid Build Coastguard Worker }
858*33b1fccfSAndroid Build Coastguard Worker
kite_mf_reset(struct kite_matchfinder * mf,const void * buffer,const void * end)859*33b1fccfSAndroid Build Coastguard Worker static void kite_mf_reset(struct kite_matchfinder *mf,
860*33b1fccfSAndroid Build Coastguard Worker const void *buffer, const void *end)
861*33b1fccfSAndroid Build Coastguard Worker {
862*33b1fccfSAndroid Build Coastguard Worker mf->buffer = buffer;
863*33b1fccfSAndroid Build Coastguard Worker mf->end = end;
864*33b1fccfSAndroid Build Coastguard Worker
865*33b1fccfSAndroid Build Coastguard Worker /*
866*33b1fccfSAndroid Build Coastguard Worker * Set the initial value as max_distance + 1. This would avoid hash
867*33b1fccfSAndroid Build Coastguard Worker * zero initialization.
868*33b1fccfSAndroid Build Coastguard Worker */
869*33b1fccfSAndroid Build Coastguard Worker mf->base += mf->offset + kHistorySize32 + 1;
870*33b1fccfSAndroid Build Coastguard Worker
871*33b1fccfSAndroid Build Coastguard Worker /*
872*33b1fccfSAndroid Build Coastguard Worker * Unlike other LZ encoders like liblzma [1], we simply reset the hash
873*33b1fccfSAndroid Build Coastguard Worker * chain instead of normalization. This avoids extra complexity, as we
874*33b1fccfSAndroid Build Coastguard Worker * don't consider extreme large input buffers in one go.
875*33b1fccfSAndroid Build Coastguard Worker *
876*33b1fccfSAndroid Build Coastguard Worker * [1] https://github.com/tukaani-project/xz/blob/v5.4.0/src/liblzma/lz/lz_encoder_mf.c#L94
877*33b1fccfSAndroid Build Coastguard Worker */
878*33b1fccfSAndroid Build Coastguard Worker if (__erofs_unlikely(mf->base > ((typeof(mf->base))-1) >> 1)) {
879*33b1fccfSAndroid Build Coastguard Worker mf->base = kHistorySize32 + 1;
880*33b1fccfSAndroid Build Coastguard Worker memset(mf->hash, 0, 0x10000 * sizeof(mf->hash[0]));
881*33b1fccfSAndroid Build Coastguard Worker }
882*33b1fccfSAndroid Build Coastguard Worker mf->offset = 0;
883*33b1fccfSAndroid Build Coastguard Worker mf->cyclic_pos = 0;
884*33b1fccfSAndroid Build Coastguard Worker
885*33b1fccfSAndroid Build Coastguard Worker mf->matches = mf->matches_matrix[0];
886*33b1fccfSAndroid Build Coastguard Worker mf->matches_matrix[0][0].len =
887*33b1fccfSAndroid Build Coastguard Worker mf->matches_matrix[1][0].len = kMatchMinLen - 1;
888*33b1fccfSAndroid Build Coastguard Worker }
889*33b1fccfSAndroid Build Coastguard Worker
deflate_count_code(struct kite_deflate * s,bool literal,unsigned int lenSlot,unsigned int distSlot)890*33b1fccfSAndroid Build Coastguard Worker static bool deflate_count_code(struct kite_deflate *s, bool literal,
891*33b1fccfSAndroid Build Coastguard Worker unsigned int lenSlot, unsigned int distSlot)
892*33b1fccfSAndroid Build Coastguard Worker {
893*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_table *t = s->tab;
894*33b1fccfSAndroid Build Coastguard Worker unsigned int lenbase = (literal ? 0 : kSymbolMatch);
895*33b1fccfSAndroid Build Coastguard Worker u64 rem = (s->outlen - s->pos_out) * 8 - s->bitpos;
896*33b1fccfSAndroid Build Coastguard Worker bool recalc = false;
897*33b1fccfSAndroid Build Coastguard Worker unsigned int bits;
898*33b1fccfSAndroid Build Coastguard Worker
899*33b1fccfSAndroid Build Coastguard Worker s->freq_changed = true;
900*33b1fccfSAndroid Build Coastguard Worker ++s->mainFreqs[lenbase + lenSlot];
901*33b1fccfSAndroid Build Coastguard Worker if (!literal)
902*33b1fccfSAndroid Build Coastguard Worker ++s->distFreqs[distSlot];
903*33b1fccfSAndroid Build Coastguard Worker
904*33b1fccfSAndroid Build Coastguard Worker if (s->encode_mode == 1) {
905*33b1fccfSAndroid Build Coastguard Worker if (literal) {
906*33b1fccfSAndroid Build Coastguard Worker bits = kstaticHuff_litLenLevels[lenSlot];
907*33b1fccfSAndroid Build Coastguard Worker goto out;
908*33b1fccfSAndroid Build Coastguard Worker }
909*33b1fccfSAndroid Build Coastguard Worker bits = kstaticHuff_litLenLevels[kSymbolMatch + lenSlot] +
910*33b1fccfSAndroid Build Coastguard Worker kLenExtraBits32[lenSlot] + 5 + kDistExtraBits[distSlot];
911*33b1fccfSAndroid Build Coastguard Worker goto out;
912*33b1fccfSAndroid Build Coastguard Worker }
913*33b1fccfSAndroid Build Coastguard Worker
914*33b1fccfSAndroid Build Coastguard Worker /* XXX: more ideas to be done later */
915*33b1fccfSAndroid Build Coastguard Worker recalc |= (!literal && !t->distLevels[distSlot]);
916*33b1fccfSAndroid Build Coastguard Worker recalc |= !t->litLenLevels[lenbase + lenSlot];
917*33b1fccfSAndroid Build Coastguard Worker if (recalc) {
918*33b1fccfSAndroid Build Coastguard Worker kite_dbg("recalc %c lS %u dS %u", literal ? 'l' : 'm',
919*33b1fccfSAndroid Build Coastguard Worker lenSlot, distSlot);
920*33b1fccfSAndroid Build Coastguard Worker s->tab = s->tables + (s->tab == s->tables);
921*33b1fccfSAndroid Build Coastguard Worker kite_deflate_fixdynblock(s);
922*33b1fccfSAndroid Build Coastguard Worker bits = 0;
923*33b1fccfSAndroid Build Coastguard Worker goto out;
924*33b1fccfSAndroid Build Coastguard Worker }
925*33b1fccfSAndroid Build Coastguard Worker
926*33b1fccfSAndroid Build Coastguard Worker if (literal) {
927*33b1fccfSAndroid Build Coastguard Worker bits = t->litLenLevels[lenSlot];
928*33b1fccfSAndroid Build Coastguard Worker goto out;
929*33b1fccfSAndroid Build Coastguard Worker }
930*33b1fccfSAndroid Build Coastguard Worker
931*33b1fccfSAndroid Build Coastguard Worker bits = t->distLevels[distSlot] + kDistExtraBits[distSlot] +
932*33b1fccfSAndroid Build Coastguard Worker t->litLenLevels[kSymbolMatch + lenSlot] +
933*33b1fccfSAndroid Build Coastguard Worker kLenExtraBits32[lenSlot];
934*33b1fccfSAndroid Build Coastguard Worker out:
935*33b1fccfSAndroid Build Coastguard Worker if (rem < s->costbits + bits) {
936*33b1fccfSAndroid Build Coastguard Worker --s->mainFreqs[lenbase + lenSlot];
937*33b1fccfSAndroid Build Coastguard Worker if (!literal)
938*33b1fccfSAndroid Build Coastguard Worker --s->distFreqs[distSlot];
939*33b1fccfSAndroid Build Coastguard Worker if (recalc)
940*33b1fccfSAndroid Build Coastguard Worker s->tab = s->tables + (s->tab == s->tables);
941*33b1fccfSAndroid Build Coastguard Worker return false;
942*33b1fccfSAndroid Build Coastguard Worker }
943*33b1fccfSAndroid Build Coastguard Worker s->costbits += bits;
944*33b1fccfSAndroid Build Coastguard Worker return true;
945*33b1fccfSAndroid Build Coastguard Worker }
946*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_tally(struct kite_deflate * s,struct kite_match * match)947*33b1fccfSAndroid Build Coastguard Worker static bool kite_deflate_tally(struct kite_deflate *s,
948*33b1fccfSAndroid Build Coastguard Worker struct kite_match *match)
949*33b1fccfSAndroid Build Coastguard Worker {
950*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate_symbol *sym = s->sym + s->symbols;
951*33b1fccfSAndroid Build Coastguard Worker u32 fixedcost = ~0;
952*33b1fccfSAndroid Build Coastguard Worker bool hassp;
953*33b1fccfSAndroid Build Coastguard Worker
954*33b1fccfSAndroid Build Coastguard Worker *sym = (struct kite_deflate_symbol) {
955*33b1fccfSAndroid Build Coastguard Worker .len = match->len,
956*33b1fccfSAndroid Build Coastguard Worker .dist = match->dist,
957*33b1fccfSAndroid Build Coastguard Worker };
958*33b1fccfSAndroid Build Coastguard Worker
959*33b1fccfSAndroid Build Coastguard Worker retry:
960*33b1fccfSAndroid Build Coastguard Worker if (sym->len < kMatchMinLen) {
961*33b1fccfSAndroid Build Coastguard Worker hassp = deflate_count_code(s, true, sym->dist, 0);
962*33b1fccfSAndroid Build Coastguard Worker } else {
963*33b1fccfSAndroid Build Coastguard Worker unsigned int lc = sym->len - kMatchMinLen;
964*33b1fccfSAndroid Build Coastguard Worker unsigned int lenSlot = g_LenSlots[lc];
965*33b1fccfSAndroid Build Coastguard Worker unsigned int distSlot = deflateDistSlot(sym->dist - 1);
966*33b1fccfSAndroid Build Coastguard Worker
967*33b1fccfSAndroid Build Coastguard Worker hassp = deflate_count_code(s, false, lenSlot, distSlot);
968*33b1fccfSAndroid Build Coastguard Worker }
969*33b1fccfSAndroid Build Coastguard Worker
970*33b1fccfSAndroid Build Coastguard Worker if (!hassp) {
971*33b1fccfSAndroid Build Coastguard Worker if (s->encode_mode == 1) {
972*33b1fccfSAndroid Build Coastguard Worker fixedcost = s->costbits;
973*33b1fccfSAndroid Build Coastguard Worker s->encode_mode = 2;
974*33b1fccfSAndroid Build Coastguard Worker goto retry;
975*33b1fccfSAndroid Build Coastguard Worker }
976*33b1fccfSAndroid Build Coastguard Worker s->lastblock = true;
977*33b1fccfSAndroid Build Coastguard Worker if (fixedcost <= s->costbits)
978*33b1fccfSAndroid Build Coastguard Worker s->encode_mode = 1;
979*33b1fccfSAndroid Build Coastguard Worker return true;
980*33b1fccfSAndroid Build Coastguard Worker }
981*33b1fccfSAndroid Build Coastguard Worker ++s->symbols;
982*33b1fccfSAndroid Build Coastguard Worker return false;
983*33b1fccfSAndroid Build Coastguard Worker }
984*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_writestore(struct kite_deflate * s)985*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_writestore(struct kite_deflate *s)
986*33b1fccfSAndroid Build Coastguard Worker {
987*33b1fccfSAndroid Build Coastguard Worker bool fb = !s->startpos && !s->bitpos;
988*33b1fccfSAndroid Build Coastguard Worker unsigned int totalsiz = s->pos_in - s->prev_valid - s->startpos;
989*33b1fccfSAndroid Build Coastguard Worker
990*33b1fccfSAndroid Build Coastguard Worker do {
991*33b1fccfSAndroid Build Coastguard Worker unsigned int len = min_t(unsigned int, totalsiz, 65535);
992*33b1fccfSAndroid Build Coastguard Worker
993*33b1fccfSAndroid Build Coastguard Worker totalsiz -= len;
994*33b1fccfSAndroid Build Coastguard Worker writebits(s, (fb << 3) | (kStored << 1) |
995*33b1fccfSAndroid Build Coastguard Worker (s->lastblock && !totalsiz), 3 + fb);
996*33b1fccfSAndroid Build Coastguard Worker flushbits(s);
997*33b1fccfSAndroid Build Coastguard Worker writebits(s, len, 16);
998*33b1fccfSAndroid Build Coastguard Worker writebits(s, len ^ 0xffff, 16);
999*33b1fccfSAndroid Build Coastguard Worker flushbits(s);
1000*33b1fccfSAndroid Build Coastguard Worker memcpy(s->out + s->pos_out, s->in + s->startpos, len);
1001*33b1fccfSAndroid Build Coastguard Worker s->pos_out += len;
1002*33b1fccfSAndroid Build Coastguard Worker s->startpos += len;
1003*33b1fccfSAndroid Build Coastguard Worker } while (totalsiz);
1004*33b1fccfSAndroid Build Coastguard Worker }
1005*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_endblock(struct kite_deflate * s)1006*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_endblock(struct kite_deflate *s)
1007*33b1fccfSAndroid Build Coastguard Worker {
1008*33b1fccfSAndroid Build Coastguard Worker if (s->encode_mode == 1) {
1009*33b1fccfSAndroid Build Coastguard Worker u32 fixedcost = s->costbits;
1010*33b1fccfSAndroid Build Coastguard Worker unsigned int storelen, storeblocks, storecost;
1011*33b1fccfSAndroid Build Coastguard Worker
1012*33b1fccfSAndroid Build Coastguard Worker kite_deflate_fixdynblock(s);
1013*33b1fccfSAndroid Build Coastguard Worker if (fixedcost > s->costbits)
1014*33b1fccfSAndroid Build Coastguard Worker s->encode_mode = 2;
1015*33b1fccfSAndroid Build Coastguard Worker else
1016*33b1fccfSAndroid Build Coastguard Worker s->costbits = fixedcost;
1017*33b1fccfSAndroid Build Coastguard Worker
1018*33b1fccfSAndroid Build Coastguard Worker storelen = s->pos_in - s->prev_valid - s->startpos;
1019*33b1fccfSAndroid Build Coastguard Worker storeblocks = max(DIV_ROUND_UP(storelen, 65535), 1U);
1020*33b1fccfSAndroid Build Coastguard Worker storecost = (8 - s->bitpos) + storeblocks - 1 +
1021*33b1fccfSAndroid Build Coastguard Worker storeblocks * 32 + storelen * 8;
1022*33b1fccfSAndroid Build Coastguard Worker if (s->costbits > storecost) {
1023*33b1fccfSAndroid Build Coastguard Worker s->costbits = storecost;
1024*33b1fccfSAndroid Build Coastguard Worker s->encode_mode = 0;
1025*33b1fccfSAndroid Build Coastguard Worker }
1026*33b1fccfSAndroid Build Coastguard Worker }
1027*33b1fccfSAndroid Build Coastguard Worker
1028*33b1fccfSAndroid Build Coastguard Worker s->lastblock |= (s->costbits + s->bitpos >=
1029*33b1fccfSAndroid Build Coastguard Worker (s->outlen - s->pos_out) * 8);
1030*33b1fccfSAndroid Build Coastguard Worker }
1031*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_startblock(struct kite_deflate * s)1032*33b1fccfSAndroid Build Coastguard Worker static void kite_deflate_startblock(struct kite_deflate *s)
1033*33b1fccfSAndroid Build Coastguard Worker {
1034*33b1fccfSAndroid Build Coastguard Worker memset(s->mainFreqs, 0, sizeof(s->mainFreqs));
1035*33b1fccfSAndroid Build Coastguard Worker memset(s->distFreqs, 0, sizeof(s->distFreqs));
1036*33b1fccfSAndroid Build Coastguard Worker memset(s->tables, 0, sizeof(s->tables[0]));
1037*33b1fccfSAndroid Build Coastguard Worker s->symbols = 0;
1038*33b1fccfSAndroid Build Coastguard Worker s->mainFreqs[kSymbolEndOfBlock]++;
1039*33b1fccfSAndroid Build Coastguard Worker s->encode_mode = 1;
1040*33b1fccfSAndroid Build Coastguard Worker s->tab = s->tables;
1041*33b1fccfSAndroid Build Coastguard Worker s->costbits = 3 + kstaticHuff_litLenLevels[kSymbolEndOfBlock];
1042*33b1fccfSAndroid Build Coastguard Worker }
1043*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_commitblock(struct kite_deflate * s)1044*33b1fccfSAndroid Build Coastguard Worker static bool kite_deflate_commitblock(struct kite_deflate *s)
1045*33b1fccfSAndroid Build Coastguard Worker {
1046*33b1fccfSAndroid Build Coastguard Worker if (s->encode_mode == 1) {
1047*33b1fccfSAndroid Build Coastguard Worker kite_deflate_setfixedtrees(s);
1048*33b1fccfSAndroid Build Coastguard Worker kite_deflate_writeblock(s, true);
1049*33b1fccfSAndroid Build Coastguard Worker } else if (s->encode_mode == 2) {
1050*33b1fccfSAndroid Build Coastguard Worker kite_deflate_sendtrees(s);
1051*33b1fccfSAndroid Build Coastguard Worker kite_deflate_writeblock(s, false);
1052*33b1fccfSAndroid Build Coastguard Worker } else {
1053*33b1fccfSAndroid Build Coastguard Worker kite_deflate_writestore(s);
1054*33b1fccfSAndroid Build Coastguard Worker }
1055*33b1fccfSAndroid Build Coastguard Worker s->startpos = s->pos_in - s->prev_valid;
1056*33b1fccfSAndroid Build Coastguard Worker return s->lastblock;
1057*33b1fccfSAndroid Build Coastguard Worker }
1058*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_fast(struct kite_deflate * s)1059*33b1fccfSAndroid Build Coastguard Worker static bool kite_deflate_fast(struct kite_deflate *s)
1060*33b1fccfSAndroid Build Coastguard Worker {
1061*33b1fccfSAndroid Build Coastguard Worker struct kite_matchfinder *mf = s->mf;
1062*33b1fccfSAndroid Build Coastguard Worker
1063*33b1fccfSAndroid Build Coastguard Worker kite_deflate_startblock(s);
1064*33b1fccfSAndroid Build Coastguard Worker while (1) {
1065*33b1fccfSAndroid Build Coastguard Worker int matches = kite_mf_getmatches_hc3(mf, mf->depth,
1066*33b1fccfSAndroid Build Coastguard Worker kMatchMinLen - 1);
1067*33b1fccfSAndroid Build Coastguard Worker
1068*33b1fccfSAndroid Build Coastguard Worker if (matches > 0) {
1069*33b1fccfSAndroid Build Coastguard Worker unsigned int len = mf->matches[matches].len;
1070*33b1fccfSAndroid Build Coastguard Worker unsigned int dist = mf->matches[matches].dist;
1071*33b1fccfSAndroid Build Coastguard Worker
1072*33b1fccfSAndroid Build Coastguard Worker if (len == kMatchMinLen && dist > ZLIB_DISTANCE_TOO_FAR)
1073*33b1fccfSAndroid Build Coastguard Worker goto nomatch;
1074*33b1fccfSAndroid Build Coastguard Worker
1075*33b1fccfSAndroid Build Coastguard Worker kite_dbg("%u matches found: longest [%u,%u] of distance %u",
1076*33b1fccfSAndroid Build Coastguard Worker matches, s->pos_in, s->pos_in + len - 1, dist);
1077*33b1fccfSAndroid Build Coastguard Worker
1078*33b1fccfSAndroid Build Coastguard Worker if (kite_deflate_tally(s, mf->matches + matches))
1079*33b1fccfSAndroid Build Coastguard Worker break;
1080*33b1fccfSAndroid Build Coastguard Worker s->pos_in += len;
1081*33b1fccfSAndroid Build Coastguard Worker /* skip the rest bytes */
1082*33b1fccfSAndroid Build Coastguard Worker while (--len)
1083*33b1fccfSAndroid Build Coastguard Worker kite_mf_hc3_skip(mf);
1084*33b1fccfSAndroid Build Coastguard Worker } else {
1085*33b1fccfSAndroid Build Coastguard Worker nomatch:
1086*33b1fccfSAndroid Build Coastguard Worker mf->matches[0].dist = s->in[s->pos_in];
1087*33b1fccfSAndroid Build Coastguard Worker if (isprint(s->in[s->pos_in]))
1088*33b1fccfSAndroid Build Coastguard Worker kite_dbg("literal %c pos_in %u", s->in[s->pos_in], s->pos_in);
1089*33b1fccfSAndroid Build Coastguard Worker else
1090*33b1fccfSAndroid Build Coastguard Worker kite_dbg("literal %x pos_in %u", s->in[s->pos_in], s->pos_in);
1091*33b1fccfSAndroid Build Coastguard Worker
1092*33b1fccfSAndroid Build Coastguard Worker if (kite_deflate_tally(s, mf->matches))
1093*33b1fccfSAndroid Build Coastguard Worker break;
1094*33b1fccfSAndroid Build Coastguard Worker ++s->pos_in;
1095*33b1fccfSAndroid Build Coastguard Worker }
1096*33b1fccfSAndroid Build Coastguard Worker
1097*33b1fccfSAndroid Build Coastguard Worker s->lastblock |= (s->pos_in >= s->inlen);
1098*33b1fccfSAndroid Build Coastguard Worker if (s->pos_in >= s->inlen || s->symbols >= s->max_symbols) {
1099*33b1fccfSAndroid Build Coastguard Worker kite_deflate_endblock(s);
1100*33b1fccfSAndroid Build Coastguard Worker break;
1101*33b1fccfSAndroid Build Coastguard Worker }
1102*33b1fccfSAndroid Build Coastguard Worker }
1103*33b1fccfSAndroid Build Coastguard Worker return kite_deflate_commitblock(s);
1104*33b1fccfSAndroid Build Coastguard Worker }
1105*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_slow(struct kite_deflate * s)1106*33b1fccfSAndroid Build Coastguard Worker static bool kite_deflate_slow(struct kite_deflate *s)
1107*33b1fccfSAndroid Build Coastguard Worker {
1108*33b1fccfSAndroid Build Coastguard Worker struct kite_matchfinder *mf = s->mf;
1109*33b1fccfSAndroid Build Coastguard Worker bool flush = false;
1110*33b1fccfSAndroid Build Coastguard Worker
1111*33b1fccfSAndroid Build Coastguard Worker kite_deflate_startblock(s);
1112*33b1fccfSAndroid Build Coastguard Worker while (1) {
1113*33b1fccfSAndroid Build Coastguard Worker struct kite_match *prev_matches = mf->matches;
1114*33b1fccfSAndroid Build Coastguard Worker unsigned int len = kMatchMinLen - 1;
1115*33b1fccfSAndroid Build Coastguard Worker int matches;
1116*33b1fccfSAndroid Build Coastguard Worker unsigned int len0;
1117*33b1fccfSAndroid Build Coastguard Worker
1118*33b1fccfSAndroid Build Coastguard Worker mf->matches = mf->matches_matrix[
1119*33b1fccfSAndroid Build Coastguard Worker mf->matches == mf->matches_matrix[0]];
1120*33b1fccfSAndroid Build Coastguard Worker mf->matches[0].dist = s->in[s->pos_in];
1121*33b1fccfSAndroid Build Coastguard Worker
1122*33b1fccfSAndroid Build Coastguard Worker len0 = prev_matches[s->prev_longest].len;
1123*33b1fccfSAndroid Build Coastguard Worker if (len0 < mf->max_lazy) {
1124*33b1fccfSAndroid Build Coastguard Worker matches = kite_mf_getmatches_hc3(mf, mf->depth >>
1125*33b1fccfSAndroid Build Coastguard Worker (len0 >= mf->good_len), len0);
1126*33b1fccfSAndroid Build Coastguard Worker if (matches > 0) {
1127*33b1fccfSAndroid Build Coastguard Worker len = mf->matches[matches].len;
1128*33b1fccfSAndroid Build Coastguard Worker if (len == kMatchMinLen &&
1129*33b1fccfSAndroid Build Coastguard Worker mf->matches[matches].dist > ZLIB_DISTANCE_TOO_FAR) {
1130*33b1fccfSAndroid Build Coastguard Worker matches = 0;
1131*33b1fccfSAndroid Build Coastguard Worker len = kMatchMinLen - 1;
1132*33b1fccfSAndroid Build Coastguard Worker }
1133*33b1fccfSAndroid Build Coastguard Worker } else {
1134*33b1fccfSAndroid Build Coastguard Worker matches = 0;
1135*33b1fccfSAndroid Build Coastguard Worker }
1136*33b1fccfSAndroid Build Coastguard Worker } else {
1137*33b1fccfSAndroid Build Coastguard Worker matches = 0;
1138*33b1fccfSAndroid Build Coastguard Worker kite_mf_hc3_skip(mf);
1139*33b1fccfSAndroid Build Coastguard Worker }
1140*33b1fccfSAndroid Build Coastguard Worker
1141*33b1fccfSAndroid Build Coastguard Worker if (len < len0) {
1142*33b1fccfSAndroid Build Coastguard Worker if (kite_deflate_tally(s,
1143*33b1fccfSAndroid Build Coastguard Worker prev_matches + s->prev_longest))
1144*33b1fccfSAndroid Build Coastguard Worker break;
1145*33b1fccfSAndroid Build Coastguard Worker
1146*33b1fccfSAndroid Build Coastguard Worker s->pos_in += --len0;
1147*33b1fccfSAndroid Build Coastguard Worker /* skip the rest bytes */
1148*33b1fccfSAndroid Build Coastguard Worker while (--len0)
1149*33b1fccfSAndroid Build Coastguard Worker kite_mf_hc3_skip(mf);
1150*33b1fccfSAndroid Build Coastguard Worker s->prev_valid = false;
1151*33b1fccfSAndroid Build Coastguard Worker s->prev_longest = 0;
1152*33b1fccfSAndroid Build Coastguard Worker } else {
1153*33b1fccfSAndroid Build Coastguard Worker if (!s->prev_valid)
1154*33b1fccfSAndroid Build Coastguard Worker s->prev_valid = true;
1155*33b1fccfSAndroid Build Coastguard Worker else if (kite_deflate_tally(s, prev_matches))
1156*33b1fccfSAndroid Build Coastguard Worker break;
1157*33b1fccfSAndroid Build Coastguard Worker ++s->pos_in;
1158*33b1fccfSAndroid Build Coastguard Worker s->prev_longest = matches;
1159*33b1fccfSAndroid Build Coastguard Worker }
1160*33b1fccfSAndroid Build Coastguard Worker
1161*33b1fccfSAndroid Build Coastguard Worker s->lastblock |= (s->pos_in >= s->inlen);
1162*33b1fccfSAndroid Build Coastguard Worker if (s->pos_in >= s->inlen) {
1163*33b1fccfSAndroid Build Coastguard Worker flush = true;
1164*33b1fccfSAndroid Build Coastguard Worker break;
1165*33b1fccfSAndroid Build Coastguard Worker }
1166*33b1fccfSAndroid Build Coastguard Worker if (s->symbols >= s->max_symbols) {
1167*33b1fccfSAndroid Build Coastguard Worker kite_deflate_endblock(s);
1168*33b1fccfSAndroid Build Coastguard Worker break;
1169*33b1fccfSAndroid Build Coastguard Worker }
1170*33b1fccfSAndroid Build Coastguard Worker }
1171*33b1fccfSAndroid Build Coastguard Worker
1172*33b1fccfSAndroid Build Coastguard Worker if (flush && s->prev_valid) {
1173*33b1fccfSAndroid Build Coastguard Worker (void)kite_deflate_tally(s, mf->matches + s->prev_longest);
1174*33b1fccfSAndroid Build Coastguard Worker s->prev_valid = false;
1175*33b1fccfSAndroid Build Coastguard Worker }
1176*33b1fccfSAndroid Build Coastguard Worker return kite_deflate_commitblock(s);
1177*33b1fccfSAndroid Build Coastguard Worker }
1178*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_end(struct kite_deflate * s)1179*33b1fccfSAndroid Build Coastguard Worker void kite_deflate_end(struct kite_deflate *s)
1180*33b1fccfSAndroid Build Coastguard Worker {
1181*33b1fccfSAndroid Build Coastguard Worker if (s->mf) {
1182*33b1fccfSAndroid Build Coastguard Worker if (s->mf->hash)
1183*33b1fccfSAndroid Build Coastguard Worker free(s->mf->hash);
1184*33b1fccfSAndroid Build Coastguard Worker if (s->mf->chain)
1185*33b1fccfSAndroid Build Coastguard Worker free(s->mf->chain);
1186*33b1fccfSAndroid Build Coastguard Worker free(s->mf);
1187*33b1fccfSAndroid Build Coastguard Worker }
1188*33b1fccfSAndroid Build Coastguard Worker if (s->sym)
1189*33b1fccfSAndroid Build Coastguard Worker free(s->sym);
1190*33b1fccfSAndroid Build Coastguard Worker free(s);
1191*33b1fccfSAndroid Build Coastguard Worker }
1192*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_init(int level,unsigned int dict_size)1193*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate *kite_deflate_init(int level, unsigned int dict_size)
1194*33b1fccfSAndroid Build Coastguard Worker {
1195*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate *s;
1196*33b1fccfSAndroid Build Coastguard Worker int err;
1197*33b1fccfSAndroid Build Coastguard Worker
1198*33b1fccfSAndroid Build Coastguard Worker kite_deflate_init_once();
1199*33b1fccfSAndroid Build Coastguard Worker s = calloc(1, sizeof(*s));
1200*33b1fccfSAndroid Build Coastguard Worker if (!s)
1201*33b1fccfSAndroid Build Coastguard Worker return ERR_PTR(-ENOMEM);
1202*33b1fccfSAndroid Build Coastguard Worker
1203*33b1fccfSAndroid Build Coastguard Worker s->max_symbols = 16384;
1204*33b1fccfSAndroid Build Coastguard Worker s->sym = malloc(sizeof(s->sym[0]) * s->max_symbols);
1205*33b1fccfSAndroid Build Coastguard Worker if (!s->sym) {
1206*33b1fccfSAndroid Build Coastguard Worker err = -ENOMEM;
1207*33b1fccfSAndroid Build Coastguard Worker goto err_out;
1208*33b1fccfSAndroid Build Coastguard Worker }
1209*33b1fccfSAndroid Build Coastguard Worker
1210*33b1fccfSAndroid Build Coastguard Worker s->mf = malloc(sizeof(*s->mf));
1211*33b1fccfSAndroid Build Coastguard Worker if (!s->mf) {
1212*33b1fccfSAndroid Build Coastguard Worker err = -ENOMEM;
1213*33b1fccfSAndroid Build Coastguard Worker goto err_out;
1214*33b1fccfSAndroid Build Coastguard Worker }
1215*33b1fccfSAndroid Build Coastguard Worker
1216*33b1fccfSAndroid Build Coastguard Worker if (!dict_size)
1217*33b1fccfSAndroid Build Coastguard Worker dict_size = kHistorySize32;
1218*33b1fccfSAndroid Build Coastguard Worker
1219*33b1fccfSAndroid Build Coastguard Worker err = kite_mf_init(s->mf, dict_size, level);
1220*33b1fccfSAndroid Build Coastguard Worker if (err < 0)
1221*33b1fccfSAndroid Build Coastguard Worker goto err_out;
1222*33b1fccfSAndroid Build Coastguard Worker
1223*33b1fccfSAndroid Build Coastguard Worker s->lazy_search = err;
1224*33b1fccfSAndroid Build Coastguard Worker return s;
1225*33b1fccfSAndroid Build Coastguard Worker err_out:
1226*33b1fccfSAndroid Build Coastguard Worker if (s->mf)
1227*33b1fccfSAndroid Build Coastguard Worker free(s->mf);
1228*33b1fccfSAndroid Build Coastguard Worker if (s->sym)
1229*33b1fccfSAndroid Build Coastguard Worker free(s->sym);
1230*33b1fccfSAndroid Build Coastguard Worker free(s);
1231*33b1fccfSAndroid Build Coastguard Worker return ERR_PTR(err);
1232*33b1fccfSAndroid Build Coastguard Worker }
1233*33b1fccfSAndroid Build Coastguard Worker
kite_deflate_destsize(struct kite_deflate * s,const u8 * in,u8 * out,unsigned int * srcsize,unsigned int target_dstsize)1234*33b1fccfSAndroid Build Coastguard Worker int kite_deflate_destsize(struct kite_deflate *s, const u8 *in, u8 *out,
1235*33b1fccfSAndroid Build Coastguard Worker unsigned int *srcsize, unsigned int target_dstsize)
1236*33b1fccfSAndroid Build Coastguard Worker {
1237*33b1fccfSAndroid Build Coastguard Worker memset(s, 0, offsetof(struct kite_deflate, mainFreqs));
1238*33b1fccfSAndroid Build Coastguard Worker s->in = in;
1239*33b1fccfSAndroid Build Coastguard Worker s->inlen = *srcsize;
1240*33b1fccfSAndroid Build Coastguard Worker s->out = out;
1241*33b1fccfSAndroid Build Coastguard Worker s->outlen = target_dstsize;
1242*33b1fccfSAndroid Build Coastguard Worker kite_mf_reset(s->mf, in, in + s->inlen);
1243*33b1fccfSAndroid Build Coastguard Worker
1244*33b1fccfSAndroid Build Coastguard Worker if (s->lazy_search)
1245*33b1fccfSAndroid Build Coastguard Worker while (!kite_deflate_slow(s));
1246*33b1fccfSAndroid Build Coastguard Worker else
1247*33b1fccfSAndroid Build Coastguard Worker while (!kite_deflate_fast(s));
1248*33b1fccfSAndroid Build Coastguard Worker flushbits(s);
1249*33b1fccfSAndroid Build Coastguard Worker
1250*33b1fccfSAndroid Build Coastguard Worker *srcsize = s->startpos;
1251*33b1fccfSAndroid Build Coastguard Worker return s->pos_out;
1252*33b1fccfSAndroid Build Coastguard Worker }
1253*33b1fccfSAndroid Build Coastguard Worker
1254*33b1fccfSAndroid Build Coastguard Worker #if TEST
1255*33b1fccfSAndroid Build Coastguard Worker #include <unistd.h>
1256*33b1fccfSAndroid Build Coastguard Worker #include <fcntl.h>
1257*33b1fccfSAndroid Build Coastguard Worker #include <sys/mman.h>
1258*33b1fccfSAndroid Build Coastguard Worker
main(int argc,char * argv[])1259*33b1fccfSAndroid Build Coastguard Worker int main(int argc, char *argv[])
1260*33b1fccfSAndroid Build Coastguard Worker {
1261*33b1fccfSAndroid Build Coastguard Worker int fd;
1262*33b1fccfSAndroid Build Coastguard Worker u64 filelength;
1263*33b1fccfSAndroid Build Coastguard Worker u8 out[1048576], *buf;
1264*33b1fccfSAndroid Build Coastguard Worker int dstsize = 4096;
1265*33b1fccfSAndroid Build Coastguard Worker unsigned int srcsize, outsize;
1266*33b1fccfSAndroid Build Coastguard Worker struct kite_deflate *s;
1267*33b1fccfSAndroid Build Coastguard Worker
1268*33b1fccfSAndroid Build Coastguard Worker fd = open(argv[1], O_RDONLY);
1269*33b1fccfSAndroid Build Coastguard Worker if (fd < 0)
1270*33b1fccfSAndroid Build Coastguard Worker return -errno;
1271*33b1fccfSAndroid Build Coastguard Worker if (argc > 2)
1272*33b1fccfSAndroid Build Coastguard Worker dstsize = atoi(argv[2]);
1273*33b1fccfSAndroid Build Coastguard Worker filelength = lseek(fd, 0, SEEK_END);
1274*33b1fccfSAndroid Build Coastguard Worker
1275*33b1fccfSAndroid Build Coastguard Worker s = kite_deflate_init(9, 0);
1276*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(s))
1277*33b1fccfSAndroid Build Coastguard Worker return PTR_ERR(s);
1278*33b1fccfSAndroid Build Coastguard Worker
1279*33b1fccfSAndroid Build Coastguard Worker filelength = lseek(fd, 0, SEEK_END);
1280*33b1fccfSAndroid Build Coastguard Worker buf = mmap(NULL, filelength, PROT_READ, MAP_SHARED, fd, 0);
1281*33b1fccfSAndroid Build Coastguard Worker if (buf == MAP_FAILED)
1282*33b1fccfSAndroid Build Coastguard Worker return -errno;
1283*33b1fccfSAndroid Build Coastguard Worker close(fd);
1284*33b1fccfSAndroid Build Coastguard Worker
1285*33b1fccfSAndroid Build Coastguard Worker srcsize = filelength;
1286*33b1fccfSAndroid Build Coastguard Worker outsize = kite_deflate_destsize(s, buf, out, &srcsize, dstsize);
1287*33b1fccfSAndroid Build Coastguard Worker fd = open("out.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
1288*33b1fccfSAndroid Build Coastguard Worker write(fd, out, outsize);
1289*33b1fccfSAndroid Build Coastguard Worker close(fd);
1290*33b1fccfSAndroid Build Coastguard Worker kite_deflate_end(s);
1291*33b1fccfSAndroid Build Coastguard Worker return 0;
1292*33b1fccfSAndroid Build Coastguard Worker }
1293*33b1fccfSAndroid Build Coastguard Worker #endif
1294