xref: /dflybsd-src/contrib/zstd/lib/compress/zstd_compress_internal.h (revision a28cd43d19e8b720a6c852a4bbc5ae147a26165a)
1*a28cd43dSSascha Wildner /*
2*a28cd43dSSascha Wildner  * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3*a28cd43dSSascha Wildner  * All rights reserved.
4*a28cd43dSSascha Wildner  *
5*a28cd43dSSascha Wildner  * This source code is licensed under both the BSD-style license (found in the
6*a28cd43dSSascha Wildner  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7*a28cd43dSSascha Wildner  * in the COPYING file in the root directory of this source tree).
8*a28cd43dSSascha Wildner  * You may select, at your option, one of the above-listed licenses.
9*a28cd43dSSascha Wildner  */
10*a28cd43dSSascha Wildner 
11*a28cd43dSSascha Wildner /* This header contains definitions
12*a28cd43dSSascha Wildner  * that shall **only** be used by modules within lib/compress.
13*a28cd43dSSascha Wildner  */
14*a28cd43dSSascha Wildner 
15*a28cd43dSSascha Wildner #ifndef ZSTD_COMPRESS_H
16*a28cd43dSSascha Wildner #define ZSTD_COMPRESS_H
17*a28cd43dSSascha Wildner 
18*a28cd43dSSascha Wildner /*-*************************************
19*a28cd43dSSascha Wildner *  Dependencies
20*a28cd43dSSascha Wildner ***************************************/
21*a28cd43dSSascha Wildner #include "../common/zstd_internal.h"
22*a28cd43dSSascha Wildner #include "zstd_cwksp.h"
23*a28cd43dSSascha Wildner #ifdef ZSTD_MULTITHREAD
24*a28cd43dSSascha Wildner #  include "zstdmt_compress.h"
25*a28cd43dSSascha Wildner #endif
26*a28cd43dSSascha Wildner 
27*a28cd43dSSascha Wildner #if defined (__cplusplus)
28*a28cd43dSSascha Wildner extern "C" {
29*a28cd43dSSascha Wildner #endif
30*a28cd43dSSascha Wildner 
31*a28cd43dSSascha Wildner /*-*************************************
32*a28cd43dSSascha Wildner *  Constants
33*a28cd43dSSascha Wildner ***************************************/
34*a28cd43dSSascha Wildner #define kSearchStrength      8
35*a28cd43dSSascha Wildner #define HASH_READ_SIZE       8
36*a28cd43dSSascha Wildner #define ZSTD_DUBT_UNSORTED_MARK 1   /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means "unsorted".
37*a28cd43dSSascha Wildner                                        It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
38*a28cd43dSSascha Wildner                                        It's not a big deal though : candidate will just be sorted again.
39*a28cd43dSSascha Wildner                                        Additionally, candidate position 1 will be lost.
40*a28cd43dSSascha Wildner                                        But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
41*a28cd43dSSascha Wildner                                        The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy.
42*a28cd43dSSascha Wildner                                        This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
43*a28cd43dSSascha Wildner 
44*a28cd43dSSascha Wildner 
45*a28cd43dSSascha Wildner /*-*************************************
46*a28cd43dSSascha Wildner *  Context memory management
47*a28cd43dSSascha Wildner ***************************************/
48*a28cd43dSSascha Wildner typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
49*a28cd43dSSascha Wildner typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
50*a28cd43dSSascha Wildner 
51*a28cd43dSSascha Wildner typedef struct ZSTD_prefixDict_s {
52*a28cd43dSSascha Wildner     const void* dict;
53*a28cd43dSSascha Wildner     size_t dictSize;
54*a28cd43dSSascha Wildner     ZSTD_dictContentType_e dictContentType;
55*a28cd43dSSascha Wildner } ZSTD_prefixDict;
56*a28cd43dSSascha Wildner 
57*a28cd43dSSascha Wildner typedef struct {
58*a28cd43dSSascha Wildner     void* dictBuffer;
59*a28cd43dSSascha Wildner     void const* dict;
60*a28cd43dSSascha Wildner     size_t dictSize;
61*a28cd43dSSascha Wildner     ZSTD_dictContentType_e dictContentType;
62*a28cd43dSSascha Wildner     ZSTD_CDict* cdict;
63*a28cd43dSSascha Wildner } ZSTD_localDict;
64*a28cd43dSSascha Wildner 
65*a28cd43dSSascha Wildner typedef struct {
66*a28cd43dSSascha Wildner     HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)];
67*a28cd43dSSascha Wildner     HUF_repeat repeatMode;
68*a28cd43dSSascha Wildner } ZSTD_hufCTables_t;
69*a28cd43dSSascha Wildner 
70*a28cd43dSSascha Wildner typedef struct {
71*a28cd43dSSascha Wildner     FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
72*a28cd43dSSascha Wildner     FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
73*a28cd43dSSascha Wildner     FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
74*a28cd43dSSascha Wildner     FSE_repeat offcode_repeatMode;
75*a28cd43dSSascha Wildner     FSE_repeat matchlength_repeatMode;
76*a28cd43dSSascha Wildner     FSE_repeat litlength_repeatMode;
77*a28cd43dSSascha Wildner } ZSTD_fseCTables_t;
78*a28cd43dSSascha Wildner 
79*a28cd43dSSascha Wildner typedef struct {
80*a28cd43dSSascha Wildner     ZSTD_hufCTables_t huf;
81*a28cd43dSSascha Wildner     ZSTD_fseCTables_t fse;
82*a28cd43dSSascha Wildner } ZSTD_entropyCTables_t;
83*a28cd43dSSascha Wildner 
84*a28cd43dSSascha Wildner typedef struct {
85*a28cd43dSSascha Wildner     U32 off;            /* Offset code (offset + ZSTD_REP_MOVE) for the match */
86*a28cd43dSSascha Wildner     U32 len;            /* Raw length of match */
87*a28cd43dSSascha Wildner } ZSTD_match_t;
88*a28cd43dSSascha Wildner 
89*a28cd43dSSascha Wildner typedef struct {
90*a28cd43dSSascha Wildner     U32 offset;         /* Offset of sequence */
91*a28cd43dSSascha Wildner     U32 litLength;      /* Length of literals prior to match */
92*a28cd43dSSascha Wildner     U32 matchLength;    /* Raw length of match */
93*a28cd43dSSascha Wildner } rawSeq;
94*a28cd43dSSascha Wildner 
95*a28cd43dSSascha Wildner typedef struct {
96*a28cd43dSSascha Wildner   rawSeq* seq;          /* The start of the sequences */
97*a28cd43dSSascha Wildner   size_t pos;           /* The index in seq where reading stopped. pos <= size. */
98*a28cd43dSSascha Wildner   size_t posInSequence; /* The position within the sequence at seq[pos] where reading
99*a28cd43dSSascha Wildner                            stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */
100*a28cd43dSSascha Wildner   size_t size;          /* The number of sequences. <= capacity. */
101*a28cd43dSSascha Wildner   size_t capacity;      /* The capacity starting from `seq` pointer */
102*a28cd43dSSascha Wildner } rawSeqStore_t;
103*a28cd43dSSascha Wildner 
104*a28cd43dSSascha Wildner UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
105*a28cd43dSSascha Wildner 
106*a28cd43dSSascha Wildner typedef struct {
107*a28cd43dSSascha Wildner     int price;
108*a28cd43dSSascha Wildner     U32 off;
109*a28cd43dSSascha Wildner     U32 mlen;
110*a28cd43dSSascha Wildner     U32 litlen;
111*a28cd43dSSascha Wildner     U32 rep[ZSTD_REP_NUM];
112*a28cd43dSSascha Wildner } ZSTD_optimal_t;
113*a28cd43dSSascha Wildner 
114*a28cd43dSSascha Wildner typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
115*a28cd43dSSascha Wildner 
116*a28cd43dSSascha Wildner typedef struct {
117*a28cd43dSSascha Wildner     /* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
118*a28cd43dSSascha Wildner     unsigned* litFreq;           /* table of literals statistics, of size 256 */
119*a28cd43dSSascha Wildner     unsigned* litLengthFreq;     /* table of litLength statistics, of size (MaxLL+1) */
120*a28cd43dSSascha Wildner     unsigned* matchLengthFreq;   /* table of matchLength statistics, of size (MaxML+1) */
121*a28cd43dSSascha Wildner     unsigned* offCodeFreq;       /* table of offCode statistics, of size (MaxOff+1) */
122*a28cd43dSSascha Wildner     ZSTD_match_t* matchTable;    /* list of found matches, of size ZSTD_OPT_NUM+1 */
123*a28cd43dSSascha Wildner     ZSTD_optimal_t* priceTable;  /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
124*a28cd43dSSascha Wildner 
125*a28cd43dSSascha Wildner     U32  litSum;                 /* nb of literals */
126*a28cd43dSSascha Wildner     U32  litLengthSum;           /* nb of litLength codes */
127*a28cd43dSSascha Wildner     U32  matchLengthSum;         /* nb of matchLength codes */
128*a28cd43dSSascha Wildner     U32  offCodeSum;             /* nb of offset codes */
129*a28cd43dSSascha Wildner     U32  litSumBasePrice;        /* to compare to log2(litfreq) */
130*a28cd43dSSascha Wildner     U32  litLengthSumBasePrice;  /* to compare to log2(llfreq)  */
131*a28cd43dSSascha Wildner     U32  matchLengthSumBasePrice;/* to compare to log2(mlfreq)  */
132*a28cd43dSSascha Wildner     U32  offCodeSumBasePrice;    /* to compare to log2(offreq)  */
133*a28cd43dSSascha Wildner     ZSTD_OptPrice_e priceType;   /* prices can be determined dynamically, or follow a pre-defined cost structure */
134*a28cd43dSSascha Wildner     const ZSTD_entropyCTables_t* symbolCosts;  /* pre-calculated dictionary statistics */
135*a28cd43dSSascha Wildner     ZSTD_literalCompressionMode_e literalCompressionMode;
136*a28cd43dSSascha Wildner } optState_t;
137*a28cd43dSSascha Wildner 
138*a28cd43dSSascha Wildner typedef struct {
139*a28cd43dSSascha Wildner   ZSTD_entropyCTables_t entropy;
140*a28cd43dSSascha Wildner   U32 rep[ZSTD_REP_NUM];
141*a28cd43dSSascha Wildner } ZSTD_compressedBlockState_t;
142*a28cd43dSSascha Wildner 
143*a28cd43dSSascha Wildner typedef struct {
144*a28cd43dSSascha Wildner     BYTE const* nextSrc;    /* next block here to continue on current prefix */
145*a28cd43dSSascha Wildner     BYTE const* base;       /* All regular indexes relative to this position */
146*a28cd43dSSascha Wildner     BYTE const* dictBase;   /* extDict indexes relative to this position */
147*a28cd43dSSascha Wildner     U32 dictLimit;          /* below that point, need extDict */
148*a28cd43dSSascha Wildner     U32 lowLimit;           /* below that point, no more valid data */
149*a28cd43dSSascha Wildner } ZSTD_window_t;
150*a28cd43dSSascha Wildner 
151*a28cd43dSSascha Wildner typedef struct ZSTD_matchState_t ZSTD_matchState_t;
152*a28cd43dSSascha Wildner struct ZSTD_matchState_t {
153*a28cd43dSSascha Wildner     ZSTD_window_t window;   /* State for window round buffer management */
154*a28cd43dSSascha Wildner     U32 loadedDictEnd;      /* index of end of dictionary, within context's referential.
155*a28cd43dSSascha Wildner                              * When loadedDictEnd != 0, a dictionary is in use, and still valid.
156*a28cd43dSSascha Wildner                              * This relies on a mechanism to set loadedDictEnd=0 when dictionary is no longer within distance.
157*a28cd43dSSascha Wildner                              * Such mechanism is provided within ZSTD_window_enforceMaxDist() and ZSTD_checkDictValidity().
158*a28cd43dSSascha Wildner                              * When dict referential is copied into active context (i.e. not attached),
159*a28cd43dSSascha Wildner                              * loadedDictEnd == dictSize, since referential starts from zero.
160*a28cd43dSSascha Wildner                              */
161*a28cd43dSSascha Wildner     U32 nextToUpdate;       /* index from which to continue table update */
162*a28cd43dSSascha Wildner     U32 hashLog3;           /* dispatch table for matches of len==3 : larger == faster, more memory */
163*a28cd43dSSascha Wildner     U32* hashTable;
164*a28cd43dSSascha Wildner     U32* hashTable3;
165*a28cd43dSSascha Wildner     U32* chainTable;
166*a28cd43dSSascha Wildner     int dedicatedDictSearch;  /* Indicates whether this matchState is using the
167*a28cd43dSSascha Wildner                                * dedicated dictionary search structure.
168*a28cd43dSSascha Wildner                                */
169*a28cd43dSSascha Wildner     optState_t opt;         /* optimal parser state */
170*a28cd43dSSascha Wildner     const ZSTD_matchState_t* dictMatchState;
171*a28cd43dSSascha Wildner     ZSTD_compressionParameters cParams;
172*a28cd43dSSascha Wildner     const rawSeqStore_t* ldmSeqStore;
173*a28cd43dSSascha Wildner };
174*a28cd43dSSascha Wildner 
175*a28cd43dSSascha Wildner typedef struct {
176*a28cd43dSSascha Wildner     ZSTD_compressedBlockState_t* prevCBlock;
177*a28cd43dSSascha Wildner     ZSTD_compressedBlockState_t* nextCBlock;
178*a28cd43dSSascha Wildner     ZSTD_matchState_t matchState;
179*a28cd43dSSascha Wildner } ZSTD_blockState_t;
180*a28cd43dSSascha Wildner 
181*a28cd43dSSascha Wildner typedef struct {
182*a28cd43dSSascha Wildner     U32 offset;
183*a28cd43dSSascha Wildner     U32 checksum;
184*a28cd43dSSascha Wildner } ldmEntry_t;
185*a28cd43dSSascha Wildner 
186*a28cd43dSSascha Wildner typedef struct {
187*a28cd43dSSascha Wildner     ZSTD_window_t window;   /* State for the window round buffer management */
188*a28cd43dSSascha Wildner     ldmEntry_t* hashTable;
189*a28cd43dSSascha Wildner     U32 loadedDictEnd;
190*a28cd43dSSascha Wildner     BYTE* bucketOffsets;    /* Next position in bucket to insert entry */
191*a28cd43dSSascha Wildner     U64 hashPower;          /* Used to compute the rolling hash.
192*a28cd43dSSascha Wildner                              * Depends on ldmParams.minMatchLength */
193*a28cd43dSSascha Wildner } ldmState_t;
194*a28cd43dSSascha Wildner 
195*a28cd43dSSascha Wildner typedef struct {
196*a28cd43dSSascha Wildner     U32 enableLdm;          /* 1 if enable long distance matching */
197*a28cd43dSSascha Wildner     U32 hashLog;            /* Log size of hashTable */
198*a28cd43dSSascha Wildner     U32 bucketSizeLog;      /* Log bucket size for collision resolution, at most 8 */
199*a28cd43dSSascha Wildner     U32 minMatchLength;     /* Minimum match length */
200*a28cd43dSSascha Wildner     U32 hashRateLog;       /* Log number of entries to skip */
201*a28cd43dSSascha Wildner     U32 windowLog;          /* Window log for the LDM */
202*a28cd43dSSascha Wildner } ldmParams_t;
203*a28cd43dSSascha Wildner 
204*a28cd43dSSascha Wildner typedef struct {
205*a28cd43dSSascha Wildner     int collectSequences;
206*a28cd43dSSascha Wildner     ZSTD_Sequence* seqStart;
207*a28cd43dSSascha Wildner     size_t seqIndex;
208*a28cd43dSSascha Wildner     size_t maxSequences;
209*a28cd43dSSascha Wildner } SeqCollector;
210*a28cd43dSSascha Wildner 
211*a28cd43dSSascha Wildner struct ZSTD_CCtx_params_s {
212*a28cd43dSSascha Wildner     ZSTD_format_e format;
213*a28cd43dSSascha Wildner     ZSTD_compressionParameters cParams;
214*a28cd43dSSascha Wildner     ZSTD_frameParameters fParams;
215*a28cd43dSSascha Wildner 
216*a28cd43dSSascha Wildner     int compressionLevel;
217*a28cd43dSSascha Wildner     int forceWindow;           /* force back-references to respect limit of
218*a28cd43dSSascha Wildner                                 * 1<<wLog, even for dictionary */
219*a28cd43dSSascha Wildner     size_t targetCBlockSize;   /* Tries to fit compressed block size to be around targetCBlockSize.
220*a28cd43dSSascha Wildner                                 * No target when targetCBlockSize == 0.
221*a28cd43dSSascha Wildner                                 * There is no guarantee on compressed block size */
222*a28cd43dSSascha Wildner     int srcSizeHint;           /* User's best guess of source size.
223*a28cd43dSSascha Wildner                                 * Hint is not valid when srcSizeHint == 0.
224*a28cd43dSSascha Wildner                                 * There is no guarantee that hint is close to actual source size */
225*a28cd43dSSascha Wildner 
226*a28cd43dSSascha Wildner     ZSTD_dictAttachPref_e attachDictPref;
227*a28cd43dSSascha Wildner     ZSTD_literalCompressionMode_e literalCompressionMode;
228*a28cd43dSSascha Wildner 
229*a28cd43dSSascha Wildner     /* Multithreading: used to pass parameters to mtctx */
230*a28cd43dSSascha Wildner     int nbWorkers;
231*a28cd43dSSascha Wildner     size_t jobSize;
232*a28cd43dSSascha Wildner     int overlapLog;
233*a28cd43dSSascha Wildner     int rsyncable;
234*a28cd43dSSascha Wildner 
235*a28cd43dSSascha Wildner     /* Long distance matching parameters */
236*a28cd43dSSascha Wildner     ldmParams_t ldmParams;
237*a28cd43dSSascha Wildner 
238*a28cd43dSSascha Wildner     /* Dedicated dict search algorithm trigger */
239*a28cd43dSSascha Wildner     int enableDedicatedDictSearch;
240*a28cd43dSSascha Wildner 
241*a28cd43dSSascha Wildner     /* Input/output buffer modes */
242*a28cd43dSSascha Wildner     ZSTD_bufferMode_e inBufferMode;
243*a28cd43dSSascha Wildner     ZSTD_bufferMode_e outBufferMode;
244*a28cd43dSSascha Wildner 
245*a28cd43dSSascha Wildner     /* Sequence compression API */
246*a28cd43dSSascha Wildner     ZSTD_sequenceFormat_e blockDelimiters;
247*a28cd43dSSascha Wildner     int validateSequences;
248*a28cd43dSSascha Wildner 
249*a28cd43dSSascha Wildner     /* Internal use, for createCCtxParams() and freeCCtxParams() only */
250*a28cd43dSSascha Wildner     ZSTD_customMem customMem;
251*a28cd43dSSascha Wildner };  /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
252*a28cd43dSSascha Wildner 
253*a28cd43dSSascha Wildner #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
254*a28cd43dSSascha Wildner #define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)
255*a28cd43dSSascha Wildner 
256*a28cd43dSSascha Wildner /**
257*a28cd43dSSascha Wildner  * Indicates whether this compression proceeds directly from user-provided
258*a28cd43dSSascha Wildner  * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
259*a28cd43dSSascha Wildner  * whether the context needs to buffer the input/output (ZSTDb_buffered).
260*a28cd43dSSascha Wildner  */
261*a28cd43dSSascha Wildner typedef enum {
262*a28cd43dSSascha Wildner     ZSTDb_not_buffered,
263*a28cd43dSSascha Wildner     ZSTDb_buffered
264*a28cd43dSSascha Wildner } ZSTD_buffered_policy_e;
265*a28cd43dSSascha Wildner 
266*a28cd43dSSascha Wildner struct ZSTD_CCtx_s {
267*a28cd43dSSascha Wildner     ZSTD_compressionStage_e stage;
268*a28cd43dSSascha Wildner     int cParamsChanged;                  /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
269*a28cd43dSSascha Wildner     int bmi2;                            /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
270*a28cd43dSSascha Wildner     ZSTD_CCtx_params requestedParams;
271*a28cd43dSSascha Wildner     ZSTD_CCtx_params appliedParams;
272*a28cd43dSSascha Wildner     U32   dictID;
273*a28cd43dSSascha Wildner 
274*a28cd43dSSascha Wildner     ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
275*a28cd43dSSascha Wildner     size_t blockSize;
276*a28cd43dSSascha Wildner     unsigned long long pledgedSrcSizePlusOne;  /* this way, 0 (default) == unknown */
277*a28cd43dSSascha Wildner     unsigned long long consumedSrcSize;
278*a28cd43dSSascha Wildner     unsigned long long producedCSize;
279*a28cd43dSSascha Wildner     XXH64_state_t xxhState;
280*a28cd43dSSascha Wildner     ZSTD_customMem customMem;
281*a28cd43dSSascha Wildner     ZSTD_threadPool* pool;
282*a28cd43dSSascha Wildner     size_t staticSize;
283*a28cd43dSSascha Wildner     SeqCollector seqCollector;
284*a28cd43dSSascha Wildner     int isFirstBlock;
285*a28cd43dSSascha Wildner     int initialized;
286*a28cd43dSSascha Wildner 
287*a28cd43dSSascha Wildner     seqStore_t seqStore;      /* sequences storage ptrs */
288*a28cd43dSSascha Wildner     ldmState_t ldmState;      /* long distance matching state */
289*a28cd43dSSascha Wildner     rawSeq* ldmSequences;     /* Storage for the ldm output sequences */
290*a28cd43dSSascha Wildner     size_t maxNbLdmSequences;
291*a28cd43dSSascha Wildner     rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
292*a28cd43dSSascha Wildner     ZSTD_blockState_t blockState;
293*a28cd43dSSascha Wildner     U32* entropyWorkspace;  /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
294*a28cd43dSSascha Wildner 
295*a28cd43dSSascha Wildner     /* Wether we are streaming or not */
296*a28cd43dSSascha Wildner     ZSTD_buffered_policy_e bufferedPolicy;
297*a28cd43dSSascha Wildner 
298*a28cd43dSSascha Wildner     /* streaming */
299*a28cd43dSSascha Wildner     char*  inBuff;
300*a28cd43dSSascha Wildner     size_t inBuffSize;
301*a28cd43dSSascha Wildner     size_t inToCompress;
302*a28cd43dSSascha Wildner     size_t inBuffPos;
303*a28cd43dSSascha Wildner     size_t inBuffTarget;
304*a28cd43dSSascha Wildner     char*  outBuff;
305*a28cd43dSSascha Wildner     size_t outBuffSize;
306*a28cd43dSSascha Wildner     size_t outBuffContentSize;
307*a28cd43dSSascha Wildner     size_t outBuffFlushedSize;
308*a28cd43dSSascha Wildner     ZSTD_cStreamStage streamStage;
309*a28cd43dSSascha Wildner     U32    frameEnded;
310*a28cd43dSSascha Wildner 
311*a28cd43dSSascha Wildner     /* Stable in/out buffer verification */
312*a28cd43dSSascha Wildner     ZSTD_inBuffer expectedInBuffer;
313*a28cd43dSSascha Wildner     size_t expectedOutBufferSize;
314*a28cd43dSSascha Wildner 
315*a28cd43dSSascha Wildner     /* Dictionary */
316*a28cd43dSSascha Wildner     ZSTD_localDict localDict;
317*a28cd43dSSascha Wildner     const ZSTD_CDict* cdict;
318*a28cd43dSSascha Wildner     ZSTD_prefixDict prefixDict;   /* single-usage dictionary */
319*a28cd43dSSascha Wildner 
320*a28cd43dSSascha Wildner     /* Multi-threading */
321*a28cd43dSSascha Wildner #ifdef ZSTD_MULTITHREAD
322*a28cd43dSSascha Wildner     ZSTDMT_CCtx* mtctx;
323*a28cd43dSSascha Wildner #endif
324*a28cd43dSSascha Wildner };
325*a28cd43dSSascha Wildner 
326*a28cd43dSSascha Wildner typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
327*a28cd43dSSascha Wildner 
328*a28cd43dSSascha Wildner typedef enum {
329*a28cd43dSSascha Wildner     ZSTD_noDict = 0,
330*a28cd43dSSascha Wildner     ZSTD_extDict = 1,
331*a28cd43dSSascha Wildner     ZSTD_dictMatchState = 2,
332*a28cd43dSSascha Wildner     ZSTD_dedicatedDictSearch = 3
333*a28cd43dSSascha Wildner } ZSTD_dictMode_e;
334*a28cd43dSSascha Wildner 
335*a28cd43dSSascha Wildner typedef enum {
336*a28cd43dSSascha Wildner     ZSTD_cpm_noAttachDict = 0,  /* Compression with ZSTD_noDict or ZSTD_extDict.
337*a28cd43dSSascha Wildner                                  * In this mode we use both the srcSize and the dictSize
338*a28cd43dSSascha Wildner                                  * when selecting and adjusting parameters.
339*a28cd43dSSascha Wildner                                  */
340*a28cd43dSSascha Wildner     ZSTD_cpm_attachDict = 1,    /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.
341*a28cd43dSSascha Wildner                                  * In this mode we only take the srcSize into account when selecting
342*a28cd43dSSascha Wildner                                  * and adjusting parameters.
343*a28cd43dSSascha Wildner                                  */
344*a28cd43dSSascha Wildner     ZSTD_cpm_createCDict = 2,   /* Creating a CDict.
345*a28cd43dSSascha Wildner                                  * In this mode we take both the source size and the dictionary size
346*a28cd43dSSascha Wildner                                  * into account when selecting and adjusting the parameters.
347*a28cd43dSSascha Wildner                                  */
348*a28cd43dSSascha Wildner     ZSTD_cpm_unknown = 3,       /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
349*a28cd43dSSascha Wildner                                  * We don't know what these parameters are for. We default to the legacy
350*a28cd43dSSascha Wildner                                  * behavior of taking both the source size and the dict size into account
351*a28cd43dSSascha Wildner                                  * when selecting and adjusting parameters.
352*a28cd43dSSascha Wildner                                  */
353*a28cd43dSSascha Wildner } ZSTD_cParamMode_e;
354*a28cd43dSSascha Wildner 
355*a28cd43dSSascha Wildner typedef size_t (*ZSTD_blockCompressor) (
356*a28cd43dSSascha Wildner         ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
357*a28cd43dSSascha Wildner         void const* src, size_t srcSize);
358*a28cd43dSSascha Wildner ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
359*a28cd43dSSascha Wildner 
360*a28cd43dSSascha Wildner 
ZSTD_LLcode(U32 litLength)361*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
362*a28cd43dSSascha Wildner {
363*a28cd43dSSascha Wildner     static const BYTE LL_Code[64] = {  0,  1,  2,  3,  4,  5,  6,  7,
364*a28cd43dSSascha Wildner                                        8,  9, 10, 11, 12, 13, 14, 15,
365*a28cd43dSSascha Wildner                                       16, 16, 17, 17, 18, 18, 19, 19,
366*a28cd43dSSascha Wildner                                       20, 20, 20, 20, 21, 21, 21, 21,
367*a28cd43dSSascha Wildner                                       22, 22, 22, 22, 22, 22, 22, 22,
368*a28cd43dSSascha Wildner                                       23, 23, 23, 23, 23, 23, 23, 23,
369*a28cd43dSSascha Wildner                                       24, 24, 24, 24, 24, 24, 24, 24,
370*a28cd43dSSascha Wildner                                       24, 24, 24, 24, 24, 24, 24, 24 };
371*a28cd43dSSascha Wildner     static const U32 LL_deltaCode = 19;
372*a28cd43dSSascha Wildner     return (litLength > 63) ? ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
373*a28cd43dSSascha Wildner }
374*a28cd43dSSascha Wildner 
375*a28cd43dSSascha Wildner /* ZSTD_MLcode() :
376*a28cd43dSSascha Wildner  * note : mlBase = matchLength - MINMATCH;
377*a28cd43dSSascha Wildner  *        because it's the format it's stored in seqStore->sequences */
ZSTD_MLcode(U32 mlBase)378*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
379*a28cd43dSSascha Wildner {
380*a28cd43dSSascha Wildner     static const BYTE ML_Code[128] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
381*a28cd43dSSascha Wildner                                       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
382*a28cd43dSSascha Wildner                                       32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
383*a28cd43dSSascha Wildner                                       38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
384*a28cd43dSSascha Wildner                                       40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
385*a28cd43dSSascha Wildner                                       41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
386*a28cd43dSSascha Wildner                                       42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
387*a28cd43dSSascha Wildner                                       42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
388*a28cd43dSSascha Wildner     static const U32 ML_deltaCode = 36;
389*a28cd43dSSascha Wildner     return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
390*a28cd43dSSascha Wildner }
391*a28cd43dSSascha Wildner 
392*a28cd43dSSascha Wildner typedef struct repcodes_s {
393*a28cd43dSSascha Wildner     U32 rep[3];
394*a28cd43dSSascha Wildner } repcodes_t;
395*a28cd43dSSascha Wildner 
ZSTD_updateRep(U32 const rep[3],U32 const offset,U32 const ll0)396*a28cd43dSSascha Wildner MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
397*a28cd43dSSascha Wildner {
398*a28cd43dSSascha Wildner     repcodes_t newReps;
399*a28cd43dSSascha Wildner     if (offset >= ZSTD_REP_NUM) {  /* full offset */
400*a28cd43dSSascha Wildner         newReps.rep[2] = rep[1];
401*a28cd43dSSascha Wildner         newReps.rep[1] = rep[0];
402*a28cd43dSSascha Wildner         newReps.rep[0] = offset - ZSTD_REP_MOVE;
403*a28cd43dSSascha Wildner     } else {   /* repcode */
404*a28cd43dSSascha Wildner         U32 const repCode = offset + ll0;
405*a28cd43dSSascha Wildner         if (repCode > 0) {  /* note : if repCode==0, no change */
406*a28cd43dSSascha Wildner             U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
407*a28cd43dSSascha Wildner             newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
408*a28cd43dSSascha Wildner             newReps.rep[1] = rep[0];
409*a28cd43dSSascha Wildner             newReps.rep[0] = currentOffset;
410*a28cd43dSSascha Wildner         } else {   /* repCode == 0 */
411*a28cd43dSSascha Wildner             ZSTD_memcpy(&newReps, rep, sizeof(newReps));
412*a28cd43dSSascha Wildner         }
413*a28cd43dSSascha Wildner     }
414*a28cd43dSSascha Wildner     return newReps;
415*a28cd43dSSascha Wildner }
416*a28cd43dSSascha Wildner 
417*a28cd43dSSascha Wildner /* ZSTD_cParam_withinBounds:
418*a28cd43dSSascha Wildner  * @return 1 if value is within cParam bounds,
419*a28cd43dSSascha Wildner  * 0 otherwise */
ZSTD_cParam_withinBounds(ZSTD_cParameter cParam,int value)420*a28cd43dSSascha Wildner MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
421*a28cd43dSSascha Wildner {
422*a28cd43dSSascha Wildner     ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
423*a28cd43dSSascha Wildner     if (ZSTD_isError(bounds.error)) return 0;
424*a28cd43dSSascha Wildner     if (value < bounds.lowerBound) return 0;
425*a28cd43dSSascha Wildner     if (value > bounds.upperBound) return 0;
426*a28cd43dSSascha Wildner     return 1;
427*a28cd43dSSascha Wildner }
428*a28cd43dSSascha Wildner 
429*a28cd43dSSascha Wildner /* ZSTD_noCompressBlock() :
430*a28cd43dSSascha Wildner  * Writes uncompressed block to dst buffer from given src.
431*a28cd43dSSascha Wildner  * Returns the size of the block */
ZSTD_noCompressBlock(void * dst,size_t dstCapacity,const void * src,size_t srcSize,U32 lastBlock)432*a28cd43dSSascha Wildner MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
433*a28cd43dSSascha Wildner {
434*a28cd43dSSascha Wildner     U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
435*a28cd43dSSascha Wildner     RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
436*a28cd43dSSascha Wildner                     dstSize_tooSmall, "dst buf too small for uncompressed block");
437*a28cd43dSSascha Wildner     MEM_writeLE24(dst, cBlockHeader24);
438*a28cd43dSSascha Wildner     ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
439*a28cd43dSSascha Wildner     return ZSTD_blockHeaderSize + srcSize;
440*a28cd43dSSascha Wildner }
441*a28cd43dSSascha Wildner 
ZSTD_rleCompressBlock(void * dst,size_t dstCapacity,BYTE src,size_t srcSize,U32 lastBlock)442*a28cd43dSSascha Wildner MEM_STATIC size_t ZSTD_rleCompressBlock (void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)
443*a28cd43dSSascha Wildner {
444*a28cd43dSSascha Wildner     BYTE* const op = (BYTE*)dst;
445*a28cd43dSSascha Wildner     U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);
446*a28cd43dSSascha Wildner     RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, "");
447*a28cd43dSSascha Wildner     MEM_writeLE24(op, cBlockHeader);
448*a28cd43dSSascha Wildner     op[3] = src;
449*a28cd43dSSascha Wildner     return 4;
450*a28cd43dSSascha Wildner }
451*a28cd43dSSascha Wildner 
452*a28cd43dSSascha Wildner 
453*a28cd43dSSascha Wildner /* ZSTD_minGain() :
454*a28cd43dSSascha Wildner  * minimum compression required
455*a28cd43dSSascha Wildner  * to generate a compress block or a compressed literals section.
456*a28cd43dSSascha Wildner  * note : use same formula for both situations */
ZSTD_minGain(size_t srcSize,ZSTD_strategy strat)457*a28cd43dSSascha Wildner MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
458*a28cd43dSSascha Wildner {
459*a28cd43dSSascha Wildner     U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
460*a28cd43dSSascha Wildner     ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
461*a28cd43dSSascha Wildner     assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
462*a28cd43dSSascha Wildner     return (srcSize >> minlog) + 2;
463*a28cd43dSSascha Wildner }
464*a28cd43dSSascha Wildner 
ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params * cctxParams)465*a28cd43dSSascha Wildner MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
466*a28cd43dSSascha Wildner {
467*a28cd43dSSascha Wildner     switch (cctxParams->literalCompressionMode) {
468*a28cd43dSSascha Wildner     case ZSTD_lcm_huffman:
469*a28cd43dSSascha Wildner         return 0;
470*a28cd43dSSascha Wildner     case ZSTD_lcm_uncompressed:
471*a28cd43dSSascha Wildner         return 1;
472*a28cd43dSSascha Wildner     default:
473*a28cd43dSSascha Wildner         assert(0 /* impossible: pre-validated */);
474*a28cd43dSSascha Wildner         /* fall-through */
475*a28cd43dSSascha Wildner     case ZSTD_lcm_auto:
476*a28cd43dSSascha Wildner         return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
477*a28cd43dSSascha Wildner     }
478*a28cd43dSSascha Wildner }
479*a28cd43dSSascha Wildner 
480*a28cd43dSSascha Wildner /*! ZSTD_safecopyLiterals() :
481*a28cd43dSSascha Wildner  *  memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w.
482*a28cd43dSSascha Wildner  *  Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
483*a28cd43dSSascha Wildner  *  large copies.
484*a28cd43dSSascha Wildner  */
ZSTD_safecopyLiterals(BYTE * op,BYTE const * ip,BYTE const * const iend,BYTE const * ilimit_w)485*a28cd43dSSascha Wildner static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) {
486*a28cd43dSSascha Wildner     assert(iend > ilimit_w);
487*a28cd43dSSascha Wildner     if (ip <= ilimit_w) {
488*a28cd43dSSascha Wildner         ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
489*a28cd43dSSascha Wildner         op += ilimit_w - ip;
490*a28cd43dSSascha Wildner         ip = ilimit_w;
491*a28cd43dSSascha Wildner     }
492*a28cd43dSSascha Wildner     while (ip < iend) *op++ = *ip++;
493*a28cd43dSSascha Wildner }
494*a28cd43dSSascha Wildner 
495*a28cd43dSSascha Wildner /*! ZSTD_storeSeq() :
496*a28cd43dSSascha Wildner  *  Store a sequence (litlen, litPtr, offCode and mlBase) into seqStore_t.
497*a28cd43dSSascha Wildner  *  `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes).
498*a28cd43dSSascha Wildner  *  `mlBase` : matchLength - MINMATCH
499*a28cd43dSSascha Wildner  *  Allowed to overread literals up to litLimit.
500*a28cd43dSSascha Wildner */
501*a28cd43dSSascha Wildner HINT_INLINE UNUSED_ATTR
ZSTD_storeSeq(seqStore_t * seqStorePtr,size_t litLength,const BYTE * literals,const BYTE * litLimit,U32 offCode,size_t mlBase)502*a28cd43dSSascha Wildner void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t mlBase)
503*a28cd43dSSascha Wildner {
504*a28cd43dSSascha Wildner     BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
505*a28cd43dSSascha Wildner     BYTE const* const litEnd = literals + litLength;
506*a28cd43dSSascha Wildner #if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
507*a28cd43dSSascha Wildner     static const BYTE* g_start = NULL;
508*a28cd43dSSascha Wildner     if (g_start==NULL) g_start = (const BYTE*)literals;  /* note : index only works for compression within a single segment */
509*a28cd43dSSascha Wildner     {   U32 const pos = (U32)((const BYTE*)literals - g_start);
510*a28cd43dSSascha Wildner         DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
511*a28cd43dSSascha Wildner                pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offCode);
512*a28cd43dSSascha Wildner     }
513*a28cd43dSSascha Wildner #endif
514*a28cd43dSSascha Wildner     assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
515*a28cd43dSSascha Wildner     /* copy Literals */
516*a28cd43dSSascha Wildner     assert(seqStorePtr->maxNbLit <= 128 KB);
517*a28cd43dSSascha Wildner     assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
518*a28cd43dSSascha Wildner     assert(literals + litLength <= litLimit);
519*a28cd43dSSascha Wildner     if (litEnd <= litLimit_w) {
520*a28cd43dSSascha Wildner         /* Common case we can use wildcopy.
521*a28cd43dSSascha Wildner 	 * First copy 16 bytes, because literals are likely short.
522*a28cd43dSSascha Wildner 	 */
523*a28cd43dSSascha Wildner         assert(WILDCOPY_OVERLENGTH >= 16);
524*a28cd43dSSascha Wildner         ZSTD_copy16(seqStorePtr->lit, literals);
525*a28cd43dSSascha Wildner         if (litLength > 16) {
526*a28cd43dSSascha Wildner             ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);
527*a28cd43dSSascha Wildner         }
528*a28cd43dSSascha Wildner     } else {
529*a28cd43dSSascha Wildner         ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);
530*a28cd43dSSascha Wildner     }
531*a28cd43dSSascha Wildner     seqStorePtr->lit += litLength;
532*a28cd43dSSascha Wildner 
533*a28cd43dSSascha Wildner     /* literal Length */
534*a28cd43dSSascha Wildner     if (litLength>0xFFFF) {
535*a28cd43dSSascha Wildner         assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
536*a28cd43dSSascha Wildner         seqStorePtr->longLengthID = 1;
537*a28cd43dSSascha Wildner         seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
538*a28cd43dSSascha Wildner     }
539*a28cd43dSSascha Wildner     seqStorePtr->sequences[0].litLength = (U16)litLength;
540*a28cd43dSSascha Wildner 
541*a28cd43dSSascha Wildner     /* match offset */
542*a28cd43dSSascha Wildner     seqStorePtr->sequences[0].offset = offCode + 1;
543*a28cd43dSSascha Wildner 
544*a28cd43dSSascha Wildner     /* match Length */
545*a28cd43dSSascha Wildner     if (mlBase>0xFFFF) {
546*a28cd43dSSascha Wildner         assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
547*a28cd43dSSascha Wildner         seqStorePtr->longLengthID = 2;
548*a28cd43dSSascha Wildner         seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
549*a28cd43dSSascha Wildner     }
550*a28cd43dSSascha Wildner     seqStorePtr->sequences[0].matchLength = (U16)mlBase;
551*a28cd43dSSascha Wildner 
552*a28cd43dSSascha Wildner     seqStorePtr->sequences++;
553*a28cd43dSSascha Wildner }
554*a28cd43dSSascha Wildner 
555*a28cd43dSSascha Wildner 
556*a28cd43dSSascha Wildner /*-*************************************
557*a28cd43dSSascha Wildner *  Match length counter
558*a28cd43dSSascha Wildner ***************************************/
ZSTD_NbCommonBytes(size_t val)559*a28cd43dSSascha Wildner static unsigned ZSTD_NbCommonBytes (size_t val)
560*a28cd43dSSascha Wildner {
561*a28cd43dSSascha Wildner     if (MEM_isLittleEndian()) {
562*a28cd43dSSascha Wildner         if (MEM_64bits()) {
563*a28cd43dSSascha Wildner #       if defined(_MSC_VER) && defined(_WIN64)
564*a28cd43dSSascha Wildner #           if STATIC_BMI2
565*a28cd43dSSascha Wildner                 return _tzcnt_u64(val) >> 3;
566*a28cd43dSSascha Wildner #           else
567*a28cd43dSSascha Wildner                 unsigned long r = 0;
568*a28cd43dSSascha Wildner                 return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
569*a28cd43dSSascha Wildner #           endif
570*a28cd43dSSascha Wildner #       elif defined(__GNUC__) && (__GNUC__ >= 4)
571*a28cd43dSSascha Wildner             return (__builtin_ctzll((U64)val) >> 3);
572*a28cd43dSSascha Wildner #       else
573*a28cd43dSSascha Wildner             static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
574*a28cd43dSSascha Wildner                                                      0, 3, 1, 3, 1, 4, 2, 7,
575*a28cd43dSSascha Wildner                                                      0, 2, 3, 6, 1, 5, 3, 5,
576*a28cd43dSSascha Wildner                                                      1, 3, 4, 4, 2, 5, 6, 7,
577*a28cd43dSSascha Wildner                                                      7, 0, 1, 2, 3, 3, 4, 6,
578*a28cd43dSSascha Wildner                                                      2, 6, 5, 5, 3, 4, 5, 6,
579*a28cd43dSSascha Wildner                                                      7, 1, 2, 4, 6, 4, 4, 5,
580*a28cd43dSSascha Wildner                                                      7, 2, 6, 5, 7, 6, 7, 7 };
581*a28cd43dSSascha Wildner             return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
582*a28cd43dSSascha Wildner #       endif
583*a28cd43dSSascha Wildner         } else { /* 32 bits */
584*a28cd43dSSascha Wildner #       if defined(_MSC_VER)
585*a28cd43dSSascha Wildner             unsigned long r=0;
586*a28cd43dSSascha Wildner             return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
587*a28cd43dSSascha Wildner #       elif defined(__GNUC__) && (__GNUC__ >= 3)
588*a28cd43dSSascha Wildner             return (__builtin_ctz((U32)val) >> 3);
589*a28cd43dSSascha Wildner #       else
590*a28cd43dSSascha Wildner             static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
591*a28cd43dSSascha Wildner                                                      3, 2, 2, 1, 3, 2, 0, 1,
592*a28cd43dSSascha Wildner                                                      3, 3, 1, 2, 2, 2, 2, 0,
593*a28cd43dSSascha Wildner                                                      3, 1, 2, 0, 1, 0, 1, 1 };
594*a28cd43dSSascha Wildner             return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
595*a28cd43dSSascha Wildner #       endif
596*a28cd43dSSascha Wildner         }
597*a28cd43dSSascha Wildner     } else {  /* Big Endian CPU */
598*a28cd43dSSascha Wildner         if (MEM_64bits()) {
599*a28cd43dSSascha Wildner #       if defined(_MSC_VER) && defined(_WIN64)
600*a28cd43dSSascha Wildner #           if STATIC_BMI2
601*a28cd43dSSascha Wildner 			    return _lzcnt_u64(val) >> 3;
602*a28cd43dSSascha Wildner #           else
603*a28cd43dSSascha Wildner 			    unsigned long r = 0;
604*a28cd43dSSascha Wildner 			    return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
605*a28cd43dSSascha Wildner #           endif
606*a28cd43dSSascha Wildner #       elif defined(__GNUC__) && (__GNUC__ >= 4)
607*a28cd43dSSascha Wildner             return (__builtin_clzll(val) >> 3);
608*a28cd43dSSascha Wildner #       else
609*a28cd43dSSascha Wildner             unsigned r;
610*a28cd43dSSascha Wildner             const unsigned n32 = sizeof(size_t)*4;   /* calculate this way due to compiler complaining in 32-bits mode */
611*a28cd43dSSascha Wildner             if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
612*a28cd43dSSascha Wildner             if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
613*a28cd43dSSascha Wildner             r += (!val);
614*a28cd43dSSascha Wildner             return r;
615*a28cd43dSSascha Wildner #       endif
616*a28cd43dSSascha Wildner         } else { /* 32 bits */
617*a28cd43dSSascha Wildner #       if defined(_MSC_VER)
618*a28cd43dSSascha Wildner             unsigned long r = 0;
619*a28cd43dSSascha Wildner             return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0;
620*a28cd43dSSascha Wildner #       elif defined(__GNUC__) && (__GNUC__ >= 3)
621*a28cd43dSSascha Wildner             return (__builtin_clz((U32)val) >> 3);
622*a28cd43dSSascha Wildner #       else
623*a28cd43dSSascha Wildner             unsigned r;
624*a28cd43dSSascha Wildner             if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
625*a28cd43dSSascha Wildner             r += (!val);
626*a28cd43dSSascha Wildner             return r;
627*a28cd43dSSascha Wildner #       endif
628*a28cd43dSSascha Wildner     }   }
629*a28cd43dSSascha Wildner }
630*a28cd43dSSascha Wildner 
631*a28cd43dSSascha Wildner 
ZSTD_count(const BYTE * pIn,const BYTE * pMatch,const BYTE * const pInLimit)632*a28cd43dSSascha Wildner MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
633*a28cd43dSSascha Wildner {
634*a28cd43dSSascha Wildner     const BYTE* const pStart = pIn;
635*a28cd43dSSascha Wildner     const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
636*a28cd43dSSascha Wildner 
637*a28cd43dSSascha Wildner     if (pIn < pInLoopLimit) {
638*a28cd43dSSascha Wildner         { size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
639*a28cd43dSSascha Wildner           if (diff) return ZSTD_NbCommonBytes(diff); }
640*a28cd43dSSascha Wildner         pIn+=sizeof(size_t); pMatch+=sizeof(size_t);
641*a28cd43dSSascha Wildner         while (pIn < pInLoopLimit) {
642*a28cd43dSSascha Wildner             size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
643*a28cd43dSSascha Wildner             if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
644*a28cd43dSSascha Wildner             pIn += ZSTD_NbCommonBytes(diff);
645*a28cd43dSSascha Wildner             return (size_t)(pIn - pStart);
646*a28cd43dSSascha Wildner     }   }
647*a28cd43dSSascha Wildner     if (MEM_64bits() && (pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
648*a28cd43dSSascha Wildner     if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
649*a28cd43dSSascha Wildner     if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
650*a28cd43dSSascha Wildner     return (size_t)(pIn - pStart);
651*a28cd43dSSascha Wildner }
652*a28cd43dSSascha Wildner 
653*a28cd43dSSascha Wildner /** ZSTD_count_2segments() :
654*a28cd43dSSascha Wildner  *  can count match length with `ip` & `match` in 2 different segments.
655*a28cd43dSSascha Wildner  *  convention : on reaching mEnd, match count continue starting from iStart
656*a28cd43dSSascha Wildner  */
657*a28cd43dSSascha Wildner MEM_STATIC size_t
ZSTD_count_2segments(const BYTE * ip,const BYTE * match,const BYTE * iEnd,const BYTE * mEnd,const BYTE * iStart)658*a28cd43dSSascha Wildner ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
659*a28cd43dSSascha Wildner                      const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
660*a28cd43dSSascha Wildner {
661*a28cd43dSSascha Wildner     const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
662*a28cd43dSSascha Wildner     size_t const matchLength = ZSTD_count(ip, match, vEnd);
663*a28cd43dSSascha Wildner     if (match + matchLength != mEnd) return matchLength;
664*a28cd43dSSascha Wildner     DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength);
665*a28cd43dSSascha Wildner     DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match);
666*a28cd43dSSascha Wildner     DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip);
667*a28cd43dSSascha Wildner     DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart);
668*a28cd43dSSascha Wildner     DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));
669*a28cd43dSSascha Wildner     return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
670*a28cd43dSSascha Wildner }
671*a28cd43dSSascha Wildner 
672*a28cd43dSSascha Wildner 
673*a28cd43dSSascha Wildner /*-*************************************
674*a28cd43dSSascha Wildner  *  Hashes
675*a28cd43dSSascha Wildner  ***************************************/
676*a28cd43dSSascha Wildner static const U32 prime3bytes = 506832829U;
ZSTD_hash3(U32 u,U32 h)677*a28cd43dSSascha Wildner static U32    ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes)  >> (32-h) ; }
ZSTD_hash3Ptr(const void * ptr,U32 h)678*a28cd43dSSascha Wildner MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
679*a28cd43dSSascha Wildner 
680*a28cd43dSSascha Wildner static const U32 prime4bytes = 2654435761U;
ZSTD_hash4(U32 u,U32 h)681*a28cd43dSSascha Wildner static U32    ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
ZSTD_hash4Ptr(const void * ptr,U32 h)682*a28cd43dSSascha Wildner static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
683*a28cd43dSSascha Wildner 
684*a28cd43dSSascha Wildner static const U64 prime5bytes = 889523592379ULL;
ZSTD_hash5(U64 u,U32 h)685*a28cd43dSSascha Wildner static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u  << (64-40)) * prime5bytes) >> (64-h)) ; }
ZSTD_hash5Ptr(const void * p,U32 h)686*a28cd43dSSascha Wildner static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
687*a28cd43dSSascha Wildner 
688*a28cd43dSSascha Wildner static const U64 prime6bytes = 227718039650203ULL;
ZSTD_hash6(U64 u,U32 h)689*a28cd43dSSascha Wildner static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u  << (64-48)) * prime6bytes) >> (64-h)) ; }
ZSTD_hash6Ptr(const void * p,U32 h)690*a28cd43dSSascha Wildner static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
691*a28cd43dSSascha Wildner 
692*a28cd43dSSascha Wildner static const U64 prime7bytes = 58295818150454627ULL;
ZSTD_hash7(U64 u,U32 h)693*a28cd43dSSascha Wildner static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u  << (64-56)) * prime7bytes) >> (64-h)) ; }
ZSTD_hash7Ptr(const void * p,U32 h)694*a28cd43dSSascha Wildner static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
695*a28cd43dSSascha Wildner 
696*a28cd43dSSascha Wildner static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
ZSTD_hash8(U64 u,U32 h)697*a28cd43dSSascha Wildner static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
ZSTD_hash8Ptr(const void * p,U32 h)698*a28cd43dSSascha Wildner static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
699*a28cd43dSSascha Wildner 
700*a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR
ZSTD_hashPtr(const void * p,U32 hBits,U32 mls)701*a28cd43dSSascha Wildner size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
702*a28cd43dSSascha Wildner {
703*a28cd43dSSascha Wildner     switch(mls)
704*a28cd43dSSascha Wildner     {
705*a28cd43dSSascha Wildner     default:
706*a28cd43dSSascha Wildner     case 4: return ZSTD_hash4Ptr(p, hBits);
707*a28cd43dSSascha Wildner     case 5: return ZSTD_hash5Ptr(p, hBits);
708*a28cd43dSSascha Wildner     case 6: return ZSTD_hash6Ptr(p, hBits);
709*a28cd43dSSascha Wildner     case 7: return ZSTD_hash7Ptr(p, hBits);
710*a28cd43dSSascha Wildner     case 8: return ZSTD_hash8Ptr(p, hBits);
711*a28cd43dSSascha Wildner     }
712*a28cd43dSSascha Wildner }
713*a28cd43dSSascha Wildner 
714*a28cd43dSSascha Wildner /** ZSTD_ipow() :
715*a28cd43dSSascha Wildner  * Return base^exponent.
716*a28cd43dSSascha Wildner  */
ZSTD_ipow(U64 base,U64 exponent)717*a28cd43dSSascha Wildner static U64 ZSTD_ipow(U64 base, U64 exponent)
718*a28cd43dSSascha Wildner {
719*a28cd43dSSascha Wildner     U64 power = 1;
720*a28cd43dSSascha Wildner     while (exponent) {
721*a28cd43dSSascha Wildner       if (exponent & 1) power *= base;
722*a28cd43dSSascha Wildner       exponent >>= 1;
723*a28cd43dSSascha Wildner       base *= base;
724*a28cd43dSSascha Wildner     }
725*a28cd43dSSascha Wildner     return power;
726*a28cd43dSSascha Wildner }
727*a28cd43dSSascha Wildner 
728*a28cd43dSSascha Wildner #define ZSTD_ROLL_HASH_CHAR_OFFSET 10
729*a28cd43dSSascha Wildner 
730*a28cd43dSSascha Wildner /** ZSTD_rollingHash_append() :
731*a28cd43dSSascha Wildner  * Add the buffer to the hash value.
732*a28cd43dSSascha Wildner  */
ZSTD_rollingHash_append(U64 hash,void const * buf,size_t size)733*a28cd43dSSascha Wildner static U64 ZSTD_rollingHash_append(U64 hash, void const* buf, size_t size)
734*a28cd43dSSascha Wildner {
735*a28cd43dSSascha Wildner     BYTE const* istart = (BYTE const*)buf;
736*a28cd43dSSascha Wildner     size_t pos;
737*a28cd43dSSascha Wildner     for (pos = 0; pos < size; ++pos) {
738*a28cd43dSSascha Wildner         hash *= prime8bytes;
739*a28cd43dSSascha Wildner         hash += istart[pos] + ZSTD_ROLL_HASH_CHAR_OFFSET;
740*a28cd43dSSascha Wildner     }
741*a28cd43dSSascha Wildner     return hash;
742*a28cd43dSSascha Wildner }
743*a28cd43dSSascha Wildner 
744*a28cd43dSSascha Wildner /** ZSTD_rollingHash_compute() :
745*a28cd43dSSascha Wildner  * Compute the rolling hash value of the buffer.
746*a28cd43dSSascha Wildner  */
ZSTD_rollingHash_compute(void const * buf,size_t size)747*a28cd43dSSascha Wildner MEM_STATIC U64 ZSTD_rollingHash_compute(void const* buf, size_t size)
748*a28cd43dSSascha Wildner {
749*a28cd43dSSascha Wildner     return ZSTD_rollingHash_append(0, buf, size);
750*a28cd43dSSascha Wildner }
751*a28cd43dSSascha Wildner 
752*a28cd43dSSascha Wildner /** ZSTD_rollingHash_primePower() :
753*a28cd43dSSascha Wildner  * Compute the primePower to be passed to ZSTD_rollingHash_rotate() for a hash
754*a28cd43dSSascha Wildner  * over a window of length bytes.
755*a28cd43dSSascha Wildner  */
ZSTD_rollingHash_primePower(U32 length)756*a28cd43dSSascha Wildner MEM_STATIC U64 ZSTD_rollingHash_primePower(U32 length)
757*a28cd43dSSascha Wildner {
758*a28cd43dSSascha Wildner     return ZSTD_ipow(prime8bytes, length - 1);
759*a28cd43dSSascha Wildner }
760*a28cd43dSSascha Wildner 
761*a28cd43dSSascha Wildner /** ZSTD_rollingHash_rotate() :
762*a28cd43dSSascha Wildner  * Rotate the rolling hash by one byte.
763*a28cd43dSSascha Wildner  */
ZSTD_rollingHash_rotate(U64 hash,BYTE toRemove,BYTE toAdd,U64 primePower)764*a28cd43dSSascha Wildner MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 primePower)
765*a28cd43dSSascha Wildner {
766*a28cd43dSSascha Wildner     hash -= (toRemove + ZSTD_ROLL_HASH_CHAR_OFFSET) * primePower;
767*a28cd43dSSascha Wildner     hash *= prime8bytes;
768*a28cd43dSSascha Wildner     hash += toAdd + ZSTD_ROLL_HASH_CHAR_OFFSET;
769*a28cd43dSSascha Wildner     return hash;
770*a28cd43dSSascha Wildner }
771*a28cd43dSSascha Wildner 
772*a28cd43dSSascha Wildner /*-*************************************
773*a28cd43dSSascha Wildner *  Round buffer management
774*a28cd43dSSascha Wildner ***************************************/
775*a28cd43dSSascha Wildner #if (ZSTD_WINDOWLOG_MAX_64 > 31)
776*a28cd43dSSascha Wildner # error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX"
777*a28cd43dSSascha Wildner #endif
778*a28cd43dSSascha Wildner /* Max current allowed */
779*a28cd43dSSascha Wildner #define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
780*a28cd43dSSascha Wildner /* Maximum chunk size before overflow correction needs to be called again */
781*a28cd43dSSascha Wildner #define ZSTD_CHUNKSIZE_MAX                                                     \
782*a28cd43dSSascha Wildner     ( ((U32)-1)                  /* Maximum ending current index */            \
783*a28cd43dSSascha Wildner     - ZSTD_CURRENT_MAX)          /* Maximum beginning lowLimit */
784*a28cd43dSSascha Wildner 
785*a28cd43dSSascha Wildner /**
786*a28cd43dSSascha Wildner  * ZSTD_window_clear():
787*a28cd43dSSascha Wildner  * Clears the window containing the history by simply setting it to empty.
788*a28cd43dSSascha Wildner  */
ZSTD_window_clear(ZSTD_window_t * window)789*a28cd43dSSascha Wildner MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
790*a28cd43dSSascha Wildner {
791*a28cd43dSSascha Wildner     size_t const endT = (size_t)(window->nextSrc - window->base);
792*a28cd43dSSascha Wildner     U32 const end = (U32)endT;
793*a28cd43dSSascha Wildner 
794*a28cd43dSSascha Wildner     window->lowLimit = end;
795*a28cd43dSSascha Wildner     window->dictLimit = end;
796*a28cd43dSSascha Wildner }
797*a28cd43dSSascha Wildner 
798*a28cd43dSSascha Wildner /**
799*a28cd43dSSascha Wildner  * ZSTD_window_hasExtDict():
800*a28cd43dSSascha Wildner  * Returns non-zero if the window has a non-empty extDict.
801*a28cd43dSSascha Wildner  */
ZSTD_window_hasExtDict(ZSTD_window_t const window)802*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
803*a28cd43dSSascha Wildner {
804*a28cd43dSSascha Wildner     return window.lowLimit < window.dictLimit;
805*a28cd43dSSascha Wildner }
806*a28cd43dSSascha Wildner 
807*a28cd43dSSascha Wildner /**
808*a28cd43dSSascha Wildner  * ZSTD_matchState_dictMode():
809*a28cd43dSSascha Wildner  * Inspects the provided matchState and figures out what dictMode should be
810*a28cd43dSSascha Wildner  * passed to the compressor.
811*a28cd43dSSascha Wildner  */
ZSTD_matchState_dictMode(const ZSTD_matchState_t * ms)812*a28cd43dSSascha Wildner MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
813*a28cd43dSSascha Wildner {
814*a28cd43dSSascha Wildner     return ZSTD_window_hasExtDict(ms->window) ?
815*a28cd43dSSascha Wildner         ZSTD_extDict :
816*a28cd43dSSascha Wildner         ms->dictMatchState != NULL ?
817*a28cd43dSSascha Wildner             (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :
818*a28cd43dSSascha Wildner             ZSTD_noDict;
819*a28cd43dSSascha Wildner }
820*a28cd43dSSascha Wildner 
821*a28cd43dSSascha Wildner /**
822*a28cd43dSSascha Wildner  * ZSTD_window_needOverflowCorrection():
823*a28cd43dSSascha Wildner  * Returns non-zero if the indices are getting too large and need overflow
824*a28cd43dSSascha Wildner  * protection.
825*a28cd43dSSascha Wildner  */
ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,void const * srcEnd)826*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
827*a28cd43dSSascha Wildner                                                   void const* srcEnd)
828*a28cd43dSSascha Wildner {
829*a28cd43dSSascha Wildner     U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
830*a28cd43dSSascha Wildner     return curr > ZSTD_CURRENT_MAX;
831*a28cd43dSSascha Wildner }
832*a28cd43dSSascha Wildner 
833*a28cd43dSSascha Wildner /**
834*a28cd43dSSascha Wildner  * ZSTD_window_correctOverflow():
835*a28cd43dSSascha Wildner  * Reduces the indices to protect from index overflow.
836*a28cd43dSSascha Wildner  * Returns the correction made to the indices, which must be applied to every
837*a28cd43dSSascha Wildner  * stored index.
838*a28cd43dSSascha Wildner  *
839*a28cd43dSSascha Wildner  * The least significant cycleLog bits of the indices must remain the same,
840*a28cd43dSSascha Wildner  * which may be 0. Every index up to maxDist in the past must be valid.
841*a28cd43dSSascha Wildner  * NOTE: (maxDist & cycleMask) must be zero.
842*a28cd43dSSascha Wildner  */
ZSTD_window_correctOverflow(ZSTD_window_t * window,U32 cycleLog,U32 maxDist,void const * src)843*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
844*a28cd43dSSascha Wildner                                            U32 maxDist, void const* src)
845*a28cd43dSSascha Wildner {
846*a28cd43dSSascha Wildner     /* preemptive overflow correction:
847*a28cd43dSSascha Wildner      * 1. correction is large enough:
848*a28cd43dSSascha Wildner      *    lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog
849*a28cd43dSSascha Wildner      *    1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
850*a28cd43dSSascha Wildner      *
851*a28cd43dSSascha Wildner      *    current - newCurrent
852*a28cd43dSSascha Wildner      *    > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)
853*a28cd43dSSascha Wildner      *    > (3<<29) - (1<<chainLog)
854*a28cd43dSSascha Wildner      *    > (3<<29) - (1<<30)             (NOTE: chainLog <= 30)
855*a28cd43dSSascha Wildner      *    > 1<<29
856*a28cd43dSSascha Wildner      *
857*a28cd43dSSascha Wildner      * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:
858*a28cd43dSSascha Wildner      *    After correction, current is less than (1<<chainLog + 1<<windowLog).
859*a28cd43dSSascha Wildner      *    In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.
860*a28cd43dSSascha Wildner      *    In 32-bit mode we are safe, because (chainLog <= 29), so
861*a28cd43dSSascha Wildner      *    ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.
862*a28cd43dSSascha Wildner      * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
863*a28cd43dSSascha Wildner      *    windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
864*a28cd43dSSascha Wildner      */
865*a28cd43dSSascha Wildner     U32 const cycleMask = (1U << cycleLog) - 1;
866*a28cd43dSSascha Wildner     U32 const curr = (U32)((BYTE const*)src - window->base);
867*a28cd43dSSascha Wildner     U32 const currentCycle0 = curr & cycleMask;
868*a28cd43dSSascha Wildner     /* Exclude zero so that newCurrent - maxDist >= 1. */
869*a28cd43dSSascha Wildner     U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0;
870*a28cd43dSSascha Wildner     U32 const newCurrent = currentCycle1 + maxDist;
871*a28cd43dSSascha Wildner     U32 const correction = curr - newCurrent;
872*a28cd43dSSascha Wildner     assert((maxDist & cycleMask) == 0);
873*a28cd43dSSascha Wildner     assert(curr > newCurrent);
874*a28cd43dSSascha Wildner     /* Loose bound, should be around 1<<29 (see above) */
875*a28cd43dSSascha Wildner     assert(correction > 1<<28);
876*a28cd43dSSascha Wildner 
877*a28cd43dSSascha Wildner     window->base += correction;
878*a28cd43dSSascha Wildner     window->dictBase += correction;
879*a28cd43dSSascha Wildner     if (window->lowLimit <= correction) window->lowLimit = 1;
880*a28cd43dSSascha Wildner     else window->lowLimit -= correction;
881*a28cd43dSSascha Wildner     if (window->dictLimit <= correction) window->dictLimit = 1;
882*a28cd43dSSascha Wildner     else window->dictLimit -= correction;
883*a28cd43dSSascha Wildner 
884*a28cd43dSSascha Wildner     /* Ensure we can still reference the full window. */
885*a28cd43dSSascha Wildner     assert(newCurrent >= maxDist);
886*a28cd43dSSascha Wildner     assert(newCurrent - maxDist >= 1);
887*a28cd43dSSascha Wildner     /* Ensure that lowLimit and dictLimit didn't underflow. */
888*a28cd43dSSascha Wildner     assert(window->lowLimit <= newCurrent);
889*a28cd43dSSascha Wildner     assert(window->dictLimit <= newCurrent);
890*a28cd43dSSascha Wildner 
891*a28cd43dSSascha Wildner     DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
892*a28cd43dSSascha Wildner              window->lowLimit);
893*a28cd43dSSascha Wildner     return correction;
894*a28cd43dSSascha Wildner }
895*a28cd43dSSascha Wildner 
896*a28cd43dSSascha Wildner /**
897*a28cd43dSSascha Wildner  * ZSTD_window_enforceMaxDist():
898*a28cd43dSSascha Wildner  * Updates lowLimit so that:
899*a28cd43dSSascha Wildner  *    (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
900*a28cd43dSSascha Wildner  *
901*a28cd43dSSascha Wildner  * It ensures index is valid as long as index >= lowLimit.
902*a28cd43dSSascha Wildner  * This must be called before a block compression call.
903*a28cd43dSSascha Wildner  *
904*a28cd43dSSascha Wildner  * loadedDictEnd is only defined if a dictionary is in use for current compression.
905*a28cd43dSSascha Wildner  * As the name implies, loadedDictEnd represents the index at end of dictionary.
906*a28cd43dSSascha Wildner  * The value lies within context's referential, it can be directly compared to blockEndIdx.
907*a28cd43dSSascha Wildner  *
908*a28cd43dSSascha Wildner  * If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.
909*a28cd43dSSascha Wildner  * If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.
910*a28cd43dSSascha Wildner  * This is because dictionaries are allowed to be referenced fully
911*a28cd43dSSascha Wildner  * as long as the last byte of the dictionary is in the window.
912*a28cd43dSSascha Wildner  * Once input has progressed beyond window size, dictionary cannot be referenced anymore.
913*a28cd43dSSascha Wildner  *
914*a28cd43dSSascha Wildner  * In normal dict mode, the dictionary lies between lowLimit and dictLimit.
915*a28cd43dSSascha Wildner  * In dictMatchState mode, lowLimit and dictLimit are the same,
916*a28cd43dSSascha Wildner  * and the dictionary is below them.
917*a28cd43dSSascha Wildner  * forceWindow and dictMatchState are therefore incompatible.
918*a28cd43dSSascha Wildner  */
919*a28cd43dSSascha Wildner MEM_STATIC void
ZSTD_window_enforceMaxDist(ZSTD_window_t * window,const void * blockEnd,U32 maxDist,U32 * loadedDictEndPtr,const ZSTD_matchState_t ** dictMatchStatePtr)920*a28cd43dSSascha Wildner ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
921*a28cd43dSSascha Wildner                      const void* blockEnd,
922*a28cd43dSSascha Wildner                            U32   maxDist,
923*a28cd43dSSascha Wildner                            U32*  loadedDictEndPtr,
924*a28cd43dSSascha Wildner                      const ZSTD_matchState_t** dictMatchStatePtr)
925*a28cd43dSSascha Wildner {
926*a28cd43dSSascha Wildner     U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
927*a28cd43dSSascha Wildner     U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
928*a28cd43dSSascha Wildner     DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
929*a28cd43dSSascha Wildner                 (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
930*a28cd43dSSascha Wildner 
931*a28cd43dSSascha Wildner     /* - When there is no dictionary : loadedDictEnd == 0.
932*a28cd43dSSascha Wildner          In which case, the test (blockEndIdx > maxDist) is merely to avoid
933*a28cd43dSSascha Wildner          overflowing next operation `newLowLimit = blockEndIdx - maxDist`.
934*a28cd43dSSascha Wildner        - When there is a standard dictionary :
935*a28cd43dSSascha Wildner          Index referential is copied from the dictionary,
936*a28cd43dSSascha Wildner          which means it starts from 0.
937*a28cd43dSSascha Wildner          In which case, loadedDictEnd == dictSize,
938*a28cd43dSSascha Wildner          and it makes sense to compare `blockEndIdx > maxDist + dictSize`
939*a28cd43dSSascha Wildner          since `blockEndIdx` also starts from zero.
940*a28cd43dSSascha Wildner        - When there is an attached dictionary :
941*a28cd43dSSascha Wildner          loadedDictEnd is expressed within the referential of the context,
942*a28cd43dSSascha Wildner          so it can be directly compared against blockEndIdx.
943*a28cd43dSSascha Wildner     */
944*a28cd43dSSascha Wildner     if (blockEndIdx > maxDist + loadedDictEnd) {
945*a28cd43dSSascha Wildner         U32 const newLowLimit = blockEndIdx - maxDist;
946*a28cd43dSSascha Wildner         if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
947*a28cd43dSSascha Wildner         if (window->dictLimit < window->lowLimit) {
948*a28cd43dSSascha Wildner             DEBUGLOG(5, "Update dictLimit to match lowLimit, from %u to %u",
949*a28cd43dSSascha Wildner                         (unsigned)window->dictLimit, (unsigned)window->lowLimit);
950*a28cd43dSSascha Wildner             window->dictLimit = window->lowLimit;
951*a28cd43dSSascha Wildner         }
952*a28cd43dSSascha Wildner         /* On reaching window size, dictionaries are invalidated */
953*a28cd43dSSascha Wildner         if (loadedDictEndPtr) *loadedDictEndPtr = 0;
954*a28cd43dSSascha Wildner         if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
955*a28cd43dSSascha Wildner     }
956*a28cd43dSSascha Wildner }
957*a28cd43dSSascha Wildner 
958*a28cd43dSSascha Wildner /* Similar to ZSTD_window_enforceMaxDist(),
959*a28cd43dSSascha Wildner  * but only invalidates dictionary
960*a28cd43dSSascha Wildner  * when input progresses beyond window size.
961*a28cd43dSSascha Wildner  * assumption : loadedDictEndPtr and dictMatchStatePtr are valid (non NULL)
962*a28cd43dSSascha Wildner  *              loadedDictEnd uses same referential as window->base
963*a28cd43dSSascha Wildner  *              maxDist is the window size */
964*a28cd43dSSascha Wildner MEM_STATIC void
ZSTD_checkDictValidity(const ZSTD_window_t * window,const void * blockEnd,U32 maxDist,U32 * loadedDictEndPtr,const ZSTD_matchState_t ** dictMatchStatePtr)965*a28cd43dSSascha Wildner ZSTD_checkDictValidity(const ZSTD_window_t* window,
966*a28cd43dSSascha Wildner                        const void* blockEnd,
967*a28cd43dSSascha Wildner                              U32   maxDist,
968*a28cd43dSSascha Wildner                              U32*  loadedDictEndPtr,
969*a28cd43dSSascha Wildner                        const ZSTD_matchState_t** dictMatchStatePtr)
970*a28cd43dSSascha Wildner {
971*a28cd43dSSascha Wildner     assert(loadedDictEndPtr != NULL);
972*a28cd43dSSascha Wildner     assert(dictMatchStatePtr != NULL);
973*a28cd43dSSascha Wildner     {   U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
974*a28cd43dSSascha Wildner         U32 const loadedDictEnd = *loadedDictEndPtr;
975*a28cd43dSSascha Wildner         DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
976*a28cd43dSSascha Wildner                     (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
977*a28cd43dSSascha Wildner         assert(blockEndIdx >= loadedDictEnd);
978*a28cd43dSSascha Wildner 
979*a28cd43dSSascha Wildner         if (blockEndIdx > loadedDictEnd + maxDist) {
980*a28cd43dSSascha Wildner             /* On reaching window size, dictionaries are invalidated.
981*a28cd43dSSascha Wildner              * For simplification, if window size is reached anywhere within next block,
982*a28cd43dSSascha Wildner              * the dictionary is invalidated for the full block.
983*a28cd43dSSascha Wildner              */
984*a28cd43dSSascha Wildner             DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)");
985*a28cd43dSSascha Wildner             *loadedDictEndPtr = 0;
986*a28cd43dSSascha Wildner             *dictMatchStatePtr = NULL;
987*a28cd43dSSascha Wildner         } else {
988*a28cd43dSSascha Wildner             if (*loadedDictEndPtr != 0) {
989*a28cd43dSSascha Wildner                 DEBUGLOG(6, "dictionary considered valid for current block");
990*a28cd43dSSascha Wildner     }   }   }
991*a28cd43dSSascha Wildner }
992*a28cd43dSSascha Wildner 
ZSTD_window_init(ZSTD_window_t * window)993*a28cd43dSSascha Wildner MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
994*a28cd43dSSascha Wildner     ZSTD_memset(window, 0, sizeof(*window));
995*a28cd43dSSascha Wildner     window->base = (BYTE const*)"";
996*a28cd43dSSascha Wildner     window->dictBase = (BYTE const*)"";
997*a28cd43dSSascha Wildner     window->dictLimit = 1;    /* start from 1, so that 1st position is valid */
998*a28cd43dSSascha Wildner     window->lowLimit = 1;     /* it ensures first and later CCtx usages compress the same */
999*a28cd43dSSascha Wildner     window->nextSrc = window->base + 1;   /* see issue #1241 */
1000*a28cd43dSSascha Wildner }
1001*a28cd43dSSascha Wildner 
1002*a28cd43dSSascha Wildner /**
1003*a28cd43dSSascha Wildner  * ZSTD_window_update():
1004*a28cd43dSSascha Wildner  * Updates the window by appending [src, src + srcSize) to the window.
1005*a28cd43dSSascha Wildner  * If it is not contiguous, the current prefix becomes the extDict, and we
1006*a28cd43dSSascha Wildner  * forget about the extDict. Handles overlap of the prefix and extDict.
1007*a28cd43dSSascha Wildner  * Returns non-zero if the segment is contiguous.
1008*a28cd43dSSascha Wildner  */
ZSTD_window_update(ZSTD_window_t * window,void const * src,size_t srcSize)1009*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
1010*a28cd43dSSascha Wildner                                   void const* src, size_t srcSize)
1011*a28cd43dSSascha Wildner {
1012*a28cd43dSSascha Wildner     BYTE const* const ip = (BYTE const*)src;
1013*a28cd43dSSascha Wildner     U32 contiguous = 1;
1014*a28cd43dSSascha Wildner     DEBUGLOG(5, "ZSTD_window_update");
1015*a28cd43dSSascha Wildner     if (srcSize == 0)
1016*a28cd43dSSascha Wildner         return contiguous;
1017*a28cd43dSSascha Wildner     assert(window->base != NULL);
1018*a28cd43dSSascha Wildner     assert(window->dictBase != NULL);
1019*a28cd43dSSascha Wildner     /* Check if blocks follow each other */
1020*a28cd43dSSascha Wildner     if (src != window->nextSrc) {
1021*a28cd43dSSascha Wildner         /* not contiguous */
1022*a28cd43dSSascha Wildner         size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
1023*a28cd43dSSascha Wildner         DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
1024*a28cd43dSSascha Wildner         window->lowLimit = window->dictLimit;
1025*a28cd43dSSascha Wildner         assert(distanceFromBase == (size_t)(U32)distanceFromBase);  /* should never overflow */
1026*a28cd43dSSascha Wildner         window->dictLimit = (U32)distanceFromBase;
1027*a28cd43dSSascha Wildner         window->dictBase = window->base;
1028*a28cd43dSSascha Wildner         window->base = ip - distanceFromBase;
1029*a28cd43dSSascha Wildner         /* ms->nextToUpdate = window->dictLimit; */
1030*a28cd43dSSascha Wildner         if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit;   /* too small extDict */
1031*a28cd43dSSascha Wildner         contiguous = 0;
1032*a28cd43dSSascha Wildner     }
1033*a28cd43dSSascha Wildner     window->nextSrc = ip + srcSize;
1034*a28cd43dSSascha Wildner     /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
1035*a28cd43dSSascha Wildner     if ( (ip+srcSize > window->dictBase + window->lowLimit)
1036*a28cd43dSSascha Wildner        & (ip < window->dictBase + window->dictLimit)) {
1037*a28cd43dSSascha Wildner         ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
1038*a28cd43dSSascha Wildner         U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
1039*a28cd43dSSascha Wildner         window->lowLimit = lowLimitMax;
1040*a28cd43dSSascha Wildner         DEBUGLOG(5, "Overlapping extDict and input : new lowLimit = %u", window->lowLimit);
1041*a28cd43dSSascha Wildner     }
1042*a28cd43dSSascha Wildner     return contiguous;
1043*a28cd43dSSascha Wildner }
1044*a28cd43dSSascha Wildner 
1045*a28cd43dSSascha Wildner /**
1046*a28cd43dSSascha Wildner  * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.
1047*a28cd43dSSascha Wildner  */
ZSTD_getLowestMatchIndex(const ZSTD_matchState_t * ms,U32 curr,unsigned windowLog)1048*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
1049*a28cd43dSSascha Wildner {
1050*a28cd43dSSascha Wildner     U32    const maxDistance = 1U << windowLog;
1051*a28cd43dSSascha Wildner     U32    const lowestValid = ms->window.lowLimit;
1052*a28cd43dSSascha Wildner     U32    const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
1053*a28cd43dSSascha Wildner     U32    const isDictionary = (ms->loadedDictEnd != 0);
1054*a28cd43dSSascha Wildner     /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
1055*a28cd43dSSascha Wildner      * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
1056*a28cd43dSSascha Wildner      * valid for the entire block. So this check is sufficient to find the lowest valid match index.
1057*a28cd43dSSascha Wildner      */
1058*a28cd43dSSascha Wildner     U32    const matchLowest = isDictionary ? lowestValid : withinWindow;
1059*a28cd43dSSascha Wildner     return matchLowest;
1060*a28cd43dSSascha Wildner }
1061*a28cd43dSSascha Wildner 
1062*a28cd43dSSascha Wildner /**
1063*a28cd43dSSascha Wildner  * Returns the lowest allowed match index in the prefix.
1064*a28cd43dSSascha Wildner  */
ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t * ms,U32 curr,unsigned windowLog)1065*a28cd43dSSascha Wildner MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
1066*a28cd43dSSascha Wildner {
1067*a28cd43dSSascha Wildner     U32    const maxDistance = 1U << windowLog;
1068*a28cd43dSSascha Wildner     U32    const lowestValid = ms->window.dictLimit;
1069*a28cd43dSSascha Wildner     U32    const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
1070*a28cd43dSSascha Wildner     U32    const isDictionary = (ms->loadedDictEnd != 0);
1071*a28cd43dSSascha Wildner     /* When computing the lowest prefix index we need to take the dictionary into account to handle
1072*a28cd43dSSascha Wildner      * the edge case where the dictionary and the source are contiguous in memory.
1073*a28cd43dSSascha Wildner      */
1074*a28cd43dSSascha Wildner     U32    const matchLowest = isDictionary ? lowestValid : withinWindow;
1075*a28cd43dSSascha Wildner     return matchLowest;
1076*a28cd43dSSascha Wildner }
1077*a28cd43dSSascha Wildner 
1078*a28cd43dSSascha Wildner 
1079*a28cd43dSSascha Wildner 
1080*a28cd43dSSascha Wildner /* debug functions */
1081*a28cd43dSSascha Wildner #if (DEBUGLEVEL>=2)
1082*a28cd43dSSascha Wildner 
ZSTD_fWeight(U32 rawStat)1083*a28cd43dSSascha Wildner MEM_STATIC double ZSTD_fWeight(U32 rawStat)
1084*a28cd43dSSascha Wildner {
1085*a28cd43dSSascha Wildner     U32 const fp_accuracy = 8;
1086*a28cd43dSSascha Wildner     U32 const fp_multiplier = (1 << fp_accuracy);
1087*a28cd43dSSascha Wildner     U32 const newStat = rawStat + 1;
1088*a28cd43dSSascha Wildner     U32 const hb = ZSTD_highbit32(newStat);
1089*a28cd43dSSascha Wildner     U32 const BWeight = hb * fp_multiplier;
1090*a28cd43dSSascha Wildner     U32 const FWeight = (newStat << fp_accuracy) >> hb;
1091*a28cd43dSSascha Wildner     U32 const weight = BWeight + FWeight;
1092*a28cd43dSSascha Wildner     assert(hb + fp_accuracy < 31);
1093*a28cd43dSSascha Wildner     return (double)weight / fp_multiplier;
1094*a28cd43dSSascha Wildner }
1095*a28cd43dSSascha Wildner 
1096*a28cd43dSSascha Wildner /* display a table content,
1097*a28cd43dSSascha Wildner  * listing each element, its frequency, and its predicted bit cost */
ZSTD_debugTable(const U32 * table,U32 max)1098*a28cd43dSSascha Wildner MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
1099*a28cd43dSSascha Wildner {
1100*a28cd43dSSascha Wildner     unsigned u, sum;
1101*a28cd43dSSascha Wildner     for (u=0, sum=0; u<=max; u++) sum += table[u];
1102*a28cd43dSSascha Wildner     DEBUGLOG(2, "total nb elts: %u", sum);
1103*a28cd43dSSascha Wildner     for (u=0; u<=max; u++) {
1104*a28cd43dSSascha Wildner         DEBUGLOG(2, "%2u: %5u  (%.2f)",
1105*a28cd43dSSascha Wildner                 u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );
1106*a28cd43dSSascha Wildner     }
1107*a28cd43dSSascha Wildner }
1108*a28cd43dSSascha Wildner 
1109*a28cd43dSSascha Wildner #endif
1110*a28cd43dSSascha Wildner 
1111*a28cd43dSSascha Wildner 
1112*a28cd43dSSascha Wildner #if defined (__cplusplus)
1113*a28cd43dSSascha Wildner }
1114*a28cd43dSSascha Wildner #endif
1115*a28cd43dSSascha Wildner 
1116*a28cd43dSSascha Wildner /* ===============================================================
1117*a28cd43dSSascha Wildner  * Shared internal declarations
1118*a28cd43dSSascha Wildner  * These prototypes may be called from sources not in lib/compress
1119*a28cd43dSSascha Wildner  * =============================================================== */
1120*a28cd43dSSascha Wildner 
1121*a28cd43dSSascha Wildner /* ZSTD_loadCEntropy() :
1122*a28cd43dSSascha Wildner  * dict : must point at beginning of a valid zstd dictionary.
1123*a28cd43dSSascha Wildner  * return : size of dictionary header (size of magic number + dict ID + entropy tables)
1124*a28cd43dSSascha Wildner  * assumptions : magic number supposed already checked
1125*a28cd43dSSascha Wildner  *               and dictSize >= 8 */
1126*a28cd43dSSascha Wildner size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
1127*a28cd43dSSascha Wildner                          const void* const dict, size_t dictSize);
1128*a28cd43dSSascha Wildner 
1129*a28cd43dSSascha Wildner void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
1130*a28cd43dSSascha Wildner 
1131*a28cd43dSSascha Wildner /* ==============================================================
1132*a28cd43dSSascha Wildner  * Private declarations
1133*a28cd43dSSascha Wildner  * These prototypes shall only be called from within lib/compress
1134*a28cd43dSSascha Wildner  * ============================================================== */
1135*a28cd43dSSascha Wildner 
1136*a28cd43dSSascha Wildner /* ZSTD_getCParamsFromCCtxParams() :
1137*a28cd43dSSascha Wildner  * cParams are built depending on compressionLevel, src size hints,
1138*a28cd43dSSascha Wildner  * LDM and manually set compression parameters.
1139*a28cd43dSSascha Wildner  * Note: srcSizeHint == 0 means 0!
1140*a28cd43dSSascha Wildner  */
1141*a28cd43dSSascha Wildner ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
1142*a28cd43dSSascha Wildner         const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
1143*a28cd43dSSascha Wildner 
1144*a28cd43dSSascha Wildner /*! ZSTD_initCStream_internal() :
1145*a28cd43dSSascha Wildner  *  Private use only. Init streaming operation.
1146*a28cd43dSSascha Wildner  *  expects params to be valid.
1147*a28cd43dSSascha Wildner  *  must receive dict, or cdict, or none, but not both.
1148*a28cd43dSSascha Wildner  *  @return : 0, or an error code */
1149*a28cd43dSSascha Wildner size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
1150*a28cd43dSSascha Wildner                      const void* dict, size_t dictSize,
1151*a28cd43dSSascha Wildner                      const ZSTD_CDict* cdict,
1152*a28cd43dSSascha Wildner                      const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize);
1153*a28cd43dSSascha Wildner 
1154*a28cd43dSSascha Wildner void ZSTD_resetSeqStore(seqStore_t* ssPtr);
1155*a28cd43dSSascha Wildner 
1156*a28cd43dSSascha Wildner /*! ZSTD_getCParamsFromCDict() :
1157*a28cd43dSSascha Wildner  *  as the name implies */
1158*a28cd43dSSascha Wildner ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
1159*a28cd43dSSascha Wildner 
1160*a28cd43dSSascha Wildner /* ZSTD_compressBegin_advanced_internal() :
1161*a28cd43dSSascha Wildner  * Private use only. To be called from zstdmt_compress.c. */
1162*a28cd43dSSascha Wildner size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
1163*a28cd43dSSascha Wildner                                     const void* dict, size_t dictSize,
1164*a28cd43dSSascha Wildner                                     ZSTD_dictContentType_e dictContentType,
1165*a28cd43dSSascha Wildner                                     ZSTD_dictTableLoadMethod_e dtlm,
1166*a28cd43dSSascha Wildner                                     const ZSTD_CDict* cdict,
1167*a28cd43dSSascha Wildner                                     const ZSTD_CCtx_params* params,
1168*a28cd43dSSascha Wildner                                     unsigned long long pledgedSrcSize);
1169*a28cd43dSSascha Wildner 
1170*a28cd43dSSascha Wildner /* ZSTD_compress_advanced_internal() :
1171*a28cd43dSSascha Wildner  * Private use only. To be called from zstdmt_compress.c. */
1172*a28cd43dSSascha Wildner size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
1173*a28cd43dSSascha Wildner                                        void* dst, size_t dstCapacity,
1174*a28cd43dSSascha Wildner                                  const void* src, size_t srcSize,
1175*a28cd43dSSascha Wildner                                  const void* dict,size_t dictSize,
1176*a28cd43dSSascha Wildner                                  const ZSTD_CCtx_params* params);
1177*a28cd43dSSascha Wildner 
1178*a28cd43dSSascha Wildner 
1179*a28cd43dSSascha Wildner /* ZSTD_writeLastEmptyBlock() :
1180*a28cd43dSSascha Wildner  * output an empty Block with end-of-frame mark to complete a frame
1181*a28cd43dSSascha Wildner  * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
1182*a28cd43dSSascha Wildner  *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
1183*a28cd43dSSascha Wildner  */
1184*a28cd43dSSascha Wildner size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
1185*a28cd43dSSascha Wildner 
1186*a28cd43dSSascha Wildner 
1187*a28cd43dSSascha Wildner /* ZSTD_referenceExternalSequences() :
1188*a28cd43dSSascha Wildner  * Must be called before starting a compression operation.
1189*a28cd43dSSascha Wildner  * seqs must parse a prefix of the source.
1190*a28cd43dSSascha Wildner  * This cannot be used when long range matching is enabled.
1191*a28cd43dSSascha Wildner  * Zstd will use these sequences, and pass the literals to a secondary block
1192*a28cd43dSSascha Wildner  * compressor.
1193*a28cd43dSSascha Wildner  * @return : An error code on failure.
1194*a28cd43dSSascha Wildner  * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory
1195*a28cd43dSSascha Wildner  * access and data corruption.
1196*a28cd43dSSascha Wildner  */
1197*a28cd43dSSascha Wildner size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
1198*a28cd43dSSascha Wildner 
1199*a28cd43dSSascha Wildner /** ZSTD_cycleLog() :
1200*a28cd43dSSascha Wildner  *  condition for correct operation : hashLog > 1 */
1201*a28cd43dSSascha Wildner /* Begin FreeBSD - This symbol is needed by dll-linked CLI zstd(1). */
1202*a28cd43dSSascha Wildner ZSTDLIB_API
1203*a28cd43dSSascha Wildner /* End FreeBSD */
1204 U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
1205 
1206 #endif /* ZSTD_COMPRESS_H */
1207