blob: 8ce18f81159c37c5a71a71b1bd4a646f637f3b01 [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 Collet5d393572016-04-07 17:19:00 +020083 ssPtr->longLengthID = 0;
Yann Collet14983e72015-11-11 21:38:21 +010084}
85
86
Yann Collet7d360282016-02-12 00:07:30 +010087/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +010088* Context memory management
89***************************************/
Yann Collet5be2dd22015-11-11 13:43:58 +010090struct ZSTD_CCtx_s
Yann Colletf3eca252015-10-22 15:31:46 +010091{
Yann Collet89db5e02015-11-13 11:27:46 +010092 const BYTE* nextSrc; /* next block here to continue on current prefix */
Yann Colleteeb8ba12015-10-22 16:55:40 +010093 const BYTE* base; /* All regular indexes relative to this position */
94 const BYTE* dictBase; /* extDict indexes relative to this position */
Yann Colletf3eca252015-10-22 15:31:46 +010095 U32 dictLimit; /* below that point, need extDict */
Yann Colleteeb8ba12015-10-22 16:55:40 +010096 U32 lowLimit; /* below that point, no more data */
Yann Colletf3eca252015-10-22 15:31:46 +010097 U32 nextToUpdate; /* index from which to continue dictionary update */
inikepcc52a972016-02-19 10:09:35 +010098 U32 nextToUpdate3; /* index from which to continue dictionary update */
inikep7adceef2016-03-23 15:53:38 +010099 U32 hashLog3; /* dispatch table : larger == faster, more memory */
Yann Collet2ce49232016-02-02 14:36:49 +0100100 U32 loadedDictEnd;
Yann Collet887e7da2016-04-11 20:12:27 +0200101 U32 stage; /* 0: created; 1: init,dictLoad; 2:started */
Yann Collet5be2dd22015-11-11 13:43:58 +0100102 ZSTD_parameters params;
Yann Collet712def92015-10-29 18:41:45 +0100103 void* workSpace;
104 size_t workSpaceSize;
Yann Collet120230b2015-12-02 14:00:45 +0100105 size_t blockSize;
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 Collet8a57b922016-04-04 13:49:18 +0200110 U32* chainTable;
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{
Yann Collet15354142016-04-04 04:22:53 +0200144 CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
Yann Collet8a57b922016-04-04 13:49:18 +0200145 CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
Yann Collet3b719252016-03-30 19:48:05 +0200146 CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
147 CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
inikep75716852016-04-06 12:34:42 +0200148 { U32 const searchLengthMin = (cParams.strategy == ZSTD_fast || cParams.strategy == ZSTD_greedy) ? ZSTD_SEARCHLENGTH_MIN+1 : ZSTD_SEARCHLENGTH_MIN;
Yann Collet3b719252016-03-30 19:48:05 +0200149 U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
150 CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
151 CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
Yann Collet9bb87e52016-03-30 21:28:15 +0200152 if ((U32)(cParams.strategy) > (U32)ZSTD_btopt) return ERROR(compressionParameter_unsupported);
Yann Collet21588e32016-03-30 16:50:44 +0200153 return 0;
154}
155
156
Yann Collet14983e72015-11-11 21:38:21 +0100157static unsigned ZSTD_highbit(U32 val);
158
Yann Collet3b719252016-03-30 19:48:05 +0200159/** ZSTD_checkCParams_advanced() :
160 temporary work-around, while the compressor compatibility remains limited regarding windowLog < 18 */
161size_t ZSTD_checkCParams_advanced(ZSTD_compressionParameters cParams, U64 srcSize)
162{
Yann Colletefb18302016-04-01 18:54:13 +0200163 if (srcSize > (1ULL << ZSTD_WINDOWLOG_MIN)) return ZSTD_checkCParams(cParams);
Yann Collet3b719252016-03-30 19:48:05 +0200164 if (cParams.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) return ERROR(compressionParameter_unsupported);
Yann Collet8a57b922016-04-04 13:49:18 +0200165 if (srcSize <= (1ULL << cParams.windowLog)) cParams.windowLog = ZSTD_WINDOWLOG_MIN; /* fake value - temporary work around */
166 if (srcSize <= (1ULL << cParams.chainLog)) cParams.chainLog = ZSTD_CHAINLOG_MIN; /* fake value - temporary work around */
Yann Colletef363902016-04-02 00:46:40 +0200167 if ((srcSize <= (1ULL << cParams.hashLog)) && ((U32)cParams.strategy < (U32)ZSTD_btlazy2)) cParams.hashLog = ZSTD_HASHLOG_MIN; /* fake value - temporary work around */
Yann Collet3b719252016-03-30 19:48:05 +0200168 return ZSTD_checkCParams(cParams);
169}
170
171
Yann Collet21588e32016-03-30 16:50:44 +0200172/** ZSTD_adjustParams() :
173 optimize params for q given input (`srcSize` and `dictSize`).
174 mostly downsizing to reduce memory consumption and initialization.
175 Both `srcSize` and `dictSize` are optional (use 0 if unknown),
176 but if both are 0, no optimization can be done.
177 Note : params is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
Yann Colletdd6466a2016-03-30 20:06:26 +0200178void ZSTD_adjustCParams(ZSTD_compressionParameters* params, U64 srcSize, size_t dictSize)
Yann Collet59d70632015-11-04 12:05:27 +0100179{
Yann Collet21588e32016-03-30 16:50:44 +0200180 if (srcSize+dictSize == 0) return; /* no size information available : no adjustment */
Yann Collet59d70632015-11-04 12:05:27 +0100181
Yann Collet70e45772016-03-19 18:08:32 +0100182 /* resize params, to use less memory when necessary */
Yann Colletdd6466a2016-03-30 20:06:26 +0200183 { U32 const minSrcSize = (srcSize==0) ? 500 : 0;
184 U64 const rSize = srcSize + dictSize + minSrcSize;
Yann Colletb59bf962016-04-04 14:53:16 +0200185 if (rSize < ((U64)1<<ZSTD_WINDOWLOG_MAX)) {
Yann Collet21588e32016-03-30 16:50:44 +0200186 U32 const srcLog = ZSTD_highbit((U32)(rSize)-1) + 1;
187 if (params->windowLog > srcLog) params->windowLog = srcLog;
188 } }
Yann Colletc6eea2b2016-03-19 17:18:00 +0100189 if (params->hashLog > params->windowLog) params->hashLog = params->windowLog;
Yann Collet21588e32016-03-30 16:50:44 +0200190 { U32 const btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_btopt);
Yann Collet8a57b922016-04-04 13:49:18 +0200191 U32 const maxChainLog = params->windowLog+btPlus;
192 if (params->chainLog > maxChainLog) params->chainLog = maxChainLog; } /* <= ZSTD_CHAINLOG_MAX */
Yann Colletc6eea2b2016-03-19 17:18:00 +0100193
194 if (params->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) params->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
Yann Collet40358d02016-04-02 00:40:09 +0200195 if ((params->hashLog < ZSTD_HASHLOG_MIN) && ((U32)params->strategy >= (U32)ZSTD_btlazy2)) params->hashLog = ZSTD_HASHLOG_MIN; /* required to ensure collision resistance in bt */
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
Yann Collet27caf2a2016-04-01 15:48:48 +0200211/*! ZSTD_resetCCtx_advanced() :
212 note : 'params' is expected to be validated */
Yann Collet5be2dd22015-11-11 13:43:58 +0100213static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
Yann Colletabb5c652016-04-11 20:42:31 +0200214 ZSTD_parameters params, U32 reset)
Yann Collet863ec402016-01-28 17:56:33 +0100215{ /* note : params considered validated here */
Yann Collet3b719252016-03-30 19:48:05 +0200216 const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
217 const U32 divider = (params.cParams.searchLength==3) ? 3 : 4;
Yann Colletdd54bbc2016-03-08 02:35:34 +0100218 const size_t maxNbSeq = blockSize / divider;
Yann Colletbe391432016-03-22 23:19:28 +0100219 const size_t tokenSpace = blockSize + 11*maxNbSeq;
Yann Collet8a57b922016-04-04 13:49:18 +0200220 const size_t chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
Yann Collet3b719252016-03-30 19:48:05 +0200221 const size_t hSize = 1 << params.cParams.hashLog;
inikep7adceef2016-03-23 15:53:38 +0100222 const size_t h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
Yann Collet8a57b922016-04-04 13:49:18 +0200223 const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
inikep87d4f3d2016-03-02 15:56:24 +0100224
Yann Collete74215e2016-03-19 16:09:09 +0100225 /* Check if workSpace is large enough, alloc a new one if needed */
Yann Collet48537162016-04-07 15:24:29 +0200226 { size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
Yann Collete74215e2016-03-19 16:09:09 +0100227 + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
228 size_t const neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
Yann Collet1005fc12016-04-04 13:28:28 +0200229 + ((params.cParams.strategy == ZSTD_btopt) ? optSpace : 0);
Yann Collete74215e2016-03-19 16:09:09 +0100230 if (zc->workSpaceSize < neededSpace) {
231 free(zc->workSpace);
232 zc->workSpace = malloc(neededSpace);
233 if (zc->workSpace == NULL) return ERROR(memory_allocation);
234 zc->workSpaceSize = neededSpace;
Yann Colletc6eea2b2016-03-19 17:18:00 +0100235 } }
Yann Collete74215e2016-03-19 16:09:09 +0100236
Yann Colletabb5c652016-04-11 20:42:31 +0200237 if (reset) memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
inikepcc52a972016-02-19 10:09:35 +0100238 zc->hashTable3 = (U32*)(zc->workSpace);
Yann Collete74215e2016-03-19 16:09:09 +0100239 zc->hashTable = zc->hashTable3 + h3Size;
Yann Collet8a57b922016-04-04 13:49:18 +0200240 zc->chainTable = zc->hashTable + hSize;
241 zc->seqStore.buffer = zc->chainTable + chainSize;
Yann Collet863ec402016-01-28 17:56:33 +0100242 zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
243 zc->flagStaticTables = 0;
Yann Collet597847a2016-03-20 19:14:22 +0100244 zc->seqStore.buffer = ((U32*)(zc->seqStore.buffer)) + 256;
Yann Collet083fcc82015-10-25 14:06:35 +0100245
Yann Colletf48e35c2015-11-07 01:13:31 +0100246 zc->nextToUpdate = 1;
Yann Collet89db5e02015-11-13 11:27:46 +0100247 zc->nextSrc = NULL;
Yann Collet2acb5d32015-10-29 16:49:43 +0100248 zc->base = NULL;
249 zc->dictBase = NULL;
250 zc->dictLimit = 0;
251 zc->lowLimit = 0;
Yann Collet083fcc82015-10-25 14:06:35 +0100252 zc->params = params;
Yann Collet120230b2015-12-02 14:00:45 +0100253 zc->blockSize = blockSize;
Yann Collet70e8c382016-02-10 13:37:52 +0100254
Yann Collet3b719252016-03-30 19:48:05 +0200255 if (params.cParams.strategy == ZSTD_btopt) {
Yann Collet72d706a2016-03-23 20:44:12 +0100256 zc->seqStore.litFreq = (U32*)(zc->seqStore.buffer);
257 zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
258 zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
259 zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
Yann Collet48537162016-04-07 15:24:29 +0200260 zc->seqStore.matchTable = (ZSTD_match_t*)((void*)(zc->seqStore.offCodeFreq + (MaxOff+1)));
Yann Collet72d706a2016-03-23 20:44:12 +0100261 zc->seqStore.priceTable = (ZSTD_optimal_t*)((void*)(zc->seqStore.matchTable + ZSTD_OPT_NUM+1));
262 zc->seqStore.buffer = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
263 zc->seqStore.litLengthSum = 0;
264 }
inikep87d4f3d2016-03-02 15:56:24 +0100265 zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
Yann Collet597847a2016-03-20 19:14:22 +0100266 zc->seqStore.litLengthStart = (U16*) (void*)(zc->seqStore.offsetStart + maxNbSeq);
Yann Colletfadda6c2016-03-22 12:14:26 +0100267 zc->seqStore.matchLengthStart = (U16*) (void*)(zc->seqStore.litLengthStart + maxNbSeq);
268 zc->seqStore.llCodeStart = (BYTE*) (zc->seqStore.matchLengthStart + maxNbSeq);
269 zc->seqStore.mlCodeStart = zc->seqStore.llCodeStart + maxNbSeq;
270 zc->seqStore.offCodeStart = zc->seqStore.mlCodeStart + maxNbSeq;
Yann Colletdd54bbc2016-03-08 02:35:34 +0100271 zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
inikep5cccd772016-03-02 20:37:49 +0100272
Yann Collet887e7da2016-04-11 20:12:27 +0200273 zc->stage = 1;
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`.
Yann Collet887e7da2016-04-11 20:12:27 +0200282* Only works during stage 1 (i.e. after creation, but 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 Collet887e7da2016-04-11 20:12:27 +0200286 if (srcCCtx->stage!=1) return ERROR(stage_wrong);
Yann Collet7b51a292016-01-26 15:58:49 +0100287
inikep7adceef2016-03-23 15:53:38 +0100288 dstCCtx->hashLog3 = srcCCtx->hashLog3; /* must be before ZSTD_resetCCtx_advanced */
Yann Colletabb5c652016-04-11 20:42:31 +0200289 ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params, 0);
Yann Collet389648c2016-04-12 19:13:08 +0200290 dstCCtx->params.fParams.contentSizeFlag = 0; /* content size different from the one set during srcCCtx init */
Yann Collet7b51a292016-01-26 15:58:49 +0100291
292 /* copy tables */
inikep0c7456c2016-04-04 14:54:53 +0200293 { const size_t chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
Yann Collet3b719252016-03-30 19:48:05 +0200294 const size_t hSize = 1 << srcCCtx->params.cParams.hashLog;
inikep7adceef2016-03-23 15:53:38 +0100295 const size_t h3Size = (srcCCtx->hashLog3) ? 1 << srcCCtx->hashLog3 : 0;
inikep0c7456c2016-04-04 14:54:53 +0200296 const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
Yann Colletc6eea2b2016-03-19 17:18:00 +0100297 memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
298 }
Yann Collet7b51a292016-01-26 15:58:49 +0100299
Yann Collet7b51a292016-01-26 15:58:49 +0100300 /* copy dictionary pointers */
Yann Colletc6eea2b2016-03-19 17:18:00 +0100301 dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
302 dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
303 dstCCtx->nextSrc = srcCCtx->nextSrc;
304 dstCCtx->base = srcCCtx->base;
305 dstCCtx->dictBase = srcCCtx->dictBase;
306 dstCCtx->dictLimit = srcCCtx->dictLimit;
307 dstCCtx->lowLimit = srcCCtx->lowLimit;
308 dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
Yann Collet7b51a292016-01-26 15:58:49 +0100309
Yann Colletfb810d62016-01-28 00:18:06 +0100310 /* copy entropy tables */
311 dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
Yann Collet863ec402016-01-28 17:56:33 +0100312 if (srcCCtx->flagStaticTables) {
Yann Collet7b51a292016-01-26 15:58:49 +0100313 memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
Yann Colletfb810d62016-01-28 00:18:06 +0100314 memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
315 memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
316 memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
317 }
Yann Collet7b51a292016-01-26 15:58:49 +0100318
319 return 0;
320}
321
322
Yann Colletecabfe32016-03-20 16:20:06 +0100323/*! ZSTD_reduceTable() :
Yann Colletd64f4352016-03-21 00:07:42 +0100324* reduce table indexes by `reducerValue` */
Yann Colletecabfe32016-03-20 16:20:06 +0100325static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
Yann Collet89db5e02015-11-13 11:27:46 +0100326{
Yann Colletecabfe32016-03-20 16:20:06 +0100327 U32 u;
328 for (u=0 ; u < size ; u++) {
329 if (table[u] < reducerValue) table[u] = 0;
330 else table[u] -= reducerValue;
Yann Collet89db5e02015-11-13 11:27:46 +0100331 }
332}
333
Yann Colletecabfe32016-03-20 16:20:06 +0100334/*! ZSTD_reduceIndex() :
335* rescale all indexes to avoid future overflow (indexes are U32) */
336static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
337{
Yann Collet3b719252016-03-30 19:48:05 +0200338 { const U32 hSize = 1 << zc->params.cParams.hashLog;
Yann Colletecabfe32016-03-20 16:20:06 +0100339 ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
340
Yann Collet8a57b922016-04-04 13:49:18 +0200341 { const U32 chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog);
342 ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
Yann Colletecabfe32016-03-20 16:20:06 +0100343
inikep7adceef2016-03-23 15:53:38 +0100344 { const U32 h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
Yann Colletecabfe32016-03-20 16:20:06 +0100345 ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
346}
347
Yann Collet89db5e02015-11-13 11:27:46 +0100348
Yann Collet863ec402016-01-28 17:56:33 +0100349/*-*******************************************************
Yann Collet14983e72015-11-11 21:38:21 +0100350* Block entropic compression
351*********************************************************/
Yann Collet14983e72015-11-11 21:38:21 +0100352
Yann Colletfb797352016-03-13 11:08:40 +0100353/* Frame format description
354 Frame Header - [ Block Header - Block ] - Frame End
355 1) Frame Header
356 - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
357 - 1 byte - Frame Descriptor
358 2) Block Header
359 - 3 bytes, starting with a 2-bits descriptor
360 Uncompressed, Compressed, Frame End, unused
361 3) Block
362 See Block Format Description
363 4) Frame End
364 - 3 bytes, compatible with Block Header
365*/
366
367
368/* Frame descriptor
369
370 1 byte, using :
371 bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)
372 bit 4 : minmatch 4(0) or 3(1)
373 bit 5 : reserved (must be zero)
374 bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes
375
376 Optional : content size (0, 1, 2 or 8 bytes)
377 0 : unknown
378 1 : 0-255 bytes
379 2 : 256 - 65535+256
380 8 : up to 16 exa
381*/
382
383
Yann Collet59d1f792016-01-23 19:28:41 +0100384/* Block format description
385
386 Block = Literal Section - Sequences Section
387 Prerequisite : size of (compressed) block, maximum size of regenerated data
388
389 1) Literal Section
390
391 1.1) Header : 1-5 bytes
392 flags: 2 bits
393 00 compressed by Huff0
394 01 unused
395 10 is Raw (uncompressed)
396 11 is Rle
397 Note : using 01 => Huff0 with precomputed table ?
398 Note : delta map ? => compressed ?
399
400 1.1.1) Huff0-compressed literal block : 3-5 bytes
Yann Colletafe07092016-01-25 04:10:46 +0100401 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
Yann Collet59d1f792016-01-23 19:28:41 +0100402 srcSize < 1 KB => 3 bytes (2-2-10-10)
Yann Colleta1249dc2016-01-25 04:22:03 +0100403 srcSize < 16KB => 4 bytes (2-2-14-14)
Yann Collet59d1f792016-01-23 19:28:41 +0100404 else => 5 bytes (2-2-18-18)
405 big endian convention
406
407 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
408 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
409 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
410 size&255
411 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
412 size>>8&255
413 size&255
414
415 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
416 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
417 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
418 size&255
419 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
420 size>>8&255
421 size&255
422
Yann Colleta1249dc2016-01-25 04:22:03 +0100423 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
424 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
425 srcSize < 1 KB => 3 bytes (2-2-10-10)
426 srcSize < 16KB => 4 bytes (2-2-14-14)
427 else => 5 bytes (2-2-18-18)
428 big endian convention
429
430 1- CTable available (stored into workspace ?)
Yann Colletb923f652016-01-26 03:14:20 +0100431 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
Yann Colleta1249dc2016-01-25 04:22:03 +0100432
Yann Collet59d1f792016-01-23 19:28:41 +0100433
434 1.2) Literal block content
435
436 1.2.1) Huff0 block, using sizes from header
437 See Huff0 format
438
Yann Colletfb810d62016-01-28 00:18:06 +0100439 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100440
Yann Colletfb810d62016-01-28 00:18:06 +0100441 1.2.3) Raw content
Yann Collet59d1f792016-01-23 19:28:41 +0100442
Yann Colletfb810d62016-01-28 00:18:06 +0100443 1.2.4) single byte
Yann Collet59d1f792016-01-23 19:28:41 +0100444
445
446 2) Sequences section
Yann Colletfb810d62016-01-28 00:18:06 +0100447
448 - Nb Sequences : 2 bytes, little endian
449 - Control Token : 1 byte (see below)
450 - Dumps Length : 1 or 2 bytes (depending on control token)
451 - Dumps : as stated by dumps length
452 - Literal Lengths FSE table (as needed depending on encoding method)
453 - Offset Codes FSE table (as needed depending on encoding method)
454 - Match Lengths FSE table (as needed depending on encoding method)
455
456 2.1) Control Token
457 8 bits, divided as :
458 0-1 : dumpsLength
459 2-3 : MatchLength, FSE encoding method
460 4-5 : Offset Codes, FSE encoding method
461 6-7 : Literal Lengths, FSE encoding method
462
463 FSE encoding method :
464 FSE_ENCODING_RAW : uncompressed; no header
465 FSE_ENCODING_RLE : single repeated value; header 1 byte
466 FSE_ENCODING_STATIC : use prepared table; no header
467 FSE_ENCODING_DYNAMIC : read NCount
Yann Collet59d1f792016-01-23 19:28:41 +0100468*/
Yann Collet14983e72015-11-11 21:38:21 +0100469
Yann Colletd1b26842016-03-15 01:24:33 +0100470size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100471{
472 BYTE* const ostart = (BYTE* const)dst;
473
Yann Colletd1b26842016-03-15 01:24:33 +0100474 if (srcSize + ZSTD_blockHeaderSize > dstCapacity) return ERROR(dstSize_tooSmall);
Yann Collet14983e72015-11-11 21:38:21 +0100475 memcpy(ostart + ZSTD_blockHeaderSize, src, srcSize);
476
477 /* Build header */
478 ostart[0] = (BYTE)(srcSize>>16);
479 ostart[1] = (BYTE)(srcSize>>8);
480 ostart[2] = (BYTE) srcSize;
481 ostart[0] += (BYTE)(bt_raw<<6); /* is a raw (uncompressed) block */
482
483 return ZSTD_blockHeaderSize+srcSize;
484}
485
486
Yann Colletd1b26842016-03-15 01:24:33 +0100487static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100488{
489 BYTE* const ostart = (BYTE* const)dst;
Yann Colleta910dc82016-03-18 12:37:45 +0100490 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100491
Yann Colletd1b26842016-03-15 01:24:33 +0100492 if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
Yann Collet14983e72015-11-11 21:38:21 +0100493
Yann Collet59d1f792016-01-23 19:28:41 +0100494 switch(flSize)
495 {
496 case 1: /* 2 - 1 - 5 */
497 ostart[0] = (BYTE)((IS_RAW<<6) + (0<<5) + srcSize);
498 break;
499 case 2: /* 2 - 2 - 12 */
500 ostart[0] = (BYTE)((IS_RAW<<6) + (2<<4) + (srcSize >> 8));
501 ostart[1] = (BYTE)srcSize;
502 break;
503 default: /*note : should not be necessary : flSize is within {1,2,3} */
504 case 3: /* 2 - 2 - 20 */
505 ostart[0] = (BYTE)((IS_RAW<<6) + (3<<4) + (srcSize >> 16));
506 ostart[1] = (BYTE)(srcSize>>8);
507 ostart[2] = (BYTE)srcSize;
508 break;
509 }
510
511 memcpy(ostart + flSize, src, srcSize);
512 return srcSize + flSize;
Yann Collet14983e72015-11-11 21:38:21 +0100513}
514
Yann Colletd1b26842016-03-15 01:24:33 +0100515static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet14983e72015-11-11 21:38:21 +0100516{
517 BYTE* const ostart = (BYTE* const)dst;
Yann Colleta910dc82016-03-18 12:37:45 +0100518 U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100519
Yann Colletd1b26842016-03-15 01:24:33 +0100520 (void)dstCapacity; /* dstCapacity guaranteed to be >=4, hence large enough */
Yann Collet59d1f792016-01-23 19:28:41 +0100521
522 switch(flSize)
523 {
524 case 1: /* 2 - 1 - 5 */
525 ostart[0] = (BYTE)((IS_RLE<<6) + (0<<5) + srcSize);
526 break;
527 case 2: /* 2 - 2 - 12 */
528 ostart[0] = (BYTE)((IS_RLE<<6) + (2<<4) + (srcSize >> 8));
529 ostart[1] = (BYTE)srcSize;
530 break;
Yann Colleta910dc82016-03-18 12:37:45 +0100531 default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
Yann Collet59d1f792016-01-23 19:28:41 +0100532 case 3: /* 2 - 2 - 20 */
533 ostart[0] = (BYTE)((IS_RLE<<6) + (3<<4) + (srcSize >> 16));
534 ostart[1] = (BYTE)(srcSize>>8);
535 ostart[2] = (BYTE)srcSize;
536 break;
537 }
538
539 ostart[flSize] = *(const BYTE*)src;
540 return flSize+1;
Yann Collet14983e72015-11-11 21:38:21 +0100541}
542
Yann Collet59d1f792016-01-23 19:28:41 +0100543
Yann Colleta5c2c082016-03-20 01:09:18 +0100544static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
Yann Collet14983e72015-11-11 21:38:21 +0100545
Yann Colletb923f652016-01-26 03:14:20 +0100546static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +0100547 void* dst, size_t dstCapacity,
Yann Collet14983e72015-11-11 21:38:21 +0100548 const void* src, size_t srcSize)
549{
Yann Colleta910dc82016-03-18 12:37:45 +0100550 size_t const minGain = ZSTD_minGain(srcSize);
551 size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
Yann Collet14983e72015-11-11 21:38:21 +0100552 BYTE* const ostart = (BYTE*)dst;
Yann Colletafe07092016-01-25 04:10:46 +0100553 U32 singleStream = srcSize < 256;
Yann Colletb923f652016-01-26 03:14:20 +0100554 U32 hType = IS_HUF;
Yann Colleta910dc82016-03-18 12:37:45 +0100555 size_t cLitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100556
Yann Collet14983e72015-11-11 21:38:21 +0100557
Yann Colleta5c2c082016-03-20 01:09:18 +0100558 /* small ? don't even attempt compression (speed opt) */
559# define LITERAL_NOENTROPY 63
560 { size_t const minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
561 if (srcSize <= minLitSize) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
562 }
563
564 if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
Yann Colletfb810d62016-01-28 00:18:06 +0100565 if (zc->flagStaticTables && (lhSize==3)) {
Yann Colletb923f652016-01-26 03:14:20 +0100566 hType = IS_PCH;
567 singleStream = 1;
Yann Colleta910dc82016-03-18 12:37:45 +0100568 cLitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable);
Yann Colletfb810d62016-01-28 00:18:06 +0100569 } else {
Yann Colleta910dc82016-03-18 12:37:45 +0100570 cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12)
Yann Colletd1b26842016-03-15 01:24:33 +0100571 : HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12);
Yann Colletb923f652016-01-26 03:14:20 +0100572 }
Yann Collet14983e72015-11-11 21:38:21 +0100573
Yann Colleta910dc82016-03-18 12:37:45 +0100574 if ((cLitSize==0) || (cLitSize >= srcSize - minGain))
575 return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
576 if (cLitSize==1)
577 return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
Yann Collet14983e72015-11-11 21:38:21 +0100578
579 /* Build header */
Yann Collet59d1f792016-01-23 19:28:41 +0100580 switch(lhSize)
Yann Collet14983e72015-11-11 21:38:21 +0100581 {
Yann Collet59d1f792016-01-23 19:28:41 +0100582 case 3: /* 2 - 2 - 10 - 10 */
Yann Colletb923f652016-01-26 03:14:20 +0100583 ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6));
Yann Colleta910dc82016-03-18 12:37:45 +0100584 ostart[1] = (BYTE)((srcSize<<2) + (cLitSize>>8));
585 ostart[2] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100586 break;
587 case 4: /* 2 - 2 - 14 - 14 */
Yann Colletb923f652016-01-26 03:14:20 +0100588 ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100589 ostart[1] = (BYTE)(srcSize>> 2);
Yann Colleta910dc82016-03-18 12:37:45 +0100590 ostart[2] = (BYTE)((srcSize<<6) + (cLitSize>>8));
591 ostart[3] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100592 break;
Yann Colleta910dc82016-03-18 12:37:45 +0100593 default: /* should not be necessary, lhSize is only {3,4,5} */
Yann Collet59d1f792016-01-23 19:28:41 +0100594 case 5: /* 2 - 2 - 18 - 18 */
Yann Colletb923f652016-01-26 03:14:20 +0100595 ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100596 ostart[1] = (BYTE)(srcSize>>6);
Yann Colleta910dc82016-03-18 12:37:45 +0100597 ostart[2] = (BYTE)((srcSize<<2) + (cLitSize>>16));
598 ostart[3] = (BYTE)(cLitSize>>8);
599 ostart[4] = (BYTE)(cLitSize);
Yann Collet59d1f792016-01-23 19:28:41 +0100600 break;
Yann Collet14983e72015-11-11 21:38:21 +0100601 }
Yann Colleta910dc82016-03-18 12:37:45 +0100602 return lhSize+cLitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100603}
604
605
Yann Colletb44be742016-03-26 20:52:14 +0100606void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq)
607{
608 /* LL codes */
609 { static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
610 8, 9, 10, 11, 12, 13, 14, 15,
611 16, 16, 17, 17, 18, 18, 19, 19,
612 20, 20, 20, 20, 21, 21, 21, 21,
613 22, 22, 22, 22, 22, 22, 22, 22,
614 23, 23, 23, 23, 23, 23, 23, 23,
615 24, 24, 24, 24, 24, 24, 24, 24,
616 24, 24, 24, 24, 24, 24, 24, 24 };
617 const BYTE LL_deltaCode = 19;
Yann Collet5d393572016-04-07 17:19:00 +0200618 const U16* const llTable = seqStorePtr->litLengthStart;
Yann Colletb44be742016-03-26 20:52:14 +0100619 BYTE* const llCodeTable = seqStorePtr->llCodeStart;
620 size_t u;
621 for (u=0; u<nbSeq; u++) {
Yann Collet5d393572016-04-07 17:19:00 +0200622 U32 const ll = llTable[u];
Yann Colletb44be742016-03-26 20:52:14 +0100623 llCodeTable[u] = (ll>63) ? (BYTE)ZSTD_highbit(ll) + LL_deltaCode : LL_Code[ll];
Yann Collet5d393572016-04-07 17:19:00 +0200624 }
625 if (seqStorePtr->longLengthID==1)
626 llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
627 }
Yann Colletb44be742016-03-26 20:52:14 +0100628
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;
Yann Collet5d393572016-04-07 17:19:00 +0200646 const U16* const mlTable = seqStorePtr->matchLengthStart;
Yann Colletb44be742016-03-26 20:52:14 +0100647 BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
648 size_t u;
649 for (u=0; u<nbSeq; u++) {
Yann Collet5d393572016-04-07 17:19:00 +0200650 U32 const ml = mlTable[u];
Yann Colletb44be742016-03-26 20:52:14 +0100651 mlCodeTable[u] = (ml>127) ? (BYTE)ZSTD_highbit(ml) + ML_deltaCode : ML_Code[ml];
Yann Collet5d393572016-04-07 17:19:00 +0200652 }
653 if (seqStorePtr->longLengthID==2)
654 mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
655 }
Yann Colletb44be742016-03-26 20:52:14 +0100656}
657
658
Yann Colletb923f652016-01-26 03:14:20 +0100659size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +0100660 void* dst, size_t dstCapacity,
Yann Collet14983e72015-11-11 21:38:21 +0100661 size_t srcSize)
662{
Yann Colletb923f652016-01-26 03:14:20 +0100663 const seqStore_t* seqStorePtr = &(zc->seqStore);
Yann Collet14983e72015-11-11 21:38:21 +0100664 U32 count[MaxSeq+1];
665 S16 norm[MaxSeq+1];
Yann Colletfb810d62016-01-28 00:18:06 +0100666 FSE_CTable* CTable_LitLength = zc->litlengthCTable;
667 FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
668 FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
Yann Collet14983e72015-11-11 21:38:21 +0100669 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
Yann Colletb0aec172016-03-21 13:24:16 +0100670 U16* const llTable = seqStorePtr->litLengthStart;
Yann Colletfadda6c2016-03-22 12:14:26 +0100671 U16* const mlTable = seqStorePtr->matchLengthStart;
Yann Collet14983e72015-11-11 21:38:21 +0100672 const U32* const offsetTable = seqStorePtr->offsetStart;
Yann Colletd64f4352016-03-21 00:07:42 +0100673 const U32* const offsetTableEnd = seqStorePtr->offset;
Yann Collet7cbe79a2016-03-23 22:31:57 +0100674 BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
Yann Collet597847a2016-03-20 19:14:22 +0100675 BYTE* const llCodeTable = seqStorePtr->llCodeStart;
Yann Colletfadda6c2016-03-22 12:14:26 +0100676 BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
Yann Collet5054ee02015-11-23 13:34:21 +0100677 BYTE* const ostart = (BYTE*)dst;
Yann Colletd1b26842016-03-15 01:24:33 +0100678 BYTE* const oend = ostart + dstCapacity;
Yann Colleta910dc82016-03-18 12:37:45 +0100679 BYTE* op = ostart;
Yann Colletd64f4352016-03-21 00:07:42 +0100680 size_t const nbSeq = offsetTableEnd - offsetTable;
Yann Collet14983e72015-11-11 21:38:21 +0100681 BYTE* seqHead;
682
Yann Collet14983e72015-11-11 21:38:21 +0100683 /* Compress literals */
Yann Colleta5c2c082016-03-20 01:09:18 +0100684 { const BYTE* const literals = seqStorePtr->litStart;
Yann Colleta910dc82016-03-18 12:37:45 +0100685 size_t const litSize = seqStorePtr->lit - literals;
Yann Colleta5c2c082016-03-20 01:09:18 +0100686 size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize);
Yann Collet14983e72015-11-11 21:38:21 +0100687 if (ZSTD_isError(cSize)) return cSize;
688 op += cSize;
689 }
690
691 /* Sequences Header */
Yann Collet7cbe79a2016-03-23 22:31:57 +0100692 if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
Yann Colletd409db62016-03-04 14:45:31 +0100693 if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
694 else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
695 else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
Yann Collete93d6ce2016-01-31 00:58:06 +0100696 if (nbSeq==0) goto _check_compressibility;
Yann Collet14983e72015-11-11 21:38:21 +0100697
Yann Colletbe391432016-03-22 23:19:28 +0100698 /* seqHead : flags for FSE encoding type */
699 seqHead = op++;
Yann Collet14983e72015-11-11 21:38:21 +0100700
Yann Colletfb810d62016-01-28 00:18:06 +0100701#define MIN_SEQ_FOR_DYNAMIC_FSE 64
702#define MAX_SEQ_FOR_STATIC_FSE 1000
703
Yann Colletb44be742016-03-26 20:52:14 +0100704 /* convert length/distances into codes */
705 ZSTD_seqToCodes(seqStorePtr, nbSeq);
Yann Collet597847a2016-03-20 19:14:22 +0100706
Yann Collet14983e72015-11-11 21:38:21 +0100707 /* CTable for Literal Lengths */
Yann Colletfadda6c2016-03-22 12:14:26 +0100708 { U32 max = MaxLL;
709 size_t const mostFrequent = FSE_countFast(count, &max, llCodeTable, nbSeq);
710 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
711 *op++ = llCodeTable[0];
712 FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
713 LLtype = FSE_ENCODING_RLE;
714 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
715 LLtype = FSE_ENCODING_STATIC;
716 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) {
717 FSE_buildCTable(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog);
718 LLtype = FSE_ENCODING_RAW;
719 } else {
Yann Colletfadda6c2016-03-22 12:14:26 +0100720 size_t nbSeq_1 = nbSeq;
721 const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
722 if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
723 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Colletadd08d62016-03-23 01:32:41 +0100724 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
725 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
726 op += NCountSize; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100727 FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
728 LLtype = FSE_ENCODING_DYNAMIC;
729 } }
Yann Collet14983e72015-11-11 21:38:21 +0100730
Yann Colletb44be742016-03-26 20:52:14 +0100731 /* CTable for Offsets */
Yann Colletfadda6c2016-03-22 12:14:26 +0100732 { U32 max = MaxOff;
Yann Collet7cbe79a2016-03-23 22:31:57 +0100733 size_t const mostFrequent = FSE_countFast(count, &max, ofCodeTable, nbSeq);
Yann Colletfadda6c2016-03-22 12:14:26 +0100734 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collet7cbe79a2016-03-23 22:31:57 +0100735 *op++ = ofCodeTable[0];
Yann Colletfadda6c2016-03-22 12:14:26 +0100736 FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
737 Offtype = FSE_ENCODING_RLE;
738 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
739 Offtype = FSE_ENCODING_STATIC;
Yann Collet48537162016-04-07 15:24:29 +0200740 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog-1)))) {
741 FSE_buildCTable(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog);
Yann Colletfadda6c2016-03-22 12:14:26 +0100742 Offtype = FSE_ENCODING_RAW;
743 } else {
Yann Colletfadda6c2016-03-22 12:14:26 +0100744 size_t nbSeq_1 = nbSeq;
745 const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100746 if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100747 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Colletadd08d62016-03-23 01:32:41 +0100748 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
749 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
750 op += NCountSize; }
Yann Colletfadda6c2016-03-22 12:14:26 +0100751 FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
752 Offtype = FSE_ENCODING_DYNAMIC;
753 } }
754
Yann Collet14983e72015-11-11 21:38:21 +0100755 /* CTable for MatchLengths */
Yann Colletfadda6c2016-03-22 12:14:26 +0100756 { U32 max = MaxML;
757 size_t const mostFrequent = FSE_countFast(count, &max, mlCodeTable, nbSeq);
758 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collet72d706a2016-03-23 20:44:12 +0100759 *op++ = *mlCodeTable;
Yann Colletfadda6c2016-03-22 12:14:26 +0100760 FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
761 MLtype = FSE_ENCODING_RLE;
762 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
763 MLtype = FSE_ENCODING_STATIC;
764 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) {
765 FSE_buildCTable(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog);
766 MLtype = FSE_ENCODING_RAW;
767 } else {
768 size_t nbSeq_1 = nbSeq;
769 const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
770 if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
771 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
772 { size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
773 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
774 op += NCountSize; }
775 FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
776 MLtype = FSE_ENCODING_DYNAMIC;
777 } }
Yann Collet14983e72015-11-11 21:38:21 +0100778
Yann Colletbe391432016-03-22 23:19:28 +0100779 *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
Yann Colletfb810d62016-01-28 00:18:06 +0100780 zc->flagStaticTables = 0;
Yann Collet14983e72015-11-11 21:38:21 +0100781
782 /* Encoding Sequences */
Yann Collet70e45772016-03-19 18:08:32 +0100783 { BIT_CStream_t blockStream;
Yann Colleta910dc82016-03-18 12:37:45 +0100784 FSE_CState_t stateMatchLength;
785 FSE_CState_t stateOffsetBits;
786 FSE_CState_t stateLitLength;
Yann Collet14983e72015-11-11 21:38:21 +0100787
Yann Colleta910dc82016-03-18 12:37:45 +0100788 { size_t const errorCode = BIT_initCStream(&blockStream, op, oend-op);
Yann Collet597847a2016-03-20 19:14:22 +0100789 if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); } /* not enough space remaining */
Yann Collet14983e72015-11-11 21:38:21 +0100790
Yann Collet597847a2016-03-20 19:14:22 +0100791 /* first symbols */
Yann Colletfadda6c2016-03-22 12:14:26 +0100792 FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100793 FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
Yann Collet597847a2016-03-20 19:14:22 +0100794 FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
Yann Colletb0aec172016-03-21 13:24:16 +0100795 BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]);
Yann Colletb9151402016-03-26 17:18:11 +0100796 if (MEM_32bits()) BIT_flushBits(&blockStream);
Yann Collet25125972016-03-23 14:00:09 +0100797 BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]);
Yann Colletb9151402016-03-26 17:18:11 +0100798 if (MEM_32bits()) BIT_flushBits(&blockStream);
Yann Collet646693e2016-03-24 02:31:27 +0100799 BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1]);
Yann Collet597847a2016-03-20 19:14:22 +0100800 BIT_flushBits(&blockStream);
801
Yann Colletfadda6c2016-03-22 12:14:26 +0100802 { size_t n;
803 for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
Yann Colletb9151402016-03-26 17:18:11 +0100804 const BYTE ofCode = ofCodeTable[n];
Yann Collet7cbe79a2016-03-23 22:31:57 +0100805 const BYTE mlCode = mlCodeTable[n];
806 const BYTE llCode = llCodeTable[n];
807 const U32 llBits = LL_bits[llCode];
808 const U32 mlBits = ML_bits[mlCode];
Yann Colletb9151402016-03-26 17:18:11 +0100809 const U32 ofBits = ofCode; /* 32b*/ /* 64b*/
Yann Colletfadda6c2016-03-22 12:14:26 +0100810 /* (7)*/ /* (7)*/
Yann Colletb9151402016-03-26 17:18:11 +0100811 FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
812 FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
813 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
814 FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
Yann Collet582933f2016-04-11 16:25:56 +0200815 if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))
Yann Colletb9151402016-03-26 17:18:11 +0100816 BIT_flushBits(&blockStream); /* (7)*/
Yann Collet7cbe79a2016-03-23 22:31:57 +0100817 BIT_addBits(&blockStream, llTable[n], llBits);
Yann Colletb9151402016-03-26 17:18:11 +0100818 if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
Yann Collet7cbe79a2016-03-23 22:31:57 +0100819 BIT_addBits(&blockStream, mlTable[n], mlBits);
Yann Colletb9151402016-03-26 17:18:11 +0100820 if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
821 BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */
822 BIT_flushBits(&blockStream); /* (7)*/
Yann Colletfadda6c2016-03-22 12:14:26 +0100823 } }
Yann Collet14983e72015-11-11 21:38:21 +0100824
825 FSE_flushCState(&blockStream, &stateMatchLength);
826 FSE_flushCState(&blockStream, &stateOffsetBits);
827 FSE_flushCState(&blockStream, &stateLitLength);
828
Yann Colletb9151402016-03-26 17:18:11 +0100829 { size_t const streamSize = BIT_closeCStream(&blockStream);
830 if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
831 op += streamSize;
832 } }
Yann Collet14983e72015-11-11 21:38:21 +0100833
834 /* check compressibility */
Yann Collete93d6ce2016-01-31 00:58:06 +0100835_check_compressibility:
Yann Colletfadda6c2016-03-22 12:14:26 +0100836 { size_t const minGain = ZSTD_minGain(srcSize);
837 size_t const maxCSize = srcSize - minGain;
838 if ((size_t)(op-ostart) >= maxCSize) return 0; }
Yann Collet14983e72015-11-11 21:38:21 +0100839
Yann Collet5054ee02015-11-23 13:34:21 +0100840 return op - ostart;
Yann Collet14983e72015-11-11 21:38:21 +0100841}
842
843
Yann Collet95cd0c22016-03-08 18:24:21 +0100844/*! ZSTD_storeSeq() :
845 Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
846 `offsetCode` : distance to match, or 0 == repCode.
847 `matchCode` : matchLength - MINMATCH
Yann Collet14983e72015-11-11 21:38:21 +0100848*/
849MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, size_t offsetCode, size_t matchCode)
850{
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100851#if 0 /* for debug */
Yann Collet14983e72015-11-11 21:38:21 +0100852 static const BYTE* g_start = NULL;
Yann Colletb0aec172016-03-21 13:24:16 +0100853 const U32 pos = (U32)(literals - g_start);
Yann Collet14983e72015-11-11 21:38:21 +0100854 if (g_start==NULL) g_start = literals;
Yann Collet582933f2016-04-11 16:25:56 +0200855 if ((pos > 5810300) && (pos < 5810500))
Yann Colletb9151402016-03-26 17:18:11 +0100856 printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
Yann Collet433a5cc2016-03-25 11:43:48 +0100857 pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
Yann Collet14983e72015-11-11 21:38:21 +0100858#endif
inikep5cc4efd2016-03-25 10:52:25 +0100859 ZSTD_statsUpdatePrices(&seqStorePtr->stats, litLength, literals, offsetCode, matchCode);
Yann Collet14983e72015-11-11 21:38:21 +0100860
861 /* copy Literals */
862 ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
863 seqStorePtr->lit += litLength;
864
865 /* literal Length */
Yann Collet5d393572016-04-07 17:19:00 +0200866 if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->litLength - seqStorePtr->litLengthStart); }
867 *seqStorePtr->litLength++ = (U16)litLength;
Yann Collet14983e72015-11-11 21:38:21 +0100868
869 /* match offset */
Yann Collet646693e2016-03-24 02:31:27 +0100870 *(seqStorePtr->offset++) = (U32)offsetCode + 1;
Yann Collet14983e72015-11-11 21:38:21 +0100871
872 /* match Length */
Yann Collet5d393572016-04-07 17:19:00 +0200873 if (matchCode>0xFFFF) { seqStorePtr->longLengthID = 2; seqStorePtr->longLengthPos = (U32)(seqStorePtr->matchLength - seqStorePtr->matchLengthStart); }
874 *seqStorePtr->matchLength++ = (U16)matchCode;
Yann Collet14983e72015-11-11 21:38:21 +0100875}
876
877
Yann Collet7d360282016-02-12 00:07:30 +0100878/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +0100879* Match length counter
880***************************************/
Yann Collet5054ee02015-11-23 13:34:21 +0100881static unsigned ZSTD_NbCommonBytes (register size_t val)
Yann Collet14983e72015-11-11 21:38:21 +0100882{
Yann Collet863ec402016-01-28 17:56:33 +0100883 if (MEM_isLittleEndian()) {
884 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100885# if defined(_MSC_VER) && defined(_WIN64)
886 unsigned long r = 0;
887 _BitScanForward64( &r, (U64)val );
Yann Colletd6080882015-12-09 09:05:22 +0100888 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100889# elif defined(__GNUC__) && (__GNUC__ >= 3)
890 return (__builtin_ctzll((U64)val) >> 3);
891# else
892 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 };
893 return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
894# endif
Yann Collet863ec402016-01-28 17:56:33 +0100895 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100896# if defined(_MSC_VER)
897 unsigned long r=0;
898 _BitScanForward( &r, (U32)val );
Yann Colletd6080882015-12-09 09:05:22 +0100899 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100900# elif defined(__GNUC__) && (__GNUC__ >= 3)
901 return (__builtin_ctz((U32)val) >> 3);
902# else
903 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 };
904 return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
905# endif
906 }
Yann Collet863ec402016-01-28 17:56:33 +0100907 } else { /* Big Endian CPU */
908 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100909# if defined(_MSC_VER) && defined(_WIN64)
910 unsigned long r = 0;
911 _BitScanReverse64( &r, val );
912 return (unsigned)(r>>3);
913# elif defined(__GNUC__) && (__GNUC__ >= 3)
914 return (__builtin_clzll(val) >> 3);
915# else
916 unsigned r;
917 const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
918 if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
919 if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
920 r += (!val);
921 return r;
922# endif
Yann Collet863ec402016-01-28 17:56:33 +0100923 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100924# if defined(_MSC_VER)
925 unsigned long r = 0;
926 _BitScanReverse( &r, (unsigned long)val );
927 return (unsigned)(r>>3);
928# elif defined(__GNUC__) && (__GNUC__ >= 3)
929 return (__builtin_clz((U32)val) >> 3);
930# else
931 unsigned r;
932 if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
933 r += (!val);
934 return r;
935# endif
Yann Collet863ec402016-01-28 17:56:33 +0100936 } }
Yann Collet14983e72015-11-11 21:38:21 +0100937}
938
939
Yann Collet5054ee02015-11-23 13:34:21 +0100940static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
Yann Collet14983e72015-11-11 21:38:21 +0100941{
942 const BYTE* const pStart = pIn;
943
Yann Colletfb810d62016-01-28 00:18:06 +0100944 while ((pIn<pInLimit-(sizeof(size_t)-1))) {
Yann Collet7d360282016-02-12 00:07:30 +0100945 size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);
Yann Collet14983e72015-11-11 21:38:21 +0100946 if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
947 pIn += ZSTD_NbCommonBytes(diff);
948 return (size_t)(pIn - pStart);
949 }
Yann Collet14983e72015-11-11 21:38:21 +0100950 if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
951 if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
952 if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
953 return (size_t)(pIn - pStart);
954}
955
Yann Collet04b12d82016-02-11 06:23:24 +0100956/** ZSTD_count_2segments() :
Yann Collet7d360282016-02-12 00:07:30 +0100957* can count match length with `ip` & `match` in 2 different segments.
Yann Collet5054ee02015-11-23 13:34:21 +0100958* convention : on reaching mEnd, match count continue starting from iStart
959*/
960static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
961{
962 size_t matchLength;
963 const BYTE* vEnd = ip + (mEnd - match);
964 if (vEnd > iEnd) vEnd = iEnd;
965 matchLength = ZSTD_count(ip, match, vEnd);
966 if (match + matchLength == mEnd)
967 matchLength += ZSTD_count(ip+matchLength, iStart, iEnd);
968 return matchLength;
969}
970
Yann Collet14983e72015-11-11 21:38:21 +0100971
Yann Collet863ec402016-01-28 17:56:33 +0100972/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +0100973* Hashes
Yann Colletf3eca252015-10-22 15:31:46 +0100974***************************************/
inikepcc52a972016-02-19 10:09:35 +0100975static const U32 prime3bytes = 506832829U;
976static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32-24)) * prime3bytes) >> (32-h) ; }
inikepe2446b02016-03-07 10:07:08 +0100977static size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); }
inikepcc52a972016-02-19 10:09:35 +0100978
Yann Collet4b100f42015-10-30 15:49:48 +0100979static const U32 prime4bytes = 2654435761U;
Yann Collet863ec402016-01-28 17:56:33 +0100980static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100981static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
Yann Collet2acb5d32015-10-29 16:49:43 +0100982
Yann Collet4b100f42015-10-30 15:49:48 +0100983static const U64 prime5bytes = 889523592379ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100984static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100985static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100986
987static const U64 prime6bytes = 227718039650203ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100988static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100989static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100990
Yann Collet14983e72015-11-11 21:38:21 +0100991static const U64 prime7bytes = 58295818150454627ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100992static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
Yann Collet4f0a3932016-02-07 04:00:27 +0100993static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); }
Yann Collet1f44b3f2015-11-05 17:32:18 +0100994
Yann Collet5be2dd22015-11-11 13:43:58 +0100995static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
Yann Collet4b100f42015-10-30 15:49:48 +0100996{
997 switch(mls)
998 {
999 default:
Yann Collet5be2dd22015-11-11 13:43:58 +01001000 case 4: return ZSTD_hash4Ptr(p, hBits);
1001 case 5: return ZSTD_hash5Ptr(p, hBits);
1002 case 6: return ZSTD_hash6Ptr(p, hBits);
1003 case 7: return ZSTD_hash7Ptr(p, hBits);
Yann Collet4b100f42015-10-30 15:49:48 +01001004 }
1005}
Yann Collet2acb5d32015-10-29 16:49:43 +01001006
Yann Collet863ec402016-01-28 17:56:33 +01001007
Yann Collet2ce49232016-02-02 14:36:49 +01001008/*-*************************************
Yann Collet1f44b3f2015-11-05 17:32:18 +01001009* Fast Scan
1010***************************************/
Yann Collet417890c2015-12-04 17:16:37 +01001011static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
1012{
1013 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001014 const U32 hBits = zc->params.cParams.hashLog;
Yann Collet417890c2015-12-04 17:16:37 +01001015 const BYTE* const base = zc->base;
1016 const BYTE* ip = base + zc->nextToUpdate;
Yann Collet2ce49232016-02-02 14:36:49 +01001017 const BYTE* const iend = ((const BYTE*)end) - 8;
Yann Collet37f3d1b2016-03-19 15:11:42 +01001018 const size_t fastHashFillStep = 3;
Yann Collet417890c2015-12-04 17:16:37 +01001019
Yann Colletfb810d62016-01-28 00:18:06 +01001020 while(ip <= iend) {
Yann Collet417890c2015-12-04 17:16:37 +01001021 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
Yann Collet37f3d1b2016-03-19 15:11:42 +01001022 ip += fastHashFillStep;
Yann Collet417890c2015-12-04 17:16:37 +01001023 }
1024}
1025
1026
Yann Collet1f44b3f2015-11-05 17:32:18 +01001027FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001028void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
Yann Collet89db5e02015-11-13 11:27:46 +01001029 const void* src, size_t srcSize,
1030 const U32 mls)
Yann Collet1f44b3f2015-11-05 17:32:18 +01001031{
Yann Collet417890c2015-12-04 17:16:37 +01001032 U32* const hashTable = zc->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001033 const U32 hBits = zc->params.cParams.hashLog;
Yann Colletc3652152015-11-24 14:06:07 +01001034 seqStore_t* seqStorePtr = &(zc->seqStore);
1035 const BYTE* const base = zc->base;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001036 const BYTE* const istart = (const BYTE*)src;
Yann Collet805a52a2015-11-06 10:52:17 +01001037 const BYTE* ip = istart;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001038 const BYTE* anchor = istart;
Yann Colletd94efbf2015-12-29 14:29:08 +01001039 const U32 lowIndex = zc->dictLimit;
1040 const BYTE* const lowest = base + lowIndex;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001041 const BYTE* const iend = istart + srcSize;
1042 const BYTE* const ilimit = iend - 8;
Yann Collet89db5e02015-11-13 11:27:46 +01001043 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001044
Yann Collet1f44b3f2015-11-05 17:32:18 +01001045 /* init */
Yann Collet743402c2015-11-20 12:03:53 +01001046 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +01001047 if (ip < lowest+REPCODE_STARTVALUE) ip = lowest+REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001048
1049 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001050 while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
Yann Collet5054ee02015-11-23 13:34:21 +01001051 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +01001052 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +01001053 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Colletd94efbf2015-12-29 14:29:08 +01001054 const U32 matchIndex = hashTable[h];
1055 const BYTE* match = base + matchIndex;
Yann Collet96ffa422016-01-02 01:16:28 +01001056 const U32 current = (U32)(ip-base);
1057 hashTable[h] = current; /* update hash table */
Yann Collet1f44b3f2015-11-05 17:32:18 +01001058
Yann Colletfb810d62016-01-28 00:18:06 +01001059 if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) { /* note : by construction, offset_1 <= current */
inikep7bc19b62016-04-06 09:46:01 +02001060 mlCode = ZSTD_count(ip+1+EQUAL_READ32, ip+1+EQUAL_READ32-offset_1, iend) + EQUAL_READ32;
Yann Collet402fdcf2015-11-20 12:46:08 +01001061 ip++;
inikep7bc19b62016-04-06 09:46:01 +02001062 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mlCode-MINMATCH);
inikep59453082016-03-16 15:35:14 +01001063 } else {
Yann Colletd94efbf2015-12-29 14:29:08 +01001064 if ( (matchIndex <= lowIndex) ||
Yann Colletfb810d62016-01-28 00:18:06 +01001065 (MEM_read32(match) != MEM_read32(ip)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001066 ip += ((ip-anchor) >> g_searchStrength) + 1;
1067 continue;
1068 }
inikep7bc19b62016-04-06 09:46:01 +02001069 mlCode = ZSTD_count(ip+EQUAL_READ32, match+EQUAL_READ32, iend) + EQUAL_READ32;
Yann Collet402fdcf2015-11-20 12:46:08 +01001070 offset = ip-match;
Yann Collet5054ee02015-11-23 13:34:21 +01001071 while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +01001072 offset_2 = offset_1;
1073 offset_1 = offset;
inikep59453082016-03-16 15:35:14 +01001074
inikep7bc19b62016-04-06 09:46:01 +02001075 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mlCode-MINMATCH);
Yann Collet402fdcf2015-11-20 12:46:08 +01001076 }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001077
Yann Collet402fdcf2015-11-20 12:46:08 +01001078 /* match found */
inikep7bc19b62016-04-06 09:46:01 +02001079 ip += mlCode;
Yann Collet402fdcf2015-11-20 12:46:08 +01001080 anchor = ip;
1081
Yann Colletfb810d62016-01-28 00:18:06 +01001082 if (ip <= ilimit) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001083 /* Fill Table */
Yann Colletecd651b2016-01-07 15:35:18 +01001084 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 +01001085 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1086 /* check immediate repcode */
1087 while ( (ip <= ilimit)
Yann Colletfb810d62016-01-28 00:18:06 +01001088 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001089 /* store sequence */
inikep7bc19b62016-04-06 09:46:01 +02001090 size_t const rlCode = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-offset_2, iend) + EQUAL_READ32;
Yann Collet70e45772016-03-19 18:08:32 +01001091 { 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 +01001092 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
inikep7bc19b62016-04-06 09:46:01 +02001093 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rlCode-MINMATCH);
1094 ip += rlCode;
Yann Collet402fdcf2015-11-20 12:46:08 +01001095 anchor = ip;
1096 continue; /* faster when present ... (?) */
Yann Colletfb810d62016-01-28 00:18:06 +01001097 } } }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001098
Yann Collet70e45772016-03-19 18:08:32 +01001099 /* Last Literals */
1100 { size_t const lastLLSize = iend - anchor;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001101 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1102 seqStorePtr->lit += lastLLSize;
1103 }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001104}
1105
1106
Yann Collet82260dd2016-02-11 07:14:25 +01001107static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
Yann Collet59d1f792016-01-23 19:28:41 +01001108 const void* src, size_t srcSize)
Yann Collet1f44b3f2015-11-05 17:32:18 +01001109{
Yann Collet3b719252016-03-30 19:48:05 +02001110 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001111 switch(mls)
1112 {
1113 default:
1114 case 4 :
Yann Collet59d1f792016-01-23 19:28:41 +01001115 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001116 case 5 :
Yann Collet59d1f792016-01-23 19:28:41 +01001117 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001118 case 6 :
Yann Collet59d1f792016-01-23 19:28:41 +01001119 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001120 case 7 :
Yann Collet59d1f792016-01-23 19:28:41 +01001121 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001122 }
1123}
Yann Colletf3eca252015-10-22 15:31:46 +01001124
Yann Colletf3eca252015-10-22 15:31:46 +01001125
Yann Collet82260dd2016-02-11 07:14:25 +01001126static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
Yann Collet59d1f792016-01-23 19:28:41 +01001127 const void* src, size_t srcSize,
1128 const U32 mls)
Yann Collet89db5e02015-11-13 11:27:46 +01001129{
1130 U32* hashTable = ctx->hashTable;
Yann Collet3b719252016-03-30 19:48:05 +02001131 const U32 hBits = ctx->params.cParams.hashLog;
Yann Collet89db5e02015-11-13 11:27:46 +01001132 seqStore_t* seqStorePtr = &(ctx->seqStore);
1133 const BYTE* const base = ctx->base;
1134 const BYTE* const dictBase = ctx->dictBase;
1135 const BYTE* const istart = (const BYTE*)src;
1136 const BYTE* ip = istart;
1137 const BYTE* anchor = istart;
1138 const U32 lowLimit = ctx->lowLimit;
Yann Collet5054ee02015-11-23 13:34:21 +01001139 const BYTE* const dictStart = dictBase + lowLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001140 const U32 dictLimit = ctx->dictLimit;
Yann Collet743402c2015-11-20 12:03:53 +01001141 const BYTE* const lowPrefixPtr = base + dictLimit;
1142 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001143 const BYTE* const iend = istart + srcSize;
1144 const BYTE* const ilimit = iend - 8;
1145
Yann Collet138e89c2015-11-17 14:26:54 +01001146 U32 offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001147
1148
1149 /* init */
1150 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +01001151 /* skip first position to avoid read overflow during repcode match check */
Yann Colletfb810d62016-01-28 00:18:06 +01001152 hashTable[ZSTD_hashPtr(ip+0, hBits, mls)] = (U32)(ip-base+0);
Yann Collet61e16ce2016-01-31 02:04:15 +01001153 ip += REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001154
1155 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001156 while (ip < ilimit) { /* < instead of <=, because (ip+1) */
Yann Collet89db5e02015-11-13 11:27:46 +01001157 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Collet743402c2015-11-20 12:03:53 +01001158 const U32 matchIndex = hashTable[h];
Yann Collet89db5e02015-11-13 11:27:46 +01001159 const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
Yann Collet6bcdeac2015-11-26 11:43:00 +01001160 const BYTE* match = matchBase + matchIndex;
Yann Collet89db5e02015-11-13 11:27:46 +01001161 const U32 current = (U32)(ip-base);
Yann Collet743402c2015-11-20 12:03:53 +01001162 const U32 repIndex = current + 1 - offset_1;
Yann Collet402fdcf2015-11-20 12:46:08 +01001163 const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
Yann Collet89db5e02015-11-13 11:27:46 +01001164 const BYTE* repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001165 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +01001166 U32 offset;
Yann Collet89db5e02015-11-13 11:27:46 +01001167 hashTable[h] = current; /* update hash table */
1168
Yann Collet52447382016-03-20 16:00:00 +01001169 if ( ((repIndex >= dictLimit) || (repIndex <= dictLimit-4))
Yann Colletfb810d62016-01-28 00:18:06 +01001170 && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001171 const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
inikep7bc19b62016-04-06 09:46:01 +02001172 mlCode = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repMatchEnd, lowPrefixPtr) + EQUAL_READ32;
Yann Collet743402c2015-11-20 12:03:53 +01001173 ip++;
inikep7bc19b62016-04-06 09:46:01 +02001174 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mlCode-MINMATCH);
Yann Colletfb810d62016-01-28 00:18:06 +01001175 } else {
Yann Collet402fdcf2015-11-20 12:46:08 +01001176 if ( (matchIndex < lowLimit) ||
Yann Collet52447382016-03-20 16:00:00 +01001177 (MEM_read32(match) != MEM_read32(ip)) ) {
1178 ip += ((ip-anchor) >> g_searchStrength) + 1;
1179 continue;
1180 }
1181 { const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001182 const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
inikep7bc19b62016-04-06 09:46:01 +02001183 mlCode = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iend, matchEnd, lowPrefixPtr) + EQUAL_READ32;
Yann Colletfb810d62016-01-28 00:18:06 +01001184 while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +01001185 offset = current - matchIndex;
1186 offset_2 = offset_1;
1187 offset_1 = offset;
inikep7bc19b62016-04-06 09:46:01 +02001188 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset + ZSTD_REP_MOVE, mlCode-MINMATCH);
Yann Colletfb810d62016-01-28 00:18:06 +01001189 } }
Yann Collet89db5e02015-11-13 11:27:46 +01001190
Yann Collet5054ee02015-11-23 13:34:21 +01001191 /* found a match : store it */
inikep7bc19b62016-04-06 09:46:01 +02001192 ip += mlCode;
Yann Collet402fdcf2015-11-20 12:46:08 +01001193 anchor = ip;
1194
Yann Colletfb810d62016-01-28 00:18:06 +01001195 if (ip <= ilimit) {
Yann Collet6bcdeac2015-11-26 11:43:00 +01001196 /* Fill Table */
Yann Collet239cc282015-11-23 16:17:21 +01001197 hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
Yann Collet402fdcf2015-11-20 12:46:08 +01001198 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1199 /* check immediate repcode */
Yann Colletfb810d62016-01-28 00:18:06 +01001200 while (ip <= ilimit) {
Yann Collet27caf2a2016-04-01 15:48:48 +02001201 U32 const current2 = (U32)(ip-base);
1202 U32 const repIndex2 = current2 - offset_2;
Yann Collet402fdcf2015-11-20 12:46:08 +01001203 const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
Yann Collet743402c2015-11-20 12:03:53 +01001204 if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
Yann Colletfb810d62016-01-28 00:18:06 +01001205 && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
Yann Collet5054ee02015-11-23 13:34:21 +01001206 const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
inikep7bc19b62016-04-06 09:46:01 +02001207 size_t repLength2 = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch2+EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32;
Yann Collet5054ee02015-11-23 13:34:21 +01001208 U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
inikep7bc19b62016-04-06 09:46:01 +02001209 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2-MINMATCH);
Yann Collet5054ee02015-11-23 13:34:21 +01001210 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
inikep7bc19b62016-04-06 09:46:01 +02001211 ip += repLength2;
Yann Collet402fdcf2015-11-20 12:46:08 +01001212 anchor = ip;
1213 continue;
1214 }
Yann Collet743402c2015-11-20 12:03:53 +01001215 break;
Yann Colletfb810d62016-01-28 00:18:06 +01001216 } } }
Yann Collet89db5e02015-11-13 11:27:46 +01001217
1218 /* Last Literals */
Yann Collet70e45772016-03-19 18:08:32 +01001219 { size_t const lastLLSize = iend - anchor;
Yann Collet89db5e02015-11-13 11:27:46 +01001220 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1221 seqStorePtr->lit += lastLLSize;
1222 }
Yann Collet89db5e02015-11-13 11:27:46 +01001223}
1224
1225
Yann Collet82260dd2016-02-11 07:14:25 +01001226static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
Yann Collet89db5e02015-11-13 11:27:46 +01001227 const void* src, size_t srcSize)
1228{
Yann Collet3b719252016-03-30 19:48:05 +02001229 const U32 mls = ctx->params.cParams.searchLength;
Yann Collet89db5e02015-11-13 11:27:46 +01001230 switch(mls)
1231 {
1232 default:
1233 case 4 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001234 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001235 case 5 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001236 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001237 case 6 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001238 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001239 case 7 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001240 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001241 }
1242}
1243
1244
inikep75716852016-04-06 12:34:42 +02001245
inikep2db1eb72016-04-06 17:14:19 +02001246
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 Collet8a57b922016-04-04 13:49:18 +02001259 U32* const bt = zc->chainTable;
1260 const U32 btLog = zc->params.cParams.chainLog - 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 Collet793c6492016-04-09 20:32:00 +02001288#if 0 /* 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);
Yann Collet8a57b922016-04-04 13:49:18 +02001361 U32* const bt = zc->chainTable;
1362 const U32 btLog = zc->params.cParams.chainLog - 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;
Yann Collet72e84cf2015-12-31 19:08:44 +01001376 U32 matchEndIdx = current+8;
Yann Collet03526e12015-11-23 15:29:15 +01001377 U32 dummy32; /* to be nullified at the end */
inikep64d7bcb2016-04-07 19:14:09 +02001378 size_t bestLength = 0;
Yann Collet03526e12015-11-23 15:29:15 +01001379
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)) )
inikep75716852016-04-06 12:34:42 +02001402 bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex;
Yann Collet03526e12015-11-23 15:29:15 +01001403 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;
inikep64d7bcb2016-04-07 19:14:09 +02001426 return bestLength;
Yann Collet03526e12015-11-23 15:29:15 +01001427}
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
inikep64d7bcb2016-04-07 19:14:09 +02001478
1479
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
inikep64d7bcb2016-04-07 19:14:09 +02001510/* ***********************
1511* Hash Chain
1512*************************/
1513
1514#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
1515
inikepafe1f792016-04-07 19:50:03 +02001516
inikep64d7bcb2016-04-07 19:14:09 +02001517/* Update chains up to ip (excluded)
1518 Assumption : always within prefix (ie. not within extDict) */
1519FORCE_INLINE
1520U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
1521{
1522 U32* const hashTable = zc->hashTable;
1523 const U32 hashLog = zc->params.cParams.hashLog;
1524 U32* const chainTable = zc->chainTable;
1525 const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1;
1526 const BYTE* const base = zc->base;
1527 const U32 target = (U32)(ip - base);
1528 U32 idx = zc->nextToUpdate;
1529
1530 while(idx < target) {
1531 size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
1532 NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
1533 hashTable[h] = idx;
1534 idx++;
1535 }
1536
1537 zc->nextToUpdate = target;
1538 return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
1539}
1540
1541
1542
1543FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
1544size_t ZSTD_HcFindBestMatch_generic (
1545 ZSTD_CCtx* zc, /* Index table will be updated */
1546 const BYTE* const ip, const BYTE* const iLimit,
1547 size_t* offsetPtr,
1548 const U32 maxNbAttempts, const U32 mls, const U32 extDict)
1549{
1550 U32* const chainTable = zc->chainTable;
1551 const U32 chainSize = (1 << zc->params.cParams.chainLog);
1552 const U32 chainMask = chainSize-1;
1553 const BYTE* const base = zc->base;
1554 const BYTE* const dictBase = zc->dictBase;
1555 const U32 dictLimit = zc->dictLimit;
1556 const BYTE* const prefixStart = base + dictLimit;
1557 const BYTE* const dictEnd = dictBase + dictLimit;
1558 const U32 lowLimit = zc->lowLimit;
1559 const U32 current = (U32)(ip-base);
1560 const U32 minChain = current > chainSize ? current - chainSize : 0;
1561 int nbAttempts=maxNbAttempts;
1562 size_t ml=EQUAL_READ32-1;
1563
1564 /* HC4 match finder */
1565 U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
1566
1567 for ( ; (matchIndex>lowLimit) && (nbAttempts) ; nbAttempts--) {
1568 const BYTE* match;
1569 size_t currentMl=0;
1570 if ((!extDict) || matchIndex >= dictLimit) {
1571 match = base + matchIndex;
1572 if (match[ml] == ip[ml]) /* potentially better */
1573 currentMl = ZSTD_count(ip, match, iLimit);
1574 } else {
1575 match = dictBase + matchIndex;
1576 if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
1577 currentMl = ZSTD_count_2segments(ip+EQUAL_READ32, match+EQUAL_READ32, iLimit, dictEnd, prefixStart) + EQUAL_READ32;
1578 }
1579
1580 /* save best solution */
1581 if (currentMl > ml) { ml = currentMl; *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; if (ip+currentMl == iLimit) break; /* best possible, and avoid read overflow*/ }
1582
1583 if (matchIndex <= minChain) break;
1584 matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
1585 }
1586
1587 return ml;
1588}
1589
1590
1591FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
1592 ZSTD_CCtx* zc,
1593 const BYTE* ip, const BYTE* const iLimit,
1594 size_t* offsetPtr,
1595 const U32 maxNbAttempts, const U32 matchLengthSearch)
1596{
1597 switch(matchLengthSearch)
1598 {
1599 default :
1600 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
1601 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
1602 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
1603 }
1604}
1605
1606
1607FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
1608 ZSTD_CCtx* zc,
1609 const BYTE* ip, const BYTE* const iLimit,
1610 size_t* offsetPtr,
1611 const U32 maxNbAttempts, const U32 matchLengthSearch)
1612{
1613 switch(matchLengthSearch)
1614 {
1615 default :
1616 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
1617 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
1618 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
1619 }
1620}
1621
1622/* The optimal parser */
1623#include "zstd_opt.h"
1624
1625
Yann Collet287b7d92015-11-22 13:24:05 +01001626/* *******************************
inikep64d7bcb2016-04-07 19:14:09 +02001627* Common parser - lazy strategy
inikepfaa8d8a2016-04-05 19:01:10 +02001628*********************************/
Yann Collet96b9f0b2015-11-04 03:52:54 +01001629FORCE_INLINE
inikep64d7bcb2016-04-07 19:14:09 +02001630void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
1631 const void* src, size_t srcSize,
1632 const U32 searchMethod, const U32 depth)
Yann Collet96b9f0b2015-11-04 03:52:54 +01001633{
inikepfaa8d8a2016-04-05 19:01:10 +02001634 seqStore_t* seqStorePtr = &(ctx->seqStore);
1635 const BYTE* const istart = (const BYTE*)src;
1636 const BYTE* ip = istart;
1637 const BYTE* anchor = istart;
1638 const BYTE* const iend = istart + srcSize;
1639 const BYTE* const ilimit = iend - 8;
1640 const BYTE* const base = ctx->base + ctx->dictLimit;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001641
Yann Collet793c6492016-04-09 20:32:00 +02001642 U32 const maxSearches = 1 << ctx->params.cParams.searchLog;
1643 U32 const mls = ctx->params.cParams.searchLength;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001644
inikep64d7bcb2016-04-07 19:14:09 +02001645 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
1646 size_t* offsetPtr,
1647 U32 maxNbAttempts, U32 matchLengthSearch);
1648 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
1649
inikepfaa8d8a2016-04-05 19:01:10 +02001650 /* init */
1651 U32 rep[ZSTD_REP_INIT];
Yann Colletea63bb72016-04-08 15:25:32 +02001652 { U32 i ; for (i=0; i<ZSTD_REP_INIT; i++) rep[i]=REPCODE_STARTVALUE; }
Yann Collet96b9f0b2015-11-04 03:52:54 +01001653
inikep64d7bcb2016-04-07 19:14:09 +02001654 ctx->nextToUpdate3 = ctx->nextToUpdate;
inikepfaa8d8a2016-04-05 19:01:10 +02001655 ZSTD_resetSeqStore(seqStorePtr);
1656 if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001657
inikepfaa8d8a2016-04-05 19:01:10 +02001658 /* Match Loop */
1659 while (ip < ilimit) {
1660 size_t matchLength=0;
1661 size_t offset=0;
1662 const BYTE* start=ip+1;
Yann Collet5106a762015-11-05 15:00:24 +01001663
inikepfaa8d8a2016-04-05 19:01:10 +02001664 /* check repCode */
inikep64d7bcb2016-04-07 19:14:09 +02001665 if (MEM_read32(ip+1) == MEM_read32(ip+1 - rep[0])) {
inikepfaa8d8a2016-04-05 19:01:10 +02001666 /* repcode : we take it */
inikep64d7bcb2016-04-07 19:14:09 +02001667 matchLength = ZSTD_count(ip+1+EQUAL_READ32, ip+1+EQUAL_READ32-rep[0], iend) + EQUAL_READ32;
1668 if (depth==0) goto _storeSequence;
Yann Collet5106a762015-11-05 15:00:24 +01001669 }
Yann Collet5be2dd22015-11-11 13:43:58 +01001670
inikepfaa8d8a2016-04-05 19:01:10 +02001671 /* first search (depth 0) */
1672 { size_t offsetFound = 99999999;
inikep64d7bcb2016-04-07 19:14:09 +02001673 size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
inikepfaa8d8a2016-04-05 19:01:10 +02001674 if (ml2 > matchLength)
inikep75716852016-04-06 12:34:42 +02001675 matchLength = ml2, start = ip, offset=offsetFound;
inikepfaa8d8a2016-04-05 19:01:10 +02001676 }
Yann Collet5106a762015-11-05 15:00:24 +01001677
inikep7bc19b62016-04-06 09:46:01 +02001678 if (matchLength < EQUAL_READ32) {
inikepfaa8d8a2016-04-05 19:01:10 +02001679 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1680 continue;
1681 }
1682
inikep64d7bcb2016-04-07 19:14:09 +02001683 /* let's try to find a better solution */
1684 if (depth>=1)
1685 while (ip<ilimit) {
1686 ip ++;
1687 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - rep[0]))) {
1688 size_t const mlRep = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-rep[0], iend) + EQUAL_READ32;
1689 int const gain2 = (int)(mlRep * 3);
1690 int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
1691 if ((mlRep >= EQUAL_READ32) && (gain2 > gain1))
1692 matchLength = mlRep, offset = 0, start = ip;
1693 }
1694 { size_t offset2=99999999;
1695 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1696 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1697 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
1698 if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
1699 matchLength = ml2, offset = offset2, start = ip;
1700 continue; /* search a better one */
1701 } }
inikepfaa8d8a2016-04-05 19:01:10 +02001702
inikep64d7bcb2016-04-07 19:14:09 +02001703 /* let's find an even better one */
1704 if ((depth==2) && (ip<ilimit)) {
1705 ip ++;
1706 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - rep[0]))) {
1707 size_t const ml2 = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-rep[0], iend) + EQUAL_READ32;
1708 int const gain2 = (int)(ml2 * 4);
1709 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
1710 if ((ml2 >= EQUAL_READ32) && (gain2 > gain1))
1711 matchLength = ml2, offset = 0, start = ip;
1712 }
1713 { size_t offset2=99999999;
1714 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1715 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1716 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
1717 if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
1718 matchLength = ml2, offset = offset2, start = ip;
1719 continue;
1720 } } }
1721 break; /* nothing found : store previous solution */
1722 }
1723
1724 /* catch up */
1725 if (offset) {
1726 while ((start>anchor) && (start>base+offset-ZSTD_REP_MOVE) && (start[-1] == start[-1-offset+ZSTD_REP_MOVE])) /* only search for offset within prefix */
1727 { start--; matchLength++; }
1728 rep[1] = rep[0]; rep[0] = (U32)(offset - ZSTD_REP_MOVE);
1729 }
1730
inikepfaa8d8a2016-04-05 19:01:10 +02001731 /* store sequence */
inikep64d7bcb2016-04-07 19:14:09 +02001732_storeSequence:
inikepfaa8d8a2016-04-05 19:01:10 +02001733 { size_t const litLength = start - anchor;
1734 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
1735 anchor = ip = start + matchLength;
1736 }
Yann Collet48537162016-04-07 15:24:29 +02001737
inikepfaa8d8a2016-04-05 19:01:10 +02001738 /* check immediate repcode */
1739 while ( (ip <= ilimit)
1740 && (MEM_read32(ip) == MEM_read32(ip - rep[1])) ) {
1741 /* store sequence */
inikep7bc19b62016-04-06 09:46:01 +02001742 matchLength = ZSTD_count(ip+EQUAL_READ32, ip+EQUAL_READ32-rep[1], iend) + EQUAL_READ32;
inikep64d7bcb2016-04-07 19:14:09 +02001743 offset = rep[1]; rep[1] = rep[0]; rep[0] = (U32)offset; /* swap repcodes */
inikep7bc19b62016-04-06 09:46:01 +02001744 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
1745 ip += matchLength;
inikepfaa8d8a2016-04-05 19:01:10 +02001746 anchor = ip;
1747 continue; /* faster when present ... (?) */
inikep64d7bcb2016-04-07 19:14:09 +02001748 } }
inikepfaa8d8a2016-04-05 19:01:10 +02001749
1750 /* Last Literals */
1751 { size_t const lastLLSize = iend - anchor;
1752 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1753 seqStorePtr->lit += lastLLSize;
1754 ZSTD_statsUpdatePrices(&seqStorePtr->stats, lastLLSize, anchor, 0, 0);
Yann Collet5106a762015-11-05 15:00:24 +01001755 }
Yann Collet5106a762015-11-05 15:00:24 +01001756}
1757
Yann Collet5be2dd22015-11-11 13:43:58 +01001758
inikep64d7bcb2016-04-07 19:14:09 +02001759
1760static void ZSTD_compressBlock_btopt(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1761{
1762 ZSTD_compressBlock_opt_generic(ctx, src, srcSize);
1763}
1764
1765static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1766{
1767 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
1768}
1769
1770static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1771{
1772 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
1773}
1774
1775static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1776{
1777 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
1778}
1779
1780static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
1781{
1782 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
1783}
1784
1785
inikepfaa8d8a2016-04-05 19:01:10 +02001786FORCE_INLINE
inikep64d7bcb2016-04-07 19:14:09 +02001787void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
1788 const void* src, size_t srcSize,
1789 const U32 searchMethod, const U32 depth)
Yann Collet5be2dd22015-11-11 13:43:58 +01001790{
inikepfaa8d8a2016-04-05 19:01:10 +02001791 seqStore_t* seqStorePtr = &(ctx->seqStore);
1792 const BYTE* const istart = (const BYTE*)src;
1793 const BYTE* ip = istart;
1794 const BYTE* anchor = istart;
1795 const BYTE* const iend = istart + srcSize;
1796 const BYTE* const ilimit = iend - 8;
1797 const BYTE* const base = ctx->base;
1798 const U32 dictLimit = ctx->dictLimit;
1799 const BYTE* const prefixStart = base + dictLimit;
1800 const BYTE* const dictBase = ctx->dictBase;
1801 const BYTE* const dictEnd = dictBase + dictLimit;
1802 const BYTE* const dictStart = dictBase + ctx->lowLimit;
1803
1804 const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
1805 const U32 mls = ctx->params.cParams.searchLength;
1806
inikep64d7bcb2016-04-07 19:14:09 +02001807 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
1808 size_t* offsetPtr,
1809 U32 maxNbAttempts, U32 matchLengthSearch);
1810 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
1811
inikepfaa8d8a2016-04-05 19:01:10 +02001812 /* init */
1813 U32 rep[ZSTD_REP_INIT];
Yann Colletea63bb72016-04-08 15:25:32 +02001814 { U32 i; for (i=0; i<ZSTD_REP_INIT; i++) rep[i]=REPCODE_STARTVALUE; }
inikepfaa8d8a2016-04-05 19:01:10 +02001815
inikep64d7bcb2016-04-07 19:14:09 +02001816 ctx->nextToUpdate3 = ctx->nextToUpdate;
inikepfaa8d8a2016-04-05 19:01:10 +02001817 ZSTD_resetSeqStore(seqStorePtr);
1818 if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
1819
1820 /* Match Loop */
1821 while (ip < ilimit) {
1822 size_t matchLength=0;
1823 size_t offset=0;
1824 const BYTE* start=ip+1;
inikep64d7bcb2016-04-07 19:14:09 +02001825 U32 current = (U32)(ip-base);
inikepfaa8d8a2016-04-05 19:01:10 +02001826
1827 /* check repCode */
1828 {
inikep64d7bcb2016-04-07 19:14:09 +02001829 const U32 repIndex = (U32)(current+1 - rep[0]);
inikepfaa8d8a2016-04-05 19:01:10 +02001830 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1831 const BYTE* const repMatch = repBase + repIndex;
1832 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
inikep64d7bcb2016-04-07 19:14:09 +02001833 if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
inikepfaa8d8a2016-04-05 19:01:10 +02001834 /* repcode detected we should take it */
1835 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
inikep64d7bcb2016-04-07 19:14:09 +02001836 matchLength = ZSTD_count_2segments(ip+1+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
1837 if (depth==0) goto _storeSequence;
inikepfaa8d8a2016-04-05 19:01:10 +02001838 } }
1839
1840 /* first search (depth 0) */
1841 { size_t offsetFound = 99999999;
inikep64d7bcb2016-04-07 19:14:09 +02001842 size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
inikepfaa8d8a2016-04-05 19:01:10 +02001843 if (ml2 > matchLength)
inikep75716852016-04-06 12:34:42 +02001844 matchLength = ml2, start = ip, offset=offsetFound;
inikepfaa8d8a2016-04-05 19:01:10 +02001845 }
1846
inikep7bc19b62016-04-06 09:46:01 +02001847 if (matchLength < EQUAL_READ32) {
inikepfaa8d8a2016-04-05 19:01:10 +02001848 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1849 continue;
1850 }
1851
inikep64d7bcb2016-04-07 19:14:09 +02001852 /* let's try to find a better solution */
1853 if (depth>=1)
1854 while (ip<ilimit) {
1855 ip ++;
1856 current++;
1857 /* check repCode */
1858 if (offset) {
1859 const U32 repIndex = (U32)(current - rep[0]);
1860 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1861 const BYTE* const repMatch = repBase + repIndex;
1862 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
1863 if (MEM_read32(ip) == MEM_read32(repMatch)) {
1864 /* repcode detected */
1865 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
1866 size_t const repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
1867 int const gain2 = (int)(repLength * 3);
1868 int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
1869 if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
1870 matchLength = repLength, offset = 0, start = ip;
1871 } }
1872
1873 /* search match, depth 1 */
1874 { size_t offset2=99999999;
1875 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1876 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1877 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
1878 if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
1879 matchLength = ml2, offset = offset2, start = ip;
1880 continue; /* search a better one */
1881 } }
1882
1883 /* let's find an even better one */
1884 if ((depth==2) && (ip<ilimit)) {
1885 ip ++;
1886 current++;
1887 /* check repCode */
1888 if (offset) {
1889 const U32 repIndex = (U32)(current - rep[0]);
1890 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1891 const BYTE* const repMatch = repBase + repIndex;
1892 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
1893 if (MEM_read32(ip) == MEM_read32(repMatch)) {
1894 /* repcode detected */
1895 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
1896 size_t repLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
1897 int gain2 = (int)(repLength * 4);
1898 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
1899 if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
1900 matchLength = repLength, offset = 0, start = ip;
1901 } }
1902
1903 /* search match, depth 2 */
1904 { size_t offset2=99999999;
1905 size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1906 int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1907 int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
1908 if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) {
1909 matchLength = ml2, offset = offset2, start = ip;
1910 continue;
1911 } } }
1912 break; /* nothing found : store previous solution */
1913 }
1914
inikepfaa8d8a2016-04-05 19:01:10 +02001915 /* catch up */
inikep64d7bcb2016-04-07 19:14:09 +02001916 if (offset) {
inikepfaa8d8a2016-04-05 19:01:10 +02001917 U32 matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
1918 const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
1919 const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
inikep64d7bcb2016-04-07 19:14:09 +02001920 while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
inikep5ce00ae2016-04-05 21:03:43 +02001921 rep[1] = rep[0]; rep[0] = (U32)(offset - ZSTD_REP_MOVE);
Yann Collet48537162016-04-07 15:24:29 +02001922 }
inikepfaa8d8a2016-04-05 19:01:10 +02001923
inikepfaa8d8a2016-04-05 19:01:10 +02001924 /* store sequence */
inikep64d7bcb2016-04-07 19:14:09 +02001925_storeSequence:
inikepfaa8d8a2016-04-05 19:01:10 +02001926 { size_t const litLength = start - anchor;
1927 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
1928 anchor = ip = start + matchLength;
1929 }
1930
1931 /* check immediate repcode */
1932 while (ip <= ilimit) {
1933 const U32 repIndex = (U32)((ip-base) - rep[1]);
1934 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1935 const BYTE* const repMatch = repBase + repIndex;
1936 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
1937 if (MEM_read32(ip) == MEM_read32(repMatch)) {
1938 /* repcode detected we should take it */
1939 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
inikep7bc19b62016-04-06 09:46:01 +02001940 matchLength = ZSTD_count_2segments(ip+EQUAL_READ32, repMatch+EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32;
inikep5ce00ae2016-04-05 21:03:43 +02001941 offset = rep[1]; rep[1] = rep[0]; rep[0] = (U32)offset; /* swap offset history */
inikepfaa8d8a2016-04-05 19:01:10 +02001942 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
1943 ip += matchLength;
1944 anchor = ip;
1945 continue; /* faster when present ... (?) */
1946 }
1947 break;
1948 } }
1949
1950 /* Last Literals */
1951 { size_t const lastLLSize = iend - anchor;
1952 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1953 seqStorePtr->lit += lastLLSize;
Yann Collet5106a762015-11-05 15:00:24 +01001954 }
1955}
1956
1957
Yann Collet59d1f792016-01-23 19:28:41 +01001958void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet9a24e592015-11-22 02:53:43 +01001959{
inikep64d7bcb2016-04-07 19:14:09 +02001960 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
Yann Collet9a24e592015-11-22 02:53:43 +01001961}
1962
Yann Collet59d1f792016-01-23 19:28:41 +01001963static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colletb7fc88e2015-11-22 03:12:28 +01001964{
Yann Colleta1249dc2016-01-25 04:22:03 +01001965 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
Yann Colletb7fc88e2015-11-22 03:12:28 +01001966}
Yann Collet9a24e592015-11-22 02:53:43 +01001967
Yann Collet59d1f792016-01-23 19:28:41 +01001968static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colleta85c77b2015-11-22 12:22:04 +01001969{
Yann Colleta1249dc2016-01-25 04:22:03 +01001970 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
Yann Colleta85c77b2015-11-22 12:22:04 +01001971}
1972
Yann Collet59d1f792016-01-23 19:28:41 +01001973static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5054ee02015-11-23 13:34:21 +01001974{
Yann Colleta1249dc2016-01-25 04:22:03 +01001975 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
Yann Collet5054ee02015-11-23 13:34:21 +01001976}
1977
inikepd3b8d7a2016-02-22 10:06:17 +01001978static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
inikepe2bfe242016-01-31 11:25:48 +01001979{
inikep5ce00ae2016-04-05 21:03:43 +02001980 ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize);
inikepe2bfe242016-01-31 11:25:48 +01001981}
1982
Yann Collet7a231792015-11-21 15:27:35 +01001983
Yann Collet59d1f792016-01-23 19:28:41 +01001984typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
Yann Collet59d70632015-11-04 12:05:27 +01001985
Yann Colletb923f652016-01-26 03:14:20 +01001986static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
Yann Collet59d70632015-11-04 12:05:27 +01001987{
inikepd3b8d7a2016-02-22 10:06:17 +01001988 static const ZSTD_blockCompressor blockCompressor[2][6] = {
inikepf8a339d2016-04-05 23:58:51 +02001989#if 1
inikepd3b8d7a2016-02-22 10:06:17 +01001990 { ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt },
inikep908fcb32016-04-05 18:16:38 +02001991#else
1992 { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict },
1993#endif
inikepd3b8d7a2016-02-22 10:06:17 +01001994 { 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 +01001995 };
1996
1997 return blockCompressor[extDict][(U32)strat];
Yann Collet59d70632015-11-04 12:05:27 +01001998}
1999
2000
Yann Colletd1b26842016-03-15 01:24:33 +01002001static 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 +01002002{
Yann Collet3b719252016-03-30 19:48:05 +02002003 ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
Yann Collet2ce49232016-02-02 14:36:49 +01002004 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 +01002005 blockCompressor(zc, src, srcSize);
Yann Colletd1b26842016-03-15 01:24:33 +01002006 return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
Yann Colletbe2010e2015-10-31 12:57:14 +01002007}
2008
2009
inikep5cc4efd2016-03-25 10:52:25 +01002010
2011
Yann Collet2ce49232016-02-02 14:36:49 +01002012static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
Yann Colletd1b26842016-03-15 01:24:33 +01002013 void* dst, size_t dstCapacity,
Yann Colletf3eca252015-10-22 15:31:46 +01002014 const void* src, size_t srcSize)
2015{
Yann Collet2ce49232016-02-02 14:36:49 +01002016 size_t blockSize = zc->blockSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002017 size_t remaining = srcSize;
2018 const BYTE* ip = (const BYTE*)src;
2019 BYTE* const ostart = (BYTE*)dst;
2020 BYTE* op = ostart;
Yann Collet3b719252016-03-30 19:48:05 +02002021 const U32 maxDist = 1 << zc->params.cParams.windowLog;
inikep5cc4efd2016-03-25 10:52:25 +01002022 ZSTD_stats_t* stats = &zc->seqStore.stats;
2023
2024 ZSTD_statsInit(stats);
Yann Collet9b11b462015-11-01 12:40:22 +01002025
Yann Collet2ce49232016-02-02 14:36:49 +01002026 while (remaining) {
Yann Collet3e358272015-11-04 18:19:39 +01002027 size_t cSize;
inikep5cc4efd2016-03-25 10:52:25 +01002028 ZSTD_statsResetFreqs(stats);
Yann Collet3e358272015-11-04 18:19:39 +01002029
Yann Colletd1b26842016-03-15 01:24:33 +01002030 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 +01002031 if (remaining < blockSize) blockSize = remaining;
Yann Collet89db5e02015-11-13 11:27:46 +01002032
Yann Collet70e45772016-03-19 18:08:32 +01002033 if ((U32)(ip+blockSize - zc->base) > zc->loadedDictEnd + maxDist) {
2034 /* enforce maxDist */
2035 U32 const newLowLimit = (U32)(ip+blockSize - zc->base) - maxDist;
Yann Collet7a6343f2016-02-02 16:00:50 +01002036 if (zc->lowLimit < newLowLimit) zc->lowLimit = newLowLimit;
Yann Collet2ce49232016-02-02 14:36:49 +01002037 if (zc->dictLimit < zc->lowLimit) zc->dictLimit = zc->lowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002038 }
Yann Collet89db5e02015-11-13 11:27:46 +01002039
Yann Colletd1b26842016-03-15 01:24:33 +01002040 cSize = ZSTD_compressBlock_internal(zc, op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize, ip, blockSize);
Yann Collet3e358272015-11-04 18:19:39 +01002041 if (ZSTD_isError(cSize)) return cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002042
Yann Collet2ce49232016-02-02 14:36:49 +01002043 if (cSize == 0) { /* block is not compressible */
Yann Colletd1b26842016-03-15 01:24:33 +01002044 cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize);
Yann Collet523b5942016-01-09 02:10:40 +01002045 if (ZSTD_isError(cSize)) return cSize;
Yann Collet2ce49232016-02-02 14:36:49 +01002046 } else {
Yann Colletf3eca252015-10-22 15:31:46 +01002047 op[0] = (BYTE)(cSize>>16);
2048 op[1] = (BYTE)(cSize>>8);
2049 op[2] = (BYTE)cSize;
Yann Colletc95f8992015-11-19 17:28:35 +01002050 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
Yann Colletf3eca252015-10-22 15:31:46 +01002051 cSize += 3;
2052 }
2053
2054 remaining -= blockSize;
Yann Colletd1b26842016-03-15 01:24:33 +01002055 dstCapacity -= cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002056 ip += blockSize;
2057 op += cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002058 }
2059
inikep19bd48f2016-04-04 12:10:00 +02002060 ZSTD_statsPrint(stats, zc->params.cParams.searchLength);
Yann Colletf3eca252015-10-22 15:31:46 +01002061 return op-ostart;
2062}
2063
2064
Yann Collet6236eba2016-04-12 15:52:33 +02002065static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
2066 ZSTD_parameters params, U64 pledgedSrcSize)
2067{ BYTE* const op = (BYTE*)dst;
2068 U32 const fcsId = params.fParams.contentSizeFlag ?
2069 (pledgedSrcSize>0) + (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) : /* 0-3 */
2070 0;
2071 BYTE const fdescriptor = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) /* windowLog : 4 KB - 128 MB */
2072 | (fcsId << 6) );
2073 size_t const hSize = ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
2074 if (hSize > dstCapacity) return ERROR(dstSize_tooSmall);
2075
2076 MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
2077 op[4] = fdescriptor;
2078 switch(fcsId)
2079 {
2080 default: /* impossible */
2081 case 0 : break;
2082 case 1 : op[5] = (BYTE)(pledgedSrcSize); break;
2083 case 2 : MEM_writeLE16(op+5, (U16)(pledgedSrcSize-256)); break;
2084 case 3 : MEM_writeLE64(op+5, (U64)(pledgedSrcSize)); break;
2085 }
2086 return hSize;
2087}
2088
2089
Yann Colletbf42c8e2016-01-09 01:08:23 +01002090static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
Yann Collet7cbe79a2016-03-23 22:31:57 +01002091 void* dst, size_t dstCapacity,
Yann Colletbf42c8e2016-01-09 01:08:23 +01002092 const void* src, size_t srcSize,
2093 U32 frame)
Yann Colletf3eca252015-10-22 15:31:46 +01002094{
Yann Collet2acb5d32015-10-29 16:49:43 +01002095 const BYTE* const ip = (const BYTE*) src;
Yann Collet6236eba2016-04-12 15:52:33 +02002096 size_t fhSize = 0;
Yann Colletecd651b2016-01-07 15:35:18 +01002097
Yann Collet887e7da2016-04-11 20:12:27 +02002098 if (zc->stage==0) return ERROR(stage_wrong);
2099 if (frame && (zc->stage==1)) { /* copy saved header */
Yann Collet6236eba2016-04-12 15:52:33 +02002100 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, zc->params, srcSize);
2101 if (ZSTD_isError(fhSize)) return fhSize;
2102 dstCapacity -= fhSize;
2103 dst = (char*)dst + fhSize;
Yann Collet887e7da2016-04-11 20:12:27 +02002104 zc->stage = 2;
Yann Colletecd651b2016-01-07 15:35:18 +01002105 }
Yann Colletf3eca252015-10-22 15:31:46 +01002106
Yann Collet417890c2015-12-04 17:16:37 +01002107 /* Check if blocks follow each other */
Yann Collet2ce49232016-02-02 14:36:49 +01002108 if (src != zc->nextSrc) {
Yann Collet417890c2015-12-04 17:16:37 +01002109 /* not contiguous */
Yann Collet70e45772016-03-19 18:08:32 +01002110 size_t const delta = zc->nextSrc - ip;
Yann Collet417890c2015-12-04 17:16:37 +01002111 zc->lowLimit = zc->dictLimit;
2112 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2113 zc->dictBase = zc->base;
Yann Collet417890c2015-12-04 17:16:37 +01002114 zc->base -= delta;
2115 zc->nextToUpdate = zc->dictLimit;
Yann Collete47c4e52015-12-05 09:23:53 +01002116 if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */
Yann Collet417890c2015-12-04 17:16:37 +01002117 }
2118
Yann Collet89db5e02015-11-13 11:27:46 +01002119 /* preemptive overflow correction */
Yann Collet2ce49232016-02-02 14:36:49 +01002120 if (zc->lowLimit > (1<<30)) {
Yann Collet3b719252016-03-30 19:48:05 +02002121 U32 const btplus = (zc->params.cParams.strategy == ZSTD_btlazy2) || (zc->params.cParams.strategy == ZSTD_btopt);
Yann Collet8a57b922016-04-04 13:49:18 +02002122 U32 const chainMask = (1 << (zc->params.cParams.chainLog - btplus)) - 1;
2123 U32 const newLowLimit = zc->lowLimit & chainMask; /* preserve position % chainSize */
Yann Collet70e45772016-03-19 18:08:32 +01002124 U32 const correction = zc->lowLimit - newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002125 ZSTD_reduceIndex(zc, correction);
2126 zc->base += correction;
2127 zc->dictBase += correction;
Yann Collet6c3e2e72015-12-11 10:44:07 +01002128 zc->lowLimit = newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01002129 zc->dictLimit -= correction;
2130 if (zc->nextToUpdate < correction) zc->nextToUpdate = 0;
2131 else zc->nextToUpdate -= correction;
Yann Colletf3eca252015-10-22 15:31:46 +01002132 }
2133
Yann Colletbf42c8e2016-01-09 01:08:23 +01002134 /* if input and dictionary overlap : reduce dictionary (presumed modified by input) */
Yann Collet2ce49232016-02-02 14:36:49 +01002135 if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit)) {
Yann Colletc3652152015-11-24 14:06:07 +01002136 zc->lowLimit = (U32)(ip + srcSize - zc->dictBase);
2137 if (zc->lowLimit > zc->dictLimit) zc->lowLimit = zc->dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01002138 }
2139
Yann Colletc3652152015-11-24 14:06:07 +01002140 zc->nextSrc = ip + srcSize;
Yann Collet70e45772016-03-19 18:08:32 +01002141 { size_t const cSize = frame ?
Yann Collet7cbe79a2016-03-23 22:31:57 +01002142 ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
2143 ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
Yann Colletecd651b2016-01-07 15:35:18 +01002144 if (ZSTD_isError(cSize)) return cSize;
Yann Collet6236eba2016-04-12 15:52:33 +02002145 return cSize + fhSize;
Yann Colletecd651b2016-01-07 15:35:18 +01002146 }
Yann Colletf3eca252015-10-22 15:31:46 +01002147}
2148
Yann Colletbf42c8e2016-01-09 01:08:23 +01002149
2150size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
Yann Collet7cbe79a2016-03-23 22:31:57 +01002151 void* dst, size_t dstCapacity,
Yann Colletbf42c8e2016-01-09 01:08:23 +01002152 const void* src, size_t srcSize)
2153{
Yann Collet7cbe79a2016-03-23 22:31:57 +01002154 return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1);
Yann Colletbf42c8e2016-01-09 01:08:23 +01002155}
2156
2157
Yann Colletd1b26842016-03-15 01:24:33 +01002158size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Colletbf42c8e2016-01-09 01:08:23 +01002159{
Yann Collet569b81a2016-03-16 15:26:51 +01002160 if (srcSize > ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
inikepd6f208b2016-04-04 21:15:23 +02002161 ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.cParams.searchLength);
Yann Colletd1b26842016-03-15 01:24:33 +01002162 return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 0);
Yann Colletbf42c8e2016-01-09 01:08:23 +01002163}
2164
2165
Yann Colletb923f652016-01-26 03:14:20 +01002166static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
Yann Collet417890c2015-12-04 17:16:37 +01002167{
2168 const BYTE* const ip = (const BYTE*) src;
2169 const BYTE* const iend = ip + srcSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002170
Yann Collet417890c2015-12-04 17:16:37 +01002171 /* input becomes current prefix */
2172 zc->lowLimit = zc->dictLimit;
2173 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2174 zc->dictBase = zc->base;
2175 zc->base += ip - zc->nextSrc;
2176 zc->nextToUpdate = zc->dictLimit;
Yann Collet2ce49232016-02-02 14:36:49 +01002177 zc->loadedDictEnd = (U32)(iend - zc->base);
Yann Collet417890c2015-12-04 17:16:37 +01002178
2179 zc->nextSrc = iend;
2180 if (srcSize <= 8) return 0;
2181
Yann Collet3b719252016-03-30 19:48:05 +02002182 switch(zc->params.cParams.strategy)
Yann Collet417890c2015-12-04 17:16:37 +01002183 {
2184 case ZSTD_fast:
Yann Collet3b719252016-03-30 19:48:05 +02002185 ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002186 break;
2187
2188 case ZSTD_greedy:
2189 case ZSTD_lazy:
2190 case ZSTD_lazy2:
Yann Collet3b719252016-03-30 19:48:05 +02002191 ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002192 break;
2193
2194 case ZSTD_btlazy2:
Yann Colletcefef8c2016-02-15 07:21:54 +01002195 case ZSTD_btopt:
Yann Collet3b719252016-03-30 19:48:05 +02002196 ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
Yann Collet417890c2015-12-04 17:16:37 +01002197 break;
2198
2199 default:
2200 return ERROR(GENERIC); /* strategy doesn't exist; impossible */
2201 }
2202
Yann Collet2ce49232016-02-02 14:36:49 +01002203 zc->nextToUpdate = zc->loadedDictEnd;
Yann Collet417890c2015-12-04 17:16:37 +01002204 return 0;
2205}
2206
2207
Yann Colletb923f652016-01-26 03:14:20 +01002208/* Dictionary format :
2209 Magic == ZSTD_DICT_MAGIC (4 bytes)
Yann Colletfb797352016-03-13 11:08:40 +01002210 HUF_writeCTable(256)
Yann Colletb923f652016-01-26 03:14:20 +01002211 Dictionary content
2212*/
Yann Colletfb797352016-03-13 11:08:40 +01002213/*! ZSTD_loadDictEntropyStats() :
Yann Colletb923f652016-01-26 03:14:20 +01002214 @return : size read from dictionary */
2215static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
2216{
2217 /* note : magic number already checked */
Yann Colletfb810d62016-01-28 00:18:06 +01002218 size_t offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize, errorCode;
2219 short offcodeNCount[MaxOff+1];
2220 unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
2221 short matchlengthNCount[MaxML+1];
2222 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
2223 short litlengthNCount[MaxLL+1];
2224 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
2225
Yann Collet70e45772016-03-19 18:08:32 +01002226 size_t const hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01002227 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01002228 zc->flagStaticTables = 1;
2229 dict = (const char*)dict + hufHeaderSize;
2230 dictSize -= hufHeaderSize;
2231
2232 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
2233 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2234 errorCode = FSE_buildCTable(zc->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
2235 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2236 dict = (const char*)dict + offcodeHeaderSize;
2237 dictSize -= offcodeHeaderSize;
2238
2239 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
2240 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
2241 errorCode = FSE_buildCTable(zc->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
2242 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2243 dict = (const char*)dict + matchlengthHeaderSize;
2244 dictSize -= matchlengthHeaderSize;
2245
2246 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
2247 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
2248 errorCode = FSE_buildCTable(zc->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
2249 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2250
2251 return hufHeaderSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01002252}
2253
Yann Colletd1b26842016-03-15 01:24:33 +01002254/** ZSTD_compress_insertDictionary() :
2255* @return : 0, or an error code */
Yann Collet1c8e1942016-01-26 16:31:22 +01002256static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01002257{
Yann Colletd1b26842016-03-15 01:24:33 +01002258 if ((dict==NULL) || (dictSize<=4)) return 0;
Yann Colletb923f652016-01-26 03:14:20 +01002259
Yann Colletd1b26842016-03-15 01:24:33 +01002260 /* default : dict is pure content */
2261 if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return ZSTD_loadDictionaryContent(zc, dict, dictSize);
2262
2263 /* known magic number : dict is parsed for entropy stats and content */
Yann Collet21588e32016-03-30 16:50:44 +02002264 { size_t const eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+4 /* skip magic */, dictSize-4) + 4;
2265 if (ZSTD_isError(eSize)) return eSize;
2266 return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
Yann Collet7b51a292016-01-26 15:58:49 +01002267 }
Yann Colletecd651b2016-01-07 15:35:18 +01002268}
2269
Yann Collet0085cd32016-04-12 14:14:10 +02002270
Yann Collet27caf2a2016-04-01 15:48:48 +02002271/*! ZSTD_compressBegin_internal() :
Yann Colletecd651b2016-01-07 15:35:18 +01002272* @return : 0, or an error code */
Yann Collet27caf2a2016-04-01 15:48:48 +02002273static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* zc,
Yann Collet1c8e1942016-01-26 16:31:22 +01002274 const void* dict, size_t dictSize,
Yann Collet3b719252016-03-30 19:48:05 +02002275 ZSTD_parameters params, U64 pledgedSrcSize)
Yann Colletf3eca252015-10-22 15:31:46 +01002276{
Yann Collet6236eba2016-04-12 15:52:33 +02002277 { U32 const hashLog3 = (pledgedSrcSize || pledgedSrcSize >= 8192) ? ZSTD_HASHLOG3_MAX : ((pledgedSrcSize >= 2048) ? ZSTD_HASHLOG3_MIN + 1 : ZSTD_HASHLOG3_MIN);
2278 zc->hashLog3 = (params.cParams.searchLength==3) ? hashLog3 : 0; }
Yann Collet88fcd292015-11-25 14:42:45 +01002279
Yann Colletabb5c652016-04-11 20:42:31 +02002280 { size_t const resetError = ZSTD_resetCCtx_advanced(zc, params, 1);
2281 if (ZSTD_isError(resetError)) return resetError; }
Yann Collet89db5e02015-11-13 11:27:46 +01002282
Yann Collet1c8e1942016-01-26 16:31:22 +01002283 return ZSTD_compress_insertDictionary(zc, dict, dictSize);
Yann Collet88fcd292015-11-25 14:42:45 +01002284}
2285
2286
Yann Collet27caf2a2016-04-01 15:48:48 +02002287/*! ZSTD_compressBegin_advanced() :
2288* @return : 0, or an error code */
2289size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
2290 const void* dict, size_t dictSize,
2291 ZSTD_parameters params, U64 pledgedSrcSize)
2292{
2293 /* compression parameters verification and optimization */
2294 { size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, pledgedSrcSize);
2295 if (ZSTD_isError(errorCode)) return errorCode; }
2296
2297 return ZSTD_compressBegin_internal(zc, dict, dictSize, params, pledgedSrcSize);
2298}
2299
2300
Yann Collet1c8e1942016-01-26 16:31:22 +01002301size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel)
Yann Colletb923f652016-01-26 03:14:20 +01002302{
Yann Collet3b719252016-03-30 19:48:05 +02002303 ZSTD_parameters params;
2304 params.cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
2305 params.fParams.contentSizeFlag = 0;
Yann Collet27caf2a2016-04-01 15:48:48 +02002306 ZSTD_adjustCParams(&params.cParams, 0, dictSize);
inikepa4dde252016-03-01 14:14:35 +01002307 ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_usingDict compressionLevel=%d\n", zc->base, compressionLevel);
Yann Collet27caf2a2016-04-01 15:48:48 +02002308 return ZSTD_compressBegin_internal(zc, dict, dictSize, params, 0);
Yann Collet1c8e1942016-01-26 16:31:22 +01002309}
Yann Collet083fcc82015-10-25 14:06:35 +01002310
inikep19bd48f2016-04-04 12:10:00 +02002311
2312size_t ZSTD_compressBegin_targetSrcSize(ZSTD_CCtx* zc, const void* dict, size_t dictSize, size_t targetSrcSize, int compressionLevel)
2313{
2314 ZSTD_parameters params;
2315 params.cParams = ZSTD_getCParams(compressionLevel, targetSrcSize, dictSize);
2316 params.fParams.contentSizeFlag = 1;
2317 ZSTD_adjustCParams(&params.cParams, targetSrcSize, dictSize);
2318 ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_targetSrcSize compressionLevel=%d\n", zc->base, compressionLevel);
2319 return ZSTD_compressBegin_internal(zc, dict, dictSize, params, targetSrcSize);
2320}
2321
2322
Yann Collet1c8e1942016-01-26 16:31:22 +01002323size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
Yann Collet083fcc82015-10-25 14:06:35 +01002324{
inikepa4dde252016-03-01 14:14:35 +01002325 ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin compressionLevel=%d\n", zc->base, compressionLevel);
Yann Collet3b719252016-03-30 19:48:05 +02002326 return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
Yann Collet083fcc82015-10-25 14:06:35 +01002327}
2328
2329
Yann Colletfb797352016-03-13 11:08:40 +01002330/*! ZSTD_compressEnd() :
2331* Write frame epilogue.
Yann Collet88fcd292015-11-25 14:42:45 +01002332* @return : nb of bytes written into dst (or an error code) */
Yann Colletd1b26842016-03-15 01:24:33 +01002333size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t dstCapacity)
Yann Collet2acb5d32015-10-29 16:49:43 +01002334{
2335 BYTE* op = (BYTE*)dst;
Yann Collet6236eba2016-04-12 15:52:33 +02002336 size_t fhSize = 0;
Yann Collet2acb5d32015-10-29 16:49:43 +01002337
Yann Collet887e7da2016-04-11 20:12:27 +02002338 /* not even init ! */
2339 if (zc->stage==0) return ERROR(stage_wrong);
2340
2341 /* special case : empty frame */
2342 if (zc->stage==1) {
Yann Collet6236eba2016-04-12 15:52:33 +02002343 fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, zc->params, 0);
2344 if (ZSTD_isError(fhSize)) return fhSize;
2345 dstCapacity -= fhSize;
2346 op += fhSize;
Yann Collet887e7da2016-04-11 20:12:27 +02002347 zc->stage = 2;
Yann Colletecd651b2016-01-07 15:35:18 +01002348 }
2349
2350 /* frame epilogue */
Yann Colletd1b26842016-03-15 01:24:33 +01002351 if (dstCapacity < 3) return ERROR(dstSize_tooSmall);
Yann Collet2acb5d32015-10-29 16:49:43 +01002352 op[0] = (BYTE)(bt_end << 6);
2353 op[1] = 0;
2354 op[2] = 0;
2355
Yann Collet887e7da2016-04-11 20:12:27 +02002356 zc->stage = 0; /* return to "created by not init" status */
Yann Collet6236eba2016-04-12 15:52:33 +02002357 return 3+fhSize;
Yann Collet2acb5d32015-10-29 16:49:43 +01002358}
2359
Yann Colletfd416f12016-01-30 03:14:15 +01002360
2361size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx,
Yann Colletd1b26842016-03-15 01:24:33 +01002362 void* dst, size_t dstCapacity,
Yann Colletfd416f12016-01-30 03:14:15 +01002363 const void* src, size_t srcSize)
2364{
Yann Collet70e45772016-03-19 18:08:32 +01002365 { size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
2366 if (ZSTD_isError(errorCode)) return errorCode;
2367 }
2368 { size_t const cSize = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize);
2369 if (ZSTD_isError(cSize)) return cSize;
Yann Collet0dbf2872016-04-08 02:02:12 +02002370
Yann Collet70e45772016-03-19 18:08:32 +01002371 { size_t const endSize = ZSTD_compressEnd(cctx, (char*)dst+cSize, dstCapacity-cSize);
2372 if (ZSTD_isError(endSize)) return endSize;
2373 return cSize + endSize;
2374 } }
Yann Colletfd416f12016-01-30 03:14:15 +01002375}
2376
2377
Yann Collet21588e32016-03-30 16:50:44 +02002378static size_t ZSTD_compress_internal (ZSTD_CCtx* ctx,
Yann Colletd1b26842016-03-15 01:24:33 +01002379 void* dst, size_t dstCapacity,
Yann Collet88fcd292015-11-25 14:42:45 +01002380 const void* src, size_t srcSize,
Yann Collet31683c02015-12-18 01:26:48 +01002381 const void* dict,size_t dictSize,
Yann Collet88fcd292015-11-25 14:42:45 +01002382 ZSTD_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +01002383{
2384 BYTE* const ostart = (BYTE*)dst;
2385 BYTE* op = ostart;
2386
Yann Collet1c8e1942016-01-26 16:31:22 +01002387 /* Init */
Yann Collet27caf2a2016-04-01 15:48:48 +02002388 { size_t const errorCode = ZSTD_compressBegin_internal(ctx, dict, dictSize, params, srcSize);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002389 if(ZSTD_isError(errorCode)) return errorCode; }
Yann Colletf3eca252015-10-22 15:31:46 +01002390
2391 /* body (compression) */
Yann Colletd1b26842016-03-15 01:24:33 +01002392 { size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002393 if(ZSTD_isError(oSize)) return oSize;
2394 op += oSize;
2395 dstCapacity -= oSize; }
Yann Colletf3eca252015-10-22 15:31:46 +01002396
2397 /* Close frame */
Yann Colletd1b26842016-03-15 01:24:33 +01002398 { size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
Yann Collet7cbe79a2016-03-23 22:31:57 +01002399 if(ZSTD_isError(oSize)) return oSize;
2400 op += oSize; }
Yann Colletf3eca252015-10-22 15:31:46 +01002401
2402 return (op - ostart);
2403}
2404
Yann Collet21588e32016-03-30 16:50:44 +02002405size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
2406 void* dst, size_t dstCapacity,
2407 const void* src, size_t srcSize,
2408 const void* dict,size_t dictSize,
2409 ZSTD_parameters params)
2410{
Yann Collet3b719252016-03-30 19:48:05 +02002411 size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, srcSize);
Yann Collet21588e32016-03-30 16:50:44 +02002412 if (ZSTD_isError(errorCode)) return errorCode;
2413 return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
2414}
2415
Yann Colletd1b26842016-03-15 01:24:33 +01002416size_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 +01002417{
Yann Collet3b719252016-03-30 19:48:05 +02002418 ZSTD_parameters params;
inikepa4dde252016-03-01 14:14:35 +01002419 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 +02002420 params.cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
2421 params.fParams.contentSizeFlag = 1;
2422 ZSTD_adjustCParams(&params.cParams, srcSize, dictSize);
Yann Collet21588e32016-03-30 16:50:44 +02002423 return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
Yann Collet31683c02015-12-18 01:26:48 +01002424}
2425
Yann Colletd1b26842016-03-15 01:24:33 +01002426size_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 +01002427{
inikepa4dde252016-03-01 14:14:35 +01002428 ZSTD_LOG_BLOCK("%p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, compressionLevel);
Yann Collet21588e32016-03-30 16:50:44 +02002429 return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
Yann Collet083fcc82015-10-25 14:06:35 +01002430}
2431
Yann Colletd1b26842016-03-15 01:24:33 +01002432size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
Yann Colletf3eca252015-10-22 15:31:46 +01002433{
Yann Collet44fe9912015-10-29 22:02:40 +01002434 size_t result;
Yann Collet5be2dd22015-11-11 13:43:58 +01002435 ZSTD_CCtx ctxBody;
Yann Collet712def92015-10-29 18:41:45 +01002436 memset(&ctxBody, 0, sizeof(ctxBody));
Yann Colletd1b26842016-03-15 01:24:33 +01002437 result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
Yann Colletecd651b2016-01-07 15:35:18 +01002438 free(ctxBody.workSpace); /* can't free ctxBody, since it's on stack; just free heap content */
Yann Collet44fe9912015-10-29 22:02:40 +01002439 return result;
Yann Colletf3eca252015-10-22 15:31:46 +01002440}
Yann Colletfdcad6d2015-12-17 23:50:15 +01002441
Yann Colletfd416f12016-01-30 03:14:15 +01002442
Yann Collet70e8c382016-02-10 13:37:52 +01002443/*-===== Pre-defined compression levels =====-*/
Yann Colletfd416f12016-01-30 03:14:15 +01002444
Yann Collete3193c42016-03-09 16:57:09 +01002445#define ZSTD_MAX_CLEVEL 22
Yann Collet7d968c72016-02-03 02:11:32 +01002446unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
2447
Yann Collet3b719252016-03-30 19:48:05 +02002448static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
Yann Colletfd416f12016-01-30 03:14:15 +01002449{ /* "default" */
Yann Collet793c6492016-04-09 20:32:00 +02002450 /* W, C, H, S, L, TL, strat */
Yann Collet3b719252016-03-30 19:48:05 +02002451 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
2452 { 19, 13, 14, 1, 7, 4, ZSTD_fast }, /* level 1 */
2453 { 19, 15, 16, 1, 6, 4, ZSTD_fast }, /* level 2 */
2454 { 20, 18, 20, 1, 6, 4, ZSTD_fast }, /* level 3 */
2455 { 20, 13, 17, 2, 5, 4, ZSTD_greedy }, /* level 4.*/
2456 { 20, 15, 18, 3, 5, 4, ZSTD_greedy }, /* level 5 */
2457 { 21, 16, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
2458 { 21, 17, 20, 3, 5, 4, ZSTD_lazy }, /* level 7 */
2459 { 21, 18, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 8.*/
2460 { 21, 20, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */
2461 { 21, 19, 21, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */
2462 { 22, 20, 22, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */
2463 { 22, 20, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */
2464 { 22, 21, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */
2465 { 22, 21, 22, 6, 5, 4, ZSTD_lazy2 }, /* level 14 */
2466 { 22, 21, 21, 5, 5, 4, ZSTD_btlazy2 }, /* level 15 */
2467 { 23, 22, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */
Yann Collet793c6492016-04-09 20:32:00 +02002468 { 23, 23, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 17.*/
2469 { 23, 23, 22, 6, 5, 24, ZSTD_btopt }, /* level 18.*/
2470 { 23, 23, 22, 6, 3, 48, ZSTD_btopt }, /* level 19.*/
2471 { 25, 26, 23, 7, 3, 64, ZSTD_btopt }, /* level 20.*/
2472 { 26, 26, 23, 7, 3,256, ZSTD_btopt }, /* level 21.*/
2473 { 27, 27, 25, 9, 3,512, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002474},
2475{ /* for srcSize <= 256 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002476 /* W, C, H, S, L, T, strat */
2477 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */
Yann Collet0dbf2872016-04-08 02:02:12 +02002478 { 18, 13, 14, 1, 6, 4, ZSTD_fast }, /* level 1 */
Yann Collet78267d12016-04-08 12:36:19 +02002479 { 18, 15, 17, 1, 5, 4, ZSTD_fast }, /* level 2 */
2480 { 18, 13, 15, 1, 5, 4, ZSTD_greedy }, /* level 3.*/
2481 { 18, 15, 17, 1, 5, 4, ZSTD_greedy }, /* level 4.*/
2482 { 18, 16, 17, 4, 5, 4, ZSTD_greedy }, /* level 5 */
2483 { 18, 17, 17, 5, 5, 4, ZSTD_greedy }, /* level 6 */
Yann Collet3b719252016-03-30 19:48:05 +02002484 { 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */
2485 { 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
2486 { 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
2487 { 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
Yann Collet78267d12016-04-08 12:36:19 +02002488 { 18, 18, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 11.*/
2489 { 18, 18, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 12.*/
2490 { 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13 */
2491 { 18, 18, 18, 4, 4, 16, ZSTD_btopt }, /* level 14.*/
2492 { 18, 18, 18, 8, 4, 24, ZSTD_btopt }, /* level 15.*/
2493 { 18, 19, 18, 8, 3, 48, ZSTD_btopt }, /* level 16.*/
2494 { 18, 19, 18, 8, 3, 96, ZSTD_btopt }, /* level 17.*/
2495 { 18, 19, 18, 9, 3,128, ZSTD_btopt }, /* level 18.*/
2496 { 18, 19, 18, 10, 3,256, ZSTD_btopt }, /* level 19.*/
2497 { 18, 19, 18, 11, 3,512, ZSTD_btopt }, /* level 20.*/
2498 { 18, 19, 18, 12, 3,512, ZSTD_btopt }, /* level 21.*/
2499 { 18, 19, 18, 13, 3,512, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002500},
2501{ /* for srcSize <= 128 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002502 /* W, C, H, S, L, T, strat */
2503 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
2504 { 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */
2505 { 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
2506 { 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */
2507 { 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */
2508 { 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
2509 { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
2510 { 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */
2511 { 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
2512 { 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
2513 { 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
2514 { 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
2515 { 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
2516 { 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
2517 { 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
2518 { 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
2519 { 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
2520 { 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
2521 { 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
2522 { 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
2523 { 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/
2524 { 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/
2525 { 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002526},
2527{ /* for srcSize <= 16 KB */
Yann Collet3b719252016-03-30 19:48:05 +02002528 /* W, C, H, S, L, T, strat */
2529 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */
2530 { 14, 14, 14, 1, 4, 4, ZSTD_fast }, /* level 1 */
2531 { 14, 14, 15, 1, 4, 4, ZSTD_fast }, /* level 2 */
2532 { 14, 14, 14, 4, 4, 4, ZSTD_greedy }, /* level 3.*/
2533 { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 4.*/
2534 { 14, 14, 14, 4, 4, 4, ZSTD_lazy2 }, /* level 5 */
2535 { 14, 14, 14, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */
2536 { 14, 14, 14, 6, 4, 4, ZSTD_lazy2 }, /* level 7.*/
2537 { 14, 14, 14, 7, 4, 4, ZSTD_lazy2 }, /* level 8.*/
2538 { 14, 15, 14, 6, 4, 4, ZSTD_btlazy2 }, /* level 9.*/
2539 { 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
2540 { 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
2541 { 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
2542 { 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
2543 { 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
2544 { 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
2545 { 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
2546 { 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
2547 { 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
2548 { 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
2549 { 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 20.*/
2550 { 14, 15, 15, 9, 3,256, ZSTD_btopt }, /* level 21.*/
2551 { 14, 15, 15, 10, 3,256, ZSTD_btopt }, /* level 22.*/
Yann Colletfd416f12016-01-30 03:14:15 +01002552},
2553};
2554
Yann Collet1df25942016-03-05 18:43:21 +01002555/*! ZSTD_getParams() :
Yann Colletfd416f12016-01-30 03:14:15 +01002556* @return ZSTD_parameters structure for a selected compression level and srcSize.
Yann Colletde406ee2016-03-20 15:46:10 +01002557* `srcSize` value is optional, select 0 if not known */
Yann Collet3b719252016-03-30 19:48:05 +02002558ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, U64 srcSize, size_t dictSize)
Yann Colletfd416f12016-01-30 03:14:15 +01002559{
Yann Collet15354142016-04-04 04:22:53 +02002560 ZSTD_compressionParameters cp;
Yann Collet1005fc12016-04-04 13:28:28 +02002561 size_t const addedSize = srcSize ? 0 : 500;
Yann Collet15354142016-04-04 04:22:53 +02002562 U64 const rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
Yann Collet3b719252016-03-30 19:48:05 +02002563 U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
Yann Colletfd416f12016-01-30 03:14:15 +01002564 if (compressionLevel<=0) compressionLevel = 1;
2565 if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
Yann Collet15354142016-04-04 04:22:53 +02002566 cp = ZSTD_defaultCParameters[tableID][compressionLevel];
Yann Collet1005fc12016-04-04 13:28:28 +02002567 if (MEM_32bits()) { /* auto-correction, for 32-bits mode */
2568 if (cp.windowLog > ZSTD_WINDOWLOG_MAX) cp.windowLog = ZSTD_WINDOWLOG_MAX;
Yann Collet8a57b922016-04-04 13:49:18 +02002569 if (cp.chainLog > ZSTD_CHAINLOG_MAX) cp.chainLog = ZSTD_CHAINLOG_MAX;
Yann Collet1005fc12016-04-04 13:28:28 +02002570 if (cp.hashLog > ZSTD_HASHLOG_MAX) cp.hashLog = ZSTD_HASHLOG_MAX;
2571 }
Yann Collet15354142016-04-04 04:22:53 +02002572 return cp;
Yann Colletfd416f12016-01-30 03:14:15 +01002573}