xref: /aosp_15_r20/external/lzma/C/ZstdDec.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* ZstdDec.c -- Zstd Decoder
2*f6dc9357SAndroid Build Coastguard Worker 2024-06-18 : the code was developed by Igor Pavlov, using Zstandard format
3*f6dc9357SAndroid Build Coastguard Worker              specification and original zstd decoder code as reference code.
4*f6dc9357SAndroid Build Coastguard Worker original zstd decoder code: Copyright (c) Facebook, Inc. All rights reserved.
5*f6dc9357SAndroid Build Coastguard Worker This source code is licensed under BSD 3-Clause License.
6*f6dc9357SAndroid Build Coastguard Worker */
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
11*f6dc9357SAndroid Build Coastguard Worker #include <stdlib.h>
12*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "Alloc.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "Xxh64.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "ZstdDec.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_ARM64)
20*f6dc9357SAndroid Build Coastguard Worker #include <arm_neon.h>
21*f6dc9357SAndroid Build Coastguard Worker #endif
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker /* original-zstd still doesn't support window larger than 2 GiB.
24*f6dc9357SAndroid Build Coastguard Worker    So we also limit our decoder for 2 GiB window: */
25*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_64BIT) && 0 == 1
26*f6dc9357SAndroid Build Coastguard Worker   #define MAX_WINDOW_SIZE_LOG  41
27*f6dc9357SAndroid Build Coastguard Worker #else
28*f6dc9357SAndroid Build Coastguard Worker   #define MAX_WINDOW_SIZE_LOG  31
29*f6dc9357SAndroid Build Coastguard Worker #endif
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker typedef
32*f6dc9357SAndroid Build Coastguard Worker   #if MAX_WINDOW_SIZE_LOG < 32
33*f6dc9357SAndroid Build Coastguard Worker     UInt32
34*f6dc9357SAndroid Build Coastguard Worker   #else
35*f6dc9357SAndroid Build Coastguard Worker     size_t
36*f6dc9357SAndroid Build Coastguard Worker   #endif
37*f6dc9357SAndroid Build Coastguard Worker     CZstdDecOffset;
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker // for debug: simpler and smaller code but slow:
40*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_STAT
43*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_STAT
44*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
45*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Blocks_Compressed = 0;
46*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Blocks_memcpy = 0;
47*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Wrap_memmove_Num = 0;
48*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Wrap_memmove_Bytes = 0;
49*f6dc9357SAndroid Build Coastguard Worker static unsigned g_NumSeqs_total = 0;
50*f6dc9357SAndroid Build Coastguard Worker // static unsigned g_NumCopy = 0;
51*f6dc9357SAndroid Build Coastguard Worker static unsigned g_NumOver = 0;
52*f6dc9357SAndroid Build Coastguard Worker static unsigned g_NumOver2 = 0;
53*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Match = 0;
54*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Lits = 0;
55*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_LitsBig = 0;
56*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Lit0 = 0;
57*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Rep0 = 0;
58*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Rep1 = 0;
59*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Rep2 = 0;
60*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Rep3 = 0;
61*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Threshold_0 = 0;
62*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Threshold_1 = 0;
63*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Threshold_0sum = 0;
64*f6dc9357SAndroid Build Coastguard Worker static unsigned g_Num_Threshold_1sum = 0;
65*f6dc9357SAndroid Build Coastguard Worker #define STAT_UPDATE(v) v
66*f6dc9357SAndroid Build Coastguard Worker #else
67*f6dc9357SAndroid Build Coastguard Worker #define STAT_UPDATE(v)
68*f6dc9357SAndroid Build Coastguard Worker #endif
69*f6dc9357SAndroid Build Coastguard Worker #define STAT_INC(v)  STAT_UPDATE(v++;)
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker 
72*f6dc9357SAndroid Build Coastguard Worker typedef struct
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   const Byte *ptr;
75*f6dc9357SAndroid Build Coastguard Worker   size_t len;
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker CInBufPair;
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker 
80*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_ARM_OR_ARM64) || defined(MY_CPU_X86_OR_AMD64)
81*f6dc9357SAndroid Build Coastguard Worker   #if (defined(__clang__) && (__clang_major__ >= 6)) \
82*f6dc9357SAndroid Build Coastguard Worker    || (defined(__GNUC__) && (__GNUC__ >= 6))
83*f6dc9357SAndroid Build Coastguard Worker     // disable for debug:
84*f6dc9357SAndroid Build Coastguard Worker     #define Z7_ZSTD_DEC_USE_BSR
85*f6dc9357SAndroid Build Coastguard Worker   #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
86*f6dc9357SAndroid Build Coastguard Worker     // #if defined(MY_CPU_ARM_OR_ARM64)
87*f6dc9357SAndroid Build Coastguard Worker     #if (_MSC_VER >= 1600)
88*f6dc9357SAndroid Build Coastguard Worker       #include <intrin.h>
89*f6dc9357SAndroid Build Coastguard Worker     #endif
90*f6dc9357SAndroid Build Coastguard Worker     // disable for debug:
91*f6dc9357SAndroid Build Coastguard Worker     #define Z7_ZSTD_DEC_USE_BSR
92*f6dc9357SAndroid Build Coastguard Worker   #endif
93*f6dc9357SAndroid Build Coastguard Worker #endif
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_BSR
96*f6dc9357SAndroid Build Coastguard Worker   #if defined(__clang__) || defined(__GNUC__)
97*f6dc9357SAndroid Build Coastguard Worker     #define MY_clz(x)  ((unsigned)__builtin_clz((UInt32)x))
98*f6dc9357SAndroid Build Coastguard Worker   #else  // #if defined(_MSC_VER)
99*f6dc9357SAndroid Build Coastguard Worker     #ifdef MY_CPU_ARM_OR_ARM64
100*f6dc9357SAndroid Build Coastguard Worker       #define MY_clz  _CountLeadingZeros
101*f6dc9357SAndroid Build Coastguard Worker     #endif // MY_CPU_X86_OR_AMD64
102*f6dc9357SAndroid Build Coastguard Worker   #endif // _MSC_VER
103*f6dc9357SAndroid Build Coastguard Worker #elif !defined(Z7_ZSTD_DEC_USE_LOG_TABLE)
104*f6dc9357SAndroid Build Coastguard Worker   #define Z7_ZSTD_DEC_USE_LOG_TABLE
105*f6dc9357SAndroid Build Coastguard Worker #endif
106*f6dc9357SAndroid Build Coastguard Worker 
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker static
109*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
GetHighestSetBit_32_nonzero_big(UInt32 num)110*f6dc9357SAndroid Build Coastguard Worker unsigned GetHighestSetBit_32_nonzero_big(UInt32 num)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker   // (num != 0)
113*f6dc9357SAndroid Build Coastguard Worker   #ifdef MY_clz
114*f6dc9357SAndroid Build Coastguard Worker     return 31 - MY_clz(num);
115*f6dc9357SAndroid Build Coastguard Worker   #elif defined(Z7_ZSTD_DEC_USE_BSR)
116*f6dc9357SAndroid Build Coastguard Worker   {
117*f6dc9357SAndroid Build Coastguard Worker     unsigned long zz;
118*f6dc9357SAndroid Build Coastguard Worker     _BitScanReverse(&zz, num);
119*f6dc9357SAndroid Build Coastguard Worker     return zz;
120*f6dc9357SAndroid Build Coastguard Worker   }
121*f6dc9357SAndroid Build Coastguard Worker   #else
122*f6dc9357SAndroid Build Coastguard Worker   {
123*f6dc9357SAndroid Build Coastguard Worker     int i = -1;
124*f6dc9357SAndroid Build Coastguard Worker     for (;;)
125*f6dc9357SAndroid Build Coastguard Worker     {
126*f6dc9357SAndroid Build Coastguard Worker       i++;
127*f6dc9357SAndroid Build Coastguard Worker       num >>= 1;
128*f6dc9357SAndroid Build Coastguard Worker       if (num == 0)
129*f6dc9357SAndroid Build Coastguard Worker         return (unsigned)i;
130*f6dc9357SAndroid Build Coastguard Worker     }
131*f6dc9357SAndroid Build Coastguard Worker   }
132*f6dc9357SAndroid Build Coastguard Worker   #endif
133*f6dc9357SAndroid Build Coastguard Worker }
134*f6dc9357SAndroid Build Coastguard Worker 
135*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_LOG_TABLE
136*f6dc9357SAndroid Build Coastguard Worker 
137*f6dc9357SAndroid Build Coastguard Worker #define R1(a)  a, a
138*f6dc9357SAndroid Build Coastguard Worker #define R2(a)  R1(a), R1(a)
139*f6dc9357SAndroid Build Coastguard Worker #define R3(a)  R2(a), R2(a)
140*f6dc9357SAndroid Build Coastguard Worker #define R4(a)  R3(a), R3(a)
141*f6dc9357SAndroid Build Coastguard Worker #define R5(a)  R4(a), R4(a)
142*f6dc9357SAndroid Build Coastguard Worker #define R6(a)  R5(a), R5(a)
143*f6dc9357SAndroid Build Coastguard Worker #define R7(a)  R6(a), R6(a)
144*f6dc9357SAndroid Build Coastguard Worker #define R8(a)  R7(a), R7(a)
145*f6dc9357SAndroid Build Coastguard Worker #define R9(a)  R8(a), R8(a)
146*f6dc9357SAndroid Build Coastguard Worker 
147*f6dc9357SAndroid Build Coastguard Worker #define Z7_ZSTD_FSE_MAX_ACCURACY  9
148*f6dc9357SAndroid Build Coastguard Worker // states[] values in FSE_Generate() can use (Z7_ZSTD_FSE_MAX_ACCURACY + 1) bits.
149*f6dc9357SAndroid Build Coastguard Worker static const Byte k_zstd_LogTable[2 << Z7_ZSTD_FSE_MAX_ACCURACY] =
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker   R1(0), R1(1), R2(2), R3(3), R4(4), R5(5), R6(6), R7(7), R8(8), R9(9)
152*f6dc9357SAndroid Build Coastguard Worker };
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker #define GetHighestSetBit_32_nonzero_small(num)  (k_zstd_LogTable[num])
155*f6dc9357SAndroid Build Coastguard Worker #else
156*f6dc9357SAndroid Build Coastguard Worker #define GetHighestSetBit_32_nonzero_small  GetHighestSetBit_32_nonzero_big
157*f6dc9357SAndroid Build Coastguard Worker #endif
158*f6dc9357SAndroid Build Coastguard Worker 
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_clz
161*f6dc9357SAndroid Build Coastguard Worker   #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
162*f6dc9357SAndroid Build Coastguard Worker     bitOffset -= (CBitCtr)(MY_clz(b) - 23);
163*f6dc9357SAndroid Build Coastguard Worker #elif defined(Z7_ZSTD_DEC_USE_BSR)
164*f6dc9357SAndroid Build Coastguard Worker   #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
165*f6dc9357SAndroid Build Coastguard Worker     { unsigned long zz;  _BitScanReverse(&zz, b);  bitOffset -= 8;  bitOffset += zz; }
166*f6dc9357SAndroid Build Coastguard Worker #else
167*f6dc9357SAndroid Build Coastguard Worker   #define UPDATE_BIT_OFFSET_FOR_PADDING(b, bitOffset) \
168*f6dc9357SAndroid Build Coastguard Worker     for (;;) { bitOffset--;  if (b & 0x80) { break; }  b <<= 1; }
169*f6dc9357SAndroid Build Coastguard Worker #endif
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker #define SET_bitOffset_TO_PAD(bitOffset, src, srcLen) \
172*f6dc9357SAndroid Build Coastguard Worker { \
173*f6dc9357SAndroid Build Coastguard Worker   unsigned lastByte = (src)[(size_t)(srcLen) - 1]; \
174*f6dc9357SAndroid Build Coastguard Worker   if (lastByte == 0) return SZ_ERROR_DATA; \
175*f6dc9357SAndroid Build Coastguard Worker   bitOffset = (CBitCtr)((srcLen) * 8); \
176*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET_FOR_PADDING(lastByte, bitOffset) \
177*f6dc9357SAndroid Build Coastguard Worker }
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker #define SET_bitOffset_TO_PAD_and_SET_BIT_SIZE(bitOffset, src, srcLen_res) \
182*f6dc9357SAndroid Build Coastguard Worker { \
183*f6dc9357SAndroid Build Coastguard Worker   unsigned lastByte = (src)[(size_t)(srcLen_res) - 1]; \
184*f6dc9357SAndroid Build Coastguard Worker   if (lastByte == 0) return SZ_ERROR_DATA; \
185*f6dc9357SAndroid Build Coastguard Worker   srcLen_res *= 8; \
186*f6dc9357SAndroid Build Coastguard Worker   bitOffset = (CBitCtr)srcLen_res; \
187*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET_FOR_PADDING(lastByte, bitOffset) \
188*f6dc9357SAndroid Build Coastguard Worker }
189*f6dc9357SAndroid Build Coastguard Worker 
190*f6dc9357SAndroid Build Coastguard Worker #endif
191*f6dc9357SAndroid Build Coastguard Worker 
192*f6dc9357SAndroid Build Coastguard Worker /*
193*f6dc9357SAndroid Build Coastguard Worker typedef Int32 CBitCtr_signed;
194*f6dc9357SAndroid Build Coastguard Worker typedef Int32 CBitCtr;
195*f6dc9357SAndroid Build Coastguard Worker */
196*f6dc9357SAndroid Build Coastguard Worker // /*
197*f6dc9357SAndroid Build Coastguard Worker typedef ptrdiff_t CBitCtr_signed;
198*f6dc9357SAndroid Build Coastguard Worker typedef ptrdiff_t CBitCtr;
199*f6dc9357SAndroid Build Coastguard Worker // */
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker #define MATCH_LEN_MIN  3
203*f6dc9357SAndroid Build Coastguard Worker #define kBlockSizeMax  (1u << 17)
204*f6dc9357SAndroid Build Coastguard Worker 
205*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_PRINT_TABLE
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_PRINT_TABLE
208*f6dc9357SAndroid Build Coastguard Worker #define NUM_OFFSET_SYMBOLS_PREDEF 29
209*f6dc9357SAndroid Build Coastguard Worker #endif
210*f6dc9357SAndroid Build Coastguard Worker #define NUM_OFFSET_SYMBOLS_MAX    (MAX_WINDOW_SIZE_LOG + 1)  // 32
211*f6dc9357SAndroid Build Coastguard Worker #define NUM_LL_SYMBOLS            36
212*f6dc9357SAndroid Build Coastguard Worker #define NUM_ML_SYMBOLS            53
213*f6dc9357SAndroid Build Coastguard Worker #define FSE_NUM_SYMBOLS_MAX       53  // NUM_ML_SYMBOLS
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker // /*
216*f6dc9357SAndroid Build Coastguard Worker #if !defined(MY_CPU_X86) || defined(__PIC__) || defined(MY_CPU_64BIT)
217*f6dc9357SAndroid Build Coastguard Worker #define Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
218*f6dc9357SAndroid Build Coastguard Worker #endif
219*f6dc9357SAndroid Build Coastguard Worker // */
220*f6dc9357SAndroid Build Coastguard Worker // for debug:
221*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_BASES_LOCAL
222*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker #define GLOBAL_TABLE(n)  k_ ## n
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_ZSTD_DEC_USE_BASES_LOCAL)
227*f6dc9357SAndroid Build Coastguard Worker   #define BASES_TABLE(n)  a_ ## n
228*f6dc9357SAndroid Build Coastguard Worker #elif defined(Z7_ZSTD_DEC_USE_BASES_IN_OBJECT)
229*f6dc9357SAndroid Build Coastguard Worker   #define BASES_TABLE(n)  p->m_ ## n
230*f6dc9357SAndroid Build Coastguard Worker #else
231*f6dc9357SAndroid Build Coastguard Worker   #define BASES_TABLE(n)  GLOBAL_TABLE(n)
232*f6dc9357SAndroid Build Coastguard Worker #endif
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker #define Z7_ZSTD_DEC_USE_ML_PLUS3
235*f6dc9357SAndroid Build Coastguard Worker 
236*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_ZSTD_DEC_USE_BASES_LOCAL) || \
237*f6dc9357SAndroid Build Coastguard Worker     defined(Z7_ZSTD_DEC_USE_BASES_IN_OBJECT)
238*f6dc9357SAndroid Build Coastguard Worker 
239*f6dc9357SAndroid Build Coastguard Worker #define SEQ_EXTRA_TABLES(n) \
240*f6dc9357SAndroid Build Coastguard Worker   Byte   n ## SEQ_LL_EXTRA [NUM_LL_SYMBOLS]; \
241*f6dc9357SAndroid Build Coastguard Worker   Byte   n ## SEQ_ML_EXTRA [NUM_ML_SYMBOLS]; \
242*f6dc9357SAndroid Build Coastguard Worker   UInt32 n ## SEQ_LL_BASES [NUM_LL_SYMBOLS]; \
243*f6dc9357SAndroid Build Coastguard Worker   UInt32 n ## SEQ_ML_BASES [NUM_ML_SYMBOLS]; \
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker #define Z7_ZSTD_DEC_USE_BASES_CALC
246*f6dc9357SAndroid Build Coastguard Worker 
247*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_BASES_CALC
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker   #define FILL_LOC_BASES(n, startSum) \
250*f6dc9357SAndroid Build Coastguard Worker     { unsigned i; UInt32 sum = startSum; \
251*f6dc9357SAndroid Build Coastguard Worker       for (i = 0; i != Z7_ARRAY_SIZE(GLOBAL_TABLE(n ## _EXTRA)); i++) \
252*f6dc9357SAndroid Build Coastguard Worker       { const unsigned a = GLOBAL_TABLE(n ## _EXTRA)[i]; \
253*f6dc9357SAndroid Build Coastguard Worker         BASES_TABLE(n ## _BASES)[i] = sum; \
254*f6dc9357SAndroid Build Coastguard Worker         /* if (sum != GLOBAL_TABLE(n ## _BASES)[i]) exit(1); */ \
255*f6dc9357SAndroid Build Coastguard Worker         sum += (UInt32)1 << a; \
256*f6dc9357SAndroid Build Coastguard Worker         BASES_TABLE(n ## _EXTRA)[i] = (Byte)a; }}
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker   #define FILL_LOC_BASES_ALL \
259*f6dc9357SAndroid Build Coastguard Worker       FILL_LOC_BASES (SEQ_LL, 0) \
260*f6dc9357SAndroid Build Coastguard Worker       FILL_LOC_BASES (SEQ_ML, MATCH_LEN_MIN) \
261*f6dc9357SAndroid Build Coastguard Worker 
262*f6dc9357SAndroid Build Coastguard Worker #else
263*f6dc9357SAndroid Build Coastguard Worker   #define COPY_GLOBAL_ARR(n)  \
264*f6dc9357SAndroid Build Coastguard Worker     memcpy(BASES_TABLE(n), GLOBAL_TABLE(n), sizeof(GLOBAL_TABLE(n)));
265*f6dc9357SAndroid Build Coastguard Worker   #define FILL_LOC_BASES_ALL \
266*f6dc9357SAndroid Build Coastguard Worker     COPY_GLOBAL_ARR (SEQ_LL_EXTRA) \
267*f6dc9357SAndroid Build Coastguard Worker     COPY_GLOBAL_ARR (SEQ_ML_EXTRA) \
268*f6dc9357SAndroid Build Coastguard Worker     COPY_GLOBAL_ARR (SEQ_LL_BASES) \
269*f6dc9357SAndroid Build Coastguard Worker     COPY_GLOBAL_ARR (SEQ_ML_BASES) \
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker #endif
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker #endif
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker /// The sequence decoding baseline and number of additional bits to read/add
278*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ZSTD_DEC_USE_BASES_CALC)
279*f6dc9357SAndroid Build Coastguard Worker static const UInt32 GLOBAL_TABLE(SEQ_LL_BASES) [NUM_LL_SYMBOLS] =
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
282*f6dc9357SAndroid Build Coastguard Worker   16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
283*f6dc9357SAndroid Build Coastguard Worker   0x2000, 0x4000, 0x8000, 0x10000
284*f6dc9357SAndroid Build Coastguard Worker };
285*f6dc9357SAndroid Build Coastguard Worker #endif
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker static const Byte GLOBAL_TABLE(SEQ_LL_EXTRA) [NUM_LL_SYMBOLS] =
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12,
291*f6dc9357SAndroid Build Coastguard Worker   13, 14, 15, 16
292*f6dc9357SAndroid Build Coastguard Worker };
293*f6dc9357SAndroid Build Coastguard Worker 
294*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ZSTD_DEC_USE_BASES_CALC)
295*f6dc9357SAndroid Build Coastguard Worker static const UInt32 GLOBAL_TABLE(SEQ_ML_BASES) [NUM_ML_SYMBOLS] =
296*f6dc9357SAndroid Build Coastguard Worker {
297*f6dc9357SAndroid Build Coastguard Worker   3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
298*f6dc9357SAndroid Build Coastguard Worker   19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
299*f6dc9357SAndroid Build Coastguard Worker   35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
300*f6dc9357SAndroid Build Coastguard Worker   0x1003, 0x2003, 0x4003, 0x8003, 0x10003
301*f6dc9357SAndroid Build Coastguard Worker };
302*f6dc9357SAndroid Build Coastguard Worker #endif
303*f6dc9357SAndroid Build Coastguard Worker 
304*f6dc9357SAndroid Build Coastguard Worker static const Byte GLOBAL_TABLE(SEQ_ML_EXTRA) [NUM_ML_SYMBOLS] =
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307*f6dc9357SAndroid Build Coastguard Worker   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
308*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11,
309*f6dc9357SAndroid Build Coastguard Worker   12, 13, 14, 15, 16
310*f6dc9357SAndroid Build Coastguard Worker };
311*f6dc9357SAndroid Build Coastguard Worker 
312*f6dc9357SAndroid Build Coastguard Worker 
313*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_PRINT_TABLE
314*f6dc9357SAndroid Build Coastguard Worker 
315*f6dc9357SAndroid Build Coastguard Worker static const Int16 SEQ_LL_PREDEF_DIST [NUM_LL_SYMBOLS] =
316*f6dc9357SAndroid Build Coastguard Worker {
317*f6dc9357SAndroid Build Coastguard Worker   4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
318*f6dc9357SAndroid Build Coastguard Worker   2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
319*f6dc9357SAndroid Build Coastguard Worker  -1,-1,-1,-1
320*f6dc9357SAndroid Build Coastguard Worker };
321*f6dc9357SAndroid Build Coastguard Worker static const Int16 SEQ_OFFSET_PREDEF_DIST [NUM_OFFSET_SYMBOLS_PREDEF] =
322*f6dc9357SAndroid Build Coastguard Worker {
323*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
324*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1
325*f6dc9357SAndroid Build Coastguard Worker };
326*f6dc9357SAndroid Build Coastguard Worker static const Int16 SEQ_ML_PREDEF_DIST [NUM_ML_SYMBOLS] =
327*f6dc9357SAndroid Build Coastguard Worker {
328*f6dc9357SAndroid Build Coastguard Worker   1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
329*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
330*f6dc9357SAndroid Build Coastguard Worker   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
331*f6dc9357SAndroid Build Coastguard Worker  -1,-1,-1,-1,-1
332*f6dc9357SAndroid Build Coastguard Worker };
333*f6dc9357SAndroid Build Coastguard Worker 
334*f6dc9357SAndroid Build Coastguard Worker #endif
335*f6dc9357SAndroid Build Coastguard Worker 
336*f6dc9357SAndroid Build Coastguard Worker // typedef int FastInt;
337*f6dc9357SAndroid Build Coastguard Worker // typedef Int32 FastInt32;
338*f6dc9357SAndroid Build Coastguard Worker typedef unsigned FastInt;
339*f6dc9357SAndroid Build Coastguard Worker typedef UInt32 FastInt32;
340*f6dc9357SAndroid Build Coastguard Worker typedef FastInt32 CFseRecord;
341*f6dc9357SAndroid Build Coastguard Worker 
342*f6dc9357SAndroid Build Coastguard Worker 
343*f6dc9357SAndroid Build Coastguard Worker #define FSE_REC_LEN_OFFSET    8
344*f6dc9357SAndroid Build Coastguard Worker #define FSE_REC_STATE_OFFSET  16
345*f6dc9357SAndroid Build Coastguard Worker #define GET_FSE_REC_SYM(st)   ((Byte)(st))
346*f6dc9357SAndroid Build Coastguard Worker #define GET_FSE_REC_LEN(st)   ((Byte)((st) >> FSE_REC_LEN_OFFSET))
347*f6dc9357SAndroid Build Coastguard Worker #define GET_FSE_REC_STATE(st) ((st) >> FSE_REC_STATE_OFFSET)
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker // #define FSE_REC_SYM_MASK      (0xff)
350*f6dc9357SAndroid Build Coastguard Worker // #define GET_FSE_REC_SYM(st)   (st & FSE_REC_SYM_MASK)
351*f6dc9357SAndroid Build Coastguard Worker 
352*f6dc9357SAndroid Build Coastguard Worker #define W_BASE(state, len, sym) \
353*f6dc9357SAndroid Build Coastguard Worker     (((UInt32)state << (4 + FSE_REC_STATE_OFFSET)) + \
354*f6dc9357SAndroid Build Coastguard Worker     (len << FSE_REC_LEN_OFFSET) + (sym))
355*f6dc9357SAndroid Build Coastguard Worker #define W(state, len, sym)  W_BASE(state, len, sym)
356*f6dc9357SAndroid Build Coastguard Worker static const CFseRecord k_PredefRecords_LL[1 << 6] = {
357*f6dc9357SAndroid Build Coastguard Worker W(0,4, 0),W(1,4, 0),W(2,5, 1),W(0,5, 3),W(0,5, 4),W(0,5, 6),W(0,5, 7),W(0,5, 9),
358*f6dc9357SAndroid Build Coastguard Worker W(0,5,10),W(0,5,12),W(0,6,14),W(0,5,16),W(0,5,18),W(0,5,19),W(0,5,21),W(0,5,22),
359*f6dc9357SAndroid Build Coastguard Worker W(0,5,24),W(2,5,25),W(0,5,26),W(0,6,27),W(0,6,29),W(0,6,31),W(2,4, 0),W(0,4, 1),
360*f6dc9357SAndroid Build Coastguard Worker W(0,5, 2),W(2,5, 4),W(0,5, 5),W(2,5, 7),W(0,5, 8),W(2,5,10),W(0,5,11),W(0,6,13),
361*f6dc9357SAndroid Build Coastguard Worker W(2,5,16),W(0,5,17),W(2,5,19),W(0,5,20),W(2,5,22),W(0,5,23),W(0,4,25),W(1,4,25),
362*f6dc9357SAndroid Build Coastguard Worker W(2,5,26),W(0,6,28),W(0,6,30),W(3,4, 0),W(1,4, 1),W(2,5, 2),W(2,5, 3),W(2,5, 5),
363*f6dc9357SAndroid Build Coastguard Worker W(2,5, 6),W(2,5, 8),W(2,5, 9),W(2,5,11),W(2,5,12),W(0,6,15),W(2,5,17),W(2,5,18),
364*f6dc9357SAndroid Build Coastguard Worker W(2,5,20),W(2,5,21),W(2,5,23),W(2,5,24),W(0,6,35),W(0,6,34),W(0,6,33),W(0,6,32)
365*f6dc9357SAndroid Build Coastguard Worker };
366*f6dc9357SAndroid Build Coastguard Worker static const CFseRecord k_PredefRecords_OF[1 << 5] = {
367*f6dc9357SAndroid Build Coastguard Worker W(0,5, 0),W(0,4, 6),W(0,5, 9),W(0,5,15),W(0,5,21),W(0,5, 3),W(0,4, 7),W(0,5,12),
368*f6dc9357SAndroid Build Coastguard Worker W(0,5,18),W(0,5,23),W(0,5, 5),W(0,4, 8),W(0,5,14),W(0,5,20),W(0,5, 2),W(1,4, 7),
369*f6dc9357SAndroid Build Coastguard Worker W(0,5,11),W(0,5,17),W(0,5,22),W(0,5, 4),W(1,4, 8),W(0,5,13),W(0,5,19),W(0,5, 1),
370*f6dc9357SAndroid Build Coastguard Worker W(1,4, 6),W(0,5,10),W(0,5,16),W(0,5,28),W(0,5,27),W(0,5,26),W(0,5,25),W(0,5,24)
371*f6dc9357SAndroid Build Coastguard Worker };
372*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
373*f6dc9357SAndroid Build Coastguard Worker #undef W
374*f6dc9357SAndroid Build Coastguard Worker #define W(state, len, sym)  W_BASE(state, len, (sym + MATCH_LEN_MIN))
375*f6dc9357SAndroid Build Coastguard Worker #endif
376*f6dc9357SAndroid Build Coastguard Worker static const CFseRecord k_PredefRecords_ML[1 << 6] = {
377*f6dc9357SAndroid Build Coastguard Worker W(0,6, 0),W(0,4, 1),W(2,5, 2),W(0,5, 3),W(0,5, 5),W(0,5, 6),W(0,5, 8),W(0,6,10),
378*f6dc9357SAndroid Build Coastguard Worker W(0,6,13),W(0,6,16),W(0,6,19),W(0,6,22),W(0,6,25),W(0,6,28),W(0,6,31),W(0,6,33),
379*f6dc9357SAndroid Build Coastguard Worker W(0,6,35),W(0,6,37),W(0,6,39),W(0,6,41),W(0,6,43),W(0,6,45),W(1,4, 1),W(0,4, 2),
380*f6dc9357SAndroid Build Coastguard Worker W(2,5, 3),W(0,5, 4),W(2,5, 6),W(0,5, 7),W(0,6, 9),W(0,6,12),W(0,6,15),W(0,6,18),
381*f6dc9357SAndroid Build Coastguard Worker W(0,6,21),W(0,6,24),W(0,6,27),W(0,6,30),W(0,6,32),W(0,6,34),W(0,6,36),W(0,6,38),
382*f6dc9357SAndroid Build Coastguard Worker W(0,6,40),W(0,6,42),W(0,6,44),W(2,4, 1),W(3,4, 1),W(1,4, 2),W(2,5, 4),W(2,5, 5),
383*f6dc9357SAndroid Build Coastguard Worker W(2,5, 7),W(2,5, 8),W(0,6,11),W(0,6,14),W(0,6,17),W(0,6,20),W(0,6,23),W(0,6,26),
384*f6dc9357SAndroid Build Coastguard Worker W(0,6,29),W(0,6,52),W(0,6,51),W(0,6,50),W(0,6,49),W(0,6,48),W(0,6,47),W(0,6,46)
385*f6dc9357SAndroid Build Coastguard Worker };
386*f6dc9357SAndroid Build Coastguard Worker 
387*f6dc9357SAndroid Build Coastguard Worker 
388*f6dc9357SAndroid Build Coastguard Worker // sum of freqs[] must be correct
389*f6dc9357SAndroid Build Coastguard Worker // (numSyms != 0)
390*f6dc9357SAndroid Build Coastguard Worker // (accuracy >= 5)
391*f6dc9357SAndroid Build Coastguard Worker static
392*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
393*f6dc9357SAndroid Build Coastguard Worker // Z7_FORCE_INLINE
FSE_Generate(CFseRecord * table,const Int16 * const freqs,const size_t numSyms,const unsigned accuracy,UInt32 delta)394*f6dc9357SAndroid Build Coastguard Worker void FSE_Generate(CFseRecord *table,
395*f6dc9357SAndroid Build Coastguard Worker     const Int16 *const freqs, const size_t numSyms,
396*f6dc9357SAndroid Build Coastguard Worker     const unsigned accuracy, UInt32 delta)
397*f6dc9357SAndroid Build Coastguard Worker {
398*f6dc9357SAndroid Build Coastguard Worker   size_t size = (size_t)1 << accuracy;
399*f6dc9357SAndroid Build Coastguard Worker   // max value in states[x] is ((1 << accuracy) * 2)
400*f6dc9357SAndroid Build Coastguard Worker   UInt16 states[FSE_NUM_SYMBOLS_MAX];
401*f6dc9357SAndroid Build Coastguard Worker   {
402*f6dc9357SAndroid Build Coastguard Worker     /* Symbols with "less than 1" probability get a single cell,
403*f6dc9357SAndroid Build Coastguard Worker        starting from the end of the table.
404*f6dc9357SAndroid Build Coastguard Worker        These symbols define a full state reset, reading (accuracy) bits. */
405*f6dc9357SAndroid Build Coastguard Worker     size_t threshold = size;
406*f6dc9357SAndroid Build Coastguard Worker     {
407*f6dc9357SAndroid Build Coastguard Worker       size_t s = 0;
408*f6dc9357SAndroid Build Coastguard Worker       do
409*f6dc9357SAndroid Build Coastguard Worker         if (freqs[s] == -1)
410*f6dc9357SAndroid Build Coastguard Worker         {
411*f6dc9357SAndroid Build Coastguard Worker           table[--threshold] = (CFseRecord)s;
412*f6dc9357SAndroid Build Coastguard Worker           states[s] = 1;
413*f6dc9357SAndroid Build Coastguard Worker         }
414*f6dc9357SAndroid Build Coastguard Worker       while (++s != numSyms);
415*f6dc9357SAndroid Build Coastguard Worker     }
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker     #ifdef SHOW_STAT
418*f6dc9357SAndroid Build Coastguard Worker     if (threshold == size)
419*f6dc9357SAndroid Build Coastguard Worker     {
420*f6dc9357SAndroid Build Coastguard Worker       STAT_INC(g_Num_Threshold_0)
421*f6dc9357SAndroid Build Coastguard Worker       STAT_UPDATE(g_Num_Threshold_0sum += (unsigned)size;)
422*f6dc9357SAndroid Build Coastguard Worker     }
423*f6dc9357SAndroid Build Coastguard Worker     else
424*f6dc9357SAndroid Build Coastguard Worker     {
425*f6dc9357SAndroid Build Coastguard Worker       STAT_INC(g_Num_Threshold_1)
426*f6dc9357SAndroid Build Coastguard Worker       STAT_UPDATE(g_Num_Threshold_1sum += (unsigned)size;)
427*f6dc9357SAndroid Build Coastguard Worker     }
428*f6dc9357SAndroid Build Coastguard Worker     #endif
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker     // { unsigned uuu; for (uuu = 0; uuu < 400; uuu++)
431*f6dc9357SAndroid Build Coastguard Worker     {
432*f6dc9357SAndroid Build Coastguard Worker       // Each (symbol) gets freqs[symbol] cells.
433*f6dc9357SAndroid Build Coastguard Worker       // Cell allocation is spread, not linear.
434*f6dc9357SAndroid Build Coastguard Worker       const size_t step = (size >> 1) + (size >> 3) + 3;
435*f6dc9357SAndroid Build Coastguard Worker       size_t pos = 0;
436*f6dc9357SAndroid Build Coastguard Worker       // const unsigned mask = size - 1;
437*f6dc9357SAndroid Build Coastguard Worker       /*
438*f6dc9357SAndroid Build Coastguard Worker       if (threshold == size)
439*f6dc9357SAndroid Build Coastguard Worker       {
440*f6dc9357SAndroid Build Coastguard Worker         size_t s = 0;
441*f6dc9357SAndroid Build Coastguard Worker         size--;
442*f6dc9357SAndroid Build Coastguard Worker         do
443*f6dc9357SAndroid Build Coastguard Worker         {
444*f6dc9357SAndroid Build Coastguard Worker           int freq = freqs[s];
445*f6dc9357SAndroid Build Coastguard Worker           if (freq <= 0)
446*f6dc9357SAndroid Build Coastguard Worker             continue;
447*f6dc9357SAndroid Build Coastguard Worker           states[s] = (UInt16)freq;
448*f6dc9357SAndroid Build Coastguard Worker           do
449*f6dc9357SAndroid Build Coastguard Worker           {
450*f6dc9357SAndroid Build Coastguard Worker             table[pos] (CFseRecord)s;
451*f6dc9357SAndroid Build Coastguard Worker             pos = (pos + step) & size; // & mask;
452*f6dc9357SAndroid Build Coastguard Worker           }
453*f6dc9357SAndroid Build Coastguard Worker           while (--freq);
454*f6dc9357SAndroid Build Coastguard Worker         }
455*f6dc9357SAndroid Build Coastguard Worker         while (++s != numSyms);
456*f6dc9357SAndroid Build Coastguard Worker       }
457*f6dc9357SAndroid Build Coastguard Worker       else
458*f6dc9357SAndroid Build Coastguard Worker       */
459*f6dc9357SAndroid Build Coastguard Worker       {
460*f6dc9357SAndroid Build Coastguard Worker         size_t s = 0;
461*f6dc9357SAndroid Build Coastguard Worker         size--;
462*f6dc9357SAndroid Build Coastguard Worker         do
463*f6dc9357SAndroid Build Coastguard Worker         {
464*f6dc9357SAndroid Build Coastguard Worker           int freq = freqs[s];
465*f6dc9357SAndroid Build Coastguard Worker           if (freq <= 0)
466*f6dc9357SAndroid Build Coastguard Worker             continue;
467*f6dc9357SAndroid Build Coastguard Worker           states[s] = (UInt16)freq;
468*f6dc9357SAndroid Build Coastguard Worker           do
469*f6dc9357SAndroid Build Coastguard Worker           {
470*f6dc9357SAndroid Build Coastguard Worker             table[pos] = (CFseRecord)s;
471*f6dc9357SAndroid Build Coastguard Worker             // we skip position, if it's already occupied by a "less than 1" probability symbol.
472*f6dc9357SAndroid Build Coastguard Worker             // (step) is coprime to table size, so the cycle will visit each position exactly once
473*f6dc9357SAndroid Build Coastguard Worker             do
474*f6dc9357SAndroid Build Coastguard Worker               pos = (pos + step) & size; // & mask;
475*f6dc9357SAndroid Build Coastguard Worker             while (pos >= threshold);
476*f6dc9357SAndroid Build Coastguard Worker           }
477*f6dc9357SAndroid Build Coastguard Worker           while (--freq);
478*f6dc9357SAndroid Build Coastguard Worker         }
479*f6dc9357SAndroid Build Coastguard Worker         while (++s != numSyms);
480*f6dc9357SAndroid Build Coastguard Worker       }
481*f6dc9357SAndroid Build Coastguard Worker       size++;
482*f6dc9357SAndroid Build Coastguard Worker       // (pos != 0) is unexpected case that means that freqs[] are not correct.
483*f6dc9357SAndroid Build Coastguard Worker       // so it's some failure in code (for example, incorrect predefined freq[] table)
484*f6dc9357SAndroid Build Coastguard Worker       // if (pos != 0) return SZ_ERROR_FAIL;
485*f6dc9357SAndroid Build Coastguard Worker     }
486*f6dc9357SAndroid Build Coastguard Worker     // }
487*f6dc9357SAndroid Build Coastguard Worker   }
488*f6dc9357SAndroid Build Coastguard Worker   {
489*f6dc9357SAndroid Build Coastguard Worker     const CFseRecord * const limit = table + size;
490*f6dc9357SAndroid Build Coastguard Worker     delta = ((UInt32)size << FSE_REC_STATE_OFFSET) - delta;
491*f6dc9357SAndroid Build Coastguard Worker     /* State increases by symbol over time, decreasing number of bits.
492*f6dc9357SAndroid Build Coastguard Worker        Baseline increases until the bit threshold is passed, at which point it resets to 0 */
493*f6dc9357SAndroid Build Coastguard Worker     do
494*f6dc9357SAndroid Build Coastguard Worker     {
495*f6dc9357SAndroid Build Coastguard Worker       #define TABLE_ITER(a) \
496*f6dc9357SAndroid Build Coastguard Worker       { \
497*f6dc9357SAndroid Build Coastguard Worker         const FastInt sym = (FastInt)table[a]; \
498*f6dc9357SAndroid Build Coastguard Worker         const unsigned nextState = states[sym]; \
499*f6dc9357SAndroid Build Coastguard Worker         unsigned nb; \
500*f6dc9357SAndroid Build Coastguard Worker         states[sym] = (UInt16)(nextState + 1); \
501*f6dc9357SAndroid Build Coastguard Worker         nb = accuracy - GetHighestSetBit_32_nonzero_small(nextState); \
502*f6dc9357SAndroid Build Coastguard Worker         table[a] = (CFseRecord)(sym - delta \
503*f6dc9357SAndroid Build Coastguard Worker             + ((UInt32)nb << FSE_REC_LEN_OFFSET) \
504*f6dc9357SAndroid Build Coastguard Worker             + ((UInt32)nextState << FSE_REC_STATE_OFFSET << nb)); \
505*f6dc9357SAndroid Build Coastguard Worker       }
506*f6dc9357SAndroid Build Coastguard Worker       TABLE_ITER(0)
507*f6dc9357SAndroid Build Coastguard Worker       TABLE_ITER(1)
508*f6dc9357SAndroid Build Coastguard Worker       table += 2;
509*f6dc9357SAndroid Build Coastguard Worker     }
510*f6dc9357SAndroid Build Coastguard Worker     while (table != limit);
511*f6dc9357SAndroid Build Coastguard Worker   }
512*f6dc9357SAndroid Build Coastguard Worker }
513*f6dc9357SAndroid Build Coastguard Worker 
514*f6dc9357SAndroid Build Coastguard Worker 
515*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_PRINT_TABLE
516*f6dc9357SAndroid Build Coastguard Worker 
Print_Predef(unsigned predefAccuracy,const unsigned numSymsPredef,const Int16 * const predefFreqs,const CFseRecord * checkTable)517*f6dc9357SAndroid Build Coastguard Worker static void Print_Predef(unsigned predefAccuracy,
518*f6dc9357SAndroid Build Coastguard Worker     const unsigned numSymsPredef,
519*f6dc9357SAndroid Build Coastguard Worker     const Int16 * const predefFreqs,
520*f6dc9357SAndroid Build Coastguard Worker     const CFseRecord *checkTable)
521*f6dc9357SAndroid Build Coastguard Worker {
522*f6dc9357SAndroid Build Coastguard Worker   CFseRecord table[1 << 6];
523*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
524*f6dc9357SAndroid Build Coastguard Worker   FSE_Generate(table, predefFreqs, numSymsPredef, predefAccuracy,
525*f6dc9357SAndroid Build Coastguard Worker         #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
526*f6dc9357SAndroid Build Coastguard Worker           numSymsPredef == NUM_ML_SYMBOLS ? MATCH_LEN_MIN :
527*f6dc9357SAndroid Build Coastguard Worker         #endif
528*f6dc9357SAndroid Build Coastguard Worker           0
529*f6dc9357SAndroid Build Coastguard Worker     );
530*f6dc9357SAndroid Build Coastguard Worker   if (memcmp(table, checkTable, sizeof(UInt32) << predefAccuracy) != 0)
531*f6dc9357SAndroid Build Coastguard Worker     exit(1);
532*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < (1u << predefAccuracy); i++)
533*f6dc9357SAndroid Build Coastguard Worker   {
534*f6dc9357SAndroid Build Coastguard Worker     const UInt32 v = table[i];
535*f6dc9357SAndroid Build Coastguard Worker     const unsigned state = (unsigned)(GET_FSE_REC_STATE(v));
536*f6dc9357SAndroid Build Coastguard Worker     if (state & 0xf)
537*f6dc9357SAndroid Build Coastguard Worker       exit(1);
538*f6dc9357SAndroid Build Coastguard Worker     if (i != 0)
539*f6dc9357SAndroid Build Coastguard Worker     {
540*f6dc9357SAndroid Build Coastguard Worker       printf(",");
541*f6dc9357SAndroid Build Coastguard Worker       if (i % 8 == 0)
542*f6dc9357SAndroid Build Coastguard Worker         printf("\n");
543*f6dc9357SAndroid Build Coastguard Worker     }
544*f6dc9357SAndroid Build Coastguard Worker     printf("W(%d,%d,%2d)",
545*f6dc9357SAndroid Build Coastguard Worker         (unsigned)(state >> 4),
546*f6dc9357SAndroid Build Coastguard Worker         (unsigned)((v >> FSE_REC_LEN_OFFSET) & 0xff),
547*f6dc9357SAndroid Build Coastguard Worker         (unsigned)GET_FSE_REC_SYM(v));
548*f6dc9357SAndroid Build Coastguard Worker   }
549*f6dc9357SAndroid Build Coastguard Worker   printf("\n\n");
550*f6dc9357SAndroid Build Coastguard Worker }
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker #endif
553*f6dc9357SAndroid Build Coastguard Worker 
554*f6dc9357SAndroid Build Coastguard Worker 
555*f6dc9357SAndroid Build Coastguard Worker #define GET16(dest, p)  { const Byte *ptr = p;  dest = GetUi16(ptr); }
556*f6dc9357SAndroid Build Coastguard Worker #define GET32(dest, p)  { const Byte *ptr = p;  dest = GetUi32(ptr); }
557*f6dc9357SAndroid Build Coastguard Worker 
558*f6dc9357SAndroid Build Coastguard Worker // (1 <= numBits <= 9)
559*f6dc9357SAndroid Build Coastguard Worker #define FORWARD_READ_BITS(destVal, numBits, mask) \
560*f6dc9357SAndroid Build Coastguard Worker   { const CBitCtr_signed bos3 = (bitOffset) >> 3; \
561*f6dc9357SAndroid Build Coastguard Worker     if (bos3 >= 0) return SZ_ERROR_DATA; \
562*f6dc9357SAndroid Build Coastguard Worker     GET16(destVal, src + bos3) \
563*f6dc9357SAndroid Build Coastguard Worker     destVal >>= (bitOffset) & 7; \
564*f6dc9357SAndroid Build Coastguard Worker     bitOffset += (CBitCtr_signed)(numBits); \
565*f6dc9357SAndroid Build Coastguard Worker     mask = (1u << (numBits)) - 1; \
566*f6dc9357SAndroid Build Coastguard Worker     destVal &= mask; \
567*f6dc9357SAndroid Build Coastguard Worker   }
568*f6dc9357SAndroid Build Coastguard Worker 
569*f6dc9357SAndroid Build Coastguard Worker #define FORWARD_READ_1BIT(destVal) \
570*f6dc9357SAndroid Build Coastguard Worker   { const CBitCtr_signed bos3 = (bitOffset) >> 3; \
571*f6dc9357SAndroid Build Coastguard Worker     if (bos3 >= 0) return SZ_ERROR_DATA; \
572*f6dc9357SAndroid Build Coastguard Worker     destVal = *(src + bos3); \
573*f6dc9357SAndroid Build Coastguard Worker     destVal >>= (bitOffset) & 7; \
574*f6dc9357SAndroid Build Coastguard Worker     (bitOffset)++; \
575*f6dc9357SAndroid Build Coastguard Worker     destVal &= 1; \
576*f6dc9357SAndroid Build Coastguard Worker   }
577*f6dc9357SAndroid Build Coastguard Worker 
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker // in: (accuracyMax <= 9)
580*f6dc9357SAndroid Build Coastguard Worker // at least 2 bytes will be processed from (in) stream.
581*f6dc9357SAndroid Build Coastguard Worker // at return: (in->len > 0)
582*f6dc9357SAndroid Build Coastguard Worker static
583*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
FSE_DecodeHeader(CFseRecord * const table,CInBufPair * const in,const unsigned accuracyMax,Byte * const accuracyRes,unsigned numSymbolsMax)584*f6dc9357SAndroid Build Coastguard Worker SRes FSE_DecodeHeader(CFseRecord *const table,
585*f6dc9357SAndroid Build Coastguard Worker     CInBufPair *const in,
586*f6dc9357SAndroid Build Coastguard Worker     const unsigned accuracyMax,
587*f6dc9357SAndroid Build Coastguard Worker     Byte *const accuracyRes,
588*f6dc9357SAndroid Build Coastguard Worker     unsigned numSymbolsMax)
589*f6dc9357SAndroid Build Coastguard Worker {
590*f6dc9357SAndroid Build Coastguard Worker   unsigned accuracy;
591*f6dc9357SAndroid Build Coastguard Worker   unsigned remain1;
592*f6dc9357SAndroid Build Coastguard Worker   unsigned syms;
593*f6dc9357SAndroid Build Coastguard Worker   Int16 freqs[FSE_NUM_SYMBOLS_MAX + 3]; // +3 for overwrite (repeat)
594*f6dc9357SAndroid Build Coastguard Worker   const Byte *src = in->ptr;
595*f6dc9357SAndroid Build Coastguard Worker   CBitCtr_signed bitOffset = (CBitCtr_signed)in->len - 1;
596*f6dc9357SAndroid Build Coastguard Worker   if (bitOffset <= 0)
597*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
598*f6dc9357SAndroid Build Coastguard Worker   accuracy = *src & 0xf;
599*f6dc9357SAndroid Build Coastguard Worker   accuracy += 5;
600*f6dc9357SAndroid Build Coastguard Worker   if (accuracy > accuracyMax)
601*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
602*f6dc9357SAndroid Build Coastguard Worker   *accuracyRes = (Byte)accuracy;
603*f6dc9357SAndroid Build Coastguard Worker   remain1 = (1u << accuracy) + 1; // (it's remain_freqs_sum + 1)
604*f6dc9357SAndroid Build Coastguard Worker   syms = 0;
605*f6dc9357SAndroid Build Coastguard Worker   src += bitOffset;  // src points to last byte
606*f6dc9357SAndroid Build Coastguard Worker   bitOffset = 4 - (bitOffset << 3);
607*f6dc9357SAndroid Build Coastguard Worker 
608*f6dc9357SAndroid Build Coastguard Worker   for (;;)
609*f6dc9357SAndroid Build Coastguard Worker   {
610*f6dc9357SAndroid Build Coastguard Worker     // (2 <= remain1)
611*f6dc9357SAndroid Build Coastguard Worker     const unsigned bits = GetHighestSetBit_32_nonzero_small((unsigned)remain1);
612*f6dc9357SAndroid Build Coastguard Worker     // (1 <= bits <= accuracy)
613*f6dc9357SAndroid Build Coastguard Worker     unsigned val; // it must be unsigned or int
614*f6dc9357SAndroid Build Coastguard Worker     unsigned mask;
615*f6dc9357SAndroid Build Coastguard Worker     FORWARD_READ_BITS(val, bits, mask)
616*f6dc9357SAndroid Build Coastguard Worker     {
617*f6dc9357SAndroid Build Coastguard Worker       const unsigned val2 = remain1 + val - mask;
618*f6dc9357SAndroid Build Coastguard Worker       if (val2 > mask)
619*f6dc9357SAndroid Build Coastguard Worker       {
620*f6dc9357SAndroid Build Coastguard Worker         unsigned bit;
621*f6dc9357SAndroid Build Coastguard Worker         FORWARD_READ_1BIT(bit)
622*f6dc9357SAndroid Build Coastguard Worker         if (bit)
623*f6dc9357SAndroid Build Coastguard Worker           val = val2;
624*f6dc9357SAndroid Build Coastguard Worker       }
625*f6dc9357SAndroid Build Coastguard Worker     }
626*f6dc9357SAndroid Build Coastguard Worker     {
627*f6dc9357SAndroid Build Coastguard Worker       // (remain1 >= 2)
628*f6dc9357SAndroid Build Coastguard Worker       // (0 <= (int)val <= remain1)
629*f6dc9357SAndroid Build Coastguard Worker       val = (unsigned)((int)val - 1);
630*f6dc9357SAndroid Build Coastguard Worker       // val now is "probability" of symbol
631*f6dc9357SAndroid Build Coastguard Worker       // (probability == -1) means "less than 1" frequency.
632*f6dc9357SAndroid Build Coastguard Worker       // (-1 <= (int)val <= remain1 - 1)
633*f6dc9357SAndroid Build Coastguard Worker       freqs[syms++] = (Int16)(int)val;
634*f6dc9357SAndroid Build Coastguard Worker       if (val != 0)
635*f6dc9357SAndroid Build Coastguard Worker       {
636*f6dc9357SAndroid Build Coastguard Worker         remain1 -= (int)val < 0 ? 1u : (unsigned)val;
637*f6dc9357SAndroid Build Coastguard Worker         // remain1 -= val;
638*f6dc9357SAndroid Build Coastguard Worker         // val >>= (sizeof(val) * 8 - 2);
639*f6dc9357SAndroid Build Coastguard Worker         // remain1 -= val & 2;
640*f6dc9357SAndroid Build Coastguard Worker         // freqs[syms++] = (Int16)(int)val;
641*f6dc9357SAndroid Build Coastguard Worker         // syms++;
642*f6dc9357SAndroid Build Coastguard Worker         if (remain1 == 1)
643*f6dc9357SAndroid Build Coastguard Worker           break;
644*f6dc9357SAndroid Build Coastguard Worker         if (syms >= FSE_NUM_SYMBOLS_MAX)
645*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
646*f6dc9357SAndroid Build Coastguard Worker       }
647*f6dc9357SAndroid Build Coastguard Worker       else // if (val == 0)
648*f6dc9357SAndroid Build Coastguard Worker       {
649*f6dc9357SAndroid Build Coastguard Worker         // freqs[syms++] = 0;
650*f6dc9357SAndroid Build Coastguard Worker         // syms++;
651*f6dc9357SAndroid Build Coastguard Worker         for (;;)
652*f6dc9357SAndroid Build Coastguard Worker         {
653*f6dc9357SAndroid Build Coastguard Worker           unsigned repeat;
654*f6dc9357SAndroid Build Coastguard Worker           FORWARD_READ_BITS(repeat, 2, mask)
655*f6dc9357SAndroid Build Coastguard Worker           freqs[syms    ] = 0;
656*f6dc9357SAndroid Build Coastguard Worker           freqs[syms + 1] = 0;
657*f6dc9357SAndroid Build Coastguard Worker           freqs[syms + 2] = 0;
658*f6dc9357SAndroid Build Coastguard Worker           syms += repeat;
659*f6dc9357SAndroid Build Coastguard Worker           if (syms >= FSE_NUM_SYMBOLS_MAX)
660*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_DATA;
661*f6dc9357SAndroid Build Coastguard Worker           if (repeat != 3)
662*f6dc9357SAndroid Build Coastguard Worker             break;
663*f6dc9357SAndroid Build Coastguard Worker         }
664*f6dc9357SAndroid Build Coastguard Worker       }
665*f6dc9357SAndroid Build Coastguard Worker     }
666*f6dc9357SAndroid Build Coastguard Worker   }
667*f6dc9357SAndroid Build Coastguard Worker 
668*f6dc9357SAndroid Build Coastguard Worker   if (syms > numSymbolsMax)
669*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
670*f6dc9357SAndroid Build Coastguard Worker   bitOffset += 7;
671*f6dc9357SAndroid Build Coastguard Worker   bitOffset >>= 3;
672*f6dc9357SAndroid Build Coastguard Worker   if (bitOffset > 0)
673*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
674*f6dc9357SAndroid Build Coastguard Worker   in->ptr = src + bitOffset;
675*f6dc9357SAndroid Build Coastguard Worker   in->len = (size_t)(1 - bitOffset);
676*f6dc9357SAndroid Build Coastguard Worker   {
677*f6dc9357SAndroid Build Coastguard Worker     // unsigned uuu; for (uuu = 0; uuu < 50; uuu++)
678*f6dc9357SAndroid Build Coastguard Worker     FSE_Generate(table, freqs, syms, accuracy,
679*f6dc9357SAndroid Build Coastguard Worker         #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
680*f6dc9357SAndroid Build Coastguard Worker           numSymbolsMax == NUM_ML_SYMBOLS ? MATCH_LEN_MIN :
681*f6dc9357SAndroid Build Coastguard Worker         #endif
682*f6dc9357SAndroid Build Coastguard Worker           0
683*f6dc9357SAndroid Build Coastguard Worker         );
684*f6dc9357SAndroid Build Coastguard Worker   }
685*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
686*f6dc9357SAndroid Build Coastguard Worker }
687*f6dc9357SAndroid Build Coastguard Worker 
688*f6dc9357SAndroid Build Coastguard Worker 
689*f6dc9357SAndroid Build Coastguard Worker // ---------- HUFFMAN ----------
690*f6dc9357SAndroid Build Coastguard Worker 
691*f6dc9357SAndroid Build Coastguard Worker #define HUF_MAX_BITS    12
692*f6dc9357SAndroid Build Coastguard Worker #define HUF_MAX_SYMBS   256
693*f6dc9357SAndroid Build Coastguard Worker #define HUF_DUMMY_SIZE  (128 + 8 * 2)  // it must multiple of 8
694*f6dc9357SAndroid Build Coastguard Worker // #define HUF_DUMMY_SIZE 0
695*f6dc9357SAndroid Build Coastguard Worker #define HUF_TABLE_SIZE  ((2 << HUF_MAX_BITS) + HUF_DUMMY_SIZE)
696*f6dc9357SAndroid Build Coastguard Worker #define HUF_GET_SYMBOLS(table)  ((table) + (1 << HUF_MAX_BITS) + HUF_DUMMY_SIZE)
697*f6dc9357SAndroid Build Coastguard Worker // #define HUF_GET_LENS(table)  (table)
698*f6dc9357SAndroid Build Coastguard Worker 
699*f6dc9357SAndroid Build Coastguard Worker typedef struct
700*f6dc9357SAndroid Build Coastguard Worker {
701*f6dc9357SAndroid Build Coastguard Worker   // Byte table[HUF_TABLE_SIZE];
702*f6dc9357SAndroid Build Coastguard Worker   UInt64 table64[HUF_TABLE_SIZE / sizeof(UInt64)];
703*f6dc9357SAndroid Build Coastguard Worker }
704*f6dc9357SAndroid Build Coastguard Worker CZstdDecHufTable;
705*f6dc9357SAndroid Build Coastguard Worker 
706*f6dc9357SAndroid Build Coastguard Worker /*
707*f6dc9357SAndroid Build Coastguard Worker Input:
708*f6dc9357SAndroid Build Coastguard Worker   numSyms != 0
709*f6dc9357SAndroid Build Coastguard Worker   (bits) array size must be aligned for 2
710*f6dc9357SAndroid Build Coastguard Worker   if (numSyms & 1), then bits[numSyms] == 0,
711*f6dc9357SAndroid Build Coastguard Worker   Huffman tree must be correct before Huf_Build() call:
712*f6dc9357SAndroid Build Coastguard Worker     (sum (1/2^bits[i]) == 1).
713*f6dc9357SAndroid Build Coastguard Worker     && (bits[i] <= HUF_MAX_BITS)
714*f6dc9357SAndroid Build Coastguard Worker */
715*f6dc9357SAndroid Build Coastguard Worker static
716*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
Huf_Build(Byte * const table,const Byte * bits,const unsigned numSyms)717*f6dc9357SAndroid Build Coastguard Worker void Huf_Build(Byte * const table,
718*f6dc9357SAndroid Build Coastguard Worker     const Byte *bits, const unsigned numSyms)
719*f6dc9357SAndroid Build Coastguard Worker {
720*f6dc9357SAndroid Build Coastguard Worker   unsigned counts0[HUF_MAX_BITS + 1];
721*f6dc9357SAndroid Build Coastguard Worker   unsigned counts1[HUF_MAX_BITS + 1];
722*f6dc9357SAndroid Build Coastguard Worker   const Byte * const bitsEnd = bits + numSyms;
723*f6dc9357SAndroid Build Coastguard Worker   // /*
724*f6dc9357SAndroid Build Coastguard Worker   {
725*f6dc9357SAndroid Build Coastguard Worker     unsigned t;
726*f6dc9357SAndroid Build Coastguard Worker     for (t = 0; t < Z7_ARRAY_SIZE(counts0); t++) counts0[t] = 0;
727*f6dc9357SAndroid Build Coastguard Worker     for (t = 0; t < Z7_ARRAY_SIZE(counts1); t++) counts1[t] = 0;
728*f6dc9357SAndroid Build Coastguard Worker   }
729*f6dc9357SAndroid Build Coastguard Worker   // */
730*f6dc9357SAndroid Build Coastguard Worker   // memset(counts0, 0, sizeof(counts0));
731*f6dc9357SAndroid Build Coastguard Worker   // memset(counts1, 0, sizeof(counts1));
732*f6dc9357SAndroid Build Coastguard Worker   {
733*f6dc9357SAndroid Build Coastguard Worker     const Byte *bits2 = bits;
734*f6dc9357SAndroid Build Coastguard Worker     // we access additional bits[symbol] if (numSyms & 1)
735*f6dc9357SAndroid Build Coastguard Worker     do
736*f6dc9357SAndroid Build Coastguard Worker     {
737*f6dc9357SAndroid Build Coastguard Worker       counts0[bits2[0]]++;
738*f6dc9357SAndroid Build Coastguard Worker       counts1[bits2[1]]++;
739*f6dc9357SAndroid Build Coastguard Worker     }
740*f6dc9357SAndroid Build Coastguard Worker     while ((bits2 += 2) < bitsEnd);
741*f6dc9357SAndroid Build Coastguard Worker   }
742*f6dc9357SAndroid Build Coastguard Worker   {
743*f6dc9357SAndroid Build Coastguard Worker     unsigned r = 0;
744*f6dc9357SAndroid Build Coastguard Worker     unsigned i = HUF_MAX_BITS;
745*f6dc9357SAndroid Build Coastguard Worker     // Byte *lens = HUF_GET_LENS(symbols);
746*f6dc9357SAndroid Build Coastguard Worker     do
747*f6dc9357SAndroid Build Coastguard Worker     {
748*f6dc9357SAndroid Build Coastguard Worker       const unsigned num = (counts0[i] + counts1[i]) << (HUF_MAX_BITS - i);
749*f6dc9357SAndroid Build Coastguard Worker       counts0[i] = r;
750*f6dc9357SAndroid Build Coastguard Worker       if (num)
751*f6dc9357SAndroid Build Coastguard Worker       {
752*f6dc9357SAndroid Build Coastguard Worker         Byte *lens = &table[r];
753*f6dc9357SAndroid Build Coastguard Worker         r += num;
754*f6dc9357SAndroid Build Coastguard Worker         memset(lens, (int)i, num);
755*f6dc9357SAndroid Build Coastguard Worker       }
756*f6dc9357SAndroid Build Coastguard Worker     }
757*f6dc9357SAndroid Build Coastguard Worker     while (--i);
758*f6dc9357SAndroid Build Coastguard Worker     counts0[0] = 0; // for speculated loads
759*f6dc9357SAndroid Build Coastguard Worker     // no need for check:
760*f6dc9357SAndroid Build Coastguard Worker     // if (r != (UInt32)1 << HUF_MAX_BITS) exit(0);
761*f6dc9357SAndroid Build Coastguard Worker   }
762*f6dc9357SAndroid Build Coastguard Worker   {
763*f6dc9357SAndroid Build Coastguard Worker     #ifdef MY_CPU_64BIT
764*f6dc9357SAndroid Build Coastguard Worker       UInt64
765*f6dc9357SAndroid Build Coastguard Worker     #else
766*f6dc9357SAndroid Build Coastguard Worker       UInt32
767*f6dc9357SAndroid Build Coastguard Worker     #endif
768*f6dc9357SAndroid Build Coastguard Worker         v = 0;
769*f6dc9357SAndroid Build Coastguard Worker     Byte *symbols = HUF_GET_SYMBOLS(table);
770*f6dc9357SAndroid Build Coastguard Worker     do
771*f6dc9357SAndroid Build Coastguard Worker     {
772*f6dc9357SAndroid Build Coastguard Worker       const unsigned nb = *bits++;
773*f6dc9357SAndroid Build Coastguard Worker       if (nb)
774*f6dc9357SAndroid Build Coastguard Worker       {
775*f6dc9357SAndroid Build Coastguard Worker         const unsigned code = counts0[nb];
776*f6dc9357SAndroid Build Coastguard Worker         const unsigned num = (1u << HUF_MAX_BITS) >> nb;
777*f6dc9357SAndroid Build Coastguard Worker         counts0[nb] = code + num;
778*f6dc9357SAndroid Build Coastguard Worker         // memset(&symbols[code], i, num);
779*f6dc9357SAndroid Build Coastguard Worker         // /*
780*f6dc9357SAndroid Build Coastguard Worker         {
781*f6dc9357SAndroid Build Coastguard Worker           Byte *s2 = &symbols[code];
782*f6dc9357SAndroid Build Coastguard Worker           if (num <= 2)
783*f6dc9357SAndroid Build Coastguard Worker           {
784*f6dc9357SAndroid Build Coastguard Worker             s2[0] = (Byte)v;
785*f6dc9357SAndroid Build Coastguard Worker             s2[(size_t)num - 1] = (Byte)v;
786*f6dc9357SAndroid Build Coastguard Worker           }
787*f6dc9357SAndroid Build Coastguard Worker           else if (num <= 8)
788*f6dc9357SAndroid Build Coastguard Worker           {
789*f6dc9357SAndroid Build Coastguard Worker             *(UInt32 *)(void *)s2 = (UInt32)v;
790*f6dc9357SAndroid Build Coastguard Worker             *(UInt32 *)(void *)(s2 + (size_t)num - 4) = (UInt32)v;
791*f6dc9357SAndroid Build Coastguard Worker           }
792*f6dc9357SAndroid Build Coastguard Worker           else
793*f6dc9357SAndroid Build Coastguard Worker           {
794*f6dc9357SAndroid Build Coastguard Worker             #ifdef MY_CPU_64BIT
795*f6dc9357SAndroid Build Coastguard Worker               UInt64 *s = (UInt64 *)(void *)s2;
796*f6dc9357SAndroid Build Coastguard Worker               const UInt64 *lim = (UInt64 *)(void *)(s2 + num);
797*f6dc9357SAndroid Build Coastguard Worker               do
798*f6dc9357SAndroid Build Coastguard Worker               {
799*f6dc9357SAndroid Build Coastguard Worker                 s[0] = v;  s[1] = v;  s += 2;
800*f6dc9357SAndroid Build Coastguard Worker               }
801*f6dc9357SAndroid Build Coastguard Worker               while (s != lim);
802*f6dc9357SAndroid Build Coastguard Worker             #else
803*f6dc9357SAndroid Build Coastguard Worker               UInt32 *s = (UInt32 *)(void *)s2;
804*f6dc9357SAndroid Build Coastguard Worker               const UInt32 *lim = (const UInt32 *)(const void *)(s2 + num);
805*f6dc9357SAndroid Build Coastguard Worker               do
806*f6dc9357SAndroid Build Coastguard Worker               {
807*f6dc9357SAndroid Build Coastguard Worker                 s[0] = v;  s[1] = v;  s += 2;
808*f6dc9357SAndroid Build Coastguard Worker                 s[0] = v;  s[1] = v;  s += 2;
809*f6dc9357SAndroid Build Coastguard Worker               }
810*f6dc9357SAndroid Build Coastguard Worker               while (s != lim);
811*f6dc9357SAndroid Build Coastguard Worker             #endif
812*f6dc9357SAndroid Build Coastguard Worker           }
813*f6dc9357SAndroid Build Coastguard Worker         }
814*f6dc9357SAndroid Build Coastguard Worker         // */
815*f6dc9357SAndroid Build Coastguard Worker       }
816*f6dc9357SAndroid Build Coastguard Worker       v +=
817*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_64BIT
818*f6dc9357SAndroid Build Coastguard Worker           0x0101010101010101;
819*f6dc9357SAndroid Build Coastguard Worker         #else
820*f6dc9357SAndroid Build Coastguard Worker           0x01010101;
821*f6dc9357SAndroid Build Coastguard Worker         #endif
822*f6dc9357SAndroid Build Coastguard Worker     }
823*f6dc9357SAndroid Build Coastguard Worker     while (bits != bitsEnd);
824*f6dc9357SAndroid Build Coastguard Worker   }
825*f6dc9357SAndroid Build Coastguard Worker }
826*f6dc9357SAndroid Build Coastguard Worker 
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker 
829*f6dc9357SAndroid Build Coastguard Worker // how many bytes (src) was moved back from original value.
830*f6dc9357SAndroid Build Coastguard Worker // we need (HUF_SRC_OFFSET == 3) for optimized 32-bit memory access
831*f6dc9357SAndroid Build Coastguard Worker #define HUF_SRC_OFFSET  3
832*f6dc9357SAndroid Build Coastguard Worker 
833*f6dc9357SAndroid Build Coastguard Worker // v <<= 8 - (bitOffset & 7) + numBits;
834*f6dc9357SAndroid Build Coastguard Worker // v >>= 32 - HUF_MAX_BITS;
835*f6dc9357SAndroid Build Coastguard Worker #define HUF_GET_STATE(v, bitOffset, numBits) \
836*f6dc9357SAndroid Build Coastguard Worker   GET32(v, src + (HUF_SRC_OFFSET - 3) + ((CBitCtr_signed)bitOffset >> 3)) \
837*f6dc9357SAndroid Build Coastguard Worker   v >>= 32 - HUF_MAX_BITS - 8 + ((unsigned)bitOffset & 7) - numBits; \
838*f6dc9357SAndroid Build Coastguard Worker   v &= (1u << HUF_MAX_BITS) - 1; \
839*f6dc9357SAndroid Build Coastguard Worker 
840*f6dc9357SAndroid Build Coastguard Worker 
841*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
842*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_AMD64) && defined(_MSC_VER) && _MSC_VER == 1400 \
843*f6dc9357SAndroid Build Coastguard Worker   || !defined(MY_CPU_X86_OR_AMD64) \
844*f6dc9357SAndroid Build Coastguard Worker   // || 1 == 1 /* for debug : to force STREAM4_PRELOAD mode */
845*f6dc9357SAndroid Build Coastguard Worker   // we need big number (>=16) of registers for PRELOAD4
846*f6dc9357SAndroid Build Coastguard Worker   #define Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4
847*f6dc9357SAndroid Build Coastguard Worker   // #define Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2 // for debug
848*f6dc9357SAndroid Build Coastguard Worker #endif
849*f6dc9357SAndroid Build Coastguard Worker #endif
850*f6dc9357SAndroid Build Coastguard Worker 
851*f6dc9357SAndroid Build Coastguard Worker // for debug: simpler and smaller code but slow:
852*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE
853*f6dc9357SAndroid Build Coastguard Worker 
854*f6dc9357SAndroid Build Coastguard Worker #if  defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE) || \
855*f6dc9357SAndroid Build Coastguard Worker     !defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS)
856*f6dc9357SAndroid Build Coastguard Worker 
857*f6dc9357SAndroid Build Coastguard Worker #define HUF_DECODE(bitOffset, dest) \
858*f6dc9357SAndroid Build Coastguard Worker { \
859*f6dc9357SAndroid Build Coastguard Worker   UInt32 v; \
860*f6dc9357SAndroid Build Coastguard Worker   HUF_GET_STATE(v, bitOffset, 0) \
861*f6dc9357SAndroid Build Coastguard Worker   bitOffset -= table[v]; \
862*f6dc9357SAndroid Build Coastguard Worker   *(dest) = symbols[v]; \
863*f6dc9357SAndroid Build Coastguard Worker   if ((CBitCtr_signed)bitOffset < 0) return SZ_ERROR_DATA; \
864*f6dc9357SAndroid Build Coastguard Worker }
865*f6dc9357SAndroid Build Coastguard Worker 
866*f6dc9357SAndroid Build Coastguard Worker #endif
867*f6dc9357SAndroid Build Coastguard Worker 
868*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE) || \
869*f6dc9357SAndroid Build Coastguard Worker      defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4) || \
870*f6dc9357SAndroid Build Coastguard Worker      defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2) \
871*f6dc9357SAndroid Build Coastguard Worker 
872*f6dc9357SAndroid Build Coastguard Worker #define HUF_DECODE_2_INIT(v, bitOffset) \
873*f6dc9357SAndroid Build Coastguard Worker   HUF_GET_STATE(v, bitOffset, 0)
874*f6dc9357SAndroid Build Coastguard Worker 
875*f6dc9357SAndroid Build Coastguard Worker #define HUF_DECODE_2(v, bitOffset, dest) \
876*f6dc9357SAndroid Build Coastguard Worker { \
877*f6dc9357SAndroid Build Coastguard Worker   unsigned numBits; \
878*f6dc9357SAndroid Build Coastguard Worker   numBits = table[v]; \
879*f6dc9357SAndroid Build Coastguard Worker   *(dest) = symbols[v]; \
880*f6dc9357SAndroid Build Coastguard Worker   HUF_GET_STATE(v, bitOffset, numBits) \
881*f6dc9357SAndroid Build Coastguard Worker   bitOffset -= (CBitCtr)numBits; \
882*f6dc9357SAndroid Build Coastguard Worker   if ((CBitCtr_signed)bitOffset < 0) return SZ_ERROR_DATA; \
883*f6dc9357SAndroid Build Coastguard Worker }
884*f6dc9357SAndroid Build Coastguard Worker 
885*f6dc9357SAndroid Build Coastguard Worker #endif
886*f6dc9357SAndroid Build Coastguard Worker 
887*f6dc9357SAndroid Build Coastguard Worker 
888*f6dc9357SAndroid Build Coastguard Worker // src == ptr - HUF_SRC_OFFSET
889*f6dc9357SAndroid Build Coastguard Worker // we are allowed to access 3 bytes before start of input buffer
890*f6dc9357SAndroid Build Coastguard Worker static
891*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Huf_Decompress_1stream(const Byte * const table,const Byte * src,const size_t srcLen,Byte * dest,const size_t destLen)892*f6dc9357SAndroid Build Coastguard Worker SRes Huf_Decompress_1stream(const Byte * const table,
893*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, const size_t srcLen,
894*f6dc9357SAndroid Build Coastguard Worker     Byte *dest, const size_t destLen)
895*f6dc9357SAndroid Build Coastguard Worker {
896*f6dc9357SAndroid Build Coastguard Worker   CBitCtr bitOffset;
897*f6dc9357SAndroid Build Coastguard Worker   if (srcLen == 0)
898*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
899*f6dc9357SAndroid Build Coastguard Worker   SET_bitOffset_TO_PAD (bitOffset, src + HUF_SRC_OFFSET, srcLen)
900*f6dc9357SAndroid Build Coastguard Worker   if (destLen)
901*f6dc9357SAndroid Build Coastguard Worker   {
902*f6dc9357SAndroid Build Coastguard Worker     const Byte *symbols = HUF_GET_SYMBOLS(table);
903*f6dc9357SAndroid Build Coastguard Worker     const Byte *destLim = dest + destLen;
904*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ZSTD_DEC_USE_HUF_STREAM1_SIMPLE
905*f6dc9357SAndroid Build Coastguard Worker     {
906*f6dc9357SAndroid Build Coastguard Worker       do
907*f6dc9357SAndroid Build Coastguard Worker       {
908*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE (bitOffset, dest)
909*f6dc9357SAndroid Build Coastguard Worker       }
910*f6dc9357SAndroid Build Coastguard Worker       while (++dest != destLim);
911*f6dc9357SAndroid Build Coastguard Worker     }
912*f6dc9357SAndroid Build Coastguard Worker     #else
913*f6dc9357SAndroid Build Coastguard Worker     {
914*f6dc9357SAndroid Build Coastguard Worker       UInt32 v;
915*f6dc9357SAndroid Build Coastguard Worker       HUF_DECODE_2_INIT (v, bitOffset)
916*f6dc9357SAndroid Build Coastguard Worker       do
917*f6dc9357SAndroid Build Coastguard Worker       {
918*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2 (v, bitOffset, dest)
919*f6dc9357SAndroid Build Coastguard Worker       }
920*f6dc9357SAndroid Build Coastguard Worker       while (++dest != destLim);
921*f6dc9357SAndroid Build Coastguard Worker     }
922*f6dc9357SAndroid Build Coastguard Worker     #endif
923*f6dc9357SAndroid Build Coastguard Worker   }
924*f6dc9357SAndroid Build Coastguard Worker   return bitOffset == 0 ? SZ_OK : SZ_ERROR_DATA;
925*f6dc9357SAndroid Build Coastguard Worker }
926*f6dc9357SAndroid Build Coastguard Worker 
927*f6dc9357SAndroid Build Coastguard Worker 
928*f6dc9357SAndroid Build Coastguard Worker // for debug : it reduces register pressure : by array copy can be slow :
929*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_HUF_LOCAL
930*f6dc9357SAndroid Build Coastguard Worker 
931*f6dc9357SAndroid Build Coastguard Worker // src == ptr + (6 - HUF_SRC_OFFSET)
932*f6dc9357SAndroid Build Coastguard Worker // srcLen >= 10
933*f6dc9357SAndroid Build Coastguard Worker // we are allowed to access 3 bytes before start of input buffer
934*f6dc9357SAndroid Build Coastguard Worker static
935*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Huf_Decompress_4stream(const Byte * const table2,const Byte * src,size_t srcLen,Byte * dest,size_t destLen)936*f6dc9357SAndroid Build Coastguard Worker SRes Huf_Decompress_4stream(const Byte * const
937*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
938*f6dc9357SAndroid Build Coastguard Worker     table2,
939*f6dc9357SAndroid Build Coastguard Worker   #else
940*f6dc9357SAndroid Build Coastguard Worker     table,
941*f6dc9357SAndroid Build Coastguard Worker   #endif
942*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, size_t srcLen,
943*f6dc9357SAndroid Build Coastguard Worker     Byte *dest, size_t destLen)
944*f6dc9357SAndroid Build Coastguard Worker {
945*f6dc9357SAndroid Build Coastguard Worker  #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
946*f6dc9357SAndroid Build Coastguard Worker   Byte table[HUF_TABLE_SIZE];
947*f6dc9357SAndroid Build Coastguard Worker  #endif
948*f6dc9357SAndroid Build Coastguard Worker   UInt32 sizes[3];
949*f6dc9357SAndroid Build Coastguard Worker   const size_t delta = (destLen + 3) / 4;
950*f6dc9357SAndroid Build Coastguard Worker   if ((sizes[0] = GetUi16(src + (0 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
951*f6dc9357SAndroid Build Coastguard Worker   if ((sizes[1] = GetUi16(src + (2 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
952*f6dc9357SAndroid Build Coastguard Worker   sizes[1] += sizes[0];
953*f6dc9357SAndroid Build Coastguard Worker   if ((sizes[2] = GetUi16(src + (4 + HUF_SRC_OFFSET - 6))) == 0) return SZ_ERROR_DATA;
954*f6dc9357SAndroid Build Coastguard Worker   sizes[2] += sizes[1];
955*f6dc9357SAndroid Build Coastguard Worker   srcLen -= 6;
956*f6dc9357SAndroid Build Coastguard Worker   if (srcLen <= sizes[2])
957*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker  #ifdef Z7_ZSTD_DEC_USE_HUF_LOCAL
960*f6dc9357SAndroid Build Coastguard Worker   {
961*f6dc9357SAndroid Build Coastguard Worker     // unsigned i = 0; for(; i < 1000; i++)
962*f6dc9357SAndroid Build Coastguard Worker     memcpy(table, table2, HUF_TABLE_SIZE);
963*f6dc9357SAndroid Build Coastguard Worker   }
964*f6dc9357SAndroid Build Coastguard Worker  #endif
965*f6dc9357SAndroid Build Coastguard Worker 
966*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
967*f6dc9357SAndroid Build Coastguard Worker   {
968*f6dc9357SAndroid Build Coastguard Worker     CBitCtr bitOffset_0,
969*f6dc9357SAndroid Build Coastguard Worker             bitOffset_1,
970*f6dc9357SAndroid Build Coastguard Worker             bitOffset_2,
971*f6dc9357SAndroid Build Coastguard Worker             bitOffset_3;
972*f6dc9357SAndroid Build Coastguard Worker     {
973*f6dc9357SAndroid Build Coastguard Worker       SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_0, src + HUF_SRC_OFFSET, sizes[0])
974*f6dc9357SAndroid Build Coastguard Worker       SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_1, src + HUF_SRC_OFFSET, sizes[1])
975*f6dc9357SAndroid Build Coastguard Worker       SET_bitOffset_TO_PAD_and_SET_BIT_SIZE (bitOffset_2, src + HUF_SRC_OFFSET, sizes[2])
976*f6dc9357SAndroid Build Coastguard Worker       SET_bitOffset_TO_PAD                  (bitOffset_3, src + HUF_SRC_OFFSET, srcLen)
977*f6dc9357SAndroid Build Coastguard Worker     }
978*f6dc9357SAndroid Build Coastguard Worker     {
979*f6dc9357SAndroid Build Coastguard Worker       const Byte * const symbols = HUF_GET_SYMBOLS(table);
980*f6dc9357SAndroid Build Coastguard Worker       Byte *destLim = dest + destLen - delta * 3;
981*f6dc9357SAndroid Build Coastguard Worker 
982*f6dc9357SAndroid Build Coastguard Worker       if (dest != destLim)
983*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD4
984*f6dc9357SAndroid Build Coastguard Worker       {
985*f6dc9357SAndroid Build Coastguard Worker         UInt32 v_0, v_1, v_2, v_3;
986*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_0, bitOffset_0)
987*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_1, bitOffset_1)
988*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_2, bitOffset_2)
989*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_3, bitOffset_3)
990*f6dc9357SAndroid Build Coastguard Worker         // #define HUF_DELTA (1 << 17) / 4
991*f6dc9357SAndroid Build Coastguard Worker         do
992*f6dc9357SAndroid Build Coastguard Worker         {
993*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_3, bitOffset_3, dest + delta * 3)
994*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_2, bitOffset_2, dest + delta * 2)
995*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_1, bitOffset_1, dest + delta)
996*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_0, bitOffset_0, dest)
997*f6dc9357SAndroid Build Coastguard Worker         }
998*f6dc9357SAndroid Build Coastguard Worker         while (++dest != destLim);
999*f6dc9357SAndroid Build Coastguard Worker         /*
1000*f6dc9357SAndroid Build Coastguard Worker         {// unsigned y = 0; for (;y < 1; y++)
1001*f6dc9357SAndroid Build Coastguard Worker         {
1002*f6dc9357SAndroid Build Coastguard Worker           const size_t num = destLen - delta * 3;
1003*f6dc9357SAndroid Build Coastguard Worker           Byte *orig = dest - num;
1004*f6dc9357SAndroid Build Coastguard Worker           memmove (orig + delta    , orig + HUF_DELTA,     num);
1005*f6dc9357SAndroid Build Coastguard Worker           memmove (orig + delta * 2, orig + HUF_DELTA * 2, num);
1006*f6dc9357SAndroid Build Coastguard Worker           memmove (orig + delta * 3, orig + HUF_DELTA * 3, num);
1007*f6dc9357SAndroid Build Coastguard Worker         }}
1008*f6dc9357SAndroid Build Coastguard Worker         */
1009*f6dc9357SAndroid Build Coastguard Worker       }
1010*f6dc9357SAndroid Build Coastguard Worker     #elif defined(Z7_ZSTD_DEC_USE_HUF_STREAM4_PRELOAD2)
1011*f6dc9357SAndroid Build Coastguard Worker       {
1012*f6dc9357SAndroid Build Coastguard Worker         UInt32 v_0, v_1, v_2, v_3;
1013*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_0, bitOffset_0)
1014*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_1, bitOffset_1)
1015*f6dc9357SAndroid Build Coastguard Worker         do
1016*f6dc9357SAndroid Build Coastguard Worker         {
1017*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_0, bitOffset_0, dest)
1018*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_1, bitOffset_1, dest + delta)
1019*f6dc9357SAndroid Build Coastguard Worker         }
1020*f6dc9357SAndroid Build Coastguard Worker         while (++dest != destLim);
1021*f6dc9357SAndroid Build Coastguard Worker         dest = destLim - (destLen - delta * 3);
1022*f6dc9357SAndroid Build Coastguard Worker         dest += delta * 2;
1023*f6dc9357SAndroid Build Coastguard Worker         destLim += delta * 2;
1024*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_2, bitOffset_2)
1025*f6dc9357SAndroid Build Coastguard Worker         HUF_DECODE_2_INIT (v_3, bitOffset_3)
1026*f6dc9357SAndroid Build Coastguard Worker         do
1027*f6dc9357SAndroid Build Coastguard Worker         {
1028*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_2, bitOffset_2, dest)
1029*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE_2 (v_3, bitOffset_3, dest + delta)
1030*f6dc9357SAndroid Build Coastguard Worker         }
1031*f6dc9357SAndroid Build Coastguard Worker         while (++dest != destLim);
1032*f6dc9357SAndroid Build Coastguard Worker         dest -= delta * 2;
1033*f6dc9357SAndroid Build Coastguard Worker         destLim -= delta * 2;
1034*f6dc9357SAndroid Build Coastguard Worker       }
1035*f6dc9357SAndroid Build Coastguard Worker     #else
1036*f6dc9357SAndroid Build Coastguard Worker       {
1037*f6dc9357SAndroid Build Coastguard Worker         do
1038*f6dc9357SAndroid Build Coastguard Worker         {
1039*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_3, dest + delta * 3)
1040*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_2, dest + delta * 2)
1041*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_1, dest + delta)
1042*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_0, dest)
1043*f6dc9357SAndroid Build Coastguard Worker         }
1044*f6dc9357SAndroid Build Coastguard Worker         while (++dest != destLim);
1045*f6dc9357SAndroid Build Coastguard Worker       }
1046*f6dc9357SAndroid Build Coastguard Worker     #endif
1047*f6dc9357SAndroid Build Coastguard Worker 
1048*f6dc9357SAndroid Build Coastguard Worker       if (bitOffset_3 != (CBitCtr)sizes[2])
1049*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
1050*f6dc9357SAndroid Build Coastguard Worker       if (destLen &= 3)
1051*f6dc9357SAndroid Build Coastguard Worker       {
1052*f6dc9357SAndroid Build Coastguard Worker         destLim = dest + 4 - destLen;
1053*f6dc9357SAndroid Build Coastguard Worker         do
1054*f6dc9357SAndroid Build Coastguard Worker         {
1055*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_2, dest + delta * 2)
1056*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_1, dest + delta)
1057*f6dc9357SAndroid Build Coastguard Worker           HUF_DECODE (bitOffset_0, dest)
1058*f6dc9357SAndroid Build Coastguard Worker         }
1059*f6dc9357SAndroid Build Coastguard Worker         while (++dest != destLim);
1060*f6dc9357SAndroid Build Coastguard Worker       }
1061*f6dc9357SAndroid Build Coastguard Worker       if (   bitOffset_0 != 0
1062*f6dc9357SAndroid Build Coastguard Worker           || bitOffset_1 != (CBitCtr)sizes[0]
1063*f6dc9357SAndroid Build Coastguard Worker           || bitOffset_2 != (CBitCtr)sizes[1])
1064*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
1065*f6dc9357SAndroid Build Coastguard Worker     }
1066*f6dc9357SAndroid Build Coastguard Worker   }
1067*f6dc9357SAndroid Build Coastguard Worker   #else // Z7_ZSTD_DEC_USE_HUF_STREAM1_ALWAYS
1068*f6dc9357SAndroid Build Coastguard Worker   {
1069*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
1070*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < 4; i++)
1071*f6dc9357SAndroid Build Coastguard Worker     {
1072*f6dc9357SAndroid Build Coastguard Worker       size_t d = destLen;
1073*f6dc9357SAndroid Build Coastguard Worker       size_t size = srcLen;
1074*f6dc9357SAndroid Build Coastguard Worker       if (i != 3)
1075*f6dc9357SAndroid Build Coastguard Worker       {
1076*f6dc9357SAndroid Build Coastguard Worker         d = delta;
1077*f6dc9357SAndroid Build Coastguard Worker         size = sizes[i];
1078*f6dc9357SAndroid Build Coastguard Worker       }
1079*f6dc9357SAndroid Build Coastguard Worker       if (i != 0)
1080*f6dc9357SAndroid Build Coastguard Worker         size -= sizes[i - 1];
1081*f6dc9357SAndroid Build Coastguard Worker       destLen -= d;
1082*f6dc9357SAndroid Build Coastguard Worker       RINOK(Huf_Decompress_1stream(table, src, size, dest, d))
1083*f6dc9357SAndroid Build Coastguard Worker       dest += d;
1084*f6dc9357SAndroid Build Coastguard Worker       src += size;
1085*f6dc9357SAndroid Build Coastguard Worker     }
1086*f6dc9357SAndroid Build Coastguard Worker   }
1087*f6dc9357SAndroid Build Coastguard Worker   #endif
1088*f6dc9357SAndroid Build Coastguard Worker 
1089*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1090*f6dc9357SAndroid Build Coastguard Worker }
1091*f6dc9357SAndroid Build Coastguard Worker 
1092*f6dc9357SAndroid Build Coastguard Worker 
1093*f6dc9357SAndroid Build Coastguard Worker 
1094*f6dc9357SAndroid Build Coastguard Worker // (in->len != 0)
1095*f6dc9357SAndroid Build Coastguard Worker // we are allowed to access in->ptr[-3]
1096*f6dc9357SAndroid Build Coastguard Worker // at least 2 bytes in (in->ptr) will be processed
Huf_DecodeTable(CZstdDecHufTable * const p,CInBufPair * const in)1097*f6dc9357SAndroid Build Coastguard Worker static SRes Huf_DecodeTable(CZstdDecHufTable *const p, CInBufPair *const in)
1098*f6dc9357SAndroid Build Coastguard Worker {
1099*f6dc9357SAndroid Build Coastguard Worker   Byte weights[HUF_MAX_SYMBS + 1];  // +1 for extra write for loop unroll
1100*f6dc9357SAndroid Build Coastguard Worker   unsigned numSyms;
1101*f6dc9357SAndroid Build Coastguard Worker   const unsigned header = *(in->ptr)++;
1102*f6dc9357SAndroid Build Coastguard Worker   in->len--;
1103*f6dc9357SAndroid Build Coastguard Worker   // memset(weights, 0, sizeof(weights));
1104*f6dc9357SAndroid Build Coastguard Worker   if (header >= 128)
1105*f6dc9357SAndroid Build Coastguard Worker   {
1106*f6dc9357SAndroid Build Coastguard Worker     // direct representation: 4 bits field (0-15) per weight
1107*f6dc9357SAndroid Build Coastguard Worker     numSyms = header - 127;
1108*f6dc9357SAndroid Build Coastguard Worker     // numSyms != 0
1109*f6dc9357SAndroid Build Coastguard Worker     {
1110*f6dc9357SAndroid Build Coastguard Worker       const size_t numBytes = (numSyms + 1) / 2;
1111*f6dc9357SAndroid Build Coastguard Worker       const Byte *const ws = in->ptr;
1112*f6dc9357SAndroid Build Coastguard Worker       size_t i = 0;
1113*f6dc9357SAndroid Build Coastguard Worker       if (in->len < numBytes)
1114*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
1115*f6dc9357SAndroid Build Coastguard Worker       in->ptr += numBytes;
1116*f6dc9357SAndroid Build Coastguard Worker       in->len -= numBytes;
1117*f6dc9357SAndroid Build Coastguard Worker       do
1118*f6dc9357SAndroid Build Coastguard Worker       {
1119*f6dc9357SAndroid Build Coastguard Worker         const unsigned b = ws[i];
1120*f6dc9357SAndroid Build Coastguard Worker         weights[i * 2    ] = (Byte)(b >> 4);
1121*f6dc9357SAndroid Build Coastguard Worker         weights[i * 2 + 1] = (Byte)(b & 0xf);
1122*f6dc9357SAndroid Build Coastguard Worker       }
1123*f6dc9357SAndroid Build Coastguard Worker       while (++i != numBytes);
1124*f6dc9357SAndroid Build Coastguard Worker       /* 7ZIP: we can restore correct zero value for weights[numSyms],
1125*f6dc9357SAndroid Build Coastguard Worker          if we want to use zero values starting from numSyms in code below. */
1126*f6dc9357SAndroid Build Coastguard Worker       // weights[numSyms] = 0;
1127*f6dc9357SAndroid Build Coastguard Worker     }
1128*f6dc9357SAndroid Build Coastguard Worker   }
1129*f6dc9357SAndroid Build Coastguard Worker   else
1130*f6dc9357SAndroid Build Coastguard Worker   {
1131*f6dc9357SAndroid Build Coastguard Worker     #define MAX_ACCURACY_LOG_FOR_WEIGHTS 6
1132*f6dc9357SAndroid Build Coastguard Worker     CFseRecord table[1 << MAX_ACCURACY_LOG_FOR_WEIGHTS];
1133*f6dc9357SAndroid Build Coastguard Worker 
1134*f6dc9357SAndroid Build Coastguard Worker     Byte accuracy;
1135*f6dc9357SAndroid Build Coastguard Worker     const Byte *src;
1136*f6dc9357SAndroid Build Coastguard Worker     size_t srcLen;
1137*f6dc9357SAndroid Build Coastguard Worker     if (in->len < header)
1138*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
1139*f6dc9357SAndroid Build Coastguard Worker     {
1140*f6dc9357SAndroid Build Coastguard Worker       CInBufPair fse_stream;
1141*f6dc9357SAndroid Build Coastguard Worker       fse_stream.len = header;
1142*f6dc9357SAndroid Build Coastguard Worker       fse_stream.ptr = in->ptr;
1143*f6dc9357SAndroid Build Coastguard Worker       in->ptr += header;
1144*f6dc9357SAndroid Build Coastguard Worker       in->len -= header;
1145*f6dc9357SAndroid Build Coastguard Worker       RINOK(FSE_DecodeHeader(table, &fse_stream,
1146*f6dc9357SAndroid Build Coastguard Worker           MAX_ACCURACY_LOG_FOR_WEIGHTS,
1147*f6dc9357SAndroid Build Coastguard Worker           &accuracy,
1148*f6dc9357SAndroid Build Coastguard Worker           16 // num weight symbols max (max-symbol is 15)
1149*f6dc9357SAndroid Build Coastguard Worker           ))
1150*f6dc9357SAndroid Build Coastguard Worker       // at least 2 bytes were processed in fse_stream.
1151*f6dc9357SAndroid Build Coastguard Worker       // (srcLen > 0) after FSE_DecodeHeader()
1152*f6dc9357SAndroid Build Coastguard Worker       // if (srcLen == 0) return SZ_ERROR_DATA;
1153*f6dc9357SAndroid Build Coastguard Worker       src = fse_stream.ptr;
1154*f6dc9357SAndroid Build Coastguard Worker       srcLen = fse_stream.len;
1155*f6dc9357SAndroid Build Coastguard Worker     }
1156*f6dc9357SAndroid Build Coastguard Worker     // we are allowed to access src[-5]
1157*f6dc9357SAndroid Build Coastguard Worker     {
1158*f6dc9357SAndroid Build Coastguard Worker       // unsigned yyy = 200; do {
1159*f6dc9357SAndroid Build Coastguard Worker       CBitCtr bitOffset;
1160*f6dc9357SAndroid Build Coastguard Worker       FastInt32 state1, state2;
1161*f6dc9357SAndroid Build Coastguard Worker       SET_bitOffset_TO_PAD (bitOffset, src, srcLen)
1162*f6dc9357SAndroid Build Coastguard Worker       state1 = accuracy;
1163*f6dc9357SAndroid Build Coastguard Worker       src -= state1 >> 2;  // src -= 1; // for GET16() optimization
1164*f6dc9357SAndroid Build Coastguard Worker       state1 <<= FSE_REC_LEN_OFFSET;
1165*f6dc9357SAndroid Build Coastguard Worker       state2 = state1;
1166*f6dc9357SAndroid Build Coastguard Worker       numSyms = 0;
1167*f6dc9357SAndroid Build Coastguard Worker       for (;;)
1168*f6dc9357SAndroid Build Coastguard Worker       {
1169*f6dc9357SAndroid Build Coastguard Worker         #define FSE_WEIGHT_DECODE(st) \
1170*f6dc9357SAndroid Build Coastguard Worker         { \
1171*f6dc9357SAndroid Build Coastguard Worker           const unsigned bits = GET_FSE_REC_LEN(st); \
1172*f6dc9357SAndroid Build Coastguard Worker           FastInt r; \
1173*f6dc9357SAndroid Build Coastguard Worker           GET16(r, src + (bitOffset >> 3)) \
1174*f6dc9357SAndroid Build Coastguard Worker           r >>= (unsigned)bitOffset & 7; \
1175*f6dc9357SAndroid Build Coastguard Worker           if ((CBitCtr_signed)(bitOffset -= (CBitCtr)bits) < 0) \
1176*f6dc9357SAndroid Build Coastguard Worker             { if (bitOffset + (CBitCtr)bits != 0) \
1177*f6dc9357SAndroid Build Coastguard Worker                 return SZ_ERROR_DATA; \
1178*f6dc9357SAndroid Build Coastguard Worker               break; } \
1179*f6dc9357SAndroid Build Coastguard Worker           r &= 0xff; \
1180*f6dc9357SAndroid Build Coastguard Worker           r >>= 8 - bits; \
1181*f6dc9357SAndroid Build Coastguard Worker           st = table[GET_FSE_REC_STATE(st) + r]; \
1182*f6dc9357SAndroid Build Coastguard Worker           weights[numSyms++] = (Byte)GET_FSE_REC_SYM(st); \
1183*f6dc9357SAndroid Build Coastguard Worker         }
1184*f6dc9357SAndroid Build Coastguard Worker         FSE_WEIGHT_DECODE (state1)
1185*f6dc9357SAndroid Build Coastguard Worker         FSE_WEIGHT_DECODE (state2)
1186*f6dc9357SAndroid Build Coastguard Worker         if (numSyms == HUF_MAX_SYMBS)
1187*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
1188*f6dc9357SAndroid Build Coastguard Worker       }
1189*f6dc9357SAndroid Build Coastguard Worker       // src += (unsigned)accuracy >> 2; } while (--yyy);
1190*f6dc9357SAndroid Build Coastguard Worker     }
1191*f6dc9357SAndroid Build Coastguard Worker   }
1192*f6dc9357SAndroid Build Coastguard Worker 
1193*f6dc9357SAndroid Build Coastguard Worker   // Build using weights:
1194*f6dc9357SAndroid Build Coastguard Worker   {
1195*f6dc9357SAndroid Build Coastguard Worker     UInt32 sum = 0;
1196*f6dc9357SAndroid Build Coastguard Worker     {
1197*f6dc9357SAndroid Build Coastguard Worker       // numSyms >= 1
1198*f6dc9357SAndroid Build Coastguard Worker       unsigned i = 0;
1199*f6dc9357SAndroid Build Coastguard Worker       weights[numSyms] = 0;
1200*f6dc9357SAndroid Build Coastguard Worker       do
1201*f6dc9357SAndroid Build Coastguard Worker       {
1202*f6dc9357SAndroid Build Coastguard Worker         sum += ((UInt32)1 << weights[i    ]) & ~(UInt32)1;
1203*f6dc9357SAndroid Build Coastguard Worker         sum += ((UInt32)1 << weights[i + 1]) & ~(UInt32)1;
1204*f6dc9357SAndroid Build Coastguard Worker         i += 2;
1205*f6dc9357SAndroid Build Coastguard Worker       }
1206*f6dc9357SAndroid Build Coastguard Worker       while (i < numSyms);
1207*f6dc9357SAndroid Build Coastguard Worker       if (sum == 0)
1208*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
1209*f6dc9357SAndroid Build Coastguard Worker     }
1210*f6dc9357SAndroid Build Coastguard Worker     {
1211*f6dc9357SAndroid Build Coastguard Worker       const unsigned maxBits = GetHighestSetBit_32_nonzero_big(sum) + 1;
1212*f6dc9357SAndroid Build Coastguard Worker       {
1213*f6dc9357SAndroid Build Coastguard Worker         const UInt32 left = ((UInt32)1 << maxBits) - sum;
1214*f6dc9357SAndroid Build Coastguard Worker         // (left != 0)
1215*f6dc9357SAndroid Build Coastguard Worker         // (left) must be power of 2 in correct stream
1216*f6dc9357SAndroid Build Coastguard Worker         if (left & (left - 1))
1217*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
1218*f6dc9357SAndroid Build Coastguard Worker         weights[numSyms++] = (Byte)GetHighestSetBit_32_nonzero_big(left);
1219*f6dc9357SAndroid Build Coastguard Worker       }
1220*f6dc9357SAndroid Build Coastguard Worker       // if (numSyms & 1)
1221*f6dc9357SAndroid Build Coastguard Worker         weights[numSyms] = 0; // for loop unroll
1222*f6dc9357SAndroid Build Coastguard Worker       // numSyms >= 2
1223*f6dc9357SAndroid Build Coastguard Worker       {
1224*f6dc9357SAndroid Build Coastguard Worker         unsigned i = 0;
1225*f6dc9357SAndroid Build Coastguard Worker         do
1226*f6dc9357SAndroid Build Coastguard Worker         {
1227*f6dc9357SAndroid Build Coastguard Worker           /*
1228*f6dc9357SAndroid Build Coastguard Worker           #define WEIGHT_ITER(a) \
1229*f6dc9357SAndroid Build Coastguard Worker             { unsigned w = weights[i + (a)]; \
1230*f6dc9357SAndroid Build Coastguard Worker               const unsigned t = maxBits - w; \
1231*f6dc9357SAndroid Build Coastguard Worker               w = w ? t: w; \
1232*f6dc9357SAndroid Build Coastguard Worker               if (w > HUF_MAX_BITS) return SZ_ERROR_DATA; \
1233*f6dc9357SAndroid Build Coastguard Worker               weights[i + (a)] = (Byte)w; }
1234*f6dc9357SAndroid Build Coastguard Worker           */
1235*f6dc9357SAndroid Build Coastguard Worker           // /*
1236*f6dc9357SAndroid Build Coastguard Worker           #define WEIGHT_ITER(a) \
1237*f6dc9357SAndroid Build Coastguard Worker             { unsigned w = weights[i + (a)]; \
1238*f6dc9357SAndroid Build Coastguard Worker               if (w) {  \
1239*f6dc9357SAndroid Build Coastguard Worker                 w = maxBits - w; \
1240*f6dc9357SAndroid Build Coastguard Worker                 if (w > HUF_MAX_BITS) return SZ_ERROR_DATA; \
1241*f6dc9357SAndroid Build Coastguard Worker                 weights[i + (a)] = (Byte)w; }}
1242*f6dc9357SAndroid Build Coastguard Worker           // */
1243*f6dc9357SAndroid Build Coastguard Worker           WEIGHT_ITER(0)
1244*f6dc9357SAndroid Build Coastguard Worker           // WEIGHT_ITER(1)
1245*f6dc9357SAndroid Build Coastguard Worker           // i += 2;
1246*f6dc9357SAndroid Build Coastguard Worker         }
1247*f6dc9357SAndroid Build Coastguard Worker         while (++i != numSyms);
1248*f6dc9357SAndroid Build Coastguard Worker       }
1249*f6dc9357SAndroid Build Coastguard Worker     }
1250*f6dc9357SAndroid Build Coastguard Worker   }
1251*f6dc9357SAndroid Build Coastguard Worker   {
1252*f6dc9357SAndroid Build Coastguard Worker     // unsigned yyy; for (yyy = 0; yyy < 100; yyy++)
1253*f6dc9357SAndroid Build Coastguard Worker     Huf_Build((Byte *)(void *)p->table64, weights, numSyms);
1254*f6dc9357SAndroid Build Coastguard Worker   }
1255*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1256*f6dc9357SAndroid Build Coastguard Worker }
1257*f6dc9357SAndroid Build Coastguard Worker 
1258*f6dc9357SAndroid Build Coastguard Worker 
1259*f6dc9357SAndroid Build Coastguard Worker typedef enum
1260*f6dc9357SAndroid Build Coastguard Worker {
1261*f6dc9357SAndroid Build Coastguard Worker   k_SeqMode_Predef = 0,
1262*f6dc9357SAndroid Build Coastguard Worker   k_SeqMode_RLE    = 1,
1263*f6dc9357SAndroid Build Coastguard Worker   k_SeqMode_FSE    = 2,
1264*f6dc9357SAndroid Build Coastguard Worker   k_SeqMode_Repeat = 3
1265*f6dc9357SAndroid Build Coastguard Worker }
1266*f6dc9357SAndroid Build Coastguard Worker z7_zstd_enum_SeqMode;
1267*f6dc9357SAndroid Build Coastguard Worker 
1268*f6dc9357SAndroid Build Coastguard Worker // predefAccuracy == 5 for OFFSET symbols
1269*f6dc9357SAndroid Build Coastguard Worker // predefAccuracy == 6 for MATCH/LIT LEN symbols
1270*f6dc9357SAndroid Build Coastguard Worker static
1271*f6dc9357SAndroid Build Coastguard Worker SRes
1272*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
1273*f6dc9357SAndroid Build Coastguard Worker // Z7_FORCE_INLINE
FSE_Decode_SeqTable(CFseRecord * const table,CInBufPair * const in,unsigned predefAccuracy,Byte * const accuracyRes,unsigned numSymbolsMax,const CFseRecord * const predefs,const unsigned seqMode)1274*f6dc9357SAndroid Build Coastguard Worker FSE_Decode_SeqTable(CFseRecord * const table,
1275*f6dc9357SAndroid Build Coastguard Worker     CInBufPair * const in,
1276*f6dc9357SAndroid Build Coastguard Worker     unsigned predefAccuracy,
1277*f6dc9357SAndroid Build Coastguard Worker     Byte * const accuracyRes,
1278*f6dc9357SAndroid Build Coastguard Worker     unsigned numSymbolsMax,
1279*f6dc9357SAndroid Build Coastguard Worker     const CFseRecord * const predefs,
1280*f6dc9357SAndroid Build Coastguard Worker     const unsigned seqMode)
1281*f6dc9357SAndroid Build Coastguard Worker {
1282*f6dc9357SAndroid Build Coastguard Worker   // UNUSED_VAR(numSymsPredef)
1283*f6dc9357SAndroid Build Coastguard Worker   // UNUSED_VAR(predefFreqs)
1284*f6dc9357SAndroid Build Coastguard Worker   if (seqMode == k_SeqMode_FSE)
1285*f6dc9357SAndroid Build Coastguard Worker   {
1286*f6dc9357SAndroid Build Coastguard Worker     // unsigned y = 50; CInBufPair in2 = *in; do { *in = in2; RINOK(
1287*f6dc9357SAndroid Build Coastguard Worker     return
1288*f6dc9357SAndroid Build Coastguard Worker     FSE_DecodeHeader(table, in,
1289*f6dc9357SAndroid Build Coastguard Worker         predefAccuracy + 3, // accuracyMax
1290*f6dc9357SAndroid Build Coastguard Worker         accuracyRes,
1291*f6dc9357SAndroid Build Coastguard Worker         numSymbolsMax)
1292*f6dc9357SAndroid Build Coastguard Worker     ;
1293*f6dc9357SAndroid Build Coastguard Worker     // )} while (--y); return SZ_OK;
1294*f6dc9357SAndroid Build Coastguard Worker   }
1295*f6dc9357SAndroid Build Coastguard Worker   // numSymsMax = numSymsPredef + ((predefAccuracy & 1) * (32 - 29))); // numSymsMax
1296*f6dc9357SAndroid Build Coastguard Worker   // numSymsMax == 32 for offsets
1297*f6dc9357SAndroid Build Coastguard Worker 
1298*f6dc9357SAndroid Build Coastguard Worker   if (seqMode == k_SeqMode_Predef)
1299*f6dc9357SAndroid Build Coastguard Worker   {
1300*f6dc9357SAndroid Build Coastguard Worker     *accuracyRes = (Byte)predefAccuracy;
1301*f6dc9357SAndroid Build Coastguard Worker     memcpy(table, predefs, sizeof(UInt32) << predefAccuracy);
1302*f6dc9357SAndroid Build Coastguard Worker     return SZ_OK;
1303*f6dc9357SAndroid Build Coastguard Worker   }
1304*f6dc9357SAndroid Build Coastguard Worker 
1305*f6dc9357SAndroid Build Coastguard Worker   // (seqMode == k_SeqMode_RLE)
1306*f6dc9357SAndroid Build Coastguard Worker   if (in->len == 0)
1307*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_DATA;
1308*f6dc9357SAndroid Build Coastguard Worker   in->len--;
1309*f6dc9357SAndroid Build Coastguard Worker   {
1310*f6dc9357SAndroid Build Coastguard Worker     const Byte *ptr = in->ptr;
1311*f6dc9357SAndroid Build Coastguard Worker     const unsigned sym = ptr[0];
1312*f6dc9357SAndroid Build Coastguard Worker     in->ptr = ptr + 1;
1313*f6dc9357SAndroid Build Coastguard Worker     if (sym >= numSymbolsMax)
1314*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
1315*f6dc9357SAndroid Build Coastguard Worker     table[0] = (FastInt32)sym
1316*f6dc9357SAndroid Build Coastguard Worker       #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
1317*f6dc9357SAndroid Build Coastguard Worker         + (numSymbolsMax == NUM_ML_SYMBOLS ? MATCH_LEN_MIN : 0)
1318*f6dc9357SAndroid Build Coastguard Worker       #endif
1319*f6dc9357SAndroid Build Coastguard Worker       ;
1320*f6dc9357SAndroid Build Coastguard Worker     *accuracyRes = 0;
1321*f6dc9357SAndroid Build Coastguard Worker   }
1322*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
1323*f6dc9357SAndroid Build Coastguard Worker }
1324*f6dc9357SAndroid Build Coastguard Worker 
1325*f6dc9357SAndroid Build Coastguard Worker 
1326*f6dc9357SAndroid Build Coastguard Worker typedef struct
1327*f6dc9357SAndroid Build Coastguard Worker {
1328*f6dc9357SAndroid Build Coastguard Worker   CFseRecord of[1 << 8];
1329*f6dc9357SAndroid Build Coastguard Worker   CFseRecord ll[1 << 9];
1330*f6dc9357SAndroid Build Coastguard Worker   CFseRecord ml[1 << 9];
1331*f6dc9357SAndroid Build Coastguard Worker }
1332*f6dc9357SAndroid Build Coastguard Worker CZstdDecFseTables;
1333*f6dc9357SAndroid Build Coastguard Worker 
1334*f6dc9357SAndroid Build Coastguard Worker 
1335*f6dc9357SAndroid Build Coastguard Worker typedef struct
1336*f6dc9357SAndroid Build Coastguard Worker {
1337*f6dc9357SAndroid Build Coastguard Worker   Byte *win;
1338*f6dc9357SAndroid Build Coastguard Worker   SizeT cycSize;
1339*f6dc9357SAndroid Build Coastguard Worker   /*
1340*f6dc9357SAndroid Build Coastguard Worker     if (outBuf_fromCaller)  : cycSize = outBufSize_fromCaller
1341*f6dc9357SAndroid Build Coastguard Worker     else {
1342*f6dc9357SAndroid Build Coastguard Worker       if ( isCyclicMode) : cycSize = cyclic_buffer_size = (winSize + extra_space)
1343*f6dc9357SAndroid Build Coastguard Worker       if (!isCyclicMode) : cycSize = ContentSize,
1344*f6dc9357SAndroid Build Coastguard Worker       (isCyclicMode == true) if (ContetSize >= winSize) or ContetSize is unknown
1345*f6dc9357SAndroid Build Coastguard Worker     }
1346*f6dc9357SAndroid Build Coastguard Worker   */
1347*f6dc9357SAndroid Build Coastguard Worker   SizeT winPos;
1348*f6dc9357SAndroid Build Coastguard Worker 
1349*f6dc9357SAndroid Build Coastguard Worker   CZstdDecOffset reps[3];
1350*f6dc9357SAndroid Build Coastguard Worker 
1351*f6dc9357SAndroid Build Coastguard Worker   Byte ll_accuracy;
1352*f6dc9357SAndroid Build Coastguard Worker   Byte of_accuracy;
1353*f6dc9357SAndroid Build Coastguard Worker   Byte ml_accuracy;
1354*f6dc9357SAndroid Build Coastguard Worker   // Byte seqTables_wereSet;
1355*f6dc9357SAndroid Build Coastguard Worker   Byte litHuf_wasSet;
1356*f6dc9357SAndroid Build Coastguard Worker 
1357*f6dc9357SAndroid Build Coastguard Worker   Byte *literalsBase;
1358*f6dc9357SAndroid Build Coastguard Worker 
1359*f6dc9357SAndroid Build Coastguard Worker   size_t winSize;        // from header
1360*f6dc9357SAndroid Build Coastguard Worker   size_t totalOutCheck;  // totalOutCheck <= winSize
1361*f6dc9357SAndroid Build Coastguard Worker 
1362*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
1363*f6dc9357SAndroid Build Coastguard Worker   SEQ_EXTRA_TABLES(m_)
1364*f6dc9357SAndroid Build Coastguard Worker   #endif
1365*f6dc9357SAndroid Build Coastguard Worker   // UInt64 _pad_Alignment;  // is not required now
1366*f6dc9357SAndroid Build Coastguard Worker   CZstdDecFseTables fse;
1367*f6dc9357SAndroid Build Coastguard Worker   CZstdDecHufTable huf;
1368*f6dc9357SAndroid Build Coastguard Worker }
1369*f6dc9357SAndroid Build Coastguard Worker CZstdDec1;
1370*f6dc9357SAndroid Build Coastguard Worker 
1371*f6dc9357SAndroid Build Coastguard Worker #define ZstdDec1_GET_BLOCK_SIZE_LIMIT(p) \
1372*f6dc9357SAndroid Build Coastguard Worker   ((p)->winSize < kBlockSizeMax ? (UInt32)(p)->winSize : kBlockSizeMax)
1373*f6dc9357SAndroid Build Coastguard Worker 
1374*f6dc9357SAndroid Build Coastguard Worker #define SEQ_TABLES_WERE_NOT_SET_ml_accuracy  1  // accuracy=1 is not used by zstd
1375*f6dc9357SAndroid Build Coastguard Worker #define IS_SEQ_TABLES_WERE_SET(p)  (((p)->ml_accuracy != SEQ_TABLES_WERE_NOT_SET_ml_accuracy))
1376*f6dc9357SAndroid Build Coastguard Worker // #define IS_SEQ_TABLES_WERE_SET(p)  ((p)->seqTables_wereSet)
1377*f6dc9357SAndroid Build Coastguard Worker 
1378*f6dc9357SAndroid Build Coastguard Worker 
ZstdDec1_Construct(CZstdDec1 * p)1379*f6dc9357SAndroid Build Coastguard Worker static void ZstdDec1_Construct(CZstdDec1 *p)
1380*f6dc9357SAndroid Build Coastguard Worker {
1381*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_ZSTD_DEC_PRINT_TABLE
1382*f6dc9357SAndroid Build Coastguard Worker   Print_Predef(6, NUM_LL_SYMBOLS, SEQ_LL_PREDEF_DIST, k_PredefRecords_LL);
1383*f6dc9357SAndroid Build Coastguard Worker   Print_Predef(5, NUM_OFFSET_SYMBOLS_PREDEF, SEQ_OFFSET_PREDEF_DIST, k_PredefRecords_OF);
1384*f6dc9357SAndroid Build Coastguard Worker   Print_Predef(6, NUM_ML_SYMBOLS, SEQ_ML_PREDEF_DIST, k_PredefRecords_ML);
1385*f6dc9357SAndroid Build Coastguard Worker   #endif
1386*f6dc9357SAndroid Build Coastguard Worker 
1387*f6dc9357SAndroid Build Coastguard Worker   p->win = NULL;
1388*f6dc9357SAndroid Build Coastguard Worker   p->cycSize = 0;
1389*f6dc9357SAndroid Build Coastguard Worker   p->literalsBase = NULL;
1390*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_ZSTD_DEC_USE_BASES_IN_OBJECT
1391*f6dc9357SAndroid Build Coastguard Worker   FILL_LOC_BASES_ALL
1392*f6dc9357SAndroid Build Coastguard Worker   #endif
1393*f6dc9357SAndroid Build Coastguard Worker }
1394*f6dc9357SAndroid Build Coastguard Worker 
1395*f6dc9357SAndroid Build Coastguard Worker 
ZstdDec1_Init(CZstdDec1 * p)1396*f6dc9357SAndroid Build Coastguard Worker static void ZstdDec1_Init(CZstdDec1 *p)
1397*f6dc9357SAndroid Build Coastguard Worker {
1398*f6dc9357SAndroid Build Coastguard Worker   p->reps[0] = 1;
1399*f6dc9357SAndroid Build Coastguard Worker   p->reps[1] = 4;
1400*f6dc9357SAndroid Build Coastguard Worker   p->reps[2] = 8;
1401*f6dc9357SAndroid Build Coastguard Worker   // p->seqTables_wereSet = False;
1402*f6dc9357SAndroid Build Coastguard Worker   p->ml_accuracy = SEQ_TABLES_WERE_NOT_SET_ml_accuracy;
1403*f6dc9357SAndroid Build Coastguard Worker   p->litHuf_wasSet = False;
1404*f6dc9357SAndroid Build Coastguard Worker   p->totalOutCheck = 0;
1405*f6dc9357SAndroid Build Coastguard Worker }
1406*f6dc9357SAndroid Build Coastguard Worker 
1407*f6dc9357SAndroid Build Coastguard Worker 
1408*f6dc9357SAndroid Build Coastguard Worker 
1409*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
1410*f6dc9357SAndroid Build Coastguard Worker   #define Z7_ZSTD_DEC_USE_UNALIGNED_COPY
1411*f6dc9357SAndroid Build Coastguard Worker #endif
1412*f6dc9357SAndroid Build Coastguard Worker 
1413*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_UNALIGNED_COPY
1414*f6dc9357SAndroid Build Coastguard Worker 
1415*f6dc9357SAndroid Build Coastguard Worker   #define COPY_CHUNK_SIZE 16
1416*f6dc9357SAndroid Build Coastguard Worker 
1417*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK_4_2(dest, src) \
1418*f6dc9357SAndroid Build Coastguard Worker     { \
1419*f6dc9357SAndroid Build Coastguard Worker       ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \
1420*f6dc9357SAndroid Build Coastguard Worker       ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \
1421*f6dc9357SAndroid Build Coastguard Worker       src += 4 * 2; \
1422*f6dc9357SAndroid Build Coastguard Worker       dest += 4 * 2; \
1423*f6dc9357SAndroid Build Coastguard Worker     }
1424*f6dc9357SAndroid Build Coastguard Worker 
1425*f6dc9357SAndroid Build Coastguard Worker   /* sse2 doesn't help here in GCC and CLANG.
1426*f6dc9357SAndroid Build Coastguard Worker      so we disabled sse2 here */
1427*f6dc9357SAndroid Build Coastguard Worker   /*
1428*f6dc9357SAndroid Build Coastguard Worker   #if defined(MY_CPU_AMD64)
1429*f6dc9357SAndroid Build Coastguard Worker     #define Z7_ZSTD_DEC_USE_SSE2
1430*f6dc9357SAndroid Build Coastguard Worker   #elif defined(MY_CPU_X86)
1431*f6dc9357SAndroid Build Coastguard Worker     #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \
1432*f6dc9357SAndroid Build Coastguard Worker       || defined(__SSE2__) \
1433*f6dc9357SAndroid Build Coastguard Worker       // || 1 == 1  // for debug only
1434*f6dc9357SAndroid Build Coastguard Worker       #define Z7_ZSTD_DEC_USE_SSE2
1435*f6dc9357SAndroid Build Coastguard Worker     #endif
1436*f6dc9357SAndroid Build Coastguard Worker   #endif
1437*f6dc9357SAndroid Build Coastguard Worker   */
1438*f6dc9357SAndroid Build Coastguard Worker 
1439*f6dc9357SAndroid Build Coastguard Worker   #if defined(MY_CPU_ARM64)
1440*f6dc9357SAndroid Build Coastguard Worker     #define COPY_OFFSET_MIN  16
1441*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK1(dest, src) \
1442*f6dc9357SAndroid Build Coastguard Worker     { \
1443*f6dc9357SAndroid Build Coastguard Worker       vst1q_u8((uint8_t *)(void *)dest, \
1444*f6dc9357SAndroid Build Coastguard Worker       vld1q_u8((const uint8_t *)(const void *)src)); \
1445*f6dc9357SAndroid Build Coastguard Worker       src += 16; \
1446*f6dc9357SAndroid Build Coastguard Worker       dest += 16; \
1447*f6dc9357SAndroid Build Coastguard Worker     }
1448*f6dc9357SAndroid Build Coastguard Worker 
1449*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK(dest, src) \
1450*f6dc9357SAndroid Build Coastguard Worker     { \
1451*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK1(dest, src) \
1452*f6dc9357SAndroid Build Coastguard Worker       if ((len -= COPY_CHUNK_SIZE) == 0) break; \
1453*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK1(dest, src) \
1454*f6dc9357SAndroid Build Coastguard Worker     }
1455*f6dc9357SAndroid Build Coastguard Worker 
1456*f6dc9357SAndroid Build Coastguard Worker   #elif defined(Z7_ZSTD_DEC_USE_SSE2)
1457*f6dc9357SAndroid Build Coastguard Worker     #include <emmintrin.h> // sse2
1458*f6dc9357SAndroid Build Coastguard Worker     #define COPY_OFFSET_MIN  16
1459*f6dc9357SAndroid Build Coastguard Worker 
1460*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK1(dest, src) \
1461*f6dc9357SAndroid Build Coastguard Worker     { \
1462*f6dc9357SAndroid Build Coastguard Worker       _mm_storeu_si128((__m128i *)(void *)dest, \
1463*f6dc9357SAndroid Build Coastguard Worker       _mm_loadu_si128((const __m128i *)(const void *)src)); \
1464*f6dc9357SAndroid Build Coastguard Worker       src += 16; \
1465*f6dc9357SAndroid Build Coastguard Worker       dest += 16; \
1466*f6dc9357SAndroid Build Coastguard Worker     }
1467*f6dc9357SAndroid Build Coastguard Worker 
1468*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK(dest, src) \
1469*f6dc9357SAndroid Build Coastguard Worker     { \
1470*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK1(dest, src) \
1471*f6dc9357SAndroid Build Coastguard Worker       if ((len -= COPY_CHUNK_SIZE) == 0) break; \
1472*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK1(dest, src) \
1473*f6dc9357SAndroid Build Coastguard Worker     }
1474*f6dc9357SAndroid Build Coastguard Worker 
1475*f6dc9357SAndroid Build Coastguard Worker   #elif defined(MY_CPU_64BIT)
1476*f6dc9357SAndroid Build Coastguard Worker     #define COPY_OFFSET_MIN  8
1477*f6dc9357SAndroid Build Coastguard Worker 
1478*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK(dest, src) \
1479*f6dc9357SAndroid Build Coastguard Worker     { \
1480*f6dc9357SAndroid Build Coastguard Worker       ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \
1481*f6dc9357SAndroid Build Coastguard Worker       ((UInt64 *)(void *)dest)[1] = ((const UInt64 *)(const void *)src)[1]; \
1482*f6dc9357SAndroid Build Coastguard Worker       src += 8 * 2; \
1483*f6dc9357SAndroid Build Coastguard Worker       dest += 8 * 2; \
1484*f6dc9357SAndroid Build Coastguard Worker     }
1485*f6dc9357SAndroid Build Coastguard Worker 
1486*f6dc9357SAndroid Build Coastguard Worker   #else
1487*f6dc9357SAndroid Build Coastguard Worker     #define COPY_OFFSET_MIN  4
1488*f6dc9357SAndroid Build Coastguard Worker 
1489*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK(dest, src) \
1490*f6dc9357SAndroid Build Coastguard Worker     { \
1491*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_4_2(dest, src); \
1492*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_4_2(dest, src); \
1493*f6dc9357SAndroid Build Coastguard Worker     }
1494*f6dc9357SAndroid Build Coastguard Worker 
1495*f6dc9357SAndroid Build Coastguard Worker   #endif
1496*f6dc9357SAndroid Build Coastguard Worker #endif
1497*f6dc9357SAndroid Build Coastguard Worker 
1498*f6dc9357SAndroid Build Coastguard Worker 
1499*f6dc9357SAndroid Build Coastguard Worker #ifndef COPY_CHUNK_SIZE
1500*f6dc9357SAndroid Build Coastguard Worker     #define COPY_OFFSET_MIN  4
1501*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK_SIZE  8
1502*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK_2(dest, src) \
1503*f6dc9357SAndroid Build Coastguard Worker     { \
1504*f6dc9357SAndroid Build Coastguard Worker       const Byte a0 = src[0]; \
1505*f6dc9357SAndroid Build Coastguard Worker       const Byte a1 = src[1]; \
1506*f6dc9357SAndroid Build Coastguard Worker       dest[0] = a0; \
1507*f6dc9357SAndroid Build Coastguard Worker       dest[1] = a1; \
1508*f6dc9357SAndroid Build Coastguard Worker       src += 2; \
1509*f6dc9357SAndroid Build Coastguard Worker       dest += 2; \
1510*f6dc9357SAndroid Build Coastguard Worker     }
1511*f6dc9357SAndroid Build Coastguard Worker     #define COPY_CHUNK(dest, src) \
1512*f6dc9357SAndroid Build Coastguard Worker     { \
1513*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_2(dest, src) \
1514*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_2(dest, src) \
1515*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_2(dest, src) \
1516*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNK_2(dest, src) \
1517*f6dc9357SAndroid Build Coastguard Worker     }
1518*f6dc9357SAndroid Build Coastguard Worker #endif
1519*f6dc9357SAndroid Build Coastguard Worker 
1520*f6dc9357SAndroid Build Coastguard Worker 
1521*f6dc9357SAndroid Build Coastguard Worker #define COPY_PREPARE \
1522*f6dc9357SAndroid Build Coastguard Worker   len += (COPY_CHUNK_SIZE - 1); \
1523*f6dc9357SAndroid Build Coastguard Worker   len &= ~(size_t)(COPY_CHUNK_SIZE - 1); \
1524*f6dc9357SAndroid Build Coastguard Worker   { if (len > rem) \
1525*f6dc9357SAndroid Build Coastguard Worker   { len = rem; \
1526*f6dc9357SAndroid Build Coastguard Worker     rem &= (COPY_CHUNK_SIZE - 1); \
1527*f6dc9357SAndroid Build Coastguard Worker     if (rem) {  \
1528*f6dc9357SAndroid Build Coastguard Worker       len -= rem; \
1529*f6dc9357SAndroid Build Coastguard Worker       Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
1530*f6dc9357SAndroid Build Coastguard Worker       do *dest++ = *src++; while (--rem); \
1531*f6dc9357SAndroid Build Coastguard Worker       if (len == 0) return; }}}
1532*f6dc9357SAndroid Build Coastguard Worker 
1533*f6dc9357SAndroid Build Coastguard Worker #define COPY_CHUNKS \
1534*f6dc9357SAndroid Build Coastguard Worker { \
1535*f6dc9357SAndroid Build Coastguard Worker   Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \
1536*f6dc9357SAndroid Build Coastguard Worker   do { COPY_CHUNK(dest, src) } \
1537*f6dc9357SAndroid Build Coastguard Worker   while (len -= COPY_CHUNK_SIZE); \
1538*f6dc9357SAndroid Build Coastguard Worker }
1539*f6dc9357SAndroid Build Coastguard Worker 
1540*f6dc9357SAndroid Build Coastguard Worker // (len != 0)
1541*f6dc9357SAndroid Build Coastguard Worker // (len <= rem)
1542*f6dc9357SAndroid Build Coastguard Worker static
1543*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
1544*f6dc9357SAndroid Build Coastguard Worker // Z7_ATTRIB_NO_VECTOR
CopyLiterals(Byte * dest,Byte const * src,size_t len,size_t rem)1545*f6dc9357SAndroid Build Coastguard Worker void CopyLiterals(Byte *dest, Byte const *src, size_t len, size_t rem)
1546*f6dc9357SAndroid Build Coastguard Worker {
1547*f6dc9357SAndroid Build Coastguard Worker   COPY_PREPARE
1548*f6dc9357SAndroid Build Coastguard Worker   COPY_CHUNKS
1549*f6dc9357SAndroid Build Coastguard Worker }
1550*f6dc9357SAndroid Build Coastguard Worker 
1551*f6dc9357SAndroid Build Coastguard Worker 
1552*f6dc9357SAndroid Build Coastguard Worker /* we can define Z7_STD_DEC_USE_AFTER_CYC_BUF, if we want to use additional
1553*f6dc9357SAndroid Build Coastguard Worker    space after cycSize that can be used to reduce the code in CopyMatch(): */
1554*f6dc9357SAndroid Build Coastguard Worker // for debug:
1555*f6dc9357SAndroid Build Coastguard Worker // #define Z7_STD_DEC_USE_AFTER_CYC_BUF
1556*f6dc9357SAndroid Build Coastguard Worker 
1557*f6dc9357SAndroid Build Coastguard Worker /*
1558*f6dc9357SAndroid Build Coastguard Worker CopyMatch()
1559*f6dc9357SAndroid Build Coastguard Worker if wrap (offset > winPos)
1560*f6dc9357SAndroid Build Coastguard Worker {
1561*f6dc9357SAndroid Build Coastguard Worker   then we have at least (COPY_CHUNK_SIZE) avail in (dest) before we will overwrite (src):
1562*f6dc9357SAndroid Build Coastguard Worker   (cycSize >= offset + COPY_CHUNK_SIZE)
1563*f6dc9357SAndroid Build Coastguard Worker   if defined(Z7_STD_DEC_USE_AFTER_CYC_BUF)
1564*f6dc9357SAndroid Build Coastguard Worker     we are allowed to read win[cycSize + COPY_CHUNK_SIZE - 1],
1565*f6dc9357SAndroid Build Coastguard Worker }
1566*f6dc9357SAndroid Build Coastguard Worker (len != 0)
1567*f6dc9357SAndroid Build Coastguard Worker */
1568*f6dc9357SAndroid Build Coastguard Worker static
1569*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE
1570*f6dc9357SAndroid Build Coastguard Worker // Z7_ATTRIB_NO_VECTOR
CopyMatch(size_t offset,size_t len,Byte * win,size_t winPos,size_t rem,const size_t cycSize)1571*f6dc9357SAndroid Build Coastguard Worker void CopyMatch(size_t offset, size_t len,
1572*f6dc9357SAndroid Build Coastguard Worker     Byte *win, size_t winPos, size_t rem, const size_t cycSize)
1573*f6dc9357SAndroid Build Coastguard Worker {
1574*f6dc9357SAndroid Build Coastguard Worker   Byte *dest = win + winPos;
1575*f6dc9357SAndroid Build Coastguard Worker   const Byte *src;
1576*f6dc9357SAndroid Build Coastguard Worker   // STAT_INC(g_NumCopy)
1577*f6dc9357SAndroid Build Coastguard Worker 
1578*f6dc9357SAndroid Build Coastguard Worker   if (offset > winPos)
1579*f6dc9357SAndroid Build Coastguard Worker   {
1580*f6dc9357SAndroid Build Coastguard Worker     size_t back = offset - winPos;
1581*f6dc9357SAndroid Build Coastguard Worker     // src = win + cycSize - back;
1582*f6dc9357SAndroid Build Coastguard Worker     // cycSize -= offset;
1583*f6dc9357SAndroid Build Coastguard Worker     STAT_INC(g_NumOver)
1584*f6dc9357SAndroid Build Coastguard Worker     src = dest + (cycSize - offset);
1585*f6dc9357SAndroid Build Coastguard Worker     // (src >= dest) here
1586*f6dc9357SAndroid Build Coastguard Worker    #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
1587*f6dc9357SAndroid Build Coastguard Worker     if (back < len)
1588*f6dc9357SAndroid Build Coastguard Worker     {
1589*f6dc9357SAndroid Build Coastguard Worker    #else
1590*f6dc9357SAndroid Build Coastguard Worker     if (back < len + (COPY_CHUNK_SIZE - 1))
1591*f6dc9357SAndroid Build Coastguard Worker     {
1592*f6dc9357SAndroid Build Coastguard Worker       if (back >= len)
1593*f6dc9357SAndroid Build Coastguard Worker       {
1594*f6dc9357SAndroid Build Coastguard Worker         Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1595*f6dc9357SAndroid Build Coastguard Worker         do
1596*f6dc9357SAndroid Build Coastguard Worker           *dest++ = *src++;
1597*f6dc9357SAndroid Build Coastguard Worker         while (--len);
1598*f6dc9357SAndroid Build Coastguard Worker         return;
1599*f6dc9357SAndroid Build Coastguard Worker       }
1600*f6dc9357SAndroid Build Coastguard Worker    #endif
1601*f6dc9357SAndroid Build Coastguard Worker       // back < len
1602*f6dc9357SAndroid Build Coastguard Worker       STAT_INC(g_NumOver2)
1603*f6dc9357SAndroid Build Coastguard Worker       len -= back;
1604*f6dc9357SAndroid Build Coastguard Worker       rem -= back;
1605*f6dc9357SAndroid Build Coastguard Worker       Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1606*f6dc9357SAndroid Build Coastguard Worker       do
1607*f6dc9357SAndroid Build Coastguard Worker         *dest++ = *src++;
1608*f6dc9357SAndroid Build Coastguard Worker       while (--back);
1609*f6dc9357SAndroid Build Coastguard Worker       src = dest - offset;
1610*f6dc9357SAndroid Build Coastguard Worker       // src = win;
1611*f6dc9357SAndroid Build Coastguard Worker       // we go to MAIN-COPY
1612*f6dc9357SAndroid Build Coastguard Worker     }
1613*f6dc9357SAndroid Build Coastguard Worker   }
1614*f6dc9357SAndroid Build Coastguard Worker   else
1615*f6dc9357SAndroid Build Coastguard Worker     src = dest - offset;
1616*f6dc9357SAndroid Build Coastguard Worker 
1617*f6dc9357SAndroid Build Coastguard Worker   // len != 0
1618*f6dc9357SAndroid Build Coastguard Worker   // do *dest++ = *src++; while (--len); return;
1619*f6dc9357SAndroid Build Coastguard Worker 
1620*f6dc9357SAndroid Build Coastguard Worker   // --- MAIN COPY ---
1621*f6dc9357SAndroid Build Coastguard Worker   // if (src >= dest), then ((size_t)(src - dest) >= COPY_CHUNK_SIZE)
1622*f6dc9357SAndroid Build Coastguard Worker   //   so we have at least COPY_CHUNK_SIZE space before overlap for writing.
1623*f6dc9357SAndroid Build Coastguard Worker   COPY_PREPARE
1624*f6dc9357SAndroid Build Coastguard Worker 
1625*f6dc9357SAndroid Build Coastguard Worker   /* now (len == COPY_CHUNK_SIZE * x)
1626*f6dc9357SAndroid Build Coastguard Worker      so we can unroll for aligned copy */
1627*f6dc9357SAndroid Build Coastguard Worker   {
1628*f6dc9357SAndroid Build Coastguard Worker     // const unsigned b0 = src[0];
1629*f6dc9357SAndroid Build Coastguard Worker     // (COPY_OFFSET_MIN >= 4)
1630*f6dc9357SAndroid Build Coastguard Worker 
1631*f6dc9357SAndroid Build Coastguard Worker     if (offset >= COPY_OFFSET_MIN)
1632*f6dc9357SAndroid Build Coastguard Worker     {
1633*f6dc9357SAndroid Build Coastguard Worker       COPY_CHUNKS
1634*f6dc9357SAndroid Build Coastguard Worker       // return;
1635*f6dc9357SAndroid Build Coastguard Worker     }
1636*f6dc9357SAndroid Build Coastguard Worker     else
1637*f6dc9357SAndroid Build Coastguard Worker   #if (COPY_OFFSET_MIN > 4)
1638*f6dc9357SAndroid Build Coastguard Worker     #if COPY_CHUNK_SIZE < 8
1639*f6dc9357SAndroid Build Coastguard Worker       #error Stop_Compiling_Bad_COPY_CHUNK_SIZE
1640*f6dc9357SAndroid Build Coastguard Worker     #endif
1641*f6dc9357SAndroid Build Coastguard Worker     if (offset >= 4)
1642*f6dc9357SAndroid Build Coastguard Worker     {
1643*f6dc9357SAndroid Build Coastguard Worker       Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1644*f6dc9357SAndroid Build Coastguard Worker       do
1645*f6dc9357SAndroid Build Coastguard Worker       {
1646*f6dc9357SAndroid Build Coastguard Worker         COPY_CHUNK_4_2(dest, src)
1647*f6dc9357SAndroid Build Coastguard Worker         #if COPY_CHUNK_SIZE != 16
1648*f6dc9357SAndroid Build Coastguard Worker           if (len == 8) break;
1649*f6dc9357SAndroid Build Coastguard Worker         #endif
1650*f6dc9357SAndroid Build Coastguard Worker         COPY_CHUNK_4_2(dest, src)
1651*f6dc9357SAndroid Build Coastguard Worker       }
1652*f6dc9357SAndroid Build Coastguard Worker       while (len -= 16);
1653*f6dc9357SAndroid Build Coastguard Worker       // return;
1654*f6dc9357SAndroid Build Coastguard Worker     }
1655*f6dc9357SAndroid Build Coastguard Worker     else
1656*f6dc9357SAndroid Build Coastguard Worker   #endif
1657*f6dc9357SAndroid Build Coastguard Worker     {
1658*f6dc9357SAndroid Build Coastguard Worker       // (offset < 4)
1659*f6dc9357SAndroid Build Coastguard Worker       const unsigned b0 = src[0];
1660*f6dc9357SAndroid Build Coastguard Worker       if (offset < 2)
1661*f6dc9357SAndroid Build Coastguard Worker       {
1662*f6dc9357SAndroid Build Coastguard Worker       #if defined(Z7_ZSTD_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)
1663*f6dc9357SAndroid Build Coastguard Worker         #if defined(MY_CPU_64BIT)
1664*f6dc9357SAndroid Build Coastguard Worker         {
1665*f6dc9357SAndroid Build Coastguard Worker           const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;
1666*f6dc9357SAndroid Build Coastguard Worker           Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
1667*f6dc9357SAndroid Build Coastguard Worker           do
1668*f6dc9357SAndroid Build Coastguard Worker           {
1669*f6dc9357SAndroid Build Coastguard Worker             ((UInt64 *)(void *)dest)[0] = v64;
1670*f6dc9357SAndroid Build Coastguard Worker             ((UInt64 *)(void *)dest)[1] = v64;
1671*f6dc9357SAndroid Build Coastguard Worker             dest += 16;
1672*f6dc9357SAndroid Build Coastguard Worker           }
1673*f6dc9357SAndroid Build Coastguard Worker           while (len -= 16);
1674*f6dc9357SAndroid Build Coastguard Worker         }
1675*f6dc9357SAndroid Build Coastguard Worker         #else
1676*f6dc9357SAndroid Build Coastguard Worker         {
1677*f6dc9357SAndroid Build Coastguard Worker           UInt32 v = b0;
1678*f6dc9357SAndroid Build Coastguard Worker           v |= v << 8;
1679*f6dc9357SAndroid Build Coastguard Worker           v |= v << 16;
1680*f6dc9357SAndroid Build Coastguard Worker           do
1681*f6dc9357SAndroid Build Coastguard Worker           {
1682*f6dc9357SAndroid Build Coastguard Worker             ((UInt32 *)(void *)dest)[0] = v;
1683*f6dc9357SAndroid Build Coastguard Worker             ((UInt32 *)(void *)dest)[1] = v;
1684*f6dc9357SAndroid Build Coastguard Worker             dest += 8;
1685*f6dc9357SAndroid Build Coastguard Worker             ((UInt32 *)(void *)dest)[0] = v;
1686*f6dc9357SAndroid Build Coastguard Worker             ((UInt32 *)(void *)dest)[1] = v;
1687*f6dc9357SAndroid Build Coastguard Worker             dest += 8;
1688*f6dc9357SAndroid Build Coastguard Worker           }
1689*f6dc9357SAndroid Build Coastguard Worker           while (len -= 16);
1690*f6dc9357SAndroid Build Coastguard Worker         }
1691*f6dc9357SAndroid Build Coastguard Worker         #endif
1692*f6dc9357SAndroid Build Coastguard Worker       #else
1693*f6dc9357SAndroid Build Coastguard Worker         do
1694*f6dc9357SAndroid Build Coastguard Worker         {
1695*f6dc9357SAndroid Build Coastguard Worker           dest[0] = (Byte)b0;
1696*f6dc9357SAndroid Build Coastguard Worker           dest[1] = (Byte)b0;
1697*f6dc9357SAndroid Build Coastguard Worker           dest += 2;
1698*f6dc9357SAndroid Build Coastguard Worker           dest[0] = (Byte)b0;
1699*f6dc9357SAndroid Build Coastguard Worker           dest[1] = (Byte)b0;
1700*f6dc9357SAndroid Build Coastguard Worker           dest += 2;
1701*f6dc9357SAndroid Build Coastguard Worker         }
1702*f6dc9357SAndroid Build Coastguard Worker         while (len -= 4);
1703*f6dc9357SAndroid Build Coastguard Worker       #endif
1704*f6dc9357SAndroid Build Coastguard Worker       }
1705*f6dc9357SAndroid Build Coastguard Worker       else if (offset == 2)
1706*f6dc9357SAndroid Build Coastguard Worker       {
1707*f6dc9357SAndroid Build Coastguard Worker         const Byte b1 = src[1];
1708*f6dc9357SAndroid Build Coastguard Worker         {
1709*f6dc9357SAndroid Build Coastguard Worker           do
1710*f6dc9357SAndroid Build Coastguard Worker           {
1711*f6dc9357SAndroid Build Coastguard Worker             dest[0] = (Byte)b0;
1712*f6dc9357SAndroid Build Coastguard Worker             dest[1] = b1;
1713*f6dc9357SAndroid Build Coastguard Worker             dest += 2;
1714*f6dc9357SAndroid Build Coastguard Worker           }
1715*f6dc9357SAndroid Build Coastguard Worker           while (len -= 2);
1716*f6dc9357SAndroid Build Coastguard Worker         }
1717*f6dc9357SAndroid Build Coastguard Worker       }
1718*f6dc9357SAndroid Build Coastguard Worker       else // (offset == 3)
1719*f6dc9357SAndroid Build Coastguard Worker       {
1720*f6dc9357SAndroid Build Coastguard Worker         const Byte *lim = dest + len - 2;
1721*f6dc9357SAndroid Build Coastguard Worker         const Byte b1 = src[1];
1722*f6dc9357SAndroid Build Coastguard Worker         const Byte b2 = src[2];
1723*f6dc9357SAndroid Build Coastguard Worker         do
1724*f6dc9357SAndroid Build Coastguard Worker         {
1725*f6dc9357SAndroid Build Coastguard Worker           dest[0] = (Byte)b0;
1726*f6dc9357SAndroid Build Coastguard Worker           dest[1] = b1;
1727*f6dc9357SAndroid Build Coastguard Worker           dest[2] = b2;
1728*f6dc9357SAndroid Build Coastguard Worker           dest += 3;
1729*f6dc9357SAndroid Build Coastguard Worker         }
1730*f6dc9357SAndroid Build Coastguard Worker         while (dest < lim);
1731*f6dc9357SAndroid Build Coastguard Worker         lim++; // points to last byte that must be written
1732*f6dc9357SAndroid Build Coastguard Worker         if (dest <= lim)
1733*f6dc9357SAndroid Build Coastguard Worker         {
1734*f6dc9357SAndroid Build Coastguard Worker           *dest = (Byte)b0;
1735*f6dc9357SAndroid Build Coastguard Worker           if (dest != lim)
1736*f6dc9357SAndroid Build Coastguard Worker             dest[1] = b1;
1737*f6dc9357SAndroid Build Coastguard Worker         }
1738*f6dc9357SAndroid Build Coastguard Worker       }
1739*f6dc9357SAndroid Build Coastguard Worker     }
1740*f6dc9357SAndroid Build Coastguard Worker   }
1741*f6dc9357SAndroid Build Coastguard Worker }
1742*f6dc9357SAndroid Build Coastguard Worker 
1743*f6dc9357SAndroid Build Coastguard Worker 
1744*f6dc9357SAndroid Build Coastguard Worker 
1745*f6dc9357SAndroid Build Coastguard Worker #define UPDATE_TOTAL_OUT(p, size) \
1746*f6dc9357SAndroid Build Coastguard Worker { \
1747*f6dc9357SAndroid Build Coastguard Worker   size_t _toc = (p)->totalOutCheck + (size); \
1748*f6dc9357SAndroid Build Coastguard Worker   const size_t _ws = (p)->winSize; \
1749*f6dc9357SAndroid Build Coastguard Worker   if (_toc >= _ws) _toc = _ws; \
1750*f6dc9357SAndroid Build Coastguard Worker   (p)->totalOutCheck = _toc; \
1751*f6dc9357SAndroid Build Coastguard Worker }
1752*f6dc9357SAndroid Build Coastguard Worker 
1753*f6dc9357SAndroid Build Coastguard Worker 
1754*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_64BIT) && defined(MY_CPU_LE_UNALIGN)
1755*f6dc9357SAndroid Build Coastguard Worker // we can disable it for debug:
1756*f6dc9357SAndroid Build Coastguard Worker #define Z7_ZSTD_DEC_USE_64BIT_LOADS
1757*f6dc9357SAndroid Build Coastguard Worker #endif
1758*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_64BIT_LOADS // for debug : slow in 32-bit
1759*f6dc9357SAndroid Build Coastguard Worker 
1760*f6dc9357SAndroid Build Coastguard Worker // SEQ_SRC_OFFSET: how many bytes (src) (seqSrc) was moved back from original value.
1761*f6dc9357SAndroid Build Coastguard Worker // we need (SEQ_SRC_OFFSET != 0) for optimized memory access
1762*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
1763*f6dc9357SAndroid Build Coastguard Worker   #define SEQ_SRC_OFFSET 7
1764*f6dc9357SAndroid Build Coastguard Worker #else
1765*f6dc9357SAndroid Build Coastguard Worker   #define SEQ_SRC_OFFSET 3
1766*f6dc9357SAndroid Build Coastguard Worker #endif
1767*f6dc9357SAndroid Build Coastguard Worker #define SRC_PLUS_FOR_4BYTES(bitOffset)  (SEQ_SRC_OFFSET - 3) + ((CBitCtr_signed)(bitOffset) >> 3)
1768*f6dc9357SAndroid Build Coastguard Worker #define BIT_OFFSET_7BITS(bitOffset)  ((unsigned)(bitOffset) & 7)
1769*f6dc9357SAndroid Build Coastguard Worker /*
1770*f6dc9357SAndroid Build Coastguard Worker   if (BIT_OFFSET_DELTA_BITS == 0) : bitOffset == number_of_unprocessed_bits
1771*f6dc9357SAndroid Build Coastguard Worker   if (BIT_OFFSET_DELTA_BITS == 1) : bitOffset == number_of_unprocessed_bits - 1
1772*f6dc9357SAndroid Build Coastguard Worker       and we can read 1 bit more in that mode : (8 * n + 1).
1773*f6dc9357SAndroid Build Coastguard Worker */
1774*f6dc9357SAndroid Build Coastguard Worker // #define BIT_OFFSET_DELTA_BITS 0
1775*f6dc9357SAndroid Build Coastguard Worker #define BIT_OFFSET_DELTA_BITS 1
1776*f6dc9357SAndroid Build Coastguard Worker #if BIT_OFFSET_DELTA_BITS == 1
1777*f6dc9357SAndroid Build Coastguard Worker   #define GET_SHIFT_FROM_BOFFS7(boff7)  (7 ^ (boff7))
1778*f6dc9357SAndroid Build Coastguard Worker #else
1779*f6dc9357SAndroid Build Coastguard Worker   #define GET_SHIFT_FROM_BOFFS7(boff7)  (8 - BIT_OFFSET_DELTA_BITS - (boff7))
1780*f6dc9357SAndroid Build Coastguard Worker #endif
1781*f6dc9357SAndroid Build Coastguard Worker 
1782*f6dc9357SAndroid Build Coastguard Worker #define UPDATE_BIT_OFFSET(bitOffset, numBits) \
1783*f6dc9357SAndroid Build Coastguard Worker     (bitOffset) -= (CBitCtr)(numBits);
1784*f6dc9357SAndroid Build Coastguard Worker 
1785*f6dc9357SAndroid Build Coastguard Worker #define GET_SHIFT(bitOffset)  GET_SHIFT_FROM_BOFFS7(BIT_OFFSET_7BITS(bitOffset))
1786*f6dc9357SAndroid Build Coastguard Worker 
1787*f6dc9357SAndroid Build Coastguard Worker 
1788*f6dc9357SAndroid Build Coastguard Worker #if defined(Z7_ZSTD_DEC_USE_64BIT_LOADS)
1789*f6dc9357SAndroid Build Coastguard Worker   #if (NUM_OFFSET_SYMBOLS_MAX - BIT_OFFSET_DELTA_BITS < 32)
1790*f6dc9357SAndroid Build Coastguard Worker     /* if (NUM_OFFSET_SYMBOLS_MAX == 32 && BIT_OFFSET_DELTA_BITS == 1),
1791*f6dc9357SAndroid Build Coastguard Worker        we have depth 31 + 9 + 9 + 8 = 57 bits that can b read with single read. */
1792*f6dc9357SAndroid Build Coastguard Worker     #define Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
1793*f6dc9357SAndroid Build Coastguard Worker   #endif
1794*f6dc9357SAndroid Build Coastguard Worker   #ifndef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
1795*f6dc9357SAndroid Build Coastguard Worker     #if (BIT_OFFSET_DELTA_BITS == 1)
1796*f6dc9357SAndroid Build Coastguard Worker     /* if (winLimit - winPos <= (kBlockSizeMax = (1 << 17)))
1797*f6dc9357SAndroid Build Coastguard Worker        {
1798*f6dc9357SAndroid Build Coastguard Worker          the case (16 bits literal extra + 16 match extra) is not possible
1799*f6dc9357SAndroid Build Coastguard Worker          in correct stream. So error will be detected for (16 + 16) case.
1800*f6dc9357SAndroid Build Coastguard Worker          And longest correct sequence after offset reading is (31 + 9 + 9 + 8 = 57 bits).
1801*f6dc9357SAndroid Build Coastguard Worker          So we can use just one 64-bit load here in that case.
1802*f6dc9357SAndroid Build Coastguard Worker        }
1803*f6dc9357SAndroid Build Coastguard Worker     */
1804*f6dc9357SAndroid Build Coastguard Worker     #define Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML
1805*f6dc9357SAndroid Build Coastguard Worker     #endif
1806*f6dc9357SAndroid Build Coastguard Worker   #endif
1807*f6dc9357SAndroid Build Coastguard Worker #endif
1808*f6dc9357SAndroid Build Coastguard Worker 
1809*f6dc9357SAndroid Build Coastguard Worker 
1810*f6dc9357SAndroid Build Coastguard Worker #if !defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) || \
1811*f6dc9357SAndroid Build Coastguard Worker     (!defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) && \
1812*f6dc9357SAndroid Build Coastguard Worker      !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML))
1813*f6dc9357SAndroid Build Coastguard Worker // in : (0 < bits <= (24 or 25)):
1814*f6dc9357SAndroid Build Coastguard Worker #define STREAM_READ_BITS(dest, bits) \
1815*f6dc9357SAndroid Build Coastguard Worker { \
1816*f6dc9357SAndroid Build Coastguard Worker   GET32(dest, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1817*f6dc9357SAndroid Build Coastguard Worker   dest <<= GET_SHIFT(bitOffset); \
1818*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1819*f6dc9357SAndroid Build Coastguard Worker   dest >>= 32 - bits; \
1820*f6dc9357SAndroid Build Coastguard Worker }
1821*f6dc9357SAndroid Build Coastguard Worker #endif
1822*f6dc9357SAndroid Build Coastguard Worker 
1823*f6dc9357SAndroid Build Coastguard Worker 
1824*f6dc9357SAndroid Build Coastguard Worker #define FSE_Peek_1(table, state)  table[state]
1825*f6dc9357SAndroid Build Coastguard Worker 
1826*f6dc9357SAndroid Build Coastguard Worker #define STATE_VAR(name)  state_ ## name
1827*f6dc9357SAndroid Build Coastguard Worker 
1828*f6dc9357SAndroid Build Coastguard Worker // in : (0 <= accuracy <= (24 or 25))
1829*f6dc9357SAndroid Build Coastguard Worker #define FSE_INIT_STATE(name, cond) \
1830*f6dc9357SAndroid Build Coastguard Worker { \
1831*f6dc9357SAndroid Build Coastguard Worker   UInt32 r; \
1832*f6dc9357SAndroid Build Coastguard Worker   const unsigned bits = p->name ## _accuracy; \
1833*f6dc9357SAndroid Build Coastguard Worker   GET32(r, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1834*f6dc9357SAndroid Build Coastguard Worker   r <<= GET_SHIFT(bitOffset); \
1835*f6dc9357SAndroid Build Coastguard Worker   r >>= 1; \
1836*f6dc9357SAndroid Build Coastguard Worker   r >>= 31 ^ bits; \
1837*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1838*f6dc9357SAndroid Build Coastguard Worker   cond \
1839*f6dc9357SAndroid Build Coastguard Worker   STATE_VAR(name) = FSE_Peek_1(FSE_TABLE(name), r); \
1840*f6dc9357SAndroid Build Coastguard Worker   /* STATE_VAR(name) = dest << 16; */ \
1841*f6dc9357SAndroid Build Coastguard Worker }
1842*f6dc9357SAndroid Build Coastguard Worker 
1843*f6dc9357SAndroid Build Coastguard Worker 
1844*f6dc9357SAndroid Build Coastguard Worker #define FSE_Peek_Plus(name, r)  \
1845*f6dc9357SAndroid Build Coastguard Worker   STATE_VAR(name) = FSE_Peek_1(FSE_TABLE(name), \
1846*f6dc9357SAndroid Build Coastguard Worker     GET_FSE_REC_STATE(STATE_VAR(name)) + r);
1847*f6dc9357SAndroid Build Coastguard Worker 
1848*f6dc9357SAndroid Build Coastguard Worker #define LZ_LOOP_ERROR_EXIT  { return SZ_ERROR_DATA; }
1849*f6dc9357SAndroid Build Coastguard Worker 
1850*f6dc9357SAndroid Build Coastguard Worker #define BO_OVERFLOW_CHECK \
1851*f6dc9357SAndroid Build Coastguard Worker   { if ((CBitCtr_signed)bitOffset < 0) LZ_LOOP_ERROR_EXIT }
1852*f6dc9357SAndroid Build Coastguard Worker 
1853*f6dc9357SAndroid Build Coastguard Worker 
1854*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
1855*f6dc9357SAndroid Build Coastguard Worker 
1856*f6dc9357SAndroid Build Coastguard Worker #define GET64(dest, p)  { const Byte *ptr = p;  dest = GetUi64(ptr); }
1857*f6dc9357SAndroid Build Coastguard Worker 
1858*f6dc9357SAndroid Build Coastguard Worker #define FSE_PRELOAD \
1859*f6dc9357SAndroid Build Coastguard Worker { \
1860*f6dc9357SAndroid Build Coastguard Worker   GET64(v, src - 4 + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1861*f6dc9357SAndroid Build Coastguard Worker   v <<= GET_SHIFT(bitOffset); \
1862*f6dc9357SAndroid Build Coastguard Worker }
1863*f6dc9357SAndroid Build Coastguard Worker 
1864*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATE_2(name, cond) \
1865*f6dc9357SAndroid Build Coastguard Worker { \
1866*f6dc9357SAndroid Build Coastguard Worker   const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1867*f6dc9357SAndroid Build Coastguard Worker   UInt64 r = v; \
1868*f6dc9357SAndroid Build Coastguard Worker   v <<= bits; \
1869*f6dc9357SAndroid Build Coastguard Worker   r >>= 1; \
1870*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1871*f6dc9357SAndroid Build Coastguard Worker   cond \
1872*f6dc9357SAndroid Build Coastguard Worker   r >>= 63 ^ bits; \
1873*f6dc9357SAndroid Build Coastguard Worker   FSE_Peek_Plus(name, r); \
1874*f6dc9357SAndroid Build Coastguard Worker }
1875*f6dc9357SAndroid Build Coastguard Worker 
1876*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATES \
1877*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_2 (ll, {} ) \
1878*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_2 (ml, {} ) \
1879*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_2 (of, BO_OVERFLOW_CHECK) \
1880*f6dc9357SAndroid Build Coastguard Worker 
1881*f6dc9357SAndroid Build Coastguard Worker #else // Z7_ZSTD_DEC_USE_64BIT_LOADS
1882*f6dc9357SAndroid Build Coastguard Worker 
1883*f6dc9357SAndroid Build Coastguard Worker // it supports 8 bits accuracy for any code
1884*f6dc9357SAndroid Build Coastguard Worker // it supports 9 bits accuracy, if (BIT_OFFSET_DELTA_BITS == 1)
1885*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATE_0(name, cond) \
1886*f6dc9357SAndroid Build Coastguard Worker { \
1887*f6dc9357SAndroid Build Coastguard Worker   UInt32 r; \
1888*f6dc9357SAndroid Build Coastguard Worker   const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1889*f6dc9357SAndroid Build Coastguard Worker   GET16(r, src + 2 + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1890*f6dc9357SAndroid Build Coastguard Worker   r >>= (bitOffset & 7); \
1891*f6dc9357SAndroid Build Coastguard Worker   r &= (1 << (8 + BIT_OFFSET_DELTA_BITS)) - 1; \
1892*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1893*f6dc9357SAndroid Build Coastguard Worker   cond \
1894*f6dc9357SAndroid Build Coastguard Worker   r >>= (8 + BIT_OFFSET_DELTA_BITS) - bits; \
1895*f6dc9357SAndroid Build Coastguard Worker   FSE_Peek_Plus(name, r); \
1896*f6dc9357SAndroid Build Coastguard Worker }
1897*f6dc9357SAndroid Build Coastguard Worker 
1898*f6dc9357SAndroid Build Coastguard Worker // for debug (slow):
1899*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_FSE_FUSION_FORCE
1900*f6dc9357SAndroid Build Coastguard Worker #if BIT_OFFSET_DELTA_BITS == 0 || defined(Z7_ZSTD_DEC_USE_FSE_FUSION_FORCE)
1901*f6dc9357SAndroid Build Coastguard Worker   #define Z7_ZSTD_DEC_USE_FSE_FUSION
1902*f6dc9357SAndroid Build Coastguard Worker #endif
1903*f6dc9357SAndroid Build Coastguard Worker 
1904*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_FSE_FUSION
1905*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATE_1(name) \
1906*f6dc9357SAndroid Build Coastguard Worker { UInt32 rest2; \
1907*f6dc9357SAndroid Build Coastguard Worker { \
1908*f6dc9357SAndroid Build Coastguard Worker   UInt32 r; \
1909*f6dc9357SAndroid Build Coastguard Worker   unsigned bits; \
1910*f6dc9357SAndroid Build Coastguard Worker   GET32(r, src + SRC_PLUS_FOR_4BYTES(bitOffset)) \
1911*f6dc9357SAndroid Build Coastguard Worker   bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1912*f6dc9357SAndroid Build Coastguard Worker   r <<= GET_SHIFT(bitOffset); \
1913*f6dc9357SAndroid Build Coastguard Worker   rest2 = r << bits; \
1914*f6dc9357SAndroid Build Coastguard Worker   r >>= 1; \
1915*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1916*f6dc9357SAndroid Build Coastguard Worker   r >>= 31 ^ bits; \
1917*f6dc9357SAndroid Build Coastguard Worker   FSE_Peek_Plus(name, r); \
1918*f6dc9357SAndroid Build Coastguard Worker }
1919*f6dc9357SAndroid Build Coastguard Worker 
1920*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATE_3(name) \
1921*f6dc9357SAndroid Build Coastguard Worker { \
1922*f6dc9357SAndroid Build Coastguard Worker   const unsigned bits = GET_FSE_REC_LEN(STATE_VAR(name)); \
1923*f6dc9357SAndroid Build Coastguard Worker   rest2 >>= 1; \
1924*f6dc9357SAndroid Build Coastguard Worker   UPDATE_BIT_OFFSET(bitOffset, bits) \
1925*f6dc9357SAndroid Build Coastguard Worker   rest2 >>= 31 ^ bits; \
1926*f6dc9357SAndroid Build Coastguard Worker   FSE_Peek_Plus(name, rest2); \
1927*f6dc9357SAndroid Build Coastguard Worker }}
1928*f6dc9357SAndroid Build Coastguard Worker 
1929*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATES \
1930*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_1 (ll) \
1931*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_3 (ml) \
1932*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_0 (of, BO_OVERFLOW_CHECK) \
1933*f6dc9357SAndroid Build Coastguard Worker 
1934*f6dc9357SAndroid Build Coastguard Worker #else // Z7_ZSTD_DEC_USE_64BIT_LOADS
1935*f6dc9357SAndroid Build Coastguard Worker 
1936*f6dc9357SAndroid Build Coastguard Worker #define FSE_UPDATE_STATES \
1937*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_0 (ll, {} ) \
1938*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_0 (ml, {} ) \
1939*f6dc9357SAndroid Build Coastguard Worker   FSE_UPDATE_STATE_0 (of, BO_OVERFLOW_CHECK) \
1940*f6dc9357SAndroid Build Coastguard Worker 
1941*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_ZSTD_DEC_USE_FSE_FUSION
1942*f6dc9357SAndroid Build Coastguard Worker #endif // Z7_ZSTD_DEC_USE_64BIT_LOADS
1943*f6dc9357SAndroid Build Coastguard Worker 
1944*f6dc9357SAndroid Build Coastguard Worker 
1945*f6dc9357SAndroid Build Coastguard Worker 
1946*f6dc9357SAndroid Build Coastguard Worker typedef struct
1947*f6dc9357SAndroid Build Coastguard Worker {
1948*f6dc9357SAndroid Build Coastguard Worker   UInt32 numSeqs;
1949*f6dc9357SAndroid Build Coastguard Worker   UInt32 literalsLen;
1950*f6dc9357SAndroid Build Coastguard Worker   const Byte *literals;
1951*f6dc9357SAndroid Build Coastguard Worker }
1952*f6dc9357SAndroid Build Coastguard Worker CZstdDec1_Vars;
1953*f6dc9357SAndroid Build Coastguard Worker 
1954*f6dc9357SAndroid Build Coastguard Worker 
1955*f6dc9357SAndroid Build Coastguard Worker // if (BIT_OFFSET_DELTA_BITS != 0), we need (BIT_OFFSET_DELTA_BYTES > 0)
1956*f6dc9357SAndroid Build Coastguard Worker #define BIT_OFFSET_DELTA_BYTES   BIT_OFFSET_DELTA_BITS
1957*f6dc9357SAndroid Build Coastguard Worker 
1958*f6dc9357SAndroid Build Coastguard Worker /* if (NUM_OFFSET_SYMBOLS_MAX == 32)
1959*f6dc9357SAndroid Build Coastguard Worker      max_seq_bit_length = (31) + 16 + 16 + 9 + 8 + 9 = 89 bits
1960*f6dc9357SAndroid Build Coastguard Worker    if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) we have longest backward
1961*f6dc9357SAndroid Build Coastguard Worker      lookahead offset, and we read UInt64 after literal_len reading.
1962*f6dc9357SAndroid Build Coastguard Worker    if (BIT_OFFSET_DELTA_BITS == 1 && NUM_OFFSET_SYMBOLS_MAX == 32)
1963*f6dc9357SAndroid Build Coastguard Worker      MAX_BACKWARD_DEPTH = 16 bytes
1964*f6dc9357SAndroid Build Coastguard Worker */
1965*f6dc9357SAndroid Build Coastguard Worker #define MAX_BACKWARD_DEPTH  \
1966*f6dc9357SAndroid Build Coastguard Worker     ((NUM_OFFSET_SYMBOLS_MAX - 1 + 16 + 16 + 7) / 8 + 7 + BIT_OFFSET_DELTA_BYTES)
1967*f6dc9357SAndroid Build Coastguard Worker 
1968*f6dc9357SAndroid Build Coastguard Worker /* srcLen != 0
1969*f6dc9357SAndroid Build Coastguard Worker    src == real_data_ptr - SEQ_SRC_OFFSET - BIT_OFFSET_DELTA_BYTES
1970*f6dc9357SAndroid Build Coastguard Worker    if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML) then
1971*f6dc9357SAndroid Build Coastguard Worker      (winLimit - p->winPos <= (1 << 17)) is required
1972*f6dc9357SAndroid Build Coastguard Worker */
1973*f6dc9357SAndroid Build Coastguard Worker static
1974*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
1975*f6dc9357SAndroid Build Coastguard Worker // Z7_ATTRIB_NO_VECTOR
1976*f6dc9357SAndroid Build Coastguard Worker SRes Decompress_Sequences(CZstdDec1 * const p,
1977*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, const size_t srcLen,
1978*f6dc9357SAndroid Build Coastguard Worker     const size_t winLimit,
1979*f6dc9357SAndroid Build Coastguard Worker     const CZstdDec1_Vars * const vars)
1980*f6dc9357SAndroid Build Coastguard Worker {
1981*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_BASES_LOCAL
1982*f6dc9357SAndroid Build Coastguard Worker   SEQ_EXTRA_TABLES(a_)
1983*f6dc9357SAndroid Build Coastguard Worker #endif
1984*f6dc9357SAndroid Build Coastguard Worker 
1985*f6dc9357SAndroid Build Coastguard Worker   // for debug:
1986*f6dc9357SAndroid Build Coastguard Worker   // #define Z7_ZSTD_DEC_USE_LOCAL_FSE_TABLES
1987*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_LOCAL_FSE_TABLES
1988*f6dc9357SAndroid Build Coastguard Worker   #define FSE_TABLE(n)  fse. n
1989*f6dc9357SAndroid Build Coastguard Worker   const CZstdDecFseTables fse = p->fse;
1990*f6dc9357SAndroid Build Coastguard Worker   /*
1991*f6dc9357SAndroid Build Coastguard Worker   CZstdDecFseTables fse;
1992*f6dc9357SAndroid Build Coastguard Worker   #define COPY_FSE_TABLE(n) \
1993*f6dc9357SAndroid Build Coastguard Worker     memcpy(fse. n, p->fse. n, (size_t)4 << p-> n ## _accuracy);
1994*f6dc9357SAndroid Build Coastguard Worker   COPY_FSE_TABLE(of)
1995*f6dc9357SAndroid Build Coastguard Worker   COPY_FSE_TABLE(ll)
1996*f6dc9357SAndroid Build Coastguard Worker   COPY_FSE_TABLE(ml)
1997*f6dc9357SAndroid Build Coastguard Worker   */
1998*f6dc9357SAndroid Build Coastguard Worker #else
1999*f6dc9357SAndroid Build Coastguard Worker   #define FSE_TABLE(n)  (p->fse.  n)
2000*f6dc9357SAndroid Build Coastguard Worker #endif
2001*f6dc9357SAndroid Build Coastguard Worker 
2002*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_BASES_LOCAL
2003*f6dc9357SAndroid Build Coastguard Worker   FILL_LOC_BASES_ALL
2004*f6dc9357SAndroid Build Coastguard Worker #endif
2005*f6dc9357SAndroid Build Coastguard Worker 
2006*f6dc9357SAndroid Build Coastguard Worker   {
2007*f6dc9357SAndroid Build Coastguard Worker     unsigned numSeqs = vars->numSeqs;
2008*f6dc9357SAndroid Build Coastguard Worker     const Byte *literals = vars->literals;
2009*f6dc9357SAndroid Build Coastguard Worker     ptrdiff_t literalsLen = (ptrdiff_t)vars->literalsLen;
2010*f6dc9357SAndroid Build Coastguard Worker     Byte * const win = p->win;
2011*f6dc9357SAndroid Build Coastguard Worker     size_t winPos = p->winPos;
2012*f6dc9357SAndroid Build Coastguard Worker     const size_t cycSize = p->cycSize;
2013*f6dc9357SAndroid Build Coastguard Worker     size_t totalOutCheck = p->totalOutCheck;
2014*f6dc9357SAndroid Build Coastguard Worker     const size_t winSize = p->winSize;
2015*f6dc9357SAndroid Build Coastguard Worker     size_t reps_0 = p->reps[0];
2016*f6dc9357SAndroid Build Coastguard Worker     size_t reps_1 = p->reps[1];
2017*f6dc9357SAndroid Build Coastguard Worker     size_t reps_2 = p->reps[2];
2018*f6dc9357SAndroid Build Coastguard Worker     UInt32 STATE_VAR(ll), STATE_VAR(of), STATE_VAR(ml);
2019*f6dc9357SAndroid Build Coastguard Worker     CBitCtr bitOffset;
2020*f6dc9357SAndroid Build Coastguard Worker 
2021*f6dc9357SAndroid Build Coastguard Worker     SET_bitOffset_TO_PAD (bitOffset, src + SEQ_SRC_OFFSET, srcLen + BIT_OFFSET_DELTA_BYTES)
2022*f6dc9357SAndroid Build Coastguard Worker 
2023*f6dc9357SAndroid Build Coastguard Worker     bitOffset -= BIT_OFFSET_DELTA_BITS;
2024*f6dc9357SAndroid Build Coastguard Worker 
2025*f6dc9357SAndroid Build Coastguard Worker     FSE_INIT_STATE(ll, {} )
2026*f6dc9357SAndroid Build Coastguard Worker     FSE_INIT_STATE(of, {} )
2027*f6dc9357SAndroid Build Coastguard Worker     FSE_INIT_STATE(ml, BO_OVERFLOW_CHECK)
2028*f6dc9357SAndroid Build Coastguard Worker 
2029*f6dc9357SAndroid Build Coastguard Worker     for (;;)
2030*f6dc9357SAndroid Build Coastguard Worker     {
2031*f6dc9357SAndroid Build Coastguard Worker       size_t matchLen;
2032*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2033*f6dc9357SAndroid Build Coastguard Worker       UInt64 v;
2034*f6dc9357SAndroid Build Coastguard Worker     #endif
2035*f6dc9357SAndroid Build Coastguard Worker 
2036*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF
2037*f6dc9357SAndroid Build Coastguard Worker         FSE_PRELOAD
2038*f6dc9357SAndroid Build Coastguard Worker       #endif
2039*f6dc9357SAndroid Build Coastguard Worker 
2040*f6dc9357SAndroid Build Coastguard Worker       // if (of_code == 0)
2041*f6dc9357SAndroid Build Coastguard Worker       if ((Byte)STATE_VAR(of) == 0)
2042*f6dc9357SAndroid Build Coastguard Worker       {
2043*f6dc9357SAndroid Build Coastguard Worker         if (GET_FSE_REC_SYM(STATE_VAR(ll)) == 0)
2044*f6dc9357SAndroid Build Coastguard Worker         {
2045*f6dc9357SAndroid Build Coastguard Worker           const size_t offset = reps_1;
2046*f6dc9357SAndroid Build Coastguard Worker           reps_1 = reps_0;
2047*f6dc9357SAndroid Build Coastguard Worker           reps_0 = offset;
2048*f6dc9357SAndroid Build Coastguard Worker           STAT_INC(g_Num_Rep1)
2049*f6dc9357SAndroid Build Coastguard Worker         }
2050*f6dc9357SAndroid Build Coastguard Worker         STAT_UPDATE(else g_Num_Rep0++;)
2051*f6dc9357SAndroid Build Coastguard Worker       }
2052*f6dc9357SAndroid Build Coastguard Worker       else
2053*f6dc9357SAndroid Build Coastguard Worker       {
2054*f6dc9357SAndroid Build Coastguard Worker         const unsigned of_code = (Byte)STATE_VAR(of);
2055*f6dc9357SAndroid Build Coastguard Worker 
2056*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2057*f6dc9357SAndroid Build Coastguard Worker         #if !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2058*f6dc9357SAndroid Build Coastguard Worker           FSE_PRELOAD
2059*f6dc9357SAndroid Build Coastguard Worker         #endif
2060*f6dc9357SAndroid Build Coastguard Worker       #else
2061*f6dc9357SAndroid Build Coastguard Worker         UInt32 v;
2062*f6dc9357SAndroid Build Coastguard Worker         {
2063*f6dc9357SAndroid Build Coastguard Worker           const Byte *src4 = src + SRC_PLUS_FOR_4BYTES(bitOffset);
2064*f6dc9357SAndroid Build Coastguard Worker           const unsigned skip = GET_SHIFT(bitOffset);
2065*f6dc9357SAndroid Build Coastguard Worker           GET32(v, src4)
2066*f6dc9357SAndroid Build Coastguard Worker           v <<= skip;
2067*f6dc9357SAndroid Build Coastguard Worker           v |= (UInt32)src4[-1] >> (8 - skip);
2068*f6dc9357SAndroid Build Coastguard Worker         }
2069*f6dc9357SAndroid Build Coastguard Worker       #endif
2070*f6dc9357SAndroid Build Coastguard Worker 
2071*f6dc9357SAndroid Build Coastguard Worker         UPDATE_BIT_OFFSET(bitOffset, of_code)
2072*f6dc9357SAndroid Build Coastguard Worker 
2073*f6dc9357SAndroid Build Coastguard Worker         if (of_code == 1)
2074*f6dc9357SAndroid Build Coastguard Worker         {
2075*f6dc9357SAndroid Build Coastguard Worker           // read 1 bit
2076*f6dc9357SAndroid Build Coastguard Worker           #if defined(Z7_MSC_VER_ORIGINAL) || defined(MY_CPU_X86_OR_AMD64)
2077*f6dc9357SAndroid Build Coastguard Worker             #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2078*f6dc9357SAndroid Build Coastguard Worker               #define CHECK_HIGH_BIT_64(a)  ((Int64)(UInt64)(a) < 0)
2079*f6dc9357SAndroid Build Coastguard Worker             #else
2080*f6dc9357SAndroid Build Coastguard Worker               #define CHECK_HIGH_BIT_32(a)  ((Int32)(UInt32)(a) < 0)
2081*f6dc9357SAndroid Build Coastguard Worker             #endif
2082*f6dc9357SAndroid Build Coastguard Worker           #else
2083*f6dc9357SAndroid Build Coastguard Worker             #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2084*f6dc9357SAndroid Build Coastguard Worker               #define CHECK_HIGH_BIT_64(a)  ((UInt64)(a) & ((UInt64)1 << 63))
2085*f6dc9357SAndroid Build Coastguard Worker             #else
2086*f6dc9357SAndroid Build Coastguard Worker               #define CHECK_HIGH_BIT_32(a)  ((UInt32)(a) & ((UInt32)1 << 31))
2087*f6dc9357SAndroid Build Coastguard Worker             #endif
2088*f6dc9357SAndroid Build Coastguard Worker           #endif
2089*f6dc9357SAndroid Build Coastguard Worker 
2090*f6dc9357SAndroid Build Coastguard Worker           if
2091*f6dc9357SAndroid Build Coastguard Worker             #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2092*f6dc9357SAndroid Build Coastguard Worker               CHECK_HIGH_BIT_64 (((UInt64)GET_FSE_REC_SYM(STATE_VAR(ll)) - 1) ^ v)
2093*f6dc9357SAndroid Build Coastguard Worker             #else
2094*f6dc9357SAndroid Build Coastguard Worker               CHECK_HIGH_BIT_32 (((UInt32)GET_FSE_REC_SYM(STATE_VAR(ll)) - 1) ^ v)
2095*f6dc9357SAndroid Build Coastguard Worker             #endif
2096*f6dc9357SAndroid Build Coastguard Worker           {
2097*f6dc9357SAndroid Build Coastguard Worker             v <<= 1;
2098*f6dc9357SAndroid Build Coastguard Worker             {
2099*f6dc9357SAndroid Build Coastguard Worker               const size_t offset = reps_2;
2100*f6dc9357SAndroid Build Coastguard Worker               reps_2 = reps_1;
2101*f6dc9357SAndroid Build Coastguard Worker               reps_1 = reps_0;
2102*f6dc9357SAndroid Build Coastguard Worker               reps_0 = offset;
2103*f6dc9357SAndroid Build Coastguard Worker               STAT_INC(g_Num_Rep2)
2104*f6dc9357SAndroid Build Coastguard Worker             }
2105*f6dc9357SAndroid Build Coastguard Worker           }
2106*f6dc9357SAndroid Build Coastguard Worker           else
2107*f6dc9357SAndroid Build Coastguard Worker           {
2108*f6dc9357SAndroid Build Coastguard Worker             if (GET_FSE_REC_SYM(STATE_VAR(ll)) == 0)
2109*f6dc9357SAndroid Build Coastguard Worker             {
2110*f6dc9357SAndroid Build Coastguard Worker               // litLen == 0 && bit == 1
2111*f6dc9357SAndroid Build Coastguard Worker               STAT_INC(g_Num_Rep3)
2112*f6dc9357SAndroid Build Coastguard Worker               v <<= 1;
2113*f6dc9357SAndroid Build Coastguard Worker               reps_2 = reps_1;
2114*f6dc9357SAndroid Build Coastguard Worker               reps_1 = reps_0;
2115*f6dc9357SAndroid Build Coastguard Worker               if (--reps_0 == 0)
2116*f6dc9357SAndroid Build Coastguard Worker               {
2117*f6dc9357SAndroid Build Coastguard Worker                 // LZ_LOOP_ERROR_EXIT
2118*f6dc9357SAndroid Build Coastguard Worker                 // original-zstd decoder : input is corrupted; force offset to 1
2119*f6dc9357SAndroid Build Coastguard Worker                 // reps_0 = 1;
2120*f6dc9357SAndroid Build Coastguard Worker                 reps_0++;
2121*f6dc9357SAndroid Build Coastguard Worker               }
2122*f6dc9357SAndroid Build Coastguard Worker             }
2123*f6dc9357SAndroid Build Coastguard Worker             else
2124*f6dc9357SAndroid Build Coastguard Worker             {
2125*f6dc9357SAndroid Build Coastguard Worker               // litLen != 0 && bit == 0
2126*f6dc9357SAndroid Build Coastguard Worker               v <<= 1;
2127*f6dc9357SAndroid Build Coastguard Worker               {
2128*f6dc9357SAndroid Build Coastguard Worker                 const size_t offset = reps_1;
2129*f6dc9357SAndroid Build Coastguard Worker                 reps_1 = reps_0;
2130*f6dc9357SAndroid Build Coastguard Worker                 reps_0 = offset;
2131*f6dc9357SAndroid Build Coastguard Worker                 STAT_INC(g_Num_Rep1)
2132*f6dc9357SAndroid Build Coastguard Worker               }
2133*f6dc9357SAndroid Build Coastguard Worker             }
2134*f6dc9357SAndroid Build Coastguard Worker           }
2135*f6dc9357SAndroid Build Coastguard Worker         }
2136*f6dc9357SAndroid Build Coastguard Worker         else
2137*f6dc9357SAndroid Build Coastguard Worker         {
2138*f6dc9357SAndroid Build Coastguard Worker           // (2 <= of_code)
2139*f6dc9357SAndroid Build Coastguard Worker           // if (of_code >= 32) LZ_LOOP_ERROR_EXIT // optional check
2140*f6dc9357SAndroid Build Coastguard Worker           // we don't allow (of_code >= 32) cases in another code
2141*f6dc9357SAndroid Build Coastguard Worker           reps_2 = reps_1;
2142*f6dc9357SAndroid Build Coastguard Worker           reps_1 = reps_0;
2143*f6dc9357SAndroid Build Coastguard Worker           reps_0 = ((size_t)1 << of_code) - 3 + (size_t)
2144*f6dc9357SAndroid Build Coastguard Worker             #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2145*f6dc9357SAndroid Build Coastguard Worker               (v >> (64 - of_code));
2146*f6dc9357SAndroid Build Coastguard Worker               v <<= of_code;
2147*f6dc9357SAndroid Build Coastguard Worker             #else
2148*f6dc9357SAndroid Build Coastguard Worker               (v >> (32 - of_code));
2149*f6dc9357SAndroid Build Coastguard Worker             #endif
2150*f6dc9357SAndroid Build Coastguard Worker         }
2151*f6dc9357SAndroid Build Coastguard Worker       }
2152*f6dc9357SAndroid Build Coastguard Worker 
2153*f6dc9357SAndroid Build Coastguard Worker       #ifdef Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML
2154*f6dc9357SAndroid Build Coastguard Worker         FSE_PRELOAD
2155*f6dc9357SAndroid Build Coastguard Worker       #endif
2156*f6dc9357SAndroid Build Coastguard Worker 
2157*f6dc9357SAndroid Build Coastguard Worker       matchLen = (size_t)GET_FSE_REC_SYM(STATE_VAR(ml))
2158*f6dc9357SAndroid Build Coastguard Worker           #ifndef Z7_ZSTD_DEC_USE_ML_PLUS3
2159*f6dc9357SAndroid Build Coastguard Worker             + MATCH_LEN_MIN
2160*f6dc9357SAndroid Build Coastguard Worker           #endif
2161*f6dc9357SAndroid Build Coastguard Worker           ;
2162*f6dc9357SAndroid Build Coastguard Worker       {
2163*f6dc9357SAndroid Build Coastguard Worker         {
2164*f6dc9357SAndroid Build Coastguard Worker           if (matchLen >= 32 + MATCH_LEN_MIN) // if (state_ml & 0x20)
2165*f6dc9357SAndroid Build Coastguard Worker           {
2166*f6dc9357SAndroid Build Coastguard Worker             const unsigned extra = BASES_TABLE(SEQ_ML_EXTRA) [(size_t)matchLen - MATCH_LEN_MIN];
2167*f6dc9357SAndroid Build Coastguard Worker             matchLen = BASES_TABLE(SEQ_ML_BASES) [(size_t)matchLen - MATCH_LEN_MIN];
2168*f6dc9357SAndroid Build Coastguard Worker             #if defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) && \
2169*f6dc9357SAndroid Build Coastguard Worker                (defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML) || \
2170*f6dc9357SAndroid Build Coastguard Worker                 defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF))
2171*f6dc9357SAndroid Build Coastguard Worker             {
2172*f6dc9357SAndroid Build Coastguard Worker               UPDATE_BIT_OFFSET(bitOffset, extra)
2173*f6dc9357SAndroid Build Coastguard Worker               matchLen += (size_t)(v >> (64 - extra));
2174*f6dc9357SAndroid Build Coastguard Worker               #if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2175*f6dc9357SAndroid Build Coastguard Worker                 FSE_PRELOAD
2176*f6dc9357SAndroid Build Coastguard Worker               #else
2177*f6dc9357SAndroid Build Coastguard Worker                 v <<= extra;
2178*f6dc9357SAndroid Build Coastguard Worker               #endif
2179*f6dc9357SAndroid Build Coastguard Worker             }
2180*f6dc9357SAndroid Build Coastguard Worker             #else
2181*f6dc9357SAndroid Build Coastguard Worker             {
2182*f6dc9357SAndroid Build Coastguard Worker               UInt32 v32;
2183*f6dc9357SAndroid Build Coastguard Worker               STREAM_READ_BITS(v32, extra)
2184*f6dc9357SAndroid Build Coastguard Worker               matchLen += v32;
2185*f6dc9357SAndroid Build Coastguard Worker             }
2186*f6dc9357SAndroid Build Coastguard Worker             #endif
2187*f6dc9357SAndroid Build Coastguard Worker             STAT_INC(g_Num_Match)
2188*f6dc9357SAndroid Build Coastguard Worker           }
2189*f6dc9357SAndroid Build Coastguard Worker         }
2190*f6dc9357SAndroid Build Coastguard Worker       }
2191*f6dc9357SAndroid Build Coastguard Worker 
2192*f6dc9357SAndroid Build Coastguard Worker       #if  defined(Z7_ZSTD_DEC_USE_64BIT_LOADS) && \
2193*f6dc9357SAndroid Build Coastguard Worker           !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF) && \
2194*f6dc9357SAndroid Build Coastguard Worker           !defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_ML)
2195*f6dc9357SAndroid Build Coastguard Worker         FSE_PRELOAD
2196*f6dc9357SAndroid Build Coastguard Worker       #endif
2197*f6dc9357SAndroid Build Coastguard Worker 
2198*f6dc9357SAndroid Build Coastguard Worker       {
2199*f6dc9357SAndroid Build Coastguard Worker         size_t litLen = GET_FSE_REC_SYM(STATE_VAR(ll));
2200*f6dc9357SAndroid Build Coastguard Worker         if (litLen)
2201*f6dc9357SAndroid Build Coastguard Worker         {
2202*f6dc9357SAndroid Build Coastguard Worker           // if (STATE_VAR(ll) & 0x70)
2203*f6dc9357SAndroid Build Coastguard Worker           if (litLen >= 16)
2204*f6dc9357SAndroid Build Coastguard Worker           {
2205*f6dc9357SAndroid Build Coastguard Worker             const unsigned extra = BASES_TABLE(SEQ_LL_EXTRA) [litLen];
2206*f6dc9357SAndroid Build Coastguard Worker             litLen = BASES_TABLE(SEQ_LL_BASES) [litLen];
2207*f6dc9357SAndroid Build Coastguard Worker             #ifdef Z7_ZSTD_DEC_USE_64BIT_LOADS
2208*f6dc9357SAndroid Build Coastguard Worker             {
2209*f6dc9357SAndroid Build Coastguard Worker               UPDATE_BIT_OFFSET(bitOffset, extra)
2210*f6dc9357SAndroid Build Coastguard Worker               litLen += (size_t)(v >> (64 - extra));
2211*f6dc9357SAndroid Build Coastguard Worker               #if defined(Z7_ZSTD_DEC_USE_64BIT_PRELOAD_OF)
2212*f6dc9357SAndroid Build Coastguard Worker                 FSE_PRELOAD
2213*f6dc9357SAndroid Build Coastguard Worker               #else
2214*f6dc9357SAndroid Build Coastguard Worker                 v <<= extra;
2215*f6dc9357SAndroid Build Coastguard Worker               #endif
2216*f6dc9357SAndroid Build Coastguard Worker             }
2217*f6dc9357SAndroid Build Coastguard Worker             #else
2218*f6dc9357SAndroid Build Coastguard Worker             {
2219*f6dc9357SAndroid Build Coastguard Worker               UInt32 v32;
2220*f6dc9357SAndroid Build Coastguard Worker               STREAM_READ_BITS(v32, extra)
2221*f6dc9357SAndroid Build Coastguard Worker               litLen += v32;
2222*f6dc9357SAndroid Build Coastguard Worker             }
2223*f6dc9357SAndroid Build Coastguard Worker             #endif
2224*f6dc9357SAndroid Build Coastguard Worker             STAT_INC(g_Num_LitsBig)
2225*f6dc9357SAndroid Build Coastguard Worker           }
2226*f6dc9357SAndroid Build Coastguard Worker 
2227*f6dc9357SAndroid Build Coastguard Worker           if ((literalsLen -= (ptrdiff_t)litLen) < 0)
2228*f6dc9357SAndroid Build Coastguard Worker             LZ_LOOP_ERROR_EXIT
2229*f6dc9357SAndroid Build Coastguard Worker           totalOutCheck += litLen;
2230*f6dc9357SAndroid Build Coastguard Worker           {
2231*f6dc9357SAndroid Build Coastguard Worker             const size_t rem = winLimit - winPos;
2232*f6dc9357SAndroid Build Coastguard Worker             if (litLen > rem)
2233*f6dc9357SAndroid Build Coastguard Worker               LZ_LOOP_ERROR_EXIT
2234*f6dc9357SAndroid Build Coastguard Worker             {
2235*f6dc9357SAndroid Build Coastguard Worker               const Byte *literals_temp = literals;
2236*f6dc9357SAndroid Build Coastguard Worker               Byte *d = win + winPos;
2237*f6dc9357SAndroid Build Coastguard Worker               literals += litLen;
2238*f6dc9357SAndroid Build Coastguard Worker               winPos += litLen;
2239*f6dc9357SAndroid Build Coastguard Worker               CopyLiterals(d, literals_temp, litLen, rem);
2240*f6dc9357SAndroid Build Coastguard Worker             }
2241*f6dc9357SAndroid Build Coastguard Worker           }
2242*f6dc9357SAndroid Build Coastguard Worker         }
2243*f6dc9357SAndroid Build Coastguard Worker         STAT_UPDATE(else g_Num_Lit0++;)
2244*f6dc9357SAndroid Build Coastguard Worker       }
2245*f6dc9357SAndroid Build Coastguard Worker 
2246*f6dc9357SAndroid Build Coastguard Worker       #define COPY_MATCH \
2247*f6dc9357SAndroid Build Coastguard Worker         { if (reps_0 > winSize || reps_0 > totalOutCheck) LZ_LOOP_ERROR_EXIT \
2248*f6dc9357SAndroid Build Coastguard Worker         totalOutCheck += matchLen; \
2249*f6dc9357SAndroid Build Coastguard Worker         { const size_t rem = winLimit - winPos; \
2250*f6dc9357SAndroid Build Coastguard Worker         if (matchLen > rem) LZ_LOOP_ERROR_EXIT \
2251*f6dc9357SAndroid Build Coastguard Worker         { const size_t winPos_temp = winPos; \
2252*f6dc9357SAndroid Build Coastguard Worker         winPos += matchLen; \
2253*f6dc9357SAndroid Build Coastguard Worker         CopyMatch(reps_0, matchLen, win, winPos_temp, rem, cycSize); }}}
2254*f6dc9357SAndroid Build Coastguard Worker 
2255*f6dc9357SAndroid Build Coastguard Worker       if (--numSeqs == 0)
2256*f6dc9357SAndroid Build Coastguard Worker       {
2257*f6dc9357SAndroid Build Coastguard Worker         COPY_MATCH
2258*f6dc9357SAndroid Build Coastguard Worker         break;
2259*f6dc9357SAndroid Build Coastguard Worker       }
2260*f6dc9357SAndroid Build Coastguard Worker       FSE_UPDATE_STATES
2261*f6dc9357SAndroid Build Coastguard Worker       COPY_MATCH
2262*f6dc9357SAndroid Build Coastguard Worker     } // for
2263*f6dc9357SAndroid Build Coastguard Worker 
2264*f6dc9357SAndroid Build Coastguard Worker     if ((CBitCtr_signed)bitOffset != BIT_OFFSET_DELTA_BYTES * 8 - BIT_OFFSET_DELTA_BITS)
2265*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2266*f6dc9357SAndroid Build Coastguard Worker 
2267*f6dc9357SAndroid Build Coastguard Worker     if (literalsLen)
2268*f6dc9357SAndroid Build Coastguard Worker     {
2269*f6dc9357SAndroid Build Coastguard Worker       const size_t rem = winLimit - winPos;
2270*f6dc9357SAndroid Build Coastguard Worker       if ((size_t)literalsLen > rem)
2271*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
2272*f6dc9357SAndroid Build Coastguard Worker       {
2273*f6dc9357SAndroid Build Coastguard Worker         Byte *d = win + winPos;
2274*f6dc9357SAndroid Build Coastguard Worker         winPos += (size_t)literalsLen;
2275*f6dc9357SAndroid Build Coastguard Worker         totalOutCheck += (size_t)literalsLen;
2276*f6dc9357SAndroid Build Coastguard Worker         CopyLiterals
2277*f6dc9357SAndroid Build Coastguard Worker         // memcpy
2278*f6dc9357SAndroid Build Coastguard Worker           (d, literals, (size_t)literalsLen, rem);
2279*f6dc9357SAndroid Build Coastguard Worker       }
2280*f6dc9357SAndroid Build Coastguard Worker     }
2281*f6dc9357SAndroid Build Coastguard Worker     if (totalOutCheck >= winSize)
2282*f6dc9357SAndroid Build Coastguard Worker       totalOutCheck = winSize;
2283*f6dc9357SAndroid Build Coastguard Worker     p->totalOutCheck = totalOutCheck;
2284*f6dc9357SAndroid Build Coastguard Worker     p->winPos = winPos;
2285*f6dc9357SAndroid Build Coastguard Worker     p->reps[0] = (CZstdDecOffset)reps_0;
2286*f6dc9357SAndroid Build Coastguard Worker     p->reps[1] = (CZstdDecOffset)reps_1;
2287*f6dc9357SAndroid Build Coastguard Worker     p->reps[2] = (CZstdDecOffset)reps_2;
2288*f6dc9357SAndroid Build Coastguard Worker   }
2289*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
2290*f6dc9357SAndroid Build Coastguard Worker }
2291*f6dc9357SAndroid Build Coastguard Worker 
2292*f6dc9357SAndroid Build Coastguard Worker 
2293*f6dc9357SAndroid Build Coastguard Worker // for debug: define to check that ZstdDec1_NeedTempBufferForInput() works correctly:
2294*f6dc9357SAndroid Build Coastguard Worker // #define Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP // define it for debug only
2295*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2296*f6dc9357SAndroid Build Coastguard Worker static unsigned g_numSeqs;
2297*f6dc9357SAndroid Build Coastguard Worker #endif
2298*f6dc9357SAndroid Build Coastguard Worker 
2299*f6dc9357SAndroid Build Coastguard Worker 
2300*f6dc9357SAndroid Build Coastguard Worker #define k_LitBlockType_Flag_RLE_or_Treeless  1
2301*f6dc9357SAndroid Build Coastguard Worker #define k_LitBlockType_Flag_Compressed       2
2302*f6dc9357SAndroid Build Coastguard Worker 
2303*f6dc9357SAndroid Build Coastguard Worker // outLimit : is strong limit
2304*f6dc9357SAndroid Build Coastguard Worker // outLimit <= ZstdDec1_GET_BLOCK_SIZE_LIMIT(p)
2305*f6dc9357SAndroid Build Coastguard Worker // inSize != 0
2306*f6dc9357SAndroid Build Coastguard Worker static
2307*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
2308*f6dc9357SAndroid Build Coastguard Worker SRes ZstdDec1_DecodeBlock(CZstdDec1 *p,
2309*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, SizeT inSize, SizeT afterAvail,
2310*f6dc9357SAndroid Build Coastguard Worker     const size_t outLimit)
2311*f6dc9357SAndroid Build Coastguard Worker {
2312*f6dc9357SAndroid Build Coastguard Worker   CZstdDec1_Vars vars;
2313*f6dc9357SAndroid Build Coastguard Worker   vars.literals = p->literalsBase;
2314*f6dc9357SAndroid Build Coastguard Worker   {
2315*f6dc9357SAndroid Build Coastguard Worker     const unsigned b0 = *src++;
2316*f6dc9357SAndroid Build Coastguard Worker     UInt32 numLits, compressedSize;
2317*f6dc9357SAndroid Build Coastguard Worker     const Byte *litStream;
2318*f6dc9357SAndroid Build Coastguard Worker     Byte *literalsDest;
2319*f6dc9357SAndroid Build Coastguard Worker     inSize--;
2320*f6dc9357SAndroid Build Coastguard Worker 
2321*f6dc9357SAndroid Build Coastguard Worker     if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2322*f6dc9357SAndroid Build Coastguard Worker     {
2323*f6dc9357SAndroid Build Coastguard Worker       // we need at least one additional byte for (numSeqs).
2324*f6dc9357SAndroid Build Coastguard Worker       // so we check for that additional byte in conditions.
2325*f6dc9357SAndroid Build Coastguard Worker       numLits = b0 >> 3;
2326*f6dc9357SAndroid Build Coastguard Worker       if (b0 & 4)
2327*f6dc9357SAndroid Build Coastguard Worker       {
2328*f6dc9357SAndroid Build Coastguard Worker         UInt32 v;
2329*f6dc9357SAndroid Build Coastguard Worker         if (inSize < 1 + 1) // we need at least 1 byte here and 1 byte for (numSeqs).
2330*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
2331*f6dc9357SAndroid Build Coastguard Worker         numLits >>= 1;
2332*f6dc9357SAndroid Build Coastguard Worker         v = GetUi16(src);
2333*f6dc9357SAndroid Build Coastguard Worker         src += 2;
2334*f6dc9357SAndroid Build Coastguard Worker         inSize -= 2;
2335*f6dc9357SAndroid Build Coastguard Worker         if ((b0 & 8) == 0)
2336*f6dc9357SAndroid Build Coastguard Worker         {
2337*f6dc9357SAndroid Build Coastguard Worker           src--;
2338*f6dc9357SAndroid Build Coastguard Worker           inSize++;
2339*f6dc9357SAndroid Build Coastguard Worker           v = (Byte)v;
2340*f6dc9357SAndroid Build Coastguard Worker         }
2341*f6dc9357SAndroid Build Coastguard Worker         numLits += v << 4;
2342*f6dc9357SAndroid Build Coastguard Worker       }
2343*f6dc9357SAndroid Build Coastguard Worker       compressedSize = 1;
2344*f6dc9357SAndroid Build Coastguard Worker       if ((b0 & k_LitBlockType_Flag_RLE_or_Treeless) == 0)
2345*f6dc9357SAndroid Build Coastguard Worker         compressedSize = numLits;
2346*f6dc9357SAndroid Build Coastguard Worker     }
2347*f6dc9357SAndroid Build Coastguard Worker     else if (inSize < 4)
2348*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2349*f6dc9357SAndroid Build Coastguard Worker     else
2350*f6dc9357SAndroid Build Coastguard Worker     {
2351*f6dc9357SAndroid Build Coastguard Worker       const unsigned mode4Streams = b0 & 0xc;
2352*f6dc9357SAndroid Build Coastguard Worker       const unsigned numBytes = (3 * mode4Streams + 32) >> 4;
2353*f6dc9357SAndroid Build Coastguard Worker       const unsigned numBits = 4 * numBytes - 2;
2354*f6dc9357SAndroid Build Coastguard Worker       const UInt32 mask = ((UInt32)16 << numBits) - 1;
2355*f6dc9357SAndroid Build Coastguard Worker       compressedSize = GetUi32(src);
2356*f6dc9357SAndroid Build Coastguard Worker       numLits = ((
2357*f6dc9357SAndroid Build Coastguard Worker           #ifdef MY_CPU_LE_UNALIGN
2358*f6dc9357SAndroid Build Coastguard Worker             GetUi32(src - 1)
2359*f6dc9357SAndroid Build Coastguard Worker           #else
2360*f6dc9357SAndroid Build Coastguard Worker             ((compressedSize << 8) + b0)
2361*f6dc9357SAndroid Build Coastguard Worker           #endif
2362*f6dc9357SAndroid Build Coastguard Worker           ) >> 4) & mask;
2363*f6dc9357SAndroid Build Coastguard Worker       src += numBytes;
2364*f6dc9357SAndroid Build Coastguard Worker       inSize -= numBytes;
2365*f6dc9357SAndroid Build Coastguard Worker       compressedSize >>= numBits;
2366*f6dc9357SAndroid Build Coastguard Worker       compressedSize &= mask;
2367*f6dc9357SAndroid Build Coastguard Worker       /*
2368*f6dc9357SAndroid Build Coastguard Worker       if (numLits != 0) printf("inSize = %7u num_lits=%7u compressed=%7u ratio = %u  ratio2 = %u\n",
2369*f6dc9357SAndroid Build Coastguard Worker           i1, numLits, (unsigned)compressedSize * 1, (unsigned)compressedSize * 100 / numLits,
2370*f6dc9357SAndroid Build Coastguard Worker           (unsigned)numLits * 100 / (unsigned)inSize);
2371*f6dc9357SAndroid Build Coastguard Worker       }
2372*f6dc9357SAndroid Build Coastguard Worker       */
2373*f6dc9357SAndroid Build Coastguard Worker       if (compressedSize == 0)
2374*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA; // (compressedSize == 0) is not allowed
2375*f6dc9357SAndroid Build Coastguard Worker     }
2376*f6dc9357SAndroid Build Coastguard Worker 
2377*f6dc9357SAndroid Build Coastguard Worker     STAT_UPDATE(g_Num_Lits += numLits;)
2378*f6dc9357SAndroid Build Coastguard Worker 
2379*f6dc9357SAndroid Build Coastguard Worker     vars.literalsLen = numLits;
2380*f6dc9357SAndroid Build Coastguard Worker 
2381*f6dc9357SAndroid Build Coastguard Worker     if (compressedSize >= inSize)
2382*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2383*f6dc9357SAndroid Build Coastguard Worker     litStream = src;
2384*f6dc9357SAndroid Build Coastguard Worker     src += compressedSize;
2385*f6dc9357SAndroid Build Coastguard Worker     inSize -= compressedSize;
2386*f6dc9357SAndroid Build Coastguard Worker     // inSize != 0
2387*f6dc9357SAndroid Build Coastguard Worker     {
2388*f6dc9357SAndroid Build Coastguard Worker       UInt32 numSeqs = *src++;
2389*f6dc9357SAndroid Build Coastguard Worker       inSize--;
2390*f6dc9357SAndroid Build Coastguard Worker       if (numSeqs > 127)
2391*f6dc9357SAndroid Build Coastguard Worker       {
2392*f6dc9357SAndroid Build Coastguard Worker         UInt32 b1;
2393*f6dc9357SAndroid Build Coastguard Worker         if (inSize == 0)
2394*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
2395*f6dc9357SAndroid Build Coastguard Worker         numSeqs -= 128;
2396*f6dc9357SAndroid Build Coastguard Worker         b1 = *src++;
2397*f6dc9357SAndroid Build Coastguard Worker         inSize--;
2398*f6dc9357SAndroid Build Coastguard Worker         if (numSeqs == 127)
2399*f6dc9357SAndroid Build Coastguard Worker         {
2400*f6dc9357SAndroid Build Coastguard Worker           if (inSize == 0)
2401*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_DATA;
2402*f6dc9357SAndroid Build Coastguard Worker           numSeqs = (UInt32)(*src++) + 127;
2403*f6dc9357SAndroid Build Coastguard Worker           inSize--;
2404*f6dc9357SAndroid Build Coastguard Worker         }
2405*f6dc9357SAndroid Build Coastguard Worker         numSeqs = (numSeqs << 8) + b1;
2406*f6dc9357SAndroid Build Coastguard Worker       }
2407*f6dc9357SAndroid Build Coastguard Worker       if (numSeqs * MATCH_LEN_MIN + numLits > outLimit)
2408*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
2409*f6dc9357SAndroid Build Coastguard Worker       vars.numSeqs = numSeqs;
2410*f6dc9357SAndroid Build Coastguard Worker 
2411*f6dc9357SAndroid Build Coastguard Worker       STAT_UPDATE(g_NumSeqs_total += numSeqs;)
2412*f6dc9357SAndroid Build Coastguard Worker       /*
2413*f6dc9357SAndroid Build Coastguard Worker         #ifdef SHOW_STAT
2414*f6dc9357SAndroid Build Coastguard Worker         printf("\n %5u : %8u, %8u : %5u", (int)g_Num_Blocks_Compressed, (int)numSeqs, (int)g_NumSeqs_total,
2415*f6dc9357SAndroid Build Coastguard Worker           (int)g_NumSeqs_total / g_Num_Blocks_Compressed);
2416*f6dc9357SAndroid Build Coastguard Worker         #endif
2417*f6dc9357SAndroid Build Coastguard Worker         // printf("\nnumSeqs2 = %d", numSeqs);
2418*f6dc9357SAndroid Build Coastguard Worker       */
2419*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2420*f6dc9357SAndroid Build Coastguard Worker       if (numSeqs != g_numSeqs) return SZ_ERROR_DATA; // for debug
2421*f6dc9357SAndroid Build Coastguard Worker     #endif
2422*f6dc9357SAndroid Build Coastguard Worker       if (numSeqs == 0)
2423*f6dc9357SAndroid Build Coastguard Worker       {
2424*f6dc9357SAndroid Build Coastguard Worker         if (inSize != 0)
2425*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_DATA;
2426*f6dc9357SAndroid Build Coastguard Worker         literalsDest = p->win + p->winPos;
2427*f6dc9357SAndroid Build Coastguard Worker       }
2428*f6dc9357SAndroid Build Coastguard Worker       else
2429*f6dc9357SAndroid Build Coastguard Worker         literalsDest = p->literalsBase;
2430*f6dc9357SAndroid Build Coastguard Worker     }
2431*f6dc9357SAndroid Build Coastguard Worker 
2432*f6dc9357SAndroid Build Coastguard Worker     if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2433*f6dc9357SAndroid Build Coastguard Worker     {
2434*f6dc9357SAndroid Build Coastguard Worker       if (b0 & k_LitBlockType_Flag_RLE_or_Treeless)
2435*f6dc9357SAndroid Build Coastguard Worker       {
2436*f6dc9357SAndroid Build Coastguard Worker         memset(literalsDest, litStream[0], numLits);
2437*f6dc9357SAndroid Build Coastguard Worker         if (vars.numSeqs)
2438*f6dc9357SAndroid Build Coastguard Worker         {
2439*f6dc9357SAndroid Build Coastguard Worker           // literalsDest == p->literalsBase == vars.literals
2440*f6dc9357SAndroid Build Coastguard Worker           #if COPY_CHUNK_SIZE > 1
2441*f6dc9357SAndroid Build Coastguard Worker             memset(p->literalsBase + numLits, 0, COPY_CHUNK_SIZE);
2442*f6dc9357SAndroid Build Coastguard Worker           #endif
2443*f6dc9357SAndroid Build Coastguard Worker         }
2444*f6dc9357SAndroid Build Coastguard Worker       }
2445*f6dc9357SAndroid Build Coastguard Worker       else
2446*f6dc9357SAndroid Build Coastguard Worker       {
2447*f6dc9357SAndroid Build Coastguard Worker         // unsigned y;
2448*f6dc9357SAndroid Build Coastguard Worker         // for (y = 0; y < 10000; y++)
2449*f6dc9357SAndroid Build Coastguard Worker         memcpy(literalsDest, litStream, numLits);
2450*f6dc9357SAndroid Build Coastguard Worker         if (vars.numSeqs)
2451*f6dc9357SAndroid Build Coastguard Worker         {
2452*f6dc9357SAndroid Build Coastguard Worker           /* we need up to (15 == COPY_CHUNK_SIZE - 1) space for optimized CopyLiterals().
2453*f6dc9357SAndroid Build Coastguard Worker              If we have additional space in input stream after literals stream,
2454*f6dc9357SAndroid Build Coastguard Worker              we use direct copy of rar literals in input stream */
2455*f6dc9357SAndroid Build Coastguard Worker           if ((size_t)(src + inSize - litStream) - numLits + afterAvail >= (COPY_CHUNK_SIZE - 1))
2456*f6dc9357SAndroid Build Coastguard Worker             vars.literals = litStream;
2457*f6dc9357SAndroid Build Coastguard Worker           else
2458*f6dc9357SAndroid Build Coastguard Worker           {
2459*f6dc9357SAndroid Build Coastguard Worker             // literalsDest == p->literalsBase == vars.literals
2460*f6dc9357SAndroid Build Coastguard Worker             #if COPY_CHUNK_SIZE > 1
2461*f6dc9357SAndroid Build Coastguard Worker             /* CopyLiterals():
2462*f6dc9357SAndroid Build Coastguard Worker                 1) we don't want reading non-initialized data
2463*f6dc9357SAndroid Build Coastguard Worker                 2) we will copy only zero byte after literals buffer */
2464*f6dc9357SAndroid Build Coastguard Worker               memset(p->literalsBase + numLits, 0, COPY_CHUNK_SIZE);
2465*f6dc9357SAndroid Build Coastguard Worker             #endif
2466*f6dc9357SAndroid Build Coastguard Worker           }
2467*f6dc9357SAndroid Build Coastguard Worker         }
2468*f6dc9357SAndroid Build Coastguard Worker       }
2469*f6dc9357SAndroid Build Coastguard Worker     }
2470*f6dc9357SAndroid Build Coastguard Worker     else
2471*f6dc9357SAndroid Build Coastguard Worker     {
2472*f6dc9357SAndroid Build Coastguard Worker       CInBufPair hufStream;
2473*f6dc9357SAndroid Build Coastguard Worker       hufStream.ptr = litStream;
2474*f6dc9357SAndroid Build Coastguard Worker       hufStream.len = compressedSize;
2475*f6dc9357SAndroid Build Coastguard Worker 
2476*f6dc9357SAndroid Build Coastguard Worker       if ((b0 & k_LitBlockType_Flag_RLE_or_Treeless) == 0)
2477*f6dc9357SAndroid Build Coastguard Worker       {
2478*f6dc9357SAndroid Build Coastguard Worker         // unsigned y = 100; CInBufPair hs2 = hufStream; do { hufStream = hs2;
2479*f6dc9357SAndroid Build Coastguard Worker         RINOK(Huf_DecodeTable(&p->huf, &hufStream))
2480*f6dc9357SAndroid Build Coastguard Worker         p->litHuf_wasSet = True;
2481*f6dc9357SAndroid Build Coastguard Worker         // } while (--y);
2482*f6dc9357SAndroid Build Coastguard Worker       }
2483*f6dc9357SAndroid Build Coastguard Worker       else if (!p->litHuf_wasSet)
2484*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
2485*f6dc9357SAndroid Build Coastguard Worker 
2486*f6dc9357SAndroid Build Coastguard Worker       {
2487*f6dc9357SAndroid Build Coastguard Worker         // int yyy; for (yyy = 0; yyy < 34; yyy++) {
2488*f6dc9357SAndroid Build Coastguard Worker         SRes sres;
2489*f6dc9357SAndroid Build Coastguard Worker         if ((b0 & 0xc) == 0) // mode4Streams
2490*f6dc9357SAndroid Build Coastguard Worker           sres = Huf_Decompress_1stream((const Byte *)(const void *)p->huf.table64,
2491*f6dc9357SAndroid Build Coastguard Worker               hufStream.ptr - HUF_SRC_OFFSET, hufStream.len, literalsDest, numLits);
2492*f6dc9357SAndroid Build Coastguard Worker         else
2493*f6dc9357SAndroid Build Coastguard Worker         {
2494*f6dc9357SAndroid Build Coastguard Worker           // 6 bytes for the jump table + 4x1 bytes of end-padding Bytes)
2495*f6dc9357SAndroid Build Coastguard Worker           if (hufStream.len < 6 + 4)
2496*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_DATA;
2497*f6dc9357SAndroid Build Coastguard Worker           // the condition from original-zstd decoder:
2498*f6dc9357SAndroid Build Coastguard Worker           #define Z7_ZSTD_MIN_LITERALS_FOR_4_STREAMS 6
2499*f6dc9357SAndroid Build Coastguard Worker           if (numLits < Z7_ZSTD_MIN_LITERALS_FOR_4_STREAMS)
2500*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_DATA;
2501*f6dc9357SAndroid Build Coastguard Worker           sres = Huf_Decompress_4stream((const Byte *)(const void *)p->huf.table64,
2502*f6dc9357SAndroid Build Coastguard Worker               hufStream.ptr + (6 - HUF_SRC_OFFSET), hufStream.len, literalsDest, numLits);
2503*f6dc9357SAndroid Build Coastguard Worker         }
2504*f6dc9357SAndroid Build Coastguard Worker         RINOK(sres)
2505*f6dc9357SAndroid Build Coastguard Worker         // }
2506*f6dc9357SAndroid Build Coastguard Worker       }
2507*f6dc9357SAndroid Build Coastguard Worker     }
2508*f6dc9357SAndroid Build Coastguard Worker 
2509*f6dc9357SAndroid Build Coastguard Worker     if (vars.numSeqs == 0)
2510*f6dc9357SAndroid Build Coastguard Worker     {
2511*f6dc9357SAndroid Build Coastguard Worker       p->winPos += numLits;
2512*f6dc9357SAndroid Build Coastguard Worker       UPDATE_TOTAL_OUT(p, numLits)
2513*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
2514*f6dc9357SAndroid Build Coastguard Worker     }
2515*f6dc9357SAndroid Build Coastguard Worker   }
2516*f6dc9357SAndroid Build Coastguard Worker   {
2517*f6dc9357SAndroid Build Coastguard Worker     CInBufPair in;
2518*f6dc9357SAndroid Build Coastguard Worker     unsigned mode;
2519*f6dc9357SAndroid Build Coastguard Worker     unsigned seqMode;
2520*f6dc9357SAndroid Build Coastguard Worker 
2521*f6dc9357SAndroid Build Coastguard Worker     in.ptr = src;
2522*f6dc9357SAndroid Build Coastguard Worker     in.len = inSize;
2523*f6dc9357SAndroid Build Coastguard Worker     if (in.len == 0)
2524*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2525*f6dc9357SAndroid Build Coastguard Worker     in.len--;
2526*f6dc9357SAndroid Build Coastguard Worker     mode = *in.ptr++;
2527*f6dc9357SAndroid Build Coastguard Worker     if (mode & 3) // Reserved bits
2528*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2529*f6dc9357SAndroid Build Coastguard Worker 
2530*f6dc9357SAndroid Build Coastguard Worker     seqMode = (mode >> 6);
2531*f6dc9357SAndroid Build Coastguard Worker     if (seqMode == k_SeqMode_Repeat)
2532*f6dc9357SAndroid Build Coastguard Worker       { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2533*f6dc9357SAndroid Build Coastguard Worker     else RINOK(FSE_Decode_SeqTable(
2534*f6dc9357SAndroid Build Coastguard Worker         p->fse.ll,
2535*f6dc9357SAndroid Build Coastguard Worker         &in,
2536*f6dc9357SAndroid Build Coastguard Worker         6, // predefAccuracy
2537*f6dc9357SAndroid Build Coastguard Worker         &p->ll_accuracy,
2538*f6dc9357SAndroid Build Coastguard Worker         NUM_LL_SYMBOLS,
2539*f6dc9357SAndroid Build Coastguard Worker         k_PredefRecords_LL,
2540*f6dc9357SAndroid Build Coastguard Worker         seqMode))
2541*f6dc9357SAndroid Build Coastguard Worker 
2542*f6dc9357SAndroid Build Coastguard Worker     seqMode = (mode >> 4) & 3;
2543*f6dc9357SAndroid Build Coastguard Worker     if (seqMode == k_SeqMode_Repeat)
2544*f6dc9357SAndroid Build Coastguard Worker       { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2545*f6dc9357SAndroid Build Coastguard Worker     else RINOK(FSE_Decode_SeqTable(
2546*f6dc9357SAndroid Build Coastguard Worker         p->fse.of,
2547*f6dc9357SAndroid Build Coastguard Worker         &in,
2548*f6dc9357SAndroid Build Coastguard Worker         5, // predefAccuracy
2549*f6dc9357SAndroid Build Coastguard Worker         &p->of_accuracy,
2550*f6dc9357SAndroid Build Coastguard Worker         NUM_OFFSET_SYMBOLS_MAX,
2551*f6dc9357SAndroid Build Coastguard Worker         k_PredefRecords_OF,
2552*f6dc9357SAndroid Build Coastguard Worker         seqMode))
2553*f6dc9357SAndroid Build Coastguard Worker 
2554*f6dc9357SAndroid Build Coastguard Worker     seqMode = (mode >> 2) & 3;
2555*f6dc9357SAndroid Build Coastguard Worker     if (seqMode == k_SeqMode_Repeat)
2556*f6dc9357SAndroid Build Coastguard Worker       { if (!IS_SEQ_TABLES_WERE_SET(p)) return SZ_ERROR_DATA; }
2557*f6dc9357SAndroid Build Coastguard Worker     else
2558*f6dc9357SAndroid Build Coastguard Worker     {
2559*f6dc9357SAndroid Build Coastguard Worker       RINOK(FSE_Decode_SeqTable(
2560*f6dc9357SAndroid Build Coastguard Worker         p->fse.ml,
2561*f6dc9357SAndroid Build Coastguard Worker         &in,
2562*f6dc9357SAndroid Build Coastguard Worker         6, // predefAccuracy
2563*f6dc9357SAndroid Build Coastguard Worker         &p->ml_accuracy,
2564*f6dc9357SAndroid Build Coastguard Worker         NUM_ML_SYMBOLS,
2565*f6dc9357SAndroid Build Coastguard Worker         k_PredefRecords_ML,
2566*f6dc9357SAndroid Build Coastguard Worker         seqMode))
2567*f6dc9357SAndroid Build Coastguard Worker       /*
2568*f6dc9357SAndroid Build Coastguard Worker       #if defined(Z7_ZSTD_DEC_USE_ML_PLUS3)
2569*f6dc9357SAndroid Build Coastguard Worker         // { unsigned y = 1 << 10; do
2570*f6dc9357SAndroid Build Coastguard Worker       {
2571*f6dc9357SAndroid Build Coastguard Worker         const unsigned accuracy = p->ml_accuracy;
2572*f6dc9357SAndroid Build Coastguard Worker         if (accuracy == 0)
2573*f6dc9357SAndroid Build Coastguard Worker           p->fse.ml[0] += 3;
2574*f6dc9357SAndroid Build Coastguard Worker         else
2575*f6dc9357SAndroid Build Coastguard Worker         #ifdef MY_CPU_64BIT
2576*f6dc9357SAndroid Build Coastguard Worker         {
2577*f6dc9357SAndroid Build Coastguard Worker           // alignemt (UInt64 _pad_Alignment) in fse.ml is required for that code
2578*f6dc9357SAndroid Build Coastguard Worker           UInt64 *table = (UInt64 *)(void *)p->fse.ml;
2579*f6dc9357SAndroid Build Coastguard Worker           const UInt64 *end = (const UInt64 *)(const void *)
2580*f6dc9357SAndroid Build Coastguard Worker             ((const Byte *)(const void *)table + ((size_t)sizeof(CFseRecord) << accuracy));
2581*f6dc9357SAndroid Build Coastguard Worker           do
2582*f6dc9357SAndroid Build Coastguard Worker           {
2583*f6dc9357SAndroid Build Coastguard Worker             table[0] += ((UInt64)MATCH_LEN_MIN << 32) + MATCH_LEN_MIN;
2584*f6dc9357SAndroid Build Coastguard Worker             table[1] += ((UInt64)MATCH_LEN_MIN << 32) + MATCH_LEN_MIN;
2585*f6dc9357SAndroid Build Coastguard Worker             table += 2;
2586*f6dc9357SAndroid Build Coastguard Worker           }
2587*f6dc9357SAndroid Build Coastguard Worker           while (table != end);
2588*f6dc9357SAndroid Build Coastguard Worker         }
2589*f6dc9357SAndroid Build Coastguard Worker         #else
2590*f6dc9357SAndroid Build Coastguard Worker         {
2591*f6dc9357SAndroid Build Coastguard Worker           UInt32 *table = p->fse.ml;
2592*f6dc9357SAndroid Build Coastguard Worker           const UInt32 *end = (const UInt32 *)(const void *)
2593*f6dc9357SAndroid Build Coastguard Worker             ((const Byte *)(const void *)table + ((size_t)sizeof(CFseRecord) << accuracy));
2594*f6dc9357SAndroid Build Coastguard Worker           do
2595*f6dc9357SAndroid Build Coastguard Worker           {
2596*f6dc9357SAndroid Build Coastguard Worker             table[0] += MATCH_LEN_MIN;
2597*f6dc9357SAndroid Build Coastguard Worker             table[1] += MATCH_LEN_MIN;
2598*f6dc9357SAndroid Build Coastguard Worker             table += 2;
2599*f6dc9357SAndroid Build Coastguard Worker             table[0] += MATCH_LEN_MIN;
2600*f6dc9357SAndroid Build Coastguard Worker             table[1] += MATCH_LEN_MIN;
2601*f6dc9357SAndroid Build Coastguard Worker             table += 2;
2602*f6dc9357SAndroid Build Coastguard Worker           }
2603*f6dc9357SAndroid Build Coastguard Worker           while (table != end);
2604*f6dc9357SAndroid Build Coastguard Worker         }
2605*f6dc9357SAndroid Build Coastguard Worker         #endif
2606*f6dc9357SAndroid Build Coastguard Worker       }
2607*f6dc9357SAndroid Build Coastguard Worker       // while (--y); }
2608*f6dc9357SAndroid Build Coastguard Worker       #endif
2609*f6dc9357SAndroid Build Coastguard Worker       */
2610*f6dc9357SAndroid Build Coastguard Worker     }
2611*f6dc9357SAndroid Build Coastguard Worker 
2612*f6dc9357SAndroid Build Coastguard Worker     // p->seqTables_wereSet = True;
2613*f6dc9357SAndroid Build Coastguard Worker     if (in.len == 0)
2614*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_DATA;
2615*f6dc9357SAndroid Build Coastguard Worker     return Decompress_Sequences(p,
2616*f6dc9357SAndroid Build Coastguard Worker         in.ptr - SEQ_SRC_OFFSET - BIT_OFFSET_DELTA_BYTES, in.len,
2617*f6dc9357SAndroid Build Coastguard Worker         p->winPos + outLimit, &vars);
2618*f6dc9357SAndroid Build Coastguard Worker   }
2619*f6dc9357SAndroid Build Coastguard Worker }
2620*f6dc9357SAndroid Build Coastguard Worker 
2621*f6dc9357SAndroid Build Coastguard Worker 
2622*f6dc9357SAndroid Build Coastguard Worker 
2623*f6dc9357SAndroid Build Coastguard Worker 
2624*f6dc9357SAndroid Build Coastguard Worker // inSize != 0
2625*f6dc9357SAndroid Build Coastguard Worker // it must do similar to ZstdDec1_DecodeBlock()
2626*f6dc9357SAndroid Build Coastguard Worker static size_t ZstdDec1_NeedTempBufferForInput(
2627*f6dc9357SAndroid Build Coastguard Worker     const SizeT beforeSize, const Byte * const src, const SizeT inSize)
2628*f6dc9357SAndroid Build Coastguard Worker {
2629*f6dc9357SAndroid Build Coastguard Worker   unsigned b0;
2630*f6dc9357SAndroid Build Coastguard Worker   UInt32 pos;
2631*f6dc9357SAndroid Build Coastguard Worker 
2632*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2633*f6dc9357SAndroid Build Coastguard Worker     g_numSeqs = 1 << 24;
2634*f6dc9357SAndroid Build Coastguard Worker   #else
2635*f6dc9357SAndroid Build Coastguard Worker   // we have at least 3 bytes before seq data: litBlockType, numSeqs, seqMode
2636*f6dc9357SAndroid Build Coastguard Worker   #define MIN_BLOCK_LZ_HEADERS_SIZE 3
2637*f6dc9357SAndroid Build Coastguard Worker   if (beforeSize >= MAX_BACKWARD_DEPTH - MIN_BLOCK_LZ_HEADERS_SIZE)
2638*f6dc9357SAndroid Build Coastguard Worker     return 0;
2639*f6dc9357SAndroid Build Coastguard Worker   #endif
2640*f6dc9357SAndroid Build Coastguard Worker 
2641*f6dc9357SAndroid Build Coastguard Worker   b0 = src[0];
2642*f6dc9357SAndroid Build Coastguard Worker 
2643*f6dc9357SAndroid Build Coastguard Worker   if ((b0 & k_LitBlockType_Flag_Compressed) == 0)
2644*f6dc9357SAndroid Build Coastguard Worker   {
2645*f6dc9357SAndroid Build Coastguard Worker     UInt32 numLits = b0 >> 3;
2646*f6dc9357SAndroid Build Coastguard Worker     pos = 1;
2647*f6dc9357SAndroid Build Coastguard Worker     if (b0 & 4)
2648*f6dc9357SAndroid Build Coastguard Worker     {
2649*f6dc9357SAndroid Build Coastguard Worker       UInt32 v;
2650*f6dc9357SAndroid Build Coastguard Worker       if (inSize < 3)
2651*f6dc9357SAndroid Build Coastguard Worker         return 0;
2652*f6dc9357SAndroid Build Coastguard Worker       numLits >>= 1;
2653*f6dc9357SAndroid Build Coastguard Worker       v = GetUi16(src + 1);
2654*f6dc9357SAndroid Build Coastguard Worker       pos = 3;
2655*f6dc9357SAndroid Build Coastguard Worker       if ((b0 & 8) == 0)
2656*f6dc9357SAndroid Build Coastguard Worker       {
2657*f6dc9357SAndroid Build Coastguard Worker         pos = 2;
2658*f6dc9357SAndroid Build Coastguard Worker         v = (Byte)v;
2659*f6dc9357SAndroid Build Coastguard Worker       }
2660*f6dc9357SAndroid Build Coastguard Worker       numLits += v << 4;
2661*f6dc9357SAndroid Build Coastguard Worker     }
2662*f6dc9357SAndroid Build Coastguard Worker     if (b0 & k_LitBlockType_Flag_RLE_or_Treeless)
2663*f6dc9357SAndroid Build Coastguard Worker       numLits = 1;
2664*f6dc9357SAndroid Build Coastguard Worker     pos += numLits;
2665*f6dc9357SAndroid Build Coastguard Worker   }
2666*f6dc9357SAndroid Build Coastguard Worker   else if (inSize < 5)
2667*f6dc9357SAndroid Build Coastguard Worker     return 0;
2668*f6dc9357SAndroid Build Coastguard Worker   else
2669*f6dc9357SAndroid Build Coastguard Worker   {
2670*f6dc9357SAndroid Build Coastguard Worker     const unsigned mode4Streams = b0 & 0xc;
2671*f6dc9357SAndroid Build Coastguard Worker     const unsigned numBytes = (3 * mode4Streams + 48) >> 4;
2672*f6dc9357SAndroid Build Coastguard Worker     const unsigned numBits = 4 * numBytes - 6;
2673*f6dc9357SAndroid Build Coastguard Worker     UInt32 cs = GetUi32(src + 1);
2674*f6dc9357SAndroid Build Coastguard Worker     cs >>= numBits;
2675*f6dc9357SAndroid Build Coastguard Worker     cs &= ((UInt32)16 << numBits) - 1;
2676*f6dc9357SAndroid Build Coastguard Worker     if (cs == 0)
2677*f6dc9357SAndroid Build Coastguard Worker       return 0;
2678*f6dc9357SAndroid Build Coastguard Worker     pos = numBytes + cs;
2679*f6dc9357SAndroid Build Coastguard Worker   }
2680*f6dc9357SAndroid Build Coastguard Worker 
2681*f6dc9357SAndroid Build Coastguard Worker   if (pos >= inSize)
2682*f6dc9357SAndroid Build Coastguard Worker     return 0;
2683*f6dc9357SAndroid Build Coastguard Worker   {
2684*f6dc9357SAndroid Build Coastguard Worker     UInt32 numSeqs = src[pos++];
2685*f6dc9357SAndroid Build Coastguard Worker     if (numSeqs > 127)
2686*f6dc9357SAndroid Build Coastguard Worker     {
2687*f6dc9357SAndroid Build Coastguard Worker       UInt32 b1;
2688*f6dc9357SAndroid Build Coastguard Worker       if (pos >= inSize)
2689*f6dc9357SAndroid Build Coastguard Worker         return 0;
2690*f6dc9357SAndroid Build Coastguard Worker       numSeqs -= 128;
2691*f6dc9357SAndroid Build Coastguard Worker       b1 = src[pos++];
2692*f6dc9357SAndroid Build Coastguard Worker       if (numSeqs == 127)
2693*f6dc9357SAndroid Build Coastguard Worker       {
2694*f6dc9357SAndroid Build Coastguard Worker         if (pos >= inSize)
2695*f6dc9357SAndroid Build Coastguard Worker           return 0;
2696*f6dc9357SAndroid Build Coastguard Worker         numSeqs = (UInt32)(src[pos++]) + 127;
2697*f6dc9357SAndroid Build Coastguard Worker       }
2698*f6dc9357SAndroid Build Coastguard Worker       numSeqs = (numSeqs << 8) + b1;
2699*f6dc9357SAndroid Build Coastguard Worker     }
2700*f6dc9357SAndroid Build Coastguard Worker     #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
2701*f6dc9357SAndroid Build Coastguard Worker       g_numSeqs = numSeqs; // for debug
2702*f6dc9357SAndroid Build Coastguard Worker     #endif
2703*f6dc9357SAndroid Build Coastguard Worker     if (numSeqs == 0)
2704*f6dc9357SAndroid Build Coastguard Worker       return 0;
2705*f6dc9357SAndroid Build Coastguard Worker   }
2706*f6dc9357SAndroid Build Coastguard Worker   /*
2707*f6dc9357SAndroid Build Coastguard Worker   if (pos >= inSize)
2708*f6dc9357SAndroid Build Coastguard Worker     return 0;
2709*f6dc9357SAndroid Build Coastguard Worker   pos++;
2710*f6dc9357SAndroid Build Coastguard Worker   */
2711*f6dc9357SAndroid Build Coastguard Worker   // we will have one additional byte for seqMode:
2712*f6dc9357SAndroid Build Coastguard Worker   if (beforeSize + pos >= MAX_BACKWARD_DEPTH - 1)
2713*f6dc9357SAndroid Build Coastguard Worker     return 0;
2714*f6dc9357SAndroid Build Coastguard Worker   return 1;
2715*f6dc9357SAndroid Build Coastguard Worker }
2716*f6dc9357SAndroid Build Coastguard Worker 
2717*f6dc9357SAndroid Build Coastguard Worker 
2718*f6dc9357SAndroid Build Coastguard Worker 
2719*f6dc9357SAndroid Build Coastguard Worker // ---------- ZSTD FRAME ----------
2720*f6dc9357SAndroid Build Coastguard Worker 
2721*f6dc9357SAndroid Build Coastguard Worker #define kBlockType_Raw          0
2722*f6dc9357SAndroid Build Coastguard Worker #define kBlockType_RLE          1
2723*f6dc9357SAndroid Build Coastguard Worker #define kBlockType_Compressed   2
2724*f6dc9357SAndroid Build Coastguard Worker #define kBlockType_Reserved     3
2725*f6dc9357SAndroid Build Coastguard Worker 
2726*f6dc9357SAndroid Build Coastguard Worker typedef enum
2727*f6dc9357SAndroid Build Coastguard Worker {
2728*f6dc9357SAndroid Build Coastguard Worker   // begin: states that require 4 bytes:
2729*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_SIGNATURE,
2730*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_HASH,
2731*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_SKIP_HEADER,
2732*f6dc9357SAndroid Build Coastguard Worker   // end of states that require 4 bytes
2733*f6dc9357SAndroid Build Coastguard Worker 
2734*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_SKIP_DATA,
2735*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_FRAME_HEADER,
2736*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_AFTER_HEADER,
2737*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_BLOCK,
2738*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_DATA,
2739*f6dc9357SAndroid Build Coastguard Worker   ZSTD2_STATE_FINISHED
2740*f6dc9357SAndroid Build Coastguard Worker } EZstd2State;
2741*f6dc9357SAndroid Build Coastguard Worker 
2742*f6dc9357SAndroid Build Coastguard Worker 
2743*f6dc9357SAndroid Build Coastguard Worker struct CZstdDec
2744*f6dc9357SAndroid Build Coastguard Worker {
2745*f6dc9357SAndroid Build Coastguard Worker   EZstd2State frameState;
2746*f6dc9357SAndroid Build Coastguard Worker   unsigned tempSize;
2747*f6dc9357SAndroid Build Coastguard Worker 
2748*f6dc9357SAndroid Build Coastguard Worker   Byte temp[14]; // 14 is required
2749*f6dc9357SAndroid Build Coastguard Worker 
2750*f6dc9357SAndroid Build Coastguard Worker   Byte descriptor;
2751*f6dc9357SAndroid Build Coastguard Worker   Byte windowDescriptor;
2752*f6dc9357SAndroid Build Coastguard Worker   Byte isLastBlock;
2753*f6dc9357SAndroid Build Coastguard Worker   Byte blockType;
2754*f6dc9357SAndroid Build Coastguard Worker   Byte isErrorState;
2755*f6dc9357SAndroid Build Coastguard Worker   Byte hashError;
2756*f6dc9357SAndroid Build Coastguard Worker   Byte disableHash;
2757*f6dc9357SAndroid Build Coastguard Worker   Byte isCyclicMode;
2758*f6dc9357SAndroid Build Coastguard Worker 
2759*f6dc9357SAndroid Build Coastguard Worker   UInt32 blockSize;
2760*f6dc9357SAndroid Build Coastguard Worker   UInt32 dictionaryId;
2761*f6dc9357SAndroid Build Coastguard Worker   UInt32 curBlockUnpackRem; // for compressed blocks only
2762*f6dc9357SAndroid Build Coastguard Worker   UInt32 inTempPos;
2763*f6dc9357SAndroid Build Coastguard Worker 
2764*f6dc9357SAndroid Build Coastguard Worker   UInt64 contentSize;
2765*f6dc9357SAndroid Build Coastguard Worker   UInt64 contentProcessed;
2766*f6dc9357SAndroid Build Coastguard Worker   CXxh64State xxh64;
2767*f6dc9357SAndroid Build Coastguard Worker 
2768*f6dc9357SAndroid Build Coastguard Worker   Byte *inTemp;
2769*f6dc9357SAndroid Build Coastguard Worker   SizeT winBufSize_Allocated;
2770*f6dc9357SAndroid Build Coastguard Worker   Byte *win_Base;
2771*f6dc9357SAndroid Build Coastguard Worker 
2772*f6dc9357SAndroid Build Coastguard Worker   ISzAllocPtr alloc_Small;
2773*f6dc9357SAndroid Build Coastguard Worker   ISzAllocPtr alloc_Big;
2774*f6dc9357SAndroid Build Coastguard Worker 
2775*f6dc9357SAndroid Build Coastguard Worker   CZstdDec1 decoder;
2776*f6dc9357SAndroid Build Coastguard Worker };
2777*f6dc9357SAndroid Build Coastguard Worker 
2778*f6dc9357SAndroid Build Coastguard Worker #define ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p) \
2779*f6dc9357SAndroid Build Coastguard Worker   ((unsigned)(p)->contentProcessed & (Z7_XXH64_BLOCK_SIZE - 1))
2780*f6dc9357SAndroid Build Coastguard Worker 
2781*f6dc9357SAndroid Build Coastguard Worker #define ZSTD_DEC_IS_LAST_BLOCK(p) ((p)->isLastBlock)
2782*f6dc9357SAndroid Build Coastguard Worker 
2783*f6dc9357SAndroid Build Coastguard Worker 
2784*f6dc9357SAndroid Build Coastguard Worker static void ZstdDec_FreeWindow(CZstdDec * const p)
2785*f6dc9357SAndroid Build Coastguard Worker {
2786*f6dc9357SAndroid Build Coastguard Worker   if (p->win_Base)
2787*f6dc9357SAndroid Build Coastguard Worker   {
2788*f6dc9357SAndroid Build Coastguard Worker     ISzAlloc_Free(p->alloc_Big, p->win_Base);
2789*f6dc9357SAndroid Build Coastguard Worker     p->win_Base = NULL;
2790*f6dc9357SAndroid Build Coastguard Worker     // p->decoder.win = NULL;
2791*f6dc9357SAndroid Build Coastguard Worker     p->winBufSize_Allocated = 0;
2792*f6dc9357SAndroid Build Coastguard Worker   }
2793*f6dc9357SAndroid Build Coastguard Worker }
2794*f6dc9357SAndroid Build Coastguard Worker 
2795*f6dc9357SAndroid Build Coastguard Worker 
2796*f6dc9357SAndroid Build Coastguard Worker CZstdDecHandle ZstdDec_Create(ISzAllocPtr alloc_Small, ISzAllocPtr alloc_Big)
2797*f6dc9357SAndroid Build Coastguard Worker {
2798*f6dc9357SAndroid Build Coastguard Worker   CZstdDec *p = (CZstdDec *)ISzAlloc_Alloc(alloc_Small, sizeof(CZstdDec));
2799*f6dc9357SAndroid Build Coastguard Worker   if (!p)
2800*f6dc9357SAndroid Build Coastguard Worker     return NULL;
2801*f6dc9357SAndroid Build Coastguard Worker   p->alloc_Small = alloc_Small;
2802*f6dc9357SAndroid Build Coastguard Worker   p->alloc_Big = alloc_Big;
2803*f6dc9357SAndroid Build Coastguard Worker   // ZstdDec_CONSTRUCT(p)
2804*f6dc9357SAndroid Build Coastguard Worker   p->inTemp = NULL;
2805*f6dc9357SAndroid Build Coastguard Worker   p->win_Base = NULL;
2806*f6dc9357SAndroid Build Coastguard Worker   p->winBufSize_Allocated = 0;
2807*f6dc9357SAndroid Build Coastguard Worker   p->disableHash = False;
2808*f6dc9357SAndroid Build Coastguard Worker   ZstdDec1_Construct(&p->decoder);
2809*f6dc9357SAndroid Build Coastguard Worker   return p;
2810*f6dc9357SAndroid Build Coastguard Worker }
2811*f6dc9357SAndroid Build Coastguard Worker 
2812*f6dc9357SAndroid Build Coastguard Worker void ZstdDec_Destroy(CZstdDecHandle p)
2813*f6dc9357SAndroid Build Coastguard Worker {
2814*f6dc9357SAndroid Build Coastguard Worker   #ifdef SHOW_STAT
2815*f6dc9357SAndroid Build Coastguard Worker     #define PRINT_STAT1(name, v) \
2816*f6dc9357SAndroid Build Coastguard Worker       printf("\n%25s = %9u", name, v);
2817*f6dc9357SAndroid Build Coastguard Worker   PRINT_STAT1("g_Num_Blocks_Compressed", g_Num_Blocks_Compressed)
2818*f6dc9357SAndroid Build Coastguard Worker   PRINT_STAT1("g_Num_Blocks_memcpy", g_Num_Blocks_memcpy)
2819*f6dc9357SAndroid Build Coastguard Worker   PRINT_STAT1("g_Num_Wrap_memmove_Num", g_Num_Wrap_memmove_Num)
2820*f6dc9357SAndroid Build Coastguard Worker   PRINT_STAT1("g_Num_Wrap_memmove_Bytes", g_Num_Wrap_memmove_Bytes)
2821*f6dc9357SAndroid Build Coastguard Worker   if (g_Num_Blocks_Compressed)
2822*f6dc9357SAndroid Build Coastguard Worker   {
2823*f6dc9357SAndroid Build Coastguard Worker     #define PRINT_STAT(name, v) \
2824*f6dc9357SAndroid Build Coastguard Worker       printf("\n%17s = %9u, per_block = %8u", name, v, v / g_Num_Blocks_Compressed);
2825*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_NumSeqs", g_NumSeqs_total)
2826*f6dc9357SAndroid Build Coastguard Worker     // PRINT_STAT("g_NumCopy", g_NumCopy)
2827*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_NumOver", g_NumOver)
2828*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_NumOver2", g_NumOver2)
2829*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Match", g_Num_Match)
2830*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Lits", g_Num_Lits)
2831*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_LitsBig", g_Num_LitsBig)
2832*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Lit0", g_Num_Lit0)
2833*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Rep_0", g_Num_Rep0)
2834*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Rep_1", g_Num_Rep1)
2835*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Rep_2", g_Num_Rep2)
2836*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Rep_3", g_Num_Rep3)
2837*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Threshold_0", g_Num_Threshold_0)
2838*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Threshold_1", g_Num_Threshold_1)
2839*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Threshold_0sum", g_Num_Threshold_0sum)
2840*f6dc9357SAndroid Build Coastguard Worker     PRINT_STAT("g_Num_Threshold_1sum", g_Num_Threshold_1sum)
2841*f6dc9357SAndroid Build Coastguard Worker   }
2842*f6dc9357SAndroid Build Coastguard Worker   printf("\n");
2843*f6dc9357SAndroid Build Coastguard Worker   #endif
2844*f6dc9357SAndroid Build Coastguard Worker 
2845*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(p->alloc_Small, p->decoder.literalsBase);
2846*f6dc9357SAndroid Build Coastguard Worker   // p->->decoder.literalsBase = NULL;
2847*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(p->alloc_Small, p->inTemp);
2848*f6dc9357SAndroid Build Coastguard Worker   // p->inTemp = NULL;
2849*f6dc9357SAndroid Build Coastguard Worker   ZstdDec_FreeWindow(p);
2850*f6dc9357SAndroid Build Coastguard Worker   ISzAlloc_Free(p->alloc_Small, p);
2851*f6dc9357SAndroid Build Coastguard Worker }
2852*f6dc9357SAndroid Build Coastguard Worker 
2853*f6dc9357SAndroid Build Coastguard Worker 
2854*f6dc9357SAndroid Build Coastguard Worker 
2855*f6dc9357SAndroid Build Coastguard Worker #define kTempBuffer_PreSize  (1u << 6)
2856*f6dc9357SAndroid Build Coastguard Worker #if kTempBuffer_PreSize < MAX_BACKWARD_DEPTH
2857*f6dc9357SAndroid Build Coastguard Worker   #error Stop_Compiling_Bad_kTempBuffer_PreSize
2858*f6dc9357SAndroid Build Coastguard Worker #endif
2859*f6dc9357SAndroid Build Coastguard Worker 
2860*f6dc9357SAndroid Build Coastguard Worker static SRes ZstdDec_AllocateMisc(CZstdDec *p)
2861*f6dc9357SAndroid Build Coastguard Worker {
2862*f6dc9357SAndroid Build Coastguard Worker   #define k_Lit_AfterAvail  (1u << 6)
2863*f6dc9357SAndroid Build Coastguard Worker   #if k_Lit_AfterAvail < (COPY_CHUNK_SIZE - 1)
2864*f6dc9357SAndroid Build Coastguard Worker     #error Stop_Compiling_Bad_k_Lit_AfterAvail
2865*f6dc9357SAndroid Build Coastguard Worker   #endif
2866*f6dc9357SAndroid Build Coastguard Worker   // return ZstdDec1_Allocate(&p->decoder, p->alloc_Small);
2867*f6dc9357SAndroid Build Coastguard Worker   if (!p->decoder.literalsBase)
2868*f6dc9357SAndroid Build Coastguard Worker   {
2869*f6dc9357SAndroid Build Coastguard Worker     p->decoder.literalsBase = (Byte *)ISzAlloc_Alloc(p->alloc_Small,
2870*f6dc9357SAndroid Build Coastguard Worker         kBlockSizeMax + k_Lit_AfterAvail);
2871*f6dc9357SAndroid Build Coastguard Worker     if (!p->decoder.literalsBase)
2872*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_MEM;
2873*f6dc9357SAndroid Build Coastguard Worker   }
2874*f6dc9357SAndroid Build Coastguard Worker   if (!p->inTemp)
2875*f6dc9357SAndroid Build Coastguard Worker   {
2876*f6dc9357SAndroid Build Coastguard Worker     // we need k_Lit_AfterAvail here for owerread from raw literals stream
2877*f6dc9357SAndroid Build Coastguard Worker     p->inTemp = (Byte *)ISzAlloc_Alloc(p->alloc_Small,
2878*f6dc9357SAndroid Build Coastguard Worker         kBlockSizeMax + kTempBuffer_PreSize + k_Lit_AfterAvail);
2879*f6dc9357SAndroid Build Coastguard Worker     if (!p->inTemp)
2880*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_MEM;
2881*f6dc9357SAndroid Build Coastguard Worker   }
2882*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
2883*f6dc9357SAndroid Build Coastguard Worker }
2884*f6dc9357SAndroid Build Coastguard Worker 
2885*f6dc9357SAndroid Build Coastguard Worker 
2886*f6dc9357SAndroid Build Coastguard Worker static void ZstdDec_Init_ForNewFrame(CZstdDec *p)
2887*f6dc9357SAndroid Build Coastguard Worker {
2888*f6dc9357SAndroid Build Coastguard Worker   p->frameState = ZSTD2_STATE_SIGNATURE;
2889*f6dc9357SAndroid Build Coastguard Worker   p->tempSize = 0;
2890*f6dc9357SAndroid Build Coastguard Worker 
2891*f6dc9357SAndroid Build Coastguard Worker   p->isErrorState = False;
2892*f6dc9357SAndroid Build Coastguard Worker   p->hashError = False;
2893*f6dc9357SAndroid Build Coastguard Worker   p->isCyclicMode = False;
2894*f6dc9357SAndroid Build Coastguard Worker   p->contentProcessed = 0;
2895*f6dc9357SAndroid Build Coastguard Worker   Xxh64State_Init(&p->xxh64);
2896*f6dc9357SAndroid Build Coastguard Worker   ZstdDec1_Init(&p->decoder);
2897*f6dc9357SAndroid Build Coastguard Worker }
2898*f6dc9357SAndroid Build Coastguard Worker 
2899*f6dc9357SAndroid Build Coastguard Worker 
2900*f6dc9357SAndroid Build Coastguard Worker void ZstdDec_Init(CZstdDec *p)
2901*f6dc9357SAndroid Build Coastguard Worker {
2902*f6dc9357SAndroid Build Coastguard Worker   ZstdDec_Init_ForNewFrame(p);
2903*f6dc9357SAndroid Build Coastguard Worker   p->decoder.winPos = 0;
2904*f6dc9357SAndroid Build Coastguard Worker   memset(p->temp, 0, sizeof(p->temp));
2905*f6dc9357SAndroid Build Coastguard Worker }
2906*f6dc9357SAndroid Build Coastguard Worker 
2907*f6dc9357SAndroid Build Coastguard Worker 
2908*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_Get_DictionaryId_Flag(d)   ((d) & 3)
2909*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_FLAG_CHECKSUM              (1 << 2)
2910*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_FLAG_RESERVED              (1 << 3)
2911*f6dc9357SAndroid Build Coastguard Worker // #define DESCRIPTOR_FLAG_UNUSED                (1 << 4)
2912*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_FLAG_SINGLE                (1 << 5)
2913*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_Get_ContentSize_Flag3(d)   ((d) >> 5)
2914*f6dc9357SAndroid Build Coastguard Worker #define DESCRIPTOR_Is_ContentSize_Defined(d)  (((d) & 0xe0) != 0)
2915*f6dc9357SAndroid Build Coastguard Worker 
2916*f6dc9357SAndroid Build Coastguard Worker 
2917*f6dc9357SAndroid Build Coastguard Worker static EZstd2State ZstdDec_UpdateState(CZstdDec * const p, const Byte b, CZstdDecInfo * const info)
2918*f6dc9357SAndroid Build Coastguard Worker {
2919*f6dc9357SAndroid Build Coastguard Worker   unsigned tempSize = p->tempSize;
2920*f6dc9357SAndroid Build Coastguard Worker   p->temp[tempSize++] = b;
2921*f6dc9357SAndroid Build Coastguard Worker   p->tempSize = tempSize;
2922*f6dc9357SAndroid Build Coastguard Worker 
2923*f6dc9357SAndroid Build Coastguard Worker   if (p->frameState == ZSTD2_STATE_BLOCK)
2924*f6dc9357SAndroid Build Coastguard Worker   {
2925*f6dc9357SAndroid Build Coastguard Worker     if (tempSize < 3)
2926*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_BLOCK;
2927*f6dc9357SAndroid Build Coastguard Worker     {
2928*f6dc9357SAndroid Build Coastguard Worker       UInt32 b0 = GetUi32(p->temp);
2929*f6dc9357SAndroid Build Coastguard Worker       const unsigned type = ((unsigned)b0 >> 1) & 3;
2930*f6dc9357SAndroid Build Coastguard Worker       if (type == kBlockType_RLE && tempSize == 3)
2931*f6dc9357SAndroid Build Coastguard Worker         return ZSTD2_STATE_BLOCK;
2932*f6dc9357SAndroid Build Coastguard Worker       // info->num_Blocks_forType[type]++;
2933*f6dc9357SAndroid Build Coastguard Worker       info->num_Blocks++;
2934*f6dc9357SAndroid Build Coastguard Worker       if (type == kBlockType_Reserved)
2935*f6dc9357SAndroid Build Coastguard Worker       {
2936*f6dc9357SAndroid Build Coastguard Worker         p->isErrorState = True; // SZ_ERROR_UNSUPPORTED
2937*f6dc9357SAndroid Build Coastguard Worker         return ZSTD2_STATE_BLOCK;
2938*f6dc9357SAndroid Build Coastguard Worker       }
2939*f6dc9357SAndroid Build Coastguard Worker       p->blockType = (Byte)type;
2940*f6dc9357SAndroid Build Coastguard Worker       p->isLastBlock = (Byte)(b0 & 1);
2941*f6dc9357SAndroid Build Coastguard Worker       p->inTempPos = 0;
2942*f6dc9357SAndroid Build Coastguard Worker       p->tempSize = 0;
2943*f6dc9357SAndroid Build Coastguard Worker       b0 >>= 3;
2944*f6dc9357SAndroid Build Coastguard Worker       b0 &= 0x1fffff;
2945*f6dc9357SAndroid Build Coastguard Worker       // info->num_BlockBytes_forType[type] += b0;
2946*f6dc9357SAndroid Build Coastguard Worker       if (b0 == 0)
2947*f6dc9357SAndroid Build Coastguard Worker       {
2948*f6dc9357SAndroid Build Coastguard Worker         // empty RAW/RLE blocks are allowed in original-zstd decoder
2949*f6dc9357SAndroid Build Coastguard Worker         if (type == kBlockType_Compressed)
2950*f6dc9357SAndroid Build Coastguard Worker         {
2951*f6dc9357SAndroid Build Coastguard Worker           p->isErrorState = True;
2952*f6dc9357SAndroid Build Coastguard Worker           return ZSTD2_STATE_BLOCK;
2953*f6dc9357SAndroid Build Coastguard Worker         }
2954*f6dc9357SAndroid Build Coastguard Worker         if (!ZSTD_DEC_IS_LAST_BLOCK(p))
2955*f6dc9357SAndroid Build Coastguard Worker           return ZSTD2_STATE_BLOCK;
2956*f6dc9357SAndroid Build Coastguard Worker         if (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM)
2957*f6dc9357SAndroid Build Coastguard Worker           return ZSTD2_STATE_HASH;
2958*f6dc9357SAndroid Build Coastguard Worker         return ZSTD2_STATE_FINISHED;
2959*f6dc9357SAndroid Build Coastguard Worker       }
2960*f6dc9357SAndroid Build Coastguard Worker       p->blockSize = b0;
2961*f6dc9357SAndroid Build Coastguard Worker       {
2962*f6dc9357SAndroid Build Coastguard Worker         UInt32 blockLim = ZstdDec1_GET_BLOCK_SIZE_LIMIT(&p->decoder);
2963*f6dc9357SAndroid Build Coastguard Worker         // compressed and uncompressed block sizes cannot be larger than min(kBlockSizeMax, window_size)
2964*f6dc9357SAndroid Build Coastguard Worker         if (b0 > blockLim)
2965*f6dc9357SAndroid Build Coastguard Worker         {
2966*f6dc9357SAndroid Build Coastguard Worker           p->isErrorState = True; // SZ_ERROR_UNSUPPORTED;
2967*f6dc9357SAndroid Build Coastguard Worker           return ZSTD2_STATE_BLOCK;
2968*f6dc9357SAndroid Build Coastguard Worker         }
2969*f6dc9357SAndroid Build Coastguard Worker         if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor))
2970*f6dc9357SAndroid Build Coastguard Worker         {
2971*f6dc9357SAndroid Build Coastguard Worker           const UInt64 rem = p->contentSize - p->contentProcessed;
2972*f6dc9357SAndroid Build Coastguard Worker           if (blockLim > rem)
2973*f6dc9357SAndroid Build Coastguard Worker               blockLim = (UInt32)rem;
2974*f6dc9357SAndroid Build Coastguard Worker         }
2975*f6dc9357SAndroid Build Coastguard Worker         p->curBlockUnpackRem = blockLim;
2976*f6dc9357SAndroid Build Coastguard Worker         // uncompressed block size cannot be larger than remain data size:
2977*f6dc9357SAndroid Build Coastguard Worker         if (type != kBlockType_Compressed)
2978*f6dc9357SAndroid Build Coastguard Worker         {
2979*f6dc9357SAndroid Build Coastguard Worker           if (b0 > blockLim)
2980*f6dc9357SAndroid Build Coastguard Worker           {
2981*f6dc9357SAndroid Build Coastguard Worker             p->isErrorState = True; // SZ_ERROR_UNSUPPORTED;
2982*f6dc9357SAndroid Build Coastguard Worker             return ZSTD2_STATE_BLOCK;
2983*f6dc9357SAndroid Build Coastguard Worker           }
2984*f6dc9357SAndroid Build Coastguard Worker         }
2985*f6dc9357SAndroid Build Coastguard Worker       }
2986*f6dc9357SAndroid Build Coastguard Worker     }
2987*f6dc9357SAndroid Build Coastguard Worker     return ZSTD2_STATE_DATA;
2988*f6dc9357SAndroid Build Coastguard Worker   }
2989*f6dc9357SAndroid Build Coastguard Worker 
2990*f6dc9357SAndroid Build Coastguard Worker   if ((unsigned)p->frameState < ZSTD2_STATE_SKIP_DATA)
2991*f6dc9357SAndroid Build Coastguard Worker   {
2992*f6dc9357SAndroid Build Coastguard Worker     UInt32 v;
2993*f6dc9357SAndroid Build Coastguard Worker     if (tempSize != 4)
2994*f6dc9357SAndroid Build Coastguard Worker       return p->frameState;
2995*f6dc9357SAndroid Build Coastguard Worker     v = GetUi32(p->temp);
2996*f6dc9357SAndroid Build Coastguard Worker     if ((unsigned)p->frameState < ZSTD2_STATE_HASH) // == ZSTD2_STATE_SIGNATURE
2997*f6dc9357SAndroid Build Coastguard Worker     {
2998*f6dc9357SAndroid Build Coastguard Worker       if (v == 0xfd2fb528)
2999*f6dc9357SAndroid Build Coastguard Worker       {
3000*f6dc9357SAndroid Build Coastguard Worker         p->tempSize = 0;
3001*f6dc9357SAndroid Build Coastguard Worker         info->num_DataFrames++;
3002*f6dc9357SAndroid Build Coastguard Worker         return ZSTD2_STATE_FRAME_HEADER;
3003*f6dc9357SAndroid Build Coastguard Worker       }
3004*f6dc9357SAndroid Build Coastguard Worker       if ((v & 0xfffffff0) == 0x184d2a50)
3005*f6dc9357SAndroid Build Coastguard Worker       {
3006*f6dc9357SAndroid Build Coastguard Worker         p->tempSize = 0;
3007*f6dc9357SAndroid Build Coastguard Worker         info->num_SkipFrames++;
3008*f6dc9357SAndroid Build Coastguard Worker         return ZSTD2_STATE_SKIP_HEADER;
3009*f6dc9357SAndroid Build Coastguard Worker       }
3010*f6dc9357SAndroid Build Coastguard Worker       p->isErrorState = True;
3011*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_SIGNATURE;
3012*f6dc9357SAndroid Build Coastguard Worker       // return ZSTD2_STATE_ERROR; // is not ZSTD stream
3013*f6dc9357SAndroid Build Coastguard Worker     }
3014*f6dc9357SAndroid Build Coastguard Worker     if (p->frameState == ZSTD2_STATE_HASH)
3015*f6dc9357SAndroid Build Coastguard Worker     {
3016*f6dc9357SAndroid Build Coastguard Worker       info->checksum_Defined = True;
3017*f6dc9357SAndroid Build Coastguard Worker       info->checksum = v;
3018*f6dc9357SAndroid Build Coastguard Worker       // #ifndef DISABLE_XXH_CHECK
3019*f6dc9357SAndroid Build Coastguard Worker       if (!p->disableHash)
3020*f6dc9357SAndroid Build Coastguard Worker       {
3021*f6dc9357SAndroid Build Coastguard Worker         if (p->decoder.winPos < ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p))
3022*f6dc9357SAndroid Build Coastguard Worker         {
3023*f6dc9357SAndroid Build Coastguard Worker           // unexpected code failure
3024*f6dc9357SAndroid Build Coastguard Worker           p->isErrorState = True;
3025*f6dc9357SAndroid Build Coastguard Worker           // SZ_ERROR_FAIL;
3026*f6dc9357SAndroid Build Coastguard Worker         }
3027*f6dc9357SAndroid Build Coastguard Worker         else
3028*f6dc9357SAndroid Build Coastguard Worker         if ((UInt32)Xxh64State_Digest(&p->xxh64,
3029*f6dc9357SAndroid Build Coastguard Worker             p->decoder.win + (p->decoder.winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p)),
3030*f6dc9357SAndroid Build Coastguard Worker             p->contentProcessed) != v)
3031*f6dc9357SAndroid Build Coastguard Worker         {
3032*f6dc9357SAndroid Build Coastguard Worker           p->hashError = True;
3033*f6dc9357SAndroid Build Coastguard Worker           // return ZSTD2_STATE_ERROR; // hash error
3034*f6dc9357SAndroid Build Coastguard Worker         }
3035*f6dc9357SAndroid Build Coastguard Worker       }
3036*f6dc9357SAndroid Build Coastguard Worker       // #endif
3037*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_FINISHED;
3038*f6dc9357SAndroid Build Coastguard Worker     }
3039*f6dc9357SAndroid Build Coastguard Worker     // (p->frameState == ZSTD2_STATE_SKIP_HEADER)
3040*f6dc9357SAndroid Build Coastguard Worker     {
3041*f6dc9357SAndroid Build Coastguard Worker       p->blockSize = v;
3042*f6dc9357SAndroid Build Coastguard Worker       info->skipFrames_Size += v;
3043*f6dc9357SAndroid Build Coastguard Worker       p->tempSize = 0;
3044*f6dc9357SAndroid Build Coastguard Worker       /* we want the caller could know that there was finished frame
3045*f6dc9357SAndroid Build Coastguard Worker          finished frame. So we allow the case where
3046*f6dc9357SAndroid Build Coastguard Worker          we have ZSTD2_STATE_SKIP_DATA state with (blockSize == 0).
3047*f6dc9357SAndroid Build Coastguard Worker       */
3048*f6dc9357SAndroid Build Coastguard Worker       // if (v == 0) return ZSTD2_STATE_SIGNATURE;
3049*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_SKIP_DATA;
3050*f6dc9357SAndroid Build Coastguard Worker     }
3051*f6dc9357SAndroid Build Coastguard Worker   }
3052*f6dc9357SAndroid Build Coastguard Worker 
3053*f6dc9357SAndroid Build Coastguard Worker   // if (p->frameState == ZSTD2_STATE_FRAME_HEADER)
3054*f6dc9357SAndroid Build Coastguard Worker   {
3055*f6dc9357SAndroid Build Coastguard Worker     unsigned descriptor;
3056*f6dc9357SAndroid Build Coastguard Worker     const Byte *h;
3057*f6dc9357SAndroid Build Coastguard Worker     descriptor = p->temp[0];
3058*f6dc9357SAndroid Build Coastguard Worker     p->descriptor = (Byte)descriptor;
3059*f6dc9357SAndroid Build Coastguard Worker     if (descriptor & DESCRIPTOR_FLAG_RESERVED) // reserved bit
3060*f6dc9357SAndroid Build Coastguard Worker     {
3061*f6dc9357SAndroid Build Coastguard Worker       p->isErrorState = True;
3062*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_FRAME_HEADER;
3063*f6dc9357SAndroid Build Coastguard Worker       // return ZSTD2_STATE_ERROR;
3064*f6dc9357SAndroid Build Coastguard Worker     }
3065*f6dc9357SAndroid Build Coastguard Worker     {
3066*f6dc9357SAndroid Build Coastguard Worker       const unsigned n = DESCRIPTOR_Get_ContentSize_Flag3(descriptor);
3067*f6dc9357SAndroid Build Coastguard Worker       // tempSize -= 1 + ((1u << (n >> 1)) | ((n + 1) & 1));
3068*f6dc9357SAndroid Build Coastguard Worker       tempSize -= (0x9a563422u >> (n * 4)) & 0xf;
3069*f6dc9357SAndroid Build Coastguard Worker     }
3070*f6dc9357SAndroid Build Coastguard Worker     if (tempSize != (4u >> (3 - DESCRIPTOR_Get_DictionaryId_Flag(descriptor))))
3071*f6dc9357SAndroid Build Coastguard Worker       return ZSTD2_STATE_FRAME_HEADER;
3072*f6dc9357SAndroid Build Coastguard Worker 
3073*f6dc9357SAndroid Build Coastguard Worker     info->descriptor_OR     = (Byte)(info->descriptor_OR     |  descriptor);
3074*f6dc9357SAndroid Build Coastguard Worker     info->descriptor_NOT_OR = (Byte)(info->descriptor_NOT_OR | ~descriptor);
3075*f6dc9357SAndroid Build Coastguard Worker 
3076*f6dc9357SAndroid Build Coastguard Worker     h = &p->temp[1];
3077*f6dc9357SAndroid Build Coastguard Worker     {
3078*f6dc9357SAndroid Build Coastguard Worker       Byte w = 0;
3079*f6dc9357SAndroid Build Coastguard Worker       if ((descriptor & DESCRIPTOR_FLAG_SINGLE) == 0)
3080*f6dc9357SAndroid Build Coastguard Worker       {
3081*f6dc9357SAndroid Build Coastguard Worker         w = *h++;
3082*f6dc9357SAndroid Build Coastguard Worker         if (info->windowDescriptor_MAX < w)
3083*f6dc9357SAndroid Build Coastguard Worker             info->windowDescriptor_MAX = w;
3084*f6dc9357SAndroid Build Coastguard Worker         // info->are_WindowDescriptors = True;
3085*f6dc9357SAndroid Build Coastguard Worker         // info->num_WindowDescriptors++;
3086*f6dc9357SAndroid Build Coastguard Worker       }
3087*f6dc9357SAndroid Build Coastguard Worker       else
3088*f6dc9357SAndroid Build Coastguard Worker       {
3089*f6dc9357SAndroid Build Coastguard Worker         // info->are_SingleSegments = True;
3090*f6dc9357SAndroid Build Coastguard Worker         // info->num_SingleSegments++;
3091*f6dc9357SAndroid Build Coastguard Worker       }
3092*f6dc9357SAndroid Build Coastguard Worker       p->windowDescriptor = w;
3093*f6dc9357SAndroid Build Coastguard Worker     }
3094*f6dc9357SAndroid Build Coastguard Worker     {
3095*f6dc9357SAndroid Build Coastguard Worker       unsigned n = DESCRIPTOR_Get_DictionaryId_Flag(descriptor);
3096*f6dc9357SAndroid Build Coastguard Worker       UInt32 d = 0;
3097*f6dc9357SAndroid Build Coastguard Worker       if (n)
3098*f6dc9357SAndroid Build Coastguard Worker       {
3099*f6dc9357SAndroid Build Coastguard Worker         n = 1u << (n - 1);
3100*f6dc9357SAndroid Build Coastguard Worker         d = GetUi32(h) & ((UInt32)(Int32)-1 >> (32 - 8u * n));
3101*f6dc9357SAndroid Build Coastguard Worker         h += n;
3102*f6dc9357SAndroid Build Coastguard Worker       }
3103*f6dc9357SAndroid Build Coastguard Worker       p->dictionaryId = d;
3104*f6dc9357SAndroid Build Coastguard Worker       // info->dictionaryId_Cur = d;
3105*f6dc9357SAndroid Build Coastguard Worker       if (d != 0)
3106*f6dc9357SAndroid Build Coastguard Worker       {
3107*f6dc9357SAndroid Build Coastguard Worker         if (info->dictionaryId == 0)
3108*f6dc9357SAndroid Build Coastguard Worker           info->dictionaryId = d;
3109*f6dc9357SAndroid Build Coastguard Worker         else if (info->dictionaryId != d)
3110*f6dc9357SAndroid Build Coastguard Worker           info->are_DictionaryId_Different = True;
3111*f6dc9357SAndroid Build Coastguard Worker       }
3112*f6dc9357SAndroid Build Coastguard Worker     }
3113*f6dc9357SAndroid Build Coastguard Worker     {
3114*f6dc9357SAndroid Build Coastguard Worker       unsigned n = DESCRIPTOR_Get_ContentSize_Flag3(descriptor);
3115*f6dc9357SAndroid Build Coastguard Worker       UInt64 v = 0;
3116*f6dc9357SAndroid Build Coastguard Worker       if (n)
3117*f6dc9357SAndroid Build Coastguard Worker       {
3118*f6dc9357SAndroid Build Coastguard Worker         n >>= 1;
3119*f6dc9357SAndroid Build Coastguard Worker         if (n == 1)
3120*f6dc9357SAndroid Build Coastguard Worker           v = 256;
3121*f6dc9357SAndroid Build Coastguard Worker         v += GetUi64(h) & ((UInt64)(Int64)-1 >> (64 - (8u << n)));
3122*f6dc9357SAndroid Build Coastguard Worker         // info->are_ContentSize_Known = True;
3123*f6dc9357SAndroid Build Coastguard Worker         // info->num_Frames_with_ContentSize++;
3124*f6dc9357SAndroid Build Coastguard Worker         if (info->contentSize_MAX < v)
3125*f6dc9357SAndroid Build Coastguard Worker             info->contentSize_MAX = v;
3126*f6dc9357SAndroid Build Coastguard Worker         info->contentSize_Total += v;
3127*f6dc9357SAndroid Build Coastguard Worker       }
3128*f6dc9357SAndroid Build Coastguard Worker       else
3129*f6dc9357SAndroid Build Coastguard Worker       {
3130*f6dc9357SAndroid Build Coastguard Worker         info->are_ContentSize_Unknown = True;
3131*f6dc9357SAndroid Build Coastguard Worker         // info->num_Frames_without_ContentSize++;
3132*f6dc9357SAndroid Build Coastguard Worker       }
3133*f6dc9357SAndroid Build Coastguard Worker       p->contentSize = v;
3134*f6dc9357SAndroid Build Coastguard Worker     }
3135*f6dc9357SAndroid Build Coastguard Worker     // if ((size_t)(h - p->temp) != headerSize) return ZSTD2_STATE_ERROR; // it's unexpected internal code failure
3136*f6dc9357SAndroid Build Coastguard Worker     p->tempSize = 0;
3137*f6dc9357SAndroid Build Coastguard Worker 
3138*f6dc9357SAndroid Build Coastguard Worker     info->checksum_Defined = False;
3139*f6dc9357SAndroid Build Coastguard Worker     /*
3140*f6dc9357SAndroid Build Coastguard Worker     if (descriptor & DESCRIPTOR_FLAG_CHECKSUM)
3141*f6dc9357SAndroid Build Coastguard Worker       info->are_Checksums = True;
3142*f6dc9357SAndroid Build Coastguard Worker     else
3143*f6dc9357SAndroid Build Coastguard Worker       info->are_Non_Checksums = True;
3144*f6dc9357SAndroid Build Coastguard Worker     */
3145*f6dc9357SAndroid Build Coastguard Worker 
3146*f6dc9357SAndroid Build Coastguard Worker     return ZSTD2_STATE_AFTER_HEADER; // ZSTD2_STATE_BLOCK;
3147*f6dc9357SAndroid Build Coastguard Worker   }
3148*f6dc9357SAndroid Build Coastguard Worker }
3149*f6dc9357SAndroid Build Coastguard Worker 
3150*f6dc9357SAndroid Build Coastguard Worker 
3151*f6dc9357SAndroid Build Coastguard Worker static void ZstdDec_Update_XXH(CZstdDec * const p, size_t xxh64_winPos)
3152*f6dc9357SAndroid Build Coastguard Worker {
3153*f6dc9357SAndroid Build Coastguard Worker  /*
3154*f6dc9357SAndroid Build Coastguard Worker  #ifdef DISABLE_XXH_CHECK
3155*f6dc9357SAndroid Build Coastguard Worker   UNUSED_VAR(data)
3156*f6dc9357SAndroid Build Coastguard Worker  #else
3157*f6dc9357SAndroid Build Coastguard Worker  */
3158*f6dc9357SAndroid Build Coastguard Worker   if (!p->disableHash && (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM))
3159*f6dc9357SAndroid Build Coastguard Worker   {
3160*f6dc9357SAndroid Build Coastguard Worker     // const size_t pos = p->xxh64_winPos;
3161*f6dc9357SAndroid Build Coastguard Worker     const size_t size = (p->decoder.winPos - xxh64_winPos) & ~(size_t)31;
3162*f6dc9357SAndroid Build Coastguard Worker     if (size)
3163*f6dc9357SAndroid Build Coastguard Worker     {
3164*f6dc9357SAndroid Build Coastguard Worker       // p->xxh64_winPos = pos + size;
3165*f6dc9357SAndroid Build Coastguard Worker       Xxh64State_UpdateBlocks(&p->xxh64,
3166*f6dc9357SAndroid Build Coastguard Worker           p->decoder.win + xxh64_winPos,
3167*f6dc9357SAndroid Build Coastguard Worker           p->decoder.win + xxh64_winPos + size);
3168*f6dc9357SAndroid Build Coastguard Worker     }
3169*f6dc9357SAndroid Build Coastguard Worker   }
3170*f6dc9357SAndroid Build Coastguard Worker }
3171*f6dc9357SAndroid Build Coastguard Worker 
3172*f6dc9357SAndroid Build Coastguard Worker 
3173*f6dc9357SAndroid Build Coastguard Worker /*
3174*f6dc9357SAndroid Build Coastguard Worker in:
3175*f6dc9357SAndroid Build Coastguard Worker   (winLimit) : is relaxed limit, where this function is allowed to stop writing of decoded data (if possible).
3176*f6dc9357SAndroid Build Coastguard Worker     - this function uses (winLimit) for RAW/RLE blocks only,
3177*f6dc9357SAndroid Build Coastguard Worker         because this function can decode single RAW/RLE block in several different calls.
3178*f6dc9357SAndroid Build Coastguard Worker     - this function DOESN'T use (winLimit) for Compressed blocks,
3179*f6dc9357SAndroid Build Coastguard Worker         because this function decodes full compressed block in single call.
3180*f6dc9357SAndroid Build Coastguard Worker   (CZstdDec1::winPos <= winLimit)
3181*f6dc9357SAndroid Build Coastguard Worker   (winLimit <= CZstdDec1::cycSize).
3182*f6dc9357SAndroid Build Coastguard Worker   Note: if (ds->outBuf_fromCaller) mode is used, then
3183*f6dc9357SAndroid Build Coastguard Worker   {
3184*f6dc9357SAndroid Build Coastguard Worker     (strong_limit) is stored in CZstdDec1::cycSize.
3185*f6dc9357SAndroid Build Coastguard Worker     So (winLimit) is more strong than (strong_limit).
3186*f6dc9357SAndroid Build Coastguard Worker   }
3187*f6dc9357SAndroid Build Coastguard Worker 
3188*f6dc9357SAndroid Build Coastguard Worker exit:
3189*f6dc9357SAndroid Build Coastguard Worker   Note: (CZstdDecState::winPos) will be set by caller after exit of this function.
3190*f6dc9357SAndroid Build Coastguard Worker 
3191*f6dc9357SAndroid Build Coastguard Worker   This function can exit for any of these conditions:
3192*f6dc9357SAndroid Build Coastguard Worker     - (frameState == ZSTD2_STATE_AFTER_HEADER)
3193*f6dc9357SAndroid Build Coastguard Worker     - (frameState == ZSTD2_STATE_FINISHED) : frame was finished : (status == ZSTD_STATUS_FINISHED_FRAME) is set
3194*f6dc9357SAndroid Build Coastguard Worker     - finished non-empty non-last block. So (CZstdDec1::winPos_atExit != winPos_atFuncStart).
3195*f6dc9357SAndroid Build Coastguard Worker     - ZSTD_STATUS_NEEDS_MORE_INPUT in src
3196*f6dc9357SAndroid Build Coastguard Worker     - (CZstdDec1::winPos) have reached (winLimit) in non-finished RAW/RLE block
3197*f6dc9357SAndroid Build Coastguard Worker 
3198*f6dc9357SAndroid Build Coastguard Worker   This function decodes no more than one non-empty block.
3199*f6dc9357SAndroid Build Coastguard Worker   So it fulfills the condition at exit:
3200*f6dc9357SAndroid Build Coastguard Worker     (CZstdDec1::winPos_atExit - winPos_atFuncStart <= block_size_max)
3201*f6dc9357SAndroid Build Coastguard Worker   Note: (winPos_atExit > winLimit) is possible in some cases after compressed block decoding.
3202*f6dc9357SAndroid Build Coastguard Worker 
3203*f6dc9357SAndroid Build Coastguard Worker   if (ds->outBuf_fromCaller) mode (useAdditionalWinLimit medo)
3204*f6dc9357SAndroid Build Coastguard Worker   {
3205*f6dc9357SAndroid Build Coastguard Worker     then this function uses additional strong limit from (CZstdDec1::cycSize).
3206*f6dc9357SAndroid Build Coastguard Worker     So this function will not write any data after (CZstdDec1::cycSize)
3207*f6dc9357SAndroid Build Coastguard Worker     And it fulfills the condition at exit:
3208*f6dc9357SAndroid Build Coastguard Worker       (CZstdDec1::winPos_atExit <= CZstdDec1::cycSize)
3209*f6dc9357SAndroid Build Coastguard Worker   }
3210*f6dc9357SAndroid Build Coastguard Worker */
3211*f6dc9357SAndroid Build Coastguard Worker static SRes ZstdDec_DecodeBlock(CZstdDec * const p, CZstdDecState * const ds,
3212*f6dc9357SAndroid Build Coastguard Worker     SizeT winLimitAdd)
3213*f6dc9357SAndroid Build Coastguard Worker {
3214*f6dc9357SAndroid Build Coastguard Worker   const Byte *src = ds->inBuf;
3215*f6dc9357SAndroid Build Coastguard Worker   SizeT * const srcLen = &ds->inPos;
3216*f6dc9357SAndroid Build Coastguard Worker   const SizeT inSize = ds->inLim;
3217*f6dc9357SAndroid Build Coastguard Worker   // const int useAdditionalWinLimit = ds->outBuf_fromCaller ? 1 : 0;
3218*f6dc9357SAndroid Build Coastguard Worker   enum_ZstdStatus * const status = &ds->status;
3219*f6dc9357SAndroid Build Coastguard Worker   CZstdDecInfo * const info = &ds->info;
3220*f6dc9357SAndroid Build Coastguard Worker   SizeT winLimit;
3221*f6dc9357SAndroid Build Coastguard Worker 
3222*f6dc9357SAndroid Build Coastguard Worker   const SizeT winPos_atFuncStart = p->decoder.winPos;
3223*f6dc9357SAndroid Build Coastguard Worker   src += *srcLen;
3224*f6dc9357SAndroid Build Coastguard Worker   *status = ZSTD_STATUS_NOT_SPECIFIED;
3225*f6dc9357SAndroid Build Coastguard Worker 
3226*f6dc9357SAndroid Build Coastguard Worker   // finishMode = ZSTD_FINISH_ANY;
3227*f6dc9357SAndroid Build Coastguard Worker   if (ds->outSize_Defined)
3228*f6dc9357SAndroid Build Coastguard Worker   {
3229*f6dc9357SAndroid Build Coastguard Worker     if (ds->outSize < ds->outProcessed)
3230*f6dc9357SAndroid Build Coastguard Worker     {
3231*f6dc9357SAndroid Build Coastguard Worker       // p->isAfterSizeMode = 2; // we have extra bytes already
3232*f6dc9357SAndroid Build Coastguard Worker       *status = ZSTD_STATUS_OUT_REACHED;
3233*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
3234*f6dc9357SAndroid Build Coastguard Worker       // size = 0;
3235*f6dc9357SAndroid Build Coastguard Worker     }
3236*f6dc9357SAndroid Build Coastguard Worker     else
3237*f6dc9357SAndroid Build Coastguard Worker     {
3238*f6dc9357SAndroid Build Coastguard Worker       // p->outSize >= p->outProcessed
3239*f6dc9357SAndroid Build Coastguard Worker       const UInt64 rem = ds->outSize - ds->outProcessed;
3240*f6dc9357SAndroid Build Coastguard Worker       /*
3241*f6dc9357SAndroid Build Coastguard Worker       if (rem == 0)
3242*f6dc9357SAndroid Build Coastguard Worker       p->isAfterSizeMode = 1; // we have reached exact required size
3243*f6dc9357SAndroid Build Coastguard Worker       */
3244*f6dc9357SAndroid Build Coastguard Worker       if (winLimitAdd >= rem)
3245*f6dc9357SAndroid Build Coastguard Worker       {
3246*f6dc9357SAndroid Build Coastguard Worker         winLimitAdd = (SizeT)rem;
3247*f6dc9357SAndroid Build Coastguard Worker         // if (p->finishMode) finishMode = ZSTD_FINISH_END;
3248*f6dc9357SAndroid Build Coastguard Worker       }
3249*f6dc9357SAndroid Build Coastguard Worker     }
3250*f6dc9357SAndroid Build Coastguard Worker   }
3251*f6dc9357SAndroid Build Coastguard Worker 
3252*f6dc9357SAndroid Build Coastguard Worker   winLimit = p->decoder.winPos + winLimitAdd;
3253*f6dc9357SAndroid Build Coastguard Worker   // (p->decoder.winPos <= winLimit)
3254*f6dc9357SAndroid Build Coastguard Worker 
3255*f6dc9357SAndroid Build Coastguard Worker   // while (p->frameState != ZSTD2_STATE_ERROR)
3256*f6dc9357SAndroid Build Coastguard Worker   while (!p->isErrorState)
3257*f6dc9357SAndroid Build Coastguard Worker   {
3258*f6dc9357SAndroid Build Coastguard Worker     SizeT inCur = inSize - *srcLen;
3259*f6dc9357SAndroid Build Coastguard Worker 
3260*f6dc9357SAndroid Build Coastguard Worker     if (p->frameState == ZSTD2_STATE_DATA)
3261*f6dc9357SAndroid Build Coastguard Worker     {
3262*f6dc9357SAndroid Build Coastguard Worker       /* (p->decoder.winPos == winPos_atFuncStart) is expected,
3263*f6dc9357SAndroid Build Coastguard Worker          because this function doesn't start new block.
3264*f6dc9357SAndroid Build Coastguard Worker          if it have finished some non-empty block in this call. */
3265*f6dc9357SAndroid Build Coastguard Worker       if (p->decoder.winPos != winPos_atFuncStart)
3266*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_FAIL; // it's unexpected
3267*f6dc9357SAndroid Build Coastguard Worker 
3268*f6dc9357SAndroid Build Coastguard Worker       /*
3269*f6dc9357SAndroid Build Coastguard Worker       if (p->decoder.winPos > winLimit)
3270*f6dc9357SAndroid Build Coastguard Worker       {
3271*f6dc9357SAndroid Build Coastguard Worker         // we can be here, if in this function call
3272*f6dc9357SAndroid Build Coastguard Worker         //      - we have extracted non-empty compressed block, and (winPos > winLimit) after that.
3273*f6dc9357SAndroid Build Coastguard Worker         //      - we have started new block decoding after that.
3274*f6dc9357SAndroid Build Coastguard Worker         // It's unexpected case, because we exit after non-empty non-last block.
3275*f6dc9357SAndroid Build Coastguard Worker         *status = (inSize == *srcLen) ?
3276*f6dc9357SAndroid Build Coastguard Worker             ZSTD_STATUS_NEEDS_MORE_INPUT :
3277*f6dc9357SAndroid Build Coastguard Worker             ZSTD_STATUS_NOT_FINISHED;
3278*f6dc9357SAndroid Build Coastguard Worker         return SZ_OK;
3279*f6dc9357SAndroid Build Coastguard Worker       }
3280*f6dc9357SAndroid Build Coastguard Worker       */
3281*f6dc9357SAndroid Build Coastguard Worker       // p->decoder.winPos <= winLimit
3282*f6dc9357SAndroid Build Coastguard Worker 
3283*f6dc9357SAndroid Build Coastguard Worker       if (p->blockType != kBlockType_Compressed)
3284*f6dc9357SAndroid Build Coastguard Worker       {
3285*f6dc9357SAndroid Build Coastguard Worker         // it's RLE or RAW block.
3286*f6dc9357SAndroid Build Coastguard Worker         // p->BlockSize != 0_
3287*f6dc9357SAndroid Build Coastguard Worker         // winLimit <= p->decoder.cycSize
3288*f6dc9357SAndroid Build Coastguard Worker         /* So here we use more strong (winLimit), even for
3289*f6dc9357SAndroid Build Coastguard Worker            (ds->outBuf_fromCaller) mode. */
3290*f6dc9357SAndroid Build Coastguard Worker         SizeT outCur = winLimit - p->decoder.winPos;
3291*f6dc9357SAndroid Build Coastguard Worker         {
3292*f6dc9357SAndroid Build Coastguard Worker           const UInt32 rem = p->blockSize;
3293*f6dc9357SAndroid Build Coastguard Worker           if (outCur > rem)
3294*f6dc9357SAndroid Build Coastguard Worker               outCur = rem;
3295*f6dc9357SAndroid Build Coastguard Worker         }
3296*f6dc9357SAndroid Build Coastguard Worker         if (p->blockType == kBlockType_Raw)
3297*f6dc9357SAndroid Build Coastguard Worker         {
3298*f6dc9357SAndroid Build Coastguard Worker           if (outCur > inCur)
3299*f6dc9357SAndroid Build Coastguard Worker               outCur = inCur;
3300*f6dc9357SAndroid Build Coastguard Worker           /* output buffer is better aligned for XXH code.
3301*f6dc9357SAndroid Build Coastguard Worker              So we use hash for output buffer data */
3302*f6dc9357SAndroid Build Coastguard Worker           // ZstdDec_Update_XXH(p, src, outCur); // for debug:
3303*f6dc9357SAndroid Build Coastguard Worker           memcpy(p->decoder.win + p->decoder.winPos, src, outCur);
3304*f6dc9357SAndroid Build Coastguard Worker           src += outCur;
3305*f6dc9357SAndroid Build Coastguard Worker           *srcLen += outCur;
3306*f6dc9357SAndroid Build Coastguard Worker         }
3307*f6dc9357SAndroid Build Coastguard Worker         else // kBlockType_RLE
3308*f6dc9357SAndroid Build Coastguard Worker         {
3309*f6dc9357SAndroid Build Coastguard Worker           #define RLE_BYTE_INDEX_IN_temp  3
3310*f6dc9357SAndroid Build Coastguard Worker           memset(p->decoder.win + p->decoder.winPos,
3311*f6dc9357SAndroid Build Coastguard Worker               p->temp[RLE_BYTE_INDEX_IN_temp], outCur);
3312*f6dc9357SAndroid Build Coastguard Worker         }
3313*f6dc9357SAndroid Build Coastguard Worker         {
3314*f6dc9357SAndroid Build Coastguard Worker           const SizeT xxh64_winPos = p->decoder.winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p);
3315*f6dc9357SAndroid Build Coastguard Worker           p->decoder.winPos += outCur;
3316*f6dc9357SAndroid Build Coastguard Worker           UPDATE_TOTAL_OUT(&p->decoder, outCur)
3317*f6dc9357SAndroid Build Coastguard Worker           p->contentProcessed += outCur;
3318*f6dc9357SAndroid Build Coastguard Worker           ZstdDec_Update_XXH(p, xxh64_winPos);
3319*f6dc9357SAndroid Build Coastguard Worker         }
3320*f6dc9357SAndroid Build Coastguard Worker         // ds->winPos = p->decoder.winPos;  // the caller does it instead. for debug:
3321*f6dc9357SAndroid Build Coastguard Worker         ds->outProcessed += outCur;
3322*f6dc9357SAndroid Build Coastguard Worker         if (p->blockSize -= (UInt32)outCur)
3323*f6dc9357SAndroid Build Coastguard Worker         {
3324*f6dc9357SAndroid Build Coastguard Worker           /*
3325*f6dc9357SAndroid Build Coastguard Worker           if (ds->outSize_Defined)
3326*f6dc9357SAndroid Build Coastguard Worker           {
3327*f6dc9357SAndroid Build Coastguard Worker             if (ds->outSize <= ds->outProcessed) ds->isAfterSizeMode = (enum_ZstdStatus)
3328*f6dc9357SAndroid Build Coastguard Worker                (ds->outSize == ds->outProcessed ? 1u: 2u);
3329*f6dc9357SAndroid Build Coastguard Worker           }
3330*f6dc9357SAndroid Build Coastguard Worker           */
3331*f6dc9357SAndroid Build Coastguard Worker           *status = (enum_ZstdStatus)
3332*f6dc9357SAndroid Build Coastguard Worker               (ds->outSize_Defined && ds->outSize <= ds->outProcessed ?
3333*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_OUT_REACHED : (p->blockType == kBlockType_Raw && inSize == *srcLen) ?
3334*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NEEDS_MORE_INPUT :
3335*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NOT_FINISHED);
3336*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
3337*f6dc9357SAndroid Build Coastguard Worker         }
3338*f6dc9357SAndroid Build Coastguard Worker       }
3339*f6dc9357SAndroid Build Coastguard Worker       else // kBlockType_Compressed
3340*f6dc9357SAndroid Build Coastguard Worker       {
3341*f6dc9357SAndroid Build Coastguard Worker         // p->blockSize != 0
3342*f6dc9357SAndroid Build Coastguard Worker         // (uncompressed_size_of_block == 0) is allowed
3343*f6dc9357SAndroid Build Coastguard Worker         // (p->curBlockUnpackRem == 0) is allowed
3344*f6dc9357SAndroid Build Coastguard Worker         /*
3345*f6dc9357SAndroid Build Coastguard Worker         if (p->decoder.winPos >= winLimit)
3346*f6dc9357SAndroid Build Coastguard Worker         {
3347*f6dc9357SAndroid Build Coastguard Worker           if (p->decoder.winPos != winPos_atFuncStart)
3348*f6dc9357SAndroid Build Coastguard Worker           {
3349*f6dc9357SAndroid Build Coastguard Worker             // it's unexpected case
3350*f6dc9357SAndroid Build Coastguard Worker             // We already have some data in finished blocks in this function call.
3351*f6dc9357SAndroid Build Coastguard Worker             //   So we don't decompress new block after (>=winLimit),
3352*f6dc9357SAndroid Build Coastguard Worker             //   even if it's empty block.
3353*f6dc9357SAndroid Build Coastguard Worker             *status = (inSize == *srcLen) ?
3354*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NEEDS_MORE_INPUT :
3355*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NOT_FINISHED;
3356*f6dc9357SAndroid Build Coastguard Worker             return SZ_OK;
3357*f6dc9357SAndroid Build Coastguard Worker           }
3358*f6dc9357SAndroid Build Coastguard Worker           // (p->decoder.winPos == winLimit == winPos_atFuncStart)
3359*f6dc9357SAndroid Build Coastguard Worker           // we will decode current block, because that current
3360*f6dc9357SAndroid Build Coastguard Worker           //   block can be empty block and we want to make some visible
3361*f6dc9357SAndroid Build Coastguard Worker           //   change of (src) stream after function start.
3362*f6dc9357SAndroid Build Coastguard Worker         }
3363*f6dc9357SAndroid Build Coastguard Worker         */
3364*f6dc9357SAndroid Build Coastguard Worker         /*
3365*f6dc9357SAndroid Build Coastguard Worker         if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3366*f6dc9357SAndroid Build Coastguard Worker         {
3367*f6dc9357SAndroid Build Coastguard Worker           // we don't want to start new block, if we have more extra decoded bytes already
3368*f6dc9357SAndroid Build Coastguard Worker           *status = ZSTD_STATUS_OUT_REACHED;
3369*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
3370*f6dc9357SAndroid Build Coastguard Worker         }
3371*f6dc9357SAndroid Build Coastguard Worker         */
3372*f6dc9357SAndroid Build Coastguard Worker         {
3373*f6dc9357SAndroid Build Coastguard Worker           const Byte *comprStream;
3374*f6dc9357SAndroid Build Coastguard Worker           size_t afterAvail;
3375*f6dc9357SAndroid Build Coastguard Worker           UInt32 inTempPos = p->inTempPos;
3376*f6dc9357SAndroid Build Coastguard Worker           const UInt32 rem = p->blockSize - inTempPos;
3377*f6dc9357SAndroid Build Coastguard Worker           // rem != 0
3378*f6dc9357SAndroid Build Coastguard Worker           if (inTempPos != 0  // (inTemp) buffer already contains some input data
3379*f6dc9357SAndroid Build Coastguard Worker               || inCur < rem  // available input data size is smaller than compressed block size
3380*f6dc9357SAndroid Build Coastguard Worker               || ZstdDec1_NeedTempBufferForInput(*srcLen, src, rem))
3381*f6dc9357SAndroid Build Coastguard Worker           {
3382*f6dc9357SAndroid Build Coastguard Worker             if (inCur > rem)
3383*f6dc9357SAndroid Build Coastguard Worker                 inCur = rem;
3384*f6dc9357SAndroid Build Coastguard Worker             if (inCur)
3385*f6dc9357SAndroid Build Coastguard Worker             {
3386*f6dc9357SAndroid Build Coastguard Worker               STAT_INC(g_Num_Blocks_memcpy)
3387*f6dc9357SAndroid Build Coastguard Worker               // we clear data for backward lookahead reading
3388*f6dc9357SAndroid Build Coastguard Worker               if (inTempPos == 0)
3389*f6dc9357SAndroid Build Coastguard Worker                 memset(p->inTemp + kTempBuffer_PreSize - MAX_BACKWARD_DEPTH, 0, MAX_BACKWARD_DEPTH);
3390*f6dc9357SAndroid Build Coastguard Worker               // { unsigned y = 0; for(;y < 1000; y++)
3391*f6dc9357SAndroid Build Coastguard Worker               memcpy(p->inTemp + inTempPos + kTempBuffer_PreSize, src, inCur);
3392*f6dc9357SAndroid Build Coastguard Worker               // }
3393*f6dc9357SAndroid Build Coastguard Worker               src += inCur;
3394*f6dc9357SAndroid Build Coastguard Worker               *srcLen += inCur;
3395*f6dc9357SAndroid Build Coastguard Worker               inTempPos += (UInt32)inCur;
3396*f6dc9357SAndroid Build Coastguard Worker               p->inTempPos = inTempPos;
3397*f6dc9357SAndroid Build Coastguard Worker             }
3398*f6dc9357SAndroid Build Coastguard Worker             if (inTempPos != p->blockSize)
3399*f6dc9357SAndroid Build Coastguard Worker             {
3400*f6dc9357SAndroid Build Coastguard Worker               *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3401*f6dc9357SAndroid Build Coastguard Worker               return SZ_OK;
3402*f6dc9357SAndroid Build Coastguard Worker             }
3403*f6dc9357SAndroid Build Coastguard Worker             #if COPY_CHUNK_SIZE > 1
3404*f6dc9357SAndroid Build Coastguard Worker               memset(p->inTemp + kTempBuffer_PreSize + inTempPos, 0, COPY_CHUNK_SIZE);
3405*f6dc9357SAndroid Build Coastguard Worker             #endif
3406*f6dc9357SAndroid Build Coastguard Worker             comprStream = p->inTemp + kTempBuffer_PreSize;
3407*f6dc9357SAndroid Build Coastguard Worker             afterAvail = k_Lit_AfterAvail;
3408*f6dc9357SAndroid Build Coastguard Worker             // we don't want to read non-initialized data or junk in CopyMatch():
3409*f6dc9357SAndroid Build Coastguard Worker           }
3410*f6dc9357SAndroid Build Coastguard Worker           else
3411*f6dc9357SAndroid Build Coastguard Worker           {
3412*f6dc9357SAndroid Build Coastguard Worker             // inCur >= rem
3413*f6dc9357SAndroid Build Coastguard Worker             // we use direct decoding from (src) buffer:
3414*f6dc9357SAndroid Build Coastguard Worker             afterAvail = inCur - rem;
3415*f6dc9357SAndroid Build Coastguard Worker             comprStream = src;
3416*f6dc9357SAndroid Build Coastguard Worker             src += rem;
3417*f6dc9357SAndroid Build Coastguard Worker             *srcLen += rem;
3418*f6dc9357SAndroid Build Coastguard Worker           }
3419*f6dc9357SAndroid Build Coastguard Worker 
3420*f6dc9357SAndroid Build Coastguard Worker           #ifdef Z7_ZSTD_DEC_USE_CHECK_OF_NEED_TEMP
3421*f6dc9357SAndroid Build Coastguard Worker             ZstdDec1_NeedTempBufferForInput(*srcLen, comprStream, p->blockSize);
3422*f6dc9357SAndroid Build Coastguard Worker           #endif
3423*f6dc9357SAndroid Build Coastguard Worker           // printf("\nblockSize=%u", p->blockSize);
3424*f6dc9357SAndroid Build Coastguard Worker           // printf("%x\n", (unsigned)p->contentProcessed);
3425*f6dc9357SAndroid Build Coastguard Worker           STAT_INC(g_Num_Blocks_Compressed)
3426*f6dc9357SAndroid Build Coastguard Worker           {
3427*f6dc9357SAndroid Build Coastguard Worker             SRes sres;
3428*f6dc9357SAndroid Build Coastguard Worker             const size_t winPos = p->decoder.winPos;
3429*f6dc9357SAndroid Build Coastguard Worker             /*
3430*f6dc9357SAndroid Build Coastguard Worker                if ( useAdditionalWinLimit), we use strong unpack limit: smallest from
3431*f6dc9357SAndroid Build Coastguard Worker                   - limit from stream : (curBlockUnpackRem)
3432*f6dc9357SAndroid Build Coastguard Worker                   - limit from caller : (cycSize - winPos)
3433*f6dc9357SAndroid Build Coastguard Worker                if (!useAdditionalWinLimit), we use only relaxed limit:
3434*f6dc9357SAndroid Build Coastguard Worker                   - limit from stream : (curBlockUnpackRem)
3435*f6dc9357SAndroid Build Coastguard Worker             */
3436*f6dc9357SAndroid Build Coastguard Worker             SizeT outLimit = p->curBlockUnpackRem;
3437*f6dc9357SAndroid Build Coastguard Worker             if (ds->outBuf_fromCaller)
3438*f6dc9357SAndroid Build Coastguard Worker             // if (useAdditionalWinLimit)
3439*f6dc9357SAndroid Build Coastguard Worker             {
3440*f6dc9357SAndroid Build Coastguard Worker               const size_t limit = p->decoder.cycSize - winPos;
3441*f6dc9357SAndroid Build Coastguard Worker               if (outLimit > limit)
3442*f6dc9357SAndroid Build Coastguard Worker                   outLimit = limit;
3443*f6dc9357SAndroid Build Coastguard Worker             }
3444*f6dc9357SAndroid Build Coastguard Worker             sres = ZstdDec1_DecodeBlock(&p->decoder,
3445*f6dc9357SAndroid Build Coastguard Worker                 comprStream, p->blockSize, afterAvail, outLimit);
3446*f6dc9357SAndroid Build Coastguard Worker             // ds->winPos = p->decoder.winPos;  // the caller does it instead. for debug:
3447*f6dc9357SAndroid Build Coastguard Worker             if (sres)
3448*f6dc9357SAndroid Build Coastguard Worker             {
3449*f6dc9357SAndroid Build Coastguard Worker               p->isErrorState = True;
3450*f6dc9357SAndroid Build Coastguard Worker               return sres;
3451*f6dc9357SAndroid Build Coastguard Worker             }
3452*f6dc9357SAndroid Build Coastguard Worker             {
3453*f6dc9357SAndroid Build Coastguard Worker               const SizeT xxh64_winPos = winPos - ZstdDec_GET_UNPROCESSED_XXH64_SIZE(p);
3454*f6dc9357SAndroid Build Coastguard Worker               const size_t num = p->decoder.winPos - winPos;
3455*f6dc9357SAndroid Build Coastguard Worker               ds->outProcessed += num;
3456*f6dc9357SAndroid Build Coastguard Worker               p->contentProcessed += num;
3457*f6dc9357SAndroid Build Coastguard Worker               ZstdDec_Update_XXH(p, xxh64_winPos);
3458*f6dc9357SAndroid Build Coastguard Worker             }
3459*f6dc9357SAndroid Build Coastguard Worker           }
3460*f6dc9357SAndroid Build Coastguard Worker           // printf("\nwinPos=%x", (int)(unsigned)p->decoder.winPos);
3461*f6dc9357SAndroid Build Coastguard Worker         }
3462*f6dc9357SAndroid Build Coastguard Worker       }
3463*f6dc9357SAndroid Build Coastguard Worker 
3464*f6dc9357SAndroid Build Coastguard Worker       /*
3465*f6dc9357SAndroid Build Coastguard Worker       if (ds->outSize_Defined)
3466*f6dc9357SAndroid Build Coastguard Worker       {
3467*f6dc9357SAndroid Build Coastguard Worker         if (ds->outSize <= ds->outProcessed) ds->isAfterSizeMode = (enum_ZstdStatus)
3468*f6dc9357SAndroid Build Coastguard Worker            (ds->outSize == ds->outProcessed ? 1u: 2u);
3469*f6dc9357SAndroid Build Coastguard Worker       }
3470*f6dc9357SAndroid Build Coastguard Worker       */
3471*f6dc9357SAndroid Build Coastguard Worker 
3472*f6dc9357SAndroid Build Coastguard Worker       if (!ZSTD_DEC_IS_LAST_BLOCK(p))
3473*f6dc9357SAndroid Build Coastguard Worker       {
3474*f6dc9357SAndroid Build Coastguard Worker         p->frameState = ZSTD2_STATE_BLOCK;
3475*f6dc9357SAndroid Build Coastguard Worker         if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3476*f6dc9357SAndroid Build Coastguard Worker         {
3477*f6dc9357SAndroid Build Coastguard Worker           *status = ZSTD_STATUS_OUT_REACHED;
3478*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
3479*f6dc9357SAndroid Build Coastguard Worker         }
3480*f6dc9357SAndroid Build Coastguard Worker         // we exit only if (winPos) was changed in this function call:
3481*f6dc9357SAndroid Build Coastguard Worker         if (p->decoder.winPos != winPos_atFuncStart)
3482*f6dc9357SAndroid Build Coastguard Worker         {
3483*f6dc9357SAndroid Build Coastguard Worker           // decoded block was not empty. So we exit:
3484*f6dc9357SAndroid Build Coastguard Worker           *status = (enum_ZstdStatus)(
3485*f6dc9357SAndroid Build Coastguard Worker               (inSize == *srcLen) ?
3486*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NEEDS_MORE_INPUT :
3487*f6dc9357SAndroid Build Coastguard Worker                 ZSTD_STATUS_NOT_FINISHED);
3488*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
3489*f6dc9357SAndroid Build Coastguard Worker         }
3490*f6dc9357SAndroid Build Coastguard Worker         // (p->decoder.winPos == winPos_atFuncStart)
3491*f6dc9357SAndroid Build Coastguard Worker         // so current decoded block was empty.
3492*f6dc9357SAndroid Build Coastguard Worker         // we will try to decode more blocks in this function.
3493*f6dc9357SAndroid Build Coastguard Worker         continue;
3494*f6dc9357SAndroid Build Coastguard Worker       }
3495*f6dc9357SAndroid Build Coastguard Worker 
3496*f6dc9357SAndroid Build Coastguard Worker       // decoded block was last in frame
3497*f6dc9357SAndroid Build Coastguard Worker       if (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM)
3498*f6dc9357SAndroid Build Coastguard Worker       {
3499*f6dc9357SAndroid Build Coastguard Worker         p->frameState = ZSTD2_STATE_HASH;
3500*f6dc9357SAndroid Build Coastguard Worker         if (ds->outSize_Defined && ds->outSize < ds->outProcessed)
3501*f6dc9357SAndroid Build Coastguard Worker         {
3502*f6dc9357SAndroid Build Coastguard Worker           *status = ZSTD_STATUS_OUT_REACHED;
3503*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK; // disable if want to
3504*f6dc9357SAndroid Build Coastguard Worker           /* We want to get same return codes for any input buffer sizes.
3505*f6dc9357SAndroid Build Coastguard Worker              We want to get faster ZSTD_STATUS_OUT_REACHED status.
3506*f6dc9357SAndroid Build Coastguard Worker              So we exit with ZSTD_STATUS_OUT_REACHED here,
3507*f6dc9357SAndroid Build Coastguard Worker              instead of ZSTD2_STATE_HASH and ZSTD2_STATE_FINISHED processing.
3508*f6dc9357SAndroid Build Coastguard Worker              that depends from input buffer size and that can set
3509*f6dc9357SAndroid Build Coastguard Worker              ZSTD_STATUS_NEEDS_MORE_INPUT or return SZ_ERROR_DATA or SZ_ERROR_CRC.
3510*f6dc9357SAndroid Build Coastguard Worker           */
3511*f6dc9357SAndroid Build Coastguard Worker         }
3512*f6dc9357SAndroid Build Coastguard Worker       }
3513*f6dc9357SAndroid Build Coastguard Worker       else
3514*f6dc9357SAndroid Build Coastguard Worker       {
3515*f6dc9357SAndroid Build Coastguard Worker         /* ZSTD2_STATE_FINISHED proccesing doesn't depend from input buffer */
3516*f6dc9357SAndroid Build Coastguard Worker         p->frameState = ZSTD2_STATE_FINISHED;
3517*f6dc9357SAndroid Build Coastguard Worker       }
3518*f6dc9357SAndroid Build Coastguard Worker       /*
3519*f6dc9357SAndroid Build Coastguard Worker       p->frameState = (p->descriptor & DESCRIPTOR_FLAG_CHECKSUM) ?
3520*f6dc9357SAndroid Build Coastguard Worker           ZSTD2_STATE_HASH :
3521*f6dc9357SAndroid Build Coastguard Worker           ZSTD2_STATE_FINISHED;
3522*f6dc9357SAndroid Build Coastguard Worker       */
3523*f6dc9357SAndroid Build Coastguard Worker       /* it's required to process ZSTD2_STATE_FINISHED state in this function call,
3524*f6dc9357SAndroid Build Coastguard Worker          because we must check contentSize and hashError in ZSTD2_STATE_FINISHED code,
3525*f6dc9357SAndroid Build Coastguard Worker          while the caller can reinit full state for ZSTD2_STATE_FINISHED
3526*f6dc9357SAndroid Build Coastguard Worker          So we can't exit from function here. */
3527*f6dc9357SAndroid Build Coastguard Worker       continue;
3528*f6dc9357SAndroid Build Coastguard Worker     }
3529*f6dc9357SAndroid Build Coastguard Worker 
3530*f6dc9357SAndroid Build Coastguard Worker     if (p->frameState == ZSTD2_STATE_FINISHED)
3531*f6dc9357SAndroid Build Coastguard Worker     {
3532*f6dc9357SAndroid Build Coastguard Worker       *status = ZSTD_STATUS_FINISHED_FRAME;
3533*f6dc9357SAndroid Build Coastguard Worker       if (DESCRIPTOR_Is_ContentSize_Defined(p->descriptor)
3534*f6dc9357SAndroid Build Coastguard Worker           && p->contentSize != p->contentProcessed)
3535*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_DATA;
3536*f6dc9357SAndroid Build Coastguard Worker       if (p->hashError) // for debug
3537*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_CRC;
3538*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
3539*f6dc9357SAndroid Build Coastguard Worker       // p->frameState = ZSTD2_STATE_SIGNATURE;
3540*f6dc9357SAndroid Build Coastguard Worker       // continue;
3541*f6dc9357SAndroid Build Coastguard Worker     }
3542*f6dc9357SAndroid Build Coastguard Worker 
3543*f6dc9357SAndroid Build Coastguard Worker     if (p->frameState == ZSTD2_STATE_AFTER_HEADER)
3544*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK; // we need memory allocation for that state
3545*f6dc9357SAndroid Build Coastguard Worker 
3546*f6dc9357SAndroid Build Coastguard Worker     if (p->frameState == ZSTD2_STATE_SKIP_DATA)
3547*f6dc9357SAndroid Build Coastguard Worker     {
3548*f6dc9357SAndroid Build Coastguard Worker       UInt32 blockSize = p->blockSize;
3549*f6dc9357SAndroid Build Coastguard Worker       // (blockSize == 0) is possible
3550*f6dc9357SAndroid Build Coastguard Worker       if (inCur > blockSize)
3551*f6dc9357SAndroid Build Coastguard Worker           inCur = blockSize;
3552*f6dc9357SAndroid Build Coastguard Worker       src += inCur;
3553*f6dc9357SAndroid Build Coastguard Worker       *srcLen += inCur;
3554*f6dc9357SAndroid Build Coastguard Worker       blockSize -= (UInt32)inCur;
3555*f6dc9357SAndroid Build Coastguard Worker       p->blockSize = blockSize;
3556*f6dc9357SAndroid Build Coastguard Worker       if (blockSize == 0)
3557*f6dc9357SAndroid Build Coastguard Worker       {
3558*f6dc9357SAndroid Build Coastguard Worker         p->frameState = ZSTD2_STATE_SIGNATURE;
3559*f6dc9357SAndroid Build Coastguard Worker         // continue; // for debug: we can continue without return to caller.
3560*f6dc9357SAndroid Build Coastguard Worker         // we notify the caller that skip frame was finished:
3561*f6dc9357SAndroid Build Coastguard Worker         *status = ZSTD_STATUS_FINISHED_FRAME;
3562*f6dc9357SAndroid Build Coastguard Worker         return SZ_OK;
3563*f6dc9357SAndroid Build Coastguard Worker       }
3564*f6dc9357SAndroid Build Coastguard Worker       // blockSize != 0
3565*f6dc9357SAndroid Build Coastguard Worker       // (inCur) was smaller than previous value of p->blockSize.
3566*f6dc9357SAndroid Build Coastguard Worker       // (inSize == *srcLen) now
3567*f6dc9357SAndroid Build Coastguard Worker       *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3568*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
3569*f6dc9357SAndroid Build Coastguard Worker     }
3570*f6dc9357SAndroid Build Coastguard Worker 
3571*f6dc9357SAndroid Build Coastguard Worker     if (inCur == 0)
3572*f6dc9357SAndroid Build Coastguard Worker     {
3573*f6dc9357SAndroid Build Coastguard Worker       *status = ZSTD_STATUS_NEEDS_MORE_INPUT;
3574*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
3575*f6dc9357SAndroid Build Coastguard Worker     }
3576*f6dc9357SAndroid Build Coastguard Worker 
3577*f6dc9357SAndroid Build Coastguard Worker     {
3578*f6dc9357SAndroid Build Coastguard Worker       (*srcLen)++;
3579*f6dc9357SAndroid Build Coastguard Worker       p->frameState = ZstdDec_UpdateState(p, *src++, info);
3580*f6dc9357SAndroid Build Coastguard Worker     }
3581*f6dc9357SAndroid Build Coastguard Worker   }
3582*f6dc9357SAndroid Build Coastguard Worker 
3583*f6dc9357SAndroid Build Coastguard Worker   *status = ZSTD_STATUS_NOT_SPECIFIED;
3584*f6dc9357SAndroid Build Coastguard Worker   p->isErrorState = True;
3585*f6dc9357SAndroid Build Coastguard Worker   // p->frameState = ZSTD2_STATE_ERROR;
3586*f6dc9357SAndroid Build Coastguard Worker   // if (p->frameState = ZSTD2_STATE_SIGNATURE)  return SZ_ERROR_NO_ARCHIVE
3587*f6dc9357SAndroid Build Coastguard Worker   return SZ_ERROR_DATA;
3588*f6dc9357SAndroid Build Coastguard Worker }
3589*f6dc9357SAndroid Build Coastguard Worker 
3590*f6dc9357SAndroid Build Coastguard Worker 
3591*f6dc9357SAndroid Build Coastguard Worker 
3592*f6dc9357SAndroid Build Coastguard Worker 
3593*f6dc9357SAndroid Build Coastguard Worker SRes ZstdDec_Decode(CZstdDecHandle dec, CZstdDecState *p)
3594*f6dc9357SAndroid Build Coastguard Worker {
3595*f6dc9357SAndroid Build Coastguard Worker   p->needWrite_Size = 0;
3596*f6dc9357SAndroid Build Coastguard Worker   p->status = ZSTD_STATUS_NOT_SPECIFIED;
3597*f6dc9357SAndroid Build Coastguard Worker   dec->disableHash = p->disableHash;
3598*f6dc9357SAndroid Build Coastguard Worker 
3599*f6dc9357SAndroid Build Coastguard Worker   if (p->outBuf_fromCaller)
3600*f6dc9357SAndroid Build Coastguard Worker   {
3601*f6dc9357SAndroid Build Coastguard Worker     dec->decoder.win = p->outBuf_fromCaller;
3602*f6dc9357SAndroid Build Coastguard Worker     dec->decoder.cycSize = p->outBufSize_fromCaller;
3603*f6dc9357SAndroid Build Coastguard Worker   }
3604*f6dc9357SAndroid Build Coastguard Worker 
3605*f6dc9357SAndroid Build Coastguard Worker   // p->winPos = dec->decoder.winPos;
3606*f6dc9357SAndroid Build Coastguard Worker 
3607*f6dc9357SAndroid Build Coastguard Worker   for (;;)
3608*f6dc9357SAndroid Build Coastguard Worker   {
3609*f6dc9357SAndroid Build Coastguard Worker     SizeT winPos, size;
3610*f6dc9357SAndroid Build Coastguard Worker     // SizeT outProcessed;
3611*f6dc9357SAndroid Build Coastguard Worker     SRes res;
3612*f6dc9357SAndroid Build Coastguard Worker 
3613*f6dc9357SAndroid Build Coastguard Worker     if (p->wrPos > dec->decoder.winPos)
3614*f6dc9357SAndroid Build Coastguard Worker       return SZ_ERROR_FAIL;
3615*f6dc9357SAndroid Build Coastguard Worker 
3616*f6dc9357SAndroid Build Coastguard Worker     if (dec->frameState == ZSTD2_STATE_FINISHED)
3617*f6dc9357SAndroid Build Coastguard Worker     {
3618*f6dc9357SAndroid Build Coastguard Worker       if (!p->outBuf_fromCaller)
3619*f6dc9357SAndroid Build Coastguard Worker       {
3620*f6dc9357SAndroid Build Coastguard Worker         // we need to set positions to zero for new frame.
3621*f6dc9357SAndroid Build Coastguard Worker         if (p->wrPos != dec->decoder.winPos)
3622*f6dc9357SAndroid Build Coastguard Worker         {
3623*f6dc9357SAndroid Build Coastguard Worker           /* We have already asked the caller to flush all data
3624*f6dc9357SAndroid Build Coastguard Worker              with (p->needWrite_Size) and (ZSTD_STATUS_FINISHED_FRAME) status.
3625*f6dc9357SAndroid Build Coastguard Worker              So it's unexpected case */
3626*f6dc9357SAndroid Build Coastguard Worker           // p->winPos = dec->decoder.winPos;
3627*f6dc9357SAndroid Build Coastguard Worker           // p->needWrite_Size = dec->decoder.winPos - p->wrPos; // flush size asking
3628*f6dc9357SAndroid Build Coastguard Worker           // return SZ_OK; // ask to flush again
3629*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_FAIL;
3630*f6dc9357SAndroid Build Coastguard Worker         }
3631*f6dc9357SAndroid Build Coastguard Worker         // (p->wrPos == dec->decoder.winPos), and we wrap to zero:
3632*f6dc9357SAndroid Build Coastguard Worker         dec->decoder.winPos = 0;
3633*f6dc9357SAndroid Build Coastguard Worker         p->winPos = 0;
3634*f6dc9357SAndroid Build Coastguard Worker         p->wrPos = 0;
3635*f6dc9357SAndroid Build Coastguard Worker       }
3636*f6dc9357SAndroid Build Coastguard Worker       ZstdDec_Init_ForNewFrame(dec);
3637*f6dc9357SAndroid Build Coastguard Worker       // continue;
3638*f6dc9357SAndroid Build Coastguard Worker     }
3639*f6dc9357SAndroid Build Coastguard Worker 
3640*f6dc9357SAndroid Build Coastguard Worker     winPos = dec->decoder.winPos;
3641*f6dc9357SAndroid Build Coastguard Worker     {
3642*f6dc9357SAndroid Build Coastguard Worker       SizeT next = dec->decoder.cycSize;
3643*f6dc9357SAndroid Build Coastguard Worker       /* cycSize == 0, if no buffer was allocated still,
3644*f6dc9357SAndroid Build Coastguard Worker          or, if (outBuf_fromCaller) mode and (outBufSize_fromCaller == 0) */
3645*f6dc9357SAndroid Build Coastguard Worker       if (!p->outBuf_fromCaller
3646*f6dc9357SAndroid Build Coastguard Worker           && next
3647*f6dc9357SAndroid Build Coastguard Worker           && next <= winPos
3648*f6dc9357SAndroid Build Coastguard Worker           && dec->isCyclicMode)
3649*f6dc9357SAndroid Build Coastguard Worker       {
3650*f6dc9357SAndroid Build Coastguard Worker         // (0 < decoder.cycSize <= winPos) in isCyclicMode.
3651*f6dc9357SAndroid Build Coastguard Worker         // so we need to wrap (winPos) and (wrPos) over (cycSize).
3652*f6dc9357SAndroid Build Coastguard Worker         const size_t delta = next;
3653*f6dc9357SAndroid Build Coastguard Worker         // (delta) is how many bytes we remove from buffer.
3654*f6dc9357SAndroid Build Coastguard Worker         /*
3655*f6dc9357SAndroid Build Coastguard Worker         // we don't need data older than last (cycSize) bytes.
3656*f6dc9357SAndroid Build Coastguard Worker         size_t delta = winPos - next; // num bytes after (cycSize)
3657*f6dc9357SAndroid Build Coastguard Worker         if (delta <= next) // it's expected case
3658*f6dc9357SAndroid Build Coastguard Worker           delta = next;
3659*f6dc9357SAndroid Build Coastguard Worker         // delta == Max(cycSize, winPos - cycSize)
3660*f6dc9357SAndroid Build Coastguard Worker         */
3661*f6dc9357SAndroid Build Coastguard Worker         if (p->wrPos < delta)
3662*f6dc9357SAndroid Build Coastguard Worker         {
3663*f6dc9357SAndroid Build Coastguard Worker           // (wrPos < decoder.cycSize)
3664*f6dc9357SAndroid Build Coastguard Worker           // We have asked already the caller to flush required data
3665*f6dc9357SAndroid Build Coastguard Worker           // p->status = ZSTD_STATUS_NOT_SPECIFIED;
3666*f6dc9357SAndroid Build Coastguard Worker           // p->winPos = winPos;
3667*f6dc9357SAndroid Build Coastguard Worker           // p->needWrite_Size = delta - p->wrPos; // flush size asking
3668*f6dc9357SAndroid Build Coastguard Worker           // return SZ_OK; // ask to flush again
3669*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_FAIL;
3670*f6dc9357SAndroid Build Coastguard Worker         }
3671*f6dc9357SAndroid Build Coastguard Worker         // p->wrPos >= decoder.cycSize
3672*f6dc9357SAndroid Build Coastguard Worker         // we move extra data after (decoder.cycSize) to start of cyclic buffer:
3673*f6dc9357SAndroid Build Coastguard Worker         winPos -= delta;
3674*f6dc9357SAndroid Build Coastguard Worker         if (winPos)
3675*f6dc9357SAndroid Build Coastguard Worker         {
3676*f6dc9357SAndroid Build Coastguard Worker           if (winPos >= delta)
3677*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_FAIL;
3678*f6dc9357SAndroid Build Coastguard Worker           memmove(dec->decoder.win, dec->decoder.win + delta, winPos);
3679*f6dc9357SAndroid Build Coastguard Worker           // printf("\nmemmove processed=%8x winPos=%8x\n", (unsigned)p->outProcessed, (unsigned)dec->decoder.winPos);
3680*f6dc9357SAndroid Build Coastguard Worker           STAT_INC(g_Num_Wrap_memmove_Num)
3681*f6dc9357SAndroid Build Coastguard Worker           STAT_UPDATE(g_Num_Wrap_memmove_Bytes += (unsigned)winPos;)
3682*f6dc9357SAndroid Build Coastguard Worker         }
3683*f6dc9357SAndroid Build Coastguard Worker         dec->decoder.winPos = winPos;
3684*f6dc9357SAndroid Build Coastguard Worker         p->winPos = winPos;
3685*f6dc9357SAndroid Build Coastguard Worker         p->wrPos -= delta;
3686*f6dc9357SAndroid Build Coastguard Worker         // dec->xxh64_winPos -= delta;
3687*f6dc9357SAndroid Build Coastguard Worker 
3688*f6dc9357SAndroid Build Coastguard Worker         // (winPos < delta)
3689*f6dc9357SAndroid Build Coastguard Worker         #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
3690*f6dc9357SAndroid Build Coastguard Worker           /* we set the data after cycSize, because
3691*f6dc9357SAndroid Build Coastguard Worker              we don't want to read non-initialized data or junk in CopyMatch(). */
3692*f6dc9357SAndroid Build Coastguard Worker           memset(dec->decoder.win + next, 0, COPY_CHUNK_SIZE);
3693*f6dc9357SAndroid Build Coastguard Worker         #endif
3694*f6dc9357SAndroid Build Coastguard Worker 
3695*f6dc9357SAndroid Build Coastguard Worker         /*
3696*f6dc9357SAndroid Build Coastguard Worker         if (winPos == next)
3697*f6dc9357SAndroid Build Coastguard Worker         {
3698*f6dc9357SAndroid Build Coastguard Worker           if (winPos != p->wrPos)
3699*f6dc9357SAndroid Build Coastguard Worker           {
3700*f6dc9357SAndroid Build Coastguard Worker             // we already requested before to flush full data for that case.
3701*f6dc9357SAndroid Build Coastguard Worker             //   but we give the caller a second chance to flush data:
3702*f6dc9357SAndroid Build Coastguard Worker             p->needWrite_Size = winPos - p->wrPos;
3703*f6dc9357SAndroid Build Coastguard Worker             return SZ_OK;
3704*f6dc9357SAndroid Build Coastguard Worker           }
3705*f6dc9357SAndroid Build Coastguard Worker           // (decoder.cycSize == winPos == p->wrPos)
3706*f6dc9357SAndroid Build Coastguard Worker           // so we do second wrapping to zero:
3707*f6dc9357SAndroid Build Coastguard Worker           winPos = 0;
3708*f6dc9357SAndroid Build Coastguard Worker           dec->decoder.winPos = 0;
3709*f6dc9357SAndroid Build Coastguard Worker           p->winPos = 0;
3710*f6dc9357SAndroid Build Coastguard Worker           p->wrPos = 0;
3711*f6dc9357SAndroid Build Coastguard Worker         }
3712*f6dc9357SAndroid Build Coastguard Worker         */
3713*f6dc9357SAndroid Build Coastguard Worker         // (winPos < next)
3714*f6dc9357SAndroid Build Coastguard Worker       }
3715*f6dc9357SAndroid Build Coastguard Worker 
3716*f6dc9357SAndroid Build Coastguard Worker       if (winPos > next)
3717*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_FAIL; // it's unexpected case
3718*f6dc9357SAndroid Build Coastguard Worker       /*
3719*f6dc9357SAndroid Build Coastguard Worker         if (!outBuf_fromCaller && isCyclicMode && cycSize != 0)
3720*f6dc9357SAndroid Build Coastguard Worker           then (winPos <  cycSize)
3721*f6dc9357SAndroid Build Coastguard Worker           else (winPos <= cycSize)
3722*f6dc9357SAndroid Build Coastguard Worker       */
3723*f6dc9357SAndroid Build Coastguard Worker       if (!p->outBuf_fromCaller)
3724*f6dc9357SAndroid Build Coastguard Worker       {
3725*f6dc9357SAndroid Build Coastguard Worker         // that code is optional. We try to optimize write chunk sizes.
3726*f6dc9357SAndroid Build Coastguard Worker         /* (next2) is expected next write position in the caller,
3727*f6dc9357SAndroid Build Coastguard Worker            if the caller writes by kBlockSizeMax chunks.
3728*f6dc9357SAndroid Build Coastguard Worker         */
3729*f6dc9357SAndroid Build Coastguard Worker         /*
3730*f6dc9357SAndroid Build Coastguard Worker         const size_t next2 = (winPos + kBlockSizeMax) & (kBlockSizeMax - 1);
3731*f6dc9357SAndroid Build Coastguard Worker         if (winPos < next2 && next2 < next)
3732*f6dc9357SAndroid Build Coastguard Worker           next = next2;
3733*f6dc9357SAndroid Build Coastguard Worker         */
3734*f6dc9357SAndroid Build Coastguard Worker       }
3735*f6dc9357SAndroid Build Coastguard Worker       size = next - winPos;
3736*f6dc9357SAndroid Build Coastguard Worker     }
3737*f6dc9357SAndroid Build Coastguard Worker 
3738*f6dc9357SAndroid Build Coastguard Worker     // note: ZstdDec_DecodeBlock() uses (winLimit = winPos + size) only for RLE and RAW blocks
3739*f6dc9357SAndroid Build Coastguard Worker     res = ZstdDec_DecodeBlock(dec, p, size);
3740*f6dc9357SAndroid Build Coastguard Worker     /*
3741*f6dc9357SAndroid Build Coastguard Worker       after one block decoding:
3742*f6dc9357SAndroid Build Coastguard Worker       if (!outBuf_fromCaller && isCyclicMode && cycSize != 0)
3743*f6dc9357SAndroid Build Coastguard Worker         then (winPos <  cycSize + max_block_size)
3744*f6dc9357SAndroid Build Coastguard Worker         else (winPos <= cycSize)
3745*f6dc9357SAndroid Build Coastguard Worker     */
3746*f6dc9357SAndroid Build Coastguard Worker 
3747*f6dc9357SAndroid Build Coastguard Worker     if (!p->outBuf_fromCaller)
3748*f6dc9357SAndroid Build Coastguard Worker       p->win = dec->decoder.win;
3749*f6dc9357SAndroid Build Coastguard Worker     p->winPos = dec->decoder.winPos;
3750*f6dc9357SAndroid Build Coastguard Worker 
3751*f6dc9357SAndroid Build Coastguard Worker     // outProcessed = dec->decoder.winPos - winPos;
3752*f6dc9357SAndroid Build Coastguard Worker     // p->outProcessed += outProcessed;
3753*f6dc9357SAndroid Build Coastguard Worker 
3754*f6dc9357SAndroid Build Coastguard Worker     if (res != SZ_OK)
3755*f6dc9357SAndroid Build Coastguard Worker       return res;
3756*f6dc9357SAndroid Build Coastguard Worker 
3757*f6dc9357SAndroid Build Coastguard Worker     if (dec->frameState != ZSTD2_STATE_AFTER_HEADER)
3758*f6dc9357SAndroid Build Coastguard Worker     {
3759*f6dc9357SAndroid Build Coastguard Worker       if (p->outBuf_fromCaller)
3760*f6dc9357SAndroid Build Coastguard Worker         return SZ_OK;
3761*f6dc9357SAndroid Build Coastguard Worker       {
3762*f6dc9357SAndroid Build Coastguard Worker         // !p->outBuf_fromCaller
3763*f6dc9357SAndroid Build Coastguard Worker         /*
3764*f6dc9357SAndroid Build Coastguard Worker           if (ZSTD_STATUS_FINISHED_FRAME), we request full flushing here because
3765*f6dc9357SAndroid Build Coastguard Worker             1) it's simpler to work with allocation and extracting of next frame,
3766*f6dc9357SAndroid Build Coastguard Worker             2) it's better to start writing to next new frame with aligned memory
3767*f6dc9357SAndroid Build Coastguard Worker                for faster xxh 64-bit reads.
3768*f6dc9357SAndroid Build Coastguard Worker         */
3769*f6dc9357SAndroid Build Coastguard Worker         size_t end = dec->decoder.winPos;  // end pos for all data flushing
3770*f6dc9357SAndroid Build Coastguard Worker         if (p->status != ZSTD_STATUS_FINISHED_FRAME)
3771*f6dc9357SAndroid Build Coastguard Worker         {
3772*f6dc9357SAndroid Build Coastguard Worker           // we will request flush here only for cases when wrap in cyclic buffer can be required in next call.
3773*f6dc9357SAndroid Build Coastguard Worker           if (!dec->isCyclicMode)
3774*f6dc9357SAndroid Build Coastguard Worker             return SZ_OK;
3775*f6dc9357SAndroid Build Coastguard Worker           // isCyclicMode
3776*f6dc9357SAndroid Build Coastguard Worker           {
3777*f6dc9357SAndroid Build Coastguard Worker             const size_t delta = dec->decoder.cycSize;
3778*f6dc9357SAndroid Build Coastguard Worker             if (end < delta)
3779*f6dc9357SAndroid Build Coastguard Worker               return SZ_OK; // (winPos < cycSize). no need for flush
3780*f6dc9357SAndroid Build Coastguard Worker             // cycSize <= winPos
3781*f6dc9357SAndroid Build Coastguard Worker             // So we ask the caller to flush of (cycSize - wrPos) bytes,
3782*f6dc9357SAndroid Build Coastguard Worker             // and then we will wrap cylicBuffer in next call
3783*f6dc9357SAndroid Build Coastguard Worker             end = delta;
3784*f6dc9357SAndroid Build Coastguard Worker           }
3785*f6dc9357SAndroid Build Coastguard Worker         }
3786*f6dc9357SAndroid Build Coastguard Worker         p->needWrite_Size = end - p->wrPos;
3787*f6dc9357SAndroid Build Coastguard Worker       }
3788*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
3789*f6dc9357SAndroid Build Coastguard Worker     }
3790*f6dc9357SAndroid Build Coastguard Worker 
3791*f6dc9357SAndroid Build Coastguard Worker     // ZSTD2_STATE_AFTER_HEADER
3792*f6dc9357SAndroid Build Coastguard Worker     {
3793*f6dc9357SAndroid Build Coastguard Worker       BoolInt useCyclic = False;
3794*f6dc9357SAndroid Build Coastguard Worker       size_t cycSize;
3795*f6dc9357SAndroid Build Coastguard Worker 
3796*f6dc9357SAndroid Build Coastguard Worker       // p->status = ZSTD_STATUS_NOT_FINISHED;
3797*f6dc9357SAndroid Build Coastguard Worker       if (dec->dictionaryId != 0)
3798*f6dc9357SAndroid Build Coastguard Worker       {
3799*f6dc9357SAndroid Build Coastguard Worker         /* actually we can try to decode some data,
3800*f6dc9357SAndroid Build Coastguard Worker            because it's possible that some data doesn't use dictionary */
3801*f6dc9357SAndroid Build Coastguard Worker         // p->status = ZSTD_STATUS_NOT_SPECIFIED;
3802*f6dc9357SAndroid Build Coastguard Worker         return SZ_ERROR_UNSUPPORTED;
3803*f6dc9357SAndroid Build Coastguard Worker       }
3804*f6dc9357SAndroid Build Coastguard Worker 
3805*f6dc9357SAndroid Build Coastguard Worker       {
3806*f6dc9357SAndroid Build Coastguard Worker         UInt64 winSize = dec->contentSize;
3807*f6dc9357SAndroid Build Coastguard Worker         UInt64 winSize_Allocate = winSize;
3808*f6dc9357SAndroid Build Coastguard Worker         const unsigned descriptor = dec->descriptor;
3809*f6dc9357SAndroid Build Coastguard Worker 
3810*f6dc9357SAndroid Build Coastguard Worker         if ((descriptor & DESCRIPTOR_FLAG_SINGLE) == 0)
3811*f6dc9357SAndroid Build Coastguard Worker         {
3812*f6dc9357SAndroid Build Coastguard Worker           const Byte wd = dec->windowDescriptor;
3813*f6dc9357SAndroid Build Coastguard Worker           winSize = (UInt64)(8 + (wd & 7)) << ((wd >> 3) + 10 - 3);
3814*f6dc9357SAndroid Build Coastguard Worker           if (!DESCRIPTOR_Is_ContentSize_Defined(descriptor)
3815*f6dc9357SAndroid Build Coastguard Worker               || winSize_Allocate > winSize)
3816*f6dc9357SAndroid Build Coastguard Worker           {
3817*f6dc9357SAndroid Build Coastguard Worker             winSize_Allocate = winSize;
3818*f6dc9357SAndroid Build Coastguard Worker             useCyclic = True;
3819*f6dc9357SAndroid Build Coastguard Worker           }
3820*f6dc9357SAndroid Build Coastguard Worker         }
3821*f6dc9357SAndroid Build Coastguard Worker         /*
3822*f6dc9357SAndroid Build Coastguard Worker         else
3823*f6dc9357SAndroid Build Coastguard Worker         {
3824*f6dc9357SAndroid Build Coastguard Worker           if (p->info.singleSegment_ContentSize_MAX < winSize)
3825*f6dc9357SAndroid Build Coastguard Worker               p->info.singleSegment_ContentSize_MAX = winSize;
3826*f6dc9357SAndroid Build Coastguard Worker           // p->info.num_SingleSegments++;
3827*f6dc9357SAndroid Build Coastguard Worker         }
3828*f6dc9357SAndroid Build Coastguard Worker         */
3829*f6dc9357SAndroid Build Coastguard Worker         if (p->info.windowSize_MAX < winSize)
3830*f6dc9357SAndroid Build Coastguard Worker             p->info.windowSize_MAX = winSize;
3831*f6dc9357SAndroid Build Coastguard Worker         if (p->info.windowSize_Allocate_MAX < winSize_Allocate)
3832*f6dc9357SAndroid Build Coastguard Worker             p->info.windowSize_Allocate_MAX = winSize_Allocate;
3833*f6dc9357SAndroid Build Coastguard Worker         /*
3834*f6dc9357SAndroid Build Coastguard Worker            winSize_Allocate is MIN(content_size, window_size_from_descriptor).
3835*f6dc9357SAndroid Build Coastguard Worker            Wven if (content_size < (window_size_from_descriptor))
3836*f6dc9357SAndroid Build Coastguard Worker              original-zstd still uses (window_size_from_descriptor) to check that decoding is allowed.
3837*f6dc9357SAndroid Build Coastguard Worker            We try to follow original-zstd, and here we check (winSize) instead of (winSize_Allocate))
3838*f6dc9357SAndroid Build Coastguard Worker         */
3839*f6dc9357SAndroid Build Coastguard Worker         if (
3840*f6dc9357SAndroid Build Coastguard Worker               // winSize_Allocate   // it's relaxed check
3841*f6dc9357SAndroid Build Coastguard Worker               winSize               // it's more strict check to be compatible with original-zstd
3842*f6dc9357SAndroid Build Coastguard Worker             > ((UInt64)1 << MAX_WINDOW_SIZE_LOG))
3843*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_UNSUPPORTED; // SZ_ERROR_MEM
3844*f6dc9357SAndroid Build Coastguard Worker         cycSize = (size_t)winSize_Allocate;
3845*f6dc9357SAndroid Build Coastguard Worker         if (cycSize != winSize_Allocate)
3846*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_MEM;
3847*f6dc9357SAndroid Build Coastguard Worker         // cycSize <= winSize
3848*f6dc9357SAndroid Build Coastguard Worker         /* later we will use (CZstdDec1::winSize) to check match offsets and check block sizes.
3849*f6dc9357SAndroid Build Coastguard Worker            if (there is window descriptor)
3850*f6dc9357SAndroid Build Coastguard Worker            {
3851*f6dc9357SAndroid Build Coastguard Worker              We will check block size with (window_size_from_descriptor) instead of (winSize_Allocate).
3852*f6dc9357SAndroid Build Coastguard Worker              Does original-zstd do it that way also?
3853*f6dc9357SAndroid Build Coastguard Worker            }
3854*f6dc9357SAndroid Build Coastguard Worker            Here we must reduce full real 64-bit (winSize) to size_t for (CZstdDec1::winSize).
3855*f6dc9357SAndroid Build Coastguard Worker            Also we don't want too big values for (CZstdDec1::winSize).
3856*f6dc9357SAndroid Build Coastguard Worker            our (CZstdDec1::winSize) will meet the condition:
3857*f6dc9357SAndroid Build Coastguard Worker              (CZstdDec1::winSize < kBlockSizeMax || CZstdDec1::winSize <= cycSize).
3858*f6dc9357SAndroid Build Coastguard Worker         */
3859*f6dc9357SAndroid Build Coastguard Worker         dec->decoder.winSize = (winSize < kBlockSizeMax) ? (size_t)winSize: cycSize;
3860*f6dc9357SAndroid Build Coastguard Worker         // note: (CZstdDec1::winSize > cycSize) is possible, if (!useCyclic)
3861*f6dc9357SAndroid Build Coastguard Worker       }
3862*f6dc9357SAndroid Build Coastguard Worker 
3863*f6dc9357SAndroid Build Coastguard Worker       RINOK(ZstdDec_AllocateMisc(dec))
3864*f6dc9357SAndroid Build Coastguard Worker 
3865*f6dc9357SAndroid Build Coastguard Worker       if (p->outBuf_fromCaller)
3866*f6dc9357SAndroid Build Coastguard Worker         dec->isCyclicMode = False;
3867*f6dc9357SAndroid Build Coastguard Worker       else
3868*f6dc9357SAndroid Build Coastguard Worker       {
3869*f6dc9357SAndroid Build Coastguard Worker         size_t d = cycSize;
3870*f6dc9357SAndroid Build Coastguard Worker 
3871*f6dc9357SAndroid Build Coastguard Worker         if (dec->decoder.winPos != p->wrPos)
3872*f6dc9357SAndroid Build Coastguard Worker           return SZ_ERROR_FAIL;
3873*f6dc9357SAndroid Build Coastguard Worker 
3874*f6dc9357SAndroid Build Coastguard Worker         dec->decoder.winPos = 0;
3875*f6dc9357SAndroid Build Coastguard Worker         p->wrPos = 0;
3876*f6dc9357SAndroid Build Coastguard Worker         p->winPos = dec->decoder.winPos;
3877*f6dc9357SAndroid Build Coastguard Worker 
3878*f6dc9357SAndroid Build Coastguard Worker         /*
3879*f6dc9357SAndroid Build Coastguard Worker         const size_t needWrite = dec->decoder.winPos - p->wrPos;
3880*f6dc9357SAndroid Build Coastguard Worker         if (!needWrite)
3881*f6dc9357SAndroid Build Coastguard Worker         {
3882*f6dc9357SAndroid Build Coastguard Worker           dec->decoder.winPos = 0;
3883*f6dc9357SAndroid Build Coastguard Worker           p->wrPos = 0;
3884*f6dc9357SAndroid Build Coastguard Worker           p->winPos = dec->decoder.winPos;
3885*f6dc9357SAndroid Build Coastguard Worker         }
3886*f6dc9357SAndroid Build Coastguard Worker         */
3887*f6dc9357SAndroid Build Coastguard Worker         /* if (!useCyclic) we allocate only cycSize = ContentSize.
3888*f6dc9357SAndroid Build Coastguard Worker            But if we want to support the case where new frame starts with winPos != 0,
3889*f6dc9357SAndroid Build Coastguard Worker            then we will wrap over zero, and we still need
3890*f6dc9357SAndroid Build Coastguard Worker            to set (useCyclic) and allocate additional buffer spaces.
3891*f6dc9357SAndroid Build Coastguard Worker            Now we don't allow new frame starting with (winPos != 0).
3892*f6dc9357SAndroid Build Coastguard Worker            so (dec->decoder->winPos == 0)
3893*f6dc9357SAndroid Build Coastguard Worker            can use (!useCyclic) with reduced buffer sizes.
3894*f6dc9357SAndroid Build Coastguard Worker         */
3895*f6dc9357SAndroid Build Coastguard Worker         /*
3896*f6dc9357SAndroid Build Coastguard Worker         if (dec->decoder->winPos != 0)
3897*f6dc9357SAndroid Build Coastguard Worker           useCyclic = True;
3898*f6dc9357SAndroid Build Coastguard Worker         */
3899*f6dc9357SAndroid Build Coastguard Worker 
3900*f6dc9357SAndroid Build Coastguard Worker         if (useCyclic)
3901*f6dc9357SAndroid Build Coastguard Worker         {
3902*f6dc9357SAndroid Build Coastguard Worker           /* cyclyc buffer size must be at least (COPY_CHUNK_SIZE - 1) bytes
3903*f6dc9357SAndroid Build Coastguard Worker              larger than window size, because CopyMatch() can write additional
3904*f6dc9357SAndroid Build Coastguard Worker              (COPY_CHUNK_SIZE - 1) bytes and overwrite oldests data in cyclyc buffer.
3905*f6dc9357SAndroid Build Coastguard Worker              But for performance reasons we align (cycSize) for (kBlockSizeMax).
3906*f6dc9357SAndroid Build Coastguard Worker              also we must provide (cycSize >= max_decoded_data_after_cycSize),
3907*f6dc9357SAndroid Build Coastguard Worker              because after data move wrapping over zero we must provide (winPos < cycSize).
3908*f6dc9357SAndroid Build Coastguard Worker           */
3909*f6dc9357SAndroid Build Coastguard Worker           const size_t alignSize = kBlockSizeMax;
3910*f6dc9357SAndroid Build Coastguard Worker           /* here we add (1 << 7) instead of (COPY_CHUNK_SIZE - 1), because
3911*f6dc9357SAndroid Build Coastguard Worker              we want to get same (cycSize) for different COPY_CHUNK_SIZE values. */
3912*f6dc9357SAndroid Build Coastguard Worker           // cycSize += (COPY_CHUNK_SIZE - 1) + (alignSize - 1); // for debug : we can get smallest (cycSize)
3913*f6dc9357SAndroid Build Coastguard Worker           cycSize += (1 << 7) + alignSize;
3914*f6dc9357SAndroid Build Coastguard Worker           cycSize &= ~(size_t)(alignSize - 1);
3915*f6dc9357SAndroid Build Coastguard Worker           // cycSize must be aligned for 32, because xxh requires 32-bytes blocks.
3916*f6dc9357SAndroid Build Coastguard Worker           // cycSize += 12345; // for debug
3917*f6dc9357SAndroid Build Coastguard Worker           // cycSize += 1 << 10; // for debug
3918*f6dc9357SAndroid Build Coastguard Worker           // cycSize += 32; // for debug
3919*f6dc9357SAndroid Build Coastguard Worker           // cycSize += kBlockSizeMax; // for debug
3920*f6dc9357SAndroid Build Coastguard Worker           if (cycSize < d)
3921*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_MEM;
3922*f6dc9357SAndroid Build Coastguard Worker           /*
3923*f6dc9357SAndroid Build Coastguard Worker              in cyclic buffer mode we allow to decode one additional block
3924*f6dc9357SAndroid Build Coastguard Worker              that exceeds (cycSize).
3925*f6dc9357SAndroid Build Coastguard Worker              So we must allocate additional (kBlockSizeMax) bytes after (cycSize).
3926*f6dc9357SAndroid Build Coastguard Worker              if defined(Z7_STD_DEC_USE_AFTER_CYC_BUF)
3927*f6dc9357SAndroid Build Coastguard Worker              {
3928*f6dc9357SAndroid Build Coastguard Worker                we can read (COPY_CHUNK_SIZE - 1) bytes after (cycSize)
3929*f6dc9357SAndroid Build Coastguard Worker                but we aready allocate additional kBlockSizeMax that
3930*f6dc9357SAndroid Build Coastguard Worker                is larger than COPY_CHUNK_SIZE.
3931*f6dc9357SAndroid Build Coastguard Worker                So we don't need additional space of COPY_CHUNK_SIZE after (cycSize).
3932*f6dc9357SAndroid Build Coastguard Worker              }
3933*f6dc9357SAndroid Build Coastguard Worker           */
3934*f6dc9357SAndroid Build Coastguard Worker           /*
3935*f6dc9357SAndroid Build Coastguard Worker           #ifdef Z7_STD_DEC_USE_AFTER_CYC_BUF
3936*f6dc9357SAndroid Build Coastguard Worker           d = cycSize + (1 << 7); // we must add at least (COPY_CHUNK_SIZE - 1)
3937*f6dc9357SAndroid Build Coastguard Worker           #endif
3938*f6dc9357SAndroid Build Coastguard Worker           */
3939*f6dc9357SAndroid Build Coastguard Worker           d = cycSize + kBlockSizeMax;
3940*f6dc9357SAndroid Build Coastguard Worker           if (d < cycSize)
3941*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_MEM;
3942*f6dc9357SAndroid Build Coastguard Worker         }
3943*f6dc9357SAndroid Build Coastguard Worker 
3944*f6dc9357SAndroid Build Coastguard Worker         {
3945*f6dc9357SAndroid Build Coastguard Worker           const size_t kMinWinAllocSize = 1 << 12;
3946*f6dc9357SAndroid Build Coastguard Worker           if (d < kMinWinAllocSize)
3947*f6dc9357SAndroid Build Coastguard Worker               d = kMinWinAllocSize;
3948*f6dc9357SAndroid Build Coastguard Worker         }
3949*f6dc9357SAndroid Build Coastguard Worker 
3950*f6dc9357SAndroid Build Coastguard Worker         if (d > dec->winBufSize_Allocated)
3951*f6dc9357SAndroid Build Coastguard Worker         {
3952*f6dc9357SAndroid Build Coastguard Worker           /*
3953*f6dc9357SAndroid Build Coastguard Worker           if (needWrite)
3954*f6dc9357SAndroid Build Coastguard Worker           {
3955*f6dc9357SAndroid Build Coastguard Worker             p->needWrite_Size = needWrite;
3956*f6dc9357SAndroid Build Coastguard Worker             return SZ_OK;
3957*f6dc9357SAndroid Build Coastguard Worker             // return SZ_ERROR_FAIL;
3958*f6dc9357SAndroid Build Coastguard Worker           }
3959*f6dc9357SAndroid Build Coastguard Worker           */
3960*f6dc9357SAndroid Build Coastguard Worker 
3961*f6dc9357SAndroid Build Coastguard Worker           if (dec->winBufSize_Allocated != 0)
3962*f6dc9357SAndroid Build Coastguard Worker           {
3963*f6dc9357SAndroid Build Coastguard Worker             const size_t k_extra = (useCyclic || d >= (1u << 20)) ?
3964*f6dc9357SAndroid Build Coastguard Worker                 2 * kBlockSizeMax : 0;
3965*f6dc9357SAndroid Build Coastguard Worker             unsigned i = useCyclic ? 17 : 12;
3966*f6dc9357SAndroid Build Coastguard Worker             for (; i < sizeof(size_t) * 8; i++)
3967*f6dc9357SAndroid Build Coastguard Worker             {
3968*f6dc9357SAndroid Build Coastguard Worker               const size_t d2 = ((size_t)1 << i) + k_extra;
3969*f6dc9357SAndroid Build Coastguard Worker               if (d2 >= d)
3970*f6dc9357SAndroid Build Coastguard Worker               {
3971*f6dc9357SAndroid Build Coastguard Worker                 d = d2;
3972*f6dc9357SAndroid Build Coastguard Worker                 break;
3973*f6dc9357SAndroid Build Coastguard Worker               }
3974*f6dc9357SAndroid Build Coastguard Worker             }
3975*f6dc9357SAndroid Build Coastguard Worker           }
3976*f6dc9357SAndroid Build Coastguard Worker           // RINOK(ZstdDec_AllocateWindow(dec, d))
3977*f6dc9357SAndroid Build Coastguard Worker           ZstdDec_FreeWindow(dec);
3978*f6dc9357SAndroid Build Coastguard Worker           dec->win_Base = (Byte *)ISzAlloc_Alloc(dec->alloc_Big, d);
3979*f6dc9357SAndroid Build Coastguard Worker           if (!dec->win_Base)
3980*f6dc9357SAndroid Build Coastguard Worker             return SZ_ERROR_MEM;
3981*f6dc9357SAndroid Build Coastguard Worker           dec->decoder.win = dec->win_Base;
3982*f6dc9357SAndroid Build Coastguard Worker           dec->winBufSize_Allocated = d;
3983*f6dc9357SAndroid Build Coastguard Worker         }
3984*f6dc9357SAndroid Build Coastguard Worker         /*
3985*f6dc9357SAndroid Build Coastguard Worker         else
3986*f6dc9357SAndroid Build Coastguard Worker         {
3987*f6dc9357SAndroid Build Coastguard Worker           // for non-cyclycMode we want flush data, and set winPos = 0
3988*f6dc9357SAndroid Build Coastguard Worker           if (needWrite)
3989*f6dc9357SAndroid Build Coastguard Worker           {
3990*f6dc9357SAndroid Build Coastguard Worker             if (!useCyclic || dec->decoder.winPos >= cycSize)
3991*f6dc9357SAndroid Build Coastguard Worker             {
3992*f6dc9357SAndroid Build Coastguard Worker               p->needWrite_Size = needWrite;
3993*f6dc9357SAndroid Build Coastguard Worker               return SZ_OK;
3994*f6dc9357SAndroid Build Coastguard Worker               // return SZ_ERROR_FAIL;
3995*f6dc9357SAndroid Build Coastguard Worker             }
3996*f6dc9357SAndroid Build Coastguard Worker           }
3997*f6dc9357SAndroid Build Coastguard Worker         }
3998*f6dc9357SAndroid Build Coastguard Worker         */
3999*f6dc9357SAndroid Build Coastguard Worker 
4000*f6dc9357SAndroid Build Coastguard Worker         dec->decoder.cycSize = cycSize;
4001*f6dc9357SAndroid Build Coastguard Worker         p->win = dec->decoder.win;
4002*f6dc9357SAndroid Build Coastguard Worker         // p->cycSize = dec->decoder.cycSize;
4003*f6dc9357SAndroid Build Coastguard Worker         dec->isCyclicMode = (Byte)useCyclic;
4004*f6dc9357SAndroid Build Coastguard Worker       } // (!p->outBuf_fromCaller) end
4005*f6dc9357SAndroid Build Coastguard Worker 
4006*f6dc9357SAndroid Build Coastguard Worker       // p->winPos = dec->decoder.winPos;
4007*f6dc9357SAndroid Build Coastguard Worker       dec->frameState = ZSTD2_STATE_BLOCK;
4008*f6dc9357SAndroid Build Coastguard Worker       // continue;
4009*f6dc9357SAndroid Build Coastguard Worker     } // ZSTD2_STATE_AFTER_HEADER end
4010*f6dc9357SAndroid Build Coastguard Worker   }
4011*f6dc9357SAndroid Build Coastguard Worker }
4012*f6dc9357SAndroid Build Coastguard Worker 
4013*f6dc9357SAndroid Build Coastguard Worker 
4014*f6dc9357SAndroid Build Coastguard Worker void ZstdDec_GetResInfo(const CZstdDec *dec,
4015*f6dc9357SAndroid Build Coastguard Worker     const CZstdDecState *p,
4016*f6dc9357SAndroid Build Coastguard Worker     SRes res,
4017*f6dc9357SAndroid Build Coastguard Worker     CZstdDecResInfo *stat)
4018*f6dc9357SAndroid Build Coastguard Worker {
4019*f6dc9357SAndroid Build Coastguard Worker   // ZstdDecInfo_CLEAR(stat);
4020*f6dc9357SAndroid Build Coastguard Worker   stat->extraSize = 0;
4021*f6dc9357SAndroid Build Coastguard Worker   stat->is_NonFinishedFrame = False;
4022*f6dc9357SAndroid Build Coastguard Worker   if (dec->frameState != ZSTD2_STATE_FINISHED)
4023*f6dc9357SAndroid Build Coastguard Worker   {
4024*f6dc9357SAndroid Build Coastguard Worker     if (dec->frameState == ZSTD2_STATE_SIGNATURE)
4025*f6dc9357SAndroid Build Coastguard Worker     {
4026*f6dc9357SAndroid Build Coastguard Worker       stat->extraSize = (Byte)dec->tempSize;
4027*f6dc9357SAndroid Build Coastguard Worker       if (ZstdDecInfo_GET_NUM_FRAMES(&p->info) == 0)
4028*f6dc9357SAndroid Build Coastguard Worker         res = SZ_ERROR_NO_ARCHIVE;
4029*f6dc9357SAndroid Build Coastguard Worker     }
4030*f6dc9357SAndroid Build Coastguard Worker     else
4031*f6dc9357SAndroid Build Coastguard Worker     {
4032*f6dc9357SAndroid Build Coastguard Worker       stat->is_NonFinishedFrame = True;
4033*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_OK && p->status == ZSTD_STATUS_NEEDS_MORE_INPUT)
4034*f6dc9357SAndroid Build Coastguard Worker         res = SZ_ERROR_INPUT_EOF;
4035*f6dc9357SAndroid Build Coastguard Worker     }
4036*f6dc9357SAndroid Build Coastguard Worker   }
4037*f6dc9357SAndroid Build Coastguard Worker   stat->decode_SRes = res;
4038*f6dc9357SAndroid Build Coastguard Worker }
4039*f6dc9357SAndroid Build Coastguard Worker 
4040*f6dc9357SAndroid Build Coastguard Worker 
4041*f6dc9357SAndroid Build Coastguard Worker size_t ZstdDec_ReadUnusedFromInBuf(
4042*f6dc9357SAndroid Build Coastguard Worker     CZstdDecHandle dec,
4043*f6dc9357SAndroid Build Coastguard Worker     size_t afterDecoding_tempPos,
4044*f6dc9357SAndroid Build Coastguard Worker     void *data, size_t size)
4045*f6dc9357SAndroid Build Coastguard Worker {
4046*f6dc9357SAndroid Build Coastguard Worker   size_t processed = 0;
4047*f6dc9357SAndroid Build Coastguard Worker   if (dec->frameState == ZSTD2_STATE_SIGNATURE)
4048*f6dc9357SAndroid Build Coastguard Worker   {
4049*f6dc9357SAndroid Build Coastguard Worker     Byte *dest = (Byte *)data;
4050*f6dc9357SAndroid Build Coastguard Worker     const size_t tempSize = dec->tempSize;
4051*f6dc9357SAndroid Build Coastguard Worker     while (afterDecoding_tempPos < tempSize)
4052*f6dc9357SAndroid Build Coastguard Worker     {
4053*f6dc9357SAndroid Build Coastguard Worker       if (size == 0)
4054*f6dc9357SAndroid Build Coastguard Worker         break;
4055*f6dc9357SAndroid Build Coastguard Worker       size--;
4056*f6dc9357SAndroid Build Coastguard Worker       *dest++ = dec->temp[afterDecoding_tempPos++];
4057*f6dc9357SAndroid Build Coastguard Worker       processed++;
4058*f6dc9357SAndroid Build Coastguard Worker     }
4059*f6dc9357SAndroid Build Coastguard Worker   }
4060*f6dc9357SAndroid Build Coastguard Worker   return processed;
4061*f6dc9357SAndroid Build Coastguard Worker }
4062*f6dc9357SAndroid Build Coastguard Worker 
4063*f6dc9357SAndroid Build Coastguard Worker 
4064*f6dc9357SAndroid Build Coastguard Worker void ZstdDecState_Clear(CZstdDecState *p)
4065*f6dc9357SAndroid Build Coastguard Worker {
4066*f6dc9357SAndroid Build Coastguard Worker   memset(p, 0 , sizeof(*p));
4067*f6dc9357SAndroid Build Coastguard Worker }
4068