xref: /freebsd-src/sys/contrib/zstd/lib/compress/zstd_compress_internal.h (revision 5ff13fbc199bdf5f0572845351c68ee5ca828e71)
1052d3c12SConrad Meyer /*
2*5ff13fbcSAllan Jude  * Copyright (c) Yann Collet, Facebook, Inc.
3052d3c12SConrad Meyer  * All rights reserved.
4052d3c12SConrad Meyer  *
5052d3c12SConrad Meyer  * This source code is licensed under both the BSD-style license (found in the
6052d3c12SConrad Meyer  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7052d3c12SConrad Meyer  * in the COPYING file in the root directory of this source tree).
8052d3c12SConrad Meyer  * You may select, at your option, one of the above-listed licenses.
9052d3c12SConrad Meyer  */
10052d3c12SConrad Meyer 
11052d3c12SConrad Meyer /* This header contains definitions
12052d3c12SConrad Meyer  * that shall **only** be used by modules within lib/compress.
13052d3c12SConrad Meyer  */
14052d3c12SConrad Meyer 
15052d3c12SConrad Meyer #ifndef ZSTD_COMPRESS_H
16052d3c12SConrad Meyer #define ZSTD_COMPRESS_H
17052d3c12SConrad Meyer 
18052d3c12SConrad Meyer /*-*************************************
19052d3c12SConrad Meyer *  Dependencies
20052d3c12SConrad Meyer ***************************************/
2137f1f268SConrad Meyer #include "../common/zstd_internal.h"
229cbefe25SConrad Meyer #include "zstd_cwksp.h"
23052d3c12SConrad Meyer #ifdef ZSTD_MULTITHREAD
24052d3c12SConrad Meyer #  include "zstdmt_compress.h"
25052d3c12SConrad Meyer #endif
26052d3c12SConrad Meyer 
27052d3c12SConrad Meyer #if defined (__cplusplus)
28052d3c12SConrad Meyer extern "C" {
29052d3c12SConrad Meyer #endif
30052d3c12SConrad Meyer 
31052d3c12SConrad Meyer /*-*************************************
32052d3c12SConrad Meyer *  Constants
33052d3c12SConrad Meyer ***************************************/
3419fcbaf1SConrad Meyer #define kSearchStrength      8
35052d3c12SConrad Meyer #define HASH_READ_SIZE       8
364d3f1eafSConrad Meyer #define ZSTD_DUBT_UNSORTED_MARK 1   /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means "unsorted".
3719fcbaf1SConrad Meyer                                        It could be confused for a real successor at index "1", if sorted as larger than its predecessor.
3819fcbaf1SConrad Meyer                                        It's not a big deal though : candidate will just be sorted again.
392b9c00cbSConrad Meyer                                        Additionally, candidate position 1 will be lost.
4019fcbaf1SConrad Meyer                                        But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.
414d3f1eafSConrad Meyer                                        The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table re-use with a different strategy.
424d3f1eafSConrad Meyer                                        This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */
43052d3c12SConrad Meyer 
44052d3c12SConrad Meyer 
45052d3c12SConrad Meyer /*-*************************************
46052d3c12SConrad Meyer *  Context memory management
47052d3c12SConrad Meyer ***************************************/
48052d3c12SConrad Meyer typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
49052d3c12SConrad Meyer typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
50052d3c12SConrad Meyer 
51052d3c12SConrad Meyer typedef struct ZSTD_prefixDict_s {
52052d3c12SConrad Meyer     const void* dict;
53052d3c12SConrad Meyer     size_t dictSize;
5419fcbaf1SConrad Meyer     ZSTD_dictContentType_e dictContentType;
55052d3c12SConrad Meyer } ZSTD_prefixDict;
56052d3c12SConrad Meyer 
57052d3c12SConrad Meyer typedef struct {
582b9c00cbSConrad Meyer     void* dictBuffer;
592b9c00cbSConrad Meyer     void const* dict;
602b9c00cbSConrad Meyer     size_t dictSize;
612b9c00cbSConrad Meyer     ZSTD_dictContentType_e dictContentType;
622b9c00cbSConrad Meyer     ZSTD_CDict* cdict;
632b9c00cbSConrad Meyer } ZSTD_localDict;
642b9c00cbSConrad Meyer 
652b9c00cbSConrad Meyer typedef struct {
66*5ff13fbcSAllan Jude     HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)];
670f743729SConrad Meyer     HUF_repeat repeatMode;
680f743729SConrad Meyer } ZSTD_hufCTables_t;
690f743729SConrad Meyer 
700f743729SConrad Meyer typedef struct {
71052d3c12SConrad Meyer     FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
72052d3c12SConrad Meyer     FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
73052d3c12SConrad Meyer     FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
74052d3c12SConrad Meyer     FSE_repeat offcode_repeatMode;
75052d3c12SConrad Meyer     FSE_repeat matchlength_repeatMode;
76052d3c12SConrad Meyer     FSE_repeat litlength_repeatMode;
770f743729SConrad Meyer } ZSTD_fseCTables_t;
780f743729SConrad Meyer 
790f743729SConrad Meyer typedef struct {
800f743729SConrad Meyer     ZSTD_hufCTables_t huf;
810f743729SConrad Meyer     ZSTD_fseCTables_t fse;
82052d3c12SConrad Meyer } ZSTD_entropyCTables_t;
83052d3c12SConrad Meyer 
84*5ff13fbcSAllan Jude /***********************************************
85*5ff13fbcSAllan Jude *  Entropy buffer statistics structs and funcs *
86*5ff13fbcSAllan Jude ***********************************************/
87*5ff13fbcSAllan Jude /** ZSTD_hufCTablesMetadata_t :
88*5ff13fbcSAllan Jude  *  Stores Literals Block Type for a super-block in hType, and
89*5ff13fbcSAllan Jude  *  huffman tree description in hufDesBuffer.
90*5ff13fbcSAllan Jude  *  hufDesSize refers to the size of huffman tree description in bytes.
91*5ff13fbcSAllan Jude  *  This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */
92052d3c12SConrad Meyer typedef struct {
93*5ff13fbcSAllan Jude     symbolEncodingType_e hType;
94*5ff13fbcSAllan Jude     BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
95*5ff13fbcSAllan Jude     size_t hufDesSize;
96*5ff13fbcSAllan Jude } ZSTD_hufCTablesMetadata_t;
97*5ff13fbcSAllan Jude 
98*5ff13fbcSAllan Jude /** ZSTD_fseCTablesMetadata_t :
99*5ff13fbcSAllan Jude  *  Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
100*5ff13fbcSAllan Jude  *  fse tables in fseTablesBuffer.
101*5ff13fbcSAllan Jude  *  fseTablesSize refers to the size of fse tables in bytes.
102*5ff13fbcSAllan Jude  *  This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */
103*5ff13fbcSAllan Jude typedef struct {
104*5ff13fbcSAllan Jude     symbolEncodingType_e llType;
105*5ff13fbcSAllan Jude     symbolEncodingType_e ofType;
106*5ff13fbcSAllan Jude     symbolEncodingType_e mlType;
107*5ff13fbcSAllan Jude     BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
108*5ff13fbcSAllan Jude     size_t fseTablesSize;
109*5ff13fbcSAllan Jude     size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
110*5ff13fbcSAllan Jude } ZSTD_fseCTablesMetadata_t;
111*5ff13fbcSAllan Jude 
112*5ff13fbcSAllan Jude typedef struct {
113*5ff13fbcSAllan Jude     ZSTD_hufCTablesMetadata_t hufMetadata;
114*5ff13fbcSAllan Jude     ZSTD_fseCTablesMetadata_t fseMetadata;
115*5ff13fbcSAllan Jude } ZSTD_entropyCTablesMetadata_t;
116*5ff13fbcSAllan Jude 
117*5ff13fbcSAllan Jude /** ZSTD_buildBlockEntropyStats() :
118*5ff13fbcSAllan Jude  *  Builds entropy for the block.
119*5ff13fbcSAllan Jude  *  @return : 0 on success or error code */
120*5ff13fbcSAllan Jude size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
121*5ff13fbcSAllan Jude                              const ZSTD_entropyCTables_t* prevEntropy,
122*5ff13fbcSAllan Jude                                    ZSTD_entropyCTables_t* nextEntropy,
123*5ff13fbcSAllan Jude                              const ZSTD_CCtx_params* cctxParams,
124*5ff13fbcSAllan Jude                                    ZSTD_entropyCTablesMetadata_t* entropyMetadata,
125*5ff13fbcSAllan Jude                                    void* workspace, size_t wkspSize);
126*5ff13fbcSAllan Jude 
127*5ff13fbcSAllan Jude /*********************************
128*5ff13fbcSAllan Jude *  Compression internals structs *
129*5ff13fbcSAllan Jude *********************************/
130*5ff13fbcSAllan Jude 
131*5ff13fbcSAllan Jude typedef struct {
132*5ff13fbcSAllan Jude     U32 off;            /* Offset sumtype code for the match, using ZSTD_storeSeq() format */
133f7cd7fe5SConrad Meyer     U32 len;            /* Raw length of match */
134052d3c12SConrad Meyer } ZSTD_match_t;
135052d3c12SConrad Meyer 
136052d3c12SConrad Meyer typedef struct {
137f7cd7fe5SConrad Meyer     U32 offset;         /* Offset of sequence */
138f7cd7fe5SConrad Meyer     U32 litLength;      /* Length of literals prior to match */
139f7cd7fe5SConrad Meyer     U32 matchLength;    /* Raw length of match */
140f7cd7fe5SConrad Meyer } rawSeq;
141f7cd7fe5SConrad Meyer 
142f7cd7fe5SConrad Meyer typedef struct {
143f7cd7fe5SConrad Meyer   rawSeq* seq;          /* The start of the sequences */
144f7cd7fe5SConrad Meyer   size_t pos;           /* The index in seq where reading stopped. pos <= size. */
145f7cd7fe5SConrad Meyer   size_t posInSequence; /* The position within the sequence at seq[pos] where reading
146f7cd7fe5SConrad Meyer                            stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */
147f7cd7fe5SConrad Meyer   size_t size;          /* The number of sequences. <= capacity. */
148f7cd7fe5SConrad Meyer   size_t capacity;      /* The capacity starting from `seq` pointer */
149f7cd7fe5SConrad Meyer } rawSeqStore_t;
150f7cd7fe5SConrad Meyer 
151f7cd7fe5SConrad Meyer UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
152f7cd7fe5SConrad Meyer 
153f7cd7fe5SConrad Meyer typedef struct {
154052d3c12SConrad Meyer     int price;
155052d3c12SConrad Meyer     U32 off;
156052d3c12SConrad Meyer     U32 mlen;
157052d3c12SConrad Meyer     U32 litlen;
158052d3c12SConrad Meyer     U32 rep[ZSTD_REP_NUM];
159052d3c12SConrad Meyer } ZSTD_optimal_t;
160052d3c12SConrad Meyer 
1610f743729SConrad Meyer typedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;
1620f743729SConrad Meyer 
163052d3c12SConrad Meyer typedef struct {
164052d3c12SConrad Meyer     /* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */
165a0483764SConrad Meyer     unsigned* litFreq;           /* table of literals statistics, of size 256 */
166a0483764SConrad Meyer     unsigned* litLengthFreq;     /* table of litLength statistics, of size (MaxLL+1) */
167a0483764SConrad Meyer     unsigned* matchLengthFreq;   /* table of matchLength statistics, of size (MaxML+1) */
168a0483764SConrad Meyer     unsigned* offCodeFreq;       /* table of offCode statistics, of size (MaxOff+1) */
169052d3c12SConrad Meyer     ZSTD_match_t* matchTable;    /* list of found matches, of size ZSTD_OPT_NUM+1 */
170052d3c12SConrad Meyer     ZSTD_optimal_t* priceTable;  /* All positions tracked by optimal parser, of size ZSTD_OPT_NUM+1 */
171052d3c12SConrad Meyer 
172052d3c12SConrad Meyer     U32  litSum;                 /* nb of literals */
173052d3c12SConrad Meyer     U32  litLengthSum;           /* nb of litLength codes */
174052d3c12SConrad Meyer     U32  matchLengthSum;         /* nb of matchLength codes */
175052d3c12SConrad Meyer     U32  offCodeSum;             /* nb of offset codes */
1760f743729SConrad Meyer     U32  litSumBasePrice;        /* to compare to log2(litfreq) */
1770f743729SConrad Meyer     U32  litLengthSumBasePrice;  /* to compare to log2(llfreq)  */
1780f743729SConrad Meyer     U32  matchLengthSumBasePrice;/* to compare to log2(mlfreq)  */
1790f743729SConrad Meyer     U32  offCodeSumBasePrice;    /* to compare to log2(offreq)  */
1800f743729SConrad Meyer     ZSTD_OptPrice_e priceType;   /* prices can be determined dynamically, or follow a pre-defined cost structure */
1810f743729SConrad Meyer     const ZSTD_entropyCTables_t* symbolCosts;  /* pre-calculated dictionary statistics */
182*5ff13fbcSAllan Jude     ZSTD_paramSwitch_e literalCompressionMode;
183052d3c12SConrad Meyer } optState_t;
184052d3c12SConrad Meyer 
185052d3c12SConrad Meyer typedef struct {
18619fcbaf1SConrad Meyer   ZSTD_entropyCTables_t entropy;
18719fcbaf1SConrad Meyer   U32 rep[ZSTD_REP_NUM];
18819fcbaf1SConrad Meyer } ZSTD_compressedBlockState_t;
18919fcbaf1SConrad Meyer 
19019fcbaf1SConrad Meyer typedef struct {
19119fcbaf1SConrad Meyer     BYTE const* nextSrc;       /* next block here to continue on current prefix */
19219fcbaf1SConrad Meyer     BYTE const* base;          /* All regular indexes relative to this position */
19319fcbaf1SConrad Meyer     BYTE const* dictBase;      /* extDict indexes relative to this position */
19419fcbaf1SConrad Meyer     U32 dictLimit;             /* below that point, need extDict */
1954d3f1eafSConrad Meyer     U32 lowLimit;              /* below that point, no more valid data */
196*5ff13fbcSAllan Jude     U32 nbOverflowCorrections; /* Number of times overflow correction has run since
197*5ff13fbcSAllan Jude                                 * ZSTD_window_init(). Useful for debugging coredumps
198*5ff13fbcSAllan Jude                                 * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.
199*5ff13fbcSAllan Jude                                 */
20019fcbaf1SConrad Meyer } ZSTD_window_t;
20119fcbaf1SConrad Meyer 
202*5ff13fbcSAllan Jude #define ZSTD_WINDOW_START_INDEX 2
203*5ff13fbcSAllan Jude 
2040f743729SConrad Meyer typedef struct ZSTD_matchState_t ZSTD_matchState_t;
205*5ff13fbcSAllan Jude 
206*5ff13fbcSAllan Jude #define ZSTD_ROW_HASH_CACHE_SIZE 8       /* Size of prefetching hash cache for row-based matchfinder */
207*5ff13fbcSAllan Jude 
2080f743729SConrad Meyer struct ZSTD_matchState_t {
20919fcbaf1SConrad Meyer     ZSTD_window_t window;   /* State for window round buffer management */
2109cbefe25SConrad Meyer     U32 loadedDictEnd;      /* index of end of dictionary, within context's referential.
2119cbefe25SConrad Meyer                              * When loadedDictEnd != 0, a dictionary is in use, and still valid.
2129cbefe25SConrad Meyer                              * This relies on a mechanism to set loadedDictEnd=0 when dictionary is no longer within distance.
2139cbefe25SConrad Meyer                              * Such mechanism is provided within ZSTD_window_enforceMaxDist() and ZSTD_checkDictValidity().
2149cbefe25SConrad Meyer                              * When dict referential is copied into active context (i.e. not attached),
2159cbefe25SConrad Meyer                              * loadedDictEnd == dictSize, since referential starts from zero.
2169cbefe25SConrad Meyer                              */
21719fcbaf1SConrad Meyer     U32 nextToUpdate;       /* index from which to continue table update */
2189cbefe25SConrad Meyer     U32 hashLog3;           /* dispatch table for matches of len==3 : larger == faster, more memory */
219*5ff13fbcSAllan Jude 
220*5ff13fbcSAllan Jude     U32 rowHashLog;                          /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
221*5ff13fbcSAllan Jude     U16* tagTable;                           /* For row-based matchFinder: A row-based table containing the hashes and head index. */
222*5ff13fbcSAllan Jude     U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
223*5ff13fbcSAllan Jude 
22419fcbaf1SConrad Meyer     U32* hashTable;
22519fcbaf1SConrad Meyer     U32* hashTable3;
22619fcbaf1SConrad Meyer     U32* chainTable;
227*5ff13fbcSAllan Jude 
228*5ff13fbcSAllan Jude     U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */
229*5ff13fbcSAllan Jude 
230f7cd7fe5SConrad Meyer     int dedicatedDictSearch;  /* Indicates whether this matchState is using the
231f7cd7fe5SConrad Meyer                                * dedicated dictionary search structure.
232f7cd7fe5SConrad Meyer                                */
23319fcbaf1SConrad Meyer     optState_t opt;         /* optimal parser state */
2340f743729SConrad Meyer     const ZSTD_matchState_t* dictMatchState;
2350f743729SConrad Meyer     ZSTD_compressionParameters cParams;
236f7cd7fe5SConrad Meyer     const rawSeqStore_t* ldmSeqStore;
2370f743729SConrad Meyer };
23819fcbaf1SConrad Meyer 
23919fcbaf1SConrad Meyer typedef struct {
24019fcbaf1SConrad Meyer     ZSTD_compressedBlockState_t* prevCBlock;
24119fcbaf1SConrad Meyer     ZSTD_compressedBlockState_t* nextCBlock;
24219fcbaf1SConrad Meyer     ZSTD_matchState_t matchState;
24319fcbaf1SConrad Meyer } ZSTD_blockState_t;
24419fcbaf1SConrad Meyer 
24519fcbaf1SConrad Meyer typedef struct {
246052d3c12SConrad Meyer     U32 offset;
247052d3c12SConrad Meyer     U32 checksum;
248052d3c12SConrad Meyer } ldmEntry_t;
249052d3c12SConrad Meyer 
250052d3c12SConrad Meyer typedef struct {
251*5ff13fbcSAllan Jude     BYTE const* split;
252*5ff13fbcSAllan Jude     U32 hash;
253*5ff13fbcSAllan Jude     U32 checksum;
254*5ff13fbcSAllan Jude     ldmEntry_t* bucket;
255*5ff13fbcSAllan Jude } ldmMatchCandidate_t;
256*5ff13fbcSAllan Jude 
257*5ff13fbcSAllan Jude #define LDM_BATCH_SIZE 64
258*5ff13fbcSAllan Jude 
259*5ff13fbcSAllan Jude typedef struct {
26019fcbaf1SConrad Meyer     ZSTD_window_t window;   /* State for the window round buffer management */
261052d3c12SConrad Meyer     ldmEntry_t* hashTable;
26237f1f268SConrad Meyer     U32 loadedDictEnd;
263052d3c12SConrad Meyer     BYTE* bucketOffsets;    /* Next position in bucket to insert entry */
264*5ff13fbcSAllan Jude     size_t splitIndices[LDM_BATCH_SIZE];
265*5ff13fbcSAllan Jude     ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];
266052d3c12SConrad Meyer } ldmState_t;
267052d3c12SConrad Meyer 
268052d3c12SConrad Meyer typedef struct {
269*5ff13fbcSAllan Jude     ZSTD_paramSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */
270052d3c12SConrad Meyer     U32 hashLog;            /* Log size of hashTable */
271052d3c12SConrad Meyer     U32 bucketSizeLog;      /* Log bucket size for collision resolution, at most 8 */
272052d3c12SConrad Meyer     U32 minMatchLength;     /* Minimum match length */
273a0483764SConrad Meyer     U32 hashRateLog;       /* Log number of entries to skip */
27419fcbaf1SConrad Meyer     U32 windowLog;          /* Window log for the LDM */
275052d3c12SConrad Meyer } ldmParams_t;
276052d3c12SConrad Meyer 
27719fcbaf1SConrad Meyer typedef struct {
2789cbefe25SConrad Meyer     int collectSequences;
2799cbefe25SConrad Meyer     ZSTD_Sequence* seqStart;
2809cbefe25SConrad Meyer     size_t seqIndex;
2819cbefe25SConrad Meyer     size_t maxSequences;
2829cbefe25SConrad Meyer } SeqCollector;
2839cbefe25SConrad Meyer 
284052d3c12SConrad Meyer struct ZSTD_CCtx_params_s {
285052d3c12SConrad Meyer     ZSTD_format_e format;
286052d3c12SConrad Meyer     ZSTD_compressionParameters cParams;
287052d3c12SConrad Meyer     ZSTD_frameParameters fParams;
288052d3c12SConrad Meyer 
289052d3c12SConrad Meyer     int compressionLevel;
29019fcbaf1SConrad Meyer     int forceWindow;           /* force back-references to respect limit of
291052d3c12SConrad Meyer                                 * 1<<wLog, even for dictionary */
2924d3f1eafSConrad Meyer     size_t targetCBlockSize;   /* Tries to fit compressed block size to be around targetCBlockSize.
2934d3f1eafSConrad Meyer                                 * No target when targetCBlockSize == 0.
2944d3f1eafSConrad Meyer                                 * There is no guarantee on compressed block size */
2959cbefe25SConrad Meyer     int srcSizeHint;           /* User's best guess of source size.
2969cbefe25SConrad Meyer                                 * Hint is not valid when srcSizeHint == 0.
2979cbefe25SConrad Meyer                                 * There is no guarantee that hint is close to actual source size */
298052d3c12SConrad Meyer 
2990f743729SConrad Meyer     ZSTD_dictAttachPref_e attachDictPref;
300*5ff13fbcSAllan Jude     ZSTD_paramSwitch_e literalCompressionMode;
3010f743729SConrad Meyer 
302052d3c12SConrad Meyer     /* Multithreading: used to pass parameters to mtctx */
303a0483764SConrad Meyer     int nbWorkers;
304a0483764SConrad Meyer     size_t jobSize;
305a0483764SConrad Meyer     int overlapLog;
306a0483764SConrad Meyer     int rsyncable;
307052d3c12SConrad Meyer 
308052d3c12SConrad Meyer     /* Long distance matching parameters */
309052d3c12SConrad Meyer     ldmParams_t ldmParams;
310052d3c12SConrad Meyer 
311f7cd7fe5SConrad Meyer     /* Dedicated dict search algorithm trigger */
312f7cd7fe5SConrad Meyer     int enableDedicatedDictSearch;
313f7cd7fe5SConrad Meyer 
314f7cd7fe5SConrad Meyer     /* Input/output buffer modes */
315f7cd7fe5SConrad Meyer     ZSTD_bufferMode_e inBufferMode;
316f7cd7fe5SConrad Meyer     ZSTD_bufferMode_e outBufferMode;
317f7cd7fe5SConrad Meyer 
318f7cd7fe5SConrad Meyer     /* Sequence compression API */
319f7cd7fe5SConrad Meyer     ZSTD_sequenceFormat_e blockDelimiters;
320f7cd7fe5SConrad Meyer     int validateSequences;
321f7cd7fe5SConrad Meyer 
322*5ff13fbcSAllan Jude     /* Block splitting */
323*5ff13fbcSAllan Jude     ZSTD_paramSwitch_e useBlockSplitter;
324*5ff13fbcSAllan Jude 
325*5ff13fbcSAllan Jude     /* Param for deciding whether to use row-based matchfinder */
326*5ff13fbcSAllan Jude     ZSTD_paramSwitch_e useRowMatchFinder;
327*5ff13fbcSAllan Jude 
328*5ff13fbcSAllan Jude     /* Always load a dictionary in ext-dict mode (not prefix mode)? */
329*5ff13fbcSAllan Jude     int deterministicRefPrefix;
330*5ff13fbcSAllan Jude 
33119fcbaf1SConrad Meyer     /* Internal use, for createCCtxParams() and freeCCtxParams() only */
332052d3c12SConrad Meyer     ZSTD_customMem customMem;
333052d3c12SConrad Meyer };  /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
334052d3c12SConrad Meyer 
335f7cd7fe5SConrad Meyer #define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
336f7cd7fe5SConrad Meyer #define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)
337f7cd7fe5SConrad Meyer 
338f7cd7fe5SConrad Meyer /**
339f7cd7fe5SConrad Meyer  * Indicates whether this compression proceeds directly from user-provided
340f7cd7fe5SConrad Meyer  * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or
341f7cd7fe5SConrad Meyer  * whether the context needs to buffer the input/output (ZSTDb_buffered).
342f7cd7fe5SConrad Meyer  */
343f7cd7fe5SConrad Meyer typedef enum {
344f7cd7fe5SConrad Meyer     ZSTDb_not_buffered,
345f7cd7fe5SConrad Meyer     ZSTDb_buffered
346f7cd7fe5SConrad Meyer } ZSTD_buffered_policy_e;
347f7cd7fe5SConrad Meyer 
348*5ff13fbcSAllan Jude /**
349*5ff13fbcSAllan Jude  * Struct that contains all elements of block splitter that should be allocated
350*5ff13fbcSAllan Jude  * in a wksp.
351*5ff13fbcSAllan Jude  */
352*5ff13fbcSAllan Jude #define ZSTD_MAX_NB_BLOCK_SPLITS 196
353*5ff13fbcSAllan Jude typedef struct {
354*5ff13fbcSAllan Jude     seqStore_t fullSeqStoreChunk;
355*5ff13fbcSAllan Jude     seqStore_t firstHalfSeqStore;
356*5ff13fbcSAllan Jude     seqStore_t secondHalfSeqStore;
357*5ff13fbcSAllan Jude     seqStore_t currSeqStore;
358*5ff13fbcSAllan Jude     seqStore_t nextSeqStore;
359*5ff13fbcSAllan Jude 
360*5ff13fbcSAllan Jude     U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS];
361*5ff13fbcSAllan Jude     ZSTD_entropyCTablesMetadata_t entropyMetadata;
362*5ff13fbcSAllan Jude } ZSTD_blockSplitCtx;
363*5ff13fbcSAllan Jude 
364052d3c12SConrad Meyer struct ZSTD_CCtx_s {
365052d3c12SConrad Meyer     ZSTD_compressionStage_e stage;
36619fcbaf1SConrad Meyer     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. */
36719fcbaf1SConrad Meyer     int bmi2;                            /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
368052d3c12SConrad Meyer     ZSTD_CCtx_params requestedParams;
369052d3c12SConrad Meyer     ZSTD_CCtx_params appliedParams;
370*5ff13fbcSAllan Jude     ZSTD_CCtx_params simpleApiParams;    /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */
37119fcbaf1SConrad Meyer     U32   dictID;
372*5ff13fbcSAllan Jude     size_t dictContentSize;
3730f743729SConrad Meyer 
3749cbefe25SConrad Meyer     ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
375052d3c12SConrad Meyer     size_t blockSize;
37619fcbaf1SConrad Meyer     unsigned long long pledgedSrcSizePlusOne;  /* this way, 0 (default) == unknown */
37719fcbaf1SConrad Meyer     unsigned long long consumedSrcSize;
37819fcbaf1SConrad Meyer     unsigned long long producedCSize;
379052d3c12SConrad Meyer     XXH64_state_t xxhState;
380052d3c12SConrad Meyer     ZSTD_customMem customMem;
381f7cd7fe5SConrad Meyer     ZSTD_threadPool* pool;
382052d3c12SConrad Meyer     size_t staticSize;
3839cbefe25SConrad Meyer     SeqCollector seqCollector;
3849cbefe25SConrad Meyer     int isFirstBlock;
38537f1f268SConrad Meyer     int initialized;
386052d3c12SConrad Meyer 
387052d3c12SConrad Meyer     seqStore_t seqStore;      /* sequences storage ptrs */
388052d3c12SConrad Meyer     ldmState_t ldmState;      /* long distance matching state */
38919fcbaf1SConrad Meyer     rawSeq* ldmSequences;     /* Storage for the ldm output sequences */
39019fcbaf1SConrad Meyer     size_t maxNbLdmSequences;
39119fcbaf1SConrad Meyer     rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */
39219fcbaf1SConrad Meyer     ZSTD_blockState_t blockState;
393f7cd7fe5SConrad Meyer     U32* entropyWorkspace;  /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
394f7cd7fe5SConrad Meyer 
395*5ff13fbcSAllan Jude     /* Whether we are streaming or not */
396f7cd7fe5SConrad Meyer     ZSTD_buffered_policy_e bufferedPolicy;
397052d3c12SConrad Meyer 
398052d3c12SConrad Meyer     /* streaming */
399052d3c12SConrad Meyer     char*  inBuff;
400052d3c12SConrad Meyer     size_t inBuffSize;
401052d3c12SConrad Meyer     size_t inToCompress;
402052d3c12SConrad Meyer     size_t inBuffPos;
403052d3c12SConrad Meyer     size_t inBuffTarget;
404052d3c12SConrad Meyer     char*  outBuff;
405052d3c12SConrad Meyer     size_t outBuffSize;
406052d3c12SConrad Meyer     size_t outBuffContentSize;
407052d3c12SConrad Meyer     size_t outBuffFlushedSize;
408052d3c12SConrad Meyer     ZSTD_cStreamStage streamStage;
409052d3c12SConrad Meyer     U32    frameEnded;
410052d3c12SConrad Meyer 
411f7cd7fe5SConrad Meyer     /* Stable in/out buffer verification */
412f7cd7fe5SConrad Meyer     ZSTD_inBuffer expectedInBuffer;
413f7cd7fe5SConrad Meyer     size_t expectedOutBufferSize;
414f7cd7fe5SConrad Meyer 
415052d3c12SConrad Meyer     /* Dictionary */
4162b9c00cbSConrad Meyer     ZSTD_localDict localDict;
417052d3c12SConrad Meyer     const ZSTD_CDict* cdict;
418052d3c12SConrad Meyer     ZSTD_prefixDict prefixDict;   /* single-usage dictionary */
419052d3c12SConrad Meyer 
420052d3c12SConrad Meyer     /* Multi-threading */
421052d3c12SConrad Meyer #ifdef ZSTD_MULTITHREAD
422052d3c12SConrad Meyer     ZSTDMT_CCtx* mtctx;
423052d3c12SConrad Meyer #endif
424*5ff13fbcSAllan Jude 
425*5ff13fbcSAllan Jude     /* Tracing */
426*5ff13fbcSAllan Jude #if ZSTD_TRACE
427*5ff13fbcSAllan Jude     ZSTD_TraceCtx traceCtx;
428*5ff13fbcSAllan Jude #endif
429*5ff13fbcSAllan Jude 
430*5ff13fbcSAllan Jude     /* Workspace for block splitter */
431*5ff13fbcSAllan Jude     ZSTD_blockSplitCtx blockSplitCtx;
432052d3c12SConrad Meyer };
433052d3c12SConrad Meyer 
4340f743729SConrad Meyer typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
4350f743729SConrad Meyer 
436f7cd7fe5SConrad Meyer typedef enum {
437f7cd7fe5SConrad Meyer     ZSTD_noDict = 0,
438f7cd7fe5SConrad Meyer     ZSTD_extDict = 1,
439f7cd7fe5SConrad Meyer     ZSTD_dictMatchState = 2,
440f7cd7fe5SConrad Meyer     ZSTD_dedicatedDictSearch = 3
441f7cd7fe5SConrad Meyer } ZSTD_dictMode_e;
4420f743729SConrad Meyer 
443f7cd7fe5SConrad Meyer typedef enum {
444f7cd7fe5SConrad Meyer     ZSTD_cpm_noAttachDict = 0,  /* Compression with ZSTD_noDict or ZSTD_extDict.
445f7cd7fe5SConrad Meyer                                  * In this mode we use both the srcSize and the dictSize
446f7cd7fe5SConrad Meyer                                  * when selecting and adjusting parameters.
447f7cd7fe5SConrad Meyer                                  */
448f7cd7fe5SConrad Meyer     ZSTD_cpm_attachDict = 1,    /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.
449f7cd7fe5SConrad Meyer                                  * In this mode we only take the srcSize into account when selecting
450f7cd7fe5SConrad Meyer                                  * and adjusting parameters.
451f7cd7fe5SConrad Meyer                                  */
452f7cd7fe5SConrad Meyer     ZSTD_cpm_createCDict = 2,   /* Creating a CDict.
453f7cd7fe5SConrad Meyer                                  * In this mode we take both the source size and the dictionary size
454f7cd7fe5SConrad Meyer                                  * into account when selecting and adjusting the parameters.
455f7cd7fe5SConrad Meyer                                  */
456f7cd7fe5SConrad Meyer     ZSTD_cpm_unknown = 3,       /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
457f7cd7fe5SConrad Meyer                                  * We don't know what these parameters are for. We default to the legacy
458f7cd7fe5SConrad Meyer                                  * behavior of taking both the source size and the dict size into account
459f7cd7fe5SConrad Meyer                                  * when selecting and adjusting parameters.
460f7cd7fe5SConrad Meyer                                  */
461f7cd7fe5SConrad Meyer } ZSTD_cParamMode_e;
462052d3c12SConrad Meyer 
46319fcbaf1SConrad Meyer typedef size_t (*ZSTD_blockCompressor) (
46419fcbaf1SConrad Meyer         ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
4650f743729SConrad Meyer         void const* src, size_t srcSize);
466*5ff13fbcSAllan Jude ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
46719fcbaf1SConrad Meyer 
46819fcbaf1SConrad Meyer 
ZSTD_LLcode(U32 litLength)469052d3c12SConrad Meyer MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
470052d3c12SConrad Meyer {
471052d3c12SConrad Meyer     static const BYTE LL_Code[64] = {  0,  1,  2,  3,  4,  5,  6,  7,
472052d3c12SConrad Meyer                                        8,  9, 10, 11, 12, 13, 14, 15,
473052d3c12SConrad Meyer                                       16, 16, 17, 17, 18, 18, 19, 19,
474052d3c12SConrad Meyer                                       20, 20, 20, 20, 21, 21, 21, 21,
475052d3c12SConrad Meyer                                       22, 22, 22, 22, 22, 22, 22, 22,
476052d3c12SConrad Meyer                                       23, 23, 23, 23, 23, 23, 23, 23,
477052d3c12SConrad Meyer                                       24, 24, 24, 24, 24, 24, 24, 24,
478052d3c12SConrad Meyer                                       24, 24, 24, 24, 24, 24, 24, 24 };
479052d3c12SConrad Meyer     static const U32 LL_deltaCode = 19;
480052d3c12SConrad Meyer     return (litLength > 63) ? ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
481052d3c12SConrad Meyer }
482052d3c12SConrad Meyer 
483052d3c12SConrad Meyer /* ZSTD_MLcode() :
484052d3c12SConrad Meyer  * note : mlBase = matchLength - MINMATCH;
485052d3c12SConrad Meyer  *        because it's the format it's stored in seqStore->sequences */
ZSTD_MLcode(U32 mlBase)486052d3c12SConrad Meyer MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
487052d3c12SConrad Meyer {
488052d3c12SConrad Meyer     static const BYTE ML_Code[128] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
489052d3c12SConrad Meyer                                       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
490052d3c12SConrad Meyer                                       32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
491052d3c12SConrad Meyer                                       38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
492052d3c12SConrad Meyer                                       40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
493052d3c12SConrad Meyer                                       41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
494052d3c12SConrad Meyer                                       42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
495052d3c12SConrad Meyer                                       42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
496052d3c12SConrad Meyer     static const U32 ML_deltaCode = 36;
497052d3c12SConrad Meyer     return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
498052d3c12SConrad Meyer }
499052d3c12SConrad Meyer 
5004d3f1eafSConrad Meyer /* ZSTD_cParam_withinBounds:
5014d3f1eafSConrad Meyer  * @return 1 if value is within cParam bounds,
5024d3f1eafSConrad Meyer  * 0 otherwise */
ZSTD_cParam_withinBounds(ZSTD_cParameter cParam,int value)5034d3f1eafSConrad Meyer MEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)
5044d3f1eafSConrad Meyer {
5054d3f1eafSConrad Meyer     ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);
5064d3f1eafSConrad Meyer     if (ZSTD_isError(bounds.error)) return 0;
5074d3f1eafSConrad Meyer     if (value < bounds.lowerBound) return 0;
5084d3f1eafSConrad Meyer     if (value > bounds.upperBound) return 0;
5094d3f1eafSConrad Meyer     return 1;
5104d3f1eafSConrad Meyer }
5114d3f1eafSConrad Meyer 
51237f1f268SConrad Meyer /* ZSTD_noCompressBlock() :
51337f1f268SConrad Meyer  * Writes uncompressed block to dst buffer from given src.
51437f1f268SConrad Meyer  * Returns the size of the block */
ZSTD_noCompressBlock(void * dst,size_t dstCapacity,const void * src,size_t srcSize,U32 lastBlock)51537f1f268SConrad Meyer MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)
51637f1f268SConrad Meyer {
51737f1f268SConrad Meyer     U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);
51837f1f268SConrad Meyer     RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,
51937f1f268SConrad Meyer                     dstSize_tooSmall, "dst buf too small for uncompressed block");
52037f1f268SConrad Meyer     MEM_writeLE24(dst, cBlockHeader24);
521f7cd7fe5SConrad Meyer     ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);
52237f1f268SConrad Meyer     return ZSTD_blockHeaderSize + srcSize;
52337f1f268SConrad Meyer }
52437f1f268SConrad Meyer 
ZSTD_rleCompressBlock(void * dst,size_t dstCapacity,BYTE src,size_t srcSize,U32 lastBlock)52537f1f268SConrad Meyer MEM_STATIC size_t ZSTD_rleCompressBlock (void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)
52637f1f268SConrad Meyer {
52737f1f268SConrad Meyer     BYTE* const op = (BYTE*)dst;
52837f1f268SConrad Meyer     U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);
52937f1f268SConrad Meyer     RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, "");
53037f1f268SConrad Meyer     MEM_writeLE24(op, cBlockHeader);
53137f1f268SConrad Meyer     op[3] = src;
53237f1f268SConrad Meyer     return 4;
53337f1f268SConrad Meyer }
53437f1f268SConrad Meyer 
53537f1f268SConrad Meyer 
5364d3f1eafSConrad Meyer /* ZSTD_minGain() :
5374d3f1eafSConrad Meyer  * minimum compression required
5384d3f1eafSConrad Meyer  * to generate a compress block or a compressed literals section.
5394d3f1eafSConrad Meyer  * note : use same formula for both situations */
ZSTD_minGain(size_t srcSize,ZSTD_strategy strat)5404d3f1eafSConrad Meyer MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
5414d3f1eafSConrad Meyer {
5424d3f1eafSConrad Meyer     U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
5434d3f1eafSConrad Meyer     ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
5444d3f1eafSConrad Meyer     assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
5454d3f1eafSConrad Meyer     return (srcSize >> minlog) + 2;
5464d3f1eafSConrad Meyer }
5474d3f1eafSConrad Meyer 
ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params * cctxParams)548*5ff13fbcSAllan Jude MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)
54937f1f268SConrad Meyer {
55037f1f268SConrad Meyer     switch (cctxParams->literalCompressionMode) {
551*5ff13fbcSAllan Jude     case ZSTD_ps_enable:
55237f1f268SConrad Meyer         return 0;
553*5ff13fbcSAllan Jude     case ZSTD_ps_disable:
55437f1f268SConrad Meyer         return 1;
55537f1f268SConrad Meyer     default:
55637f1f268SConrad Meyer         assert(0 /* impossible: pre-validated */);
557*5ff13fbcSAllan Jude         ZSTD_FALLTHROUGH;
558*5ff13fbcSAllan Jude     case ZSTD_ps_auto:
55937f1f268SConrad Meyer         return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
56037f1f268SConrad Meyer     }
56137f1f268SConrad Meyer }
56237f1f268SConrad Meyer 
5639cbefe25SConrad Meyer /*! ZSTD_safecopyLiterals() :
5649cbefe25SConrad Meyer  *  memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w.
5659cbefe25SConrad Meyer  *  Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
5669cbefe25SConrad Meyer  *  large copies.
567052d3c12SConrad Meyer  */
568*5ff13fbcSAllan Jude static void
ZSTD_safecopyLiterals(BYTE * op,BYTE const * ip,BYTE const * const iend,BYTE const * ilimit_w)569*5ff13fbcSAllan Jude ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)
570*5ff13fbcSAllan Jude {
5719cbefe25SConrad Meyer     assert(iend > ilimit_w);
5729cbefe25SConrad Meyer     if (ip <= ilimit_w) {
5739cbefe25SConrad Meyer         ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
5749cbefe25SConrad Meyer         op += ilimit_w - ip;
5759cbefe25SConrad Meyer         ip = ilimit_w;
5769cbefe25SConrad Meyer     }
5779cbefe25SConrad Meyer     while (ip < iend) *op++ = *ip++;
5789cbefe25SConrad Meyer }
5799cbefe25SConrad Meyer 
580*5ff13fbcSAllan Jude #define ZSTD_REP_MOVE     (ZSTD_REP_NUM-1)
581*5ff13fbcSAllan Jude #define STORE_REPCODE_1 STORE_REPCODE(1)
582*5ff13fbcSAllan Jude #define STORE_REPCODE_2 STORE_REPCODE(2)
583*5ff13fbcSAllan Jude #define STORE_REPCODE_3 STORE_REPCODE(3)
584*5ff13fbcSAllan Jude #define STORE_REPCODE(r) (assert((r)>=1), assert((r)<=3), (r)-1)
585*5ff13fbcSAllan Jude #define STORE_OFFSET(o)  (assert((o)>0), o + ZSTD_REP_MOVE)
586*5ff13fbcSAllan Jude #define STORED_IS_OFFSET(o)  ((o) > ZSTD_REP_MOVE)
587*5ff13fbcSAllan Jude #define STORED_IS_REPCODE(o) ((o) <= ZSTD_REP_MOVE)
588*5ff13fbcSAllan Jude #define STORED_OFFSET(o)  (assert(STORED_IS_OFFSET(o)), (o)-ZSTD_REP_MOVE)
589*5ff13fbcSAllan Jude #define STORED_REPCODE(o) (assert(STORED_IS_REPCODE(o)), (o)+1)  /* returns ID 1,2,3 */
590*5ff13fbcSAllan Jude #define STORED_TO_OFFBASE(o) ((o)+1)
591*5ff13fbcSAllan Jude #define OFFBASE_TO_STORED(o) ((o)-1)
592*5ff13fbcSAllan Jude 
5939cbefe25SConrad Meyer /*! ZSTD_storeSeq() :
594*5ff13fbcSAllan Jude  *  Store a sequence (litlen, litPtr, offCode and matchLength) into seqStore_t.
595*5ff13fbcSAllan Jude  *  @offBase_minus1 : Users should use employ macros STORE_REPCODE_X and STORE_OFFSET().
596*5ff13fbcSAllan Jude  *  @matchLength : must be >= MINMATCH
5979cbefe25SConrad Meyer  *  Allowed to overread literals up to litLimit.
5989cbefe25SConrad Meyer */
599*5ff13fbcSAllan Jude HINT_INLINE UNUSED_ATTR void
ZSTD_storeSeq(seqStore_t * seqStorePtr,size_t litLength,const BYTE * literals,const BYTE * litLimit,U32 offBase_minus1,size_t matchLength)600*5ff13fbcSAllan Jude ZSTD_storeSeq(seqStore_t* seqStorePtr,
601*5ff13fbcSAllan Jude               size_t litLength, const BYTE* literals, const BYTE* litLimit,
602*5ff13fbcSAllan Jude               U32 offBase_minus1,
603*5ff13fbcSAllan Jude               size_t matchLength)
604052d3c12SConrad Meyer {
6059cbefe25SConrad Meyer     BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
6069cbefe25SConrad Meyer     BYTE const* const litEnd = literals + litLength;
6070f743729SConrad Meyer #if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)
608052d3c12SConrad Meyer     static const BYTE* g_start = NULL;
609052d3c12SConrad Meyer     if (g_start==NULL) g_start = (const BYTE*)literals;  /* note : index only works for compression within a single segment */
610052d3c12SConrad Meyer     {   U32 const pos = (U32)((const BYTE*)literals - g_start);
6110f743729SConrad Meyer         DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
612*5ff13fbcSAllan Jude                pos, (U32)litLength, (U32)matchLength, (U32)offBase_minus1);
613052d3c12SConrad Meyer     }
614052d3c12SConrad Meyer #endif
6150f743729SConrad Meyer     assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
616052d3c12SConrad Meyer     /* copy Literals */
6170f743729SConrad Meyer     assert(seqStorePtr->maxNbLit <= 128 KB);
6180f743729SConrad Meyer     assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);
6199cbefe25SConrad Meyer     assert(literals + litLength <= litLimit);
6209cbefe25SConrad Meyer     if (litEnd <= litLimit_w) {
6219cbefe25SConrad Meyer         /* Common case we can use wildcopy.
6229cbefe25SConrad Meyer 	 * First copy 16 bytes, because literals are likely short.
6239cbefe25SConrad Meyer 	 */
6249cbefe25SConrad Meyer         assert(WILDCOPY_OVERLENGTH >= 16);
6259cbefe25SConrad Meyer         ZSTD_copy16(seqStorePtr->lit, literals);
6269cbefe25SConrad Meyer         if (litLength > 16) {
6279cbefe25SConrad Meyer             ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);
6289cbefe25SConrad Meyer         }
6299cbefe25SConrad Meyer     } else {
6309cbefe25SConrad Meyer         ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);
6319cbefe25SConrad Meyer     }
632052d3c12SConrad Meyer     seqStorePtr->lit += litLength;
633052d3c12SConrad Meyer 
634052d3c12SConrad Meyer     /* literal Length */
635052d3c12SConrad Meyer     if (litLength>0xFFFF) {
636*5ff13fbcSAllan Jude         assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
637*5ff13fbcSAllan Jude         seqStorePtr->longLengthType = ZSTD_llt_literalLength;
638052d3c12SConrad Meyer         seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
639052d3c12SConrad Meyer     }
640052d3c12SConrad Meyer     seqStorePtr->sequences[0].litLength = (U16)litLength;
641052d3c12SConrad Meyer 
642052d3c12SConrad Meyer     /* match offset */
643*5ff13fbcSAllan Jude     seqStorePtr->sequences[0].offBase = STORED_TO_OFFBASE(offBase_minus1);
644052d3c12SConrad Meyer 
645052d3c12SConrad Meyer     /* match Length */
646*5ff13fbcSAllan Jude     assert(matchLength >= MINMATCH);
647*5ff13fbcSAllan Jude     {   size_t const mlBase = matchLength - MINMATCH;
648052d3c12SConrad Meyer         if (mlBase>0xFFFF) {
649*5ff13fbcSAllan Jude             assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
650*5ff13fbcSAllan Jude             seqStorePtr->longLengthType = ZSTD_llt_matchLength;
651052d3c12SConrad Meyer             seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
652052d3c12SConrad Meyer         }
653*5ff13fbcSAllan Jude         seqStorePtr->sequences[0].mlBase = (U16)mlBase;
654*5ff13fbcSAllan Jude     }
655052d3c12SConrad Meyer 
656052d3c12SConrad Meyer     seqStorePtr->sequences++;
657052d3c12SConrad Meyer }
658052d3c12SConrad Meyer 
659*5ff13fbcSAllan Jude /* ZSTD_updateRep() :
660*5ff13fbcSAllan Jude  * updates in-place @rep (array of repeat offsets)
661*5ff13fbcSAllan Jude  * @offBase_minus1 : sum-type, with same numeric representation as ZSTD_storeSeq()
662*5ff13fbcSAllan Jude  */
663*5ff13fbcSAllan Jude MEM_STATIC void
ZSTD_updateRep(U32 rep[ZSTD_REP_NUM],U32 const offBase_minus1,U32 const ll0)664*5ff13fbcSAllan Jude ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
665*5ff13fbcSAllan Jude {
666*5ff13fbcSAllan Jude     if (STORED_IS_OFFSET(offBase_minus1)) {  /* full offset */
667*5ff13fbcSAllan Jude         rep[2] = rep[1];
668*5ff13fbcSAllan Jude         rep[1] = rep[0];
669*5ff13fbcSAllan Jude         rep[0] = STORED_OFFSET(offBase_minus1);
670*5ff13fbcSAllan Jude     } else {   /* repcode */
671*5ff13fbcSAllan Jude         U32 const repCode = STORED_REPCODE(offBase_minus1) - 1 + ll0;
672*5ff13fbcSAllan Jude         if (repCode > 0) {  /* note : if repCode==0, no change */
673*5ff13fbcSAllan Jude             U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
674*5ff13fbcSAllan Jude             rep[2] = (repCode >= 2) ? rep[1] : rep[2];
675*5ff13fbcSAllan Jude             rep[1] = rep[0];
676*5ff13fbcSAllan Jude             rep[0] = currentOffset;
677*5ff13fbcSAllan Jude         } else {   /* repCode == 0 */
678*5ff13fbcSAllan Jude             /* nothing to do */
679*5ff13fbcSAllan Jude         }
680*5ff13fbcSAllan Jude     }
681*5ff13fbcSAllan Jude }
682*5ff13fbcSAllan Jude 
683*5ff13fbcSAllan Jude typedef struct repcodes_s {
684*5ff13fbcSAllan Jude     U32 rep[3];
685*5ff13fbcSAllan Jude } repcodes_t;
686*5ff13fbcSAllan Jude 
687*5ff13fbcSAllan Jude MEM_STATIC repcodes_t
ZSTD_newRep(U32 const rep[ZSTD_REP_NUM],U32 const offBase_minus1,U32 const ll0)688*5ff13fbcSAllan Jude ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
689*5ff13fbcSAllan Jude {
690*5ff13fbcSAllan Jude     repcodes_t newReps;
691*5ff13fbcSAllan Jude     ZSTD_memcpy(&newReps, rep, sizeof(newReps));
692*5ff13fbcSAllan Jude     ZSTD_updateRep(newReps.rep, offBase_minus1, ll0);
693*5ff13fbcSAllan Jude     return newReps;
694*5ff13fbcSAllan Jude }
695*5ff13fbcSAllan Jude 
696052d3c12SConrad Meyer 
697052d3c12SConrad Meyer /*-*************************************
698052d3c12SConrad Meyer *  Match length counter
699052d3c12SConrad Meyer ***************************************/
ZSTD_NbCommonBytes(size_t val)700052d3c12SConrad Meyer static unsigned ZSTD_NbCommonBytes (size_t val)
701052d3c12SConrad Meyer {
702052d3c12SConrad Meyer     if (MEM_isLittleEndian()) {
703052d3c12SConrad Meyer         if (MEM_64bits()) {
704052d3c12SConrad Meyer #       if defined(_MSC_VER) && defined(_WIN64)
705f7cd7fe5SConrad Meyer #           if STATIC_BMI2
706f7cd7fe5SConrad Meyer                 return _tzcnt_u64(val) >> 3;
707f7cd7fe5SConrad Meyer #           else
708*5ff13fbcSAllan Jude                 if (val != 0) {
709*5ff13fbcSAllan Jude                     unsigned long r;
710*5ff13fbcSAllan Jude                     _BitScanForward64(&r, (U64)val);
711*5ff13fbcSAllan Jude                     return (unsigned)(r >> 3);
712*5ff13fbcSAllan Jude                 } else {
713*5ff13fbcSAllan Jude                     /* Should not reach this code path */
714*5ff13fbcSAllan Jude                     __assume(0);
715*5ff13fbcSAllan Jude                 }
716f7cd7fe5SConrad Meyer #           endif
717052d3c12SConrad Meyer #       elif defined(__GNUC__) && (__GNUC__ >= 4)
718052d3c12SConrad Meyer             return (__builtin_ctzll((U64)val) >> 3);
719052d3c12SConrad Meyer #       else
720052d3c12SConrad Meyer             static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,
721052d3c12SConrad Meyer                                                      0, 3, 1, 3, 1, 4, 2, 7,
722052d3c12SConrad Meyer                                                      0, 2, 3, 6, 1, 5, 3, 5,
723052d3c12SConrad Meyer                                                      1, 3, 4, 4, 2, 5, 6, 7,
724052d3c12SConrad Meyer                                                      7, 0, 1, 2, 3, 3, 4, 6,
725052d3c12SConrad Meyer                                                      2, 6, 5, 5, 3, 4, 5, 6,
726052d3c12SConrad Meyer                                                      7, 1, 2, 4, 6, 4, 4, 5,
727052d3c12SConrad Meyer                                                      7, 2, 6, 5, 7, 6, 7, 7 };
728052d3c12SConrad Meyer             return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
729052d3c12SConrad Meyer #       endif
730052d3c12SConrad Meyer         } else { /* 32 bits */
731052d3c12SConrad Meyer #       if defined(_MSC_VER)
732*5ff13fbcSAllan Jude             if (val != 0) {
733*5ff13fbcSAllan Jude                 unsigned long r;
734*5ff13fbcSAllan Jude                 _BitScanForward(&r, (U32)val);
735*5ff13fbcSAllan Jude                 return (unsigned)(r >> 3);
736*5ff13fbcSAllan Jude             } else {
737*5ff13fbcSAllan Jude                 /* Should not reach this code path */
738*5ff13fbcSAllan Jude                 __assume(0);
739*5ff13fbcSAllan Jude             }
740052d3c12SConrad Meyer #       elif defined(__GNUC__) && (__GNUC__ >= 3)
741052d3c12SConrad Meyer             return (__builtin_ctz((U32)val) >> 3);
742052d3c12SConrad Meyer #       else
743052d3c12SConrad Meyer             static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,
744052d3c12SConrad Meyer                                                      3, 2, 2, 1, 3, 2, 0, 1,
745052d3c12SConrad Meyer                                                      3, 3, 1, 2, 2, 2, 2, 0,
746052d3c12SConrad Meyer                                                      3, 1, 2, 0, 1, 0, 1, 1 };
747052d3c12SConrad Meyer             return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
748052d3c12SConrad Meyer #       endif
749052d3c12SConrad Meyer         }
750052d3c12SConrad Meyer     } else {  /* Big Endian CPU */
751052d3c12SConrad Meyer         if (MEM_64bits()) {
752052d3c12SConrad Meyer #       if defined(_MSC_VER) && defined(_WIN64)
753f7cd7fe5SConrad Meyer #           if STATIC_BMI2
754f7cd7fe5SConrad Meyer 			    return _lzcnt_u64(val) >> 3;
755f7cd7fe5SConrad Meyer #           else
756*5ff13fbcSAllan Jude                 if (val != 0) {
757*5ff13fbcSAllan Jude                     unsigned long r;
758*5ff13fbcSAllan Jude                     _BitScanReverse64(&r, (U64)val);
759*5ff13fbcSAllan Jude                     return (unsigned)(r >> 3);
760*5ff13fbcSAllan Jude                 } else {
761*5ff13fbcSAllan Jude                     /* Should not reach this code path */
762*5ff13fbcSAllan Jude                     __assume(0);
763*5ff13fbcSAllan Jude                 }
764f7cd7fe5SConrad Meyer #           endif
7650f743729SConrad Meyer #       elif defined(__GNUC__) && (__GNUC__ >= 4)
766052d3c12SConrad Meyer             return (__builtin_clzll(val) >> 3);
767052d3c12SConrad Meyer #       else
768052d3c12SConrad Meyer             unsigned r;
769052d3c12SConrad Meyer             const unsigned n32 = sizeof(size_t)*4;   /* calculate this way due to compiler complaining in 32-bits mode */
770052d3c12SConrad Meyer             if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
771052d3c12SConrad Meyer             if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
772052d3c12SConrad Meyer             r += (!val);
773052d3c12SConrad Meyer             return r;
774052d3c12SConrad Meyer #       endif
775052d3c12SConrad Meyer         } else { /* 32 bits */
776052d3c12SConrad Meyer #       if defined(_MSC_VER)
777*5ff13fbcSAllan Jude             if (val != 0) {
778*5ff13fbcSAllan Jude                 unsigned long r;
779*5ff13fbcSAllan Jude                 _BitScanReverse(&r, (unsigned long)val);
780*5ff13fbcSAllan Jude                 return (unsigned)(r >> 3);
781*5ff13fbcSAllan Jude             } else {
782*5ff13fbcSAllan Jude                 /* Should not reach this code path */
783*5ff13fbcSAllan Jude                 __assume(0);
784*5ff13fbcSAllan Jude             }
7850f743729SConrad Meyer #       elif defined(__GNUC__) && (__GNUC__ >= 3)
786052d3c12SConrad Meyer             return (__builtin_clz((U32)val) >> 3);
787052d3c12SConrad Meyer #       else
788052d3c12SConrad Meyer             unsigned r;
789052d3c12SConrad Meyer             if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
790052d3c12SConrad Meyer             r += (!val);
791052d3c12SConrad Meyer             return r;
792052d3c12SConrad Meyer #       endif
793052d3c12SConrad Meyer     }   }
794052d3c12SConrad Meyer }
795052d3c12SConrad Meyer 
796052d3c12SConrad Meyer 
ZSTD_count(const BYTE * pIn,const BYTE * pMatch,const BYTE * const pInLimit)797052d3c12SConrad Meyer MEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)
798052d3c12SConrad Meyer {
799052d3c12SConrad Meyer     const BYTE* const pStart = pIn;
800052d3c12SConrad Meyer     const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);
801052d3c12SConrad Meyer 
802052d3c12SConrad Meyer     if (pIn < pInLoopLimit) {
803052d3c12SConrad Meyer         { size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
804052d3c12SConrad Meyer           if (diff) return ZSTD_NbCommonBytes(diff); }
805052d3c12SConrad Meyer         pIn+=sizeof(size_t); pMatch+=sizeof(size_t);
806052d3c12SConrad Meyer         while (pIn < pInLoopLimit) {
807052d3c12SConrad Meyer             size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
808052d3c12SConrad Meyer             if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
809052d3c12SConrad Meyer             pIn += ZSTD_NbCommonBytes(diff);
810052d3c12SConrad Meyer             return (size_t)(pIn - pStart);
811052d3c12SConrad Meyer     }   }
812052d3c12SConrad Meyer     if (MEM_64bits() && (pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
813052d3c12SConrad Meyer     if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
814052d3c12SConrad Meyer     if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
815052d3c12SConrad Meyer     return (size_t)(pIn - pStart);
816052d3c12SConrad Meyer }
817052d3c12SConrad Meyer 
818052d3c12SConrad Meyer /** ZSTD_count_2segments() :
819052d3c12SConrad Meyer  *  can count match length with `ip` & `match` in 2 different segments.
820052d3c12SConrad Meyer  *  convention : on reaching mEnd, match count continue starting from iStart
821052d3c12SConrad Meyer  */
82219fcbaf1SConrad Meyer MEM_STATIC size_t
ZSTD_count_2segments(const BYTE * ip,const BYTE * match,const BYTE * iEnd,const BYTE * mEnd,const BYTE * iStart)82319fcbaf1SConrad Meyer ZSTD_count_2segments(const BYTE* ip, const BYTE* match,
82419fcbaf1SConrad Meyer                      const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
825052d3c12SConrad Meyer {
826052d3c12SConrad Meyer     const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);
827052d3c12SConrad Meyer     size_t const matchLength = ZSTD_count(ip, match, vEnd);
828052d3c12SConrad Meyer     if (match + matchLength != mEnd) return matchLength;
8290f743729SConrad Meyer     DEBUGLOG(7, "ZSTD_count_2segments: found a 2-parts match (current length==%zu)", matchLength);
8300f743729SConrad Meyer     DEBUGLOG(7, "distance from match beginning to end dictionary = %zi", mEnd - match);
8310f743729SConrad Meyer     DEBUGLOG(7, "distance from current pos to end buffer = %zi", iEnd - ip);
8320f743729SConrad Meyer     DEBUGLOG(7, "next byte : ip==%02X, istart==%02X", ip[matchLength], *iStart);
8330f743729SConrad Meyer     DEBUGLOG(7, "final match length = %zu", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));
834052d3c12SConrad Meyer     return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);
835052d3c12SConrad Meyer }
836052d3c12SConrad Meyer 
837052d3c12SConrad Meyer 
838052d3c12SConrad Meyer /*-*************************************
839052d3c12SConrad Meyer  *  Hashes
840052d3c12SConrad Meyer  ***************************************/
841052d3c12SConrad Meyer static const U32 prime3bytes = 506832829U;
ZSTD_hash3(U32 u,U32 h)842052d3c12SConrad Meyer static U32    ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes)  >> (32-h) ; }
ZSTD_hash3Ptr(const void * ptr,U32 h)843052d3c12SConrad Meyer MEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */
844052d3c12SConrad Meyer 
845052d3c12SConrad Meyer static const U32 prime4bytes = 2654435761U;
ZSTD_hash4(U32 u,U32 h)846052d3c12SConrad Meyer static U32    ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
ZSTD_hash4Ptr(const void * ptr,U32 h)847052d3c12SConrad Meyer static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
848052d3c12SConrad Meyer 
849052d3c12SConrad Meyer static const U64 prime5bytes = 889523592379ULL;
ZSTD_hash5(U64 u,U32 h)850052d3c12SConrad Meyer 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)851052d3c12SConrad Meyer static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
852052d3c12SConrad Meyer 
853052d3c12SConrad Meyer static const U64 prime6bytes = 227718039650203ULL;
ZSTD_hash6(U64 u,U32 h)854052d3c12SConrad Meyer 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)855052d3c12SConrad Meyer static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
856052d3c12SConrad Meyer 
857052d3c12SConrad Meyer static const U64 prime7bytes = 58295818150454627ULL;
ZSTD_hash7(U64 u,U32 h)858052d3c12SConrad Meyer 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)859052d3c12SConrad Meyer static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
860052d3c12SConrad Meyer 
861052d3c12SConrad Meyer static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;
ZSTD_hash8(U64 u,U32 h)862052d3c12SConrad Meyer static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; }
ZSTD_hash8Ptr(const void * p,U32 h)863052d3c12SConrad Meyer static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); }
864052d3c12SConrad Meyer 
865f7cd7fe5SConrad Meyer MEM_STATIC FORCE_INLINE_ATTR
ZSTD_hashPtr(const void * p,U32 hBits,U32 mls)866f7cd7fe5SConrad Meyer size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
867052d3c12SConrad Meyer {
868052d3c12SConrad Meyer     switch(mls)
869052d3c12SConrad Meyer     {
870052d3c12SConrad Meyer     default:
871052d3c12SConrad Meyer     case 4: return ZSTD_hash4Ptr(p, hBits);
872052d3c12SConrad Meyer     case 5: return ZSTD_hash5Ptr(p, hBits);
873052d3c12SConrad Meyer     case 6: return ZSTD_hash6Ptr(p, hBits);
874052d3c12SConrad Meyer     case 7: return ZSTD_hash7Ptr(p, hBits);
875052d3c12SConrad Meyer     case 8: return ZSTD_hash8Ptr(p, hBits);
876052d3c12SConrad Meyer     }
877052d3c12SConrad Meyer }
878052d3c12SConrad Meyer 
879a0483764SConrad Meyer /** ZSTD_ipow() :
880a0483764SConrad Meyer  * Return base^exponent.
881a0483764SConrad Meyer  */
ZSTD_ipow(U64 base,U64 exponent)882a0483764SConrad Meyer static U64 ZSTD_ipow(U64 base, U64 exponent)
883a0483764SConrad Meyer {
884a0483764SConrad Meyer     U64 power = 1;
885a0483764SConrad Meyer     while (exponent) {
886a0483764SConrad Meyer       if (exponent & 1) power *= base;
887a0483764SConrad Meyer       exponent >>= 1;
888a0483764SConrad Meyer       base *= base;
889a0483764SConrad Meyer     }
890a0483764SConrad Meyer     return power;
891a0483764SConrad Meyer }
892a0483764SConrad Meyer 
893a0483764SConrad Meyer #define ZSTD_ROLL_HASH_CHAR_OFFSET 10
894a0483764SConrad Meyer 
895a0483764SConrad Meyer /** ZSTD_rollingHash_append() :
896a0483764SConrad Meyer  * Add the buffer to the hash value.
897a0483764SConrad Meyer  */
ZSTD_rollingHash_append(U64 hash,void const * buf,size_t size)898a0483764SConrad Meyer static U64 ZSTD_rollingHash_append(U64 hash, void const* buf, size_t size)
899a0483764SConrad Meyer {
900a0483764SConrad Meyer     BYTE const* istart = (BYTE const*)buf;
901a0483764SConrad Meyer     size_t pos;
902a0483764SConrad Meyer     for (pos = 0; pos < size; ++pos) {
903a0483764SConrad Meyer         hash *= prime8bytes;
904a0483764SConrad Meyer         hash += istart[pos] + ZSTD_ROLL_HASH_CHAR_OFFSET;
905a0483764SConrad Meyer     }
906a0483764SConrad Meyer     return hash;
907a0483764SConrad Meyer }
908a0483764SConrad Meyer 
909a0483764SConrad Meyer /** ZSTD_rollingHash_compute() :
910a0483764SConrad Meyer  * Compute the rolling hash value of the buffer.
911a0483764SConrad Meyer  */
ZSTD_rollingHash_compute(void const * buf,size_t size)912a0483764SConrad Meyer MEM_STATIC U64 ZSTD_rollingHash_compute(void const* buf, size_t size)
913a0483764SConrad Meyer {
914a0483764SConrad Meyer     return ZSTD_rollingHash_append(0, buf, size);
915a0483764SConrad Meyer }
916a0483764SConrad Meyer 
917a0483764SConrad Meyer /** ZSTD_rollingHash_primePower() :
918a0483764SConrad Meyer  * Compute the primePower to be passed to ZSTD_rollingHash_rotate() for a hash
919a0483764SConrad Meyer  * over a window of length bytes.
920a0483764SConrad Meyer  */
ZSTD_rollingHash_primePower(U32 length)921a0483764SConrad Meyer MEM_STATIC U64 ZSTD_rollingHash_primePower(U32 length)
922a0483764SConrad Meyer {
923a0483764SConrad Meyer     return ZSTD_ipow(prime8bytes, length - 1);
924a0483764SConrad Meyer }
925a0483764SConrad Meyer 
926a0483764SConrad Meyer /** ZSTD_rollingHash_rotate() :
927a0483764SConrad Meyer  * Rotate the rolling hash by one byte.
928a0483764SConrad Meyer  */
ZSTD_rollingHash_rotate(U64 hash,BYTE toRemove,BYTE toAdd,U64 primePower)929a0483764SConrad Meyer MEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 primePower)
930a0483764SConrad Meyer {
931a0483764SConrad Meyer     hash -= (toRemove + ZSTD_ROLL_HASH_CHAR_OFFSET) * primePower;
932a0483764SConrad Meyer     hash *= prime8bytes;
933a0483764SConrad Meyer     hash += toAdd + ZSTD_ROLL_HASH_CHAR_OFFSET;
934a0483764SConrad Meyer     return hash;
935a0483764SConrad Meyer }
936a0483764SConrad Meyer 
93719fcbaf1SConrad Meyer /*-*************************************
93819fcbaf1SConrad Meyer *  Round buffer management
93919fcbaf1SConrad Meyer ***************************************/
9404d3f1eafSConrad Meyer #if (ZSTD_WINDOWLOG_MAX_64 > 31)
9414d3f1eafSConrad Meyer # error "ZSTD_WINDOWLOG_MAX is too large : would overflow ZSTD_CURRENT_MAX"
9424d3f1eafSConrad Meyer #endif
94319fcbaf1SConrad Meyer /* Max current allowed */
94419fcbaf1SConrad Meyer #define ZSTD_CURRENT_MAX ((3U << 29) + (1U << ZSTD_WINDOWLOG_MAX))
94519fcbaf1SConrad Meyer /* Maximum chunk size before overflow correction needs to be called again */
94619fcbaf1SConrad Meyer #define ZSTD_CHUNKSIZE_MAX                                                     \
94719fcbaf1SConrad Meyer     ( ((U32)-1)                  /* Maximum ending current index */            \
94819fcbaf1SConrad Meyer     - ZSTD_CURRENT_MAX)          /* Maximum beginning lowLimit */
94919fcbaf1SConrad Meyer 
95019fcbaf1SConrad Meyer /**
95119fcbaf1SConrad Meyer  * ZSTD_window_clear():
95219fcbaf1SConrad Meyer  * Clears the window containing the history by simply setting it to empty.
95319fcbaf1SConrad Meyer  */
ZSTD_window_clear(ZSTD_window_t * window)95419fcbaf1SConrad Meyer MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
95519fcbaf1SConrad Meyer {
95619fcbaf1SConrad Meyer     size_t const endT = (size_t)(window->nextSrc - window->base);
95719fcbaf1SConrad Meyer     U32 const end = (U32)endT;
95819fcbaf1SConrad Meyer 
95919fcbaf1SConrad Meyer     window->lowLimit = end;
96019fcbaf1SConrad Meyer     window->dictLimit = end;
96119fcbaf1SConrad Meyer }
96219fcbaf1SConrad Meyer 
ZSTD_window_isEmpty(ZSTD_window_t const window)963*5ff13fbcSAllan Jude MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
964*5ff13fbcSAllan Jude {
965*5ff13fbcSAllan Jude     return window.dictLimit == ZSTD_WINDOW_START_INDEX &&
966*5ff13fbcSAllan Jude            window.lowLimit == ZSTD_WINDOW_START_INDEX &&
967*5ff13fbcSAllan Jude            (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;
968*5ff13fbcSAllan Jude }
969*5ff13fbcSAllan Jude 
97019fcbaf1SConrad Meyer /**
97119fcbaf1SConrad Meyer  * ZSTD_window_hasExtDict():
97219fcbaf1SConrad Meyer  * Returns non-zero if the window has a non-empty extDict.
97319fcbaf1SConrad Meyer  */
ZSTD_window_hasExtDict(ZSTD_window_t const window)97419fcbaf1SConrad Meyer MEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)
97519fcbaf1SConrad Meyer {
97619fcbaf1SConrad Meyer     return window.lowLimit < window.dictLimit;
97719fcbaf1SConrad Meyer }
97819fcbaf1SConrad Meyer 
97919fcbaf1SConrad Meyer /**
9800f743729SConrad Meyer  * ZSTD_matchState_dictMode():
9810f743729SConrad Meyer  * Inspects the provided matchState and figures out what dictMode should be
9820f743729SConrad Meyer  * passed to the compressor.
9830f743729SConrad Meyer  */
ZSTD_matchState_dictMode(const ZSTD_matchState_t * ms)9840f743729SConrad Meyer MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
9850f743729SConrad Meyer {
9860f743729SConrad Meyer     return ZSTD_window_hasExtDict(ms->window) ?
9870f743729SConrad Meyer         ZSTD_extDict :
9880f743729SConrad Meyer         ms->dictMatchState != NULL ?
989f7cd7fe5SConrad Meyer             (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :
9900f743729SConrad Meyer             ZSTD_noDict;
9910f743729SConrad Meyer }
9920f743729SConrad Meyer 
993*5ff13fbcSAllan Jude /* Defining this macro to non-zero tells zstd to run the overflow correction
994*5ff13fbcSAllan Jude  * code much more frequently. This is very inefficient, and should only be
995*5ff13fbcSAllan Jude  * used for tests and fuzzers.
996*5ff13fbcSAllan Jude  */
997*5ff13fbcSAllan Jude #ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY
998*5ff13fbcSAllan Jude #  ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
999*5ff13fbcSAllan Jude #    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1
1000*5ff13fbcSAllan Jude #  else
1001*5ff13fbcSAllan Jude #    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0
1002*5ff13fbcSAllan Jude #  endif
1003*5ff13fbcSAllan Jude #endif
1004*5ff13fbcSAllan Jude 
1005*5ff13fbcSAllan Jude /**
1006*5ff13fbcSAllan Jude  * ZSTD_window_canOverflowCorrect():
1007*5ff13fbcSAllan Jude  * Returns non-zero if the indices are large enough for overflow correction
1008*5ff13fbcSAllan Jude  * to work correctly without impacting compression ratio.
1009*5ff13fbcSAllan Jude  */
ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,U32 cycleLog,U32 maxDist,U32 loadedDictEnd,void const * src)1010*5ff13fbcSAllan Jude MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
1011*5ff13fbcSAllan Jude                                               U32 cycleLog,
1012*5ff13fbcSAllan Jude                                               U32 maxDist,
1013*5ff13fbcSAllan Jude                                               U32 loadedDictEnd,
1014*5ff13fbcSAllan Jude                                               void const* src)
1015*5ff13fbcSAllan Jude {
1016*5ff13fbcSAllan Jude     U32 const cycleSize = 1u << cycleLog;
1017*5ff13fbcSAllan Jude     U32 const curr = (U32)((BYTE const*)src - window.base);
1018*5ff13fbcSAllan Jude     U32 const minIndexToOverflowCorrect = cycleSize
1019*5ff13fbcSAllan Jude                                         + MAX(maxDist, cycleSize)
1020*5ff13fbcSAllan Jude                                         + ZSTD_WINDOW_START_INDEX;
1021*5ff13fbcSAllan Jude 
1022*5ff13fbcSAllan Jude     /* Adjust the min index to backoff the overflow correction frequency,
1023*5ff13fbcSAllan Jude      * so we don't waste too much CPU in overflow correction. If this
1024*5ff13fbcSAllan Jude      * computation overflows we don't really care, we just need to make
1025*5ff13fbcSAllan Jude      * sure it is at least minIndexToOverflowCorrect.
1026*5ff13fbcSAllan Jude      */
1027*5ff13fbcSAllan Jude     U32 const adjustment = window.nbOverflowCorrections + 1;
1028*5ff13fbcSAllan Jude     U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,
1029*5ff13fbcSAllan Jude                                   minIndexToOverflowCorrect);
1030*5ff13fbcSAllan Jude     U32 const indexLargeEnough = curr > adjustedIndex;
1031*5ff13fbcSAllan Jude 
1032*5ff13fbcSAllan Jude     /* Only overflow correct early if the dictionary is invalidated already,
1033*5ff13fbcSAllan Jude      * so we don't hurt compression ratio.
1034*5ff13fbcSAllan Jude      */
1035*5ff13fbcSAllan Jude     U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;
1036*5ff13fbcSAllan Jude 
1037*5ff13fbcSAllan Jude     return indexLargeEnough && dictionaryInvalidated;
1038*5ff13fbcSAllan Jude }
1039*5ff13fbcSAllan Jude 
10400f743729SConrad Meyer /**
104119fcbaf1SConrad Meyer  * ZSTD_window_needOverflowCorrection():
104219fcbaf1SConrad Meyer  * Returns non-zero if the indices are getting too large and need overflow
104319fcbaf1SConrad Meyer  * protection.
104419fcbaf1SConrad Meyer  */
ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,U32 cycleLog,U32 maxDist,U32 loadedDictEnd,void const * src,void const * srcEnd)104519fcbaf1SConrad Meyer MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
1046*5ff13fbcSAllan Jude                                                   U32 cycleLog,
1047*5ff13fbcSAllan Jude                                                   U32 maxDist,
1048*5ff13fbcSAllan Jude                                                   U32 loadedDictEnd,
1049*5ff13fbcSAllan Jude                                                   void const* src,
105019fcbaf1SConrad Meyer                                                   void const* srcEnd)
105119fcbaf1SConrad Meyer {
1052f7cd7fe5SConrad Meyer     U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
1053*5ff13fbcSAllan Jude     if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
1054*5ff13fbcSAllan Jude         if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {
1055*5ff13fbcSAllan Jude             return 1;
1056*5ff13fbcSAllan Jude         }
1057*5ff13fbcSAllan Jude     }
1058f7cd7fe5SConrad Meyer     return curr > ZSTD_CURRENT_MAX;
105919fcbaf1SConrad Meyer }
106019fcbaf1SConrad Meyer 
106119fcbaf1SConrad Meyer /**
106219fcbaf1SConrad Meyer  * ZSTD_window_correctOverflow():
106319fcbaf1SConrad Meyer  * Reduces the indices to protect from index overflow.
106419fcbaf1SConrad Meyer  * Returns the correction made to the indices, which must be applied to every
106519fcbaf1SConrad Meyer  * stored index.
106619fcbaf1SConrad Meyer  *
106719fcbaf1SConrad Meyer  * The least significant cycleLog bits of the indices must remain the same,
106819fcbaf1SConrad Meyer  * which may be 0. Every index up to maxDist in the past must be valid.
106919fcbaf1SConrad Meyer  */
ZSTD_window_correctOverflow(ZSTD_window_t * window,U32 cycleLog,U32 maxDist,void const * src)107019fcbaf1SConrad Meyer MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
107119fcbaf1SConrad Meyer                                            U32 maxDist, void const* src)
107219fcbaf1SConrad Meyer {
107319fcbaf1SConrad Meyer     /* preemptive overflow correction:
107419fcbaf1SConrad Meyer      * 1. correction is large enough:
107519fcbaf1SConrad Meyer      *    lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog
107619fcbaf1SConrad Meyer      *    1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog
107719fcbaf1SConrad Meyer      *
107819fcbaf1SConrad Meyer      *    current - newCurrent
107919fcbaf1SConrad Meyer      *    > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)
108019fcbaf1SConrad Meyer      *    > (3<<29) - (1<<chainLog)
108119fcbaf1SConrad Meyer      *    > (3<<29) - (1<<30)             (NOTE: chainLog <= 30)
108219fcbaf1SConrad Meyer      *    > 1<<29
108319fcbaf1SConrad Meyer      *
108419fcbaf1SConrad Meyer      * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:
108519fcbaf1SConrad Meyer      *    After correction, current is less than (1<<chainLog + 1<<windowLog).
108619fcbaf1SConrad Meyer      *    In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.
108719fcbaf1SConrad Meyer      *    In 32-bit mode we are safe, because (chainLog <= 29), so
108819fcbaf1SConrad Meyer      *    ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.
108919fcbaf1SConrad Meyer      * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
109019fcbaf1SConrad Meyer      *    windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
109119fcbaf1SConrad Meyer      */
1092*5ff13fbcSAllan Jude     U32 const cycleSize = 1u << cycleLog;
1093*5ff13fbcSAllan Jude     U32 const cycleMask = cycleSize - 1;
1094f7cd7fe5SConrad Meyer     U32 const curr = (U32)((BYTE const*)src - window->base);
1095*5ff13fbcSAllan Jude     U32 const currentCycle = curr & cycleMask;
1096*5ff13fbcSAllan Jude     /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */
1097*5ff13fbcSAllan Jude     U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX
1098*5ff13fbcSAllan Jude                                      ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)
1099*5ff13fbcSAllan Jude                                      : 0;
1100*5ff13fbcSAllan Jude     U32 const newCurrent = currentCycle
1101*5ff13fbcSAllan Jude                          + currentCycleCorrection
1102*5ff13fbcSAllan Jude                          + MAX(maxDist, cycleSize);
1103f7cd7fe5SConrad Meyer     U32 const correction = curr - newCurrent;
1104*5ff13fbcSAllan Jude     /* maxDist must be a power of two so that:
1105*5ff13fbcSAllan Jude      *   (newCurrent & cycleMask) == (curr & cycleMask)
1106*5ff13fbcSAllan Jude      * This is required to not corrupt the chains / binary tree.
1107*5ff13fbcSAllan Jude      */
1108*5ff13fbcSAllan Jude     assert((maxDist & (maxDist - 1)) == 0);
1109*5ff13fbcSAllan Jude     assert((curr & cycleMask) == (newCurrent & cycleMask));
1110f7cd7fe5SConrad Meyer     assert(curr > newCurrent);
1111*5ff13fbcSAllan Jude     if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
111219fcbaf1SConrad Meyer         /* Loose bound, should be around 1<<29 (see above) */
111319fcbaf1SConrad Meyer         assert(correction > 1<<28);
1114*5ff13fbcSAllan Jude     }
111519fcbaf1SConrad Meyer 
111619fcbaf1SConrad Meyer     window->base += correction;
111719fcbaf1SConrad Meyer     window->dictBase += correction;
1118*5ff13fbcSAllan Jude     if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {
1119*5ff13fbcSAllan Jude         window->lowLimit = ZSTD_WINDOW_START_INDEX;
1120*5ff13fbcSAllan Jude     } else {
1121*5ff13fbcSAllan Jude         window->lowLimit -= correction;
1122*5ff13fbcSAllan Jude     }
1123*5ff13fbcSAllan Jude     if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {
1124*5ff13fbcSAllan Jude         window->dictLimit = ZSTD_WINDOW_START_INDEX;
1125*5ff13fbcSAllan Jude     } else {
1126*5ff13fbcSAllan Jude         window->dictLimit -= correction;
1127*5ff13fbcSAllan Jude     }
112837f1f268SConrad Meyer 
112937f1f268SConrad Meyer     /* Ensure we can still reference the full window. */
113037f1f268SConrad Meyer     assert(newCurrent >= maxDist);
1131*5ff13fbcSAllan Jude     assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);
113237f1f268SConrad Meyer     /* Ensure that lowLimit and dictLimit didn't underflow. */
113337f1f268SConrad Meyer     assert(window->lowLimit <= newCurrent);
113437f1f268SConrad Meyer     assert(window->dictLimit <= newCurrent);
113519fcbaf1SConrad Meyer 
1136*5ff13fbcSAllan Jude     ++window->nbOverflowCorrections;
1137*5ff13fbcSAllan Jude 
113819fcbaf1SConrad Meyer     DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
113919fcbaf1SConrad Meyer              window->lowLimit);
114019fcbaf1SConrad Meyer     return correction;
114119fcbaf1SConrad Meyer }
114219fcbaf1SConrad Meyer 
114319fcbaf1SConrad Meyer /**
114419fcbaf1SConrad Meyer  * ZSTD_window_enforceMaxDist():
114519fcbaf1SConrad Meyer  * Updates lowLimit so that:
114619fcbaf1SConrad Meyer  *    (srcEnd - base) - lowLimit == maxDist + loadedDictEnd
11470f743729SConrad Meyer  *
11484d3f1eafSConrad Meyer  * It ensures index is valid as long as index >= lowLimit.
11494d3f1eafSConrad Meyer  * This must be called before a block compression call.
11500f743729SConrad Meyer  *
11514d3f1eafSConrad Meyer  * loadedDictEnd is only defined if a dictionary is in use for current compression.
11524d3f1eafSConrad Meyer  * As the name implies, loadedDictEnd represents the index at end of dictionary.
11534d3f1eafSConrad Meyer  * The value lies within context's referential, it can be directly compared to blockEndIdx.
11540f743729SConrad Meyer  *
11554d3f1eafSConrad Meyer  * If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.
11564d3f1eafSConrad Meyer  * If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.
11574d3f1eafSConrad Meyer  * This is because dictionaries are allowed to be referenced fully
11584d3f1eafSConrad Meyer  * as long as the last byte of the dictionary is in the window.
11594d3f1eafSConrad Meyer  * Once input has progressed beyond window size, dictionary cannot be referenced anymore.
11604d3f1eafSConrad Meyer  *
11614d3f1eafSConrad Meyer  * In normal dict mode, the dictionary lies between lowLimit and dictLimit.
11624d3f1eafSConrad Meyer  * In dictMatchState mode, lowLimit and dictLimit are the same,
11634d3f1eafSConrad Meyer  * and the dictionary is below them.
11644d3f1eafSConrad Meyer  * forceWindow and dictMatchState are therefore incompatible.
116519fcbaf1SConrad Meyer  */
1166a0483764SConrad Meyer MEM_STATIC void
ZSTD_window_enforceMaxDist(ZSTD_window_t * window,const void * blockEnd,U32 maxDist,U32 * loadedDictEndPtr,const ZSTD_matchState_t ** dictMatchStatePtr)1167a0483764SConrad Meyer ZSTD_window_enforceMaxDist(ZSTD_window_t* window,
11684d3f1eafSConrad Meyer                      const void* blockEnd,
1169a0483764SConrad Meyer                            U32   maxDist,
11700f743729SConrad Meyer                            U32*  loadedDictEndPtr,
11710f743729SConrad Meyer                      const ZSTD_matchState_t** dictMatchStatePtr)
117219fcbaf1SConrad Meyer {
11734d3f1eafSConrad Meyer     U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
11744d3f1eafSConrad Meyer     U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;
11754d3f1eafSConrad Meyer     DEBUGLOG(5, "ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
11764d3f1eafSConrad Meyer                 (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
11774d3f1eafSConrad Meyer 
11784d3f1eafSConrad Meyer     /* - When there is no dictionary : loadedDictEnd == 0.
11794d3f1eafSConrad Meyer          In which case, the test (blockEndIdx > maxDist) is merely to avoid
11804d3f1eafSConrad Meyer          overflowing next operation `newLowLimit = blockEndIdx - maxDist`.
11814d3f1eafSConrad Meyer        - When there is a standard dictionary :
11824d3f1eafSConrad Meyer          Index referential is copied from the dictionary,
11834d3f1eafSConrad Meyer          which means it starts from 0.
11844d3f1eafSConrad Meyer          In which case, loadedDictEnd == dictSize,
11854d3f1eafSConrad Meyer          and it makes sense to compare `blockEndIdx > maxDist + dictSize`
11864d3f1eafSConrad Meyer          since `blockEndIdx` also starts from zero.
11874d3f1eafSConrad Meyer        - When there is an attached dictionary :
11884d3f1eafSConrad Meyer          loadedDictEnd is expressed within the referential of the context,
11894d3f1eafSConrad Meyer          so it can be directly compared against blockEndIdx.
11904d3f1eafSConrad Meyer     */
1191a0483764SConrad Meyer     if (blockEndIdx > maxDist + loadedDictEnd) {
1192a0483764SConrad Meyer         U32 const newLowLimit = blockEndIdx - maxDist;
119319fcbaf1SConrad Meyer         if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;
119419fcbaf1SConrad Meyer         if (window->dictLimit < window->lowLimit) {
11950f743729SConrad Meyer             DEBUGLOG(5, "Update dictLimit to match lowLimit, from %u to %u",
1196a0483764SConrad Meyer                         (unsigned)window->dictLimit, (unsigned)window->lowLimit);
119719fcbaf1SConrad Meyer             window->dictLimit = window->lowLimit;
119819fcbaf1SConrad Meyer         }
11994d3f1eafSConrad Meyer         /* On reaching window size, dictionaries are invalidated */
12004d3f1eafSConrad Meyer         if (loadedDictEndPtr) *loadedDictEndPtr = 0;
12014d3f1eafSConrad Meyer         if (dictMatchStatePtr) *dictMatchStatePtr = NULL;
12024d3f1eafSConrad Meyer     }
12034d3f1eafSConrad Meyer }
12044d3f1eafSConrad Meyer 
12054d3f1eafSConrad Meyer /* Similar to ZSTD_window_enforceMaxDist(),
12064d3f1eafSConrad Meyer  * but only invalidates dictionary
12079cbefe25SConrad Meyer  * when input progresses beyond window size.
12089cbefe25SConrad Meyer  * assumption : loadedDictEndPtr and dictMatchStatePtr are valid (non NULL)
12099cbefe25SConrad Meyer  *              loadedDictEnd uses same referential as window->base
12109cbefe25SConrad Meyer  *              maxDist is the window size */
12114d3f1eafSConrad Meyer MEM_STATIC void
ZSTD_checkDictValidity(const ZSTD_window_t * window,const void * blockEnd,U32 maxDist,U32 * loadedDictEndPtr,const ZSTD_matchState_t ** dictMatchStatePtr)12129cbefe25SConrad Meyer ZSTD_checkDictValidity(const ZSTD_window_t* window,
12134d3f1eafSConrad Meyer                        const void* blockEnd,
12144d3f1eafSConrad Meyer                              U32   maxDist,
12154d3f1eafSConrad Meyer                              U32*  loadedDictEndPtr,
12164d3f1eafSConrad Meyer                        const ZSTD_matchState_t** dictMatchStatePtr)
12174d3f1eafSConrad Meyer {
12189cbefe25SConrad Meyer     assert(loadedDictEndPtr != NULL);
12199cbefe25SConrad Meyer     assert(dictMatchStatePtr != NULL);
12209cbefe25SConrad Meyer     {   U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);
12219cbefe25SConrad Meyer         U32 const loadedDictEnd = *loadedDictEndPtr;
12224d3f1eafSConrad Meyer         DEBUGLOG(5, "ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u",
12234d3f1eafSConrad Meyer                     (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
12249cbefe25SConrad Meyer         assert(blockEndIdx >= loadedDictEnd);
12254d3f1eafSConrad Meyer 
12269cbefe25SConrad Meyer         if (blockEndIdx > loadedDictEnd + maxDist) {
12279cbefe25SConrad Meyer             /* On reaching window size, dictionaries are invalidated.
12289cbefe25SConrad Meyer              * For simplification, if window size is reached anywhere within next block,
12299cbefe25SConrad Meyer              * the dictionary is invalidated for the full block.
12309cbefe25SConrad Meyer              */
12319cbefe25SConrad Meyer             DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)");
12329cbefe25SConrad Meyer             *loadedDictEndPtr = 0;
12339cbefe25SConrad Meyer             *dictMatchStatePtr = NULL;
12349cbefe25SConrad Meyer         } else {
12359cbefe25SConrad Meyer             if (*loadedDictEndPtr != 0) {
12369cbefe25SConrad Meyer                 DEBUGLOG(6, "dictionary considered valid for current block");
12379cbefe25SConrad Meyer     }   }   }
123819fcbaf1SConrad Meyer }
123919fcbaf1SConrad Meyer 
ZSTD_window_init(ZSTD_window_t * window)124037f1f268SConrad Meyer MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
1241f7cd7fe5SConrad Meyer     ZSTD_memset(window, 0, sizeof(*window));
124237f1f268SConrad Meyer     window->base = (BYTE const*)" ";
124337f1f268SConrad Meyer     window->dictBase = (BYTE const*)" ";
1244*5ff13fbcSAllan Jude     ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */
1245*5ff13fbcSAllan Jude     window->dictLimit = ZSTD_WINDOW_START_INDEX;    /* start from >0, so that 1st position is valid */
1246*5ff13fbcSAllan Jude     window->lowLimit = ZSTD_WINDOW_START_INDEX;     /* it ensures first and later CCtx usages compress the same */
1247*5ff13fbcSAllan Jude     window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX;   /* see issue #1241 */
1248*5ff13fbcSAllan Jude     window->nbOverflowCorrections = 0;
124937f1f268SConrad Meyer }
125037f1f268SConrad Meyer 
125119fcbaf1SConrad Meyer /**
125219fcbaf1SConrad Meyer  * ZSTD_window_update():
125319fcbaf1SConrad Meyer  * Updates the window by appending [src, src + srcSize) to the window.
125419fcbaf1SConrad Meyer  * If it is not contiguous, the current prefix becomes the extDict, and we
125519fcbaf1SConrad Meyer  * forget about the extDict. Handles overlap of the prefix and extDict.
125619fcbaf1SConrad Meyer  * Returns non-zero if the segment is contiguous.
125719fcbaf1SConrad Meyer  */
ZSTD_window_update(ZSTD_window_t * window,void const * src,size_t srcSize,int forceNonContiguous)125819fcbaf1SConrad Meyer MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
1259*5ff13fbcSAllan Jude                                   void const* src, size_t srcSize,
1260*5ff13fbcSAllan Jude                                   int forceNonContiguous)
126119fcbaf1SConrad Meyer {
126219fcbaf1SConrad Meyer     BYTE const* const ip = (BYTE const*)src;
126319fcbaf1SConrad Meyer     U32 contiguous = 1;
12640f743729SConrad Meyer     DEBUGLOG(5, "ZSTD_window_update");
126537f1f268SConrad Meyer     if (srcSize == 0)
126637f1f268SConrad Meyer         return contiguous;
126737f1f268SConrad Meyer     assert(window->base != NULL);
126837f1f268SConrad Meyer     assert(window->dictBase != NULL);
126919fcbaf1SConrad Meyer     /* Check if blocks follow each other */
1270*5ff13fbcSAllan Jude     if (src != window->nextSrc || forceNonContiguous) {
127119fcbaf1SConrad Meyer         /* not contiguous */
127219fcbaf1SConrad Meyer         size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
12730f743729SConrad Meyer         DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
127419fcbaf1SConrad Meyer         window->lowLimit = window->dictLimit;
127519fcbaf1SConrad Meyer         assert(distanceFromBase == (size_t)(U32)distanceFromBase);  /* should never overflow */
127619fcbaf1SConrad Meyer         window->dictLimit = (U32)distanceFromBase;
127719fcbaf1SConrad Meyer         window->dictBase = window->base;
127819fcbaf1SConrad Meyer         window->base = ip - distanceFromBase;
127937f1f268SConrad Meyer         /* ms->nextToUpdate = window->dictLimit; */
128019fcbaf1SConrad Meyer         if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit;   /* too small extDict */
128119fcbaf1SConrad Meyer         contiguous = 0;
128219fcbaf1SConrad Meyer     }
128319fcbaf1SConrad Meyer     window->nextSrc = ip + srcSize;
128419fcbaf1SConrad Meyer     /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */
128519fcbaf1SConrad Meyer     if ( (ip+srcSize > window->dictBase + window->lowLimit)
128619fcbaf1SConrad Meyer        & (ip < window->dictBase + window->dictLimit)) {
128719fcbaf1SConrad Meyer         ptrdiff_t const highInputIdx = (ip + srcSize) - window->dictBase;
128819fcbaf1SConrad Meyer         U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;
128919fcbaf1SConrad Meyer         window->lowLimit = lowLimitMax;
12900f743729SConrad Meyer         DEBUGLOG(5, "Overlapping extDict and input : new lowLimit = %u", window->lowLimit);
129119fcbaf1SConrad Meyer     }
129219fcbaf1SConrad Meyer     return contiguous;
129319fcbaf1SConrad Meyer }
129419fcbaf1SConrad Meyer 
129537f1f268SConrad Meyer /**
129637f1f268SConrad Meyer  * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.
129737f1f268SConrad Meyer  */
ZSTD_getLowestMatchIndex(const ZSTD_matchState_t * ms,U32 curr,unsigned windowLog)1298f7cd7fe5SConrad Meyer MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
12999cbefe25SConrad Meyer {
13009cbefe25SConrad Meyer     U32 const maxDistance = 1U << windowLog;
13019cbefe25SConrad Meyer     U32 const lowestValid = ms->window.lowLimit;
1302f7cd7fe5SConrad Meyer     U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
13039cbefe25SConrad Meyer     U32 const isDictionary = (ms->loadedDictEnd != 0);
1304f7cd7fe5SConrad Meyer     /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
1305f7cd7fe5SConrad Meyer      * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
1306f7cd7fe5SConrad Meyer      * valid for the entire block. So this check is sufficient to find the lowest valid match index.
1307f7cd7fe5SConrad Meyer      */
13089cbefe25SConrad Meyer     U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
13099cbefe25SConrad Meyer     return matchLowest;
13109cbefe25SConrad Meyer }
13119cbefe25SConrad Meyer 
131237f1f268SConrad Meyer /**
131337f1f268SConrad Meyer  * Returns the lowest allowed match index in the prefix.
131437f1f268SConrad Meyer  */
ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t * ms,U32 curr,unsigned windowLog)1315f7cd7fe5SConrad Meyer MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
131637f1f268SConrad Meyer {
131737f1f268SConrad Meyer     U32    const maxDistance = 1U << windowLog;
131837f1f268SConrad Meyer     U32    const lowestValid = ms->window.dictLimit;
1319f7cd7fe5SConrad Meyer     U32    const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
132037f1f268SConrad Meyer     U32    const isDictionary = (ms->loadedDictEnd != 0);
1321f7cd7fe5SConrad Meyer     /* When computing the lowest prefix index we need to take the dictionary into account to handle
1322f7cd7fe5SConrad Meyer      * the edge case where the dictionary and the source are contiguous in memory.
1323f7cd7fe5SConrad Meyer      */
132437f1f268SConrad Meyer     U32    const matchLowest = isDictionary ? lowestValid : withinWindow;
132537f1f268SConrad Meyer     return matchLowest;
132637f1f268SConrad Meyer }
132737f1f268SConrad Meyer 
13289cbefe25SConrad Meyer 
13290f743729SConrad Meyer 
13300f743729SConrad Meyer /* debug functions */
1331a0483764SConrad Meyer #if (DEBUGLEVEL>=2)
13320f743729SConrad Meyer 
ZSTD_fWeight(U32 rawStat)13330f743729SConrad Meyer MEM_STATIC double ZSTD_fWeight(U32 rawStat)
13340f743729SConrad Meyer {
13350f743729SConrad Meyer     U32 const fp_accuracy = 8;
13360f743729SConrad Meyer     U32 const fp_multiplier = (1 << fp_accuracy);
1337a0483764SConrad Meyer     U32 const newStat = rawStat + 1;
1338a0483764SConrad Meyer     U32 const hb = ZSTD_highbit32(newStat);
13390f743729SConrad Meyer     U32 const BWeight = hb * fp_multiplier;
1340a0483764SConrad Meyer     U32 const FWeight = (newStat << fp_accuracy) >> hb;
13410f743729SConrad Meyer     U32 const weight = BWeight + FWeight;
13420f743729SConrad Meyer     assert(hb + fp_accuracy < 31);
13430f743729SConrad Meyer     return (double)weight / fp_multiplier;
13440f743729SConrad Meyer }
13450f743729SConrad Meyer 
1346a0483764SConrad Meyer /* display a table content,
1347a0483764SConrad Meyer  * listing each element, its frequency, and its predicted bit cost */
ZSTD_debugTable(const U32 * table,U32 max)13480f743729SConrad Meyer MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)
13490f743729SConrad Meyer {
13500f743729SConrad Meyer     unsigned u, sum;
13510f743729SConrad Meyer     for (u=0, sum=0; u<=max; u++) sum += table[u];
13520f743729SConrad Meyer     DEBUGLOG(2, "total nb elts: %u", sum);
13530f743729SConrad Meyer     for (u=0; u<=max; u++) {
13540f743729SConrad Meyer         DEBUGLOG(2, "%2u: %5u  (%.2f)",
13550f743729SConrad Meyer                 u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );
13560f743729SConrad Meyer     }
13570f743729SConrad Meyer }
13580f743729SConrad Meyer 
1359a0483764SConrad Meyer #endif
1360a0483764SConrad Meyer 
1361a0483764SConrad Meyer 
1362052d3c12SConrad Meyer #if defined (__cplusplus)
1363052d3c12SConrad Meyer }
1364052d3c12SConrad Meyer #endif
1365052d3c12SConrad Meyer 
136637f1f268SConrad Meyer /* ===============================================================
136737f1f268SConrad Meyer  * Shared internal declarations
136837f1f268SConrad Meyer  * These prototypes may be called from sources not in lib/compress
136937f1f268SConrad Meyer  * =============================================================== */
137037f1f268SConrad Meyer 
137137f1f268SConrad Meyer /* ZSTD_loadCEntropy() :
137237f1f268SConrad Meyer  * dict : must point at beginning of a valid zstd dictionary.
137337f1f268SConrad Meyer  * return : size of dictionary header (size of magic number + dict ID + entropy tables)
137437f1f268SConrad Meyer  * assumptions : magic number supposed already checked
137537f1f268SConrad Meyer  *               and dictSize >= 8 */
137637f1f268SConrad Meyer size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,
137737f1f268SConrad Meyer                          const void* const dict, size_t dictSize);
137837f1f268SConrad Meyer 
137937f1f268SConrad Meyer void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);
1380052d3c12SConrad Meyer 
1381052d3c12SConrad Meyer /* ==============================================================
1382052d3c12SConrad Meyer  * Private declarations
1383052d3c12SConrad Meyer  * These prototypes shall only be called from within lib/compress
1384052d3c12SConrad Meyer  * ============================================================== */
1385052d3c12SConrad Meyer 
138619fcbaf1SConrad Meyer /* ZSTD_getCParamsFromCCtxParams() :
138719fcbaf1SConrad Meyer  * cParams are built depending on compressionLevel, src size hints,
138819fcbaf1SConrad Meyer  * LDM and manually set compression parameters.
138937f1f268SConrad Meyer  * Note: srcSizeHint == 0 means 0!
139019fcbaf1SConrad Meyer  */
139119fcbaf1SConrad Meyer ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
1392f7cd7fe5SConrad Meyer         const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
139319fcbaf1SConrad Meyer 
1394052d3c12SConrad Meyer /*! ZSTD_initCStream_internal() :
1395052d3c12SConrad Meyer  *  Private use only. Init streaming operation.
1396052d3c12SConrad Meyer  *  expects params to be valid.
1397052d3c12SConrad Meyer  *  must receive dict, or cdict, or none, but not both.
1398052d3c12SConrad Meyer  *  @return : 0, or an error code */
1399052d3c12SConrad Meyer size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
1400052d3c12SConrad Meyer                      const void* dict, size_t dictSize,
1401052d3c12SConrad Meyer                      const ZSTD_CDict* cdict,
14029cbefe25SConrad Meyer                      const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize);
1403052d3c12SConrad Meyer 
14040f743729SConrad Meyer void ZSTD_resetSeqStore(seqStore_t* ssPtr);
14050f743729SConrad Meyer 
1406052d3c12SConrad Meyer /*! ZSTD_getCParamsFromCDict() :
1407052d3c12SConrad Meyer  *  as the name implies */
1408052d3c12SConrad Meyer ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);
1409052d3c12SConrad Meyer 
1410052d3c12SConrad Meyer /* ZSTD_compressBegin_advanced_internal() :
1411052d3c12SConrad Meyer  * Private use only. To be called from zstdmt_compress.c. */
1412052d3c12SConrad Meyer size_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,
1413052d3c12SConrad Meyer                                     const void* dict, size_t dictSize,
141419fcbaf1SConrad Meyer                                     ZSTD_dictContentType_e dictContentType,
14150f743729SConrad Meyer                                     ZSTD_dictTableLoadMethod_e dtlm,
1416052d3c12SConrad Meyer                                     const ZSTD_CDict* cdict,
14179cbefe25SConrad Meyer                                     const ZSTD_CCtx_params* params,
1418052d3c12SConrad Meyer                                     unsigned long long pledgedSrcSize);
1419052d3c12SConrad Meyer 
1420052d3c12SConrad Meyer /* ZSTD_compress_advanced_internal() :
1421052d3c12SConrad Meyer  * Private use only. To be called from zstdmt_compress.c. */
1422052d3c12SConrad Meyer size_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,
1423052d3c12SConrad Meyer                                        void* dst, size_t dstCapacity,
1424052d3c12SConrad Meyer                                  const void* src, size_t srcSize,
1425052d3c12SConrad Meyer                                  const void* dict,size_t dictSize,
14269cbefe25SConrad Meyer                                  const ZSTD_CCtx_params* params);
1427052d3c12SConrad Meyer 
142819fcbaf1SConrad Meyer 
142919fcbaf1SConrad Meyer /* ZSTD_writeLastEmptyBlock() :
143019fcbaf1SConrad Meyer  * output an empty Block with end-of-frame mark to complete a frame
143119fcbaf1SConrad Meyer  * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))
14322b9c00cbSConrad Meyer  *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)
143319fcbaf1SConrad Meyer  */
143419fcbaf1SConrad Meyer size_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);
143519fcbaf1SConrad Meyer 
143619fcbaf1SConrad Meyer 
143719fcbaf1SConrad Meyer /* ZSTD_referenceExternalSequences() :
143819fcbaf1SConrad Meyer  * Must be called before starting a compression operation.
143919fcbaf1SConrad Meyer  * seqs must parse a prefix of the source.
144019fcbaf1SConrad Meyer  * This cannot be used when long range matching is enabled.
144119fcbaf1SConrad Meyer  * Zstd will use these sequences, and pass the literals to a secondary block
144219fcbaf1SConrad Meyer  * compressor.
144319fcbaf1SConrad Meyer  * @return : An error code on failure.
144419fcbaf1SConrad Meyer  * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory
144519fcbaf1SConrad Meyer  * access and data corruption.
144619fcbaf1SConrad Meyer  */
144719fcbaf1SConrad Meyer size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);
144819fcbaf1SConrad Meyer 
144937f1f268SConrad Meyer /** ZSTD_cycleLog() :
145037f1f268SConrad Meyer  *  condition for correct operation : hashLog > 1 */
1451bcae12b5SConrad Meyer /* Begin FreeBSD - This symbol is needed by dll-linked CLI zstd(1). */
1452bcae12b5SConrad Meyer ZSTDLIB_API
1453bcae12b5SConrad Meyer /* End FreeBSD */
1454bcae12b5SConrad Meyer U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
145519fcbaf1SConrad Meyer 
1456*5ff13fbcSAllan Jude /** ZSTD_CCtx_trace() :
1457*5ff13fbcSAllan Jude  *  Trace the end of a compression call.
1458*5ff13fbcSAllan Jude  */
1459*5ff13fbcSAllan Jude void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
1460*5ff13fbcSAllan Jude 
1461052d3c12SConrad Meyer #endif /* ZSTD_COMPRESS_H */
1462