blob: 3cec2778f793eee90ecd73cdb105f86ffbad9098 [file] [log] [blame]
Yann Colletf3eca252015-10-22 15:31:46 +01001/*
2 ZSTD HC - High Compression Mode of Zstandard
Yann Collet863ec402016-01-28 17:56:33 +01003 Copyright (C) 2015-2016, Yann Collet.
Yann Colletf3eca252015-10-22 15:31:46 +01004
5 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
9 met:
10
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following disclaimer
15 in the documentation and/or other materials provided with the
16 distribution.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 You can contact the author at :
31 - Zstd source repository : https://www.zstd.net
32*/
33
34
Yann Collet4b100f42015-10-30 15:49:48 +010035/* *******************************************************
36* Compiler specifics
37*********************************************************/
38#ifdef _MSC_VER /* Visual Studio */
39# define FORCE_INLINE static __forceinline
40# include <intrin.h> /* For Visual 2005 */
41# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
Yann Collet4b100f42015-10-30 15:49:48 +010042#else
Yann Collet4b100f42015-10-30 15:49:48 +010043# ifdef __GNUC__
44# define FORCE_INLINE static inline __attribute__((always_inline))
45# else
46# define FORCE_INLINE static inline
47# endif
48#endif
49
50
Yann Collet7d360282016-02-12 00:07:30 +010051/*-*************************************
Yann Colletae7aa062016-02-03 02:46:46 +010052* Dependencies
Yann Colletf3eca252015-10-22 15:31:46 +010053***************************************/
54#include <stdlib.h> /* malloc */
55#include <string.h> /* memset */
Yann Collet14983e72015-11-11 21:38:21 +010056#include "mem.h"
57#include "fse_static.h"
Yann Colletafe07092016-01-25 04:10:46 +010058#include "huff0_static.h"
Yann Collet3d9cf7a2015-10-29 17:15:14 +010059#include "zstd_internal.h"
Yann Colletf3eca252015-10-22 15:31:46 +010060
61
Yann Collet7d360282016-02-12 00:07:30 +010062/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +010063* Constants
Yann Colletf3eca252015-10-22 15:31:46 +010064***************************************/
Yann Colletbb604482016-03-19 15:18:42 +010065static const U32 g_searchStrength = 8; /* control skip over incompressible data */
Yann Colletf3eca252015-10-22 15:31:46 +010066
Yann Colletf3eca252015-10-22 15:31:46 +010067
Yann Collet7d360282016-02-12 00:07:30 +010068/*-*************************************
Yann Collet59d1f792016-01-23 19:28:41 +010069* Helper functions
70***************************************/
Yann Collet59d1f792016-01-23 19:28:41 +010071size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
72
73
Yann Collet7d360282016-02-12 00:07:30 +010074/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +010075* Sequence storage
Yann Colletf3eca252015-10-22 15:31:46 +010076***************************************/
Yann Collet14983e72015-11-11 21:38:21 +010077static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
78{
79 ssPtr->offset = ssPtr->offsetStart;
80 ssPtr->lit = ssPtr->litStart;
81 ssPtr->litLength = ssPtr->litLengthStart;
82 ssPtr->matchLength = ssPtr->matchLengthStart;
Yann Collet14983e72015-11-11 21:38:21 +010083}
84
85
Yann Collet7d360282016-02-12 00:07:30 +010086/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +010087* Context memory management
88***************************************/
Yann Collet5be2dd22015-11-11 13:43:58 +010089struct ZSTD_CCtx_s
Yann Colletf3eca252015-10-22 15:31:46 +010090{
Yann Collet89db5e02015-11-13 11:27:46 +010091 const BYTE* nextSrc; /* next block here to continue on current prefix */
Yann Colleteeb8ba12015-10-22 16:55:40 +010092 const BYTE* base; /* All regular indexes relative to this position */
93 const BYTE* dictBase; /* extDict indexes relative to this position */
Yann Colletf3eca252015-10-22 15:31:46 +010094 U32 dictLimit; /* below that point, need extDict */
Yann Colleteeb8ba12015-10-22 16:55:40 +010095 U32 lowLimit; /* below that point, no more data */
Yann Colletf3eca252015-10-22 15:31:46 +010096 U32 nextToUpdate; /* index from which to continue dictionary update */
inikepcc52a972016-02-19 10:09:35 +010097 U32 nextToUpdate3; /* index from which to continue dictionary update */
Yann Collet2ce49232016-02-02 14:36:49 +010098 U32 loadedDictEnd;
Yann Colletecd651b2016-01-07 15:35:18 +010099 U32 stage;
Yann Collet5be2dd22015-11-11 13:43:58 +0100100 ZSTD_parameters params;
Yann Collet712def92015-10-29 18:41:45 +0100101 void* workSpace;
102 size_t workSpaceSize;
Yann Collet120230b2015-12-02 14:00:45 +0100103 size_t blockSize;
Yann Colletecd651b2016-01-07 15:35:18 +0100104 size_t hbSize;
Yann Collet0e491c02016-03-11 21:58:04 +0100105 char headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
Yann Colletecd651b2016-01-07 15:35:18 +0100106
Yann Collet712def92015-10-29 18:41:45 +0100107 seqStore_t seqStore; /* sequences storage ptrs */
Yann Collet083fcc82015-10-25 14:06:35 +0100108 U32* hashTable;
inikepcc52a972016-02-19 10:09:35 +0100109 U32* hashTable3;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100110 U32* contentTable;
Yann Colletb923f652016-01-26 03:14:20 +0100111 HUF_CElt* hufTable;
Yann Colletfb810d62016-01-28 00:18:06 +0100112 U32 flagStaticTables;
113 FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
114 FSE_CTable matchlengthCTable [FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
115 FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
Yann Colletf3eca252015-10-22 15:31:46 +0100116};
117
Yann Collet5be2dd22015-11-11 13:43:58 +0100118ZSTD_CCtx* ZSTD_createCCtx(void)
Yann Colletf3eca252015-10-22 15:31:46 +0100119{
Yann Collet5be2dd22015-11-11 13:43:58 +0100120 return (ZSTD_CCtx*) calloc(1, sizeof(ZSTD_CCtx));
Yann Colletf3eca252015-10-22 15:31:46 +0100121}
122
Yann Collet5be2dd22015-11-11 13:43:58 +0100123size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
Yann Colletf3eca252015-10-22 15:31:46 +0100124{
Yann Collet712def92015-10-29 18:41:45 +0100125 free(cctx->workSpace);
Yann Collet083fcc82015-10-25 14:06:35 +0100126 free(cctx);
Yann Collet982ffc72016-02-05 02:33:10 +0100127 return 0; /* reserved as a potential error code in the future */
Yann Collet083fcc82015-10-25 14:06:35 +0100128}
129
Yann Colletb44be742016-03-26 20:52:14 +0100130const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
Yann Collet7d360282016-02-12 00:07:30 +0100131{
Yann Colletb44be742016-03-26 20:52:14 +0100132 return &(ctx->seqStore);
Yann Collet7d360282016-02-12 00:07:30 +0100133}
134
Yann Collet59d70632015-11-04 12:05:27 +0100135
Yann Collet21588e32016-03-30 16:50:44 +0200136#define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
137#define CLAMPCHECK(val,min,max) { if ((val<min) || (val>max)) return ERROR(compressionParameter_unsupported); }
138
139/** ZSTD_checkParams() :
140 ensure param values remain within authorized range.
141 @return : 0, or an error code if one value is beyond authorized range */
Yann Collet3b719252016-03-30 19:48:05 +0200142size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
Yann Collet21588e32016-03-30 16:50:44 +0200143{
144 { U32 const windowLog_max = MEM_32bits() ? 25 : ZSTD_WINDOWLOG_MAX; /* 32 bits mode cannot flush > 24 bits */
Yann Collet3b719252016-03-30 19:48:05 +0200145 CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, windowLog_max); }
146 CLAMPCHECK(cParams.contentLog, ZSTD_CONTENTLOG_MIN, ZSTD_CONTENTLOG_MAX);
147 CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
148 CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
149 { U32 const searchLengthMin = (cParams.strategy == ZSTD_btopt) ? ZSTD_SEARCHLENGTH_MIN : ZSTD_SEARCHLENGTH_MIN+1;
150 U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
151 CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
152 CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
Yann Collet9bb87e52016-03-30 21:28:15 +0200153 if ((U32)(cParams.strategy) > (U32)ZSTD_btopt) return ERROR(compressionParameter_unsupported);
Yann Collet21588e32016-03-30 16:50:44 +0200154 return 0;
155}
156
157
Yann Collet14983e72015-11-11 21:38:21 +0100158static unsigned ZSTD_highbit(U32 val);
159
Yann Collet3b719252016-03-30 19:48:05 +0200160/** ZSTD_checkCParams_advanced() :
161 temporary work-around, while the compressor compatibility remains limited regarding windowLog < 18 */
162size_t ZSTD_checkCParams_advanced(ZSTD_compressionParameters cParams, U64 srcSize)
163{
164 if (srcSize > (1U << ZSTD_WINDOWLOG_MIN)) return ZSTD_checkCParams(cParams);
165 if (cParams.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) return ERROR(compressionParameter_unsupported);
166 if (srcSize <= (1U << cParams.windowLog)) cParams.windowLog = ZSTD_WINDOWLOG_MIN; /* fake value - temporary work around */
167 if (srcSize <= (1U << cParams.hashLog)) cParams.hashLog = ZSTD_HASHLOG_MIN; /* fake value - temporary work around */
168 if (srcSize <= (1U << cParams.contentLog)) cParams.contentLog = ZSTD_CONTENTLOG_MIN; /* fake value - temporary work around */
169 return ZSTD_checkCParams(cParams);
170}
171
172
Yann Collet21588e32016-03-30 16:50:44 +0200173/** ZSTD_adjustParams() :
174 optimize params for q given input (`srcSize` and `dictSize`).
175 mostly downsizing to reduce memory consumption and initialization.
176 Both `srcSize` and `dictSize` are optional (use 0 if unknown),
177 but if both are 0, no optimization can be done.
178 Note : params is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
Yann Colletdd6466a2016-03-30 20:06:26 +0200179void ZSTD_adjustCParams(ZSTD_compressionParameters* params, U64 srcSize, size_t dictSize)
Yann Collet59d70632015-11-04 12:05:27 +0100180{
Yann Collet21588e32016-03-30 16:50:44 +0200181 if (srcSize+dictSize == 0) return; /* no size information available : no adjustment */
Yann Collet59d70632015-11-04 12:05:27 +0100182
Yann Collet70e45772016-03-19 18:08:32 +0100183 /* resize params, to use less memory when necessary */
Yann Colletdd6466a2016-03-30 20:06:26 +0200184 { U32 const minSrcSize = (srcSize==0) ? 500 : 0;
185 U64 const rSize = srcSize + dictSize + minSrcSize;
Yann Collet21588e32016-03-30 16:50:44 +0200186 if (rSize < (1<<ZSTD_WINDOWLOG_MAX)) {
187 U32 const srcLog = ZSTD_highbit((U32)(rSize)-1) + 1;
188 if (params->windowLog > srcLog) params->windowLog = srcLog;
189 } }
Yann Colletc6eea2b2016-03-19 17:18:00 +0100190 if (params->hashLog > params->windowLog) params->hashLog = params->windowLog;
Yann Collet21588e32016-03-30 16:50:44 +0200191 { U32 const btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_btopt);
192 U32 const maxContentLog = params->windowLog+btPlus;
193 if (params->contentLog > maxContentLog) params->contentLog = maxContentLog; } /* <= ZSTD_CONTENTLOG_MAX */
Yann Colletc6eea2b2016-03-19 17:18:00 +0100194
195 if (params->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) params->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
Yann Collet59d70632015-11-04 12:05:27 +0100196}
197
198
Yann Collet51d50042016-03-30 20:42:19 +0200199size_t ZSTD_sizeofCCtx(ZSTD_compressionParameters cParams) /* hidden interface, for paramagrill */
Yann Collete74215e2016-03-19 16:09:09 +0100200{
201 ZSTD_CCtx* zc = ZSTD_createCCtx();
Yann Collet51d50042016-03-30 20:42:19 +0200202 ZSTD_parameters params;
203 params.cParams = cParams;
204 params.fParams.contentSizeFlag = 1;
Yann Collet3b719252016-03-30 19:48:05 +0200205 ZSTD_compressBegin_advanced(zc, NULL, 0, params, 0);
Yann Colletd64f4352016-03-21 00:07:42 +0100206 { size_t const ccsize = sizeof(*zc) + zc->workSpaceSize;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100207 ZSTD_freeCCtx(zc);
Yann Colletd64f4352016-03-21 00:07:42 +0100208 return ccsize; }
Yann Collet2e91dde2016-03-08 12:22:11 +0100209}
210
211
Yann Collet5be2dd22015-11-11 13:43:58 +0100212static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
Yann Collet88fcd292015-11-25 14:42:45 +0100213 ZSTD_parameters params)
Yann Collet863ec402016-01-28 17:56:33 +0100214{ /* note : params considered validated here */
Yann Collet3b719252016-03-30 19:48:05 +0200215 const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
216 const U32 divider = (params.cParams.searchLength==3) ? 3 : 4;
Yann Colletdd54bbc2016-03-08 02:35:34 +0100217 const size_t maxNbSeq = blockSize / divider;
Yann Colletbe391432016-03-22 23:19:28 +0100218 const size_t tokenSpace = blockSize + 11*maxNbSeq;
Yann Collet3b719252016-03-30 19:48:05 +0200219 const size_t contentSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.contentLog);
220 const size_t hSize = 1 << params.cParams.hashLog;
221 const size_t h3Size = (params.cParams.searchLength==3) ? (1 << HASHLOG3) : 0;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100222 const size_t tableSpace = (contentSize + hSize + h3Size) * sizeof(U32);
inikep87d4f3d2016-03-02 15:56:24 +0100223
Yann Collete74215e2016-03-19 16:09:09 +0100224 /* Check if workSpace is large enough, alloc a new one if needed */
Yann Colletbe391432016-03-22 23:19:28 +0100225 { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (1<<Offbits) + (1<<Litbits))*sizeof(U32)
Yann Collete74215e2016-03-19 16:09:09 +0100226 + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
227 size_t const neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
Yann Collet3b719252016-03-30 19:48:05 +0200228 + ((params.cParams.strategy == ZSTD_btopt) ? optSpace : 0);
Yann Collete74215e2016-03-19 16:09:09 +0100229 if (zc->workSpaceSize < neededSpace) {
230 free(zc->workSpace);
231 zc->workSpace = malloc(neededSpace);
232 if (zc->workSpace == NULL) return ERROR(memory_allocation);
233 zc->workSpaceSize = neededSpace;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100234 } }
Yann Collete74215e2016-03-19 16:09:09 +0100235
Yann Collet863ec402016-01-28 17:56:33 +0100236 memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
inikepcc52a972016-02-19 10:09:35 +0100237 zc->hashTable3 = (U32*)(zc->workSpace);
Yann Collete74215e2016-03-19 16:09:09 +0100238 zc->hashTable = zc->hashTable3 + h3Size;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100239 zc->contentTable = zc->hashTable + hSize;
240 zc->seqStore.buffer = zc->contentTable + contentSize;
Yann Collet863ec402016-01-28 17:56:33 +0100241 zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
242 zc->flagStaticTables = 0;
Yann Collet597847a2016-03-20 19:14:22 +0100243 zc->seqStore.buffer = ((U32*)(zc->seqStore.buffer)) + 256;
Yann Collet083fcc82015-10-25 14:06:35 +0100244
Yann Colletf48e35c2015-11-07 01:13:31 +0100245 zc->nextToUpdate = 1;
Yann Collet89db5e02015-11-13 11:27:46 +0100246 zc->nextSrc = NULL;
Yann Collet2acb5d32015-10-29 16:49:43 +0100247 zc->base = NULL;
248 zc->dictBase = NULL;
249 zc->dictLimit = 0;
250 zc->lowLimit = 0;
Yann Collet083fcc82015-10-25 14:06:35 +0100251 zc->params = params;
Yann Collet120230b2015-12-02 14:00:45 +0100252 zc->blockSize = blockSize;
Yann Collet70e8c382016-02-10 13:37:52 +0100253
Yann Collet3b719252016-03-30 19:48:05 +0200254 if (params.cParams.strategy == ZSTD_btopt) {
Yann Collet72d706a2016-03-23 20:44:12 +0100255 zc->seqStore.litFreq = (U32*)(zc->seqStore.buffer);
256 zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
257 zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
258 zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
259 zc->seqStore.matchTable = (ZSTD_match_t*)((void*)(zc->seqStore.offCodeFreq + (1<<Offbits)));
260 zc->seqStore.priceTable = (ZSTD_optimal_t*)((void*)(zc->seqStore.matchTable + ZSTD_OPT_NUM+1));
261 zc->seqStore.buffer = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
262 zc->seqStore.litLengthSum = 0;
263 }
inikep87d4f3d2016-03-02 15:56:24 +0100264 zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
Yann Collet597847a2016-03-20 19:14:22 +0100265 zc->seqStore.litLengthStart = (U16*) (void*)(zc->seqStore.offsetStart + maxNbSeq);
Yann Colletfadda6c2016-03-22 12:14:26 +0100266 zc->seqStore.matchLengthStart = (U16*) (void*)(zc->seqStore.litLengthStart + maxNbSeq);
267 zc->seqStore.llCodeStart = (BYTE*) (zc->seqStore.matchLengthStart + maxNbSeq);
268 zc->seqStore.mlCodeStart = zc->seqStore.llCodeStart + maxNbSeq;
269 zc->seqStore.offCodeStart = zc->seqStore.mlCodeStart + maxNbSeq;
Yann Colletdd54bbc2016-03-08 02:35:34 +0100270 zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
inikep5cccd772016-03-02 20:37:49 +0100271
Yann Colletecd651b2016-01-07 15:35:18 +0100272 zc->hbSize = 0;
Yann Collet60096272016-01-08 17:27:50 +0100273 zc->stage = 0;
Yann Collet2ce49232016-02-02 14:36:49 +0100274 zc->loadedDictEnd = 0;
Yann Collet2acb5d32015-10-29 16:49:43 +0100275
Yann Collet4114f952015-10-30 06:40:22 +0100276 return 0;
Yann Colletf3eca252015-10-22 15:31:46 +0100277}
278
Yann Collet083fcc82015-10-25 14:06:35 +0100279
Yann Collet370b08e2016-03-08 00:03:59 +0100280/*! ZSTD_copyCCtx() :
281* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
282* Only works during stage 0 (i.e. before first call to ZSTD_compressContinue()).
Yann Collet7b51a292016-01-26 15:58:49 +0100283* @return : 0, or an error code */
284size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
285{
Yann Collet7b51a292016-01-26 15:58:49 +0100286 if (srcCCtx->stage!=0) return ERROR(stage_wrong);
287
288 ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params);
289
290 /* copy tables */
Yann Collet3b719252016-03-30 19:48:05 +0200291 { const size_t contentSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.contentLog);
292 const size_t hSize = 1 << srcCCtx->params.cParams.hashLog;
293 const size_t h3Size = (srcCCtx->params.cParams.searchLength == 3) ? (1 << HASHLOG3) : 0;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100294 const size_t tableSpace = (contentSize + hSize + h3Size) * sizeof(U32);
295 memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
296 }
Yann Collet7b51a292016-01-26 15:58:49 +0100297
298 /* copy frame header */
299 dstCCtx->hbSize = srcCCtx->hbSize;
300 memcpy(dstCCtx->headerBuffer , srcCCtx->headerBuffer, srcCCtx->hbSize);
301
302 /* copy dictionary pointers */
Yann Colletc6eea2b2016-03-19 17:18:00 +0100303 dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
304 dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
305 dstCCtx->nextSrc = srcCCtx->nextSrc;
306 dstCCtx->base = srcCCtx->base;
307 dstCCtx->dictBase = srcCCtx->dictBase;
308 dstCCtx->dictLimit = srcCCtx->dictLimit;
309 dstCCtx->lowLimit = srcCCtx->lowLimit;
310 dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
Yann Collet7b51a292016-01-26 15:58:49 +0100311
Yann Colletfb810d62016-01-28 00:18:06 +0100312 /* copy entropy tables */
313 dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
Yann Collet863ec402016-01-28 17:56:33 +0100314 if (srcCCtx->flagStaticTables) {
Yann Collet7b51a292016-01-26 15:58:49 +0100315 memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
Yann Colletfb810d62016-01-28 00:18:06 +0100316 memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
317 memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
318 memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
319 }
Yann Collet7b51a292016-01-26 15:58:49 +0100320
321 return 0;
322}
323
324
Yann Colletecabfe32016-03-20 16:20:06 +0100325/*! ZSTD_reduceTable() :
Yann Colletd64f4352016-03-21 00:07:42 +0100326* reduce table indexes by `reducerValue` */
Yann Colletecabfe32016-03-20 16:20:06 +0100327static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
Yann Collet89db5e02015-11-13 11:27:46 +0100328{
Yann Colletecabfe32016-03-20 16:20:06 +0100329 U32 u;
330 for (u=0 ; u < size ; u++) {
331 if (table[u] < reducerValue) table[u] = 0;
332 else table[u] -= reducerValue;
Yann Collet89db5e02015-11-13 11:27:46 +0100333 }
334}
335
Yann Colletecabfe32016-03-20 16:20:06 +0100336/*! ZSTD_reduceIndex() :
337* rescale all indexes to avoid future overflow (indexes are U32) */
338static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
339{
Yann Collet3b719252016-03-30 19:48:05 +0200340 { const U32 hSize = 1 << zc->params.cParams.hashLog;
Yann Colletecabfe32016-03-20 16:20:06 +0100341 ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
342
Yann Collet3b719252016-03-30 19:48:05 +0200343 { const U32 contentSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.contentLog);
Yann Colletecabfe32016-03-20 16:20:06 +0100344 ZSTD_reduceTable(zc->contentTable, contentSize, reducerValue); }
345
Yann Collet3b719252016-03-30 19:48:05 +0200346 { const U32 h3Size = (zc->params.cParams.searchLength == 3) ? (1 << HASHLOG3) : 0;
Yann Colletecabfe32016-03-20 16:20:06 +0100347 ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
348}
349
Yann Collet89db5e02015-11-13 11:27:46 +0100350
Yann Collet863ec402016-01-28 17:56:33 +0100351/*-*******************************************************
Yann Collet14983e72015-11-11 21:38:21 +0100352* Block entropic compression
353*********************************************************/
Yann Collet14983e72015-11-11 21:38:21 +0100354
Yann Colletfb797352016-03-13 11:08:40 +0100355/* Frame format description
356 Frame Header - [ Block Header - Block ] - Frame End
357 1) Frame Header
358 - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
359 - 1 byte - Frame Descriptor
360 2) Block Header
361 - 3 bytes, starting with a 2-bits descriptor
362 Uncompressed, Compressed, Frame End, unused
363 3) Block
364 See Block Format Description
365 4) Frame End
366 - 3 bytes, compatible with Block Header
367*/
368
369
370/* Frame descriptor
371
372 1 byte, using :
373 bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)
374 bit 4 : minmatch 4(0) or 3(1)
375 bit 5 : reserved (must be zero)
376 bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes
377
378 Optional : content size (0, 1, 2 or 8 bytes)
379 0 : unknown
380 1 : 0-255 bytes
381 2 : 256 - 65535+256
382 8 : up to 16 exa
383*/
384
385
Yann Collet59d1f792016-01-23 19:28:41 +0100386/* Block format description
387
388 Block = Literal Section - Sequences Section
389 Prerequisite : size of (compressed) block, maximum size of regenerated data
390
391 1) Literal Section
392
393 1.1) Header : 1-5 bytes
394 flags: 2 bits
395 00 compressed by Huff0
396 01 unused
397 10 is Raw (uncompressed)
398 11 is Rle
399 Note : using 01 => Huff0 with precomputed table ?
400 Note : delta map ? => compressed ?
401
402 1.1.1) Huff0-compressed literal block : 3-5 bytes
Yann Colletafe07092016-01-25 04:10:46 +0100403 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
Yann Collet59d1f792016-01-23 19:28:41 +0100404 srcSize < 1 KB => 3 bytes (2-2-10-10)
Yann Colleta1249dc2016-01-25 04:22:03 +0100405 srcSize < 16KB => 4 bytes (2-2-14-14)
Yann Collet59d1f792016-01-23 19:28:41 +0100406 else => 5 bytes (2-2-18-18)
407 big endian convention
408
409 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
410 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
411 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
412 size&255
413 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
414 size>>8&255
415 size&255
416
417 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
418 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
419 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
420 size&255
421 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
422 size>>8&255
423 size&255
424
Yann Colleta1249dc2016-01-25 04:22:03 +0100425 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
426 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
427 srcSize < 1 KB => 3 bytes (2-2-10-10)
428 srcSize < 16KB => 4 bytes (2-2-14-14)
429 else => 5 bytes (2-2-18-18)
430 big endian convention
431
432 1- CTable available (stored into workspace ?)
Yann Colletb923f652016-01-26 03:14:20 +0100433 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
Yann Colleta1249dc2016-01-25 04:22:03 +0100434
Yann Collet59d1f792016-01-23 19:28:41 +0100435
436 1.2) Literal block content
437
438 1.2.1) Huff0 block, using sizes from header
439 See Huff0 format
440
Yann Colletfb810d62016-01-28 00:18:06 +0100441 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100442
Yann Colletfb810d62016-01-28 00:18:06 +0100443 1.2.3) Raw content
Yann Collet59d1f792016-01-23 19:28:41 +0100444
Yann Colletfb810d62016-01-28 00:18:06 +0100445 1.2.4) single byte
Yann Collet59d1f792016-01-23 19:28:41 +0100446
447
448 2) Sequences section
Yann Colletfb810d62016-01-28 00:18:06 +0100449
450 - Nb Sequences : 2 bytes, little endian
451 - Control Token : 1 byte (see below)
452 - Dumps Length : 1 or 2 bytes (depending on control token)
453 - Dumps : as stated by dumps length
454 - Literal Lengths FSE table (as needed depending on encoding method)
455 - Offset Codes FSE table (as needed depending on encoding method)
456 - Match Lengths FSE table (as needed depending on encoding method)
457
458 2.1) Control Token
459 8 bits, divided as :
460 0-1 : dumpsLength
461 2-3 : MatchLength, FSE encoding method
462 4-5 : Offset Codes, FSE encoding method
463 6-7 : Literal Lengths, FSE encoding method
464
465 FSE encoding method :
466 FSE_ENCODING_RAW : uncompressed; no header
467 FSE_ENCODING_RLE : single repeated value; header 1 byte
468 FSE_ENCODING_STATIC : use prepared table; no header
469 FSE_ENCODING_DYNAMIC : read NCount
Yann Collet59d1f792016-01-23 19:28:41 +0100470*/
Yann Collet14983e72015-11-11 21:38:21 +0100471
Yann Colletd1b26842016-03-15 01:24:33 +0100472size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100473{
474 BYTE* const ostart = (BYTE* const)dst;
475
Yann Colletd1b26842016-03-15 01:24:33 +0100476 if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
Yann Collet14983e72015-11-11 21:38:21 +0100477 memcpy(ostart + ZSTD_blockHeaderSize, src, srcSize);
478
479 /* Build header */
480 ostart[0] = (BYTE)(srcSize>>16);
481 ostart[1] = (BYTE)(srcSize>>8);
482 ostart[2] = (BYTE) srcSize;
483 ostart[0] += (BYTE)(bt_raw<<6); /* is a raw (uncompressed) block */
484
485 return ZSTD_blockHeaderSize+srcSize;
486}
487
488
Yann Colletd1b26842016-03-15 01:24:33 +0100489static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100490{
491 BYTE* const ostart = (BYTE* const)dst;
Yann Colleta910dc82016-03-18 12:37:45 +0100492 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100493
Yann Colletd1b26842016-03-15 01:24:33 +0100494 if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
Yann Collet14983e72015-11-11 21:38:21 +0100495
Yann Collet59d1f792016-01-23 19:28:41 +0100496 switch(flSize)
497 {
498 case 1: /* 2 - 1 - 5 */
499 ostart[0] = (BYTE)((IS_RAW<<6) + (0<<5) + srcSize);
500 break;
501 case 2: /* 2 - 2 - 12 */
502 ostart[0] = (BYTE)((IS_RAW<<6) + (2<<4) + (srcSize >> 8));
503 ostart[1] = (BYTE)srcSize;
504 break;
505 default: /*note : should not be necessary : flSize is within {1,2,3} */
506 case 3: /* 2 - 2 - 20 */
507 ostart[0] = (BYTE)((IS_RAW<<6) + (3<<4) + (srcSize >> 16));
508 ostart[1] = (BYTE)(srcSize>>8);
509 ostart[2] = (BYTE)srcSize;
510 break;
511 }
512
513 memcpy(ostart + flSize, src, srcSize);
514 return srcSize + flSize;
Yann Collet14983e72015-11-11 21:38:21 +0100515}
516
Yann Colletd1b26842016-03-15 01:24:33 +0100517static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100518{
519 BYTE* const ostart = (BYTE* const)dst;
Yann Colleta910dc82016-03-18 12:37:45 +0100520 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100521
Yann Colletd1b26842016-03-15 01:24:33 +0100522 (void)dstCapacity; /* dstCapacity guaranteed to be >=4, hence large enough */
Yann Collet59d1f792016-01-23 19:28:41 +0100523
524 switch(flSize)
525 {
526 case 1: /* 2 - 1 - 5 */
527 ostart[0] = (BYTE)((IS_RLE<<6) + (0<<5) + srcSize);
528 break;
529 case 2: /* 2 - 2 - 12 */
530 ostart[0] = (BYTE)((IS_RLE<<6) + (2<<4) + (srcSize >> 8));
531 ostart[1] = (BYTE)srcSize;
532 break;
Yann Colleta910dc82016-03-18 12:37:45 +0100533 default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
Yann Collet59d1f792016-01-23 19:28:41 +0100534 case 3: /* 2 - 2 - 20 */
535 ostart[0] = (BYTE)((IS_RLE<<6) + (3<<4) + (srcSize >> 16));
536 ostart[1] = (BYTE)(srcSize>>8);
537 ostart[2] = (BYTE)srcSize;
538 break;
539 }
540
541 ostart[flSize] = *(const BYTE*)src;
542 return flSize+1;
Yann Collet14983e72015-11-11 21:38:21 +0100543}
544
Yann Collet59d1f792016-01-23 19:28:41 +0100545
Yann Colleta5c2c082016-03-20 01:09:18 +0100546static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
Yann Collet14983e72015-11-11 21:38:21 +0100547
Yann Colletb923f652016-01-26 03:14:20 +0100548static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +0100549 void* dst, size_t dstCapacity,
Yann Collet14983e72015-11-11 21:38:21 +0100550 const void* src, size_t srcSize)
551{
Yann Colleta910dc82016-03-18 12:37:45 +0100552 size_t const minGain = ZSTD_minGain(srcSize);
553 size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
Yann Collet14983e72015-11-11 21:38:21 +0100554 BYTE* const ostart = (BYTE*)dst;
Yann Colletafe07092016-01-25 04:10:46 +0100555 U32 singleStream = srcSize < 256;
Yann Colletb923f652016-01-26 03:14:20 +0100556 U32 hType = IS_HUF;
Yann Colleta910dc82016-03-18 12:37:45 +0100557 size_t cLitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100558
Yann Collet14983e72015-11-11 21:38:21 +0100559
Yann Colleta5c2c082016-03-20 01:09:18 +0100560 /* small ? don't even attempt compression (speed opt) */
561# define LITERAL_NOENTROPY 63
562 { size_t const minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
563 if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
564 }
565
566 if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
Yann Colletfb810d62016-01-28 00:18:06 +0100567 if (zc->flagStaticTables && (lhSize==3)) {
Yann Colletb923f652016-01-26 03:14:20 +0100568 hType = IS_PCH;
569 singleStream = 1;
Yann Colleta910dc82016-03-18 12:37:45 +0100570 cLitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable);
Yann Colletfb810d62016-01-28 00:18:06 +0100571 } else {
Yann Colleta910dc82016-03-18 12:37:45 +0100572 cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12)
Yann Colletd1b26842016-03-15 01:24:33 +0100573 : HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12);
Yann Colletb923f652016-01-26 03:14:20 +0100574 }
Yann Collet14983e72015-11-11 21:38:21 +0100575
Yann Colleta910dc82016-03-18 12:37:45 +0100576 if ((cLitSize==0) || (cLitSize >= srcSize - minGain))
577 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
578 if (cLitSize==1)
579 return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
Yann Collet14983e72015-11-11 21:38:21 +0100580
581 /* Build header */
Yann Collet59d1f792016-01-23 19:28:41 +0100582 switch(lhSize)
Yann Collet14983e72015-11-11 21:38:21 +0100583 {
Yann Collet59d1f792016-01-23 19:28:41 +0100584 case 3: /* 2 - 2 - 10 - 10 */
Yann Colletb923f652016-01-26 03:14:20 +0100585 ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6));
Yann Colleta910dc82016-03-18 12:37:45 +0100586 ostart[1] = (BYTE)((srcSize<<2) + (cLitSize>>8));
587 ostart[2] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100588 break;
589 case 4: /* 2 - 2 - 14 - 14 */
Yann Colletb923f652016-01-26 03:14:20 +0100590 ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100591 ostart[1] = (BYTE)(srcSize>> 2);
Yann Colleta910dc82016-03-18 12:37:45 +0100592 ostart[2] = (BYTE)((srcSize<<6) + (cLitSize>>8));
593 ostart[3] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100594 break;
Yann Colleta910dc82016-03-18 12:37:45 +0100595 default: /* should not be necessary, lhSize is only {3,4,5} */
Yann Collet59d1f792016-01-23 19:28:41 +0100596 case 5: /* 2 - 2 - 18 - 18 */
Yann Colletb923f652016-01-26 03:14:20 +0100597 ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100598 ostart[1] = (BYTE)(srcSize>>6);
Yann Colleta910dc82016-03-18 12:37:45 +0100599 ostart[2] = (BYTE)((srcSize<<2) + (cLitSize>>16));
600 ostart[3] = (BYTE)(cLitSize>>8);
601 ostart[4] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100602 break;
Yann Collet14983e72015-11-11 21:38:21 +0100603 }
Yann Colleta910dc82016-03-18 12:37:45 +0100604 return lhSize+cLitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100605}
606
607
Yann Colletb44be742016-03-26 20:52:14 +0100608void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq)
609{
610 /* LL codes */
611 { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
612 8, 9, 10, 11, 12, 13, 14, 15,
613 16, 16, 17, 17, 18, 18, 19, 19,
614 20, 20, 20, 20, 21, 21, 21, 21,
615 22, 22, 22, 22, 22, 22, 22, 22,
616 23, 23, 23, 23, 23, 23, 23, 23,
617 24, 24, 24, 24, 24, 24, 24, 24,
618 24, 24, 24, 24, 24, 24, 24, 24 };
619 const BYTE LL_deltaCode = 19;
620 U16* const llTable = seqStorePtr->litLengthStart;
621 BYTE* const llCodeTable = seqStorePtr->llCodeStart;
622 size_t u;
623 for (u=0; u<nbSeq; u++) {
624 U32 ll = llTable[u];
625 if (llTable[u] == 65535) { ll = seqStorePtr->longLength; llTable[u] = (U16)ll; }
626 llCodeTable[u] = (ll>63) ? (BYTE)ZSTD_highbit(ll) + LL_deltaCode : LL_Code[ll];
627 } }
628
629 /* Offset codes */
630 { const U32* const offsetTable = seqStorePtr->offsetStart;
631 BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
632 size_t u;
633 for (u=0; u<nbSeq; u++) ofCodeTable[u] = (BYTE)ZSTD_highbit(offsetTable[u]);
634 }
635
636 /* ML codes */
637 { static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
638 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
639 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
640 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
641 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
642 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
643 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
644 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
645 const BYTE ML_deltaCode = 36;
646 U16* const mlTable = seqStorePtr->matchLengthStart;
647 BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
648 size_t u;
649 for (u=0; u<nbSeq; u++) {
650 U32 ml = mlTable[u];
651 if (mlTable[u] == 65535) { ml = seqStorePtr->longLength; mlTable[u] = (U16)ml; }
652 mlCodeTable[u] = (ml>127) ? (BYTE)ZSTD_highbit(ml) + ML_deltaCode : ML_Code[ml];
653 } }
654}
655
656
Yann Colletb923f652016-01-26 03:14:20 +0100657size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +0100658 void* dst, size_t dstCapacity,
Yann Collet14983e72015-11-11 21:38:21 +0100659 size_t srcSize)
660{
Yann Colletb923f652016-01-26 03:14:20 +0100661 const seqStore_t* seqStorePtr = &(zc->seqStore);
Yann Collet14983e72015-11-11 21:38:21 +0100662 U32 count[MaxSeq+1];
663 S16 norm[MaxSeq+1];
Yann Colletfb810d62016-01-28 00:18:06 +0100664 FSE_CTable* CTable_LitLength = zc->litlengthCTable;
665 FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
666 FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
Yann Collet14983e72015-11-11 21:38:21 +0100667 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
Yann Colletb0aec172016-03-21 13:24:16 +0100668 U16* const llTable = seqStorePtr->litLengthStart;
Yann Colletfadda6c2016-03-22 12:14:26 +0100669 U16* const mlTable = seqStorePtr->matchLengthStart;
Yann Collet14983e72015-11-11 21:38:21 +0100670 const U32* const offsetTable = seqStorePtr->offsetStart;
Yann Colletd64f4352016-03-21 00:07:42 +0100671 const U32* const offsetTableEnd = seqStorePtr->offset;
Yann Collet7cbe79a2016-03-23 22:31:57 +0100672 BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
Yann Collet597847a2016-03-20 19:14:22 +0100673 BYTE* const llCodeTable = seqStorePtr->llCodeStart;
Yann Colletfadda6c2016-03-22 12:14:26 +0100674 BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
Yann Collet5054ee02015-11-23 13:34:21 +0100675 BYTE* const ostart = (BYTE*)dst;
Yann Colletd1b26842016-03-15 01:24:33 +0100676 BYTE* const oend = ostart + dstCapacity;
Yann Colleta910dc82016-03-18 12:37:45 +0100677 BYTE* op = ostart;
Yann Colletd64f4352016-03-21 00:07:42 +0100678 size_t const nbSeq = offsetTableEnd - offsetTable;
Yann Collet14983e72015-11-11 21:38:21 +0100679 BYTE* seqHead;
680
Yann Collet14983e72015-11-11 21:38:21 +0100681 /* Compress literals */
Yann Colleta5c2c082016-03-20 01:09:18 +0100682 { const BYTE* const literals = seqStorePtr->litStart;
Yann Colleta910dc82016-03-18 12:37:45 +0100683 size_t const litSize = seqStorePtr->lit - literals;
Yann Colleta5c2c082016-03-20 01:09:18 +0100684 size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize);
Yann Collet14983e72015-11-11 21:38:21 +0100685 if (ZSTD_isError(cSize)) return cSize;
686 op += cSize;
687 }
688
689 /* Sequences Header */
Yann Collet7cbe79a2016-03-23 22:31:57 +0100690 if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
Yann Colletd409db62016-03-04 14:45:31 +0100691 if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
692 else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
693 else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
Yann Collete93d6ce2016-01-31 00:58:06 +0100694 if (nbSeq==0) goto _check_compressibility;
Yann Collet14983e72015-11-11 21:38:21 +0100695
Yann Colletbe391432016-03-22 23:19:28 +0100696 /* seqHead : flags for FSE encoding type */
697 seqHead = op++;
Yann Collet14983e72015-11-11 21:38:21 +0100698
Yann Colletfb810d62016-01-28 00:18:06 +0100699#define MIN_SEQ_FOR_DYNAMIC_FSE 64
700#define MAX_SEQ_FOR_STATIC_FSE 1000
701
Yann Colletb44be742016-03-26 20:52:14 +0100702 /* convert length/distances into codes */
703 ZSTD_seqToCodes(seqStorePtr, nbSeq);
Yann Collet597847a2016-03-20 19:14:22 +0100704
Yann Collet14983e72015-11-11 21:38:21 +0100705 /* CTable for Literal Lengths */
Yann Colletfadda6c2016-03-22 12:14:26 +0100706 { U32 max = MaxLL;
707 size_t const mostFrequent = FSE_countFast(count, &max, llCodeTable, nbSeq);
708 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
709 *op++ = llCodeTable[0];
710 FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
711 LLtype = FSE_ENCODING_RLE;
712 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
713 LLtype = FSE_ENCODING_STATIC;
714 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) {
715 FSE_buildCTable(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog);
716 LLtype = FSE_ENCODING_RAW;
717 } else {
Yann Colletfadda6c2016-03-22 12:14:26 +0100718 size_t nbSeq_1 = nbSeq;
719 const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
720 if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
721 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Colletadd08d62016-03-23 01:32:41 +0100722 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
723 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
724 op += NCountSize; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100725 FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
726 LLtype = FSE_ENCODING_DYNAMIC;
727 } }
Yann Collet14983e72015-11-11 21:38:21 +0100728
Yann Colletb44be742016-03-26 20:52:14 +0100729 /* CTable for Offsets */
Yann Colletfadda6c2016-03-22 12:14:26 +0100730 { U32 max = MaxOff;
Yann Collet7cbe79a2016-03-23 22:31:57 +0100731 size_t const mostFrequent = FSE_countFast(count, &max, ofCodeTable, nbSeq);
Yann Colletfadda6c2016-03-22 12:14:26 +0100732 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collet7cbe79a2016-03-23 22:31:57 +0100733 *op++ = ofCodeTable[0];
Yann Colletfadda6c2016-03-22 12:14:26 +0100734 FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
735 Offtype = FSE_ENCODING_RLE;
736 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
737 Offtype = FSE_ENCODING_STATIC;
738 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
739 FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
740 Offtype = FSE_ENCODING_RAW;
741 } else {
Yann Colletfadda6c2016-03-22 12:14:26 +0100742 size_t nbSeq_1 = nbSeq;
743 const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100744 if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100745 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Colletadd08d62016-03-23 01:32:41 +0100746 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
747 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
748 op += NCountSize; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100749 FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
750 Offtype = FSE_ENCODING_DYNAMIC;
751 } }
752
Yann Collet14983e72015-11-11 21:38:21 +0100753 /* CTable for MatchLengths */
Yann Colletfadda6c2016-03-22 12:14:26 +0100754 { U32 max = MaxML;
755 size_t const mostFrequent = FSE_countFast(count, &max, mlCodeTable, nbSeq);
756 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collet72d706a2016-03-23 20:44:12 +0100757 *op++ = *mlCodeTable;
Yann Colletfadda6c2016-03-22 12:14:26 +0100758 FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
759 MLtype = FSE_ENCODING_RLE;
760 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
761 MLtype = FSE_ENCODING_STATIC;
762 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) {
763 FSE_buildCTable(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog);
764 MLtype = FSE_ENCODING_RAW;
765 } else {
766 size_t nbSeq_1 = nbSeq;
767 const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
768 if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
769 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
770 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
771 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
772 op += NCountSize; }
773 FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
774 MLtype = FSE_ENCODING_DYNAMIC;
775 } }
Yann Collet14983e72015-11-11 21:38:21 +0100776
Yann Colletbe391432016-03-22 23:19:28 +0100777 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
Yann Colletfb810d62016-01-28 00:18:06 +0100778 zc->flagStaticTables = 0;
Yann Collet14983e72015-11-11 21:38:21 +0100779
780 /* Encoding Sequences */
Yann Collet70e45772016-03-19 18:08:32 +0100781 { BIT_CStream_t blockStream;
Yann Colleta910dc82016-03-18 12:37:45 +0100782 FSE_CState_t stateMatchLength;
783 FSE_CState_t stateOffsetBits;
784 FSE_CState_t stateLitLength;
Yann Collet14983e72015-11-11 21:38:21 +0100785
Yann Colleta910dc82016-03-18 12:37:45 +0100786 { size_t const errorCode = BIT_initCStream(&blockStream, op, oend-op);
Yann Collet597847a2016-03-20 19:14:22 +0100787 if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); } /* not enough space remaining */
Yann Collet14983e72015-11-11 21:38:21 +0100788
Yann Collet597847a2016-03-20 19:14:22 +0100789 /* first symbols */
Yann Colletfadda6c2016-03-22 12:14:26 +0100790 FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100791 FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
Yann Collet597847a2016-03-20 19:14:22 +0100792 FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
Yann Colletb0aec172016-03-21 13:24:16 +0100793 BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]);
Yann Colletb9151402016-03-26 17:18:11 +0100794 if (MEM_32bits()) BIT_flushBits(&blockStream);
Yann Collet25125972016-03-23 14:00:09 +0100795 BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]);
Yann Colletb9151402016-03-26 17:18:11 +0100796 if (MEM_32bits()) BIT_flushBits(&blockStream);
Yann Collet646693e2016-03-24 02:31:27 +0100797 BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1]);
Yann Collet597847a2016-03-20 19:14:22 +0100798 BIT_flushBits(&blockStream);
799
Yann Colletfadda6c2016-03-22 12:14:26 +0100800 { size_t n;
801 for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
Yann Colletb9151402016-03-26 17:18:11 +0100802 const BYTE ofCode = ofCodeTable[n];
Yann Collet7cbe79a2016-03-23 22:31:57 +0100803 const BYTE mlCode = mlCodeTable[n];
804 const BYTE llCode = llCodeTable[n];
805 const U32 llBits = LL_bits[llCode];
806 const U32 mlBits = ML_bits[mlCode];
Yann Colletb9151402016-03-26 17:18:11 +0100807 const U32 ofBits = ofCode; /* 32b*/ /* 64b*/
Yann Colletfadda6c2016-03-22 12:14:26 +0100808 /* (7)*/ /* (7)*/
Yann Colletb9151402016-03-26 17:18:11 +0100809 FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
810 FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
811 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
812 FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
813 if (MEM_32bits() || (ofBits+mlBits+llBits > 64-7-(LLFSELog+MLFSELog+OffFSELog)))
814 BIT_flushBits(&blockStream); /* (7)*/
Yann Collet7cbe79a2016-03-23 22:31:57 +0100815 BIT_addBits(&blockStream, llTable[n], llBits);
Yann Colletb9151402016-03-26 17:18:11 +0100816 if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100817 BIT_addBits(&blockStream, mlTable[n], mlBits);
Yann Colletb9151402016-03-26 17:18:11 +0100818 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
819 BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */
820 BIT_flushBits(&blockStream); /* (7)*/
Yann Colletfadda6c2016-03-22 12:14:26 +0100821 } }
Yann Collet14983e72015-11-11 21:38:21 +0100822
823 FSE_flushCState(&blockStream, &stateMatchLength);
824 FSE_flushCState(&blockStream, &stateOffsetBits);
825 FSE_flushCState(&blockStream, &stateLitLength);
826
Yann Colletb9151402016-03-26 17:18:11 +0100827 { size_t const streamSize = BIT_closeCStream(&blockStream);
828 if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
829 op += streamSize;
830 } }
Yann Collet14983e72015-11-11 21:38:21 +0100831
832 /* check compressibility */
Yann Collete93d6ce2016-01-31 00:58:06 +0100833_check_compressibility:
Yann Colletfadda6c2016-03-22 12:14:26 +0100834 { size_t const minGain = ZSTD_minGain(srcSize);
835 size_t const maxCSize = srcSize - minGain;
836 if ((size_t)(op-ostart) >= maxCSize) return 0; }
Yann Collet14983e72015-11-11 21:38:21 +0100837
Yann Collet5054ee02015-11-23 13:34:21 +0100838 return op - ostart;
Yann Collet14983e72015-11-11 21:38:21 +0100839}
840
841
Yann Collet95cd0c22016-03-08 18:24:21 +0100842/*! ZSTD_storeSeq() :
843 Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
844 `offsetCode` : distance to match, or 0 == repCode.
845 `matchCode` : matchLength - MINMATCH
Yann Collet14983e72015-11-11 21:38:21 +0100846*/
847MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, size_t offsetCode, size_t matchCode)
848{
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100849#if 0 /* for debug */
Yann Collet14983e72015-11-11 21:38:21 +0100850 static const BYTE* g_start = NULL;
Yann Colletb0aec172016-03-21 13:24:16 +0100851 const U32 pos = (U32)(literals - g_start);
Yann Collet14983e72015-11-11 21:38:21 +0100852 if (g_start==NULL) g_start = literals;
Yann Colletb9151402016-03-26 17:18:11 +0100853 if ((pos > 200000000) && (pos < 200900000))
854 printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
Yann Collet433a5cc2016-03-25 11:43:48 +0100855 pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
Yann Collet14983e72015-11-11 21:38:21 +0100856#endif
inikepe29caf72016-03-04 19:52:23 +0100857#if ZSTD_OPT_DEBUG == 3
inikep15174b02016-02-23 12:41:56 +0100858 if (offsetCode == 0) seqStorePtr->realRepSum++;
859 seqStorePtr->realSeqSum++;
860 seqStorePtr->realMatchSum += matchCode;
861 seqStorePtr->realLitSum += litLength;
862#endif
Yann Collet14983e72015-11-11 21:38:21 +0100863
864 /* copy Literals */
865 ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
866 seqStorePtr->lit += litLength;
867
868 /* literal Length */
Yann Colletfadda6c2016-03-22 12:14:26 +0100869 if (litLength>=65535) { *(seqStorePtr->litLength++) = 65535; seqStorePtr->longLength = (U32)litLength; }
Yann Colletd64f4352016-03-21 00:07:42 +0100870 else *seqStorePtr->litLength++ = (U16)litLength;
Yann Collet14983e72015-11-11 21:38:21 +0100871
872 /* match offset */
Yann Collet646693e2016-03-24 02:31:27 +0100873 *(seqStorePtr->offset++) = (U32)offsetCode + 1;
Yann Collet14983e72015-11-11 21:38:21 +0100874
875 /* match Length */
Yann Colletfadda6c2016-03-22 12:14:26 +0100876 if (matchCode>=65535) { *(seqStorePtr->matchLength++) = 65535; seqStorePtr->longLength = (U32)matchCode; }
877 else *seqStorePtr->matchLength++ = (U16)matchCode;
Yann Collet14983e72015-11-11 21:38:21 +0100878}
879
880
Yann Collet7d360282016-02-12 00:07:30 +0100881/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +0100882* Match length counter
883***************************************/
Yann Collet5054ee02015-11-23 13:34:21 +0100884static unsigned ZSTD_NbCommonBytes (register size_t val)
Yann Collet14983e72015-11-11 21:38:21 +0100885{
Yann Collet863ec402016-01-28 17:56:33 +0100886 if (MEM_isLittleEndian()) {
887 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100888# if defined(_MSC_VER) && defined(_WIN64)
889 unsigned long r = 0;
890 _BitScanForward64( &r, (U64)val );
Yann Colletd6080882015-12-09 09:05:22 +0100891 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100892# elif defined(__GNUC__) && (__GNUC__ >= 3)
893 return (__builtin_ctzll((U64)val) >> 3);
894# else
895 static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
896 return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
897# endif
Yann Collet863ec402016-01-28 17:56:33 +0100898 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100899# if defined(_MSC_VER)
900 unsigned long r=0;
901 _BitScanForward( &r, (U32)val );
Yann Colletd6080882015-12-09 09:05:22 +0100902 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100903# elif defined(__GNUC__) && (__GNUC__ >= 3)
904 return (__builtin_ctz((U32)val) >> 3);
905# else
906 static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
907 return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
908# endif
909 }
Yann Collet863ec402016-01-28 17:56:33 +0100910 } else { /* Big Endian CPU */
911 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100912# if defined(_MSC_VER) && defined(_WIN64)
913 unsigned long r = 0;
914 _BitScanReverse64( &r, val );
915 return (unsigned)(r>>3);
916# elif defined(__GNUC__) && (__GNUC__ >= 3)
917 return (__builtin_clzll(val) >> 3);
918# else
919 unsigned r;
920 const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
921 if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
922 if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
923 r += (!val);
924 return r;
925# endif
Yann Collet863ec402016-01-28 17:56:33 +0100926 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100927# if defined(_MSC_VER)
928 unsigned long r = 0;
929 _BitScanReverse( &r, (unsigned long)val );
930 return (unsigned)(r>>3);
931# elif defined(__GNUC__) && (__GNUC__ >= 3)
932 return (__builtin_clz((U32)val) >> 3);
933# else
934 unsigned r;
935 if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
936 r += (!val);
937 return r;
938# endif
Yann Collet863ec402016-01-28 17:56:33 +0100939 } }
Yann Collet14983e72015-11-11 21:38:21 +0100940}
941
942
Yann Collet5054ee02015-11-23 13:34:21 +0100943static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
Yann Collet14983e72015-11-11 21:38:21 +0100944{
945 const BYTE* const pStart = pIn;
946
Yann Colletfb810d62016-01-28 00:18:06 +0100947 while ((pIn<pInLimit-(sizeof(size_t)-1))) {
Yann Collet7d360282016-02-12 00:07:30 +0100948 size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
Yann Collet14983e72015-11-11 21:38:21 +0100949 if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
950 pIn += ZSTD_NbCommonBytes(diff);
951 return (size_t)(pIn - pStart);
952 }
Yann Collet14983e72015-11-11 21:38:21 +0100953 if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
954 if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
955 if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
956 return (size_t)(pIn - pStart);
957}
958
Yann Collet04b12d82016-02-11 06:23:24 +0100959/** ZSTD_count_2segments() :
Yann Collet7d360282016-02-12 00:07:30 +0100960* can count match length with `ip` & `match` in 2 different segments.
Yann Collet5054ee02015-11-23 13:34:21 +0100961* convention : on reaching mEnd, match count continue starting from iStart
962*/
963static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
964{
965 size_t matchLength;
966 const BYTE* vEnd = ip + (mEnd - match);
967 if (vEnd > iEnd) vEnd = iEnd;
968 matchLength = ZSTD_count(ip, match, vEnd);
969 if (match + matchLength == mEnd)
970 matchLength += ZSTD_count(ip+matchLength, iStart, iEnd);
971 return matchLength;
972}
973
Yann Collet14983e72015-11-11 21:38:21 +0100974
Yann Collet863ec402016-01-28 17:56:33 +0100975/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +0100976* Hashes
Yann Colletf3eca252015-10-22 15:31:46 +0100977***************************************/
inikepcc52a972016-02-19 10:09:35 +0100978static const U32 prime3bytes = 506832829U;
979static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
inikepe2446b02016-03-07 10:07:08 +0100980static size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); }
inikepcc52a972016-02-19 10:09:35 +0100981
Yann Collet4b100f42015-10-30 15:49:48 +0100982static const U32 prime4bytes = 2654435761U;
Yann Collet863ec402016-01-28 17:56:33 +0100983static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100984static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
Yann Collet2acb5d32015-10-29 16:49:43 +0100985
Yann Collet4b100f42015-10-30 15:49:48 +0100986static const U64 prime5bytes = 889523592379ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100987static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100988static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100989
990static const U64 prime6bytes = 227718039650203ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100991static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100992static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100993
Yann Collet14983e72015-11-11 21:38:21 +0100994static const U64 prime7bytes = 58295818150454627ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100995static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100996static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
Yann Collet1f44b3f2015-11-05 17:32:18 +0100997
Yann Collet5be2dd22015-11-11 13:43:58 +0100998static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
Yann Collet4b100f42015-10-30 15:49:48 +0100999{
1000 switch(mls)
1001 {
1002 default:
Yann Collet5be2dd22015-11-11 13:43:58 +01001003 case 4: return ZSTD_hash4Ptr(p, hBits);
1004 case 5: return ZSTD_hash5Ptr(p, hBits);
1005 case 6: return ZSTD_hash6Ptr(p, hBits);
1006 case 7: return ZSTD_hash7Ptr(p, hBits);
Yann Collet4b100f42015-10-30 15:49:48 +01001007 }
1008}
Yann Collet2acb5d32015-10-29 16:49:43 +01001009
Yann Collet863ec402016-01-28 17:56:33 +01001010
Yann Collet2ce49232016-02-02 14:36:49 +01001011/*-*************************************
Yann Collet1f44b3f2015-11-05 17:32:18 +01001012* Fast Scan
1013***************************************/
Yann Collet417890c2015-12-04 17:16:37 +01001014static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
1015{
1016 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001017 const U32 hBits = zc->params.cParams.hashLog;
Yann Collet417890c2015-12-04 17:16:37 +01001018 const BYTE* const base = zc->base;
1019 const BYTE* ip = base + zc->nextToUpdate;
Yann Collet2ce49232016-02-02 14:36:49 +01001020 const BYTE* const iend = ((const BYTE*)end) - 8;
Yann Collet37f3d1b2016-03-19 15:11:42 +01001021 const size_t fastHashFillStep = 3;
Yann Collet417890c2015-12-04 17:16:37 +01001022
Yann Colletfb810d62016-01-28 00:18:06 +01001023 while(ip <= iend) {
Yann Collet417890c2015-12-04 17:16:37 +01001024 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
Yann Collet37f3d1b2016-03-19 15:11:42 +01001025 ip += fastHashFillStep;
Yann Collet417890c2015-12-04 17:16:37 +01001026 }
1027}
1028
1029
Yann Collet1f44b3f2015-11-05 17:32:18 +01001030FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001031void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
Yann Collet89db5e02015-11-13 11:27:46 +01001032 const void* src, size_t srcSize,
1033 const U32 mls)
Yann Collet1f44b3f2015-11-05 17:32:18 +01001034{
Yann Collet417890c2015-12-04 17:16:37 +01001035 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001036 const U32 hBits = zc->params.cParams.hashLog;
Yann Colletc3652152015-11-24 14:06:07 +01001037 seqStore_t* seqStorePtr = &(zc->seqStore);
1038 const BYTE* const base = zc->base;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001039 const BYTE* const istart = (const BYTE*)src;
Yann Collet805a52a2015-11-06 10:52:17 +01001040 const BYTE* ip = istart;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001041 const BYTE* anchor = istart;
Yann Colletd94efbf2015-12-29 14:29:08 +01001042 const U32 lowIndex = zc->dictLimit;
1043 const BYTE* const lowest = base + lowIndex;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001044 const BYTE* const iend = istart + srcSize;
1045 const BYTE* const ilimit = iend - 8;
Yann Collet89db5e02015-11-13 11:27:46 +01001046 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001047
Yann Collet1f44b3f2015-11-05 17:32:18 +01001048 /* init */
Yann Collet743402c2015-11-20 12:03:53 +01001049 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +01001050 if (ip < lowest+REPCODE_STARTVALUE) ip = lowest+REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001051
1052 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001053 while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
Yann Collet5054ee02015-11-23 13:34:21 +01001054 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +01001055 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +01001056 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Colletd94efbf2015-12-29 14:29:08 +01001057 const U32 matchIndex = hashTable[h];
1058 const BYTE* match = base + matchIndex;
Yann Collet96ffa422016-01-02 01:16:28 +01001059 const U32 current = (U32)(ip-base);
1060 hashTable[h] = current; /* update hash table */
Yann Collet1f44b3f2015-11-05 17:32:18 +01001061
Yann Colletfb810d62016-01-28 00:18:06 +01001062 if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) { /* note : by construction, offset_1 <= current */
Yann Collet5054ee02015-11-23 13:34:21 +01001063 mlCode = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend);
Yann Collet402fdcf2015-11-20 12:46:08 +01001064 ip++;
1065 offset = 0;
Yann Colletfb810d62016-01-28 00:18:06 +01001066 } else {
Yann Colletd94efbf2015-12-29 14:29:08 +01001067 if ( (matchIndex <= lowIndex) ||
Yann Colletfb810d62016-01-28 00:18:06 +01001068 (MEM_read32(match) != MEM_read32(ip)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001069 ip += ((ip-anchor) >> g_searchStrength) + 1;
1070 continue;
1071 }
Yann Collet5054ee02015-11-23 13:34:21 +01001072 mlCode = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend);
Yann Collet402fdcf2015-11-20 12:46:08 +01001073 offset = ip-match;
Yann Collet5054ee02015-11-23 13:34:21 +01001074 while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +01001075 offset_2 = offset_1;
1076 offset_1 = offset;
1077 }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001078
Yann Collet402fdcf2015-11-20 12:46:08 +01001079 /* match found */
Yann Collet6bcdeac2015-11-26 11:43:00 +01001080 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
Yann Collet5054ee02015-11-23 13:34:21 +01001081 ip += mlCode + MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001082 anchor = ip;
1083
Yann Colletfb810d62016-01-28 00:18:06 +01001084 if (ip <= ilimit) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001085 /* Fill Table */
Yann Colletecd651b2016-01-07 15:35:18 +01001086 hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2; /* here because current+2 could be > iend-8 */
Yann Collet402fdcf2015-11-20 12:46:08 +01001087 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1088 /* check immediate repcode */
1089 while ( (ip <= ilimit)
Yann Colletfb810d62016-01-28 00:18:06 +01001090 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001091 /* store sequence */
Yann Collet70e45772016-03-19 18:08:32 +01001092 size_t const rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
1093 { size_t const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
Yann Collet402fdcf2015-11-20 12:46:08 +01001094 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
Yann Collet06eade52015-11-23 14:23:47 +01001095 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rlCode);
1096 ip += rlCode+MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001097 anchor = ip;
1098 continue; /* faster when present ... (?) */
Yann Colletfb810d62016-01-28 00:18:06 +01001099 } } }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001100
Yann Collet70e45772016-03-19 18:08:32 +01001101 /* Last Literals */
1102 { size_t const lastLLSize = iend - anchor;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001103 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1104 seqStorePtr->lit += lastLLSize;
1105 }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001106}
1107
1108
Yann Collet82260dd2016-02-11 07:14:25 +01001109static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
Yann Collet59d1f792016-01-23 19:28:41 +01001110 const void* src, size_t srcSize)
Yann Collet1f44b3f2015-11-05 17:32:18 +01001111{
Yann Collet3b719252016-03-30 19:48:05 +02001112 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001113 switch(mls)
1114 {
1115 default:
1116 case 4 :
Yann Collet59d1f792016-01-23 19:28:41 +01001117 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001118 case 5 :
Yann Collet59d1f792016-01-23 19:28:41 +01001119 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001120 case 6 :
Yann Collet59d1f792016-01-23 19:28:41 +01001121 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001122 case 7 :
Yann Collet59d1f792016-01-23 19:28:41 +01001123 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001124 }
1125}
Yann Colletf3eca252015-10-22 15:31:46 +01001126
Yann Colletf3eca252015-10-22 15:31:46 +01001127
Yann Collet82260dd2016-02-11 07:14:25 +01001128static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
Yann Collet59d1f792016-01-23 19:28:41 +01001129 const void* src, size_t srcSize,
1130 const U32 mls)
Yann Collet89db5e02015-11-13 11:27:46 +01001131{
1132 U32* hashTable = ctx->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001133 const U32 hBits = ctx->params.cParams.hashLog;
Yann Collet89db5e02015-11-13 11:27:46 +01001134 seqStore_t* seqStorePtr = &(ctx->seqStore);
1135 const BYTE* const base = ctx->base;
1136 const BYTE* const dictBase = ctx->dictBase;
1137 const BYTE* const istart = (const BYTE*)src;
1138 const BYTE* ip = istart;
1139 const BYTE* anchor = istart;
1140 const U32 lowLimit = ctx->lowLimit;
Yann Collet5054ee02015-11-23 13:34:21 +01001141 const BYTE* const dictStart = dictBase + lowLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001142 const U32 dictLimit = ctx->dictLimit;
Yann Collet743402c2015-11-20 12:03:53 +01001143 const BYTE* const lowPrefixPtr = base + dictLimit;
1144 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001145 const BYTE* const iend = istart + srcSize;
1146 const BYTE* const ilimit = iend - 8;
1147
Yann Collet138e89c2015-11-17 14:26:54 +01001148 U32 offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001149
1150
1151 /* init */
1152 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +01001153 /* skip first position to avoid read overflow during repcode match check */
Yann Colletfb810d62016-01-28 00:18:06 +01001154 hashTable[ZSTD_hashPtr(ip+0, hBits, mls)] = (U32)(ip-base+0);
Yann Collet61e16ce2016-01-31 02:04:15 +01001155 ip += REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001156
1157 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001158 while (ip < ilimit) { /* < instead of <=, because (ip+1) */
Yann Collet89db5e02015-11-13 11:27:46 +01001159 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Collet743402c2015-11-20 12:03:53 +01001160 const U32 matchIndex = hashTable[h];
Yann Collet89db5e02015-11-13 11:27:46 +01001161 const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
Yann Collet6bcdeac2015-11-26 11:43:00 +01001162 const BYTE* match = matchBase + matchIndex;
Yann Collet89db5e02015-11-13 11:27:46 +01001163 const U32 current = (U32)(ip-base);
Yann Collet743402c2015-11-20 12:03:53 +01001164 const U32 repIndex = current + 1 - offset_1;
Yann Collet402fdcf2015-11-20 12:46:08 +01001165 const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
Yann Collet89db5e02015-11-13 11:27:46 +01001166 const BYTE* repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001167 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +01001168 U32 offset;
Yann Collet89db5e02015-11-13 11:27:46 +01001169 hashTable[h] = current; /* update hash table */
1170
Yann Collet52447382016-03-20 16:00:00 +01001171 if ( ((repIndex >= dictLimit) || (repIndex <= dictLimit-4))
Yann Colletfb810d62016-01-28 00:18:06 +01001172 && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001173 const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001174 mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
Yann Collet743402c2015-11-20 12:03:53 +01001175 ip++;
Yann Collet402fdcf2015-11-20 12:46:08 +01001176 offset = 0;
Yann Colletfb810d62016-01-28 00:18:06 +01001177 } else {
Yann Collet402fdcf2015-11-20 12:46:08 +01001178 if ( (matchIndex < lowLimit) ||
Yann Collet52447382016-03-20 16:00:00 +01001179 (MEM_read32(match) != MEM_read32(ip)) ) {
1180 ip += ((ip-anchor) >> g_searchStrength) + 1;
1181 continue;
1182 }
1183 { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001184 const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1185 mlCode = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iend, matchEnd, lowPrefixPtr);
Yann Colletfb810d62016-01-28 00:18:06 +01001186 while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +01001187 offset = current - matchIndex;
1188 offset_2 = offset_1;
1189 offset_1 = offset;
Yann Colletfb810d62016-01-28 00:18:06 +01001190 } }
Yann Collet89db5e02015-11-13 11:27:46 +01001191
Yann Collet5054ee02015-11-23 13:34:21 +01001192 /* found a match : store it */
1193 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
Yann Collet5054ee02015-11-23 13:34:21 +01001194 ip += mlCode + MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001195 anchor = ip;
1196
Yann Colletfb810d62016-01-28 00:18:06 +01001197 if (ip <= ilimit) {
Yann Collet6bcdeac2015-11-26 11:43:00 +01001198 /* Fill Table */
Yann Collet239cc282015-11-23 16:17:21 +01001199 hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
Yann Collet402fdcf2015-11-20 12:46:08 +01001200 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1201 /* check immediate repcode */
Yann Colletfb810d62016-01-28 00:18:06 +01001202 while (ip <= ilimit) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001203 U32 current2 = (U32)(ip-base);
1204 const U32 repIndex2 = current2 - offset_2;
1205 const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
Yann Collet743402c2015-11-20 12:03:53 +01001206 if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
Yann Colletfb810d62016-01-28 00:18:06 +01001207 && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
Yann Collet5054ee02015-11-23 13:34:21 +01001208 const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1209 size_t repLength2 = ZSTD_count_2segments(ip+MINMATCH, repMatch2+MINMATCH, iend, repEnd2, lowPrefixPtr);
1210 U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1211 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2);
1212 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
1213 ip += repLength2+MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001214 anchor = ip;
1215 continue;
1216 }
Yann Collet743402c2015-11-20 12:03:53 +01001217 break;
Yann Colletfb810d62016-01-28 00:18:06 +01001218 } } }
Yann Collet89db5e02015-11-13 11:27:46 +01001219
1220 /* Last Literals */
Yann Collet70e45772016-03-19 18:08:32 +01001221 { size_t const lastLLSize = iend - anchor;
Yann Collet89db5e02015-11-13 11:27:46 +01001222 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1223 seqStorePtr->lit += lastLLSize;
1224 }
Yann Collet89db5e02015-11-13 11:27:46 +01001225}
1226
1227
Yann Collet82260dd2016-02-11 07:14:25 +01001228static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
Yann Collet89db5e02015-11-13 11:27:46 +01001229 const void* src, size_t srcSize)
1230{
Yann Collet3b719252016-03-30 19:48:05 +02001231 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet89db5e02015-11-13 11:27:46 +01001232 switch(mls)
1233 {
1234 default:
1235 case 4 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001236 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001237 case 5 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001238 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001239 case 6 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001240 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001241 case 7 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001242 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001243 }
1244}
1245
1246
Yann Collet04b12d82016-02-11 06:23:24 +01001247/*-*************************************
Yann Collet96b9f0b2015-11-04 03:52:54 +01001248* Binary Tree search
Yann Colletf3eca252015-10-22 15:31:46 +01001249***************************************/
Yann Collet04b12d82016-02-11 06:23:24 +01001250/** ZSTD_insertBt1() : add one or multiple positions to tree.
1251* ip : assumed <= iend-8 .
Yann Collet06eade52015-11-23 14:23:47 +01001252* @return : nb of positions added */
Yann Collet1358f912016-01-01 07:29:39 +01001253static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
1254 U32 extDict)
Yann Collet96b9f0b2015-11-04 03:52:54 +01001255{
1256 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001257 const U32 hashLog = zc->params.cParams.hashLog;
Yann Collet5be2dd22015-11-11 13:43:58 +01001258 const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
Yann Collet1f44b3f2015-11-05 17:32:18 +01001259 U32* const bt = zc->contentTable;
Yann Collet3b719252016-03-30 19:48:05 +02001260 const U32 btLog = zc->params.cParams.contentLog - 1;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001261 const U32 btMask= (1 << btLog) - 1;
1262 U32 matchIndex = hashTable[h];
1263 size_t commonLengthSmaller=0, commonLengthLarger=0;
1264 const BYTE* const base = zc->base;
Yann Collet1358f912016-01-01 07:29:39 +01001265 const BYTE* const dictBase = zc->dictBase;
1266 const U32 dictLimit = zc->dictLimit;
1267 const BYTE* const dictEnd = dictBase + dictLimit;
1268 const BYTE* const prefixStart = base + dictLimit;
Yann Colletf48e35c2015-11-07 01:13:31 +01001269 const BYTE* match = base + matchIndex;
Yann Collet6c3e2e72015-12-11 10:44:07 +01001270 const U32 current = (U32)(ip-base);
Yann Collete9eba602015-11-08 15:08:03 +01001271 const U32 btLow = btMask >= current ? 0 : current - btMask;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001272 U32* smallerPtr = bt + 2*(current&btMask);
Yann Colleta87278a2016-01-17 00:12:55 +01001273 U32* largerPtr = smallerPtr + 1;
Yann Collet59d70632015-11-04 12:05:27 +01001274 U32 dummy32; /* to be nullified at the end */
Yann Collet03526e12015-11-23 15:29:15 +01001275 const U32 windowLow = zc->lowLimit;
Yann Collet72e84cf2015-12-31 19:08:44 +01001276 U32 matchEndIdx = current+8;
Yann Colletb8a6f682016-02-15 17:06:29 +01001277 size_t bestLength = 8;
Yann Collet7beaa052016-01-21 11:57:45 +01001278 U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
1279 U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
1280 predictedSmall += (predictedSmall>0);
1281 predictedLarge += (predictedLarge>0);
Yann Colletf48e35c2015-11-07 01:13:31 +01001282
Yann Collet6c3e2e72015-12-11 10:44:07 +01001283 hashTable[h] = current; /* Update Hash Table */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001284
Yann Colletfb810d62016-01-28 00:18:06 +01001285 while (nbCompares-- && (matchIndex > windowLow)) {
Yann Collet96b9f0b2015-11-04 03:52:54 +01001286 U32* nextPtr = bt + 2*(matchIndex & btMask);
Yann Collet96b9f0b2015-11-04 03:52:54 +01001287 size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
Yann Collet04b12d82016-02-11 06:23:24 +01001288#if 1 /* note : can create issues when hlog small <= 11 */
Yann Collet70e8c382016-02-10 13:37:52 +01001289 const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
Yann Colletfb810d62016-01-28 00:18:06 +01001290 if (matchIndex == predictedSmall) {
1291 /* no need to check length, result known */
Yann Colleta87278a2016-01-17 00:12:55 +01001292 *smallerPtr = matchIndex;
1293 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1294 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1295 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Collet7beaa052016-01-21 11:57:45 +01001296 predictedSmall = predictPtr[1] + (predictPtr[1]>0);
Yann Colleta87278a2016-01-17 00:12:55 +01001297 continue;
1298 }
Yann Colletfb810d62016-01-28 00:18:06 +01001299 if (matchIndex == predictedLarge) {
Yann Colleta87278a2016-01-17 00:12:55 +01001300 *largerPtr = matchIndex;
1301 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1302 largerPtr = nextPtr;
1303 matchIndex = nextPtr[0];
Yann Collet7beaa052016-01-21 11:57:45 +01001304 predictedLarge = predictPtr[0] + (predictPtr[0]>0);
Yann Colleta87278a2016-01-17 00:12:55 +01001305 continue;
1306 }
Yann Collet04b12d82016-02-11 06:23:24 +01001307#endif
Yann Colletfb810d62016-01-28 00:18:06 +01001308 if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
Yann Collet1358f912016-01-01 07:29:39 +01001309 match = base + matchIndex;
1310 if (match[matchLength] == ip[matchLength])
1311 matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
Yann Colletfb810d62016-01-28 00:18:06 +01001312 } else {
Yann Collet1358f912016-01-01 07:29:39 +01001313 match = dictBase + matchIndex;
1314 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
1315 if (matchIndex+matchLength >= dictLimit)
1316 match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
1317 }
Yann Collet96b9f0b2015-11-04 03:52:54 +01001318
Yann Colletb8a6f682016-02-15 17:06:29 +01001319 if (matchLength > bestLength) {
1320 bestLength = matchLength;
1321 if (matchLength > matchEndIdx - matchIndex)
1322 matchEndIdx = matchIndex + (U32)matchLength;
1323 }
Yann Colletee3f4512015-12-29 22:26:09 +01001324
Yann Collet59d70632015-11-04 12:05:27 +01001325 if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
Yann Collet1358f912016-01-01 07:29:39 +01001326 break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001327
Yann Colletfb810d62016-01-28 00:18:06 +01001328 if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001329 /* match is smaller than current */
1330 *smallerPtr = matchIndex; /* update smaller idx */
1331 commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
Yann Colletf48e35c2015-11-07 01:13:31 +01001332 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001333 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
Yann Colletf48e35c2015-11-07 01:13:31 +01001334 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Colletfb810d62016-01-28 00:18:06 +01001335 } else {
Yann Collet96b9f0b2015-11-04 03:52:54 +01001336 /* match is larger than current */
1337 *largerPtr = matchIndex;
1338 commonLengthLarger = matchLength;
Yann Colletf48e35c2015-11-07 01:13:31 +01001339 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001340 largerPtr = nextPtr;
Yann Colletf48e35c2015-11-07 01:13:31 +01001341 matchIndex = nextPtr[0];
Yann Colletfb810d62016-01-28 00:18:06 +01001342 } }
Yann Collet96b9f0b2015-11-04 03:52:54 +01001343
Yann Collet59d70632015-11-04 12:05:27 +01001344 *smallerPtr = *largerPtr = 0;
Yann Colletb8a6f682016-02-15 17:06:29 +01001345 if (bestLength > 384) return MIN(192, (U32)(bestLength - 384));
1346 if (matchEndIdx > current + 8) return matchEndIdx - current - 8;
1347 return 1;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001348}
1349
1350
Yann Collet82260dd2016-02-11 07:14:25 +01001351static size_t ZSTD_insertBtAndFindBestMatch (
Yann Collet03526e12015-11-23 15:29:15 +01001352 ZSTD_CCtx* zc,
1353 const BYTE* const ip, const BYTE* const iend,
1354 size_t* offsetPtr,
Yann Collet2cc12cb2016-01-01 07:47:58 +01001355 U32 nbCompares, const U32 mls,
1356 U32 extDict)
Yann Collet03526e12015-11-23 15:29:15 +01001357{
1358 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001359 const U32 hashLog = zc->params.cParams.hashLog;
Yann Collet03526e12015-11-23 15:29:15 +01001360 const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
1361 U32* const bt = zc->contentTable;
Yann Collet3b719252016-03-30 19:48:05 +02001362 const U32 btLog = zc->params.cParams.contentLog - 1;
Yann Collet03526e12015-11-23 15:29:15 +01001363 const U32 btMask= (1 << btLog) - 1;
1364 U32 matchIndex = hashTable[h];
1365 size_t commonLengthSmaller=0, commonLengthLarger=0;
1366 const BYTE* const base = zc->base;
1367 const BYTE* const dictBase = zc->dictBase;
1368 const U32 dictLimit = zc->dictLimit;
1369 const BYTE* const dictEnd = dictBase + dictLimit;
1370 const BYTE* const prefixStart = base + dictLimit;
1371 const U32 current = (U32)(ip-base);
1372 const U32 btLow = btMask >= current ? 0 : current - btMask;
1373 const U32 windowLow = zc->lowLimit;
1374 U32* smallerPtr = bt + 2*(current&btMask);
1375 U32* largerPtr = bt + 2*(current&btMask) + 1;
1376 size_t bestLength = 0;
Yann Collet72e84cf2015-12-31 19:08:44 +01001377 U32 matchEndIdx = current+8;
Yann Collet03526e12015-11-23 15:29:15 +01001378 U32 dummy32; /* to be nullified at the end */
1379
Yann Collet6c3e2e72015-12-11 10:44:07 +01001380 hashTable[h] = current; /* Update Hash Table */
Yann Collet03526e12015-11-23 15:29:15 +01001381
Yann Colletfb810d62016-01-28 00:18:06 +01001382 while (nbCompares-- && (matchIndex > windowLow)) {
Yann Collet03526e12015-11-23 15:29:15 +01001383 U32* nextPtr = bt + 2*(matchIndex & btMask);
1384 size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
1385 const BYTE* match;
1386
Yann Colletfb810d62016-01-28 00:18:06 +01001387 if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
Yann Collet03526e12015-11-23 15:29:15 +01001388 match = base + matchIndex;
1389 if (match[matchLength] == ip[matchLength])
1390 matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
Yann Colletfb810d62016-01-28 00:18:06 +01001391 } else {
Yann Collet03526e12015-11-23 15:29:15 +01001392 match = dictBase + matchIndex;
1393 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
Yann Collet225179d2015-11-23 16:52:22 +01001394 if (matchIndex+matchLength >= dictLimit)
1395 match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
Yann Collet03526e12015-11-23 15:29:15 +01001396 }
1397
Yann Colletfb810d62016-01-28 00:18:06 +01001398 if (matchLength > bestLength) {
Yann Colletee3f4512015-12-29 22:26:09 +01001399 if (matchLength > matchEndIdx - matchIndex)
Yann Collet48da1642015-12-29 23:40:02 +01001400 matchEndIdx = matchIndex + (U32)matchLength;
Yann Collet03526e12015-11-23 15:29:15 +01001401 if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) )
1402 bestLength = matchLength, *offsetPtr = current - matchIndex;
1403 if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
1404 break; /* drop, to guarantee consistency (miss a little bit of compression) */
1405 }
1406
Yann Colletfb810d62016-01-28 00:18:06 +01001407 if (match[matchLength] < ip[matchLength]) {
Yann Collet03526e12015-11-23 15:29:15 +01001408 /* match is smaller than current */
1409 *smallerPtr = matchIndex; /* update smaller idx */
1410 commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
1411 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1412 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1413 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Colletfb810d62016-01-28 00:18:06 +01001414 } else {
Yann Collet03526e12015-11-23 15:29:15 +01001415 /* match is larger than current */
1416 *largerPtr = matchIndex;
1417 commonLengthLarger = matchLength;
1418 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1419 largerPtr = nextPtr;
1420 matchIndex = nextPtr[0];
Yann Collet768c6bc2016-02-10 14:01:49 +01001421 } }
Yann Collet03526e12015-11-23 15:29:15 +01001422
1423 *smallerPtr = *largerPtr = 0;
1424
Yann Collet72e84cf2015-12-31 19:08:44 +01001425 zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
Yann Collet03526e12015-11-23 15:29:15 +01001426 return bestLength;
1427}
1428
Yann Collet2cc12cb2016-01-01 07:47:58 +01001429
Yann Colletb8a6f682016-02-15 17:06:29 +01001430static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
Yann Collet82260dd2016-02-11 07:14:25 +01001431{
1432 const BYTE* const base = zc->base;
1433 const U32 target = (U32)(ip - base);
1434 U32 idx = zc->nextToUpdate;
Yann Colletb8a6f682016-02-15 17:06:29 +01001435
1436 while(idx < target)
1437 idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
Yann Collet82260dd2016-02-11 07:14:25 +01001438}
1439
Yann Collet52447382016-03-20 16:00:00 +01001440/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
Yann Collet82260dd2016-02-11 07:14:25 +01001441static size_t ZSTD_BtFindBestMatch (
Yann Collet2cc12cb2016-01-01 07:47:58 +01001442 ZSTD_CCtx* zc,
1443 const BYTE* const ip, const BYTE* const iLimit,
1444 size_t* offsetPtr,
1445 const U32 maxNbAttempts, const U32 mls)
1446{
1447 if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
Yann Colletb8a6f682016-02-15 17:06:29 +01001448 ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
Yann Collet2cc12cb2016-01-01 07:47:58 +01001449 return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
1450}
1451
1452
Yann Collet768c6bc2016-02-10 14:01:49 +01001453static size_t ZSTD_BtFindBestMatch_selectMLS (
Yann Collet2cc12cb2016-01-01 07:47:58 +01001454 ZSTD_CCtx* zc, /* Index table will be updated */
1455 const BYTE* ip, const BYTE* const iLimit,
1456 size_t* offsetPtr,
1457 const U32 maxNbAttempts, const U32 matchLengthSearch)
1458{
1459 switch(matchLengthSearch)
1460 {
1461 default :
1462 case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1463 case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1464 case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1465 }
1466}
1467
1468
Yann Colletb8a6f682016-02-15 17:06:29 +01001469static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
1470{
1471 const BYTE* const base = zc->base;
1472 const U32 target = (U32)(ip - base);
1473 U32 idx = zc->nextToUpdate;
1474
1475 while (idx < target) idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
1476}
1477
inikep805d2a72016-03-04 19:31:57 +01001478#include "zstd_opt.h"
Yann Collet2cc12cb2016-01-01 07:47:58 +01001479
Yann Collet03526e12015-11-23 15:29:15 +01001480/** Tree updater, providing best match */
Yann Collet82260dd2016-02-11 07:14:25 +01001481static size_t ZSTD_BtFindBestMatch_extDict (
Yann Collet03526e12015-11-23 15:29:15 +01001482 ZSTD_CCtx* zc,
1483 const BYTE* const ip, const BYTE* const iLimit,
1484 size_t* offsetPtr,
1485 const U32 maxNbAttempts, const U32 mls)
1486{
Yann Colletee3f4512015-12-29 22:26:09 +01001487 if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
Yann Colletb8a6f682016-02-15 17:06:29 +01001488 ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
Yann Collet2cc12cb2016-01-01 07:47:58 +01001489 return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
Yann Collet03526e12015-11-23 15:29:15 +01001490}
1491
1492
Yann Collet82260dd2016-02-11 07:14:25 +01001493static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
Yann Collet03526e12015-11-23 15:29:15 +01001494 ZSTD_CCtx* zc, /* Index table will be updated */
1495 const BYTE* ip, const BYTE* const iLimit,
1496 size_t* offsetPtr,
1497 const U32 maxNbAttempts, const U32 matchLengthSearch)
1498{
1499 switch(matchLengthSearch)
1500 {
1501 default :
1502 case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1503 case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1504 case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1505 }
1506}
1507
1508
Yann Collet5106a762015-11-05 15:00:24 +01001509/* ***********************
1510* Hash Chain
1511*************************/
1512
Yann Collet1f44b3f2015-11-05 17:32:18 +01001513#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
1514
Yann Collet6bcdeac2015-11-26 11:43:00 +01001515/* Update chains up to ip (excluded)
Yann Collet06eade52015-11-23 14:23:47 +01001516 Assumption : always within prefix (ie. not within extDict) */
Yann Collet6062b152016-02-16 17:41:03 +01001517FORCE_INLINE
1518U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
Yann Collet5106a762015-11-05 15:00:24 +01001519{
1520 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001521 const U32 hashLog = zc->params.cParams.hashLog;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001522 U32* const chainTable = zc->contentTable;
Yann Collet3b719252016-03-30 19:48:05 +02001523 const U32 chainMask = (1 << zc->params.cParams.contentLog) - 1;
Yann Collet5106a762015-11-05 15:00:24 +01001524 const BYTE* const base = zc->base;
1525 const U32 target = (U32)(ip - base);
1526 U32 idx = zc->nextToUpdate;
1527
Yann Colletfb810d62016-01-28 00:18:06 +01001528 while(idx < target) {
Yann Collet52447382016-03-20 16:00:00 +01001529 size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
Yann Collet5106a762015-11-05 15:00:24 +01001530 NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
1531 hashTable[h] = idx;
1532 idx++;
1533 }
1534
1535 zc->nextToUpdate = target;
Yann Collet5be2dd22015-11-11 13:43:58 +01001536 return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
Yann Collet5106a762015-11-05 15:00:24 +01001537}
1538
1539
1540FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
Yann Colletc1e52f02015-11-23 14:37:59 +01001541size_t ZSTD_HcFindBestMatch_generic (
Yann Collet5be2dd22015-11-11 13:43:58 +01001542 ZSTD_CCtx* zc, /* Index table will be updated */
Yann Collet5106a762015-11-05 15:00:24 +01001543 const BYTE* const ip, const BYTE* const iLimit,
1544 size_t* offsetPtr,
Yann Colletc1e52f02015-11-23 14:37:59 +01001545 const U32 maxNbAttempts, const U32 mls, const U32 extDict)
Yann Collet287b7d92015-11-22 13:24:05 +01001546{
Yann Collet1f44b3f2015-11-05 17:32:18 +01001547 U32* const chainTable = zc->contentTable;
Yann Collet3b719252016-03-30 19:48:05 +02001548 const U32 chainSize = (1 << zc->params.cParams.contentLog);
Yann Collet5106a762015-11-05 15:00:24 +01001549 const U32 chainMask = chainSize-1;
1550 const BYTE* const base = zc->base;
1551 const BYTE* const dictBase = zc->dictBase;
1552 const U32 dictLimit = zc->dictLimit;
Yann Collet5054ee02015-11-23 13:34:21 +01001553 const BYTE* const prefixStart = base + dictLimit;
1554 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001555 const U32 lowLimit = zc->lowLimit;
Yann Collet9a24e592015-11-22 02:53:43 +01001556 const U32 current = (U32)(ip-base);
1557 const U32 minChain = current > chainSize ? current - chainSize : 0;
Yann Collet5106a762015-11-05 15:00:24 +01001558 U32 matchIndex;
1559 const BYTE* match;
1560 int nbAttempts=maxNbAttempts;
Yann Collet5054ee02015-11-23 13:34:21 +01001561 size_t ml=MINMATCH-1;
Yann Collet5106a762015-11-05 15:00:24 +01001562
1563 /* HC4 match finder */
Yann Colletc1e52f02015-11-23 14:37:59 +01001564 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
Yann Collet5106a762015-11-05 15:00:24 +01001565
Yann Collet52447382016-03-20 16:00:00 +01001566 for ( ; (matchIndex>lowLimit) && (nbAttempts) ; nbAttempts--) {
Yann Collet5054ee02015-11-23 13:34:21 +01001567 size_t currentMl=0;
Yann Colletfb810d62016-01-28 00:18:06 +01001568 if ((!extDict) || matchIndex >= dictLimit) {
Yann Collet5106a762015-11-05 15:00:24 +01001569 match = base + matchIndex;
Yann Collet4baee502015-11-09 03:19:33 +01001570 if (match[ml] == ip[ml]) /* potentially better */
Yann Collet5054ee02015-11-23 13:34:21 +01001571 currentMl = ZSTD_count(ip, match, iLimit);
Yann Colletfb810d62016-01-28 00:18:06 +01001572 } else {
Yann Collet5106a762015-11-05 15:00:24 +01001573 match = dictBase + matchIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001574 if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
1575 currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
Yann Collet5106a762015-11-05 15:00:24 +01001576 }
1577
Yann Collet5054ee02015-11-23 13:34:21 +01001578 /* save best solution */
Yann Collet239cc282015-11-23 16:17:21 +01001579 if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex; if (ip+currentMl == iLimit) break; /* best possible, and avoid read overflow*/ }
Yann Collet5054ee02015-11-23 13:34:21 +01001580
Yann Collet9a24e592015-11-22 02:53:43 +01001581 if (matchIndex <= minChain) break;
Yann Collet5106a762015-11-05 15:00:24 +01001582 matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
1583 }
1584
1585 return ml;
1586}
1587
1588
Yann Colletc1e52f02015-11-23 14:37:59 +01001589FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
1590 ZSTD_CCtx* zc,
Yann Collet5106a762015-11-05 15:00:24 +01001591 const BYTE* ip, const BYTE* const iLimit,
1592 size_t* offsetPtr,
1593 const U32 maxNbAttempts, const U32 matchLengthSearch)
1594{
1595 switch(matchLengthSearch)
1596 {
1597 default :
Yann Colletc1e52f02015-11-23 14:37:59 +01001598 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
1599 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
1600 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
1601 }
1602}
1603
1604
1605FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
1606 ZSTD_CCtx* zc,
1607 const BYTE* ip, const BYTE* const iLimit,
1608 size_t* offsetPtr,
1609 const U32 maxNbAttempts, const U32 matchLengthSearch)
1610{
1611 switch(matchLengthSearch)
1612 {
1613 default :
1614 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
1615 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
1616 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
Yann Collet5106a762015-11-05 15:00:24 +01001617 }
1618}
1619
1620
Yann Collet287b7d92015-11-22 13:24:05 +01001621/* *******************************
Yann Collet9a24e592015-11-22 02:53:43 +01001622* Common parser - lazy strategy
Yann Collet287b7d92015-11-22 13:24:05 +01001623*********************************/
Yann Collet5106a762015-11-05 15:00:24 +01001624FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001625void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
1626 const void* src, size_t srcSize,
Yann Collet007c1c62015-11-22 02:42:28 +01001627 const U32 searchMethod, const U32 depth)
Yann Collet5106a762015-11-05 15:00:24 +01001628{
1629 seqStore_t* seqStorePtr = &(ctx->seqStore);
1630 const BYTE* const istart = (const BYTE*)src;
1631 const BYTE* ip = istart;
1632 const BYTE* anchor = istart;
1633 const BYTE* const iend = istart + srcSize;
1634 const BYTE* const ilimit = iend - 8;
Yann Collete47c4e52015-12-05 09:23:53 +01001635 const BYTE* const base = ctx->base + ctx->dictLimit;
Yann Collet5106a762015-11-05 15:00:24 +01001636
1637 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet3b719252016-03-30 19:48:05 +02001638 const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
1639 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet5106a762015-11-05 15:00:24 +01001640
Yann Collet5be2dd22015-11-11 13:43:58 +01001641 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
Yann Collet5106a762015-11-05 15:00:24 +01001642 size_t* offsetPtr,
1643 U32 maxNbAttempts, U32 matchLengthSearch);
Yann Collet5be2dd22015-11-11 13:43:58 +01001644 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
Yann Collet5106a762015-11-05 15:00:24 +01001645
1646 /* init */
1647 ZSTD_resetSeqStore(seqStorePtr);
Yann Collete47c4e52015-12-05 09:23:53 +01001648 if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
Yann Collet5106a762015-11-05 15:00:24 +01001649
1650 /* Match Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001651 while (ip < ilimit) {
Yann Collet7a231792015-11-21 15:27:35 +01001652 size_t matchLength=0;
1653 size_t offset=0;
1654 const BYTE* start=ip+1;
Yann Collet5106a762015-11-05 15:00:24 +01001655
Yann Collet743402c2015-11-20 12:03:53 +01001656 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001657 if (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1)) {
Yann Collet743402c2015-11-20 12:03:53 +01001658 /* repcode : we take it */
Yann Collet7a231792015-11-21 15:27:35 +01001659 matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend) + MINMATCH;
Yann Collet007c1c62015-11-22 02:42:28 +01001660 if (depth==0) goto _storeSequence;
Yann Collet5106a762015-11-05 15:00:24 +01001661 }
1662
Yann Collet70e45772016-03-19 18:08:32 +01001663 /* first search (depth 0) */
1664 { size_t offsetFound = 99999999;
1665 size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
Yann Collet239cc282015-11-23 16:17:21 +01001666 if (ml2 > matchLength)
1667 matchLength = ml2, start = ip, offset=offsetFound;
1668 }
Yann Collet9a24e592015-11-22 02:53:43 +01001669
Yann Colletfb810d62016-01-28 00:18:06 +01001670 if (matchLength < MINMATCH) {
Yann Collet239cc282015-11-23 16:17:21 +01001671 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1672 continue;
1673 }
Yann Collet5106a762015-11-05 15:00:24 +01001674
1675 /* let's try to find a better solution */
Yann Collet007c1c62015-11-22 02:42:28 +01001676 if (depth>=1)
Yann Colletfb810d62016-01-28 00:18:06 +01001677 while (ip<ilimit) {
Yann Collet5106a762015-11-05 15:00:24 +01001678 ip ++;
Yann Colletfb810d62016-01-28 00:18:06 +01001679 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
Yann Collet70e45772016-03-19 18:08:32 +01001680 size_t const mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
1681 int const gain2 = (int)(mlRep * 3);
1682 int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
Yann Collet007c1c62015-11-22 02:42:28 +01001683 if ((mlRep >= MINMATCH) && (gain2 > gain1))
1684 matchLength = mlRep, offset = 0, start = ip;
Yann Collet5106a762015-11-05 15:00:24 +01001685 }
Yann Collet70e45772016-03-19 18:08:32 +01001686 { size_t offset2=99999999;
1687 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1688 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1689 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
Yann Colletfb810d62016-01-28 00:18:06 +01001690 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet628065c2015-11-06 18:44:54 +01001691 matchLength = ml2, offset = offset2, start = ip;
Yann Collet5106a762015-11-05 15:00:24 +01001692 continue; /* search a better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001693 } }
Yann Collet5106a762015-11-05 15:00:24 +01001694
1695 /* let's find an even better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001696 if ((depth==2) && (ip<ilimit)) {
Yann Collet5106a762015-11-05 15:00:24 +01001697 ip ++;
Yann Colletfb810d62016-01-28 00:18:06 +01001698 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
Yann Collet70e45772016-03-19 18:08:32 +01001699 size_t const ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
1700 int const gain2 = (int)(ml2 * 4);
1701 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
Yann Collet4baee502015-11-09 03:19:33 +01001702 if ((ml2 >= MINMATCH) && (gain2 > gain1))
Yann Collet5106a762015-11-05 15:00:24 +01001703 matchLength = ml2, offset = 0, start = ip;
1704 }
Yann Collet70e45772016-03-19 18:08:32 +01001705 { size_t offset2=99999999;
1706 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1707 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1708 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
Yann Colletfb810d62016-01-28 00:18:06 +01001709 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet628065c2015-11-06 18:44:54 +01001710 matchLength = ml2, offset = offset2, start = ip;
1711 continue;
Yann Colletfb810d62016-01-28 00:18:06 +01001712 } } }
Yann Collet5106a762015-11-05 15:00:24 +01001713 break; /* nothing found : store previous solution */
1714 }
1715
Yann Collet6062b152016-02-16 17:41:03 +01001716 /* catch up */
Yann Colletfb810d62016-01-28 00:18:06 +01001717 if (offset) {
Yann Collete47c4e52015-12-05 09:23:53 +01001718 while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
Yann Collet4baee502015-11-09 03:19:33 +01001719 { start--; matchLength++; }
Yann Collet743402c2015-11-20 12:03:53 +01001720 offset_2 = offset_1; offset_1 = offset;
Yann Collet4baee502015-11-09 03:19:33 +01001721 }
1722
1723 /* store sequence */
Yann Collet7a231792015-11-21 15:27:35 +01001724_storeSequence:
Yann Collet70e45772016-03-19 18:08:32 +01001725 { size_t const litLength = start - anchor;
Yann Collet5106a762015-11-05 15:00:24 +01001726 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
Yann Collet4baee502015-11-09 03:19:33 +01001727 anchor = ip = start + matchLength;
Yann Collet5106a762015-11-05 15:00:24 +01001728 }
1729
Yann Collet743402c2015-11-20 12:03:53 +01001730 /* check immediate repcode */
1731 while ( (ip <= ilimit)
Yann Colletfb810d62016-01-28 00:18:06 +01001732 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
Yann Collet743402c2015-11-20 12:03:53 +01001733 /* store sequence */
1734 matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
1735 offset = offset_2;
1736 offset_2 = offset_1;
1737 offset_1 = offset;
1738 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength);
1739 ip += matchLength+MINMATCH;
1740 anchor = ip;
1741 continue; /* faster when present ... (?) */
Yann Colletfb810d62016-01-28 00:18:06 +01001742 } }
Yann Collet5106a762015-11-05 15:00:24 +01001743
1744 /* Last Literals */
Yann Collet70e45772016-03-19 18:08:32 +01001745 { size_t const lastLLSize = iend - anchor;
Yann Collet5106a762015-11-05 15:00:24 +01001746 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1747 seqStorePtr->lit += lastLLSize;
1748 }
Yann Collet5106a762015-11-05 15:00:24 +01001749}
1750
inikepe2bfe242016-01-31 11:25:48 +01001751
inikepd3b8d7a2016-02-22 10:06:17 +01001752static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
inikepe2bfe242016-01-31 11:25:48 +01001753{
inikep4ab9c912016-03-04 19:17:31 +01001754 ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 2);
inikepe2bfe242016-01-31 11:25:48 +01001755}
1756
Yann Collet59d1f792016-01-23 19:28:41 +01001757static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001758{
Yann Colleta1249dc2016-01-25 04:22:03 +01001759 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
Yann Collet5106a762015-11-05 15:00:24 +01001760}
1761
Yann Collet59d1f792016-01-23 19:28:41 +01001762static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001763{
Yann Colleta1249dc2016-01-25 04:22:03 +01001764 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
Yann Collet5106a762015-11-05 15:00:24 +01001765}
1766
Yann Collet59d1f792016-01-23 19:28:41 +01001767static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001768{
Yann Colleta1249dc2016-01-25 04:22:03 +01001769 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
Yann Collet5106a762015-11-05 15:00:24 +01001770}
1771
Yann Collet59d1f792016-01-23 19:28:41 +01001772static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colletf3eca252015-10-22 15:31:46 +01001773{
Yann Colleta1249dc2016-01-25 04:22:03 +01001774 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
Yann Colletbe2010e2015-10-31 12:57:14 +01001775}
1776
1777
Yann Collet9a24e592015-11-22 02:53:43 +01001778FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001779void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
1780 const void* src, size_t srcSize,
Yann Collet9a24e592015-11-22 02:53:43 +01001781 const U32 searchMethod, const U32 depth)
1782{
1783 seqStore_t* seqStorePtr = &(ctx->seqStore);
1784 const BYTE* const istart = (const BYTE*)src;
1785 const BYTE* ip = istart;
1786 const BYTE* anchor = istart;
1787 const BYTE* const iend = istart + srcSize;
1788 const BYTE* const ilimit = iend - 8;
1789 const BYTE* const base = ctx->base;
1790 const U32 dictLimit = ctx->dictLimit;
1791 const BYTE* const prefixStart = base + dictLimit;
1792 const BYTE* const dictBase = ctx->dictBase;
1793 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Colletc3652152015-11-24 14:06:07 +01001794 const BYTE* const dictStart = dictBase + ctx->lowLimit;
Yann Collet9a24e592015-11-22 02:53:43 +01001795
1796 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet3b719252016-03-30 19:48:05 +02001797 const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
1798 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet9a24e592015-11-22 02:53:43 +01001799
1800 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
1801 size_t* offsetPtr,
1802 U32 maxNbAttempts, U32 matchLengthSearch);
Yann Collet03526e12015-11-23 15:29:15 +01001803 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
Yann Collet9a24e592015-11-22 02:53:43 +01001804
1805 /* init */
1806 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet6c3e2e72015-12-11 10:44:07 +01001807 if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
Yann Collet9a24e592015-11-22 02:53:43 +01001808
1809 /* Match Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001810 while (ip < ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001811 size_t matchLength=0;
1812 size_t offset=0;
1813 const BYTE* start=ip+1;
1814 U32 current = (U32)(ip-base);
1815
1816 /* check repCode */
1817 {
1818 const U32 repIndex = (U32)(current+1 - offset_1);
1819 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1820 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001821 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001822 if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001823 /* repcode detected we should take it */
1824 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001825 matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
Yann Collet9a24e592015-11-22 02:53:43 +01001826 if (depth==0) goto _storeSequence;
Yann Colletfb810d62016-01-28 00:18:06 +01001827 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001828
Yann Collet70e45772016-03-19 18:08:32 +01001829 /* first search (depth 0) */
1830 { size_t offsetFound = 99999999;
1831 size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
Yann Collet239cc282015-11-23 16:17:21 +01001832 if (ml2 > matchLength)
1833 matchLength = ml2, start = ip, offset=offsetFound;
1834 }
Yann Collet9a24e592015-11-22 02:53:43 +01001835
Yann Colletfb810d62016-01-28 00:18:06 +01001836 if (matchLength < MINMATCH) {
Yann Collet239cc282015-11-23 16:17:21 +01001837 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1838 continue;
1839 }
Yann Collet9a24e592015-11-22 02:53:43 +01001840
1841 /* let's try to find a better solution */
1842 if (depth>=1)
Yann Colletfb810d62016-01-28 00:18:06 +01001843 while (ip<ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001844 ip ++;
1845 current++;
1846 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001847 if (offset) {
Yann Collet9a24e592015-11-22 02:53:43 +01001848 const U32 repIndex = (U32)(current - offset_1);
1849 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1850 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001851 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001852 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001853 /* repcode detected */
Yann Collet9a24e592015-11-22 02:53:43 +01001854 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet70e45772016-03-19 18:08:32 +01001855 size_t const repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1856 int const gain2 = (int)(repLength * 3);
1857 int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
Yann Collet5054ee02015-11-23 13:34:21 +01001858 if ((repLength >= MINMATCH) && (gain2 > gain1))
1859 matchLength = repLength, offset = 0, start = ip;
Yann Colletfb810d62016-01-28 00:18:06 +01001860 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001861
1862 /* search match, depth 1 */
Yann Collet70e45772016-03-19 18:08:32 +01001863 { size_t offset2=99999999;
1864 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1865 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1866 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
Yann Colletfb810d62016-01-28 00:18:06 +01001867 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001868 matchLength = ml2, offset = offset2, start = ip;
1869 continue; /* search a better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001870 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001871
1872 /* let's find an even better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001873 if ((depth==2) && (ip<ilimit)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001874 ip ++;
1875 current++;
1876 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001877 if (offset) {
Yann Collet9a24e592015-11-22 02:53:43 +01001878 const U32 repIndex = (U32)(current - offset_1);
1879 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1880 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001881 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001882 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001883 /* repcode detected */
Yann Collet9a24e592015-11-22 02:53:43 +01001884 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001885 size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1886 int gain2 = (int)(repLength * 4);
1887 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
1888 if ((repLength >= MINMATCH) && (gain2 > gain1))
1889 matchLength = repLength, offset = 0, start = ip;
Yann Colletfb810d62016-01-28 00:18:06 +01001890 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001891
1892 /* search match, depth 2 */
Yann Collet70e45772016-03-19 18:08:32 +01001893 { size_t offset2=99999999;
1894 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1895 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1896 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
Yann Colletfb810d62016-01-28 00:18:06 +01001897 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001898 matchLength = ml2, offset = offset2, start = ip;
1899 continue;
Yann Colletfb810d62016-01-28 00:18:06 +01001900 } } }
Yann Collet9a24e592015-11-22 02:53:43 +01001901 break; /* nothing found : store previous solution */
1902 }
1903
1904 /* catch up */
Yann Colletfb810d62016-01-28 00:18:06 +01001905 if (offset) {
Yann Colletc3652152015-11-24 14:06:07 +01001906 U32 matchIndex = (U32)((start-base) - offset);
1907 const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
1908 const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
1909 while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
Yann Collet9a24e592015-11-22 02:53:43 +01001910 offset_2 = offset_1; offset_1 = offset;
1911 }
1912
1913 /* store sequence */
1914_storeSequence:
Yann Collet52447382016-03-20 16:00:00 +01001915 { size_t const litLength = start - anchor;
Yann Collet9a24e592015-11-22 02:53:43 +01001916 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
1917 anchor = ip = start + matchLength;
1918 }
1919
1920 /* check immediate repcode */
Yann Colletfb810d62016-01-28 00:18:06 +01001921 while (ip <= ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001922 const U32 repIndex = (U32)((ip-base) - offset_2);
1923 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1924 const BYTE* const repMatch = repBase + repIndex;
Yann Collet239cc282015-11-23 16:17:21 +01001925 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001926 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001927 /* repcode detected we should take it */
1928 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001929 matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1930 offset = offset_2; offset_2 = offset_1; offset_1 = offset; /* swap offset history */
Yann Collet9a24e592015-11-22 02:53:43 +01001931 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
1932 ip += matchLength;
1933 anchor = ip;
1934 continue; /* faster when present ... (?) */
1935 }
1936 break;
Yann Colletfb810d62016-01-28 00:18:06 +01001937 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001938
1939 /* Last Literals */
Yann Collet52447382016-03-20 16:00:00 +01001940 { size_t const lastLLSize = iend - anchor;
Yann Collet9a24e592015-11-22 02:53:43 +01001941 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1942 seqStorePtr->lit += lastLLSize;
1943 }
Yann Collet9a24e592015-11-22 02:53:43 +01001944}
1945
Yann Collet59d1f792016-01-23 19:28:41 +01001946void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet9a24e592015-11-22 02:53:43 +01001947{
Yann Colleta1249dc2016-01-25 04:22:03 +01001948 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
Yann Collet9a24e592015-11-22 02:53:43 +01001949}
1950
Yann Collet59d1f792016-01-23 19:28:41 +01001951static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colletb7fc88e2015-11-22 03:12:28 +01001952{
Yann Colleta1249dc2016-01-25 04:22:03 +01001953 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
Yann Colletb7fc88e2015-11-22 03:12:28 +01001954}
Yann Collet9a24e592015-11-22 02:53:43 +01001955
Yann Collet59d1f792016-01-23 19:28:41 +01001956static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colleta85c77b2015-11-22 12:22:04 +01001957{
Yann Colleta1249dc2016-01-25 04:22:03 +01001958 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
Yann Colleta85c77b2015-11-22 12:22:04 +01001959}
1960
Yann Collet59d1f792016-01-23 19:28:41 +01001961static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5054ee02015-11-23 13:34:21 +01001962{
Yann Colleta1249dc2016-01-25 04:22:03 +01001963 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
Yann Collet5054ee02015-11-23 13:34:21 +01001964}
1965
inikepd3b8d7a2016-02-22 10:06:17 +01001966static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
inikepe2bfe242016-01-31 11:25:48 +01001967{
inikep4ab9c912016-03-04 19:17:31 +01001968 ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 2);
inikepe2bfe242016-01-31 11:25:48 +01001969}
1970
Yann Collet7a231792015-11-21 15:27:35 +01001971
Yann Collet59d1f792016-01-23 19:28:41 +01001972typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
Yann Collet59d70632015-11-04 12:05:27 +01001973
Yann Colletb923f652016-01-26 03:14:20 +01001974static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
Yann Collet59d70632015-11-04 12:05:27 +01001975{
inikepd3b8d7a2016-02-22 10:06:17 +01001976 static const ZSTD_blockCompressor blockCompressor[2][6] = {
1977 { ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt },
1978 { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict }
Yann Collet7fe531e2015-11-29 02:38:09 +01001979 };
1980
1981 return blockCompressor[extDict][(U32)strat];
Yann Collet59d70632015-11-04 12:05:27 +01001982}
1983
1984
Yann Colletd1b26842016-03-15 01:24:33 +01001985static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Colletbe2010e2015-10-31 12:57:14 +01001986{
Yann Collet3b719252016-03-30 19:48:05 +02001987 ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
Yann Collet2ce49232016-02-02 14:36:49 +01001988 if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
Yann Collet59d1f792016-01-23 19:28:41 +01001989 blockCompressor(zc, src, srcSize);
Yann Colletd1b26842016-03-15 01:24:33 +01001990 return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
Yann Colletbe2010e2015-10-31 12:57:14 +01001991}
1992
1993
Yann Collet2ce49232016-02-02 14:36:49 +01001994static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +01001995 void* dst, size_t dstCapacity,
Yann Colletf3eca252015-10-22 15:31:46 +01001996 const void* src, size_t srcSize)
1997{
Yann Collet2ce49232016-02-02 14:36:49 +01001998 size_t blockSize = zc->blockSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001999 size_t remaining = srcSize;
2000 const BYTE* ip = (const BYTE*)src;
2001 BYTE* const ostart = (BYTE*)dst;
2002 BYTE* op = ostart;
Yann Collet3b719252016-03-30 19:48:05 +02002003 const U32 maxDist = 1 << zc->params.cParams.windowLog;
inikepe29caf72016-03-04 19:52:23 +01002004#if ZSTD_OPT_DEBUG == 3
inikep15174b02016-02-23 12:41:56 +01002005 seqStore_t* ssPtr = &zc->seqStore;
inikepe0010e92016-02-23 16:25:04 +01002006 static U32 priceFunc = 0;
inikepe0010e92016-02-23 16:25:04 +01002007 ssPtr->realMatchSum = ssPtr->realLitSum = ssPtr->realSeqSum = ssPtr->realRepSum = 1;
2008 ssPtr->priceFunc = priceFunc;
inikepe29caf72016-03-04 19:52:23 +01002009#endif
Yann Collet9b11b462015-11-01 12:40:22 +01002010
Yann Collet2ce49232016-02-02 14:36:49 +01002011 while (remaining) {
Yann Collet3e358272015-11-04 18:19:39 +01002012 size_t cSize;
2013
Yann Colletd1b26842016-03-15 01:24:33 +01002014 if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
Yann Collet3e358272015-11-04 18:19:39 +01002015 if (remaining < blockSize) blockSize = remaining;
Yann Collet89db5e02015-11-13 11:27:46 +01002016
Yann Collet70e45772016-03-19 18:08:32 +01002017 if ((U32)(ip+blockSize - zc->base) > zc->loadedDictEnd + maxDist) {
2018 /* enforce maxDist */
2019 U32 const newLowLimit = (U32)(ip+blockSize - zc->base) - maxDist;
Yann Collet7a6343f2016-02-02 16:00:50 +01002020 if (zc->lowLimit < newLowLimit) zc->lowLimit = newLowLimit;
Yann Collet2ce49232016-02-02 14:36:49 +01002021 if (zc->dictLimit < zc->lowLimit) zc->dictLimit = zc->lowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002022 }
Yann Collet89db5e02015-11-13 11:27:46 +01002023
Yann Colletd1b26842016-03-15 01:24:33 +01002024 cSize = ZSTD_compressBlock_internal(zc, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, ip, blockSize);
Yann Collet3e358272015-11-04 18:19:39 +01002025 if (ZSTD_isError(cSize)) return cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002026
Yann Collet2ce49232016-02-02 14:36:49 +01002027 if (cSize == 0) { /* block is not compressible */
Yann Colletd1b26842016-03-15 01:24:33 +01002028 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize);
Yann Collet523b5942016-01-09 02:10:40 +01002029 if (ZSTD_isError(cSize)) return cSize;
Yann Collet2ce49232016-02-02 14:36:49 +01002030 } else {
Yann Colletf3eca252015-10-22 15:31:46 +01002031 op[0] = (BYTE)(cSize>>16);
2032 op[1] = (BYTE)(cSize>>8);
2033 op[2] = (BYTE)cSize;
Yann Colletc95f8992015-11-19 17:28:35 +01002034 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
Yann Colletf3eca252015-10-22 15:31:46 +01002035 cSize += 3;
2036 }
2037
2038 remaining -= blockSize;
Yann Colletd1b26842016-03-15 01:24:33 +01002039 dstCapacity -= cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002040 ip += blockSize;
2041 op += cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002042 }
2043
inikepf647d992016-02-29 12:33:08 +01002044#if ZSTD_OPT_DEBUG == 3
inikep15174b02016-02-23 12:41:56 +01002045 ssPtr->realMatchSum += ssPtr->realSeqSum * ((zc->params.searchLength == 3) ? 3 : 4);
inikepe0010e92016-02-23 16:25:04 +01002046 printf("avgMatchL=%.2f avgLitL=%.2f match=%.1f%% lit=%.1f%% reps=%d seq=%d priceFunc=%d\n", (float)ssPtr->realMatchSum/ssPtr->realSeqSum, (float)ssPtr->realLitSum/ssPtr->realSeqSum, 100.0*ssPtr->realMatchSum/(ssPtr->realMatchSum+ssPtr->realLitSum), 100.0*ssPtr->realLitSum/(ssPtr->realMatchSum+ssPtr->realLitSum), ssPtr->realRepSum, ssPtr->realSeqSum, ssPtr->priceFunc);
2047 priceFunc++;
inikep15174b02016-02-23 12:41:56 +01002048#endif
2049
Yann Colletf3eca252015-10-22 15:31:46 +01002050 return op-ostart;
2051}
2052
2053
Yann Colletbf42c8e2016-01-09 01:08:23 +01002054static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
Yann Collet7cbe79a2016-03-23 22:31:57 +01002055 void* dst, size_t dstCapacity,
Yann Colletbf42c8e2016-01-09 01:08:23 +01002056 const void* src, size_t srcSize,
2057 U32 frame)
Yann Colletf3eca252015-10-22 15:31:46 +01002058{
Yann Collet2acb5d32015-10-29 16:49:43 +01002059 const BYTE* const ip = (const BYTE*) src;
Yann Colletecd651b2016-01-07 15:35:18 +01002060 size_t hbSize = 0;
2061
Yann Collet2ce49232016-02-02 14:36:49 +01002062 if (frame && (zc->stage==0)) {
Yann Colletecd651b2016-01-07 15:35:18 +01002063 hbSize = zc->hbSize;
Yann Collet7cbe79a2016-03-23 22:31:57 +01002064 if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
Yann Colletecd651b2016-01-07 15:35:18 +01002065 zc->stage = 1;
2066 memcpy(dst, zc->headerBuffer, hbSize);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002067 dstCapacity -= hbSize;
Yann Colletecd651b2016-01-07 15:35:18 +01002068 dst = (char*)dst + hbSize;
2069 }
Yann Colletf3eca252015-10-22 15:31:46 +01002070
Yann Collet417890c2015-12-04 17:16:37 +01002071 /* Check if blocks follow each other */
Yann Collet2ce49232016-02-02 14:36:49 +01002072 if (src != zc->nextSrc) {
Yann Collet417890c2015-12-04 17:16:37 +01002073 /* not contiguous */
Yann Collet70e45772016-03-19 18:08:32 +01002074 size_t const delta = zc->nextSrc - ip;
Yann Collet417890c2015-12-04 17:16:37 +01002075 zc->lowLimit = zc->dictLimit;
2076 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2077 zc->dictBase = zc->base;
Yann Collet417890c2015-12-04 17:16:37 +01002078 zc->base -= delta;
2079 zc->nextToUpdate = zc->dictLimit;
Yann Collete47c4e52015-12-05 09:23:53 +01002080 if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */
Yann Collet417890c2015-12-04 17:16:37 +01002081 }
2082
Yann Collet89db5e02015-11-13 11:27:46 +01002083 /* preemptive overflow correction */
Yann Collet2ce49232016-02-02 14:36:49 +01002084 if (zc->lowLimit > (1<<30)) {
Yann Collet3b719252016-03-30 19:48:05 +02002085 U32 const btplus = (zc->params.cParams.strategy == ZSTD_btlazy2) || (zc->params.cParams.strategy == ZSTD_btopt);
2086 U32 const contentMask = (1 << (zc->params.cParams.contentLog - btplus)) - 1;
Yann Collet70e45772016-03-19 18:08:32 +01002087 U32 const newLowLimit = zc->lowLimit & contentMask; /* preserve position % contentSize */
2088 U32 const correction = zc->lowLimit - newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002089 ZSTD_reduceIndex(zc, correction);
2090 zc->base += correction;
2091 zc->dictBase += correction;
Yann Collet6c3e2e72015-12-11 10:44:07 +01002092 zc->lowLimit = newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002093 zc->dictLimit -= correction;
2094 if (zc->nextToUpdate < correction) zc->nextToUpdate = 0;
2095 else zc->nextToUpdate -= correction;
Yann Colletf3eca252015-10-22 15:31:46 +01002096 }
2097
Yann Colletbf42c8e2016-01-09 01:08:23 +01002098 /* if input and dictionary overlap : reduce dictionary (presumed modified by input) */
Yann Collet2ce49232016-02-02 14:36:49 +01002099 if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit)) {
Yann Colletc3652152015-11-24 14:06:07 +01002100 zc->lowLimit = (U32)(ip + srcSize - zc->dictBase);
2101 if (zc->lowLimit > zc->dictLimit) zc->lowLimit = zc->dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01002102 }
2103
Yann Colletc3652152015-11-24 14:06:07 +01002104 zc->nextSrc = ip + srcSize;
Yann Collet70e45772016-03-19 18:08:32 +01002105 { size_t const cSize = frame ?
Yann Collet7cbe79a2016-03-23 22:31:57 +01002106 ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
2107 ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
Yann Colletecd651b2016-01-07 15:35:18 +01002108 if (ZSTD_isError(cSize)) return cSize;
2109 return cSize + hbSize;
2110 }
Yann Colletf3eca252015-10-22 15:31:46 +01002111}
2112
Yann Colletbf42c8e2016-01-09 01:08:23 +01002113
2114size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
Yann Collet7cbe79a2016-03-23 22:31:57 +01002115 void* dst, size_t dstCapacity,
Yann Colletbf42c8e2016-01-09 01:08:23 +01002116 const void* src, size_t srcSize)
2117{
Yann Collet7cbe79a2016-03-23 22:31:57 +01002118 return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1);
Yann Colletbf42c8e2016-01-09 01:08:23 +01002119}
2120
2121
Yann Colletd1b26842016-03-15 01:24:33 +01002122size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Colletbf42c8e2016-01-09 01:08:23 +01002123{
Yann Collet569b81a2016-03-16 15:26:51 +01002124 if (srcSize > ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
Yann Collet3b719252016-03-30 19:48:05 +02002125 zc->params.cParams.searchLength = MINMATCH; /* force ZSTD_btopt to MINMATCH in block mode */
inikepa4dde252016-03-01 14:14:35 +01002126 ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.searchLength);
Yann Colletd1b26842016-03-15 01:24:33 +01002127 return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 0);
Yann Colletbf42c8e2016-01-09 01:08:23 +01002128}
2129
2130
Yann Colletb923f652016-01-26 03:14:20 +01002131static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
Yann Collet417890c2015-12-04 17:16:37 +01002132{
2133 const BYTE* const ip = (const BYTE*) src;
2134 const BYTE* const iend = ip + srcSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002135
Yann Collet417890c2015-12-04 17:16:37 +01002136 /* input becomes current prefix */
2137 zc->lowLimit = zc->dictLimit;
2138 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2139 zc->dictBase = zc->base;
2140 zc->base += ip - zc->nextSrc;
2141 zc->nextToUpdate = zc->dictLimit;
Yann Collet2ce49232016-02-02 14:36:49 +01002142 zc->loadedDictEnd = (U32)(iend - zc->base);
Yann Collet417890c2015-12-04 17:16:37 +01002143
2144 zc->nextSrc = iend;
2145 if (srcSize <= 8) return 0;
2146
Yann Collet3b719252016-03-30 19:48:05 +02002147 switch(zc->params.cParams.strategy)
Yann Collet417890c2015-12-04 17:16:37 +01002148 {
2149 case ZSTD_fast:
Yann Collet3b719252016-03-30 19:48:05 +02002150 ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002151 break;
2152
2153 case ZSTD_greedy:
2154 case ZSTD_lazy:
2155 case ZSTD_lazy2:
Yann Collet3b719252016-03-30 19:48:05 +02002156 ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002157 break;
2158
2159 case ZSTD_btlazy2:
Yann Colletcefef8c2016-02-15 07:21:54 +01002160 case ZSTD_btopt:
Yann Collet3b719252016-03-30 19:48:05 +02002161 ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002162 break;
2163
2164 default:
2165 return ERROR(GENERIC); /* strategy doesn't exist; impossible */
2166 }
2167
Yann Collet2ce49232016-02-02 14:36:49 +01002168 zc->nextToUpdate = zc->loadedDictEnd;
Yann Collet417890c2015-12-04 17:16:37 +01002169 return 0;
2170}
2171
2172
Yann Colletb923f652016-01-26 03:14:20 +01002173/* Dictionary format :
2174 Magic == ZSTD_DICT_MAGIC (4 bytes)
Yann Colletfb797352016-03-13 11:08:40 +01002175 HUF_writeCTable(256)
Yann Colletb923f652016-01-26 03:14:20 +01002176 Dictionary content
2177*/
Yann Colletfb797352016-03-13 11:08:40 +01002178/*! ZSTD_loadDictEntropyStats() :
Yann Colletb923f652016-01-26 03:14:20 +01002179 @return : size read from dictionary */
2180static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
2181{
2182 /* note : magic number already checked */
Yann Colletfb810d62016-01-28 00:18:06 +01002183 size_t offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize, errorCode;
2184 short offcodeNCount[MaxOff+1];
2185 unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
2186 short matchlengthNCount[MaxML+1];
2187 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
2188 short litlengthNCount[MaxLL+1];
2189 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
2190
Yann Collet70e45772016-03-19 18:08:32 +01002191 size_t const hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01002192 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01002193 zc->flagStaticTables = 1;
2194 dict = (const char*)dict + hufHeaderSize;
2195 dictSize -= hufHeaderSize;
2196
2197 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
2198 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2199 errorCode = FSE_buildCTable(zc->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
2200 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2201 dict = (const char*)dict + offcodeHeaderSize;
2202 dictSize -= offcodeHeaderSize;
2203
2204 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
2205 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
2206 errorCode = FSE_buildCTable(zc->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
2207 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2208 dict = (const char*)dict + matchlengthHeaderSize;
2209 dictSize -= matchlengthHeaderSize;
2210
2211 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
2212 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
2213 errorCode = FSE_buildCTable(zc->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
2214 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2215
2216 return hufHeaderSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01002217}
2218
Yann Colletd1b26842016-03-15 01:24:33 +01002219/** ZSTD_compress_insertDictionary() :
2220* @return : 0, or an error code */
Yann Collet1c8e1942016-01-26 16:31:22 +01002221static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01002222{
Yann Colletd1b26842016-03-15 01:24:33 +01002223 if ((dict==NULL) || (dictSize<=4)) return 0;
Yann Colletb923f652016-01-26 03:14:20 +01002224
Yann Colletd1b26842016-03-15 01:24:33 +01002225 /* default : dict is pure content */
2226 if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return ZSTD_loadDictionaryContent(zc, dict, dictSize);
2227
2228 /* known magic number : dict is parsed for entropy stats and content */
Yann Collet21588e32016-03-30 16:50:44 +02002229 { size_t const eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+4 /* skip magic */, dictSize-4) + 4;
2230 if (ZSTD_isError(eSize)) return eSize;
2231 return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
Yann Collet7b51a292016-01-26 15:58:49 +01002232 }
Yann Colletecd651b2016-01-07 15:35:18 +01002233}
2234
2235
Yann Colletfb797352016-03-13 11:08:40 +01002236/*! ZSTD_compressBegin_advanced() :
Yann Colletecd651b2016-01-07 15:35:18 +01002237* @return : 0, or an error code */
Yann Collet1c8e1942016-01-26 16:31:22 +01002238size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
2239 const void* dict, size_t dictSize,
Yann Collet3b719252016-03-30 19:48:05 +02002240 ZSTD_parameters params, U64 pledgedSrcSize)
Yann Colletf3eca252015-10-22 15:31:46 +01002241{
Yann Collet21588e32016-03-30 16:50:44 +02002242 /* compression parameters verification and optimization */
Yann Collet3b719252016-03-30 19:48:05 +02002243 { size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, pledgedSrcSize);
Yann Collet21588e32016-03-30 16:50:44 +02002244 if (ZSTD_isError(errorCode)) return errorCode; }
2245
Yann Collet3b719252016-03-30 19:48:05 +02002246 ZSTD_adjustCParams(&params.cParams, pledgedSrcSize, dictSize);
Yann Collet88fcd292015-11-25 14:42:45 +01002247
Yann Colletd1b26842016-03-15 01:24:33 +01002248 { size_t const errorCode = ZSTD_resetCCtx_advanced(zc, params);
Yann Colletb0aec172016-03-21 13:24:16 +01002249 if (ZSTD_isError(errorCode)) return errorCode; }
Yann Collet89db5e02015-11-13 11:27:46 +01002250
Yann Colletd1b26842016-03-15 01:24:33 +01002251 /* Write Frame Header into ctx headerBuffer */
2252 MEM_writeLE32(zc->headerBuffer, ZSTD_MAGICNUMBER);
Yann Collet37f3d1b2016-03-19 15:11:42 +01002253 { BYTE* const op = (BYTE*)zc->headerBuffer;
Yann Collet3b719252016-03-30 19:48:05 +02002254 U32 const fcsId = (pledgedSrcSize>0) + (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256); /* 0-3 */
2255 BYTE fdescriptor = (BYTE)(params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN); /* windowLog : 4 KB - 128 MB */
2256 fdescriptor |= (BYTE)((params.cParams.searchLength==3)<<4); /* mml : 3-4 */
Yann Colletd1b26842016-03-15 01:24:33 +01002257 fdescriptor |= (BYTE)(fcsId << 6);
Yann Collet1c2c2bc2016-03-15 01:33:36 +01002258 op[4] = fdescriptor;
Yann Colletd1b26842016-03-15 01:24:33 +01002259 switch(fcsId)
2260 {
2261 default: /* impossible */
2262 case 0 : break;
Yann Collet3b719252016-03-30 19:48:05 +02002263 case 1 : op[5] = (BYTE)(pledgedSrcSize); break;
2264 case 2 : MEM_writeLE16(op+5, (U16)(pledgedSrcSize-256)); break;
2265 case 3 : MEM_writeLE64(op+5, (U64)(pledgedSrcSize)); break;
Yann Colletd1b26842016-03-15 01:24:33 +01002266 }
Yann Collet37f3d1b2016-03-19 15:11:42 +01002267 zc->hbSize = ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
Yann Colletd1b26842016-03-15 01:24:33 +01002268 }
2269
Yann Collet1c8e1942016-01-26 16:31:22 +01002270 zc->stage = 0;
Yann Collet1c8e1942016-01-26 16:31:22 +01002271 return ZSTD_compress_insertDictionary(zc, dict, dictSize);
Yann Collet88fcd292015-11-25 14:42:45 +01002272}
2273
2274
Yann Collet1c8e1942016-01-26 16:31:22 +01002275size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel)
Yann Colletb923f652016-01-26 03:14:20 +01002276{
Yann Collet3b719252016-03-30 19:48:05 +02002277 ZSTD_parameters params;
2278 params.cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
2279 params.fParams.contentSizeFlag = 0;
inikepa4dde252016-03-01 14:14:35 +01002280 ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_usingDict compressionLevel=%d\n", zc->base, compressionLevel);
Yann Collet3b719252016-03-30 19:48:05 +02002281 return ZSTD_compressBegin_advanced(zc, dict, dictSize, params, 0);
Yann Collet1c8e1942016-01-26 16:31:22 +01002282}
Yann Collet083fcc82015-10-25 14:06:35 +01002283
Yann Collet1c8e1942016-01-26 16:31:22 +01002284size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
Yann Collet083fcc82015-10-25 14:06:35 +01002285{
inikepa4dde252016-03-01 14:14:35 +01002286 ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin compressionLevel=%d\n", zc->base, compressionLevel);
Yann Collet3b719252016-03-30 19:48:05 +02002287 return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
Yann Collet083fcc82015-10-25 14:06:35 +01002288}
2289
2290
Yann Colletfb797352016-03-13 11:08:40 +01002291/*! ZSTD_compressEnd() :
2292* Write frame epilogue.
Yann Collet88fcd292015-11-25 14:42:45 +01002293* @return : nb of bytes written into dst (or an error code) */
Yann Colletd1b26842016-03-15 01:24:33 +01002294size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t dstCapacity)
Yann Collet2acb5d32015-10-29 16:49:43 +01002295{
2296 BYTE* op = (BYTE*)dst;
Yann Colletecd651b2016-01-07 15:35:18 +01002297 size_t hbSize = 0;
Yann Collet2acb5d32015-10-29 16:49:43 +01002298
Yann Collet70e45772016-03-19 18:08:32 +01002299 /* special case : empty frame : header still within internal buffer */
Yann Colletfb810d62016-01-28 00:18:06 +01002300 if (zc->stage==0) {
Yann Colletecd651b2016-01-07 15:35:18 +01002301 hbSize = zc->hbSize;
Yann Colletd1b26842016-03-15 01:24:33 +01002302 if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
Yann Colletecd651b2016-01-07 15:35:18 +01002303 zc->stage = 1;
2304 memcpy(dst, zc->headerBuffer, hbSize);
Yann Colletd1b26842016-03-15 01:24:33 +01002305 dstCapacity -= hbSize;
Yann Colletecd651b2016-01-07 15:35:18 +01002306 op += hbSize;
2307 }
2308
2309 /* frame epilogue */
Yann Colletd1b26842016-03-15 01:24:33 +01002310 if (dstCapacity < 3) return ERROR(dstSize_tooSmall);
Yann Collet2acb5d32015-10-29 16:49:43 +01002311 op[0] = (BYTE)(bt_end << 6);
2312 op[1] = 0;
2313 op[2] = 0;
2314
Yann Colletecd651b2016-01-07 15:35:18 +01002315 return 3+hbSize;
Yann Collet2acb5d32015-10-29 16:49:43 +01002316}
2317
Yann Colletfd416f12016-01-30 03:14:15 +01002318
2319size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx,
Yann Colletd1b26842016-03-15 01:24:33 +01002320 void* dst, size_t dstCapacity,
Yann Colletfd416f12016-01-30 03:14:15 +01002321 const void* src, size_t srcSize)
2322{
Yann Collet70e45772016-03-19 18:08:32 +01002323 { size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
2324 if (ZSTD_isError(errorCode)) return errorCode;
2325 }
2326 { size_t const cSize = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize);
2327 if (ZSTD_isError(cSize)) return cSize;
2328 { size_t const endSize = ZSTD_compressEnd(cctx, (char*)dst+cSize, dstCapacity-cSize);
2329 if (ZSTD_isError(endSize)) return endSize;
2330 return cSize + endSize;
2331 } }
Yann Colletfd416f12016-01-30 03:14:15 +01002332}
2333
2334
Yann Collet21588e32016-03-30 16:50:44 +02002335static size_t ZSTD_compress_internal (ZSTD_CCtx* ctx,
Yann Colletd1b26842016-03-15 01:24:33 +01002336 void* dst, size_t dstCapacity,
Yann Collet88fcd292015-11-25 14:42:45 +01002337 const void* src, size_t srcSize,
Yann Collet31683c02015-12-18 01:26:48 +01002338 const void* dict,size_t dictSize,
Yann Collet88fcd292015-11-25 14:42:45 +01002339 ZSTD_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +01002340{
2341 BYTE* const ostart = (BYTE*)dst;
2342 BYTE* op = ostart;
2343
Yann Collet1c8e1942016-01-26 16:31:22 +01002344 /* Init */
Yann Collet3b719252016-03-30 19:48:05 +02002345 { size_t const errorCode = ZSTD_compressBegin_advanced(ctx, dict, dictSize, params, srcSize);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002346 if(ZSTD_isError(errorCode)) return errorCode; }
Yann Colletf3eca252015-10-22 15:31:46 +01002347
2348 /* body (compression) */
Yann Colletd1b26842016-03-15 01:24:33 +01002349 { size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002350 if(ZSTD_isError(oSize)) return oSize;
2351 op += oSize;
2352 dstCapacity -= oSize; }
Yann Colletf3eca252015-10-22 15:31:46 +01002353
2354 /* Close frame */
Yann Colletd1b26842016-03-15 01:24:33 +01002355 { size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002356 if(ZSTD_isError(oSize)) return oSize;
2357 op += oSize; }
Yann Colletf3eca252015-10-22 15:31:46 +01002358
2359 return (op - ostart);
2360}
2361
Yann Collet21588e32016-03-30 16:50:44 +02002362size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2363 void* dst, size_t dstCapacity,
2364 const void* src, size_t srcSize,
2365 const void* dict,size_t dictSize,
2366 ZSTD_parameters params)
2367{
Yann Collet3b719252016-03-30 19:48:05 +02002368 size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, srcSize);
Yann Collet21588e32016-03-30 16:50:44 +02002369 if (ZSTD_isError(errorCode)) return errorCode;
2370 return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2371}
2372
Yann Colletd1b26842016-03-15 01:24:33 +01002373size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
Yann Collet31683c02015-12-18 01:26:48 +01002374{
Yann Collet3b719252016-03-30 19:48:05 +02002375 ZSTD_parameters params;
inikepa4dde252016-03-01 14:14:35 +01002376 ZSTD_LOG_BLOCK("%p: ZSTD_compress_usingDict srcSize=%d dictSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, (int)dictSize, compressionLevel);
Yann Collet3b719252016-03-30 19:48:05 +02002377 params.cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
2378 params.fParams.contentSizeFlag = 1;
2379 ZSTD_adjustCParams(&params.cParams, srcSize, dictSize);
Yann Collet21588e32016-03-30 16:50:44 +02002380 return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
Yann Collet31683c02015-12-18 01:26:48 +01002381}
2382
Yann Colletd1b26842016-03-15 01:24:33 +01002383size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
Yann Collet083fcc82015-10-25 14:06:35 +01002384{
inikepa4dde252016-03-01 14:14:35 +01002385 ZSTD_LOG_BLOCK("%p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, compressionLevel);
Yann Collet21588e32016-03-30 16:50:44 +02002386 return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
Yann Collet083fcc82015-10-25 14:06:35 +01002387}
2388
Yann Colletd1b26842016-03-15 01:24:33 +01002389size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
Yann Colletf3eca252015-10-22 15:31:46 +01002390{
Yann Collet44fe9912015-10-29 22:02:40 +01002391 size_t result;
Yann Collet5be2dd22015-11-11 13:43:58 +01002392 ZSTD_CCtx ctxBody;
Yann Collet712def92015-10-29 18:41:45 +01002393 memset(&ctxBody, 0, sizeof(ctxBody));
Yann Colletd1b26842016-03-15 01:24:33 +01002394 result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
Yann Colletecd651b2016-01-07 15:35:18 +01002395 free(ctxBody.workSpace); /* can't free ctxBody, since it's on stack; just free heap content */
Yann Collet44fe9912015-10-29 22:02:40 +01002396 return result;
Yann Colletf3eca252015-10-22 15:31:46 +01002397}
Yann Colletfdcad6d2015-12-17 23:50:15 +01002398
Yann Colletfd416f12016-01-30 03:14:15 +01002399
Yann Collet70e8c382016-02-10 13:37:52 +01002400/*-===== Pre-defined compression levels =====-*/
Yann Colletfd416f12016-01-30 03:14:15 +01002401
Yann Collete3193c42016-03-09 16:57:09 +01002402#define ZSTD_MAX_CLEVEL 22
Yann Collet7d968c72016-02-03 02:11:32 +01002403unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
2404
inikepcc52a972016-02-19 10:09:35 +01002405
Yann Collet3b719252016-03-30 19:48:05 +02002406static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
Yann Colletfd416f12016-01-30 03:14:15 +01002407{ /* "default" */
Yann Collet3b719252016-03-30 19:48:05 +02002408 /* W, C, H, S, L, SL, strat */
2409 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
2410 { 19, 13, 14, 1, 7, 4, ZSTD_fast }, /* level 1 */
2411 { 19, 15, 16, 1, 6, 4, ZSTD_fast }, /* level 2 */
2412 { 20, 18, 20, 1, 6, 4, ZSTD_fast }, /* level 3 */
2413 { 20, 13, 17, 2, 5, 4, ZSTD_greedy }, /* level 4.*/
2414 { 20, 15, 18, 3, 5, 4, ZSTD_greedy }, /* level 5 */
2415 { 21, 16, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
2416 { 21, 17, 20, 3, 5, 4, ZSTD_lazy }, /* level 7 */
2417 { 21, 18, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 8.*/
2418 { 21, 20, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */
2419 { 21, 19, 21, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */
2420 { 22, 20, 22, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */
2421 { 22, 20, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */
2422 { 22, 21, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */
2423 { 22, 21, 22, 6, 5, 4, ZSTD_lazy2 }, /* level 14 */
2424 { 22, 21, 21, 5, 5, 4, ZSTD_btlazy2 }, /* level 15 */
2425 { 23, 22, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */
2426 { 23, 22, 22, 6, 5, 22, ZSTD_btopt }, /* level 17 */
2427 { 22, 22, 22, 5, 3, 44, ZSTD_btopt }, /* level 18 */
2428 { 23, 24, 22, 7, 3, 44, ZSTD_btopt }, /* level 19 */
2429 { 25, 26, 22, 7, 3, 71, ZSTD_btopt }, /* level 20 */
2430 { 26, 26, 24, 7, 3,256, ZSTD_btopt }, /* level 21 */
2431 { 27, 28, 26, 9, 3,256, ZSTD_btopt }, /* level 22 */
Yann Colletfd416f12016-01-30 03:14:15 +01002432},
2433{ /* for srcSize <= 256 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002434 /* W, C, H, S, L, T, strat */
2435 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */
2436 { 18, 14, 15, 1, 6, 4, ZSTD_fast }, /* level 1 */
2437 { 18, 14, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
2438 { 18, 14, 17, 1, 5, 4, ZSTD_fast }, /* level 3.*/
2439 { 18, 14, 15, 4, 4, 4, ZSTD_greedy }, /* level 4 */
2440 { 18, 16, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
2441 { 18, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
2442 { 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */
2443 { 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
2444 { 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
2445 { 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
2446 { 18, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
2447 { 18, 18, 17, 4, 4, 4, ZSTD_btlazy2 }, /* level 12 */
2448 { 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
2449 { 18, 17, 19, 8, 4, 24, ZSTD_btopt }, /* level 14.*/
2450 { 18, 19, 19, 8, 4, 48, ZSTD_btopt }, /* level 15.*/
2451 { 18, 19, 18, 9, 4,128, ZSTD_btopt }, /* level 16.*/
2452 { 18, 19, 18, 9, 4,192, ZSTD_btopt }, /* level 17.*/
2453 { 18, 19, 18, 9, 4,256, ZSTD_btopt }, /* level 18.*/
2454 { 18, 19, 18, 10, 4,256, ZSTD_btopt }, /* level 19.*/
2455 { 18, 19, 18, 11, 4,256, ZSTD_btopt }, /* level 20.*/
2456 { 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 21.*/
2457 { 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 22*/
Yann Colletfd416f12016-01-30 03:14:15 +01002458},
2459{ /* for srcSize <= 128 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002460 /* W, C, H, S, L, T, strat */
2461 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
2462 { 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */
2463 { 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
2464 { 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */
2465 { 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */
2466 { 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
2467 { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
2468 { 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */
2469 { 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
2470 { 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
2471 { 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
2472 { 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
2473 { 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
2474 { 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
2475 { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
2476 { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
2477 { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
2478 { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
2479 { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
2480 { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
2481 { 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/
2482 { 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/
2483 { 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002484},
2485{ /* for srcSize <= 16 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002486 /* W, C, H, S, L, T, strat */
2487 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */
2488 { 14, 14, 14, 1, 4, 4, ZSTD_fast }, /* level 1 */
2489 { 14, 14, 15, 1, 4, 4, ZSTD_fast }, /* level 2 */
2490 { 14, 14, 14, 4, 4, 4, ZSTD_greedy }, /* level 3.*/
2491 { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 4.*/
2492 { 14, 14, 14, 4, 4, 4, ZSTD_lazy2 }, /* level 5 */
2493 { 14, 14, 14, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */
2494 { 14, 14, 14, 6, 4, 4, ZSTD_lazy2 }, /* level 7.*/
2495 { 14, 14, 14, 7, 4, 4, ZSTD_lazy2 }, /* level 8.*/
2496 { 14, 15, 14, 6, 4, 4, ZSTD_btlazy2 }, /* level 9.*/
2497 { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
2498 { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
2499 { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
2500 { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
2501 { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
2502 { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
2503 { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
2504 { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
2505 { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
2506 { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
2507 { 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 20.*/
2508 { 14, 15, 15, 9, 3,256, ZSTD_btopt }, /* level 21.*/
2509 { 14, 15, 15, 10, 3,256, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002510},
2511};
2512
Yann Collet1df25942016-03-05 18:43:21 +01002513/*! ZSTD_getParams() :
Yann Colletfd416f12016-01-30 03:14:15 +01002514* @return ZSTD_parameters structure for a selected compression level and srcSize.
Yann Colletde406ee2016-03-20 15:46:10 +01002515* `srcSize` value is optional, select 0 if not known */
Yann Collet3b719252016-03-30 19:48:05 +02002516ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, U64 srcSize, size_t dictSize)
Yann Colletfd416f12016-01-30 03:14:15 +01002517{
Yann Collet3b719252016-03-30 19:48:05 +02002518 size_t addedSize = srcSize ? 0 : 500;
2519 U64 rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
2520 U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
Yann Colletfd416f12016-01-30 03:14:15 +01002521 if (compressionLevel<=0) compressionLevel = 1;
2522 if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
inikep3379c5d2016-02-05 09:21:20 +01002523#if ZSTD_OPT_DEBUG >= 1
2524 tableID=0;
2525#endif
Yann Collet3b719252016-03-30 19:48:05 +02002526 return ZSTD_defaultCParameters[tableID][compressionLevel];
Yann Colletfd416f12016-01-30 03:14:15 +01002527}
2528