1*f6dc9357SAndroid Build Coastguard Worker // LzxDecoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
6*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
11*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
12*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
13*f6dc9357SAndroid Build Coastguard Worker #else
14*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
15*f6dc9357SAndroid Build Coastguard Worker #endif
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/RotateDefs.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
20*f6dc9357SAndroid Build Coastguard Worker
21*f6dc9357SAndroid Build Coastguard Worker #include "LzxDecoder.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_X86_OR_AMD64
25*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_AMD64) \
26*f6dc9357SAndroid Build Coastguard Worker || defined(__SSE2__) \
27*f6dc9357SAndroid Build Coastguard Worker || defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
28*f6dc9357SAndroid Build Coastguard Worker || 0 && defined(_MSC_VER) && (_MSC_VER >= 1400) // set (1 &&) for debug
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__) && (__clang_major__ >= 2) \
31*f6dc9357SAndroid Build Coastguard Worker || defined(__GNUC__) && (__GNUC__ >= 4) \
32*f6dc9357SAndroid Build Coastguard Worker || defined(_MSC_VER) && (_MSC_VER >= 1400)
33*f6dc9357SAndroid Build Coastguard Worker #define Z7_LZX_X86_FILTER_USE_SSE2
34*f6dc9357SAndroid Build Coastguard Worker #endif
35*f6dc9357SAndroid Build Coastguard Worker #endif
36*f6dc9357SAndroid Build Coastguard Worker #endif
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker
39*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_X86_FILTER_USE_SSE2
40*f6dc9357SAndroid Build Coastguard Worker // #ifdef MY_CPU_X86_OR_AMD64
41*f6dc9357SAndroid Build Coastguard Worker #include <emmintrin.h> // SSE2
42*f6dc9357SAndroid Build Coastguard Worker // #endif
43*f6dc9357SAndroid Build Coastguard Worker #if defined(__clang__) || defined(__GNUC__)
44*f6dc9357SAndroid Build Coastguard Worker typedef int ctz_type;
45*f6dc9357SAndroid Build Coastguard Worker #define MY_CTZ(dest, mask) dest = __builtin_ctz((UInt32)(mask))
46*f6dc9357SAndroid Build Coastguard Worker #else // #if defined(_MSC_VER)
47*f6dc9357SAndroid Build Coastguard Worker #if (_MSC_VER >= 1600)
48*f6dc9357SAndroid Build Coastguard Worker // #include <intrin.h>
49*f6dc9357SAndroid Build Coastguard Worker #endif
50*f6dc9357SAndroid Build Coastguard Worker typedef unsigned long ctz_type;
51*f6dc9357SAndroid Build Coastguard Worker #define MY_CTZ(dest, mask) _BitScanForward(&dest, (mask));
52*f6dc9357SAndroid Build Coastguard Worker #endif // _MSC_VER
53*f6dc9357SAndroid Build Coastguard Worker #endif
54*f6dc9357SAndroid Build Coastguard Worker
55*f6dc9357SAndroid Build Coastguard Worker // when window buffer is filled, we must wrap position to zero,
56*f6dc9357SAndroid Build Coastguard Worker // and we want to wrap at same points where original-lzx must wrap.
57*f6dc9357SAndroid Build Coastguard Worker // But the wrapping is possible in point where chunk is finished.
58*f6dc9357SAndroid Build Coastguard Worker // Usually (chunk_size == 32KB), but (chunk_size != 32KB) also is allowed.
59*f6dc9357SAndroid Build Coastguard Worker // So we don't use additional buffer space over required (winSize).
60*f6dc9357SAndroid Build Coastguard Worker // And we can't use large overwrite after (len) in CopyLzMatch().
61*f6dc9357SAndroid Build Coastguard Worker // But we are allowed to write 3 bytes after (len), because
62*f6dc9357SAndroid Build Coastguard Worker // (delta <= _winSize - 3).
63*f6dc9357SAndroid Build Coastguard Worker
64*f6dc9357SAndroid Build Coastguard Worker // #define k_Lz_OverwriteSize 0 // for debug : to disable overwrite
65*f6dc9357SAndroid Build Coastguard Worker #define k_Lz_OverwriteSize 3 // = kNumReps
66*f6dc9357SAndroid Build Coastguard Worker #if k_Lz_OverwriteSize > 0
67*f6dc9357SAndroid Build Coastguard Worker // (k_Lz_OutBufSize_Add >= k_Lz_OverwriteSize) is required
68*f6dc9357SAndroid Build Coastguard Worker // we use value 4 to simplify memset() code.
69*f6dc9357SAndroid Build Coastguard Worker #define k_Lz_OutBufSize_Add (k_Lz_OverwriteSize + 1) // == 4
70*f6dc9357SAndroid Build Coastguard Worker #else
71*f6dc9357SAndroid Build Coastguard Worker #define k_Lz_OutBufSize_Add 0
72*f6dc9357SAndroid Build Coastguard Worker #endif
73*f6dc9357SAndroid Build Coastguard Worker
74*f6dc9357SAndroid Build Coastguard Worker // (len != 0)
75*f6dc9357SAndroid Build Coastguard Worker // (0 < delta <= _winSize - 3)
76*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
CopyLzMatch(Byte * dest,const Byte * src,UInt32 len,UInt32 delta)77*f6dc9357SAndroid Build Coastguard Worker void CopyLzMatch(Byte *dest, const Byte *src, UInt32 len, UInt32 delta)
78*f6dc9357SAndroid Build Coastguard Worker {
79*f6dc9357SAndroid Build Coastguard Worker if (delta >= 4)
80*f6dc9357SAndroid Build Coastguard Worker {
81*f6dc9357SAndroid Build Coastguard Worker #if k_Lz_OverwriteSize >= 3
82*f6dc9357SAndroid Build Coastguard Worker // optimized code with overwrite to reduce the number of branches
83*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
84*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
85*f6dc9357SAndroid Build Coastguard Worker #else
86*f6dc9357SAndroid Build Coastguard Worker dest[0] = src[0];
87*f6dc9357SAndroid Build Coastguard Worker dest[1] = src[1];
88*f6dc9357SAndroid Build Coastguard Worker dest[2] = src[2];
89*f6dc9357SAndroid Build Coastguard Worker dest[3] = src[3];
90*f6dc9357SAndroid Build Coastguard Worker #endif
91*f6dc9357SAndroid Build Coastguard Worker len--;
92*f6dc9357SAndroid Build Coastguard Worker src++;
93*f6dc9357SAndroid Build Coastguard Worker dest++;
94*f6dc9357SAndroid Build Coastguard Worker {
95*f6dc9357SAndroid Build Coastguard Worker #else
96*f6dc9357SAndroid Build Coastguard Worker // no overwrite in out buffer
97*f6dc9357SAndroid Build Coastguard Worker dest[0] = src[0];
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker const unsigned m = (unsigned)len & 1;
100*f6dc9357SAndroid Build Coastguard Worker src += m;
101*f6dc9357SAndroid Build Coastguard Worker dest += m;
102*f6dc9357SAndroid Build Coastguard Worker }
103*f6dc9357SAndroid Build Coastguard Worker if (len &= ~(unsigned)1)
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker dest[0] = src[0];
106*f6dc9357SAndroid Build Coastguard Worker dest[1] = src[1];
107*f6dc9357SAndroid Build Coastguard Worker #endif
108*f6dc9357SAndroid Build Coastguard Worker // len == 0 is allowed here
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker const unsigned m = (unsigned)len & 3;
111*f6dc9357SAndroid Build Coastguard Worker src += m;
112*f6dc9357SAndroid Build Coastguard Worker dest += m;
113*f6dc9357SAndroid Build Coastguard Worker }
114*f6dc9357SAndroid Build Coastguard Worker if (len &= ~(unsigned)3)
115*f6dc9357SAndroid Build Coastguard Worker {
116*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
117*f6dc9357SAndroid Build Coastguard Worker #if 1
118*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker const unsigned m = (unsigned)len & 7;
121*f6dc9357SAndroid Build Coastguard Worker dest += m;
122*f6dc9357SAndroid Build Coastguard Worker src += m;
123*f6dc9357SAndroid Build Coastguard Worker }
124*f6dc9357SAndroid Build Coastguard Worker if (len &= ~(unsigned)7)
125*f6dc9357SAndroid Build Coastguard Worker do
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)(dest ) = *(const UInt32 *)(const void *)(src);
128*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)(dest + 4) = *(const UInt32 *)(const void *)(src + 4);
129*f6dc9357SAndroid Build Coastguard Worker src += 8;
130*f6dc9357SAndroid Build Coastguard Worker dest += 8;
131*f6dc9357SAndroid Build Coastguard Worker }
132*f6dc9357SAndroid Build Coastguard Worker while (len -= 8);
133*f6dc9357SAndroid Build Coastguard Worker #else
134*f6dc9357SAndroid Build Coastguard Worker // gcc-11 -O3 for x64 generates incorrect code here
135*f6dc9357SAndroid Build Coastguard Worker do
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);
138*f6dc9357SAndroid Build Coastguard Worker src += 4;
139*f6dc9357SAndroid Build Coastguard Worker dest += 4;
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker while (len -= 4);
142*f6dc9357SAndroid Build Coastguard Worker #endif
143*f6dc9357SAndroid Build Coastguard Worker #else
144*f6dc9357SAndroid Build Coastguard Worker do
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker const Byte b0 = src[0];
147*f6dc9357SAndroid Build Coastguard Worker const Byte b1 = src[1];
148*f6dc9357SAndroid Build Coastguard Worker dest[0] = b0;
149*f6dc9357SAndroid Build Coastguard Worker dest[1] = b1;
150*f6dc9357SAndroid Build Coastguard Worker const Byte b2 = src[2];
151*f6dc9357SAndroid Build Coastguard Worker const Byte b3 = src[3];
152*f6dc9357SAndroid Build Coastguard Worker dest[2] = b2;
153*f6dc9357SAndroid Build Coastguard Worker dest[3] = b3;
154*f6dc9357SAndroid Build Coastguard Worker src += 4;
155*f6dc9357SAndroid Build Coastguard Worker dest += 4;
156*f6dc9357SAndroid Build Coastguard Worker }
157*f6dc9357SAndroid Build Coastguard Worker while (len -= 4);
158*f6dc9357SAndroid Build Coastguard Worker #endif
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker }
162*f6dc9357SAndroid Build Coastguard Worker else // (delta < 4)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker const unsigned b0 = *src;
165*f6dc9357SAndroid Build Coastguard Worker *dest = (Byte)b0;
166*f6dc9357SAndroid Build Coastguard Worker if (len >= 2)
167*f6dc9357SAndroid Build Coastguard Worker {
168*f6dc9357SAndroid Build Coastguard Worker if (delta < 2)
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker dest += (unsigned)len & 1;
171*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
172*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b0;
173*f6dc9357SAndroid Build Coastguard Worker dest += (unsigned)len & 2;
174*f6dc9357SAndroid Build Coastguard Worker if (len &= ~(unsigned)3)
175*f6dc9357SAndroid Build Coastguard Worker {
176*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
177*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT
178*f6dc9357SAndroid Build Coastguard Worker const UInt64 a = (UInt64)b0 * 0x101010101010101;
179*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)dest = (UInt32)a;
180*f6dc9357SAndroid Build Coastguard Worker dest += (unsigned)len & 7;
181*f6dc9357SAndroid Build Coastguard Worker if (len &= ~(unsigned)7)
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker // *(UInt64 *)(void *)dest = a;
184*f6dc9357SAndroid Build Coastguard Worker // dest += 8;
185*f6dc9357SAndroid Build Coastguard Worker // len -= 8;
186*f6dc9357SAndroid Build Coastguard Worker // if (len)
187*f6dc9357SAndroid Build Coastguard Worker {
188*f6dc9357SAndroid Build Coastguard Worker // const ptrdiff_t delta = (ptrdiff_t)dest & 7;
189*f6dc9357SAndroid Build Coastguard Worker // dest -= delta;
190*f6dc9357SAndroid Build Coastguard Worker do
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker *(UInt64 *)(void *)dest = a;
193*f6dc9357SAndroid Build Coastguard Worker dest += 8;
194*f6dc9357SAndroid Build Coastguard Worker }
195*f6dc9357SAndroid Build Coastguard Worker while (len -= 8);
196*f6dc9357SAndroid Build Coastguard Worker // dest += delta - 8;
197*f6dc9357SAndroid Build Coastguard Worker // *(UInt64 *)(void *)dest = a;
198*f6dc9357SAndroid Build Coastguard Worker }
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker #else
201*f6dc9357SAndroid Build Coastguard Worker const UInt32 a = (UInt32)b0 * 0x1010101;
202*f6dc9357SAndroid Build Coastguard Worker do
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker *(UInt32 *)(void *)dest = a;
205*f6dc9357SAndroid Build Coastguard Worker dest += 4;
206*f6dc9357SAndroid Build Coastguard Worker }
207*f6dc9357SAndroid Build Coastguard Worker while (len -= 4);
208*f6dc9357SAndroid Build Coastguard Worker #endif
209*f6dc9357SAndroid Build Coastguard Worker #else
210*f6dc9357SAndroid Build Coastguard Worker do
211*f6dc9357SAndroid Build Coastguard Worker {
212*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
213*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b0;
214*f6dc9357SAndroid Build Coastguard Worker dest[2] = (Byte)b0;
215*f6dc9357SAndroid Build Coastguard Worker dest[3] = (Byte)b0;
216*f6dc9357SAndroid Build Coastguard Worker dest += 4;
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker while (len -= 4);
219*f6dc9357SAndroid Build Coastguard Worker #endif
220*f6dc9357SAndroid Build Coastguard Worker }
221*f6dc9357SAndroid Build Coastguard Worker }
222*f6dc9357SAndroid Build Coastguard Worker else if (delta == 2)
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker const unsigned m = (unsigned)len & 1;
225*f6dc9357SAndroid Build Coastguard Worker len &= ~(unsigned)1;
226*f6dc9357SAndroid Build Coastguard Worker src += m;
227*f6dc9357SAndroid Build Coastguard Worker dest += m;
228*f6dc9357SAndroid Build Coastguard Worker {
229*f6dc9357SAndroid Build Coastguard Worker const Byte a0 = src[0];
230*f6dc9357SAndroid Build Coastguard Worker const Byte a1 = src[1];
231*f6dc9357SAndroid Build Coastguard Worker do
232*f6dc9357SAndroid Build Coastguard Worker {
233*f6dc9357SAndroid Build Coastguard Worker dest[0] = a0;
234*f6dc9357SAndroid Build Coastguard Worker dest[1] = a1;
235*f6dc9357SAndroid Build Coastguard Worker dest += 2;
236*f6dc9357SAndroid Build Coastguard Worker }
237*f6dc9357SAndroid Build Coastguard Worker while (len -= 2);
238*f6dc9357SAndroid Build Coastguard Worker }
239*f6dc9357SAndroid Build Coastguard Worker }
240*f6dc9357SAndroid Build Coastguard Worker else /* if (delta == 3) */
241*f6dc9357SAndroid Build Coastguard Worker {
242*f6dc9357SAndroid Build Coastguard Worker const unsigned b1 = src[1];
243*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b1;
244*f6dc9357SAndroid Build Coastguard Worker if (len -= 2)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker const unsigned b2 = src[2];
247*f6dc9357SAndroid Build Coastguard Worker dest += 2;
248*f6dc9357SAndroid Build Coastguard Worker do
249*f6dc9357SAndroid Build Coastguard Worker {
250*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b2; if (--len == 0) break;
251*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b0; if (--len == 0) break;
252*f6dc9357SAndroid Build Coastguard Worker dest[2] = (Byte)b1;
253*f6dc9357SAndroid Build Coastguard Worker dest += 3;
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker while (--len);
256*f6dc9357SAndroid Build Coastguard Worker }
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker }
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker
262*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LZX_SHOW_STAT
263*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_SHOW_STAT
264*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
265*f6dc9357SAndroid Build Coastguard Worker #endif
266*f6dc9357SAndroid Build Coastguard Worker
267*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
268*f6dc9357SAndroid Build Coastguard Worker namespace NLzx {
269*f6dc9357SAndroid Build Coastguard Worker
270*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LZX_SHOW_STAT
271*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_SHOW_STAT
272*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_Num_x86[3];
273*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_NumTables;
274*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_NumLits;
275*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_NumAlign;
276*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_main[kMainTableSize];
277*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_len[kNumLenSymbols];
278*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_main_levels[kNumHuffmanBits + 1];
279*f6dc9357SAndroid Build Coastguard Worker static UInt32 g_stats_len_levels[kNumHuffmanBits + 1];
280*f6dc9357SAndroid Build Coastguard Worker #define UPDATE_STAT(a) a
281*f6dc9357SAndroid Build Coastguard Worker static void PrintVal(UInt32 v)
282*f6dc9357SAndroid Build Coastguard Worker {
283*f6dc9357SAndroid Build Coastguard Worker printf("\n : %9u", v);
284*f6dc9357SAndroid Build Coastguard Worker }
285*f6dc9357SAndroid Build Coastguard Worker static void PrintStat(const char *name, const UInt32 *a, size_t num)
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker printf("\n\n==== %s:", name);
288*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = 0;
289*f6dc9357SAndroid Build Coastguard Worker size_t i;
290*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
291*f6dc9357SAndroid Build Coastguard Worker sum += a[i];
292*f6dc9357SAndroid Build Coastguard Worker PrintVal(sum);
293*f6dc9357SAndroid Build Coastguard Worker if (sum != 0)
294*f6dc9357SAndroid Build Coastguard Worker {
295*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker if (i % 8 == 0)
298*f6dc9357SAndroid Build Coastguard Worker printf("\n");
299*f6dc9357SAndroid Build Coastguard Worker printf("\n%3x : %9u : %5.2f", (unsigned)i, (unsigned)a[i], (double)a[i] * 100 / sum);
300*f6dc9357SAndroid Build Coastguard Worker }
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker printf("\n");
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker
305*f6dc9357SAndroid Build Coastguard Worker static struct CStat
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker ~CStat()
308*f6dc9357SAndroid Build Coastguard Worker {
309*f6dc9357SAndroid Build Coastguard Worker PrintStat("x86_filter", g_stats_Num_x86, Z7_ARRAY_SIZE(g_stats_Num_x86));
310*f6dc9357SAndroid Build Coastguard Worker printf("\nTables:"); PrintVal(g_stats_NumTables);
311*f6dc9357SAndroid Build Coastguard Worker printf("\nLits:"); PrintVal(g_stats_NumLits);
312*f6dc9357SAndroid Build Coastguard Worker printf("\nAlign:"); PrintVal(g_stats_NumAlign);
313*f6dc9357SAndroid Build Coastguard Worker PrintStat("Main", g_stats_main, Z7_ARRAY_SIZE(g_stats_main));
314*f6dc9357SAndroid Build Coastguard Worker PrintStat("Len", g_stats_len, Z7_ARRAY_SIZE(g_stats_len));
315*f6dc9357SAndroid Build Coastguard Worker PrintStat("Main Levels", g_stats_main_levels, Z7_ARRAY_SIZE(g_stats_main_levels));
316*f6dc9357SAndroid Build Coastguard Worker PrintStat("Len Levels", g_stats_len_levels, Z7_ARRAY_SIZE(g_stats_len_levels));
317*f6dc9357SAndroid Build Coastguard Worker }
318*f6dc9357SAndroid Build Coastguard Worker } g_stat;
319*f6dc9357SAndroid Build Coastguard Worker #else
320*f6dc9357SAndroid Build Coastguard Worker #define UPDATE_STAT(a)
321*f6dc9357SAndroid Build Coastguard Worker #endif
322*f6dc9357SAndroid Build Coastguard Worker
323*f6dc9357SAndroid Build Coastguard Worker
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker /*
326*f6dc9357SAndroid Build Coastguard Worker 3 p015 : ivb- : or r32,r32 / add r32,r32
327*f6dc9357SAndroid Build Coastguard Worker 4 p0156 : hsw+
328*f6dc9357SAndroid Build Coastguard Worker 5 p0156b: adl+
329*f6dc9357SAndroid Build Coastguard Worker 2 p0_5 : ivb- : shl r32,i8
330*f6dc9357SAndroid Build Coastguard Worker 2 p0__6 : hsw+
331*f6dc9357SAndroid Build Coastguard Worker 1 p5 : ivb- : jb
332*f6dc9357SAndroid Build Coastguard Worker 2 p0__6 : hsw+
333*f6dc9357SAndroid Build Coastguard Worker 2 p0_5 : wsm- : SSE2 : pcmpeqb : _mm_cmpeq_epi8
334*f6dc9357SAndroid Build Coastguard Worker 2 p_15 : snb-bdw
335*f6dc9357SAndroid Build Coastguard Worker 2 p01 : skl+
336*f6dc9357SAndroid Build Coastguard Worker 1 p0 : SSE2 : pmovmskb : _mm_movemask_epi8
337*f6dc9357SAndroid Build Coastguard Worker */
338*f6dc9357SAndroid Build Coastguard Worker /*
339*f6dc9357SAndroid Build Coastguard Worker v24.00: the code was fixed for more compatibility with original-ms-cab-decoder.
340*f6dc9357SAndroid Build Coastguard Worker for ((Int32)translationSize >= 0) : LZX specification shows the code with signed Int32.
341*f6dc9357SAndroid Build Coastguard Worker for ((Int32)translationSize < 0) : no specification for that case, but we support that case.
342*f6dc9357SAndroid Build Coastguard Worker We suppose our code now is compatible with original-ms-cab-decoder.
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker Starting byte of data stream (real_pos == 0) is special corner case,
345*f6dc9357SAndroid Build Coastguard Worker where we don't need any conversion (as in original-ms-cab-decoder).
346*f6dc9357SAndroid Build Coastguard Worker Our optimization: we use unsigned (UInt32 pos) (pos = -1 - real_pos).
347*f6dc9357SAndroid Build Coastguard Worker So (pos) is always negative: ((Int32)pos < 0).
348*f6dc9357SAndroid Build Coastguard Worker It allows us to use simple comparison (v > pos) instead of more complex comparisons.
349*f6dc9357SAndroid Build Coastguard Worker */
350*f6dc9357SAndroid Build Coastguard Worker // (p) will point 5 bytes after 0xe8 byte:
351*f6dc9357SAndroid Build Coastguard Worker // pos == -1 - (p - 5 - data_start) == 4 + data_start - p
352*f6dc9357SAndroid Build Coastguard Worker // (FILTER_PROCESSED_SIZE_DELTA == 4) is optimized value for better speed in some compilers:
353*f6dc9357SAndroid Build Coastguard Worker #define FILTER_PROCESSED_SIZE_DELTA 4
354*f6dc9357SAndroid Build Coastguard Worker
355*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_OR_ARM64)
356*f6dc9357SAndroid Build Coastguard Worker // optimized branch:
357*f6dc9357SAndroid Build Coastguard Worker // size_t must be at least 32-bit for this branch.
358*f6dc9357SAndroid Build Coastguard Worker #if 1 // use 1 for simpler code
359*f6dc9357SAndroid Build Coastguard Worker // use integer (low 32 bits of pointer) instead of pointer
360*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_PREPARE processedSize4 = (UInt32)(size_t)(ptrdiff_t)data + \
361*f6dc9357SAndroid Build Coastguard Worker (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
362*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_CALC_pos(p) const UInt32 pos = processedSize4 - (UInt32)(size_t)(ptrdiff_t)p;
363*f6dc9357SAndroid Build Coastguard Worker #else
364*f6dc9357SAndroid Build Coastguard Worker // note: (dataStart) pointer can point out of array ranges:
365*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_PREPARE const Byte *dataStart = data + \
366*f6dc9357SAndroid Build Coastguard Worker (4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
367*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_CALC_pos(p) const UInt32 pos = (UInt32)(size_t)(dataStart - p);
368*f6dc9357SAndroid Build Coastguard Worker #endif
369*f6dc9357SAndroid Build Coastguard Worker #else
370*f6dc9357SAndroid Build Coastguard Worker // non-optimized branch for unusual platforms (16-bit size_t or unusual size_t):
371*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_PREPARE processedSize4 = \
372*f6dc9357SAndroid Build Coastguard Worker (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;
373*f6dc9357SAndroid Build Coastguard Worker #define X86_FILTER_CALC_pos(p) const UInt32 pos = processedSize4 - (UInt32)(size_t)(p - data);
374*f6dc9357SAndroid Build Coastguard Worker #endif
375*f6dc9357SAndroid Build Coastguard Worker
376*f6dc9357SAndroid Build Coastguard Worker #define X86_TRANSLATE_PRE(p) \
377*f6dc9357SAndroid Build Coastguard Worker UInt32 v = GetUi32((p) - 4);
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker #define X86_TRANSLATE_POST(p) \
380*f6dc9357SAndroid Build Coastguard Worker { \
381*f6dc9357SAndroid Build Coastguard Worker X86_FILTER_CALC_pos(p) \
382*f6dc9357SAndroid Build Coastguard Worker if (v < translationSize) { \
383*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_Num_x86[0]++;) \
384*f6dc9357SAndroid Build Coastguard Worker v += pos + 1; \
385*f6dc9357SAndroid Build Coastguard Worker SetUi32((p) - 4, v) \
386*f6dc9357SAndroid Build Coastguard Worker } \
387*f6dc9357SAndroid Build Coastguard Worker else if (v > pos) { \
388*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_Num_x86[1]++;) \
389*f6dc9357SAndroid Build Coastguard Worker v += translationSize; \
390*f6dc9357SAndroid Build Coastguard Worker SetUi32((p) - 4, v) \
391*f6dc9357SAndroid Build Coastguard Worker } else { UPDATE_STAT(g_stats_Num_x86[2]++;) } \
392*f6dc9357SAndroid Build Coastguard Worker }
393*f6dc9357SAndroid Build Coastguard Worker
394*f6dc9357SAndroid Build Coastguard Worker
395*f6dc9357SAndroid Build Coastguard Worker /*
396*f6dc9357SAndroid Build Coastguard Worker if ( defined(Z7_LZX_X86_FILTER_USE_SSE2)
397*f6dc9357SAndroid Build Coastguard Worker && defined(Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED))
398*f6dc9357SAndroid Build Coastguard Worker the function can read up to aligned_for_32_up_from(size) bytes in (data).
399*f6dc9357SAndroid Build Coastguard Worker */
400*f6dc9357SAndroid Build Coastguard Worker // processedSize < (1 << 30)
401*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
402*f6dc9357SAndroid Build Coastguard Worker static void x86_Filter4(Byte *data, size_t size, UInt32 processedSize4, UInt32 translationSize)
403*f6dc9357SAndroid Build Coastguard Worker {
404*f6dc9357SAndroid Build Coastguard Worker const size_t kResidue = 10;
405*f6dc9357SAndroid Build Coastguard Worker if (size <= kResidue)
406*f6dc9357SAndroid Build Coastguard Worker return;
407*f6dc9357SAndroid Build Coastguard Worker Byte * const lim = data + size - kResidue + 4;
408*f6dc9357SAndroid Build Coastguard Worker const Byte save = lim[0];
409*f6dc9357SAndroid Build Coastguard Worker lim[0] = 0xe8;
410*f6dc9357SAndroid Build Coastguard Worker X86_FILTER_PREPARE
411*f6dc9357SAndroid Build Coastguard Worker Byte *p = data;
412*f6dc9357SAndroid Build Coastguard Worker
413*f6dc9357SAndroid Build Coastguard Worker #define FILTER_RETURN_IF_LIM(_p_) if (_p_ > lim) { lim[0] = save; return; }
414*f6dc9357SAndroid Build Coastguard Worker
415*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_X86_FILTER_USE_SSE2
416*f6dc9357SAndroid Build Coastguard Worker
417*f6dc9357SAndroid Build Coastguard Worker // sse2-aligned/sse2-unaligned provide same speed on real data.
418*f6dc9357SAndroid Build Coastguard Worker // but the code is smaller for sse2-unaligned version.
419*f6dc9357SAndroid Build Coastguard Worker // for debug : define it to get alternative version with aligned 128-bit reads:
420*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
421*f6dc9357SAndroid Build Coastguard Worker
422*f6dc9357SAndroid Build Coastguard Worker #define FILTER_MASK_INT UInt32
423*f6dc9357SAndroid Build Coastguard Worker #define FILTER_NUM_VECTORS_IN_CHUNK 2
424*f6dc9357SAndroid Build Coastguard Worker #define FILTER_CHUNK_BYTES_OFFSET (16 * FILTER_NUM_VECTORS_IN_CHUNK - 5)
425*f6dc9357SAndroid Build Coastguard Worker
426*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
427*f6dc9357SAndroid Build Coastguard Worker // aligned version doesn't uses additional space if buf size is aligned for 32
428*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_Add 0
429*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_AlignMask (16 * FILTER_NUM_VECTORS_IN_CHUNK - 1)
430*f6dc9357SAndroid Build Coastguard Worker #define FILTER_LOAD_128(p) _mm_load_si128 ((const __m128i *)(const void *)(p))
431*f6dc9357SAndroid Build Coastguard Worker #else
432*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_Add (16 * FILTER_NUM_VECTORS_IN_CHUNK)
433*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_AlignMask 0
434*f6dc9357SAndroid Build Coastguard Worker #define FILTER_LOAD_128(p) _mm_loadu_si128((const __m128i *)(const void *)(p))
435*f6dc9357SAndroid Build Coastguard Worker #endif
436*f6dc9357SAndroid Build Coastguard Worker
437*f6dc9357SAndroid Build Coastguard Worker #define GET_E8_MASK(dest, dest1, p) \
438*f6dc9357SAndroid Build Coastguard Worker { \
439*f6dc9357SAndroid Build Coastguard Worker __m128i v0 = FILTER_LOAD_128(p); \
440*f6dc9357SAndroid Build Coastguard Worker __m128i v1 = FILTER_LOAD_128(p + 16); \
441*f6dc9357SAndroid Build Coastguard Worker p += 16 * FILTER_NUM_VECTORS_IN_CHUNK; \
442*f6dc9357SAndroid Build Coastguard Worker v0 = _mm_cmpeq_epi8(v0, k_e8_Vector); \
443*f6dc9357SAndroid Build Coastguard Worker v1 = _mm_cmpeq_epi8(v1, k_e8_Vector); \
444*f6dc9357SAndroid Build Coastguard Worker dest = (unsigned)_mm_movemask_epi8(v0); \
445*f6dc9357SAndroid Build Coastguard Worker dest1 = (unsigned)_mm_movemask_epi8(v1); \
446*f6dc9357SAndroid Build Coastguard Worker }
447*f6dc9357SAndroid Build Coastguard Worker
448*f6dc9357SAndroid Build Coastguard Worker const __m128i k_e8_Vector = _mm_set1_epi32((Int32)(UInt32)0xe8e8e8e8);
449*f6dc9357SAndroid Build Coastguard Worker for (;;)
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker // for debug: define it for smaller code:
452*f6dc9357SAndroid Build Coastguard Worker // #define Z7_LZX_X86_FILTER_CALC_IN_LOOP
453*f6dc9357SAndroid Build Coastguard Worker // without Z7_LZX_X86_FILTER_CALC_IN_LOOP, we can get faster and simpler loop
454*f6dc9357SAndroid Build Coastguard Worker FILTER_MASK_INT mask;
455*f6dc9357SAndroid Build Coastguard Worker {
456*f6dc9357SAndroid Build Coastguard Worker FILTER_MASK_INT mask1;
457*f6dc9357SAndroid Build Coastguard Worker do
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker GET_E8_MASK(mask, mask1, p)
460*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP
461*f6dc9357SAndroid Build Coastguard Worker mask += mask1;
462*f6dc9357SAndroid Build Coastguard Worker #else
463*f6dc9357SAndroid Build Coastguard Worker mask |= mask1 << 16;
464*f6dc9357SAndroid Build Coastguard Worker #endif
465*f6dc9357SAndroid Build Coastguard Worker }
466*f6dc9357SAndroid Build Coastguard Worker while (!mask);
467*f6dc9357SAndroid Build Coastguard Worker
468*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP
469*f6dc9357SAndroid Build Coastguard Worker mask -= mask1;
470*f6dc9357SAndroid Build Coastguard Worker mask |= mask1 << 16;
471*f6dc9357SAndroid Build Coastguard Worker #endif
472*f6dc9357SAndroid Build Coastguard Worker }
473*f6dc9357SAndroid Build Coastguard Worker
474*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
475*f6dc9357SAndroid Build Coastguard Worker for (;;)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker ctz_type index;
478*f6dc9357SAndroid Build Coastguard Worker typedef
479*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT
480*f6dc9357SAndroid Build Coastguard Worker UInt64
481*f6dc9357SAndroid Build Coastguard Worker #else
482*f6dc9357SAndroid Build Coastguard Worker UInt32
483*f6dc9357SAndroid Build Coastguard Worker #endif
484*f6dc9357SAndroid Build Coastguard Worker SUPER_MASK_INT;
485*f6dc9357SAndroid Build Coastguard Worker SUPER_MASK_INT superMask;
486*f6dc9357SAndroid Build Coastguard Worker {
487*f6dc9357SAndroid Build Coastguard Worker MY_CTZ(index, mask);
488*f6dc9357SAndroid Build Coastguard Worker Byte *p2 = p - FILTER_CHUNK_BYTES_OFFSET + (unsigned)index;
489*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_PRE(p2)
490*f6dc9357SAndroid Build Coastguard Worker superMask = ~(SUPER_MASK_INT)0x1f << index;
491*f6dc9357SAndroid Build Coastguard Worker FILTER_RETURN_IF_LIM(p2)
492*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_POST(p2)
493*f6dc9357SAndroid Build Coastguard Worker mask &= (UInt32)superMask;
494*f6dc9357SAndroid Build Coastguard Worker }
495*f6dc9357SAndroid Build Coastguard Worker if (mask)
496*f6dc9357SAndroid Build Coastguard Worker continue;
497*f6dc9357SAndroid Build Coastguard Worker if (index <= FILTER_CHUNK_BYTES_OFFSET)
498*f6dc9357SAndroid Build Coastguard Worker break;
499*f6dc9357SAndroid Build Coastguard Worker {
500*f6dc9357SAndroid Build Coastguard Worker FILTER_MASK_INT mask1;
501*f6dc9357SAndroid Build Coastguard Worker GET_E8_MASK(mask, mask1, p)
502*f6dc9357SAndroid Build Coastguard Worker mask &=
503*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT
504*f6dc9357SAndroid Build Coastguard Worker (UInt32)(superMask >> 32);
505*f6dc9357SAndroid Build Coastguard Worker #else
506*f6dc9357SAndroid Build Coastguard Worker ((FILTER_MASK_INT)0 - 1) << ((int)index - FILTER_CHUNK_BYTES_OFFSET);
507*f6dc9357SAndroid Build Coastguard Worker #endif
508*f6dc9357SAndroid Build Coastguard Worker mask |= mask1 << 16;
509*f6dc9357SAndroid Build Coastguard Worker }
510*f6dc9357SAndroid Build Coastguard Worker if (!mask)
511*f6dc9357SAndroid Build Coastguard Worker break;
512*f6dc9357SAndroid Build Coastguard Worker }
513*f6dc9357SAndroid Build Coastguard Worker #else // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
514*f6dc9357SAndroid Build Coastguard Worker {
515*f6dc9357SAndroid Build Coastguard Worker // we use simplest version without loop:
516*f6dc9357SAndroid Build Coastguard Worker // for (;;)
517*f6dc9357SAndroid Build Coastguard Worker {
518*f6dc9357SAndroid Build Coastguard Worker ctz_type index;
519*f6dc9357SAndroid Build Coastguard Worker MY_CTZ(index, mask);
520*f6dc9357SAndroid Build Coastguard Worker /*
521*f6dc9357SAndroid Build Coastguard Worker printf("\np=%p, mask=%8x, index = %2d, p + index = %x\n",
522*f6dc9357SAndroid Build Coastguard Worker (p - 16 * FILTER_NUM_VECTORS_IN_CHUNK), (unsigned)mask,
523*f6dc9357SAndroid Build Coastguard Worker (unsigned)index, (unsigned)((unsigned)(ptrdiff_t)(p - 16 * FILTER_NUM_VECTORS_IN_CHUNK) + index));
524*f6dc9357SAndroid Build Coastguard Worker */
525*f6dc9357SAndroid Build Coastguard Worker p += (size_t)(unsigned)index - FILTER_CHUNK_BYTES_OFFSET;
526*f6dc9357SAndroid Build Coastguard Worker FILTER_RETURN_IF_LIM(p)
527*f6dc9357SAndroid Build Coastguard Worker // mask &= ~(FILTER_MASK_INT)0x1f << index; mask >>= index;
528*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_PRE(p)
529*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_POST(p)
530*f6dc9357SAndroid Build Coastguard Worker // if (!mask) break; // p += 16 * FILTER_NUM_VECTORS_IN_CHUNK;
531*f6dc9357SAndroid Build Coastguard Worker }
532*f6dc9357SAndroid Build Coastguard Worker }
533*f6dc9357SAndroid Build Coastguard Worker #endif // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED
534*f6dc9357SAndroid Build Coastguard Worker }
535*f6dc9357SAndroid Build Coastguard Worker
536*f6dc9357SAndroid Build Coastguard Worker #else // ! Z7_LZX_X86_FILTER_USE_SSE2
537*f6dc9357SAndroid Build Coastguard Worker
538*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_Add 0
539*f6dc9357SAndroid Build Coastguard Worker #define k_Filter_OutBufSize_AlignMask 0
540*f6dc9357SAndroid Build Coastguard Worker
541*f6dc9357SAndroid Build Coastguard Worker
542*f6dc9357SAndroid Build Coastguard Worker for (;;)
543*f6dc9357SAndroid Build Coastguard Worker {
544*f6dc9357SAndroid Build Coastguard Worker for (;;)
545*f6dc9357SAndroid Build Coastguard Worker {
546*f6dc9357SAndroid Build Coastguard Worker if (p[0] == 0xe8) { p += 5; break; }
547*f6dc9357SAndroid Build Coastguard Worker if (p[1] == 0xe8) { p += 6; break; }
548*f6dc9357SAndroid Build Coastguard Worker if (p[2] == 0xe8) { p += 7; break; }
549*f6dc9357SAndroid Build Coastguard Worker p += 4;
550*f6dc9357SAndroid Build Coastguard Worker if (p[-1] == 0xe8) { p += 4; break; }
551*f6dc9357SAndroid Build Coastguard Worker }
552*f6dc9357SAndroid Build Coastguard Worker FILTER_RETURN_IF_LIM(p)
553*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_PRE(p)
554*f6dc9357SAndroid Build Coastguard Worker X86_TRANSLATE_POST(p)
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker
557*f6dc9357SAndroid Build Coastguard Worker #endif // ! Z7_LZX_X86_FILTER_USE_SSE2
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker
560*f6dc9357SAndroid Build Coastguard Worker
561*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder() throw():
562*f6dc9357SAndroid Build Coastguard Worker _win(NULL),
563*f6dc9357SAndroid Build Coastguard Worker _isUncompressedBlock(false),
564*f6dc9357SAndroid Build Coastguard Worker _skipByte(false),
565*f6dc9357SAndroid Build Coastguard Worker _keepHistory(false),
566*f6dc9357SAndroid Build Coastguard Worker _keepHistoryForNext(true),
567*f6dc9357SAndroid Build Coastguard Worker _needAlloc(true),
568*f6dc9357SAndroid Build Coastguard Worker _wimMode(false),
569*f6dc9357SAndroid Build Coastguard Worker _numDictBits(15),
570*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize(0),
571*f6dc9357SAndroid Build Coastguard Worker _x86_translationSize(0),
572*f6dc9357SAndroid Build Coastguard Worker _x86_buf(NULL),
573*f6dc9357SAndroid Build Coastguard Worker _unpackedData(NULL)
574*f6dc9357SAndroid Build Coastguard Worker {
575*f6dc9357SAndroid Build Coastguard Worker {
576*f6dc9357SAndroid Build Coastguard Worker // it's better to get empty virtual entries, if mispredicted value can be used:
577*f6dc9357SAndroid Build Coastguard Worker memset(_reps, 0, kPosSlotOffset * sizeof(_reps[0]));
578*f6dc9357SAndroid Build Coastguard Worker memset(_extra, 0, kPosSlotOffset);
579*f6dc9357SAndroid Build Coastguard Worker #define SET_NUM_BITS(i) i // #define NUM_BITS_DELTA 31
580*f6dc9357SAndroid Build Coastguard Worker _extra[kPosSlotOffset + 0] = SET_NUM_BITS(0);
581*f6dc9357SAndroid Build Coastguard Worker _extra[kPosSlotOffset + 1] = SET_NUM_BITS(0);
582*f6dc9357SAndroid Build Coastguard Worker // reps[0] = 0 - (kNumReps - 1);
583*f6dc9357SAndroid Build Coastguard Worker // reps[1] = 1 - (kNumReps - 1);
584*f6dc9357SAndroid Build Coastguard Worker UInt32 a = 2 - (kNumReps - 1);
585*f6dc9357SAndroid Build Coastguard Worker UInt32 delta = 1;
586*f6dc9357SAndroid Build Coastguard Worker unsigned i;
587*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kNumLinearPosSlotBits; i++)
588*f6dc9357SAndroid Build Coastguard Worker {
589*f6dc9357SAndroid Build Coastguard Worker _extra[(size_t)i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
590*f6dc9357SAndroid Build Coastguard Worker _extra[(size_t)i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
591*f6dc9357SAndroid Build Coastguard Worker _reps [(size_t)i * 2 + 2 + kPosSlotOffset] = a; a += delta;
592*f6dc9357SAndroid Build Coastguard Worker _reps [(size_t)i * 2 + 3 + kPosSlotOffset] = a; a += delta;
593*f6dc9357SAndroid Build Coastguard Worker delta += delta;
594*f6dc9357SAndroid Build Coastguard Worker }
595*f6dc9357SAndroid Build Coastguard Worker for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
596*f6dc9357SAndroid Build Coastguard Worker {
597*f6dc9357SAndroid Build Coastguard Worker _extra[(size_t)i + kPosSlotOffset] = SET_NUM_BITS(kNumLinearPosSlotBits);
598*f6dc9357SAndroid Build Coastguard Worker _reps [(size_t)i + kPosSlotOffset] = a;
599*f6dc9357SAndroid Build Coastguard Worker a += (UInt32)1 << kNumLinearPosSlotBits;
600*f6dc9357SAndroid Build Coastguard Worker }
601*f6dc9357SAndroid Build Coastguard Worker }
602*f6dc9357SAndroid Build Coastguard Worker }
603*f6dc9357SAndroid Build Coastguard Worker
604*f6dc9357SAndroid Build Coastguard Worker CDecoder::~CDecoder() throw()
605*f6dc9357SAndroid Build Coastguard Worker {
606*f6dc9357SAndroid Build Coastguard Worker if (_needAlloc)
607*f6dc9357SAndroid Build Coastguard Worker // BigFree
608*f6dc9357SAndroid Build Coastguard Worker z7_AlignedFree
609*f6dc9357SAndroid Build Coastguard Worker (_win);
610*f6dc9357SAndroid Build Coastguard Worker z7_AlignedFree(_x86_buf);
611*f6dc9357SAndroid Build Coastguard Worker }
612*f6dc9357SAndroid Build Coastguard Worker
613*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Flush() throw()
614*f6dc9357SAndroid Build Coastguard Worker {
615*f6dc9357SAndroid Build Coastguard Worker // UInt32 t = _x86_processedSize; for (int y = 0; y < 50; y++) { _x86_processedSize = t; // benchmark: (branch predicted)
616*f6dc9357SAndroid Build Coastguard Worker if (_x86_translationSize != 0)
617*f6dc9357SAndroid Build Coastguard Worker {
618*f6dc9357SAndroid Build Coastguard Worker Byte *destData = _win + _writePos;
619*f6dc9357SAndroid Build Coastguard Worker const UInt32 curSize = _pos - _writePos;
620*f6dc9357SAndroid Build Coastguard Worker if (_keepHistoryForNext)
621*f6dc9357SAndroid Build Coastguard Worker {
622*f6dc9357SAndroid Build Coastguard Worker const size_t kChunkSize = (size_t)1 << 15;
623*f6dc9357SAndroid Build Coastguard Worker if (curSize > kChunkSize)
624*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
625*f6dc9357SAndroid Build Coastguard Worker if (!_x86_buf)
626*f6dc9357SAndroid Build Coastguard Worker {
627*f6dc9357SAndroid Build Coastguard Worker // (kChunkSize % 32 == 0) is required in some cases, because
628*f6dc9357SAndroid Build Coastguard Worker // the filter can read data by 32-bytes chunks in some cases.
629*f6dc9357SAndroid Build Coastguard Worker // if (chunk_size > (1 << 15)) is possible, then we must the code:
630*f6dc9357SAndroid Build Coastguard Worker const size_t kAllocSize = kChunkSize + k_Filter_OutBufSize_Add;
631*f6dc9357SAndroid Build Coastguard Worker _x86_buf = (Byte *)z7_AlignedAlloc(kAllocSize);
632*f6dc9357SAndroid Build Coastguard Worker if (!_x86_buf)
633*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
634*f6dc9357SAndroid Build Coastguard Worker #if 0 != k_Filter_OutBufSize_Add || \
635*f6dc9357SAndroid Build Coastguard Worker 0 != k_Filter_OutBufSize_AlignMask
636*f6dc9357SAndroid Build Coastguard Worker // x86_Filter4() can read after curSize.
637*f6dc9357SAndroid Build Coastguard Worker // So we set all data to zero to prevent reading of uninitialized data:
638*f6dc9357SAndroid Build Coastguard Worker memset(_x86_buf, 0, kAllocSize); // optional
639*f6dc9357SAndroid Build Coastguard Worker #endif
640*f6dc9357SAndroid Build Coastguard Worker }
641*f6dc9357SAndroid Build Coastguard Worker // for (int yy = 0; yy < 1; yy++) // for debug
642*f6dc9357SAndroid Build Coastguard Worker memcpy(_x86_buf, destData, curSize);
643*f6dc9357SAndroid Build Coastguard Worker _unpackedData = _x86_buf;
644*f6dc9357SAndroid Build Coastguard Worker destData = _x86_buf;
645*f6dc9357SAndroid Build Coastguard Worker }
646*f6dc9357SAndroid Build Coastguard Worker else
647*f6dc9357SAndroid Build Coastguard Worker {
648*f6dc9357SAndroid Build Coastguard Worker // x86_Filter4() can overread after (curSize),
649*f6dc9357SAndroid Build Coastguard Worker // so we can do memset() after (curSize):
650*f6dc9357SAndroid Build Coastguard Worker // k_Filter_OutBufSize_AlignMask also can be used
651*f6dc9357SAndroid Build Coastguard Worker // if (!_overDict) memset(destData + curSize, 0, k_Filter_OutBufSize_Add);
652*f6dc9357SAndroid Build Coastguard Worker }
653*f6dc9357SAndroid Build Coastguard Worker x86_Filter4(destData, curSize, _x86_processedSize - FILTER_PROCESSED_SIZE_DELTA, _x86_translationSize);
654*f6dc9357SAndroid Build Coastguard Worker _x86_processedSize += (UInt32)curSize;
655*f6dc9357SAndroid Build Coastguard Worker if (_x86_processedSize >= ((UInt32)1 << 30))
656*f6dc9357SAndroid Build Coastguard Worker _x86_translationSize = 0;
657*f6dc9357SAndroid Build Coastguard Worker }
658*f6dc9357SAndroid Build Coastguard Worker // }
659*f6dc9357SAndroid Build Coastguard Worker return S_OK;
660*f6dc9357SAndroid Build Coastguard Worker }
661*f6dc9357SAndroid Build Coastguard Worker
662*f6dc9357SAndroid Build Coastguard Worker
663*f6dc9357SAndroid Build Coastguard Worker
664*f6dc9357SAndroid Build Coastguard Worker // (NUM_DELTA_BYTES == 2) reduces the code in main loop.
665*f6dc9357SAndroid Build Coastguard Worker #if 1
666*f6dc9357SAndroid Build Coastguard Worker #define NUM_DELTA_BYTES 2
667*f6dc9357SAndroid Build Coastguard Worker #else
668*f6dc9357SAndroid Build Coastguard Worker #define NUM_DELTA_BYTES 0
669*f6dc9357SAndroid Build Coastguard Worker #endif
670*f6dc9357SAndroid Build Coastguard Worker
671*f6dc9357SAndroid Build Coastguard Worker #define NUM_DELTA_BIT_OFFSET_BITS (NUM_DELTA_BYTES * 8)
672*f6dc9357SAndroid Build Coastguard Worker
673*f6dc9357SAndroid Build Coastguard Worker #if NUM_DELTA_BIT_OFFSET_BITS > 0
674*f6dc9357SAndroid Build Coastguard Worker #define DECODE_ERROR_CODE 0
675*f6dc9357SAndroid Build Coastguard Worker #define IS_OVERFLOW_bitOffset(bo) ((bo) >= 0)
676*f6dc9357SAndroid Build Coastguard Worker // ( >= 0) comparison after bitOffset change gives simpler commands than ( > 0) comparison
677*f6dc9357SAndroid Build Coastguard Worker #else
678*f6dc9357SAndroid Build Coastguard Worker #define DECODE_ERROR_CODE 1
679*f6dc9357SAndroid Build Coastguard Worker #define IS_OVERFLOW_bitOffset(bo) ((bo) > 0)
680*f6dc9357SAndroid Build Coastguard Worker #endif
681*f6dc9357SAndroid Build Coastguard Worker
682*f6dc9357SAndroid Build Coastguard Worker // (numBits != 0)
683*f6dc9357SAndroid Build Coastguard Worker #define GET_VAL_BASE(numBits) (_value >> (32 - (numBits)))
684*f6dc9357SAndroid Build Coastguard Worker
685*f6dc9357SAndroid Build Coastguard Worker #define Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, check_op, error_op) \
686*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huff, kNumHuffmanBits, kNumTableBits, \
687*f6dc9357SAndroid Build Coastguard Worker _value, check_op, error_op, move_pos_op, NORMALIZE, bs)
688*f6dc9357SAndroid Build Coastguard Worker
689*f6dc9357SAndroid Build Coastguard Worker #define Z7_LZX_HUFF_DECODE_CHECK_YES(sym, huff, kNumTableBits, move_pos_op) \
690*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, \
691*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, { return DECODE_ERROR_CODE; })
692*f6dc9357SAndroid Build Coastguard Worker
693*f6dc9357SAndroid Build Coastguard Worker #define Z7_LZX_HUFF_DECODE_CHECK_NO( sym, huff, kNumTableBits, move_pos_op) \
694*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, \
695*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {})
696*f6dc9357SAndroid Build Coastguard Worker
697*f6dc9357SAndroid Build Coastguard Worker #define NORMALIZE \
698*f6dc9357SAndroid Build Coastguard Worker { \
699*f6dc9357SAndroid Build Coastguard Worker const Byte *ptr = _buf + (_bitOffset >> 4) * 2; \
700*f6dc9357SAndroid Build Coastguard Worker /* _value = (((UInt32)GetUi16(ptr) << 16) | GetUi16(ptr + 2)) << (_bitOffset & 15); */ \
701*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = GetUi32(ptr); \
702*f6dc9357SAndroid Build Coastguard Worker _value = rotlFixed (v, ((int)_bitOffset & 15) + 16); \
703*f6dc9357SAndroid Build Coastguard Worker }
704*f6dc9357SAndroid Build Coastguard Worker
705*f6dc9357SAndroid Build Coastguard Worker #define MOVE_POS(bs, numBits) \
706*f6dc9357SAndroid Build Coastguard Worker { \
707*f6dc9357SAndroid Build Coastguard Worker _bitOffset += numBits; \
708*f6dc9357SAndroid Build Coastguard Worker }
709*f6dc9357SAndroid Build Coastguard Worker
710*f6dc9357SAndroid Build Coastguard Worker #define MOVE_POS_STAT(bs, numBits) \
711*f6dc9357SAndroid Build Coastguard Worker { \
712*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_len_levels[numBits]++;) \
713*f6dc9357SAndroid Build Coastguard Worker MOVE_POS(bs, numBits); \
714*f6dc9357SAndroid Build Coastguard Worker }
715*f6dc9357SAndroid Build Coastguard Worker
716*f6dc9357SAndroid Build Coastguard Worker #define MOVE_POS_CHECK(bs, numBits) \
717*f6dc9357SAndroid Build Coastguard Worker { \
718*f6dc9357SAndroid Build Coastguard Worker if (IS_OVERFLOW_bitOffset(_bitOffset += numBits)) return DECODE_ERROR_CODE; \
719*f6dc9357SAndroid Build Coastguard Worker }
720*f6dc9357SAndroid Build Coastguard Worker
721*f6dc9357SAndroid Build Coastguard Worker #define MOVE_POS_CHECK_STAT(bs, numBits) \
722*f6dc9357SAndroid Build Coastguard Worker { \
723*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_main_levels[numBits]++;) \
724*f6dc9357SAndroid Build Coastguard Worker MOVE_POS_CHECK(bs, numBits) \
725*f6dc9357SAndroid Build Coastguard Worker }
726*f6dc9357SAndroid Build Coastguard Worker
727*f6dc9357SAndroid Build Coastguard Worker
728*f6dc9357SAndroid Build Coastguard Worker // (numBits == 0) is supported
729*f6dc9357SAndroid Build Coastguard Worker
730*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_HUFF_USE_64BIT_LIMIT
731*f6dc9357SAndroid Build Coastguard Worker
732*f6dc9357SAndroid Build Coastguard Worker #define MACRO_ReadBitsBig_pre(numBits) \
733*f6dc9357SAndroid Build Coastguard Worker { \
734*f6dc9357SAndroid Build Coastguard Worker _bitOffset += (numBits); \
735*f6dc9357SAndroid Build Coastguard Worker _value >>= 32 - (numBits); \
736*f6dc9357SAndroid Build Coastguard Worker }
737*f6dc9357SAndroid Build Coastguard Worker
738*f6dc9357SAndroid Build Coastguard Worker #else
739*f6dc9357SAndroid Build Coastguard Worker
740*f6dc9357SAndroid Build Coastguard Worker #define MACRO_ReadBitsBig_pre(numBits) \
741*f6dc9357SAndroid Build Coastguard Worker { \
742*f6dc9357SAndroid Build Coastguard Worker _bitOffset += (numBits); \
743*f6dc9357SAndroid Build Coastguard Worker _value = (UInt32)((UInt32)_value >> 1 >> (31 ^ (numBits))); \
744*f6dc9357SAndroid Build Coastguard Worker }
745*f6dc9357SAndroid Build Coastguard Worker
746*f6dc9357SAndroid Build Coastguard Worker #endif
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker
749*f6dc9357SAndroid Build Coastguard Worker #define MACRO_ReadBitsBig_add(dest) \
750*f6dc9357SAndroid Build Coastguard Worker { dest += (UInt32)_value; }
751*f6dc9357SAndroid Build Coastguard Worker
752*f6dc9357SAndroid Build Coastguard Worker #define MACRO_ReadBitsBig_add3(dest) \
753*f6dc9357SAndroid Build Coastguard Worker { dest += (UInt32)(_value) << 3; }
754*f6dc9357SAndroid Build Coastguard Worker
755*f6dc9357SAndroid Build Coastguard Worker
756*f6dc9357SAndroid Build Coastguard Worker // (numBits != 0)
757*f6dc9357SAndroid Build Coastguard Worker #define MACRO_ReadBits_NonZero(val, numBits) \
758*f6dc9357SAndroid Build Coastguard Worker { \
759*f6dc9357SAndroid Build Coastguard Worker val = (UInt32)(_value >> (32 - (numBits))); \
760*f6dc9357SAndroid Build Coastguard Worker MOVE_POS(bs, numBits); \
761*f6dc9357SAndroid Build Coastguard Worker NORMALIZE \
762*f6dc9357SAndroid Build Coastguard Worker }
763*f6dc9357SAndroid Build Coastguard Worker
764*f6dc9357SAndroid Build Coastguard Worker
765*f6dc9357SAndroid Build Coastguard Worker struct CBitDecoder
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker ptrdiff_t _bitOffset;
768*f6dc9357SAndroid Build Coastguard Worker const Byte *_buf;
769*f6dc9357SAndroid Build Coastguard Worker
770*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
771*f6dc9357SAndroid Build Coastguard Worker UInt32 GetVal() const
772*f6dc9357SAndroid Build Coastguard Worker {
773*f6dc9357SAndroid Build Coastguard Worker const Byte *ptr = _buf + (_bitOffset >> 4) * 2;
774*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = GetUi32(ptr);
775*f6dc9357SAndroid Build Coastguard Worker return rotlFixed (v, ((int)_bitOffset & 15) + 16);
776*f6dc9357SAndroid Build Coastguard Worker }
777*f6dc9357SAndroid Build Coastguard Worker
778*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
779*f6dc9357SAndroid Build Coastguard Worker bool IsOverRead() const
780*f6dc9357SAndroid Build Coastguard Worker {
781*f6dc9357SAndroid Build Coastguard Worker return _bitOffset > (int)(0 - NUM_DELTA_BIT_OFFSET_BITS);
782*f6dc9357SAndroid Build Coastguard Worker }
783*f6dc9357SAndroid Build Coastguard Worker
784*f6dc9357SAndroid Build Coastguard Worker
785*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
786*f6dc9357SAndroid Build Coastguard Worker bool WasBitStreamFinishedOK() const
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker // we check that all 0-15 unused bits are zeros:
789*f6dc9357SAndroid Build Coastguard Worker if (_bitOffset == 0 - NUM_DELTA_BIT_OFFSET_BITS)
790*f6dc9357SAndroid Build Coastguard Worker return true;
791*f6dc9357SAndroid Build Coastguard Worker if ((_bitOffset + NUM_DELTA_BIT_OFFSET_BITS + 15) & ~(ptrdiff_t)15)
792*f6dc9357SAndroid Build Coastguard Worker return false;
793*f6dc9357SAndroid Build Coastguard Worker const Byte *ptr = _buf - NUM_DELTA_BYTES - 2;
794*f6dc9357SAndroid Build Coastguard Worker if ((UInt16)(GetUi16(ptr) << (_bitOffset & 15)))
795*f6dc9357SAndroid Build Coastguard Worker return false;
796*f6dc9357SAndroid Build Coastguard Worker return true;
797*f6dc9357SAndroid Build Coastguard Worker }
798*f6dc9357SAndroid Build Coastguard Worker
799*f6dc9357SAndroid Build Coastguard Worker // (numBits != 0)
800*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
801*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits_NonZero(unsigned numBits) throw()
802*f6dc9357SAndroid Build Coastguard Worker {
803*f6dc9357SAndroid Build Coastguard Worker const UInt32 val = GetVal() >> (32 - numBits);
804*f6dc9357SAndroid Build Coastguard Worker _bitOffset += numBits;
805*f6dc9357SAndroid Build Coastguard Worker return val;
806*f6dc9357SAndroid Build Coastguard Worker }
807*f6dc9357SAndroid Build Coastguard Worker };
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker
810*f6dc9357SAndroid Build Coastguard Worker class CBitByteDecoder: public CBitDecoder
811*f6dc9357SAndroid Build Coastguard Worker {
812*f6dc9357SAndroid Build Coastguard Worker size_t _size;
813*f6dc9357SAndroid Build Coastguard Worker public:
814*f6dc9357SAndroid Build Coastguard Worker
815*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
816*f6dc9357SAndroid Build Coastguard Worker void Init_ByteMode(const Byte *data, size_t size)
817*f6dc9357SAndroid Build Coastguard Worker {
818*f6dc9357SAndroid Build Coastguard Worker _buf = data;
819*f6dc9357SAndroid Build Coastguard Worker _size = size;
820*f6dc9357SAndroid Build Coastguard Worker }
821*f6dc9357SAndroid Build Coastguard Worker
822*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
823*f6dc9357SAndroid Build Coastguard Worker void Init_BitMode(const Byte *data, size_t size)
824*f6dc9357SAndroid Build Coastguard Worker {
825*f6dc9357SAndroid Build Coastguard Worker _size = size & 1;
826*f6dc9357SAndroid Build Coastguard Worker size &= ~(size_t)1;
827*f6dc9357SAndroid Build Coastguard Worker _buf = data + size + NUM_DELTA_BYTES;
828*f6dc9357SAndroid Build Coastguard Worker _bitOffset = 0 - (ptrdiff_t)(size * 8) - NUM_DELTA_BIT_OFFSET_BITS;
829*f6dc9357SAndroid Build Coastguard Worker }
830*f6dc9357SAndroid Build Coastguard Worker
831*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
832*f6dc9357SAndroid Build Coastguard Worker void Switch_To_BitMode()
833*f6dc9357SAndroid Build Coastguard Worker {
834*f6dc9357SAndroid Build Coastguard Worker Init_BitMode(_buf, _size);
835*f6dc9357SAndroid Build Coastguard Worker }
836*f6dc9357SAndroid Build Coastguard Worker
837*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
838*f6dc9357SAndroid Build Coastguard Worker bool Switch_To_ByteMode()
839*f6dc9357SAndroid Build Coastguard Worker {
840*f6dc9357SAndroid Build Coastguard Worker /* here we check that unused bits in high 16-bits word are zeros.
841*f6dc9357SAndroid Build Coastguard Worker If high word is full (all 16-bits are unused),
842*f6dc9357SAndroid Build Coastguard Worker we check that all 16-bits are zeros.
843*f6dc9357SAndroid Build Coastguard Worker So we check and skip (1-16 bits) unused bits */
844*f6dc9357SAndroid Build Coastguard Worker if ((GetVal() >> (16 + (_bitOffset & 15))) != 0)
845*f6dc9357SAndroid Build Coastguard Worker return false;
846*f6dc9357SAndroid Build Coastguard Worker _bitOffset += 16;
847*f6dc9357SAndroid Build Coastguard Worker _bitOffset &= ~(ptrdiff_t)15;
848*f6dc9357SAndroid Build Coastguard Worker if (_bitOffset > 0 - NUM_DELTA_BIT_OFFSET_BITS)
849*f6dc9357SAndroid Build Coastguard Worker return false;
850*f6dc9357SAndroid Build Coastguard Worker const ptrdiff_t delta = _bitOffset >> 3;
851*f6dc9357SAndroid Build Coastguard Worker _size = (size_t)((ptrdiff_t)(_size) - delta - NUM_DELTA_BYTES);
852*f6dc9357SAndroid Build Coastguard Worker _buf += delta;
853*f6dc9357SAndroid Build Coastguard Worker // _bitOffset = 0; // optional
854*f6dc9357SAndroid Build Coastguard Worker return true;
855*f6dc9357SAndroid Build Coastguard Worker }
856*f6dc9357SAndroid Build Coastguard Worker
857*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
858*f6dc9357SAndroid Build Coastguard Worker size_t GetRem() const { return _size; }
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
861*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadUInt32()
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker const Byte *ptr = _buf;
864*f6dc9357SAndroid Build Coastguard Worker const UInt32 v = GetUi32(ptr);
865*f6dc9357SAndroid Build Coastguard Worker _buf += 4;
866*f6dc9357SAndroid Build Coastguard Worker _size -= 4;
867*f6dc9357SAndroid Build Coastguard Worker return v;
868*f6dc9357SAndroid Build Coastguard Worker }
869*f6dc9357SAndroid Build Coastguard Worker
870*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
871*f6dc9357SAndroid Build Coastguard Worker void CopyTo(Byte *dest, size_t size)
872*f6dc9357SAndroid Build Coastguard Worker {
873*f6dc9357SAndroid Build Coastguard Worker memcpy(dest, _buf, size);
874*f6dc9357SAndroid Build Coastguard Worker _buf += size;
875*f6dc9357SAndroid Build Coastguard Worker _size -= size;
876*f6dc9357SAndroid Build Coastguard Worker }
877*f6dc9357SAndroid Build Coastguard Worker
878*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
879*f6dc9357SAndroid Build Coastguard Worker bool IsOneDirectByteLeft() const
880*f6dc9357SAndroid Build Coastguard Worker {
881*f6dc9357SAndroid Build Coastguard Worker return GetRem() == 1;
882*f6dc9357SAndroid Build Coastguard Worker }
883*f6dc9357SAndroid Build Coastguard Worker
884*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
885*f6dc9357SAndroid Build Coastguard Worker Byte DirectReadByte()
886*f6dc9357SAndroid Build Coastguard Worker {
887*f6dc9357SAndroid Build Coastguard Worker _size--;
888*f6dc9357SAndroid Build Coastguard Worker return *_buf++;
889*f6dc9357SAndroid Build Coastguard Worker }
890*f6dc9357SAndroid Build Coastguard Worker };
891*f6dc9357SAndroid Build Coastguard Worker
892*f6dc9357SAndroid Build Coastguard Worker
893*f6dc9357SAndroid Build Coastguard Worker // numBits != 0
894*f6dc9357SAndroid Build Coastguard Worker // Z7_FORCE_INLINE
895*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
896*f6dc9357SAndroid Build Coastguard Worker static
897*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadBits(CBitDecoder &_bitStream, unsigned numBits)
898*f6dc9357SAndroid Build Coastguard Worker {
899*f6dc9357SAndroid Build Coastguard Worker return _bitStream.ReadBits_NonZero(numBits);
900*f6dc9357SAndroid Build Coastguard Worker }
901*f6dc9357SAndroid Build Coastguard Worker
902*f6dc9357SAndroid Build Coastguard Worker #define RIF(x) { if (!(x)) return false; }
903*f6dc9357SAndroid Build Coastguard Worker
904*f6dc9357SAndroid Build Coastguard Worker
905*f6dc9357SAndroid Build Coastguard Worker /*
906*f6dc9357SAndroid Build Coastguard Worker MSVC compiler adds extra move operation,
907*f6dc9357SAndroid Build Coastguard Worker if we access array with 32-bit index
908*f6dc9357SAndroid Build Coastguard Worker array[calc_index_32_bit(32-bit_var)]
909*f6dc9357SAndroid Build Coastguard Worker where calc_index_32_bit operations are: ((unsigned)a>>cnt), &, ^, |
910*f6dc9357SAndroid Build Coastguard Worker clang is also affected for ((unsigned)a>>cnt) in byte array.
911*f6dc9357SAndroid Build Coastguard Worker */
912*f6dc9357SAndroid Build Coastguard Worker
913*f6dc9357SAndroid Build Coastguard Worker // it can overread input buffer for 7-17 bytes.
914*f6dc9357SAndroid Build Coastguard Worker // (levels != levelsEnd)
915*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
916*f6dc9357SAndroid Build Coastguard Worker static ptrdiff_t ReadTable(ptrdiff_t _bitOffset, const Byte *_buf, Byte *levels, const Byte *levelsEnd)
917*f6dc9357SAndroid Build Coastguard Worker {
918*f6dc9357SAndroid Build Coastguard Worker const unsigned kNumTableBits_Level = 7;
919*f6dc9357SAndroid Build Coastguard Worker NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, kNumTableBits_Level> _levelDecoder;
920*f6dc9357SAndroid Build Coastguard Worker NHuffman::CValueInt _value;
921*f6dc9357SAndroid Build Coastguard Worker // optional check to reduce size of overread zone:
922*f6dc9357SAndroid Build Coastguard Worker if (_bitOffset > (int)0 - (int)NUM_DELTA_BIT_OFFSET_BITS - (int)(kLevelTableSize * kNumLevelBits))
923*f6dc9357SAndroid Build Coastguard Worker return DECODE_ERROR_CODE;
924*f6dc9357SAndroid Build Coastguard Worker NORMALIZE
925*f6dc9357SAndroid Build Coastguard Worker {
926*f6dc9357SAndroid Build Coastguard Worker Byte levels2[kLevelTableSize / 4 * 4];
927*f6dc9357SAndroid Build Coastguard Worker for (size_t i = 0; i < kLevelTableSize / 4 * 4; i += 4)
928*f6dc9357SAndroid Build Coastguard Worker {
929*f6dc9357SAndroid Build Coastguard Worker UInt32 val;
930*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBits_NonZero(val, kNumLevelBits * 4)
931*f6dc9357SAndroid Build Coastguard Worker levels2[i + 0] = (Byte)((val >> (3 * kNumLevelBits)));
932*f6dc9357SAndroid Build Coastguard Worker levels2[i + 1] = (Byte)((val >> (2 * kNumLevelBits)) & ((1u << kNumLevelBits) - 1));
933*f6dc9357SAndroid Build Coastguard Worker levels2[i + 2] = (Byte)((Byte)val >> (1 * kNumLevelBits));
934*f6dc9357SAndroid Build Coastguard Worker levels2[i + 3] = (Byte)((val) & ((1u << kNumLevelBits) - 1));
935*f6dc9357SAndroid Build Coastguard Worker }
936*f6dc9357SAndroid Build Coastguard Worker RIF(_levelDecoder.Build(levels2, NHuffman::k_BuildMode_Full))
937*f6dc9357SAndroid Build Coastguard Worker }
938*f6dc9357SAndroid Build Coastguard Worker
939*f6dc9357SAndroid Build Coastguard Worker do
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker unsigned sym;
942*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS_CHECK)
943*f6dc9357SAndroid Build Coastguard Worker // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return false)
944*f6dc9357SAndroid Build Coastguard Worker // sym = _levelDecoder.Decode(&bitStream);
945*f6dc9357SAndroid Build Coastguard Worker // if (!_levelDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return false;
946*f6dc9357SAndroid Build Coastguard Worker
947*f6dc9357SAndroid Build Coastguard Worker if (sym <= kNumHuffmanBits)
948*f6dc9357SAndroid Build Coastguard Worker {
949*f6dc9357SAndroid Build Coastguard Worker int delta = (int)*levels - (int)sym;
950*f6dc9357SAndroid Build Coastguard Worker delta += delta < 0 ? kNumHuffmanBits + 1 : 0;
951*f6dc9357SAndroid Build Coastguard Worker *levels++ = (Byte)delta;
952*f6dc9357SAndroid Build Coastguard Worker continue;
953*f6dc9357SAndroid Build Coastguard Worker }
954*f6dc9357SAndroid Build Coastguard Worker
955*f6dc9357SAndroid Build Coastguard Worker unsigned num;
956*f6dc9357SAndroid Build Coastguard Worker int symbol;
957*f6dc9357SAndroid Build Coastguard Worker
958*f6dc9357SAndroid Build Coastguard Worker if (sym < kLevelSym_Same)
959*f6dc9357SAndroid Build Coastguard Worker {
960*f6dc9357SAndroid Build Coastguard Worker // sym -= kLevelSym_Zero1;
961*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBits_NonZero(num, kLevelSym_Zero1_NumBits + (sym - kLevelSym_Zero1))
962*f6dc9357SAndroid Build Coastguard Worker num += (sym << kLevelSym_Zero1_NumBits) - (kLevelSym_Zero1 << kLevelSym_Zero1_NumBits) + kLevelSym_Zero1_Start;
963*f6dc9357SAndroid Build Coastguard Worker symbol = 0;
964*f6dc9357SAndroid Build Coastguard Worker }
965*f6dc9357SAndroid Build Coastguard Worker // else if (sym != kLevelSym_Same) return DECODE_ERROR_CODE;
966*f6dc9357SAndroid Build Coastguard Worker else // (sym == kLevelSym_Same)
967*f6dc9357SAndroid Build Coastguard Worker {
968*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBits_NonZero(num, kLevelSym_Same_NumBits)
969*f6dc9357SAndroid Build Coastguard Worker num += kLevelSym_Same_Start;
970*f6dc9357SAndroid Build Coastguard Worker // + (unsigned)bitStream.ReadBitsSmall(kLevelSym_Same_NumBits);
971*f6dc9357SAndroid Build Coastguard Worker // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return DECODE_ERROR_CODE)
972*f6dc9357SAndroid Build Coastguard Worker // if (!_levelDecoder.Decode2(&bitStream, sym)) return DECODE_ERROR_CODE;
973*f6dc9357SAndroid Build Coastguard Worker // sym = _levelDecoder.Decode(&bitStream);
974*f6dc9357SAndroid Build Coastguard Worker
975*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS)
976*f6dc9357SAndroid Build Coastguard Worker
977*f6dc9357SAndroid Build Coastguard Worker if (sym > kNumHuffmanBits) return DECODE_ERROR_CODE;
978*f6dc9357SAndroid Build Coastguard Worker symbol = *levels - (int)sym;
979*f6dc9357SAndroid Build Coastguard Worker symbol += symbol < 0 ? kNumHuffmanBits + 1 : 0;
980*f6dc9357SAndroid Build Coastguard Worker }
981*f6dc9357SAndroid Build Coastguard Worker
982*f6dc9357SAndroid Build Coastguard Worker if (num > (size_t)(levelsEnd - levels))
983*f6dc9357SAndroid Build Coastguard Worker return false;
984*f6dc9357SAndroid Build Coastguard Worker const Byte *limit = levels + num;
985*f6dc9357SAndroid Build Coastguard Worker do
986*f6dc9357SAndroid Build Coastguard Worker *levels++ = (Byte)symbol;
987*f6dc9357SAndroid Build Coastguard Worker while (levels != limit);
988*f6dc9357SAndroid Build Coastguard Worker }
989*f6dc9357SAndroid Build Coastguard Worker while (levels != levelsEnd);
990*f6dc9357SAndroid Build Coastguard Worker
991*f6dc9357SAndroid Build Coastguard Worker return _bitOffset;
992*f6dc9357SAndroid Build Coastguard Worker }
993*f6dc9357SAndroid Build Coastguard Worker
994*f6dc9357SAndroid Build Coastguard Worker
995*f6dc9357SAndroid Build Coastguard Worker static const unsigned kPosSlotDelta = 256 / kNumLenSlots - kPosSlotOffset;
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker
998*f6dc9357SAndroid Build Coastguard Worker #define READ_TABLE(_bitStream, levels, levelsEnd) \
999*f6dc9357SAndroid Build Coastguard Worker { \
1000*f6dc9357SAndroid Build Coastguard Worker _bitStream._bitOffset = ReadTable(_bitStream._bitOffset, _bitStream._buf, levels, levelsEnd); \
1001*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.IsOverRead()) return false; \
1002*f6dc9357SAndroid Build Coastguard Worker }
1003*f6dc9357SAndroid Build Coastguard Worker
1004*f6dc9357SAndroid Build Coastguard Worker // can over-read input buffer for less than 32 bytes
1005*f6dc9357SAndroid Build Coastguard Worker bool CDecoder::ReadTables(CBitByteDecoder &_bitStream) throw()
1006*f6dc9357SAndroid Build Coastguard Worker {
1007*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_NumTables++;)
1008*f6dc9357SAndroid Build Coastguard Worker {
1009*f6dc9357SAndroid Build Coastguard Worker const unsigned blockType = (unsigned)ReadBits(_bitStream, kBlockType_NumBits);
1010*f6dc9357SAndroid Build Coastguard Worker // if (blockType > kBlockType_Uncompressed || blockType == 0)
1011*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)(blockType - 1) > kBlockType_Uncompressed - 1)
1012*f6dc9357SAndroid Build Coastguard Worker return false;
1013*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize = 1u << 15;
1014*f6dc9357SAndroid Build Coastguard Worker if (!_wimMode || ReadBits(_bitStream, 1) == 0)
1015*f6dc9357SAndroid Build Coastguard Worker {
1016*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize = ReadBits(_bitStream, 16);
1017*f6dc9357SAndroid Build Coastguard Worker // wimlib supports chunks larger than 32KB (unsupported my MS wim).
1018*f6dc9357SAndroid Build Coastguard Worker if (!_wimMode || _numDictBits >= 16)
1019*f6dc9357SAndroid Build Coastguard Worker {
1020*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize <<= 8;
1021*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize |= ReadBits(_bitStream, 8);
1022*f6dc9357SAndroid Build Coastguard Worker }
1023*f6dc9357SAndroid Build Coastguard Worker }
1024*f6dc9357SAndroid Build Coastguard Worker
1025*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\nBlockSize = %6d %s ", _unpackBlockSize, (_pos & 1) ? "@@@" : " "));
1026*f6dc9357SAndroid Build Coastguard Worker
1027*f6dc9357SAndroid Build Coastguard Worker _isUncompressedBlock = (blockType == kBlockType_Uncompressed);
1028*f6dc9357SAndroid Build Coastguard Worker _skipByte = false;
1029*f6dc9357SAndroid Build Coastguard Worker
1030*f6dc9357SAndroid Build Coastguard Worker if (_isUncompressedBlock)
1031*f6dc9357SAndroid Build Coastguard Worker {
1032*f6dc9357SAndroid Build Coastguard Worker _skipByte = ((_unpackBlockSize & 1) != 0);
1033*f6dc9357SAndroid Build Coastguard Worker // printf("\n UncompressedBlock %d", _unpackBlockSize);
1034*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" UncompressedBlock ");)
1035*f6dc9357SAndroid Build Coastguard Worker // if (_unpackBlockSize & 1) { PRF(printf(" ######### ")); }
1036*f6dc9357SAndroid Build Coastguard Worker if (!_bitStream.Switch_To_ByteMode())
1037*f6dc9357SAndroid Build Coastguard Worker return false;
1038*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.GetRem() < kNumReps * 4)
1039*f6dc9357SAndroid Build Coastguard Worker return false;
1040*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNumReps; i++)
1041*f6dc9357SAndroid Build Coastguard Worker {
1042*f6dc9357SAndroid Build Coastguard Worker const UInt32 rep = _bitStream.ReadUInt32();
1043*f6dc9357SAndroid Build Coastguard Worker // here we allow only such values for (rep) that can be set also by LZ code:
1044*f6dc9357SAndroid Build Coastguard Worker if (rep == 0 || rep > _winSize - kNumReps)
1045*f6dc9357SAndroid Build Coastguard Worker return false;
1046*f6dc9357SAndroid Build Coastguard Worker _reps[(size_t)i + kPosSlotOffset] = rep;
1047*f6dc9357SAndroid Build Coastguard Worker }
1048*f6dc9357SAndroid Build Coastguard Worker // printf("\n");
1049*f6dc9357SAndroid Build Coastguard Worker return true;
1050*f6dc9357SAndroid Build Coastguard Worker }
1051*f6dc9357SAndroid Build Coastguard Worker
1052*f6dc9357SAndroid Build Coastguard Worker // _numAlignBits = 64;
1053*f6dc9357SAndroid Build Coastguard Worker // const UInt32 k_numAlignBits_PosSlots_MAX = 64 + kPosSlotDelta;
1054*f6dc9357SAndroid Build Coastguard Worker // _numAlignBits_PosSlots = k_numAlignBits_PosSlots_MAX;
1055*f6dc9357SAndroid Build Coastguard Worker const UInt32 k_numAlignBits_Dist_MAX = (UInt32)(Int32)-1;
1056*f6dc9357SAndroid Build Coastguard Worker _numAlignBits_Dist = k_numAlignBits_Dist_MAX;
1057*f6dc9357SAndroid Build Coastguard Worker if (blockType == kBlockType_Aligned)
1058*f6dc9357SAndroid Build Coastguard Worker {
1059*f6dc9357SAndroid Build Coastguard Worker Byte levels[kAlignTableSize];
1060*f6dc9357SAndroid Build Coastguard Worker // unsigned not0 = 0;
1061*f6dc9357SAndroid Build Coastguard Worker unsigned not3 = 0;
1062*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kAlignTableSize; i++)
1063*f6dc9357SAndroid Build Coastguard Worker {
1064*f6dc9357SAndroid Build Coastguard Worker const unsigned val = ReadBits(_bitStream, kNumAlignLevelBits);
1065*f6dc9357SAndroid Build Coastguard Worker levels[i] = (Byte)val;
1066*f6dc9357SAndroid Build Coastguard Worker // not0 |= val;
1067*f6dc9357SAndroid Build Coastguard Worker not3 |= (val ^ 3);
1068*f6dc9357SAndroid Build Coastguard Worker }
1069*f6dc9357SAndroid Build Coastguard Worker // static unsigned number = 0, all = 0; all++;
1070*f6dc9357SAndroid Build Coastguard Worker // if (!not0) return false; // Build(true) will test this case
1071*f6dc9357SAndroid Build Coastguard Worker if (not3)
1072*f6dc9357SAndroid Build Coastguard Worker {
1073*f6dc9357SAndroid Build Coastguard Worker // _numAlignBits_PosSlots = (kNumAlignBits + 1) * 2 + kPosSlotDelta;
1074*f6dc9357SAndroid Build Coastguard Worker // _numAlignBits = kNumAlignBits;
1075*f6dc9357SAndroid Build Coastguard Worker _numAlignBits_Dist = (1u << (kNumAlignBits + 1)) - (kNumReps - 1);
1076*f6dc9357SAndroid Build Coastguard Worker RIF(_alignDecoder.Build(levels, true)) // full
1077*f6dc9357SAndroid Build Coastguard Worker }
1078*f6dc9357SAndroid Build Coastguard Worker // else { number++; if (number % 4 == 0) printf("\nnumber= %u : %u%%", number, number * 100 / all); }
1079*f6dc9357SAndroid Build Coastguard Worker }
1080*f6dc9357SAndroid Build Coastguard Worker // if (_numAlignBits_PosSlots == k_numAlignBits_PosSlots_MAX)
1081*f6dc9357SAndroid Build Coastguard Worker if (_numAlignBits_Dist == k_numAlignBits_Dist_MAX)
1082*f6dc9357SAndroid Build Coastguard Worker {
1083*f6dc9357SAndroid Build Coastguard Worker size_t i;
1084*f6dc9357SAndroid Build Coastguard Worker for (i = 3; i < kNumLinearPosSlotBits; i++)
1085*f6dc9357SAndroid Build Coastguard Worker {
1086*f6dc9357SAndroid Build Coastguard Worker _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
1087*f6dc9357SAndroid Build Coastguard Worker _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));
1088*f6dc9357SAndroid Build Coastguard Worker }
1089*f6dc9357SAndroid Build Coastguard Worker for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
1090*f6dc9357SAndroid Build Coastguard Worker _extra[i + kPosSlotOffset] = (Byte)SET_NUM_BITS(kNumLinearPosSlotBits);
1091*f6dc9357SAndroid Build Coastguard Worker }
1092*f6dc9357SAndroid Build Coastguard Worker else
1093*f6dc9357SAndroid Build Coastguard Worker {
1094*f6dc9357SAndroid Build Coastguard Worker size_t i;
1095*f6dc9357SAndroid Build Coastguard Worker for (i = 3; i < kNumLinearPosSlotBits; i++)
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);
1098*f6dc9357SAndroid Build Coastguard Worker _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);
1099*f6dc9357SAndroid Build Coastguard Worker }
1100*f6dc9357SAndroid Build Coastguard Worker for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)
1101*f6dc9357SAndroid Build Coastguard Worker _extra[i + kPosSlotOffset] = (Byte)(SET_NUM_BITS(kNumLinearPosSlotBits) - 3);
1102*f6dc9357SAndroid Build Coastguard Worker }
1103*f6dc9357SAndroid Build Coastguard Worker }
1104*f6dc9357SAndroid Build Coastguard Worker
1105*f6dc9357SAndroid Build Coastguard Worker READ_TABLE(_bitStream, _mainLevels, _mainLevels + 256)
1106*f6dc9357SAndroid Build Coastguard Worker READ_TABLE(_bitStream, _mainLevels + 256, _mainLevels + 256 + _numPosLenSlots)
1107*f6dc9357SAndroid Build Coastguard Worker const unsigned end = 256 + _numPosLenSlots;
1108*f6dc9357SAndroid Build Coastguard Worker memset(_mainLevels + end, 0, kMainTableSize - end);
1109*f6dc9357SAndroid Build Coastguard Worker // #define NUM_CYC 1
1110*f6dc9357SAndroid Build Coastguard Worker // unsigned j; for (j = 0; j < NUM_CYC; j++)
1111*f6dc9357SAndroid Build Coastguard Worker RIF(_mainDecoder.Build(_mainLevels, NHuffman::k_BuildMode_Full))
1112*f6dc9357SAndroid Build Coastguard Worker // if (kNumLenSymols_Big_Start)
1113*f6dc9357SAndroid Build Coastguard Worker memset(_lenLevels, 0, kNumLenSymols_Big_Start);
1114*f6dc9357SAndroid Build Coastguard Worker READ_TABLE(_bitStream,
1115*f6dc9357SAndroid Build Coastguard Worker _lenLevels + kNumLenSymols_Big_Start,
1116*f6dc9357SAndroid Build Coastguard Worker _lenLevels + kNumLenSymols_Big_Start + kNumLenSymbols)
1117*f6dc9357SAndroid Build Coastguard Worker // for (j = 0; j < NUM_CYC; j++)
1118*f6dc9357SAndroid Build Coastguard Worker RIF(_lenDecoder.Build(_lenLevels, NHuffman::k_BuildMode_Full_or_Empty))
1119*f6dc9357SAndroid Build Coastguard Worker return true;
1120*f6dc9357SAndroid Build Coastguard Worker }
1121*f6dc9357SAndroid Build Coastguard Worker
1122*f6dc9357SAndroid Build Coastguard Worker
1123*f6dc9357SAndroid Build Coastguard Worker
1124*f6dc9357SAndroid Build Coastguard Worker static ptrdiff_t CodeLz(CDecoder *dec, size_t next, ptrdiff_t _bitOffset, const Byte *_buf) throw()
1125*f6dc9357SAndroid Build Coastguard Worker {
1126*f6dc9357SAndroid Build Coastguard Worker {
1127*f6dc9357SAndroid Build Coastguard Worker Byte *const win = dec->_win;
1128*f6dc9357SAndroid Build Coastguard Worker const UInt32 winSize = dec->_winSize;
1129*f6dc9357SAndroid Build Coastguard Worker Byte *pos = win + dec->_pos;
1130*f6dc9357SAndroid Build Coastguard Worker const Byte * const posEnd = pos + next;
1131*f6dc9357SAndroid Build Coastguard Worker NHuffman::CValueInt _value;
1132*f6dc9357SAndroid Build Coastguard Worker
1133*f6dc9357SAndroid Build Coastguard Worker NORMALIZE
1134*f6dc9357SAndroid Build Coastguard Worker
1135*f6dc9357SAndroid Build Coastguard Worker #if 1
1136*f6dc9357SAndroid Build Coastguard Worker #define HUFF_DEC_PREFIX dec->
1137*f6dc9357SAndroid Build Coastguard Worker #else
1138*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main> _mainDecoder = dec->_mainDecoder;
1139*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len> _lenDecoder = dec->_lenDecoder;
1140*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder = dec->_alignDecoder;
1141*f6dc9357SAndroid Build Coastguard Worker #define HUFF_DEC_PREFIX
1142*f6dc9357SAndroid Build Coastguard Worker #endif
1143*f6dc9357SAndroid Build Coastguard Worker
1144*f6dc9357SAndroid Build Coastguard Worker do
1145*f6dc9357SAndroid Build Coastguard Worker {
1146*f6dc9357SAndroid Build Coastguard Worker unsigned sym;
1147*f6dc9357SAndroid Build Coastguard Worker // printf("\npos = %6u", pos - win);
1148*f6dc9357SAndroid Build Coastguard Worker {
1149*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main>
1150*f6dc9357SAndroid Build Coastguard Worker *mainDecoder = & HUFF_DEC_PREFIX _mainDecoder;
1151*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE_CHECK_NO(sym, mainDecoder, kNumTableBits_Main, MOVE_POS_CHECK_STAT)
1152*f6dc9357SAndroid Build Coastguard Worker }
1153*f6dc9357SAndroid Build Coastguard Worker // if (!_mainDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return DECODE_ERROR_CODE;
1154*f6dc9357SAndroid Build Coastguard Worker // sym = _mainDecoder.Decode(&bitStream);
1155*f6dc9357SAndroid Build Coastguard Worker // if (bitStream.WasExtraReadError_Fast()) return DECODE_ERROR_CODE;
1156*f6dc9357SAndroid Build Coastguard Worker
1157*f6dc9357SAndroid Build Coastguard Worker // printf(" sym = %3x", sym);
1158*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_main[sym]++;)
1159*f6dc9357SAndroid Build Coastguard Worker
1160*f6dc9357SAndroid Build Coastguard Worker if (sym < 256)
1161*f6dc9357SAndroid Build Coastguard Worker {
1162*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_NumLits++;)
1163*f6dc9357SAndroid Build Coastguard Worker *pos++ = (Byte)sym;
1164*f6dc9357SAndroid Build Coastguard Worker }
1165*f6dc9357SAndroid Build Coastguard Worker else
1166*f6dc9357SAndroid Build Coastguard Worker {
1167*f6dc9357SAndroid Build Coastguard Worker // sym -= 256;
1168*f6dc9357SAndroid Build Coastguard Worker // if (sym >= _numPosLenSlots) return DECODE_ERROR_CODE;
1169*f6dc9357SAndroid Build Coastguard Worker const unsigned posSlot = sym / kNumLenSlots;
1170*f6dc9357SAndroid Build Coastguard Worker unsigned len = sym % kNumLenSlots + kMatchMinLen;
1171*f6dc9357SAndroid Build Coastguard Worker if (len == kNumLenSlots - 1 + kMatchMinLen)
1172*f6dc9357SAndroid Build Coastguard Worker {
1173*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len>
1174*f6dc9357SAndroid Build Coastguard Worker *lenDecoder = & HUFF_DEC_PREFIX _lenDecoder;
1175*f6dc9357SAndroid Build Coastguard Worker Z7_LZX_HUFF_DECODE_CHECK_YES(len, lenDecoder, kNumTableBits_Len, MOVE_POS_STAT)
1176*f6dc9357SAndroid Build Coastguard Worker // if (!_lenDecoder.Decode2(&bitStream, len)) return DECODE_ERROR_CODE;
1177*f6dc9357SAndroid Build Coastguard Worker // len = _lenDecoder.Decode(&bitStream);
1178*f6dc9357SAndroid Build Coastguard Worker // if (len >= kNumLenSymbols) return DECODE_ERROR_CODE;
1179*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_len[len - kNumLenSymols_Big_Start]++;)
1180*f6dc9357SAndroid Build Coastguard Worker len += kNumLenSlots - 1 + kMatchMinLen - kNumLenSymols_Big_Start;
1181*f6dc9357SAndroid Build Coastguard Worker }
1182*f6dc9357SAndroid Build Coastguard Worker /*
1183*f6dc9357SAndroid Build Coastguard Worker if ((next -= len) < 0)
1184*f6dc9357SAndroid Build Coastguard Worker return DECODE_ERROR_CODE;
1185*f6dc9357SAndroid Build Coastguard Worker */
1186*f6dc9357SAndroid Build Coastguard Worker UInt32 dist;
1187*f6dc9357SAndroid Build Coastguard Worker
1188*f6dc9357SAndroid Build Coastguard Worker dist = dec->_reps[(size_t)posSlot - kPosSlotDelta];
1189*f6dc9357SAndroid Build Coastguard Worker if (posSlot < kNumReps + 256 / kNumLenSlots)
1190*f6dc9357SAndroid Build Coastguard Worker {
1191*f6dc9357SAndroid Build Coastguard Worker // if (posSlot != kNumReps + kPosSlotDelta)
1192*f6dc9357SAndroid Build Coastguard Worker // if (posSlot - (kNumReps + kPosSlotDelta + 1) < 2)
1193*f6dc9357SAndroid Build Coastguard Worker dec->_reps[(size_t)posSlot - kPosSlotDelta] = dec->_reps[kPosSlotOffset];
1194*f6dc9357SAndroid Build Coastguard Worker /*
1195*f6dc9357SAndroid Build Coastguard Worker if (posSlot != kPosSlotDelta)
1196*f6dc9357SAndroid Build Coastguard Worker {
1197*f6dc9357SAndroid Build Coastguard Worker UInt32 temp = dist;
1198*f6dc9357SAndroid Build Coastguard Worker if (posSlot == kPosSlotDelta + 1)
1199*f6dc9357SAndroid Build Coastguard Worker {
1200*f6dc9357SAndroid Build Coastguard Worker dist = reps[1];
1201*f6dc9357SAndroid Build Coastguard Worker reps[1] = temp;
1202*f6dc9357SAndroid Build Coastguard Worker }
1203*f6dc9357SAndroid Build Coastguard Worker else
1204*f6dc9357SAndroid Build Coastguard Worker {
1205*f6dc9357SAndroid Build Coastguard Worker dist = reps[2];
1206*f6dc9357SAndroid Build Coastguard Worker reps[2] = temp;
1207*f6dc9357SAndroid Build Coastguard Worker }
1208*f6dc9357SAndroid Build Coastguard Worker // dist = reps[(size_t)(posSlot) - kPosSlotDelta];
1209*f6dc9357SAndroid Build Coastguard Worker // reps[(size_t)(posSlot) - kPosSlotDelta] = reps[0];
1210*f6dc9357SAndroid Build Coastguard Worker // reps[(size_t)(posSlot) - kPosSlotDelta] = temp;
1211*f6dc9357SAndroid Build Coastguard Worker }
1212*f6dc9357SAndroid Build Coastguard Worker */
1213*f6dc9357SAndroid Build Coastguard Worker }
1214*f6dc9357SAndroid Build Coastguard Worker else // if (posSlot != kNumReps + kPosSlotDelta)
1215*f6dc9357SAndroid Build Coastguard Worker {
1216*f6dc9357SAndroid Build Coastguard Worker unsigned numDirectBits;
1217*f6dc9357SAndroid Build Coastguard Worker #if 0
1218*f6dc9357SAndroid Build Coastguard Worker if (posSlot < kNumPowerPosSlots + kPosSlotDelta)
1219*f6dc9357SAndroid Build Coastguard Worker {
1220*f6dc9357SAndroid Build Coastguard Worker numDirectBits = (posSlot - 2 - kPosSlotDelta) >> 1;
1221*f6dc9357SAndroid Build Coastguard Worker dist = (UInt32)(2 | (posSlot & 1)) << numDirectBits;
1222*f6dc9357SAndroid Build Coastguard Worker }
1223*f6dc9357SAndroid Build Coastguard Worker else
1224*f6dc9357SAndroid Build Coastguard Worker {
1225*f6dc9357SAndroid Build Coastguard Worker numDirectBits = kNumLinearPosSlotBits;
1226*f6dc9357SAndroid Build Coastguard Worker dist = (UInt32)(posSlot - 0x22 - kPosSlotDelta) << kNumLinearPosSlotBits;
1227*f6dc9357SAndroid Build Coastguard Worker }
1228*f6dc9357SAndroid Build Coastguard Worker dist -= kNumReps - 1;
1229*f6dc9357SAndroid Build Coastguard Worker #else
1230*f6dc9357SAndroid Build Coastguard Worker numDirectBits = dec->_extra[(size_t)posSlot - kPosSlotDelta];
1231*f6dc9357SAndroid Build Coastguard Worker // dist = reps[(size_t)(posSlot) - kPosSlotDelta];
1232*f6dc9357SAndroid Build Coastguard Worker #endif
1233*f6dc9357SAndroid Build Coastguard Worker dec->_reps[kPosSlotOffset + 2] =
1234*f6dc9357SAndroid Build Coastguard Worker dec->_reps[kPosSlotOffset + 1];
1235*f6dc9357SAndroid Build Coastguard Worker dec->_reps[kPosSlotOffset + 1] =
1236*f6dc9357SAndroid Build Coastguard Worker dec->_reps[kPosSlotOffset + 0];
1237*f6dc9357SAndroid Build Coastguard Worker
1238*f6dc9357SAndroid Build Coastguard Worker // dist += val; dist += bitStream.ReadBitsBig(numDirectBits);
1239*f6dc9357SAndroid Build Coastguard Worker // if (posSlot >= _numAlignBits_PosSlots)
1240*f6dc9357SAndroid Build Coastguard Worker // if (numDirectBits >= _numAlignBits)
1241*f6dc9357SAndroid Build Coastguard Worker // if (val >= _numAlignBits_Dist)
1242*f6dc9357SAndroid Build Coastguard Worker // UInt32 val; MACRO_ReadBitsBig(val , numDirectBits)
1243*f6dc9357SAndroid Build Coastguard Worker // dist += val;
1244*f6dc9357SAndroid Build Coastguard Worker // dist += (UInt32)((UInt32)_value >> 1 >> (/* 31 ^ */ (numDirectBits)));
1245*f6dc9357SAndroid Build Coastguard Worker // MOVE_POS((numDirectBits ^ 31))
1246*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBitsBig_pre(numDirectBits)
1247*f6dc9357SAndroid Build Coastguard Worker // dist += (UInt32)_value;
1248*f6dc9357SAndroid Build Coastguard Worker if (dist >= dec->_numAlignBits_Dist)
1249*f6dc9357SAndroid Build Coastguard Worker {
1250*f6dc9357SAndroid Build Coastguard Worker // if (numDirectBits != _numAlignBits)
1251*f6dc9357SAndroid Build Coastguard Worker {
1252*f6dc9357SAndroid Build Coastguard Worker // UInt32 val;
1253*f6dc9357SAndroid Build Coastguard Worker // dist -= (UInt32)_value;
1254*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBitsBig_add3(dist)
1255*f6dc9357SAndroid Build Coastguard Worker NORMALIZE
1256*f6dc9357SAndroid Build Coastguard Worker // dist += (val << kNumAlignBits);
1257*f6dc9357SAndroid Build Coastguard Worker // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;
1258*f6dc9357SAndroid Build Coastguard Worker }
1259*f6dc9357SAndroid Build Coastguard Worker {
1260*f6dc9357SAndroid Build Coastguard Worker // const unsigned alignTemp = _alignDecoder.Decode(&bitStream);
1261*f6dc9357SAndroid Build Coastguard Worker const NHuffman::CDecoder7b<kAlignTableSize> *alignDecoder = & HUFF_DEC_PREFIX _alignDecoder;
1262*f6dc9357SAndroid Build Coastguard Worker unsigned alignTemp;
1263*f6dc9357SAndroid Build Coastguard Worker UPDATE_STAT(g_stats_NumAlign++;)
1264*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODER_7B_DECODE(alignTemp, alignDecoder, GET_VAL_BASE, MOVE_POS, bs)
1265*f6dc9357SAndroid Build Coastguard Worker // NORMALIZE
1266*f6dc9357SAndroid Build Coastguard Worker // if (alignTemp >= kAlignTableSize) return DECODE_ERROR_CODE;
1267*f6dc9357SAndroid Build Coastguard Worker dist += alignTemp;
1268*f6dc9357SAndroid Build Coastguard Worker }
1269*f6dc9357SAndroid Build Coastguard Worker }
1270*f6dc9357SAndroid Build Coastguard Worker else
1271*f6dc9357SAndroid Build Coastguard Worker {
1272*f6dc9357SAndroid Build Coastguard Worker {
1273*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBitsBig_add(dist)
1274*f6dc9357SAndroid Build Coastguard Worker // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;
1275*f6dc9357SAndroid Build Coastguard Worker }
1276*f6dc9357SAndroid Build Coastguard Worker }
1277*f6dc9357SAndroid Build Coastguard Worker NORMALIZE
1278*f6dc9357SAndroid Build Coastguard Worker /*
1279*f6dc9357SAndroid Build Coastguard Worker else
1280*f6dc9357SAndroid Build Coastguard Worker {
1281*f6dc9357SAndroid Build Coastguard Worker UInt32 val;
1282*f6dc9357SAndroid Build Coastguard Worker MACRO_ReadBitsBig(val, numDirectBits)
1283*f6dc9357SAndroid Build Coastguard Worker dist += val;
1284*f6dc9357SAndroid Build Coastguard Worker // dist += bitStream.ReadBitsBig(numDirectBits);
1285*f6dc9357SAndroid Build Coastguard Worker }
1286*f6dc9357SAndroid Build Coastguard Worker */
1287*f6dc9357SAndroid Build Coastguard Worker }
1288*f6dc9357SAndroid Build Coastguard Worker dec->_reps[kPosSlotOffset + 0] = dist;
1289*f6dc9357SAndroid Build Coastguard Worker
1290*f6dc9357SAndroid Build Coastguard Worker Byte *dest = pos;
1291*f6dc9357SAndroid Build Coastguard Worker if (len > (size_t)(posEnd - pos))
1292*f6dc9357SAndroid Build Coastguard Worker return DECODE_ERROR_CODE;
1293*f6dc9357SAndroid Build Coastguard Worker Int32 srcPos = (Int32)(pos - win);
1294*f6dc9357SAndroid Build Coastguard Worker pos += len;
1295*f6dc9357SAndroid Build Coastguard Worker srcPos -= (Int32)dist;
1296*f6dc9357SAndroid Build Coastguard Worker if (srcPos < 0) // fast version
1297*f6dc9357SAndroid Build Coastguard Worker {
1298*f6dc9357SAndroid Build Coastguard Worker if (!dec->_overDict)
1299*f6dc9357SAndroid Build Coastguard Worker return DECODE_ERROR_CODE;
1300*f6dc9357SAndroid Build Coastguard Worker srcPos &= winSize - 1;
1301*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = winSize - (UInt32)srcPos;
1302*f6dc9357SAndroid Build Coastguard Worker if (len > rem)
1303*f6dc9357SAndroid Build Coastguard Worker {
1304*f6dc9357SAndroid Build Coastguard Worker len -= rem;
1305*f6dc9357SAndroid Build Coastguard Worker const Byte *src = win + (UInt32)srcPos;
1306*f6dc9357SAndroid Build Coastguard Worker do
1307*f6dc9357SAndroid Build Coastguard Worker *dest++ = *src++;
1308*f6dc9357SAndroid Build Coastguard Worker while (--rem);
1309*f6dc9357SAndroid Build Coastguard Worker srcPos = 0;
1310*f6dc9357SAndroid Build Coastguard Worker }
1311*f6dc9357SAndroid Build Coastguard Worker }
1312*f6dc9357SAndroid Build Coastguard Worker CopyLzMatch(dest, win + (UInt32)srcPos, len, dist);
1313*f6dc9357SAndroid Build Coastguard Worker }
1314*f6dc9357SAndroid Build Coastguard Worker }
1315*f6dc9357SAndroid Build Coastguard Worker while (pos != posEnd);
1316*f6dc9357SAndroid Build Coastguard Worker
1317*f6dc9357SAndroid Build Coastguard Worker return _bitOffset;
1318*f6dc9357SAndroid Build Coastguard Worker }
1319*f6dc9357SAndroid Build Coastguard Worker }
1320*f6dc9357SAndroid Build Coastguard Worker
1321*f6dc9357SAndroid Build Coastguard Worker
1322*f6dc9357SAndroid Build Coastguard Worker
1323*f6dc9357SAndroid Build Coastguard Worker
1324*f6dc9357SAndroid Build Coastguard Worker // inSize != 0
1325*f6dc9357SAndroid Build Coastguard Worker // outSize != 0 ???
1326*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) throw()
1327*f6dc9357SAndroid Build Coastguard Worker {
1328*f6dc9357SAndroid Build Coastguard Worker // ((inSize & 1) != 0) case is possible, if current call will be finished with Uncompressed Block.
1329*f6dc9357SAndroid Build Coastguard Worker CBitByteDecoder _bitStream;
1330*f6dc9357SAndroid Build Coastguard Worker if (_keepHistory && _isUncompressedBlock)
1331*f6dc9357SAndroid Build Coastguard Worker _bitStream.Init_ByteMode(inData, inSize);
1332*f6dc9357SAndroid Build Coastguard Worker else
1333*f6dc9357SAndroid Build Coastguard Worker _bitStream.Init_BitMode(inData, inSize);
1334*f6dc9357SAndroid Build Coastguard Worker
1335*f6dc9357SAndroid Build Coastguard Worker if (!_keepHistory)
1336*f6dc9357SAndroid Build Coastguard Worker {
1337*f6dc9357SAndroid Build Coastguard Worker _isUncompressedBlock = false;
1338*f6dc9357SAndroid Build Coastguard Worker _skipByte = false;
1339*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize = 0;
1340*f6dc9357SAndroid Build Coastguard Worker memset(_mainLevels, 0, sizeof(_mainLevels));
1341*f6dc9357SAndroid Build Coastguard Worker memset(_lenLevels, 0, sizeof(_lenLevels));
1342*f6dc9357SAndroid Build Coastguard Worker {
1343*f6dc9357SAndroid Build Coastguard Worker _x86_translationSize = 12000000;
1344*f6dc9357SAndroid Build Coastguard Worker if (!_wimMode)
1345*f6dc9357SAndroid Build Coastguard Worker {
1346*f6dc9357SAndroid Build Coastguard Worker _x86_translationSize = 0;
1347*f6dc9357SAndroid Build Coastguard Worker if (ReadBits(_bitStream, 1) != 0)
1348*f6dc9357SAndroid Build Coastguard Worker {
1349*f6dc9357SAndroid Build Coastguard Worker UInt32 v = ReadBits(_bitStream, 16) << 16;
1350*f6dc9357SAndroid Build Coastguard Worker v |= ReadBits(_bitStream, 16);
1351*f6dc9357SAndroid Build Coastguard Worker _x86_translationSize = v;
1352*f6dc9357SAndroid Build Coastguard Worker }
1353*f6dc9357SAndroid Build Coastguard Worker }
1354*f6dc9357SAndroid Build Coastguard Worker _x86_processedSize = 0;
1355*f6dc9357SAndroid Build Coastguard Worker }
1356*f6dc9357SAndroid Build Coastguard Worker _reps[0 + kPosSlotOffset] = 1;
1357*f6dc9357SAndroid Build Coastguard Worker _reps[1 + kPosSlotOffset] = 1;
1358*f6dc9357SAndroid Build Coastguard Worker _reps[2 + kPosSlotOffset] = 1;
1359*f6dc9357SAndroid Build Coastguard Worker }
1360*f6dc9357SAndroid Build Coastguard Worker
1361*f6dc9357SAndroid Build Coastguard Worker while (outSize)
1362*f6dc9357SAndroid Build Coastguard Worker {
1363*f6dc9357SAndroid Build Coastguard Worker /*
1364*f6dc9357SAndroid Build Coastguard Worker // check it for bit mode only:
1365*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.WasExtraReadError_Fast())
1366*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1367*f6dc9357SAndroid Build Coastguard Worker */
1368*f6dc9357SAndroid Build Coastguard Worker if (_unpackBlockSize == 0)
1369*f6dc9357SAndroid Build Coastguard Worker {
1370*f6dc9357SAndroid Build Coastguard Worker if (_skipByte)
1371*f6dc9357SAndroid Build Coastguard Worker {
1372*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.GetRem() < 1)
1373*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1374*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.DirectReadByte() != 0)
1375*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1376*f6dc9357SAndroid Build Coastguard Worker }
1377*f6dc9357SAndroid Build Coastguard Worker if (_isUncompressedBlock)
1378*f6dc9357SAndroid Build Coastguard Worker _bitStream.Switch_To_BitMode();
1379*f6dc9357SAndroid Build Coastguard Worker if (!ReadTables(_bitStream))
1380*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1381*f6dc9357SAndroid Build Coastguard Worker continue;
1382*f6dc9357SAndroid Build Coastguard Worker }
1383*f6dc9357SAndroid Build Coastguard Worker
1384*f6dc9357SAndroid Build Coastguard Worker // _unpackBlockSize != 0
1385*f6dc9357SAndroid Build Coastguard Worker UInt32 next = _unpackBlockSize;
1386*f6dc9357SAndroid Build Coastguard Worker if (next > outSize)
1387*f6dc9357SAndroid Build Coastguard Worker next = outSize;
1388*f6dc9357SAndroid Build Coastguard Worker // next != 0
1389*f6dc9357SAndroid Build Coastguard Worker
1390*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\nnext = %d", (unsigned)next);)
1391*f6dc9357SAndroid Build Coastguard Worker
1392*f6dc9357SAndroid Build Coastguard Worker if (_isUncompressedBlock)
1393*f6dc9357SAndroid Build Coastguard Worker {
1394*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.GetRem() < next)
1395*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1396*f6dc9357SAndroid Build Coastguard Worker _bitStream.CopyTo(_win + _pos, next);
1397*f6dc9357SAndroid Build Coastguard Worker _pos += next;
1398*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize -= next;
1399*f6dc9357SAndroid Build Coastguard Worker }
1400*f6dc9357SAndroid Build Coastguard Worker else
1401*f6dc9357SAndroid Build Coastguard Worker {
1402*f6dc9357SAndroid Build Coastguard Worker _unpackBlockSize -= next;
1403*f6dc9357SAndroid Build Coastguard Worker _bitStream._bitOffset = CodeLz(this, next, _bitStream._bitOffset, _bitStream._buf);
1404*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.IsOverRead())
1405*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1406*f6dc9357SAndroid Build Coastguard Worker _pos += next;
1407*f6dc9357SAndroid Build Coastguard Worker }
1408*f6dc9357SAndroid Build Coastguard Worker outSize -= next;
1409*f6dc9357SAndroid Build Coastguard Worker }
1410*f6dc9357SAndroid Build Coastguard Worker
1411*f6dc9357SAndroid Build Coastguard Worker // outSize == 0
1412*f6dc9357SAndroid Build Coastguard Worker
1413*f6dc9357SAndroid Build Coastguard Worker if (_isUncompressedBlock)
1414*f6dc9357SAndroid Build Coastguard Worker {
1415*f6dc9357SAndroid Build Coastguard Worker /* we don't know where skipByte can be placed, if it's end of chunk:
1416*f6dc9357SAndroid Build Coastguard Worker 1) in current chunk - there are such cab archives, if chunk is last
1417*f6dc9357SAndroid Build Coastguard Worker 2) in next chunk - are there such archives ? */
1418*f6dc9357SAndroid Build Coastguard Worker if (_unpackBlockSize == 0
1419*f6dc9357SAndroid Build Coastguard Worker && _skipByte
1420*f6dc9357SAndroid Build Coastguard Worker // && outSize == 0
1421*f6dc9357SAndroid Build Coastguard Worker && _bitStream.IsOneDirectByteLeft())
1422*f6dc9357SAndroid Build Coastguard Worker {
1423*f6dc9357SAndroid Build Coastguard Worker _skipByte = false;
1424*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.DirectReadByte() != 0)
1425*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1426*f6dc9357SAndroid Build Coastguard Worker }
1427*f6dc9357SAndroid Build Coastguard Worker }
1428*f6dc9357SAndroid Build Coastguard Worker
1429*f6dc9357SAndroid Build Coastguard Worker if (_bitStream.GetRem() != 0)
1430*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1431*f6dc9357SAndroid Build Coastguard Worker if (!_isUncompressedBlock)
1432*f6dc9357SAndroid Build Coastguard Worker if (!_bitStream.WasBitStreamFinishedOK())
1433*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1434*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1435*f6dc9357SAndroid Build Coastguard Worker }
1436*f6dc9357SAndroid Build Coastguard Worker
1437*f6dc9357SAndroid Build Coastguard Worker
1438*f6dc9357SAndroid Build Coastguard Worker #if k_Filter_OutBufSize_Add > k_Lz_OutBufSize_Add
1439*f6dc9357SAndroid Build Coastguard Worker #define k_OutBufSize_Add k_Filter_OutBufSize_Add
1440*f6dc9357SAndroid Build Coastguard Worker #else
1441*f6dc9357SAndroid Build Coastguard Worker #define k_OutBufSize_Add k_Lz_OutBufSize_Add
1442*f6dc9357SAndroid Build Coastguard Worker #endif
1443*f6dc9357SAndroid Build Coastguard Worker
1444*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Code_WithExceedReadWrite(const Byte *inData, size_t inSize, UInt32 outSize) throw()
1445*f6dc9357SAndroid Build Coastguard Worker {
1446*f6dc9357SAndroid Build Coastguard Worker if (!_keepHistory)
1447*f6dc9357SAndroid Build Coastguard Worker {
1448*f6dc9357SAndroid Build Coastguard Worker _pos = 0;
1449*f6dc9357SAndroid Build Coastguard Worker _overDict = false;
1450*f6dc9357SAndroid Build Coastguard Worker }
1451*f6dc9357SAndroid Build Coastguard Worker else if (_pos == _winSize)
1452*f6dc9357SAndroid Build Coastguard Worker {
1453*f6dc9357SAndroid Build Coastguard Worker _pos = 0;
1454*f6dc9357SAndroid Build Coastguard Worker _overDict = true;
1455*f6dc9357SAndroid Build Coastguard Worker #if k_OutBufSize_Add > 0
1456*f6dc9357SAndroid Build Coastguard Worker // data after (_winSize) can be used, because we can use overwrite.
1457*f6dc9357SAndroid Build Coastguard Worker // memset(_win + _winSize, 0, k_OutBufSize_Add);
1458*f6dc9357SAndroid Build Coastguard Worker #endif
1459*f6dc9357SAndroid Build Coastguard Worker }
1460*f6dc9357SAndroid Build Coastguard Worker _writePos = _pos;
1461*f6dc9357SAndroid Build Coastguard Worker _unpackedData = _win + _pos;
1462*f6dc9357SAndroid Build Coastguard Worker
1463*f6dc9357SAndroid Build Coastguard Worker if (outSize > _winSize - _pos)
1464*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1465*f6dc9357SAndroid Build Coastguard Worker
1466*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\ninSize = %d", (unsigned)inSize);)
1467*f6dc9357SAndroid Build Coastguard Worker PRF(if ((inSize & 1) != 0) printf("---------");)
1468*f6dc9357SAndroid Build Coastguard Worker
1469*f6dc9357SAndroid Build Coastguard Worker if (inSize == 0)
1470*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1471*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = CodeSpec(inData, inSize, outSize);
1472*f6dc9357SAndroid Build Coastguard Worker const HRESULT res2 = Flush();
1473*f6dc9357SAndroid Build Coastguard Worker return (res == S_OK ? res2 : res);
1474*f6dc9357SAndroid Build Coastguard Worker }
1475*f6dc9357SAndroid Build Coastguard Worker
1476*f6dc9357SAndroid Build Coastguard Worker
1477*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::SetParams2(unsigned numDictBits) throw()
1478*f6dc9357SAndroid Build Coastguard Worker {
1479*f6dc9357SAndroid Build Coastguard Worker if (numDictBits < kNumDictBits_Min ||
1480*f6dc9357SAndroid Build Coastguard Worker numDictBits > kNumDictBits_Max)
1481*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
1482*f6dc9357SAndroid Build Coastguard Worker _numDictBits = (Byte)numDictBits;
1483*f6dc9357SAndroid Build Coastguard Worker const unsigned numPosSlots2 = (numDictBits < 20) ?
1484*f6dc9357SAndroid Build Coastguard Worker numDictBits : 17 + (1u << (numDictBits - 18));
1485*f6dc9357SAndroid Build Coastguard Worker _numPosLenSlots = numPosSlots2 * (kNumLenSlots * 2);
1486*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1487*f6dc9357SAndroid Build Coastguard Worker }
1488*f6dc9357SAndroid Build Coastguard Worker
1489*f6dc9357SAndroid Build Coastguard Worker
1490*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Set_DictBits_and_Alloc(unsigned numDictBits) throw()
1491*f6dc9357SAndroid Build Coastguard Worker {
1492*f6dc9357SAndroid Build Coastguard Worker RINOK(SetParams2(numDictBits))
1493*f6dc9357SAndroid Build Coastguard Worker const UInt32 newWinSize = (UInt32)1 << numDictBits;
1494*f6dc9357SAndroid Build Coastguard Worker if (_needAlloc)
1495*f6dc9357SAndroid Build Coastguard Worker {
1496*f6dc9357SAndroid Build Coastguard Worker if (!_win || newWinSize != _winSize)
1497*f6dc9357SAndroid Build Coastguard Worker {
1498*f6dc9357SAndroid Build Coastguard Worker // BigFree
1499*f6dc9357SAndroid Build Coastguard Worker z7_AlignedFree
1500*f6dc9357SAndroid Build Coastguard Worker (_win);
1501*f6dc9357SAndroid Build Coastguard Worker _winSize = 0;
1502*f6dc9357SAndroid Build Coastguard Worker const size_t alloc_size = newWinSize + k_OutBufSize_Add;
1503*f6dc9357SAndroid Build Coastguard Worker _win = (Byte *)
1504*f6dc9357SAndroid Build Coastguard Worker // BigAlloc
1505*f6dc9357SAndroid Build Coastguard Worker z7_AlignedAlloc
1506*f6dc9357SAndroid Build Coastguard Worker (alloc_size);
1507*f6dc9357SAndroid Build Coastguard Worker if (!_win)
1508*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
1509*f6dc9357SAndroid Build Coastguard Worker // optional:
1510*f6dc9357SAndroid Build Coastguard Worker memset(_win, 0, alloc_size);
1511*f6dc9357SAndroid Build Coastguard Worker }
1512*f6dc9357SAndroid Build Coastguard Worker }
1513*f6dc9357SAndroid Build Coastguard Worker _winSize = newWinSize;
1514*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1515*f6dc9357SAndroid Build Coastguard Worker }
1516*f6dc9357SAndroid Build Coastguard Worker
1517*f6dc9357SAndroid Build Coastguard Worker }}
1518