1*f6dc9357SAndroid Build Coastguard Worker // XpressDecoder.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 "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/RotateDefs.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "HuffmanDecoder.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "XpressDecoder.h"
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
12*f6dc9357SAndroid Build Coastguard Worker #define Z7_XPRESS_DEC_USE_UNALIGNED_COPY
13*f6dc9357SAndroid Build Coastguard Worker #endif
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_XPRESS_DEC_USE_UNALIGNED_COPY
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK_SIZE 16
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK_4_2(dest, src) \
20*f6dc9357SAndroid Build Coastguard Worker { \
21*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \
22*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \
23*f6dc9357SAndroid Build Coastguard Worker src += 4 * 2; \
24*f6dc9357SAndroid Build Coastguard Worker dest += 4 * 2; \
25*f6dc9357SAndroid Build Coastguard Worker }
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker /* sse2 doesn't help here in GCC and CLANG.
28*f6dc9357SAndroid Build Coastguard Worker so we disabled sse2 here */
29*f6dc9357SAndroid Build Coastguard Worker #if 0
30*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_AMD64)
31*f6dc9357SAndroid Build Coastguard Worker #define Z7_XPRESS_DEC_USE_SSE2
32*f6dc9357SAndroid Build Coastguard Worker #elif defined(MY_CPU_X86)
33*f6dc9357SAndroid Build Coastguard Worker #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
34*f6dc9357SAndroid Build Coastguard Worker || defined(__SSE2__) \
35*f6dc9357SAndroid Build Coastguard Worker // || 1 == 1 // for debug only
36*f6dc9357SAndroid Build Coastguard Worker #define Z7_XPRESS_DEC_USE_SSE2
37*f6dc9357SAndroid Build Coastguard Worker #endif
38*f6dc9357SAndroid Build Coastguard Worker #endif
39*f6dc9357SAndroid Build Coastguard Worker #endif
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_ARM64)
42*f6dc9357SAndroid Build Coastguard Worker #include <arm_neon.h>
43*f6dc9357SAndroid Build Coastguard Worker #define COPY_OFFSET_MIN 16
44*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK1(dest, src) \
45*f6dc9357SAndroid Build Coastguard Worker { \
46*f6dc9357SAndroid Build Coastguard Worker vst1q_u8((uint8_t *)(void *)dest, \
47*f6dc9357SAndroid Build Coastguard Worker vld1q_u8((const uint8_t *)(const void *)src)); \
48*f6dc9357SAndroid Build Coastguard Worker src += 16; \
49*f6dc9357SAndroid Build Coastguard Worker dest += 16; \
50*f6dc9357SAndroid Build Coastguard Worker }
51*f6dc9357SAndroid Build Coastguard Worker
52*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK(dest, src) \
53*f6dc9357SAndroid Build Coastguard Worker { \
54*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK1(dest, src) \
55*f6dc9357SAndroid Build Coastguard Worker if (dest >= dest_lim) break; \
56*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK1(dest, src) \
57*f6dc9357SAndroid Build Coastguard Worker }
58*f6dc9357SAndroid Build Coastguard Worker
59*f6dc9357SAndroid Build Coastguard Worker #elif defined(Z7_XPRESS_DEC_USE_SSE2)
60*f6dc9357SAndroid Build Coastguard Worker #include <emmintrin.h> // sse2
61*f6dc9357SAndroid Build Coastguard Worker #define COPY_OFFSET_MIN 16
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK1(dest, src) \
64*f6dc9357SAndroid Build Coastguard Worker { \
65*f6dc9357SAndroid Build Coastguard Worker _mm_storeu_si128((__m128i *)(void *)dest, \
66*f6dc9357SAndroid Build Coastguard Worker _mm_loadu_si128((const __m128i *)(const void *)src)); \
67*f6dc9357SAndroid Build Coastguard Worker src += 16; \
68*f6dc9357SAndroid Build Coastguard Worker dest += 16; \
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker
71*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK(dest, src) \
72*f6dc9357SAndroid Build Coastguard Worker { \
73*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK1(dest, src) \
74*f6dc9357SAndroid Build Coastguard Worker if (dest >= dest_lim) break; \
75*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK1(dest, src) \
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker
78*f6dc9357SAndroid Build Coastguard Worker #elif defined(MY_CPU_64BIT)
79*f6dc9357SAndroid Build Coastguard Worker #define COPY_OFFSET_MIN 8
80*f6dc9357SAndroid Build Coastguard Worker
81*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK(dest, src) \
82*f6dc9357SAndroid Build Coastguard Worker { \
83*f6dc9357SAndroid Build Coastguard Worker ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
84*f6dc9357SAndroid Build Coastguard Worker ((UInt64 *)(void *)dest)[1] = ((const UInt64 *)(const void *)src)[1]; \
85*f6dc9357SAndroid Build Coastguard Worker src += 8 * 2; \
86*f6dc9357SAndroid Build Coastguard Worker dest += 8 * 2; \
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker
89*f6dc9357SAndroid Build Coastguard Worker #else
90*f6dc9357SAndroid Build Coastguard Worker #define COPY_OFFSET_MIN 4
91*f6dc9357SAndroid Build Coastguard Worker
92*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK(dest, src) \
93*f6dc9357SAndroid Build Coastguard Worker { \
94*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_4_2(dest, src); \
95*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_4_2(dest, src); \
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker
98*f6dc9357SAndroid Build Coastguard Worker #endif
99*f6dc9357SAndroid Build Coastguard Worker #endif
100*f6dc9357SAndroid Build Coastguard Worker
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker #ifndef COPY_CHUNK_SIZE
103*f6dc9357SAndroid Build Coastguard Worker #define COPY_OFFSET_MIN 4
104*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK_SIZE 8
105*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK_2(dest, src) \
106*f6dc9357SAndroid Build Coastguard Worker { \
107*f6dc9357SAndroid Build Coastguard Worker const Byte a0 = src[0]; \
108*f6dc9357SAndroid Build Coastguard Worker const Byte a1 = src[1]; \
109*f6dc9357SAndroid Build Coastguard Worker dest[0] = a0; \
110*f6dc9357SAndroid Build Coastguard Worker dest[1] = a1; \
111*f6dc9357SAndroid Build Coastguard Worker src += 2; \
112*f6dc9357SAndroid Build Coastguard Worker dest += 2; \
113*f6dc9357SAndroid Build Coastguard Worker }
114*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNK(dest, src) \
115*f6dc9357SAndroid Build Coastguard Worker { \
116*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_2(dest, src) \
117*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_2(dest, src) \
118*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_2(dest, src) \
119*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_2(dest, src) \
120*f6dc9357SAndroid Build Coastguard Worker }
121*f6dc9357SAndroid Build Coastguard Worker #endif
122*f6dc9357SAndroid Build Coastguard Worker
123*f6dc9357SAndroid Build Coastguard Worker
124*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNKS \
125*f6dc9357SAndroid Build Coastguard Worker { \
126*f6dc9357SAndroid Build Coastguard Worker Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
127*f6dc9357SAndroid Build Coastguard Worker do { COPY_CHUNK(dest, src) } \
128*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim); \
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker
131*f6dc9357SAndroid Build Coastguard Worker
132*f6dc9357SAndroid Build Coastguard Worker static
133*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
134*f6dc9357SAndroid Build Coastguard Worker // Z7_ATTRIB_NO_VECTOR
CopyMatch_1(Byte * dest,const Byte * dest_lim)135*f6dc9357SAndroid Build Coastguard Worker void CopyMatch_1(Byte *dest, const Byte *dest_lim)
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker const unsigned b0 = dest[-1];
138*f6dc9357SAndroid Build Coastguard Worker {
139*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)
140*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_64BIT)
141*f6dc9357SAndroid Build Coastguard Worker {
142*f6dc9357SAndroid Build Coastguard Worker const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;
143*f6dc9357SAndroid Build Coastguard Worker Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
144*f6dc9357SAndroid Build Coastguard Worker do
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker ((UInt64 *)(void *)dest)[0] = v64;
147*f6dc9357SAndroid Build Coastguard Worker ((UInt64 *)(void *)dest)[1] = v64;
148*f6dc9357SAndroid Build Coastguard Worker dest += 16;
149*f6dc9357SAndroid Build Coastguard Worker }
150*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
151*f6dc9357SAndroid Build Coastguard Worker }
152*f6dc9357SAndroid Build Coastguard Worker #else
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker UInt32 v = b0;
155*f6dc9357SAndroid Build Coastguard Worker v |= v << 8;
156*f6dc9357SAndroid Build Coastguard Worker v |= v << 16;
157*f6dc9357SAndroid Build Coastguard Worker do
158*f6dc9357SAndroid Build Coastguard Worker {
159*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[0] = v;
160*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[1] = v;
161*f6dc9357SAndroid Build Coastguard Worker dest += 8;
162*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[0] = v;
163*f6dc9357SAndroid Build Coastguard Worker ((UInt32 *)(void *)dest)[1] = v;
164*f6dc9357SAndroid Build Coastguard Worker dest += 8;
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
167*f6dc9357SAndroid Build Coastguard Worker }
168*f6dc9357SAndroid Build Coastguard Worker #endif
169*f6dc9357SAndroid Build Coastguard Worker #else
170*f6dc9357SAndroid Build Coastguard Worker do
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
173*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b0;
174*f6dc9357SAndroid Build Coastguard Worker dest += 2;
175*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
176*f6dc9357SAndroid Build Coastguard Worker dest[1] = (Byte)b0;
177*f6dc9357SAndroid Build Coastguard Worker dest += 2;
178*f6dc9357SAndroid Build Coastguard Worker }
179*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
180*f6dc9357SAndroid Build Coastguard Worker #endif
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker
184*f6dc9357SAndroid Build Coastguard Worker
185*f6dc9357SAndroid Build Coastguard Worker // (offset != 1)
186*f6dc9357SAndroid Build Coastguard Worker static
187*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
188*f6dc9357SAndroid Build Coastguard Worker // Z7_ATTRIB_NO_VECTOR
CopyMatch_Non1(Byte * dest,size_t offset,const Byte * dest_lim)189*f6dc9357SAndroid Build Coastguard Worker void CopyMatch_Non1(Byte *dest, size_t offset, const Byte *dest_lim)
190*f6dc9357SAndroid Build Coastguard Worker {
191*f6dc9357SAndroid Build Coastguard Worker const Byte *src = dest - offset;
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker // (COPY_OFFSET_MIN >= 4)
194*f6dc9357SAndroid Build Coastguard Worker if (offset >= COPY_OFFSET_MIN)
195*f6dc9357SAndroid Build Coastguard Worker {
196*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNKS
197*f6dc9357SAndroid Build Coastguard Worker // return;
198*f6dc9357SAndroid Build Coastguard Worker }
199*f6dc9357SAndroid Build Coastguard Worker else
200*f6dc9357SAndroid Build Coastguard Worker #if (COPY_OFFSET_MIN > 4)
201*f6dc9357SAndroid Build Coastguard Worker #if COPY_CHUNK_SIZE < 8
202*f6dc9357SAndroid Build Coastguard Worker #error Stop_Compiling_Bad_COPY_CHUNK_SIZE
203*f6dc9357SAndroid Build Coastguard Worker #endif
204*f6dc9357SAndroid Build Coastguard Worker if (offset >= 4)
205*f6dc9357SAndroid Build Coastguard Worker {
206*f6dc9357SAndroid Build Coastguard Worker Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
207*f6dc9357SAndroid Build Coastguard Worker do
208*f6dc9357SAndroid Build Coastguard Worker {
209*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_4_2(dest, src)
210*f6dc9357SAndroid Build Coastguard Worker #if COPY_CHUNK_SIZE != 16
211*f6dc9357SAndroid Build Coastguard Worker if (dest >= dest_lim) break;
212*f6dc9357SAndroid Build Coastguard Worker #endif
213*f6dc9357SAndroid Build Coastguard Worker COPY_CHUNK_4_2(dest, src)
214*f6dc9357SAndroid Build Coastguard Worker }
215*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
216*f6dc9357SAndroid Build Coastguard Worker // return;
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker else
219*f6dc9357SAndroid Build Coastguard Worker #endif
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker // (offset < 4)
222*f6dc9357SAndroid Build Coastguard Worker if (offset == 2)
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)
225*f6dc9357SAndroid Build Coastguard Worker UInt32 w0 = GetUi16(src);
226*f6dc9357SAndroid Build Coastguard Worker w0 += w0 << 16;
227*f6dc9357SAndroid Build Coastguard Worker do
228*f6dc9357SAndroid Build Coastguard Worker {
229*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest, w0)
230*f6dc9357SAndroid Build Coastguard Worker dest += 4;
231*f6dc9357SAndroid Build Coastguard Worker }
232*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
233*f6dc9357SAndroid Build Coastguard Worker #else
234*f6dc9357SAndroid Build Coastguard Worker const unsigned b0 = src[0];
235*f6dc9357SAndroid Build Coastguard Worker const Byte b1 = src[1];
236*f6dc9357SAndroid Build Coastguard Worker do
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
239*f6dc9357SAndroid Build Coastguard Worker dest[1] = b1;
240*f6dc9357SAndroid Build Coastguard Worker dest += 2;
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
243*f6dc9357SAndroid Build Coastguard Worker #endif
244*f6dc9357SAndroid Build Coastguard Worker }
245*f6dc9357SAndroid Build Coastguard Worker else // (offset == 3)
246*f6dc9357SAndroid Build Coastguard Worker {
247*f6dc9357SAndroid Build Coastguard Worker const unsigned b0 = src[0];
248*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)
249*f6dc9357SAndroid Build Coastguard Worker const unsigned w1 = GetUi16(src + 1);
250*f6dc9357SAndroid Build Coastguard Worker do
251*f6dc9357SAndroid Build Coastguard Worker {
252*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
253*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest + 1, (UInt16)w1)
254*f6dc9357SAndroid Build Coastguard Worker dest += 3;
255*f6dc9357SAndroid Build Coastguard Worker }
256*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
257*f6dc9357SAndroid Build Coastguard Worker #else
258*f6dc9357SAndroid Build Coastguard Worker const Byte b1 = src[1];
259*f6dc9357SAndroid Build Coastguard Worker const Byte b2 = src[2];
260*f6dc9357SAndroid Build Coastguard Worker do
261*f6dc9357SAndroid Build Coastguard Worker {
262*f6dc9357SAndroid Build Coastguard Worker dest[0] = (Byte)b0;
263*f6dc9357SAndroid Build Coastguard Worker dest[1] = b1;
264*f6dc9357SAndroid Build Coastguard Worker dest[2] = b2;
265*f6dc9357SAndroid Build Coastguard Worker dest += 3;
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker while (dest < dest_lim);
268*f6dc9357SAndroid Build Coastguard Worker #endif
269*f6dc9357SAndroid Build Coastguard Worker }
270*f6dc9357SAndroid Build Coastguard Worker }
271*f6dc9357SAndroid Build Coastguard Worker }
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker
275*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
276*f6dc9357SAndroid Build Coastguard Worker namespace NXpress {
277*f6dc9357SAndroid Build Coastguard Worker
278*f6dc9357SAndroid Build Coastguard Worker #define BIT_STREAM_NORMALIZE \
279*f6dc9357SAndroid Build Coastguard Worker if (BitPos > 16) { \
280*f6dc9357SAndroid Build Coastguard Worker if (in >= lim) return S_FALSE; \
281*f6dc9357SAndroid Build Coastguard Worker BitPos -= 16; \
282*f6dc9357SAndroid Build Coastguard Worker Value |= (UInt32)GetUi16(in) << BitPos; \
283*f6dc9357SAndroid Build Coastguard Worker in += 2; }
284*f6dc9357SAndroid Build Coastguard Worker
285*f6dc9357SAndroid Build Coastguard Worker #define MOVE_POS(bs, numBits) \
286*f6dc9357SAndroid Build Coastguard Worker BitPos += (unsigned)numBits; \
287*f6dc9357SAndroid Build Coastguard Worker Value <<= numBits; \
288*f6dc9357SAndroid Build Coastguard Worker
289*f6dc9357SAndroid Build Coastguard Worker
290*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumHuffBits = 15;
291*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumTableBits = 10;
292*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumLenBits = 4;
293*f6dc9357SAndroid Build Coastguard Worker static const unsigned kLenMask = (1 << kNumLenBits) - 1;
294*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumPosSlots = 16;
295*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumSyms = 256 + (kNumPosSlots << kNumLenBits);
296*f6dc9357SAndroid Build Coastguard Worker
Decode_WithExceedWrite(const Byte * in,size_t inSize,Byte * out,size_t outSize)297*f6dc9357SAndroid Build Coastguard Worker HRESULT Decode_WithExceedWrite(const Byte *in, size_t inSize, Byte *out, size_t outSize)
298*f6dc9357SAndroid Build Coastguard Worker {
299*f6dc9357SAndroid Build Coastguard Worker NCompress::NHuffman::CDecoder<kNumHuffBits, kNumSyms, kNumTableBits> huff;
300*f6dc9357SAndroid Build Coastguard Worker
301*f6dc9357SAndroid Build Coastguard Worker if (inSize < kNumSyms / 2 + 4)
302*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
303*f6dc9357SAndroid Build Coastguard Worker {
304*f6dc9357SAndroid Build Coastguard Worker Byte levels[kNumSyms];
305*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNumSyms / 2; i++)
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker const unsigned b = in[i];
308*f6dc9357SAndroid Build Coastguard Worker levels[(size_t)i * 2 ] = (Byte)(b & 0xf);
309*f6dc9357SAndroid Build Coastguard Worker levels[(size_t)i * 2 + 1] = (Byte)(b >> 4);
310*f6dc9357SAndroid Build Coastguard Worker }
311*f6dc9357SAndroid Build Coastguard Worker if (!huff.Build(levels, NHuffman::k_BuildMode_Full))
312*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
313*f6dc9357SAndroid Build Coastguard Worker }
314*f6dc9357SAndroid Build Coastguard Worker
315*f6dc9357SAndroid Build Coastguard Worker UInt32 Value;
316*f6dc9357SAndroid Build Coastguard Worker unsigned BitPos; // how many bits in (Value) were processed
317*f6dc9357SAndroid Build Coastguard Worker
318*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = in + inSize - 1; // points to last byte
319*f6dc9357SAndroid Build Coastguard Worker in += kNumSyms / 2;
320*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
321*f6dc9357SAndroid Build Coastguard Worker Value = GetUi32(in);
322*f6dc9357SAndroid Build Coastguard Worker Value = rotlFixed(Value, 16);
323*f6dc9357SAndroid Build Coastguard Worker #else
324*f6dc9357SAndroid Build Coastguard Worker Value = ((UInt32)GetUi16(in) << 16) | GetUi16(in + 2);
325*f6dc9357SAndroid Build Coastguard Worker #endif
326*f6dc9357SAndroid Build Coastguard Worker
327*f6dc9357SAndroid Build Coastguard Worker in += 4;
328*f6dc9357SAndroid Build Coastguard Worker BitPos = 0;
329*f6dc9357SAndroid Build Coastguard Worker Byte *dest = out;
330*f6dc9357SAndroid Build Coastguard Worker const Byte *outLim = out + outSize;
331*f6dc9357SAndroid Build Coastguard Worker
332*f6dc9357SAndroid Build Coastguard Worker for (;;)
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker unsigned sym;
335*f6dc9357SAndroid Build Coastguard Worker Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, &huff, kNumHuffBits, kNumTableBits,
336*f6dc9357SAndroid Build Coastguard Worker Value, Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {}, MOVE_POS, {}, bs)
337*f6dc9357SAndroid Build Coastguard Worker // 0 < BitPos <= 31
338*f6dc9357SAndroid Build Coastguard Worker BIT_STREAM_NORMALIZE
339*f6dc9357SAndroid Build Coastguard Worker // 0 < BitPos <= 16
340*f6dc9357SAndroid Build Coastguard Worker
341*f6dc9357SAndroid Build Coastguard Worker if (dest >= outLim)
342*f6dc9357SAndroid Build Coastguard Worker return (sym == 256 && Value == 0 && in == lim + 1) ? S_OK : S_FALSE;
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker if (sym < 256)
345*f6dc9357SAndroid Build Coastguard Worker *dest++ = (Byte)sym;
346*f6dc9357SAndroid Build Coastguard Worker else
347*f6dc9357SAndroid Build Coastguard Worker {
348*f6dc9357SAndroid Build Coastguard Worker const unsigned distBits = (unsigned)(Byte)sym >> kNumLenBits; // (sym - 256) >> kNumLenBits;
349*f6dc9357SAndroid Build Coastguard Worker UInt32 len = (UInt32)(sym & kLenMask);
350*f6dc9357SAndroid Build Coastguard Worker
351*f6dc9357SAndroid Build Coastguard Worker if (len == kLenMask)
352*f6dc9357SAndroid Build Coastguard Worker {
353*f6dc9357SAndroid Build Coastguard Worker if (in > lim)
354*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
355*f6dc9357SAndroid Build Coastguard Worker // here we read input bytes in out-of-order related to main input stream (bits in Value):
356*f6dc9357SAndroid Build Coastguard Worker len = *in++;
357*f6dc9357SAndroid Build Coastguard Worker if (len == 0xff)
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker if (in >= lim)
360*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
361*f6dc9357SAndroid Build Coastguard Worker len = GetUi16(in);
362*f6dc9357SAndroid Build Coastguard Worker in += 2;
363*f6dc9357SAndroid Build Coastguard Worker }
364*f6dc9357SAndroid Build Coastguard Worker else
365*f6dc9357SAndroid Build Coastguard Worker len += kLenMask;
366*f6dc9357SAndroid Build Coastguard Worker }
367*f6dc9357SAndroid Build Coastguard Worker
368*f6dc9357SAndroid Build Coastguard Worker len += 3;
369*f6dc9357SAndroid Build Coastguard Worker if (len > (size_t)(outLim - dest))
370*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
371*f6dc9357SAndroid Build Coastguard Worker
372*f6dc9357SAndroid Build Coastguard Worker if (distBits == 0)
373*f6dc9357SAndroid Build Coastguard Worker {
374*f6dc9357SAndroid Build Coastguard Worker // d == 1
375*f6dc9357SAndroid Build Coastguard Worker if (dest == out)
376*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
377*f6dc9357SAndroid Build Coastguard Worker Byte *destTemp = dest;
378*f6dc9357SAndroid Build Coastguard Worker dest += len;
379*f6dc9357SAndroid Build Coastguard Worker CopyMatch_1(destTemp, dest);
380*f6dc9357SAndroid Build Coastguard Worker }
381*f6dc9357SAndroid Build Coastguard Worker else
382*f6dc9357SAndroid Build Coastguard Worker {
383*f6dc9357SAndroid Build Coastguard Worker unsigned d = (unsigned)(Value >> (32 - distBits));
384*f6dc9357SAndroid Build Coastguard Worker MOVE_POS(bs, distBits)
385*f6dc9357SAndroid Build Coastguard Worker d += 1u << distBits;
386*f6dc9357SAndroid Build Coastguard Worker // 0 < BitPos <= 31
387*f6dc9357SAndroid Build Coastguard Worker BIT_STREAM_NORMALIZE
388*f6dc9357SAndroid Build Coastguard Worker // 0 < BitPos <= 16
389*f6dc9357SAndroid Build Coastguard Worker if (d > (size_t)(dest - out))
390*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
391*f6dc9357SAndroid Build Coastguard Worker Byte *destTemp = dest;
392*f6dc9357SAndroid Build Coastguard Worker dest += len;
393*f6dc9357SAndroid Build Coastguard Worker CopyMatch_Non1(destTemp, d, dest);
394*f6dc9357SAndroid Build Coastguard Worker }
395*f6dc9357SAndroid Build Coastguard Worker }
396*f6dc9357SAndroid Build Coastguard Worker }
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker
399*f6dc9357SAndroid Build Coastguard Worker }}
400