blob: c2becc5fff406dfef15f899286ab1c747952e8ed [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 Colletf3eca252015-10-22 15:31:46 +010051/* *************************************
52* Includes
53***************************************/
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 Colletf3eca252015-10-22 15:31:46 +010059#include "zstd_static.h"
Yann Collet3d9cf7a2015-10-29 17:15:14 +010060#include "zstd_internal.h"
Yann Colletf3eca252015-10-22 15:31:46 +010061
62
63/* *************************************
Yann Collet14983e72015-11-11 21:38:21 +010064* Constants
Yann Colletf3eca252015-10-22 15:31:46 +010065***************************************/
Yann Collet14983e72015-11-11 21:38:21 +010066static const U32 g_searchStrength = 8;
Yann Colletf3eca252015-10-22 15:31:46 +010067
Yann Colletf3eca252015-10-22 15:31:46 +010068
69/* *************************************
Yann Collet59d1f792016-01-23 19:28:41 +010070* Helper functions
71***************************************/
72unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
73
74size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
75
76
77/* *************************************
Yann Collet14983e72015-11-11 21:38:21 +010078* Sequence storage
Yann Colletf3eca252015-10-22 15:31:46 +010079***************************************/
Yann Collet14983e72015-11-11 21:38:21 +010080typedef struct {
81 void* buffer;
82 U32* offsetStart;
83 U32* offset;
84 BYTE* offCodeStart;
85 BYTE* offCode;
86 BYTE* litStart;
87 BYTE* lit;
88 BYTE* litLengthStart;
89 BYTE* litLength;
90 BYTE* matchLengthStart;
91 BYTE* matchLength;
92 BYTE* dumpsStart;
93 BYTE* dumps;
94} seqStore_t;
95
96static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
97{
98 ssPtr->offset = ssPtr->offsetStart;
99 ssPtr->lit = ssPtr->litStart;
100 ssPtr->litLength = ssPtr->litLengthStart;
101 ssPtr->matchLength = ssPtr->matchLengthStart;
102 ssPtr->dumps = ssPtr->dumpsStart;
103}
104
105
106/* *************************************
107* Context memory management
108***************************************/
Yann Collet5be2dd22015-11-11 13:43:58 +0100109struct ZSTD_CCtx_s
Yann Colletf3eca252015-10-22 15:31:46 +0100110{
Yann Collet89db5e02015-11-13 11:27:46 +0100111 const BYTE* nextSrc; /* next block here to continue on current prefix */
Yann Colleteeb8ba12015-10-22 16:55:40 +0100112 const BYTE* base; /* All regular indexes relative to this position */
113 const BYTE* dictBase; /* extDict indexes relative to this position */
Yann Colletf3eca252015-10-22 15:31:46 +0100114 U32 dictLimit; /* below that point, need extDict */
Yann Colleteeb8ba12015-10-22 16:55:40 +0100115 U32 lowLimit; /* below that point, no more data */
Yann Colletf3eca252015-10-22 15:31:46 +0100116 U32 nextToUpdate; /* index from which to continue dictionary update */
Yann Colletecd651b2016-01-07 15:35:18 +0100117 U32 stage;
Yann Collet5be2dd22015-11-11 13:43:58 +0100118 ZSTD_parameters params;
Yann Collet712def92015-10-29 18:41:45 +0100119 void* workSpace;
120 size_t workSpaceSize;
Yann Collet120230b2015-12-02 14:00:45 +0100121 size_t blockSize;
Yann Colletecd651b2016-01-07 15:35:18 +0100122 size_t hbSize;
Yann Collet60096272016-01-08 17:27:50 +0100123 char headerBuffer[ZSTD_frameHeaderSize_max];
Yann Colletecd651b2016-01-07 15:35:18 +0100124
Yann Collet712def92015-10-29 18:41:45 +0100125 seqStore_t seqStore; /* sequences storage ptrs */
Yann Collet083fcc82015-10-25 14:06:35 +0100126 U32* hashTable;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100127 U32* contentTable;
Yann Colletb923f652016-01-26 03:14:20 +0100128 HUF_CElt* hufTable;
Yann Colletfb810d62016-01-28 00:18:06 +0100129 U32 flagStaticTables;
130 FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
131 FSE_CTable matchlengthCTable [FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
132 FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
Yann Colletf3eca252015-10-22 15:31:46 +0100133};
134
135
Yann Collet5be2dd22015-11-11 13:43:58 +0100136ZSTD_CCtx* ZSTD_createCCtx(void)
Yann Colletf3eca252015-10-22 15:31:46 +0100137{
Yann Collet5be2dd22015-11-11 13:43:58 +0100138 return (ZSTD_CCtx*) calloc(1, sizeof(ZSTD_CCtx));
Yann Colletf3eca252015-10-22 15:31:46 +0100139}
140
Yann Collet5be2dd22015-11-11 13:43:58 +0100141size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
Yann Colletf3eca252015-10-22 15:31:46 +0100142{
Yann Collet712def92015-10-29 18:41:45 +0100143 free(cctx->workSpace);
Yann Collet083fcc82015-10-25 14:06:35 +0100144 free(cctx);
145 return 0;
146}
147
Yann Collet59d70632015-11-04 12:05:27 +0100148
Yann Collet14983e72015-11-11 21:38:21 +0100149static unsigned ZSTD_highbit(U32 val);
150
Yann Collet5be2dd22015-11-11 13:43:58 +0100151/** ZSTD_validateParams
Yann Collet59d70632015-11-04 12:05:27 +0100152 correct params value to remain within authorized range
153 optimize for srcSize if srcSize > 0 */
Yann Collet88fcd292015-11-25 14:42:45 +0100154void ZSTD_validateParams(ZSTD_parameters* params)
Yann Collet59d70632015-11-04 12:05:27 +0100155{
inikepc71568f2016-01-30 12:15:56 +0100156 const U32 btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_opt_bt);
Yann Collet59d70632015-11-04 12:05:27 +0100157
158 /* validate params */
Yann Collet00fd7a22015-11-28 16:03:22 +0100159 if (MEM_32bits()) if (params->windowLog > 25) params->windowLog = 25; /* 32 bits mode cannot flush > 24 bits */
Yann Collet5be2dd22015-11-11 13:43:58 +0100160 if (params->windowLog > ZSTD_WINDOWLOG_MAX) params->windowLog = ZSTD_WINDOWLOG_MAX;
161 if (params->windowLog < ZSTD_WINDOWLOG_MIN) params->windowLog = ZSTD_WINDOWLOG_MIN;
Yann Collet59d70632015-11-04 12:05:27 +0100162
163 /* correct params, to use less memory */
Yann Colletfb810d62016-01-28 00:18:06 +0100164 if ((params->srcSize > 0) && (params->srcSize < (1<<ZSTD_WINDOWLOG_MAX))) {
Yann Collet88fcd292015-11-25 14:42:45 +0100165 U32 srcLog = ZSTD_highbit((U32)(params->srcSize)-1) + 1;
Yann Collet59d70632015-11-04 12:05:27 +0100166 if (params->windowLog > srcLog) params->windowLog = srcLog;
167 }
168
Yann Collet00fd7a22015-11-28 16:03:22 +0100169 if (params->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) params->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
Yann Collet5be2dd22015-11-11 13:43:58 +0100170 if (params->contentLog > params->windowLog+btPlus) params->contentLog = params->windowLog+btPlus; /* <= ZSTD_CONTENTLOG_MAX */
171 if (params->contentLog < ZSTD_CONTENTLOG_MIN) params->contentLog = ZSTD_CONTENTLOG_MIN;
172 if (params->hashLog > ZSTD_HASHLOG_MAX) params->hashLog = ZSTD_HASHLOG_MAX;
173 if (params->hashLog < ZSTD_HASHLOG_MIN) params->hashLog = ZSTD_HASHLOG_MIN;
174 if (params->searchLog > ZSTD_SEARCHLOG_MAX) params->searchLog = ZSTD_SEARCHLOG_MAX;
175 if (params->searchLog < ZSTD_SEARCHLOG_MIN) params->searchLog = ZSTD_SEARCHLOG_MIN;
176 if (params->searchLength> ZSTD_SEARCHLENGTH_MAX) params->searchLength = ZSTD_SEARCHLENGTH_MAX;
177 if (params->searchLength< ZSTD_SEARCHLENGTH_MIN) params->searchLength = ZSTD_SEARCHLENGTH_MIN;
inikepc71568f2016-01-30 12:15:56 +0100178 if ((U32)params->strategy>(U32)ZSTD_opt_bt) params->strategy = ZSTD_opt_bt;
Yann Collet59d70632015-11-04 12:05:27 +0100179}
180
181
Yann Collet5be2dd22015-11-11 13:43:58 +0100182static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
Yann Collet88fcd292015-11-25 14:42:45 +0100183 ZSTD_parameters params)
Yann Collet863ec402016-01-28 17:56:33 +0100184{ /* note : params considered validated here */
Yann Collet120230b2015-12-02 14:00:45 +0100185 const size_t blockSize = MIN(BLOCKSIZE, (size_t)1 << params.windowLog);
Yann Collet2acb5d32015-10-29 16:49:43 +0100186 /* reserve table memory */
Yann Collet863ec402016-01-28 17:56:33 +0100187 const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog;
188 const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog)) * sizeof(U32);
189 const size_t neededSpace = tableSpace + (256*sizeof(U32)) + (3*blockSize);
190 if (zc->workSpaceSize < neededSpace) {
191 free(zc->workSpace);
192 zc->workSpace = malloc(neededSpace);
193 if (zc->workSpace == NULL) return ERROR(memory_allocation);
194 zc->workSpaceSize = neededSpace;
Yann Collet083fcc82015-10-25 14:06:35 +0100195 }
Yann Collet863ec402016-01-28 17:56:33 +0100196 memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
197 zc->hashTable = (U32*)(zc->workSpace);
198 zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog);
199 zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog);
200 zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
201 zc->flagStaticTables = 0;
202 zc->seqStore.buffer = (U32*)(zc->seqStore.buffer) + 256;
Yann Collet083fcc82015-10-25 14:06:35 +0100203
Yann Colletf48e35c2015-11-07 01:13:31 +0100204 zc->nextToUpdate = 1;
Yann Collet89db5e02015-11-13 11:27:46 +0100205 zc->nextSrc = NULL;
Yann Collet2acb5d32015-10-29 16:49:43 +0100206 zc->base = NULL;
207 zc->dictBase = NULL;
208 zc->dictLimit = 0;
209 zc->lowLimit = 0;
Yann Collet083fcc82015-10-25 14:06:35 +0100210 zc->params = params;
Yann Collet120230b2015-12-02 14:00:45 +0100211 zc->blockSize = blockSize;
Yann Colletf3eca252015-10-22 15:31:46 +0100212 zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
Yann Collet120230b2015-12-02 14:00:45 +0100213 zc->seqStore.offCodeStart = (BYTE*) (zc->seqStore.offsetStart + (blockSize>>2));
214 zc->seqStore.litStart = zc->seqStore.offCodeStart + (blockSize>>2);
215 zc->seqStore.litLengthStart = zc->seqStore.litStart + blockSize;
216 zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + (blockSize>>2);
217 zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + (blockSize>>2);
Yann Colletecd651b2016-01-07 15:35:18 +0100218 zc->hbSize = 0;
Yann Collet60096272016-01-08 17:27:50 +0100219 zc->stage = 0;
Yann Collet2acb5d32015-10-29 16:49:43 +0100220
Yann Collet4114f952015-10-30 06:40:22 +0100221 return 0;
Yann Colletf3eca252015-10-22 15:31:46 +0100222}
223
Yann Collet083fcc82015-10-25 14:06:35 +0100224
Yann Collet7b51a292016-01-26 15:58:49 +0100225/*! ZSTD_copyCCtx
226* Duplicate an existing context @srcCCtx into another one @dstCCtx.
227* Only works during stage 0 (i.e. before first call to ZSTD_compressContinue())
228* @return : 0, or an error code */
229size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
230{
231 const U32 contentLog = (srcCCtx->params.strategy == ZSTD_fast) ? 1 : srcCCtx->params.contentLog;
232 const size_t tableSpace = ((1 << contentLog) + (1 << srcCCtx->params.hashLog)) * sizeof(U32);
233
234 if (srcCCtx->stage!=0) return ERROR(stage_wrong);
235
236 ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params);
237
238 /* copy tables */
239 memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace);
240
241 /* copy frame header */
242 dstCCtx->hbSize = srcCCtx->hbSize;
243 memcpy(dstCCtx->headerBuffer , srcCCtx->headerBuffer, srcCCtx->hbSize);
244
245 /* copy dictionary pointers */
246 dstCCtx->nextToUpdate= srcCCtx->nextToUpdate;
247 dstCCtx->nextSrc = srcCCtx->nextSrc;
248 dstCCtx->base = srcCCtx->base;
249 dstCCtx->dictBase = srcCCtx->dictBase;
250 dstCCtx->dictLimit = srcCCtx->dictLimit;
251 dstCCtx->lowLimit = srcCCtx->lowLimit;
252
Yann Colletfb810d62016-01-28 00:18:06 +0100253 /* copy entropy tables */
254 dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
Yann Collet863ec402016-01-28 17:56:33 +0100255 if (srcCCtx->flagStaticTables) {
Yann Collet7b51a292016-01-26 15:58:49 +0100256 memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
Yann Colletfb810d62016-01-28 00:18:06 +0100257 memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable));
258 memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable));
259 memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable));
260 }
Yann Collet7b51a292016-01-26 15:58:49 +0100261
262 return 0;
263}
264
265
Yann Collet863ec402016-01-28 17:56:33 +0100266/*! ZSTD_reduceIndex
Yann Collet88fcd292015-11-25 14:42:45 +0100267* rescale indexes to avoid future overflow (indexes are U32) */
Yann Collet89db5e02015-11-13 11:27:46 +0100268static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
269 const U32 reducerValue)
270{
Yann Collet88fcd292015-11-25 14:42:45 +0100271 const U32 contentLog = (zc->params.strategy == ZSTD_fast) ? 1 : zc->params.contentLog;
Yann Collet89db5e02015-11-13 11:27:46 +0100272 const U32 tableSpaceU32 = (1 << contentLog) + (1 << zc->params.hashLog);
273 U32* table32 = zc->hashTable;
274 U32 index;
275
Yann Colletfb810d62016-01-28 00:18:06 +0100276 for (index=0 ; index < tableSpaceU32 ; index++) {
Yann Collet89db5e02015-11-13 11:27:46 +0100277 if (table32[index] < reducerValue) table32[index] = 0;
278 else table32[index] -= reducerValue;
279 }
280}
281
282
Yann Collet863ec402016-01-28 17:56:33 +0100283/*-*******************************************************
Yann Collet14983e72015-11-11 21:38:21 +0100284* Block entropic compression
285*********************************************************/
Yann Collet14983e72015-11-11 21:38:21 +0100286
Yann Collet59d1f792016-01-23 19:28:41 +0100287/* Block format description
288
289 Block = Literal Section - Sequences Section
290 Prerequisite : size of (compressed) block, maximum size of regenerated data
291
292 1) Literal Section
293
294 1.1) Header : 1-5 bytes
295 flags: 2 bits
296 00 compressed by Huff0
297 01 unused
298 10 is Raw (uncompressed)
299 11 is Rle
300 Note : using 01 => Huff0 with precomputed table ?
301 Note : delta map ? => compressed ?
302
303 1.1.1) Huff0-compressed literal block : 3-5 bytes
Yann Colletafe07092016-01-25 04:10:46 +0100304 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
Yann Collet59d1f792016-01-23 19:28:41 +0100305 srcSize < 1 KB => 3 bytes (2-2-10-10)
Yann Colleta1249dc2016-01-25 04:22:03 +0100306 srcSize < 16KB => 4 bytes (2-2-14-14)
Yann Collet59d1f792016-01-23 19:28:41 +0100307 else => 5 bytes (2-2-18-18)
308 big endian convention
309
310 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
311 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
312 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
313 size&255
314 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
315 size>>8&255
316 size&255
317
318 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
319 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
320 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
321 size&255
322 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
323 size>>8&255
324 size&255
325
Yann Colleta1249dc2016-01-25 04:22:03 +0100326 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
327 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
328 srcSize < 1 KB => 3 bytes (2-2-10-10)
329 srcSize < 16KB => 4 bytes (2-2-14-14)
330 else => 5 bytes (2-2-18-18)
331 big endian convention
332
333 1- CTable available (stored into workspace ?)
Yann Colletb923f652016-01-26 03:14:20 +0100334 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
Yann Colleta1249dc2016-01-25 04:22:03 +0100335
Yann Collet59d1f792016-01-23 19:28:41 +0100336
337 1.2) Literal block content
338
339 1.2.1) Huff0 block, using sizes from header
340 See Huff0 format
341
Yann Colletfb810d62016-01-28 00:18:06 +0100342 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100343
Yann Colletfb810d62016-01-28 00:18:06 +0100344 1.2.3) Raw content
Yann Collet59d1f792016-01-23 19:28:41 +0100345
Yann Colletfb810d62016-01-28 00:18:06 +0100346 1.2.4) single byte
Yann Collet59d1f792016-01-23 19:28:41 +0100347
348
349 2) Sequences section
Yann Colletfb810d62016-01-28 00:18:06 +0100350
351 - Nb Sequences : 2 bytes, little endian
352 - Control Token : 1 byte (see below)
353 - Dumps Length : 1 or 2 bytes (depending on control token)
354 - Dumps : as stated by dumps length
355 - Literal Lengths FSE table (as needed depending on encoding method)
356 - Offset Codes FSE table (as needed depending on encoding method)
357 - Match Lengths FSE table (as needed depending on encoding method)
358
359 2.1) Control Token
360 8 bits, divided as :
361 0-1 : dumpsLength
362 2-3 : MatchLength, FSE encoding method
363 4-5 : Offset Codes, FSE encoding method
364 6-7 : Literal Lengths, FSE encoding method
365
366 FSE encoding method :
367 FSE_ENCODING_RAW : uncompressed; no header
368 FSE_ENCODING_RLE : single repeated value; header 1 byte
369 FSE_ENCODING_STATIC : use prepared table; no header
370 FSE_ENCODING_DYNAMIC : read NCount
Yann Collet59d1f792016-01-23 19:28:41 +0100371*/
Yann Collet14983e72015-11-11 21:38:21 +0100372
373size_t ZSTD_noCompressBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
374{
375 BYTE* const ostart = (BYTE* const)dst;
376
377 if (srcSize + ZSTD_blockHeaderSize > maxDstSize) return ERROR(dstSize_tooSmall);
378 memcpy(ostart + ZSTD_blockHeaderSize, src, srcSize);
379
380 /* Build header */
381 ostart[0] = (BYTE)(srcSize>>16);
382 ostart[1] = (BYTE)(srcSize>>8);
383 ostart[2] = (BYTE) srcSize;
384 ostart[0] += (BYTE)(bt_raw<<6); /* is a raw (uncompressed) block */
385
386 return ZSTD_blockHeaderSize+srcSize;
387}
388
389
390static size_t ZSTD_noCompressLiterals (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
391{
392 BYTE* const ostart = (BYTE* const)dst;
Yann Collet59d1f792016-01-23 19:28:41 +0100393 const U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100394
Yann Collet59d1f792016-01-23 19:28:41 +0100395 if (srcSize + flSize > maxDstSize) return ERROR(dstSize_tooSmall);
Yann Collet14983e72015-11-11 21:38:21 +0100396
Yann Collet59d1f792016-01-23 19:28:41 +0100397 switch(flSize)
398 {
399 case 1: /* 2 - 1 - 5 */
400 ostart[0] = (BYTE)((IS_RAW<<6) + (0<<5) + srcSize);
401 break;
402 case 2: /* 2 - 2 - 12 */
403 ostart[0] = (BYTE)((IS_RAW<<6) + (2<<4) + (srcSize >> 8));
404 ostart[1] = (BYTE)srcSize;
405 break;
406 default: /*note : should not be necessary : flSize is within {1,2,3} */
407 case 3: /* 2 - 2 - 20 */
408 ostart[0] = (BYTE)((IS_RAW<<6) + (3<<4) + (srcSize >> 16));
409 ostart[1] = (BYTE)(srcSize>>8);
410 ostart[2] = (BYTE)srcSize;
411 break;
412 }
413
414 memcpy(ostart + flSize, src, srcSize);
415 return srcSize + flSize;
Yann Collet14983e72015-11-11 21:38:21 +0100416}
417
418static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
419{
420 BYTE* const ostart = (BYTE* const)dst;
Yann Collet59d1f792016-01-23 19:28:41 +0100421 U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
Yann Collet14983e72015-11-11 21:38:21 +0100422
Yann Colletfb810d62016-01-28 00:18:06 +0100423 (void)maxDstSize; /* maxDstSize guaranteed to be >=4, hence large enough */
Yann Collet59d1f792016-01-23 19:28:41 +0100424
425 switch(flSize)
426 {
427 case 1: /* 2 - 1 - 5 */
428 ostart[0] = (BYTE)((IS_RLE<<6) + (0<<5) + srcSize);
429 break;
430 case 2: /* 2 - 2 - 12 */
431 ostart[0] = (BYTE)((IS_RLE<<6) + (2<<4) + (srcSize >> 8));
432 ostart[1] = (BYTE)srcSize;
433 break;
434 default: /*note : should not be necessary : flSize is necessary within {1,2,3} */
435 case 3: /* 2 - 2 - 20 */
436 ostart[0] = (BYTE)((IS_RLE<<6) + (3<<4) + (srcSize >> 16));
437 ostart[1] = (BYTE)(srcSize>>8);
438 ostart[2] = (BYTE)srcSize;
439 break;
440 }
441
442 ostart[flSize] = *(const BYTE*)src;
443 return flSize+1;
Yann Collet14983e72015-11-11 21:38:21 +0100444}
445
Yann Collet59d1f792016-01-23 19:28:41 +0100446
Yann Colletb923f652016-01-26 03:14:20 +0100447size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
Yann Collet14983e72015-11-11 21:38:21 +0100448
Yann Colletb923f652016-01-26 03:14:20 +0100449static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
450 void* dst, size_t maxDstSize,
Yann Collet14983e72015-11-11 21:38:21 +0100451 const void* src, size_t srcSize)
452{
453 const size_t minGain = ZSTD_minGain(srcSize);
454 BYTE* const ostart = (BYTE*)dst;
Yann Colletb923f652016-01-26 03:14:20 +0100455 const size_t lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
Yann Colletafe07092016-01-25 04:10:46 +0100456 U32 singleStream = srcSize < 256;
Yann Colletb923f652016-01-26 03:14:20 +0100457 U32 hType = IS_HUF;
Yann Collet59d1f792016-01-23 19:28:41 +0100458 size_t clitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100459
Yann Collet35f7de52016-01-31 02:51:03 +0100460 if (maxDstSize < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
Yann Collet14983e72015-11-11 21:38:21 +0100461
Yann Colletfb810d62016-01-28 00:18:06 +0100462 if (zc->flagStaticTables && (lhSize==3)) {
Yann Colletb923f652016-01-26 03:14:20 +0100463 hType = IS_PCH;
464 singleStream = 1;
465 clitSize = HUF_compress1X_usingCTable(ostart+lhSize, maxDstSize-lhSize, src, srcSize, zc->hufTable);
Yann Colletfb810d62016-01-28 00:18:06 +0100466 } else {
Yann Colletb923f652016-01-26 03:14:20 +0100467 clitSize = singleStream ? HUF_compress1X(ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12)
468 : HUF_compress2 (ostart+lhSize, maxDstSize-lhSize, src, srcSize, 255, 12);
469 }
Yann Collet14983e72015-11-11 21:38:21 +0100470
Yann Collet59d1f792016-01-23 19:28:41 +0100471 if ((clitSize==0) || (clitSize >= srcSize - minGain)) return ZSTD_noCompressLiterals(dst, maxDstSize, src, srcSize);
472 if (clitSize==1) return ZSTD_compressRleLiteralsBlock(dst, maxDstSize, src, srcSize);
Yann Collet14983e72015-11-11 21:38:21 +0100473
474 /* Build header */
Yann Collet59d1f792016-01-23 19:28:41 +0100475 switch(lhSize)
Yann Collet14983e72015-11-11 21:38:21 +0100476 {
Yann Collet59d1f792016-01-23 19:28:41 +0100477 case 3: /* 2 - 2 - 10 - 10 */
Yann Colletb923f652016-01-26 03:14:20 +0100478 ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100479 ostart[1] = (BYTE)((srcSize<<2) + (clitSize>>8));
480 ostart[2] = (BYTE)(clitSize);
481 break;
482 case 4: /* 2 - 2 - 14 - 14 */
Yann Colletb923f652016-01-26 03:14:20 +0100483 ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100484 ostart[1] = (BYTE)(srcSize>> 2);
485 ostart[2] = (BYTE)((srcSize<<6) + (clitSize>>8));
486 ostart[3] = (BYTE)(clitSize);
487 break;
488 default: /* should not be necessary, lhSize is {3,4,5} */
489 case 5: /* 2 - 2 - 18 - 18 */
Yann Colletb923f652016-01-26 03:14:20 +0100490 ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6));
Yann Collet59d1f792016-01-23 19:28:41 +0100491 ostart[1] = (BYTE)(srcSize>>6);
492 ostart[2] = (BYTE)((srcSize<<2) + (clitSize>>16));
493 ostart[3] = (BYTE)(clitSize>>8);
494 ostart[4] = (BYTE)(clitSize);
495 break;
Yann Collet14983e72015-11-11 21:38:21 +0100496 }
497
Yann Collet59d1f792016-01-23 19:28:41 +0100498 return lhSize+clitSize;
Yann Collet14983e72015-11-11 21:38:21 +0100499}
500
501
Yann Colletafe07092016-01-25 04:10:46 +0100502#define LITERAL_NOENTROPY 63 /* don't even attempt to compress literals below this threshold (cheap heuristic) */
Yann Collet14983e72015-11-11 21:38:21 +0100503
Yann Colletb923f652016-01-26 03:14:20 +0100504size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
505 void* dst, size_t maxDstSize,
Yann Collet14983e72015-11-11 21:38:21 +0100506 size_t srcSize)
507{
Yann Colletb923f652016-01-26 03:14:20 +0100508 const seqStore_t* seqStorePtr = &(zc->seqStore);
Yann Collet14983e72015-11-11 21:38:21 +0100509 U32 count[MaxSeq+1];
510 S16 norm[MaxSeq+1];
511 size_t mostFrequent;
Yann Colletfb810d62016-01-28 00:18:06 +0100512 U32 max;
513 FSE_CTable* CTable_LitLength = zc->litlengthCTable;
514 FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
515 FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
Yann Collet14983e72015-11-11 21:38:21 +0100516 U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
517 const BYTE* const op_lit_start = seqStorePtr->litStart;
518 const BYTE* const llTable = seqStorePtr->litLengthStart;
519 const BYTE* const llPtr = seqStorePtr->litLength;
520 const BYTE* const mlTable = seqStorePtr->matchLengthStart;
521 const U32* const offsetTable = seqStorePtr->offsetStart;
522 BYTE* const offCodeTable = seqStorePtr->offCodeStart;
Yann Collet5054ee02015-11-23 13:34:21 +0100523 BYTE* const ostart = (BYTE*)dst;
524 BYTE* op = ostart;
525 BYTE* const oend = ostart + maxDstSize;
Yann Collet14983e72015-11-11 21:38:21 +0100526 const size_t nbSeq = llPtr - llTable;
527 const size_t minGain = ZSTD_minGain(srcSize);
528 const size_t maxCSize = srcSize - minGain;
529 BYTE* seqHead;
530
531
532 /* Compress literals */
533 {
534 size_t cSize;
535 size_t litSize = seqStorePtr->lit - op_lit_start;
Yann Colletfb810d62016-01-28 00:18:06 +0100536 const size_t minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
Yann Collet14983e72015-11-11 21:38:21 +0100537
Yann Colletb923f652016-01-26 03:14:20 +0100538 if (litSize <= minLitSize)
Yann Collet14983e72015-11-11 21:38:21 +0100539 cSize = ZSTD_noCompressLiterals(op, maxDstSize, op_lit_start, litSize);
540 else
Yann Colletb923f652016-01-26 03:14:20 +0100541 cSize = ZSTD_compressLiterals(zc, op, maxDstSize, op_lit_start, litSize);
Yann Collet14983e72015-11-11 21:38:21 +0100542 if (ZSTD_isError(cSize)) return cSize;
543 op += cSize;
544 }
545
546 /* Sequences Header */
Yann Collet61e16ce2016-01-31 02:04:15 +0100547 if ((oend-op) < MIN_SEQUENCES_SIZE) return ERROR(dstSize_tooSmall);
548 if (nbSeq < 128) *op++ = (BYTE)nbSeq;
549 else {
Yann Collet35f7de52016-01-31 02:51:03 +0100550 op[0] = (BYTE)((nbSeq>>8) + 128); op[1] = (BYTE)nbSeq; op+=2;
Yann Collet61e16ce2016-01-31 02:04:15 +0100551 }
Yann Collete93d6ce2016-01-31 00:58:06 +0100552 if (nbSeq==0) goto _check_compressibility;
Yann Collet14983e72015-11-11 21:38:21 +0100553
Yann Collet863ec402016-01-28 17:56:33 +0100554 /* dumps : contains rests of large lengths */
Yann Collete93d6ce2016-01-31 00:58:06 +0100555 if ((oend-op) < 3 /* dumps */ + 1 /*seqHead*/)
556 return ERROR(dstSize_tooSmall);
557 seqHead = op;
Yann Collet14983e72015-11-11 21:38:21 +0100558 {
559 size_t dumpsLength = seqStorePtr->dumps - seqStorePtr->dumpsStart;
Yann Colletfb810d62016-01-28 00:18:06 +0100560 if (dumpsLength < 512) {
Yann Collet14983e72015-11-11 21:38:21 +0100561 op[0] = (BYTE)(dumpsLength >> 8);
562 op[1] = (BYTE)(dumpsLength);
563 op += 2;
Yann Colletfb810d62016-01-28 00:18:06 +0100564 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100565 op[0] = 2;
566 op[1] = (BYTE)(dumpsLength>>8);
567 op[2] = (BYTE)(dumpsLength);
568 op += 3;
569 }
570 if ((size_t)(oend-op) < dumpsLength+6) return ERROR(dstSize_tooSmall);
571 memcpy(op, seqStorePtr->dumpsStart, dumpsLength);
572 op += dumpsLength;
573 }
574
Yann Colletfb810d62016-01-28 00:18:06 +0100575#define MIN_SEQ_FOR_DYNAMIC_FSE 64
576#define MAX_SEQ_FOR_STATIC_FSE 1000
577
Yann Collet14983e72015-11-11 21:38:21 +0100578 /* CTable for Literal Lengths */
579 max = MaxLL;
Yann Collete93d6ce2016-01-31 00:58:06 +0100580 mostFrequent = FSE_countFast(count, &max, llTable, nbSeq);
Yann Colletfb810d62016-01-28 00:18:06 +0100581 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collete93d6ce2016-01-31 00:58:06 +0100582 *op++ = llTable[0];
Yann Collet14983e72015-11-11 21:38:21 +0100583 FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
Yann Colletfb810d62016-01-28 00:18:06 +0100584 LLtype = FSE_ENCODING_RLE;
585 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
586 LLtype = FSE_ENCODING_STATIC;
587 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LLbits-1)))) {
Yann Collet14983e72015-11-11 21:38:21 +0100588 FSE_buildCTable_raw(CTable_LitLength, LLbits);
Yann Colletfb810d62016-01-28 00:18:06 +0100589 LLtype = FSE_ENCODING_RAW;
590 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100591 size_t NCountSize;
Yann Collete93d6ce2016-01-31 00:58:06 +0100592 size_t nbSeq_1 = nbSeq;
Yann Colletfb810d62016-01-28 00:18:06 +0100593 U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
Yann Collete93d6ce2016-01-31 00:58:06 +0100594 if (count[llTable[nbSeq-1]]>1) { count[llTable[nbSeq-1]]--; nbSeq_1--; }
595 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Collet14983e72015-11-11 21:38:21 +0100596 NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
597 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
598 op += NCountSize;
599 FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
Yann Colletfb810d62016-01-28 00:18:06 +0100600 LLtype = FSE_ENCODING_DYNAMIC;
Yann Collet14983e72015-11-11 21:38:21 +0100601 }
602
Yann Colletfb810d62016-01-28 00:18:06 +0100603 /* CTable for Offset codes */
604 { /* create Offset codes */
605 size_t i; for (i=0; i<nbSeq; i++) {
Yann Collet14983e72015-11-11 21:38:21 +0100606 offCodeTable[i] = (BYTE)ZSTD_highbit(offsetTable[i]) + 1;
607 if (offsetTable[i]==0) offCodeTable[i]=0;
608 }
Yann Collet14983e72015-11-11 21:38:21 +0100609 }
Yann Colletfb810d62016-01-28 00:18:06 +0100610 max = MaxOff;
611 mostFrequent = FSE_countFast(count, &max, offCodeTable, nbSeq);
612 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collete93d6ce2016-01-31 00:58:06 +0100613 *op++ = offCodeTable[0];
Yann Collet14983e72015-11-11 21:38:21 +0100614 FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
Yann Colletfb810d62016-01-28 00:18:06 +0100615 Offtype = FSE_ENCODING_RLE;
616 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
617 Offtype = FSE_ENCODING_STATIC;
618 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
Yann Collet14983e72015-11-11 21:38:21 +0100619 FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
Yann Colletfb810d62016-01-28 00:18:06 +0100620 Offtype = FSE_ENCODING_RAW;
621 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100622 size_t NCountSize;
Yann Collete93d6ce2016-01-31 00:58:06 +0100623 size_t nbSeq_1 = nbSeq;
Yann Colletfb810d62016-01-28 00:18:06 +0100624 U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
Yann Collete93d6ce2016-01-31 00:58:06 +0100625 if (count[offCodeTable[nbSeq-1]]>1) { count[offCodeTable[nbSeq-1]]--; nbSeq_1--; }
626 FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
Yann Collet14983e72015-11-11 21:38:21 +0100627 NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
628 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
629 op += NCountSize;
630 FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
Yann Colletfb810d62016-01-28 00:18:06 +0100631 Offtype = FSE_ENCODING_DYNAMIC;
Yann Collet14983e72015-11-11 21:38:21 +0100632 }
633
634 /* CTable for MatchLengths */
635 max = MaxML;
Yann Collete93d6ce2016-01-31 00:58:06 +0100636 mostFrequent = FSE_countFast(count, &max, mlTable, nbSeq);
Yann Colletfb810d62016-01-28 00:18:06 +0100637 if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
Yann Collete93d6ce2016-01-31 00:58:06 +0100638 *op++ = *mlTable;
Yann Collet14983e72015-11-11 21:38:21 +0100639 FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
Yann Colletfb810d62016-01-28 00:18:06 +0100640 MLtype = FSE_ENCODING_RLE;
641 } else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
642 MLtype = FSE_ENCODING_STATIC;
643 } else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (MLbits-1)))) {
Yann Collet14983e72015-11-11 21:38:21 +0100644 FSE_buildCTable_raw(CTable_MatchLength, MLbits);
Yann Colletfb810d62016-01-28 00:18:06 +0100645 MLtype = FSE_ENCODING_RAW;
646 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100647 size_t NCountSize;
Yann Colletfb810d62016-01-28 00:18:06 +0100648 U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
Yann Collet14983e72015-11-11 21:38:21 +0100649 FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
650 NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
651 if (FSE_isError(NCountSize)) return ERROR(GENERIC);
652 op += NCountSize;
653 FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
Yann Colletfb810d62016-01-28 00:18:06 +0100654 MLtype = FSE_ENCODING_DYNAMIC;
Yann Collet14983e72015-11-11 21:38:21 +0100655 }
656
657 seqHead[0] += (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
Yann Colletfb810d62016-01-28 00:18:06 +0100658 zc->flagStaticTables = 0;
Yann Collet14983e72015-11-11 21:38:21 +0100659
660 /* Encoding Sequences */
661 {
662 size_t streamSize, errorCode;
663 BIT_CStream_t blockStream;
664 FSE_CState_t stateMatchLength;
665 FSE_CState_t stateOffsetBits;
666 FSE_CState_t stateLitLength;
667 int i;
668
669 errorCode = BIT_initCStream(&blockStream, op, oend-op);
670 if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); /* not enough space remaining */
Yann Collet14983e72015-11-11 21:38:21 +0100671
Yann Collete93d6ce2016-01-31 00:58:06 +0100672 /* first symbols */
673 FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlTable[nbSeq-1]);
674 FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, offCodeTable[nbSeq-1]);
675 FSE_initCState2(&stateLitLength, CTable_LitLength, llTable[nbSeq-1]);
676 BIT_addBits(&blockStream, offsetTable[nbSeq-1], offCodeTable[nbSeq-1] ? (offCodeTable[nbSeq-1]-1) : 0);
677 BIT_flushBits(&blockStream);
678
679 for (i=(int)nbSeq-2; i>=0; i--) {
Yann Colletfb810d62016-01-28 00:18:06 +0100680 BYTE mlCode = mlTable[i];
Yann Collet14983e72015-11-11 21:38:21 +0100681 U32 offset = offsetTable[i];
682 BYTE offCode = offCodeTable[i]; /* 32b*/ /* 64b*/
Yann Collete93d6ce2016-01-31 00:58:06 +0100683 U32 nbBits = (offCode-1) + (!offCode);
Yann Collet14983e72015-11-11 21:38:21 +0100684 BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/
Yann Colletfb810d62016-01-28 00:18:06 +0100685 FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 17 */ /* 17 */
Yann Collet743402c2015-11-20 12:03:53 +0100686 if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
Yann Collet14983e72015-11-11 21:38:21 +0100687 FSE_encodeSymbol(&blockStream, &stateLitLength, litLength); /* 26 */ /* 61 */
Yann Collete93d6ce2016-01-31 00:58:06 +0100688 FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 16 */ /* 51 */
689 if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
690 BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */
Yann Collet14983e72015-11-11 21:38:21 +0100691 BIT_flushBits(&blockStream); /* 7 */ /* 7 */
692 }
693
694 FSE_flushCState(&blockStream, &stateMatchLength);
695 FSE_flushCState(&blockStream, &stateOffsetBits);
696 FSE_flushCState(&blockStream, &stateLitLength);
697
698 streamSize = BIT_closeCStream(&blockStream);
699 if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
700 op += streamSize;
701 }
702
703 /* check compressibility */
Yann Collete93d6ce2016-01-31 00:58:06 +0100704_check_compressibility:
Yann Collet5054ee02015-11-23 13:34:21 +0100705 if ((size_t)(op-ostart) >= maxCSize) return 0;
Yann Collet14983e72015-11-11 21:38:21 +0100706
Yann Collet5054ee02015-11-23 13:34:21 +0100707 return op - ostart;
Yann Collet14983e72015-11-11 21:38:21 +0100708}
709
710
Yann Collete93d6ce2016-01-31 00:58:06 +0100711/*! ZSTD_storeSeq
712 Store a sequence (literal length, literals, offset code and match length code) into seqStore_t
Yann Collet14983e72015-11-11 21:38:21 +0100713 @offsetCode : distance to match, or 0 == repCode
714 @matchCode : matchLength - MINMATCH
715*/
716MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, size_t offsetCode, size_t matchCode)
717{
718#if 0
719 static const BYTE* g_start = NULL;
720 if (g_start==NULL) g_start = literals;
Yann Colletfb810d62016-01-28 00:18:06 +0100721 //if (literals - g_start == 8695)
Yann Collet14983e72015-11-11 21:38:21 +0100722 printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
723 (U32)(literals - g_start), (U32)litLength, (U32)matchCode+4, (U32)offsetCode);
724#endif
725
726 /* copy Literals */
727 ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
728 seqStorePtr->lit += litLength;
729
730 /* literal Length */
Yann Colletfb810d62016-01-28 00:18:06 +0100731 if (litLength >= MaxLL) {
Yann Collet14983e72015-11-11 21:38:21 +0100732 *(seqStorePtr->litLength++) = MaxLL;
Yann Colletfb810d62016-01-28 00:18:06 +0100733 if (litLength<255 + MaxLL) {
Yann Collet14983e72015-11-11 21:38:21 +0100734 *(seqStorePtr->dumps++) = (BYTE)(litLength - MaxLL);
Yann Colletfb810d62016-01-28 00:18:06 +0100735 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100736 *(seqStorePtr->dumps++) = 255;
737 MEM_writeLE32(seqStorePtr->dumps, (U32)litLength); seqStorePtr->dumps += 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100738 } }
Yann Collet14983e72015-11-11 21:38:21 +0100739 else *(seqStorePtr->litLength++) = (BYTE)litLength;
740
741 /* match offset */
742 *(seqStorePtr->offset++) = (U32)offsetCode;
743
744 /* match Length */
Yann Colletfb810d62016-01-28 00:18:06 +0100745 if (matchCode >= MaxML) {
Yann Collet14983e72015-11-11 21:38:21 +0100746 *(seqStorePtr->matchLength++) = MaxML;
Yann Colletfb810d62016-01-28 00:18:06 +0100747 if (matchCode < 255+MaxML) {
Yann Collet14983e72015-11-11 21:38:21 +0100748 *(seqStorePtr->dumps++) = (BYTE)(matchCode - MaxML);
Yann Colletfb810d62016-01-28 00:18:06 +0100749 } else {
Yann Collet14983e72015-11-11 21:38:21 +0100750 *(seqStorePtr->dumps++) = 255;
751 MEM_writeLE32(seqStorePtr->dumps, (U32)matchCode); seqStorePtr->dumps += 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100752 } }
Yann Collet14983e72015-11-11 21:38:21 +0100753 else *(seqStorePtr->matchLength++) = (BYTE)matchCode;
754}
755
756
Yann Colletf3eca252015-10-22 15:31:46 +0100757/* *************************************
Yann Collet14983e72015-11-11 21:38:21 +0100758* Match length counter
759***************************************/
760static size_t ZSTD_read_ARCH(const void* p) { size_t r; memcpy(&r, p, sizeof(r)); return r; }
761
762static unsigned ZSTD_highbit(U32 val)
763{
764# if defined(_MSC_VER) /* Visual */
765 unsigned long r=0;
766 _BitScanReverse(&r, val);
767 return (unsigned)r;
768# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
769 return 31 - __builtin_clz(val);
770# else /* Software version */
771 static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
772 U32 v = val;
773 int r;
774 v |= v >> 1;
775 v |= v >> 2;
776 v |= v >> 4;
777 v |= v >> 8;
778 v |= v >> 16;
779 r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];
780 return r;
781# endif
782}
783
Yann Collet5054ee02015-11-23 13:34:21 +0100784static unsigned ZSTD_NbCommonBytes (register size_t val)
Yann Collet14983e72015-11-11 21:38:21 +0100785{
Yann Collet863ec402016-01-28 17:56:33 +0100786 if (MEM_isLittleEndian()) {
787 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100788# if defined(_MSC_VER) && defined(_WIN64)
789 unsigned long r = 0;
790 _BitScanForward64( &r, (U64)val );
Yann Colletd6080882015-12-09 09:05:22 +0100791 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100792# elif defined(__GNUC__) && (__GNUC__ >= 3)
793 return (__builtin_ctzll((U64)val) >> 3);
794# else
795 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 };
796 return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
797# endif
Yann Collet863ec402016-01-28 17:56:33 +0100798 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100799# if defined(_MSC_VER)
800 unsigned long r=0;
801 _BitScanForward( &r, (U32)val );
Yann Colletd6080882015-12-09 09:05:22 +0100802 return (unsigned)(r>>3);
Yann Collet14983e72015-11-11 21:38:21 +0100803# elif defined(__GNUC__) && (__GNUC__ >= 3)
804 return (__builtin_ctz((U32)val) >> 3);
805# else
806 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 };
807 return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
808# endif
809 }
Yann Collet863ec402016-01-28 17:56:33 +0100810 } else { /* Big Endian CPU */
811 if (MEM_64bits()) {
Yann Collet14983e72015-11-11 21:38:21 +0100812# if defined(_MSC_VER) && defined(_WIN64)
813 unsigned long r = 0;
814 _BitScanReverse64( &r, val );
815 return (unsigned)(r>>3);
816# elif defined(__GNUC__) && (__GNUC__ >= 3)
817 return (__builtin_clzll(val) >> 3);
818# else
819 unsigned r;
820 const unsigned n32 = sizeof(size_t)*4; /* calculate this way due to compiler complaining in 32-bits mode */
821 if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }
822 if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
823 r += (!val);
824 return r;
825# endif
Yann Collet863ec402016-01-28 17:56:33 +0100826 } else { /* 32 bits */
Yann Collet14983e72015-11-11 21:38:21 +0100827# if defined(_MSC_VER)
828 unsigned long r = 0;
829 _BitScanReverse( &r, (unsigned long)val );
830 return (unsigned)(r>>3);
831# elif defined(__GNUC__) && (__GNUC__ >= 3)
832 return (__builtin_clz((U32)val) >> 3);
833# else
834 unsigned r;
835 if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
836 r += (!val);
837 return r;
838# endif
Yann Collet863ec402016-01-28 17:56:33 +0100839 } }
Yann Collet14983e72015-11-11 21:38:21 +0100840}
841
842
Yann Collet5054ee02015-11-23 13:34:21 +0100843static size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
Yann Collet14983e72015-11-11 21:38:21 +0100844{
845 const BYTE* const pStart = pIn;
846
Yann Colletfb810d62016-01-28 00:18:06 +0100847 while ((pIn<pInLimit-(sizeof(size_t)-1))) {
Yann Collet14983e72015-11-11 21:38:21 +0100848 size_t diff = ZSTD_read_ARCH(pMatch) ^ ZSTD_read_ARCH(pIn);
849 if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }
850 pIn += ZSTD_NbCommonBytes(diff);
851 return (size_t)(pIn - pStart);
852 }
853
854 if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }
855 if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }
856 if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
857 return (size_t)(pIn - pStart);
858}
859
Yann Collet5054ee02015-11-23 13:34:21 +0100860/** ZSTD_count_2segments
861* can count match length with ip & match in potentially 2 different segments.
862* convention : on reaching mEnd, match count continue starting from iStart
863*/
864static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)
865{
866 size_t matchLength;
867 const BYTE* vEnd = ip + (mEnd - match);
868 if (vEnd > iEnd) vEnd = iEnd;
869 matchLength = ZSTD_count(ip, match, vEnd);
870 if (match + matchLength == mEnd)
871 matchLength += ZSTD_count(ip+matchLength, iStart, iEnd);
872 return matchLength;
873}
874
Yann Collet14983e72015-11-11 21:38:21 +0100875
876
Yann Collet863ec402016-01-28 17:56:33 +0100877/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +0100878* Hashes
Yann Colletf3eca252015-10-22 15:31:46 +0100879***************************************/
Yann Collet4b100f42015-10-30 15:49:48 +0100880static const U32 prime4bytes = 2654435761U;
Yann Collet863ec402016-01-28 17:56:33 +0100881static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100882static size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); }
Yann Collet2acb5d32015-10-29 16:49:43 +0100883
Yann Collet4b100f42015-10-30 15:49:48 +0100884static const U64 prime5bytes = 889523592379ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100885static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64-40)) * prime5bytes) >> (64-h)) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100886static size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_read64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100887
888static const U64 prime6bytes = 227718039650203ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100889static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64-48)) * prime6bytes) >> (64-h)) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100890static size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_read64(p), h); }
Yann Collet4b100f42015-10-30 15:49:48 +0100891
Yann Collet14983e72015-11-11 21:38:21 +0100892static const U64 prime7bytes = 58295818150454627ULL;
Yann Collet863ec402016-01-28 17:56:33 +0100893static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64-56)) * prime7bytes) >> (64-h)) ; }
Yann Collet5be2dd22015-11-11 13:43:58 +0100894static size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_read64(p), h); }
Yann Collet1f44b3f2015-11-05 17:32:18 +0100895
Yann Collet5be2dd22015-11-11 13:43:58 +0100896static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
Yann Collet4b100f42015-10-30 15:49:48 +0100897{
898 switch(mls)
899 {
900 default:
Yann Collet5be2dd22015-11-11 13:43:58 +0100901 case 4: return ZSTD_hash4Ptr(p, hBits);
902 case 5: return ZSTD_hash5Ptr(p, hBits);
903 case 6: return ZSTD_hash6Ptr(p, hBits);
904 case 7: return ZSTD_hash7Ptr(p, hBits);
Yann Collet4b100f42015-10-30 15:49:48 +0100905 }
906}
Yann Collet2acb5d32015-10-29 16:49:43 +0100907
Yann Collet863ec402016-01-28 17:56:33 +0100908
Yann Collet1f44b3f2015-11-05 17:32:18 +0100909/* *************************************
910* Fast Scan
911***************************************/
Yann Collet417890c2015-12-04 17:16:37 +0100912#define FILLHASHSTEP 3
913static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
914{
915 U32* const hashTable = zc->hashTable;
916 const U32 hBits = zc->params.hashLog;
917 const BYTE* const base = zc->base;
918 const BYTE* ip = base + zc->nextToUpdate;
919 const BYTE* const iend = (const BYTE*) end;
920
Yann Colletfb810d62016-01-28 00:18:06 +0100921 while(ip <= iend) {
Yann Collet417890c2015-12-04 17:16:37 +0100922 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
923 ip += FILLHASHSTEP;
924 }
925}
926
927
Yann Collet1f44b3f2015-11-05 17:32:18 +0100928FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +0100929void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
Yann Collet89db5e02015-11-13 11:27:46 +0100930 const void* src, size_t srcSize,
931 const U32 mls)
Yann Collet1f44b3f2015-11-05 17:32:18 +0100932{
Yann Collet417890c2015-12-04 17:16:37 +0100933 U32* const hashTable = zc->hashTable;
Yann Colletc3652152015-11-24 14:06:07 +0100934 const U32 hBits = zc->params.hashLog;
935 seqStore_t* seqStorePtr = &(zc->seqStore);
936 const BYTE* const base = zc->base;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100937 const BYTE* const istart = (const BYTE*)src;
Yann Collet805a52a2015-11-06 10:52:17 +0100938 const BYTE* ip = istart;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100939 const BYTE* anchor = istart;
Yann Colletd94efbf2015-12-29 14:29:08 +0100940 const U32 lowIndex = zc->dictLimit;
941 const BYTE* const lowest = base + lowIndex;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100942 const BYTE* const iend = istart + srcSize;
943 const BYTE* const ilimit = iend - 8;
944
Yann Collet89db5e02015-11-13 11:27:46 +0100945 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100946
947
948 /* init */
Yann Collet743402c2015-11-20 12:03:53 +0100949 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +0100950 if (ip < lowest+REPCODE_STARTVALUE) ip = lowest+REPCODE_STARTVALUE;
Yann Collet1f44b3f2015-11-05 17:32:18 +0100951
952 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +0100953 while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
Yann Collet5054ee02015-11-23 13:34:21 +0100954 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +0100955 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100956 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Colletd94efbf2015-12-29 14:29:08 +0100957 const U32 matchIndex = hashTable[h];
958 const BYTE* match = base + matchIndex;
Yann Collet96ffa422016-01-02 01:16:28 +0100959 const U32 current = (U32)(ip-base);
960 hashTable[h] = current; /* update hash table */
Yann Collet1f44b3f2015-11-05 17:32:18 +0100961
Yann Colletfb810d62016-01-28 00:18:06 +0100962 if (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)) { /* note : by construction, offset_1 <= current */
Yann Collet5054ee02015-11-23 13:34:21 +0100963 mlCode = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend);
Yann Collet402fdcf2015-11-20 12:46:08 +0100964 ip++;
965 offset = 0;
Yann Colletfb810d62016-01-28 00:18:06 +0100966 } else {
Yann Colletd94efbf2015-12-29 14:29:08 +0100967 if ( (matchIndex <= lowIndex) ||
Yann Colletfb810d62016-01-28 00:18:06 +0100968 (MEM_read32(match) != MEM_read32(ip)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +0100969 ip += ((ip-anchor) >> g_searchStrength) + 1;
970 continue;
971 }
Yann Collet5054ee02015-11-23 13:34:21 +0100972 mlCode = ZSTD_count(ip+MINMATCH, match+MINMATCH, iend);
Yann Collet402fdcf2015-11-20 12:46:08 +0100973 offset = ip-match;
Yann Collet5054ee02015-11-23 13:34:21 +0100974 while ((ip>anchor) && (match>lowest) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +0100975 offset_2 = offset_1;
976 offset_1 = offset;
977 }
Yann Collet1f44b3f2015-11-05 17:32:18 +0100978
Yann Collet402fdcf2015-11-20 12:46:08 +0100979 /* match found */
Yann Collet6bcdeac2015-11-26 11:43:00 +0100980 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
Yann Collet5054ee02015-11-23 13:34:21 +0100981 ip += mlCode + MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +0100982 anchor = ip;
983
Yann Colletfb810d62016-01-28 00:18:06 +0100984 if (ip <= ilimit) {
Yann Collet402fdcf2015-11-20 12:46:08 +0100985 /* Fill Table */
Yann Colletecd651b2016-01-07 15:35:18 +0100986 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 +0100987 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
988 /* check immediate repcode */
989 while ( (ip <= ilimit)
Yann Colletfb810d62016-01-28 00:18:06 +0100990 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +0100991 /* store sequence */
Yann Collet06eade52015-11-23 14:23:47 +0100992 size_t rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
Yann Collet402fdcf2015-11-20 12:46:08 +0100993 size_t tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
994 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
Yann Collet06eade52015-11-23 14:23:47 +0100995 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rlCode);
996 ip += rlCode+MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +0100997 anchor = ip;
998 continue; /* faster when present ... (?) */
Yann Colletfb810d62016-01-28 00:18:06 +0100999 } } }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001000
1001 /* Last Literals */
1002 {
1003 size_t lastLLSize = iend - anchor;
1004 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1005 seqStorePtr->lit += lastLLSize;
1006 }
Yann Collet1f44b3f2015-11-05 17:32:18 +01001007}
1008
1009
Yann Collet59d1f792016-01-23 19:28:41 +01001010void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
1011 const void* src, size_t srcSize)
Yann Collet1f44b3f2015-11-05 17:32:18 +01001012{
1013 const U32 mls = ctx->params.searchLength;
1014 switch(mls)
1015 {
1016 default:
1017 case 4 :
Yann Collet59d1f792016-01-23 19:28:41 +01001018 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001019 case 5 :
Yann Collet59d1f792016-01-23 19:28:41 +01001020 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001021 case 6 :
Yann Collet59d1f792016-01-23 19:28:41 +01001022 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001023 case 7 :
Yann Collet59d1f792016-01-23 19:28:41 +01001024 ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001025 }
1026}
Yann Colletf3eca252015-10-22 15:31:46 +01001027
Yann Colletf3eca252015-10-22 15:31:46 +01001028
Yann Collet93a823c2015-11-13 15:08:43 +01001029//FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001030void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
1031 const void* src, size_t srcSize,
1032 const U32 mls)
Yann Collet89db5e02015-11-13 11:27:46 +01001033{
1034 U32* hashTable = ctx->hashTable;
1035 const U32 hBits = ctx->params.hashLog;
1036 seqStore_t* seqStorePtr = &(ctx->seqStore);
1037 const BYTE* const base = ctx->base;
1038 const BYTE* const dictBase = ctx->dictBase;
1039 const BYTE* const istart = (const BYTE*)src;
1040 const BYTE* ip = istart;
1041 const BYTE* anchor = istart;
1042 const U32 lowLimit = ctx->lowLimit;
Yann Collet5054ee02015-11-23 13:34:21 +01001043 const BYTE* const dictStart = dictBase + lowLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001044 const U32 dictLimit = ctx->dictLimit;
Yann Collet743402c2015-11-20 12:03:53 +01001045 const BYTE* const lowPrefixPtr = base + dictLimit;
1046 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001047 const BYTE* const iend = istart + srcSize;
1048 const BYTE* const ilimit = iend - 8;
1049
Yann Collet138e89c2015-11-17 14:26:54 +01001050 U32 offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001051
1052
1053 /* init */
1054 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet61e16ce2016-01-31 02:04:15 +01001055 /* skip first position to avoid read overflow during repcode match check */
Yann Colletfb810d62016-01-28 00:18:06 +01001056 hashTable[ZSTD_hashPtr(ip+0, hBits, mls)] = (U32)(ip-base+0);
Yann Collet61e16ce2016-01-31 02:04:15 +01001057 ip += REPCODE_STARTVALUE;
Yann Collet89db5e02015-11-13 11:27:46 +01001058
1059 /* Main Search Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001060 while (ip < ilimit) { /* < instead of <=, because (ip+1) */
Yann Collet89db5e02015-11-13 11:27:46 +01001061 const size_t h = ZSTD_hashPtr(ip, hBits, mls);
Yann Collet743402c2015-11-20 12:03:53 +01001062 const U32 matchIndex = hashTable[h];
Yann Collet89db5e02015-11-13 11:27:46 +01001063 const BYTE* matchBase = matchIndex < dictLimit ? dictBase : base;
Yann Collet6bcdeac2015-11-26 11:43:00 +01001064 const BYTE* match = matchBase + matchIndex;
Yann Collet89db5e02015-11-13 11:27:46 +01001065 const U32 current = (U32)(ip-base);
Yann Collet743402c2015-11-20 12:03:53 +01001066 const U32 repIndex = current + 1 - offset_1;
Yann Collet402fdcf2015-11-20 12:46:08 +01001067 const BYTE* repBase = repIndex < dictLimit ? dictBase : base;
Yann Collet89db5e02015-11-13 11:27:46 +01001068 const BYTE* repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001069 size_t mlCode;
Yann Collet743402c2015-11-20 12:03:53 +01001070 U32 offset;
Yann Collet89db5e02015-11-13 11:27:46 +01001071 hashTable[h] = current; /* update hash table */
1072
1073 if ( ((repIndex <= dictLimit-4) || (repIndex >= dictLimit))
Yann Colletfb810d62016-01-28 00:18:06 +01001074 && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001075 const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001076 mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
Yann Collet743402c2015-11-20 12:03:53 +01001077 ip++;
Yann Collet402fdcf2015-11-20 12:46:08 +01001078 offset = 0;
Yann Colletfb810d62016-01-28 00:18:06 +01001079 } else {
Yann Collet402fdcf2015-11-20 12:46:08 +01001080 if ( (matchIndex < lowLimit) ||
1081 (MEM_read32(match) != MEM_read32(ip)) )
1082 { ip += ((ip-anchor) >> g_searchStrength) + 1; continue; }
1083 {
1084 const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001085 const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
1086 mlCode = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iend, matchEnd, lowPrefixPtr);
Yann Colletfb810d62016-01-28 00:18:06 +01001087 while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
Yann Collet402fdcf2015-11-20 12:46:08 +01001088 offset = current - matchIndex;
1089 offset_2 = offset_1;
1090 offset_1 = offset;
Yann Colletfb810d62016-01-28 00:18:06 +01001091 } }
Yann Collet89db5e02015-11-13 11:27:46 +01001092
Yann Collet5054ee02015-11-23 13:34:21 +01001093 /* found a match : store it */
1094 ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, offset, mlCode);
Yann Collet5054ee02015-11-23 13:34:21 +01001095 ip += mlCode + MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001096 anchor = ip;
1097
Yann Colletfb810d62016-01-28 00:18:06 +01001098 if (ip <= ilimit) {
Yann Collet6bcdeac2015-11-26 11:43:00 +01001099 /* Fill Table */
Yann Collet239cc282015-11-23 16:17:21 +01001100 hashTable[ZSTD_hashPtr(base+current+2, hBits, mls)] = current+2;
Yann Collet402fdcf2015-11-20 12:46:08 +01001101 hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
1102 /* check immediate repcode */
Yann Colletfb810d62016-01-28 00:18:06 +01001103 while (ip <= ilimit) {
Yann Collet402fdcf2015-11-20 12:46:08 +01001104 U32 current2 = (U32)(ip-base);
1105 const U32 repIndex2 = current2 - offset_2;
1106 const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
Yann Collet743402c2015-11-20 12:03:53 +01001107 if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
Yann Colletfb810d62016-01-28 00:18:06 +01001108 && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
Yann Collet5054ee02015-11-23 13:34:21 +01001109 const BYTE* const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend;
1110 size_t repLength2 = ZSTD_count_2segments(ip+MINMATCH, repMatch2+MINMATCH, iend, repEnd2, lowPrefixPtr);
1111 U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
1112 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2);
1113 hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2;
1114 ip += repLength2+MINMATCH;
Yann Collet402fdcf2015-11-20 12:46:08 +01001115 anchor = ip;
1116 continue;
1117 }
Yann Collet743402c2015-11-20 12:03:53 +01001118 break;
Yann Colletfb810d62016-01-28 00:18:06 +01001119 } } }
Yann Collet89db5e02015-11-13 11:27:46 +01001120
1121 /* Last Literals */
1122 {
1123 size_t lastLLSize = iend - anchor;
1124 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1125 seqStorePtr->lit += lastLLSize;
1126 }
Yann Collet89db5e02015-11-13 11:27:46 +01001127}
1128
1129
Yann Collet59d1f792016-01-23 19:28:41 +01001130void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
Yann Collet89db5e02015-11-13 11:27:46 +01001131 const void* src, size_t srcSize)
1132{
1133 const U32 mls = ctx->params.searchLength;
1134 switch(mls)
1135 {
1136 default:
1137 case 4 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001138 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001139 case 5 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001140 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001141 case 6 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001142 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001143 case 7 :
Yann Colleta1249dc2016-01-25 04:22:03 +01001144 ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); return;
Yann Collet89db5e02015-11-13 11:27:46 +01001145 }
1146}
1147
1148
Yann Colletf3eca252015-10-22 15:31:46 +01001149/* *************************************
Yann Collet96b9f0b2015-11-04 03:52:54 +01001150* Binary Tree search
Yann Colletf3eca252015-10-22 15:31:46 +01001151***************************************/
Yann Collet1358f912016-01-01 07:29:39 +01001152/** ZSTD_insertBt1 : add one or multiple positions to tree
Yann Collet6bcdeac2015-11-26 11:43:00 +01001153* @ip : assumed <= iend-8
Yann Collet06eade52015-11-23 14:23:47 +01001154* @return : nb of positions added */
Yann Collet1358f912016-01-01 07:29:39 +01001155static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, const BYTE* const iend, U32 nbCompares,
1156 U32 extDict)
Yann Collet96b9f0b2015-11-04 03:52:54 +01001157{
1158 U32* const hashTable = zc->hashTable;
1159 const U32 hashLog = zc->params.hashLog;
Yann Collet5be2dd22015-11-11 13:43:58 +01001160 const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
Yann Collet1f44b3f2015-11-05 17:32:18 +01001161 U32* const bt = zc->contentTable;
1162 const U32 btLog = zc->params.contentLog - 1;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001163 const U32 btMask= (1 << btLog) - 1;
1164 U32 matchIndex = hashTable[h];
1165 size_t commonLengthSmaller=0, commonLengthLarger=0;
1166 const BYTE* const base = zc->base;
Yann Collet1358f912016-01-01 07:29:39 +01001167 const BYTE* const dictBase = zc->dictBase;
1168 const U32 dictLimit = zc->dictLimit;
1169 const BYTE* const dictEnd = dictBase + dictLimit;
1170 const BYTE* const prefixStart = base + dictLimit;
Yann Colletf48e35c2015-11-07 01:13:31 +01001171 const BYTE* match = base + matchIndex;
Yann Collet6c3e2e72015-12-11 10:44:07 +01001172 const U32 current = (U32)(ip-base);
Yann Collete9eba602015-11-08 15:08:03 +01001173 const U32 btLow = btMask >= current ? 0 : current - btMask;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001174 U32* smallerPtr = bt + 2*(current&btMask);
Yann Colleta87278a2016-01-17 00:12:55 +01001175 U32* largerPtr = smallerPtr + 1;
Yann Collet59d70632015-11-04 12:05:27 +01001176 U32 dummy32; /* to be nullified at the end */
Yann Collet03526e12015-11-23 15:29:15 +01001177 const U32 windowLow = zc->lowLimit;
Yann Collet72e84cf2015-12-31 19:08:44 +01001178 U32 matchEndIdx = current+8;
Yann Collet7beaa052016-01-21 11:57:45 +01001179 U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0);
1180 U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1);
1181 predictedSmall += (predictedSmall>0);
1182 predictedLarge += (predictedLarge>0);
Yann Colletf48e35c2015-11-07 01:13:31 +01001183
Yann Collet6c3e2e72015-12-11 10:44:07 +01001184 hashTable[h] = current; /* Update Hash Table */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001185
Yann Colletfb810d62016-01-28 00:18:06 +01001186 while (nbCompares-- && (matchIndex > windowLow)) {
Yann Collet96b9f0b2015-11-04 03:52:54 +01001187 U32* nextPtr = bt + 2*(matchIndex & btMask);
Yann Colleta87278a2016-01-17 00:12:55 +01001188 const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001189 size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
1190
Yann Colletfb810d62016-01-28 00:18:06 +01001191 if (matchIndex == predictedSmall) {
1192 /* no need to check length, result known */
Yann Colleta87278a2016-01-17 00:12:55 +01001193 *smallerPtr = matchIndex;
1194 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1195 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1196 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Collet7beaa052016-01-21 11:57:45 +01001197 predictedSmall = predictPtr[1] + (predictPtr[1]>0);
Yann Colleta87278a2016-01-17 00:12:55 +01001198 continue;
1199 }
1200
Yann Colletfb810d62016-01-28 00:18:06 +01001201 if (matchIndex == predictedLarge) {
Yann Colleta87278a2016-01-17 00:12:55 +01001202 *largerPtr = matchIndex;
1203 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1204 largerPtr = nextPtr;
1205 matchIndex = nextPtr[0];
Yann Collet7beaa052016-01-21 11:57:45 +01001206 predictedLarge = predictPtr[0] + (predictPtr[0]>0);
Yann Colleta87278a2016-01-17 00:12:55 +01001207 continue;
1208 }
1209
Yann Colletfb810d62016-01-28 00:18:06 +01001210 if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
Yann Collet1358f912016-01-01 07:29:39 +01001211 match = base + matchIndex;
1212 if (match[matchLength] == ip[matchLength])
1213 matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
Yann Colletfb810d62016-01-28 00:18:06 +01001214 } else {
Yann Collet1358f912016-01-01 07:29:39 +01001215 match = dictBase + matchIndex;
1216 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
1217 if (matchIndex+matchLength >= dictLimit)
1218 match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
1219 }
Yann Collet96b9f0b2015-11-04 03:52:54 +01001220
Yann Colletee3f4512015-12-29 22:26:09 +01001221 if (matchLength > matchEndIdx - matchIndex)
Yann Collet48da1642015-12-29 23:40:02 +01001222 matchEndIdx = matchIndex + (U32)matchLength;
Yann Colletee3f4512015-12-29 22:26:09 +01001223
Yann Collet59d70632015-11-04 12:05:27 +01001224 if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
Yann Collet1358f912016-01-01 07:29:39 +01001225 break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001226
Yann Colletfb810d62016-01-28 00:18:06 +01001227 if (match[matchLength] < ip[matchLength]) { /* necessarily within correct buffer */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001228 /* match is smaller than current */
1229 *smallerPtr = matchIndex; /* update smaller idx */
1230 commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
Yann Colletf48e35c2015-11-07 01:13:31 +01001231 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001232 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
Yann Colletf48e35c2015-11-07 01:13:31 +01001233 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Colletfb810d62016-01-28 00:18:06 +01001234 } else {
Yann Collet96b9f0b2015-11-04 03:52:54 +01001235 /* match is larger than current */
1236 *largerPtr = matchIndex;
1237 commonLengthLarger = matchLength;
Yann Colletf48e35c2015-11-07 01:13:31 +01001238 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
Yann Collet96b9f0b2015-11-04 03:52:54 +01001239 largerPtr = nextPtr;
Yann Colletf48e35c2015-11-07 01:13:31 +01001240 matchIndex = nextPtr[0];
Yann Colletfb810d62016-01-28 00:18:06 +01001241 } }
Yann Collet96b9f0b2015-11-04 03:52:54 +01001242
Yann Collet59d70632015-11-04 12:05:27 +01001243 *smallerPtr = *largerPtr = 0;
Yann Collet72e84cf2015-12-31 19:08:44 +01001244 return (matchEndIdx > current + 8) ? matchEndIdx - current - 8 : 1;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001245}
1246
1247
Yann Colletee3f4512015-12-29 22:26:09 +01001248static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
Yann Collet96b9f0b2015-11-04 03:52:54 +01001249{
1250 const BYTE* const base = zc->base;
1251 const U32 target = (U32)(ip - base);
1252 U32 idx = zc->nextToUpdate;
Yann Collet96b9f0b2015-11-04 03:52:54 +01001253
Yann Colletf48e35c2015-11-07 01:13:31 +01001254 for( ; idx < target ; )
Yann Collet1358f912016-01-01 07:29:39 +01001255 idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
Yann Collet96b9f0b2015-11-04 03:52:54 +01001256}
1257
Yann Collet96b9f0b2015-11-04 03:52:54 +01001258FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
Yann Collet2cc12cb2016-01-01 07:47:58 +01001259size_t ZSTD_insertBtAndFindBestMatch (
Yann Collet03526e12015-11-23 15:29:15 +01001260 ZSTD_CCtx* zc,
1261 const BYTE* const ip, const BYTE* const iend,
1262 size_t* offsetPtr,
Yann Collet2cc12cb2016-01-01 07:47:58 +01001263 U32 nbCompares, const U32 mls,
1264 U32 extDict)
Yann Collet03526e12015-11-23 15:29:15 +01001265{
1266 U32* const hashTable = zc->hashTable;
1267 const U32 hashLog = zc->params.hashLog;
1268 const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
1269 U32* const bt = zc->contentTable;
1270 const U32 btLog = zc->params.contentLog - 1;
1271 const U32 btMask= (1 << btLog) - 1;
1272 U32 matchIndex = hashTable[h];
1273 size_t commonLengthSmaller=0, commonLengthLarger=0;
1274 const BYTE* const base = zc->base;
1275 const BYTE* const dictBase = zc->dictBase;
1276 const U32 dictLimit = zc->dictLimit;
1277 const BYTE* const dictEnd = dictBase + dictLimit;
1278 const BYTE* const prefixStart = base + dictLimit;
1279 const U32 current = (U32)(ip-base);
1280 const U32 btLow = btMask >= current ? 0 : current - btMask;
1281 const U32 windowLow = zc->lowLimit;
1282 U32* smallerPtr = bt + 2*(current&btMask);
1283 U32* largerPtr = bt + 2*(current&btMask) + 1;
1284 size_t bestLength = 0;
Yann Collet72e84cf2015-12-31 19:08:44 +01001285 U32 matchEndIdx = current+8;
Yann Collet03526e12015-11-23 15:29:15 +01001286 U32 dummy32; /* to be nullified at the end */
1287
Yann Collet6c3e2e72015-12-11 10:44:07 +01001288 hashTable[h] = current; /* Update Hash Table */
Yann Collet03526e12015-11-23 15:29:15 +01001289
Yann Colletfb810d62016-01-28 00:18:06 +01001290 while (nbCompares-- && (matchIndex > windowLow)) {
Yann Collet03526e12015-11-23 15:29:15 +01001291 U32* nextPtr = bt + 2*(matchIndex & btMask);
1292 size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
1293 const BYTE* match;
1294
Yann Colletfb810d62016-01-28 00:18:06 +01001295 if ((!extDict) || (matchIndex+matchLength >= dictLimit)) {
Yann Collet03526e12015-11-23 15:29:15 +01001296 match = base + matchIndex;
1297 if (match[matchLength] == ip[matchLength])
1298 matchLength += ZSTD_count(ip+matchLength+1, match+matchLength+1, iend) +1;
Yann Colletfb810d62016-01-28 00:18:06 +01001299 } else {
Yann Collet03526e12015-11-23 15:29:15 +01001300 match = dictBase + matchIndex;
1301 matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);
Yann Collet225179d2015-11-23 16:52:22 +01001302 if (matchIndex+matchLength >= dictLimit)
1303 match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
Yann Collet03526e12015-11-23 15:29:15 +01001304 }
1305
Yann Colletfb810d62016-01-28 00:18:06 +01001306 if (matchLength > bestLength) {
Yann Colletee3f4512015-12-29 22:26:09 +01001307 if (matchLength > matchEndIdx - matchIndex)
Yann Collet48da1642015-12-29 23:40:02 +01001308 matchEndIdx = matchIndex + (U32)matchLength;
Yann Collet03526e12015-11-23 15:29:15 +01001309 if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit(current-matchIndex+1) - ZSTD_highbit((U32)offsetPtr[0]+1)) )
1310 bestLength = matchLength, *offsetPtr = current - matchIndex;
1311 if (ip+matchLength == iend) /* equal : no way to know if inf or sup */
1312 break; /* drop, to guarantee consistency (miss a little bit of compression) */
1313 }
1314
Yann Colletfb810d62016-01-28 00:18:06 +01001315 if (match[matchLength] < ip[matchLength]) {
Yann Collet03526e12015-11-23 15:29:15 +01001316 /* match is smaller than current */
1317 *smallerPtr = matchIndex; /* update smaller idx */
1318 commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
1319 if (matchIndex <= btLow) { smallerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1320 smallerPtr = nextPtr+1; /* new "smaller" => larger of match */
1321 matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */
Yann Colletfb810d62016-01-28 00:18:06 +01001322 } else {
Yann Collet03526e12015-11-23 15:29:15 +01001323 /* match is larger than current */
1324 *largerPtr = matchIndex;
1325 commonLengthLarger = matchLength;
1326 if (matchIndex <= btLow) { largerPtr=&dummy32; break; } /* beyond tree size, stop the search */
1327 largerPtr = nextPtr;
1328 matchIndex = nextPtr[0];
1329 }
1330 }
1331
1332 *smallerPtr = *largerPtr = 0;
1333
Yann Collet72e84cf2015-12-31 19:08:44 +01001334 zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current+1;
Yann Collet03526e12015-11-23 15:29:15 +01001335 return bestLength;
1336}
1337
Yann Collet2cc12cb2016-01-01 07:47:58 +01001338
1339/** Tree updater, providing best match */
1340FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
1341size_t ZSTD_BtFindBestMatch (
1342 ZSTD_CCtx* zc,
1343 const BYTE* const ip, const BYTE* const iLimit,
1344 size_t* offsetPtr,
1345 const U32 maxNbAttempts, const U32 mls)
1346{
1347 if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
1348 ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
1349 return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0);
1350}
1351
1352
1353FORCE_INLINE size_t ZSTD_BtFindBestMatch_selectMLS (
1354 ZSTD_CCtx* zc, /* Index table will be updated */
1355 const BYTE* ip, const BYTE* const iLimit,
1356 size_t* offsetPtr,
1357 const U32 maxNbAttempts, const U32 matchLengthSearch)
1358{
1359 switch(matchLengthSearch)
1360 {
1361 default :
1362 case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1363 case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1364 case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1365 }
1366}
1367
1368
1369static void ZSTD_updateTree_extDict(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* const iend, const U32 nbCompares, const U32 mls)
1370{
1371 const BYTE* const base = zc->base;
1372 const U32 target = (U32)(ip - base);
1373 U32 idx = zc->nextToUpdate;
1374
1375 for( ; idx < target ; )
1376 idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 1);
1377}
1378
1379
Yann Collet03526e12015-11-23 15:29:15 +01001380/** Tree updater, providing best match */
1381FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
1382size_t ZSTD_BtFindBestMatch_extDict (
1383 ZSTD_CCtx* zc,
1384 const BYTE* const ip, const BYTE* const iLimit,
1385 size_t* offsetPtr,
1386 const U32 maxNbAttempts, const U32 mls)
1387{
Yann Colletee3f4512015-12-29 22:26:09 +01001388 if (ip < zc->base + zc->nextToUpdate) return 0; /* skipped area */
1389 ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
Yann Collet2cc12cb2016-01-01 07:47:58 +01001390 return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1);
Yann Collet03526e12015-11-23 15:29:15 +01001391}
1392
1393
1394FORCE_INLINE size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
1395 ZSTD_CCtx* zc, /* Index table will be updated */
1396 const BYTE* ip, const BYTE* const iLimit,
1397 size_t* offsetPtr,
1398 const U32 maxNbAttempts, const U32 matchLengthSearch)
1399{
1400 switch(matchLengthSearch)
1401 {
1402 default :
1403 case 4 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
1404 case 5 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
1405 case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
1406 }
1407}
1408
1409
Yann Collet5106a762015-11-05 15:00:24 +01001410/* ***********************
1411* Hash Chain
1412*************************/
1413
Yann Collet1f44b3f2015-11-05 17:32:18 +01001414#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask]
1415
Yann Collet6bcdeac2015-11-26 11:43:00 +01001416/* Update chains up to ip (excluded)
Yann Collet06eade52015-11-23 14:23:47 +01001417 Assumption : always within prefix (ie. not within extDict) */
1418static U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
Yann Collet5106a762015-11-05 15:00:24 +01001419{
1420 U32* const hashTable = zc->hashTable;
1421 const U32 hashLog = zc->params.hashLog;
Yann Collet1f44b3f2015-11-05 17:32:18 +01001422 U32* const chainTable = zc->contentTable;
1423 const U32 chainMask = (1 << zc->params.contentLog) - 1;
Yann Collet5106a762015-11-05 15:00:24 +01001424 const BYTE* const base = zc->base;
1425 const U32 target = (U32)(ip - base);
1426 U32 idx = zc->nextToUpdate;
1427
Yann Colletfb810d62016-01-28 00:18:06 +01001428 while(idx < target) {
Yann Collet5be2dd22015-11-11 13:43:58 +01001429 size_t h = ZSTD_hashPtr(base+idx, hashLog, mls);
Yann Collet5106a762015-11-05 15:00:24 +01001430 NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
1431 hashTable[h] = idx;
1432 idx++;
1433 }
1434
1435 zc->nextToUpdate = target;
Yann Collet5be2dd22015-11-11 13:43:58 +01001436 return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];
Yann Collet5106a762015-11-05 15:00:24 +01001437}
1438
1439
1440FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */
Yann Colletc1e52f02015-11-23 14:37:59 +01001441size_t ZSTD_HcFindBestMatch_generic (
Yann Collet5be2dd22015-11-11 13:43:58 +01001442 ZSTD_CCtx* zc, /* Index table will be updated */
Yann Collet5106a762015-11-05 15:00:24 +01001443 const BYTE* const ip, const BYTE* const iLimit,
1444 size_t* offsetPtr,
Yann Colletc1e52f02015-11-23 14:37:59 +01001445 const U32 maxNbAttempts, const U32 mls, const U32 extDict)
Yann Collet287b7d92015-11-22 13:24:05 +01001446{
Yann Collet1f44b3f2015-11-05 17:32:18 +01001447 U32* const chainTable = zc->contentTable;
1448 const U32 chainSize = (1 << zc->params.contentLog);
Yann Collet5106a762015-11-05 15:00:24 +01001449 const U32 chainMask = chainSize-1;
1450 const BYTE* const base = zc->base;
1451 const BYTE* const dictBase = zc->dictBase;
1452 const U32 dictLimit = zc->dictLimit;
Yann Collet5054ee02015-11-23 13:34:21 +01001453 const BYTE* const prefixStart = base + dictLimit;
1454 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001455 const U32 lowLimit = zc->lowLimit;
Yann Collet9a24e592015-11-22 02:53:43 +01001456 const U32 current = (U32)(ip-base);
1457 const U32 minChain = current > chainSize ? current - chainSize : 0;
Yann Collet5106a762015-11-05 15:00:24 +01001458 U32 matchIndex;
1459 const BYTE* match;
1460 int nbAttempts=maxNbAttempts;
Yann Collet5054ee02015-11-23 13:34:21 +01001461 size_t ml=MINMATCH-1;
Yann Collet5106a762015-11-05 15:00:24 +01001462
1463 /* HC4 match finder */
Yann Colletc1e52f02015-11-23 14:37:59 +01001464 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
Yann Collet5106a762015-11-05 15:00:24 +01001465
Yann Colletfb810d62016-01-28 00:18:06 +01001466 while ((matchIndex>lowLimit) && (nbAttempts)) {
Yann Collet5054ee02015-11-23 13:34:21 +01001467 size_t currentMl=0;
Yann Collet5106a762015-11-05 15:00:24 +01001468 nbAttempts--;
Yann Colletfb810d62016-01-28 00:18:06 +01001469 if ((!extDict) || matchIndex >= dictLimit) {
Yann Collet5106a762015-11-05 15:00:24 +01001470 match = base + matchIndex;
Yann Collet4baee502015-11-09 03:19:33 +01001471 if (match[ml] == ip[ml]) /* potentially better */
Yann Collet5054ee02015-11-23 13:34:21 +01001472 currentMl = ZSTD_count(ip, match, iLimit);
Yann Colletfb810d62016-01-28 00:18:06 +01001473 } else {
Yann Collet5106a762015-11-05 15:00:24 +01001474 match = dictBase + matchIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001475 if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */
1476 currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
Yann Collet5106a762015-11-05 15:00:24 +01001477 }
1478
Yann Collet5054ee02015-11-23 13:34:21 +01001479 /* save best solution */
Yann Collet239cc282015-11-23 16:17:21 +01001480 if (currentMl > ml) { ml = currentMl; *offsetPtr = current - matchIndex; if (ip+currentMl == iLimit) break; /* best possible, and avoid read overflow*/ }
Yann Collet5054ee02015-11-23 13:34:21 +01001481
Yann Collet9a24e592015-11-22 02:53:43 +01001482 if (matchIndex <= minChain) break;
Yann Collet5106a762015-11-05 15:00:24 +01001483 matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
1484 }
1485
1486 return ml;
1487}
1488
1489
Yann Colletc1e52f02015-11-23 14:37:59 +01001490FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
1491 ZSTD_CCtx* zc,
Yann Collet5106a762015-11-05 15:00:24 +01001492 const BYTE* ip, const BYTE* const iLimit,
1493 size_t* offsetPtr,
1494 const U32 maxNbAttempts, const U32 matchLengthSearch)
1495{
1496 switch(matchLengthSearch)
1497 {
1498 default :
Yann Colletc1e52f02015-11-23 14:37:59 +01001499 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0);
1500 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0);
1501 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
1502 }
1503}
1504
1505
1506FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
1507 ZSTD_CCtx* zc,
1508 const BYTE* ip, const BYTE* const iLimit,
1509 size_t* offsetPtr,
1510 const U32 maxNbAttempts, const U32 matchLengthSearch)
1511{
1512 switch(matchLengthSearch)
1513 {
1514 default :
1515 case 4 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1);
1516 case 5 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1);
1517 case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
Yann Collet5106a762015-11-05 15:00:24 +01001518 }
1519}
1520
1521
Yann Collet287b7d92015-11-22 13:24:05 +01001522/* *******************************
Yann Collet9a24e592015-11-22 02:53:43 +01001523* Common parser - lazy strategy
Yann Collet287b7d92015-11-22 13:24:05 +01001524*********************************/
Yann Collet5106a762015-11-05 15:00:24 +01001525FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001526void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
1527 const void* src, size_t srcSize,
Yann Collet007c1c62015-11-22 02:42:28 +01001528 const U32 searchMethod, const U32 depth)
Yann Collet5106a762015-11-05 15:00:24 +01001529{
1530 seqStore_t* seqStorePtr = &(ctx->seqStore);
1531 const BYTE* const istart = (const BYTE*)src;
1532 const BYTE* ip = istart;
1533 const BYTE* anchor = istart;
1534 const BYTE* const iend = istart + srcSize;
1535 const BYTE* const ilimit = iend - 8;
Yann Collete47c4e52015-12-05 09:23:53 +01001536 const BYTE* const base = ctx->base + ctx->dictLimit;
Yann Collet5106a762015-11-05 15:00:24 +01001537
1538 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
1539 const U32 maxSearches = 1 << ctx->params.searchLog;
1540 const U32 mls = ctx->params.searchLength;
1541
Yann Collet5be2dd22015-11-11 13:43:58 +01001542 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
Yann Collet5106a762015-11-05 15:00:24 +01001543 size_t* offsetPtr,
1544 U32 maxNbAttempts, U32 matchLengthSearch);
Yann Collet5be2dd22015-11-11 13:43:58 +01001545 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS;
Yann Collet5106a762015-11-05 15:00:24 +01001546
1547 /* init */
1548 ZSTD_resetSeqStore(seqStorePtr);
Yann Collete47c4e52015-12-05 09:23:53 +01001549 if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE;
Yann Collet5106a762015-11-05 15:00:24 +01001550
1551 /* Match Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001552 while (ip < ilimit) {
Yann Collet7a231792015-11-21 15:27:35 +01001553 size_t matchLength=0;
1554 size_t offset=0;
1555 const BYTE* start=ip+1;
Yann Collet5106a762015-11-05 15:00:24 +01001556
Yann Collet743402c2015-11-20 12:03:53 +01001557 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001558 if (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1)) {
Yann Collet743402c2015-11-20 12:03:53 +01001559 /* repcode : we take it */
Yann Collet7a231792015-11-21 15:27:35 +01001560 matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend) + MINMATCH;
Yann Collet007c1c62015-11-22 02:42:28 +01001561 if (depth==0) goto _storeSequence;
Yann Collet5106a762015-11-05 15:00:24 +01001562 }
1563
Yann Colletfc2afcf2015-11-06 15:40:14 +01001564 {
Yann Collet239cc282015-11-23 16:17:21 +01001565 /* first search (depth 0) */
1566 size_t offsetFound = 99999999;
1567 size_t ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
1568 if (ml2 > matchLength)
1569 matchLength = ml2, start = ip, offset=offsetFound;
1570 }
Yann Collet9a24e592015-11-22 02:53:43 +01001571
Yann Colletfb810d62016-01-28 00:18:06 +01001572 if (matchLength < MINMATCH) {
Yann Collet239cc282015-11-23 16:17:21 +01001573 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1574 continue;
1575 }
Yann Collet5106a762015-11-05 15:00:24 +01001576
1577 /* let's try to find a better solution */
Yann Collet007c1c62015-11-22 02:42:28 +01001578 if (depth>=1)
Yann Colletfb810d62016-01-28 00:18:06 +01001579 while (ip<ilimit) {
Yann Collet5106a762015-11-05 15:00:24 +01001580 ip ++;
Yann Colletfb810d62016-01-28 00:18:06 +01001581 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
Yann Collet007c1c62015-11-22 02:42:28 +01001582 size_t mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
1583 int gain2 = (int)(mlRep * 3);
Yann Collet5106a762015-11-05 15:00:24 +01001584 int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
Yann Collet007c1c62015-11-22 02:42:28 +01001585 if ((mlRep >= MINMATCH) && (gain2 > gain1))
1586 matchLength = mlRep, offset = 0, start = ip;
Yann Collet5106a762015-11-05 15:00:24 +01001587 }
1588 {
1589 size_t offset2=999999;
1590 size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
Yann Collet007c1c62015-11-22 02:42:28 +01001591 int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1592 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
Yann Colletfb810d62016-01-28 00:18:06 +01001593 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet628065c2015-11-06 18:44:54 +01001594 matchLength = ml2, offset = offset2, start = ip;
Yann Collet5106a762015-11-05 15:00:24 +01001595 continue; /* search a better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001596 } }
Yann Collet5106a762015-11-05 15:00:24 +01001597
1598 /* let's find an even better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001599 if ((depth==2) && (ip<ilimit)) {
Yann Collet5106a762015-11-05 15:00:24 +01001600 ip ++;
Yann Colletfb810d62016-01-28 00:18:06 +01001601 if ((offset) && (MEM_read32(ip) == MEM_read32(ip - offset_1))) {
Yann Collet5106a762015-11-05 15:00:24 +01001602 size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_1, iend) + MINMATCH;
1603 int gain2 = (int)(ml2 * 4);
1604 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
Yann Collet4baee502015-11-09 03:19:33 +01001605 if ((ml2 >= MINMATCH) && (gain2 > gain1))
Yann Collet5106a762015-11-05 15:00:24 +01001606 matchLength = ml2, offset = 0, start = ip;
1607 }
1608 {
1609 size_t offset2=999999;
1610 size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
Yann Collet628065c2015-11-06 18:44:54 +01001611 int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1612 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
Yann Colletfb810d62016-01-28 00:18:06 +01001613 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet628065c2015-11-06 18:44:54 +01001614 matchLength = ml2, offset = offset2, start = ip;
1615 continue;
Yann Colletfb810d62016-01-28 00:18:06 +01001616 } } }
Yann Collet5106a762015-11-05 15:00:24 +01001617 break; /* nothing found : store previous solution */
1618 }
1619
Yann Collet4baee502015-11-09 03:19:33 +01001620 /* catch up */
Yann Colletfb810d62016-01-28 00:18:06 +01001621 if (offset) {
Yann Collete47c4e52015-12-05 09:23:53 +01001622 while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */
Yann Collet4baee502015-11-09 03:19:33 +01001623 { start--; matchLength++; }
Yann Collet743402c2015-11-20 12:03:53 +01001624 offset_2 = offset_1; offset_1 = offset;
Yann Collet4baee502015-11-09 03:19:33 +01001625 }
1626
1627 /* store sequence */
Yann Collet7a231792015-11-21 15:27:35 +01001628_storeSequence:
Yann Collet5106a762015-11-05 15:00:24 +01001629 {
1630 size_t litLength = start - anchor;
Yann Collet5106a762015-11-05 15:00:24 +01001631 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
Yann Collet4baee502015-11-09 03:19:33 +01001632 anchor = ip = start + matchLength;
Yann Collet5106a762015-11-05 15:00:24 +01001633 }
1634
Yann Collet743402c2015-11-20 12:03:53 +01001635 /* check immediate repcode */
1636 while ( (ip <= ilimit)
Yann Colletfb810d62016-01-28 00:18:06 +01001637 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
Yann Collet743402c2015-11-20 12:03:53 +01001638 /* store sequence */
1639 matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
1640 offset = offset_2;
1641 offset_2 = offset_1;
1642 offset_1 = offset;
1643 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength);
1644 ip += matchLength+MINMATCH;
1645 anchor = ip;
1646 continue; /* faster when present ... (?) */
Yann Colletfb810d62016-01-28 00:18:06 +01001647 } }
Yann Collet5106a762015-11-05 15:00:24 +01001648
1649 /* Last Literals */
1650 {
1651 size_t lastLLSize = iend - anchor;
1652 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1653 seqStorePtr->lit += lastLLSize;
1654 }
Yann Collet5106a762015-11-05 15:00:24 +01001655}
1656
Yann Collet59d1f792016-01-23 19:28:41 +01001657static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001658{
Yann Colleta1249dc2016-01-25 04:22:03 +01001659 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
Yann Collet5106a762015-11-05 15:00:24 +01001660}
1661
Yann Collet59d1f792016-01-23 19:28:41 +01001662static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001663{
Yann Colleta1249dc2016-01-25 04:22:03 +01001664 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
Yann Collet5106a762015-11-05 15:00:24 +01001665}
1666
Yann Collet59d1f792016-01-23 19:28:41 +01001667static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5106a762015-11-05 15:00:24 +01001668{
Yann Colleta1249dc2016-01-25 04:22:03 +01001669 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
Yann Collet5106a762015-11-05 15:00:24 +01001670}
1671
Yann Collet59d1f792016-01-23 19:28:41 +01001672static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colletf3eca252015-10-22 15:31:46 +01001673{
Yann Colleta1249dc2016-01-25 04:22:03 +01001674 ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
Yann Colletbe2010e2015-10-31 12:57:14 +01001675}
1676
1677
Yann Collet9a24e592015-11-22 02:53:43 +01001678FORCE_INLINE
Yann Collet59d1f792016-01-23 19:28:41 +01001679void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
1680 const void* src, size_t srcSize,
Yann Collet9a24e592015-11-22 02:53:43 +01001681 const U32 searchMethod, const U32 depth)
1682{
1683 seqStore_t* seqStorePtr = &(ctx->seqStore);
1684 const BYTE* const istart = (const BYTE*)src;
1685 const BYTE* ip = istart;
1686 const BYTE* anchor = istart;
1687 const BYTE* const iend = istart + srcSize;
1688 const BYTE* const ilimit = iend - 8;
1689 const BYTE* const base = ctx->base;
1690 const U32 dictLimit = ctx->dictLimit;
1691 const BYTE* const prefixStart = base + dictLimit;
1692 const BYTE* const dictBase = ctx->dictBase;
1693 const BYTE* const dictEnd = dictBase + dictLimit;
Yann Colletc3652152015-11-24 14:06:07 +01001694 const BYTE* const dictStart = dictBase + ctx->lowLimit;
Yann Collet9a24e592015-11-22 02:53:43 +01001695
1696 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
1697 const U32 maxSearches = 1 << ctx->params.searchLog;
1698 const U32 mls = ctx->params.searchLength;
1699
1700 typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
1701 size_t* offsetPtr,
1702 U32 maxNbAttempts, U32 matchLengthSearch);
Yann Collet03526e12015-11-23 15:29:15 +01001703 searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS;
Yann Collet9a24e592015-11-22 02:53:43 +01001704
1705 /* init */
1706 ZSTD_resetSeqStore(seqStorePtr);
Yann Collet6c3e2e72015-12-11 10:44:07 +01001707 if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
Yann Collet9a24e592015-11-22 02:53:43 +01001708
1709 /* Match Loop */
Yann Colletfb810d62016-01-28 00:18:06 +01001710 while (ip < ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001711 size_t matchLength=0;
1712 size_t offset=0;
1713 const BYTE* start=ip+1;
1714 U32 current = (U32)(ip-base);
1715
1716 /* check repCode */
1717 {
1718 const U32 repIndex = (U32)(current+1 - offset_1);
1719 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1720 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001721 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001722 if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001723 /* repcode detected we should take it */
1724 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001725 matchLength = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
Yann Collet9a24e592015-11-22 02:53:43 +01001726 if (depth==0) goto _storeSequence;
Yann Colletfb810d62016-01-28 00:18:06 +01001727 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001728
1729 {
Yann Collet239cc282015-11-23 16:17:21 +01001730 /* first search (depth 0) */
1731 size_t offsetFound = 99999999;
1732 size_t ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
1733 if (ml2 > matchLength)
1734 matchLength = ml2, start = ip, offset=offsetFound;
1735 }
Yann Collet9a24e592015-11-22 02:53:43 +01001736
Yann Colletfb810d62016-01-28 00:18:06 +01001737 if (matchLength < MINMATCH) {
Yann Collet239cc282015-11-23 16:17:21 +01001738 ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
1739 continue;
1740 }
Yann Collet9a24e592015-11-22 02:53:43 +01001741
1742 /* let's try to find a better solution */
1743 if (depth>=1)
Yann Colletfb810d62016-01-28 00:18:06 +01001744 while (ip<ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001745 ip ++;
1746 current++;
1747 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001748 if (offset) {
Yann Collet9a24e592015-11-22 02:53:43 +01001749 const U32 repIndex = (U32)(current - offset_1);
1750 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1751 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001752 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001753 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001754 /* repcode detected */
Yann Collet9a24e592015-11-22 02:53:43 +01001755 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001756 size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1757 int gain2 = (int)(repLength * 3);
1758 int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
1759 if ((repLength >= MINMATCH) && (gain2 > gain1))
1760 matchLength = repLength, offset = 0, start = ip;
Yann Colletfb810d62016-01-28 00:18:06 +01001761 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001762
1763 /* search match, depth 1 */
1764 {
1765 size_t offset2=999999;
1766 size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1767 int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1768 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
Yann Colletfb810d62016-01-28 00:18:06 +01001769 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001770 matchLength = ml2, offset = offset2, start = ip;
1771 continue; /* search a better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001772 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001773
1774 /* let's find an even better one */
Yann Colletfb810d62016-01-28 00:18:06 +01001775 if ((depth==2) && (ip<ilimit)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001776 ip ++;
1777 current++;
1778 /* check repCode */
Yann Colletfb810d62016-01-28 00:18:06 +01001779 if (offset) {
Yann Collet9a24e592015-11-22 02:53:43 +01001780 const U32 repIndex = (U32)(current - offset_1);
1781 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1782 const BYTE* const repMatch = repBase + repIndex;
Yann Collet5054ee02015-11-23 13:34:21 +01001783 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001784 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001785 /* repcode detected */
Yann Collet9a24e592015-11-22 02:53:43 +01001786 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001787 size_t repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1788 int gain2 = (int)(repLength * 4);
1789 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1);
1790 if ((repLength >= MINMATCH) && (gain2 > gain1))
1791 matchLength = repLength, offset = 0, start = ip;
Yann Colletfb810d62016-01-28 00:18:06 +01001792 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001793
1794 /* search match, depth 2 */
1795 {
1796 size_t offset2=999999;
1797 size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
1798 int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
1799 int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
Yann Colletfb810d62016-01-28 00:18:06 +01001800 if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001801 matchLength = ml2, offset = offset2, start = ip;
1802 continue;
Yann Colletfb810d62016-01-28 00:18:06 +01001803 } } }
Yann Collet9a24e592015-11-22 02:53:43 +01001804 break; /* nothing found : store previous solution */
1805 }
1806
1807 /* catch up */
Yann Colletfb810d62016-01-28 00:18:06 +01001808 if (offset) {
Yann Colletc3652152015-11-24 14:06:07 +01001809 U32 matchIndex = (U32)((start-base) - offset);
1810 const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
1811 const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
1812 while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
Yann Collet9a24e592015-11-22 02:53:43 +01001813 offset_2 = offset_1; offset_1 = offset;
1814 }
1815
1816 /* store sequence */
1817_storeSequence:
1818 {
1819 size_t litLength = start - anchor;
1820 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
1821 anchor = ip = start + matchLength;
1822 }
1823
1824 /* check immediate repcode */
Yann Colletfb810d62016-01-28 00:18:06 +01001825 while (ip <= ilimit) {
Yann Collet9a24e592015-11-22 02:53:43 +01001826 const U32 repIndex = (U32)((ip-base) - offset_2);
1827 const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
1828 const BYTE* const repMatch = repBase + repIndex;
Yann Collet239cc282015-11-23 16:17:21 +01001829 if ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
Yann Colletfb810d62016-01-28 00:18:06 +01001830 if (MEM_read32(ip) == MEM_read32(repMatch)) {
Yann Collet9a24e592015-11-22 02:53:43 +01001831 /* repcode detected we should take it */
1832 const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
Yann Collet5054ee02015-11-23 13:34:21 +01001833 matchLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
1834 offset = offset_2; offset_2 = offset_1; offset_1 = offset; /* swap offset history */
Yann Collet9a24e592015-11-22 02:53:43 +01001835 ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
1836 ip += matchLength;
1837 anchor = ip;
1838 continue; /* faster when present ... (?) */
1839 }
1840 break;
Yann Colletfb810d62016-01-28 00:18:06 +01001841 } }
Yann Collet9a24e592015-11-22 02:53:43 +01001842
1843 /* Last Literals */
1844 {
1845 size_t lastLLSize = iend - anchor;
1846 memcpy(seqStorePtr->lit, anchor, lastLLSize);
1847 seqStorePtr->lit += lastLLSize;
1848 }
Yann Collet9a24e592015-11-22 02:53:43 +01001849}
1850
Yann Collet59d1f792016-01-23 19:28:41 +01001851void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet9a24e592015-11-22 02:53:43 +01001852{
Yann Colleta1249dc2016-01-25 04:22:03 +01001853 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
Yann Collet9a24e592015-11-22 02:53:43 +01001854}
1855
Yann Collet59d1f792016-01-23 19:28:41 +01001856static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colletb7fc88e2015-11-22 03:12:28 +01001857{
Yann Colleta1249dc2016-01-25 04:22:03 +01001858 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
Yann Colletb7fc88e2015-11-22 03:12:28 +01001859}
Yann Collet9a24e592015-11-22 02:53:43 +01001860
Yann Collet59d1f792016-01-23 19:28:41 +01001861static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Colleta85c77b2015-11-22 12:22:04 +01001862{
Yann Colleta1249dc2016-01-25 04:22:03 +01001863 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
Yann Colleta85c77b2015-11-22 12:22:04 +01001864}
1865
Yann Collet59d1f792016-01-23 19:28:41 +01001866static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
Yann Collet5054ee02015-11-23 13:34:21 +01001867{
Yann Colleta1249dc2016-01-25 04:22:03 +01001868 ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
Yann Collet5054ee02015-11-23 13:34:21 +01001869}
1870
Yann Collet7a231792015-11-21 15:27:35 +01001871
Yann Collet59d1f792016-01-23 19:28:41 +01001872typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
Yann Collet59d70632015-11-04 12:05:27 +01001873
Yann Colletb923f652016-01-26 03:14:20 +01001874static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
Yann Collet59d70632015-11-04 12:05:27 +01001875{
Yann Collet7fe531e2015-11-29 02:38:09 +01001876 static const ZSTD_blockCompressor blockCompressor[2][5] = {
1877 { ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy,ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2 },
1878 { ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict }
1879 };
1880
1881 return blockCompressor[extDict][(U32)strat];
Yann Collet59d70632015-11-04 12:05:27 +01001882}
1883
1884
Yann Colletbf42c8e2016-01-09 01:08:23 +01001885static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Colletbe2010e2015-10-31 12:57:14 +01001886{
Yann Collet03526e12015-11-23 15:29:15 +01001887 ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.strategy, zc->lowLimit < zc->dictLimit);
Yann Collet523b5942016-01-09 02:10:40 +01001888 if (srcSize < MIN_CBLOCK_SIZE+3) return 0; /* don't even attempt compression below a certain srcSize */
Yann Collet59d1f792016-01-23 19:28:41 +01001889 blockCompressor(zc, src, srcSize);
Yann Colletb923f652016-01-26 03:14:20 +01001890 return ZSTD_compressSequences(zc, dst, maxDstSize, srcSize);
Yann Colletbe2010e2015-10-31 12:57:14 +01001891}
1892
1893
Yann Collet5be2dd22015-11-11 13:43:58 +01001894static size_t ZSTD_compress_generic (ZSTD_CCtx* ctxPtr,
Yann Colletf3eca252015-10-22 15:31:46 +01001895 void* dst, size_t maxDstSize,
1896 const void* src, size_t srcSize)
1897{
Yann Collet120230b2015-12-02 14:00:45 +01001898 size_t blockSize = ctxPtr->blockSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001899 size_t remaining = srcSize;
1900 const BYTE* ip = (const BYTE*)src;
1901 BYTE* const ostart = (BYTE*)dst;
1902 BYTE* op = ostart;
Yann Collet89db5e02015-11-13 11:27:46 +01001903 const U32 maxDist = 1 << ctxPtr->params.windowLog;
Yann Collet9b11b462015-11-01 12:40:22 +01001904
Yann Collet3e358272015-11-04 18:19:39 +01001905 while (remaining)
Yann Colletf3eca252015-10-22 15:31:46 +01001906 {
Yann Collet3e358272015-11-04 18:19:39 +01001907 size_t cSize;
1908
Yann Collet3137d1a2015-11-04 23:36:36 +01001909 if (maxDstSize < 3 + MIN_CBLOCK_SIZE) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
Yann Collet3e358272015-11-04 18:19:39 +01001910 if (remaining < blockSize) blockSize = remaining;
Yann Collet89db5e02015-11-13 11:27:46 +01001911
1912 if ((U32)(ip+blockSize - (ctxPtr->base + ctxPtr->lowLimit)) > maxDist)
Yann Colletc3652152015-11-24 14:06:07 +01001913 {
Yann Collet89db5e02015-11-13 11:27:46 +01001914 /* respect windowLog contract */
Yann Colletc3652152015-11-24 14:06:07 +01001915 ctxPtr->lowLimit = (U32)(ip+blockSize - ctxPtr->base) - maxDist;
1916 if (ctxPtr->dictLimit < ctxPtr->lowLimit) ctxPtr->dictLimit = ctxPtr->lowLimit;
1917 }
Yann Collet89db5e02015-11-13 11:27:46 +01001918
Yann Colletbf42c8e2016-01-09 01:08:23 +01001919 cSize = ZSTD_compressBlock_internal(ctxPtr, op+3, maxDstSize-3, ip, blockSize);
Yann Collet3e358272015-11-04 18:19:39 +01001920 if (ZSTD_isError(cSize)) return cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001921
1922 if (cSize == 0)
1923 {
1924 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */
Yann Collet523b5942016-01-09 02:10:40 +01001925 if (ZSTD_isError(cSize)) return cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001926 }
1927 else
1928 {
1929 op[0] = (BYTE)(cSize>>16);
1930 op[1] = (BYTE)(cSize>>8);
1931 op[2] = (BYTE)cSize;
Yann Colletc95f8992015-11-19 17:28:35 +01001932 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
Yann Colletf3eca252015-10-22 15:31:46 +01001933 cSize += 3;
1934 }
1935
1936 remaining -= blockSize;
Yann Collet3e358272015-11-04 18:19:39 +01001937 maxDstSize -= cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001938 ip += blockSize;
1939 op += cSize;
Yann Colletf3eca252015-10-22 15:31:46 +01001940 }
1941
1942 return op-ostart;
1943}
1944
1945
Yann Colletbf42c8e2016-01-09 01:08:23 +01001946static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
1947 void* dst, size_t dstSize,
1948 const void* src, size_t srcSize,
1949 U32 frame)
Yann Colletf3eca252015-10-22 15:31:46 +01001950{
Yann Collet2acb5d32015-10-29 16:49:43 +01001951 const BYTE* const ip = (const BYTE*) src;
Yann Colletecd651b2016-01-07 15:35:18 +01001952 size_t hbSize = 0;
1953
Yann Colletbf42c8e2016-01-09 01:08:23 +01001954 if (frame && (zc->stage==0))
Yann Colletecd651b2016-01-07 15:35:18 +01001955 {
1956 hbSize = zc->hbSize;
1957 if (dstSize <= hbSize) return ERROR(dstSize_tooSmall);
1958 zc->stage = 1;
1959 memcpy(dst, zc->headerBuffer, hbSize);
1960 dstSize -= hbSize;
1961 dst = (char*)dst + hbSize;
1962 }
Yann Colletf3eca252015-10-22 15:31:46 +01001963
Yann Collet417890c2015-12-04 17:16:37 +01001964 /* Check if blocks follow each other */
1965 if (src != zc->nextSrc)
1966 {
1967 /* not contiguous */
1968 size_t delta = zc->nextSrc - ip;
1969 zc->lowLimit = zc->dictLimit;
1970 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
1971 zc->dictBase = zc->base;
Yann Collet417890c2015-12-04 17:16:37 +01001972 zc->base -= delta;
1973 zc->nextToUpdate = zc->dictLimit;
Yann Collete47c4e52015-12-05 09:23:53 +01001974 if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */
Yann Collet417890c2015-12-04 17:16:37 +01001975 }
1976
Yann Collet89db5e02015-11-13 11:27:46 +01001977 /* preemptive overflow correction */
Yann Collet6c3e2e72015-12-11 10:44:07 +01001978 if (zc->lowLimit > (1<<30))
Yann Colletf3eca252015-10-22 15:31:46 +01001979 {
inikepc71568f2016-01-30 12:15:56 +01001980 U32 btplus = (zc->params.strategy == ZSTD_btlazy2) || (zc->params.strategy == ZSTD_opt_bt);
Yann Collet6c3e2e72015-12-11 10:44:07 +01001981 U32 contentMask = (1 << (zc->params.contentLog - btplus)) - 1;
1982 U32 newLowLimit = zc->lowLimit & contentMask; /* preserve position % contentSize */
1983 U32 correction = zc->lowLimit - newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01001984 ZSTD_reduceIndex(zc, correction);
1985 zc->base += correction;
1986 zc->dictBase += correction;
Yann Collet6c3e2e72015-12-11 10:44:07 +01001987 zc->lowLimit = newLowLimit;
Yann Colletc3652152015-11-24 14:06:07 +01001988 zc->dictLimit -= correction;
1989 if (zc->nextToUpdate < correction) zc->nextToUpdate = 0;
1990 else zc->nextToUpdate -= correction;
Yann Colletf3eca252015-10-22 15:31:46 +01001991 }
1992
Yann Colletbf42c8e2016-01-09 01:08:23 +01001993 /* if input and dictionary overlap : reduce dictionary (presumed modified by input) */
Yann Colletc3652152015-11-24 14:06:07 +01001994 if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit))
Yann Collet89db5e02015-11-13 11:27:46 +01001995 {
Yann Colletc3652152015-11-24 14:06:07 +01001996 zc->lowLimit = (U32)(ip + srcSize - zc->dictBase);
1997 if (zc->lowLimit > zc->dictLimit) zc->lowLimit = zc->dictLimit;
Yann Collet89db5e02015-11-13 11:27:46 +01001998 }
1999
Yann Colletc3652152015-11-24 14:06:07 +01002000 zc->nextSrc = ip + srcSize;
Yann Colletecd651b2016-01-07 15:35:18 +01002001 {
Yann Colletbf42c8e2016-01-09 01:08:23 +01002002 size_t cSize;
2003 if (frame) cSize = ZSTD_compress_generic (zc, dst, dstSize, src, srcSize);
2004 else cSize = ZSTD_compressBlock_internal (zc, dst, dstSize, src, srcSize);
Yann Colletecd651b2016-01-07 15:35:18 +01002005 if (ZSTD_isError(cSize)) return cSize;
2006 return cSize + hbSize;
2007 }
Yann Colletf3eca252015-10-22 15:31:46 +01002008}
2009
Yann Colletbf42c8e2016-01-09 01:08:23 +01002010
2011size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
2012 void* dst, size_t dstSize,
2013 const void* src, size_t srcSize)
2014{
2015 return ZSTD_compressContinue_internal(zc, dst, dstSize, src, srcSize, 1);
2016}
2017
2018
2019size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
2020{
2021 if (srcSize > BLOCKSIZE) return ERROR(srcSize_wrong);
Yann Colletbf42c8e2016-01-09 01:08:23 +01002022 return ZSTD_compressContinue_internal(zc, dst, maxDstSize, src, srcSize, 0);
2023}
2024
2025
Yann Colletb923f652016-01-26 03:14:20 +01002026static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
Yann Collet417890c2015-12-04 17:16:37 +01002027{
2028 const BYTE* const ip = (const BYTE*) src;
2029 const BYTE* const iend = ip + srcSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002030
Yann Collet417890c2015-12-04 17:16:37 +01002031 /* input becomes current prefix */
2032 zc->lowLimit = zc->dictLimit;
2033 zc->dictLimit = (U32)(zc->nextSrc - zc->base);
2034 zc->dictBase = zc->base;
2035 zc->base += ip - zc->nextSrc;
2036 zc->nextToUpdate = zc->dictLimit;
2037
2038 zc->nextSrc = iend;
2039 if (srcSize <= 8) return 0;
2040
2041 switch(zc->params.strategy)
2042 {
2043 case ZSTD_fast:
2044 ZSTD_fillHashTable (zc, iend-8, zc->params.searchLength);
2045 break;
2046
2047 case ZSTD_greedy:
2048 case ZSTD_lazy:
2049 case ZSTD_lazy2:
2050 ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength);
2051 break;
2052
2053 case ZSTD_btlazy2:
2054 ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.searchLog, zc->params.searchLength);
Yann Collet48da1642015-12-29 23:40:02 +01002055 zc->nextToUpdate = (U32)(iend - zc->base);
Yann Collet417890c2015-12-04 17:16:37 +01002056 break;
2057
2058 default:
2059 return ERROR(GENERIC); /* strategy doesn't exist; impossible */
2060 }
2061
2062 return 0;
2063}
2064
2065
Yann Colletb923f652016-01-26 03:14:20 +01002066/* Dictionary format :
2067 Magic == ZSTD_DICT_MAGIC (4 bytes)
2068 Huff0 CTable (256 * 4 bytes) => to be changed to read from writeCTable
2069 Dictionary content
2070*/
2071/*! ZSTD_loadDictEntropyStats
2072 @return : size read from dictionary */
2073static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
2074{
2075 /* note : magic number already checked */
Yann Colletfb810d62016-01-28 00:18:06 +01002076 size_t offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize, errorCode;
2077 short offcodeNCount[MaxOff+1];
2078 unsigned offcodeMaxValue = MaxOff, offcodeLog = OffFSELog;
2079 short matchlengthNCount[MaxML+1];
2080 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
2081 short litlengthNCount[MaxLL+1];
2082 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
2083
Yann Colletb923f652016-01-26 03:14:20 +01002084 const size_t hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
2085 if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01002086 zc->flagStaticTables = 1;
2087 dict = (const char*)dict + hufHeaderSize;
2088 dictSize -= hufHeaderSize;
2089
2090 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
2091 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
2092 errorCode = FSE_buildCTable(zc->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog);
2093 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2094 dict = (const char*)dict + offcodeHeaderSize;
2095 dictSize -= offcodeHeaderSize;
2096
2097 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
2098 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
2099 errorCode = FSE_buildCTable(zc->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
2100 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2101 dict = (const char*)dict + matchlengthHeaderSize;
2102 dictSize -= matchlengthHeaderSize;
2103
2104 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
2105 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
2106 errorCode = FSE_buildCTable(zc->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog);
2107 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
2108
2109 return hufHeaderSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01002110}
2111
Yann Colletfb810d62016-01-28 00:18:06 +01002112
Yann Collet1c8e1942016-01-26 16:31:22 +01002113static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01002114{
Yann Collet7b51a292016-01-26 15:58:49 +01002115 if (dict && dictSize)
2116 {
2117 U32 magic = MEM_readLE32(dict);
2118 size_t eSize;
2119 if (magic != ZSTD_DICT_MAGIC)
2120 return ZSTD_loadDictionaryContent(zc, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01002121
Yann Collet7b51a292016-01-26 15:58:49 +01002122 eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+4, dictSize-4) + 4;
2123 if (ZSTD_isError(eSize)) return eSize;
2124 return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
2125 }
Yann Colletecd651b2016-01-07 15:35:18 +01002126 return 0;
2127}
2128
2129
Yann Collet417890c2015-12-04 17:16:37 +01002130/*! ZSTD_compressBegin_advanced
Yann Colletecd651b2016-01-07 15:35:18 +01002131* @return : 0, or an error code */
Yann Collet1c8e1942016-01-26 16:31:22 +01002132size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
2133 const void* dict, size_t dictSize,
Yann Collet88fcd292015-11-25 14:42:45 +01002134 ZSTD_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +01002135{
Yann Collet4114f952015-10-30 06:40:22 +01002136 size_t errorCode;
Yann Collet88fcd292015-11-25 14:42:45 +01002137
2138 ZSTD_validateParams(&params);
2139
Yann Collet1c8e1942016-01-26 16:31:22 +01002140 errorCode = ZSTD_resetCCtx_advanced(zc, params);
Yann Collet4114f952015-10-30 06:40:22 +01002141 if (ZSTD_isError(errorCode)) return errorCode;
Yann Collet89db5e02015-11-13 11:27:46 +01002142
Yann Collet1c8e1942016-01-26 16:31:22 +01002143 MEM_writeLE32(zc->headerBuffer, ZSTD_MAGICNUMBER); /* Write Header */
2144 ((BYTE*)zc->headerBuffer)[4] = (BYTE)(params.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN);
2145 zc->hbSize = ZSTD_frameHeaderSize_min;
2146 zc->stage = 0;
Yann Colletecd651b2016-01-07 15:35:18 +01002147
Yann Collet1c8e1942016-01-26 16:31:22 +01002148 return ZSTD_compress_insertDictionary(zc, dict, dictSize);
Yann Collet88fcd292015-11-25 14:42:45 +01002149}
2150
2151
Yann Collet1c8e1942016-01-26 16:31:22 +01002152size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel)
Yann Colletb923f652016-01-26 03:14:20 +01002153{
Yann Collet1c8e1942016-01-26 16:31:22 +01002154 return ZSTD_compressBegin_advanced(zc, dict, dictSize, ZSTD_getParams(compressionLevel, 0));
2155}
Yann Collet083fcc82015-10-25 14:06:35 +01002156
Yann Collet1c8e1942016-01-26 16:31:22 +01002157size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
Yann Collet083fcc82015-10-25 14:06:35 +01002158{
Yann Collet1c8e1942016-01-26 16:31:22 +01002159 return ZSTD_compressBegin_advanced(zc, NULL, 0, ZSTD_getParams(compressionLevel, 0));
Yann Collet083fcc82015-10-25 14:06:35 +01002160}
2161
2162
Yann Collet31683c02015-12-18 01:26:48 +01002163/*! ZSTD_compressEnd
Yann Collet88fcd292015-11-25 14:42:45 +01002164* Write frame epilogue
2165* @return : nb of bytes written into dst (or an error code) */
Yann Colletecd651b2016-01-07 15:35:18 +01002166size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t maxDstSize)
Yann Collet2acb5d32015-10-29 16:49:43 +01002167{
2168 BYTE* op = (BYTE*)dst;
Yann Colletecd651b2016-01-07 15:35:18 +01002169 size_t hbSize = 0;
Yann Collet2acb5d32015-10-29 16:49:43 +01002170
Yann Colletecd651b2016-01-07 15:35:18 +01002171 /* empty frame */
Yann Colletfb810d62016-01-28 00:18:06 +01002172 if (zc->stage==0) {
Yann Colletecd651b2016-01-07 15:35:18 +01002173 hbSize = zc->hbSize;
2174 if (maxDstSize <= hbSize) return ERROR(dstSize_tooSmall);
2175 zc->stage = 1;
2176 memcpy(dst, zc->headerBuffer, hbSize);
2177 maxDstSize -= hbSize;
2178 op += hbSize;
2179 }
2180
2181 /* frame epilogue */
Yann Collet2acb5d32015-10-29 16:49:43 +01002182 if (maxDstSize < 3) return ERROR(dstSize_tooSmall);
Yann Collet2acb5d32015-10-29 16:49:43 +01002183 op[0] = (BYTE)(bt_end << 6);
2184 op[1] = 0;
2185 op[2] = 0;
2186
Yann Colletecd651b2016-01-07 15:35:18 +01002187 return 3+hbSize;
Yann Collet2acb5d32015-10-29 16:49:43 +01002188}
2189
Yann Colletfd416f12016-01-30 03:14:15 +01002190
2191size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx,
2192 void* dst, size_t maxDstSize,
2193 const void* src, size_t srcSize)
2194{
2195 size_t outSize;
2196 size_t errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
2197 if (ZSTD_isError(errorCode)) return errorCode;
2198 errorCode = ZSTD_compressContinue(cctx, dst, maxDstSize, src, srcSize);
2199 if (ZSTD_isError(errorCode)) return errorCode;
2200 outSize = errorCode;
2201 errorCode = ZSTD_compressEnd(cctx, (char*)dst+outSize, maxDstSize-outSize);
2202 if (ZSTD_isError(errorCode)) return errorCode;
2203 outSize += errorCode;
2204 return outSize;
2205}
2206
2207
Yann Collet5be2dd22015-11-11 13:43:58 +01002208size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
Yann Collet88fcd292015-11-25 14:42:45 +01002209 void* dst, size_t maxDstSize,
2210 const void* src, size_t srcSize,
Yann Collet31683c02015-12-18 01:26:48 +01002211 const void* dict,size_t dictSize,
Yann Collet88fcd292015-11-25 14:42:45 +01002212 ZSTD_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +01002213{
2214 BYTE* const ostart = (BYTE*)dst;
2215 BYTE* op = ostart;
Yann Collet4114f952015-10-30 06:40:22 +01002216 size_t oSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002217
Yann Collet1c8e1942016-01-26 16:31:22 +01002218 /* Init */
2219 oSize = ZSTD_compressBegin_advanced(ctx, dict, dictSize, params);
Yann Colletf3eca252015-10-22 15:31:46 +01002220 if(ZSTD_isError(oSize)) return oSize;
Yann Colletf3eca252015-10-22 15:31:46 +01002221
2222 /* body (compression) */
Yann Collet31683c02015-12-18 01:26:48 +01002223 oSize = ZSTD_compressContinue (ctx, op, maxDstSize, src, srcSize);
Yann Colletf3eca252015-10-22 15:31:46 +01002224 if(ZSTD_isError(oSize)) return oSize;
2225 op += oSize;
2226 maxDstSize -= oSize;
2227
2228 /* Close frame */
Yann Collet5be2dd22015-11-11 13:43:58 +01002229 oSize = ZSTD_compressEnd(ctx, op, maxDstSize);
Yann Colletf3eca252015-10-22 15:31:46 +01002230 if(ZSTD_isError(oSize)) return oSize;
2231 op += oSize;
2232
2233 return (op - ostart);
2234}
2235
Yann Collet31683c02015-12-18 01:26:48 +01002236size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
2237{
2238 return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, dict, dictSize, ZSTD_getParams(compressionLevel, srcSize+dictSize));
2239}
2240
Yann Collet5be2dd22015-11-11 13:43:58 +01002241size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel)
Yann Collet083fcc82015-10-25 14:06:35 +01002242{
Yann Collet31683c02015-12-18 01:26:48 +01002243 return ZSTD_compress_advanced(ctx, dst, maxDstSize, src, srcSize, NULL, 0, ZSTD_getParams(compressionLevel, srcSize));
Yann Collet083fcc82015-10-25 14:06:35 +01002244}
2245
Yann Collet5be2dd22015-11-11 13:43:58 +01002246size_t ZSTD_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSize, int compressionLevel)
Yann Colletf3eca252015-10-22 15:31:46 +01002247{
Yann Collet44fe9912015-10-29 22:02:40 +01002248 size_t result;
Yann Collet5be2dd22015-11-11 13:43:58 +01002249 ZSTD_CCtx ctxBody;
Yann Collet712def92015-10-29 18:41:45 +01002250 memset(&ctxBody, 0, sizeof(ctxBody));
Yann Collet5be2dd22015-11-11 13:43:58 +01002251 result = ZSTD_compressCCtx(&ctxBody, dst, maxDstSize, src, srcSize, compressionLevel);
Yann Colletecd651b2016-01-07 15:35:18 +01002252 free(ctxBody.workSpace); /* can't free ctxBody, since it's on stack; just free heap content */
Yann Collet44fe9912015-10-29 22:02:40 +01002253 return result;
Yann Colletf3eca252015-10-22 15:31:46 +01002254}
Yann Colletfdcad6d2015-12-17 23:50:15 +01002255
Yann Colletfd416f12016-01-30 03:14:15 +01002256
2257/*- Pre-defined compression levels -*/
2258
2259static const ZSTD_parameters ZSTD_defaultParameters[4][ZSTD_MAX_CLEVEL+1] = {
2260{ /* "default" */
2261 /* W, C, H, S, L, strat */
2262 { 0, 18, 12, 12, 1, 4, ZSTD_fast }, /* level 0 - never used */
2263 { 0, 19, 13, 14, 1, 7, ZSTD_fast }, /* level 1 */
2264 { 0, 19, 15, 16, 1, 6, ZSTD_fast }, /* level 2 */
2265 { 0, 20, 18, 20, 1, 6, ZSTD_fast }, /* level 3 */
2266 { 0, 21, 19, 21, 1, 6, ZSTD_fast }, /* level 4 */
2267 { 0, 20, 14, 18, 3, 5, ZSTD_greedy }, /* level 5 */
2268 { 0, 20, 18, 19, 3, 5, ZSTD_greedy }, /* level 6 */
2269 { 0, 21, 17, 20, 3, 5, ZSTD_lazy }, /* level 7 */
2270 { 0, 21, 19, 20, 3, 5, ZSTD_lazy }, /* level 8 */
2271 { 0, 21, 20, 20, 3, 5, ZSTD_lazy2 }, /* level 9 */
2272 { 0, 21, 19, 21, 4, 5, ZSTD_lazy2 }, /* level 10 */
2273 { 0, 22, 20, 22, 4, 5, ZSTD_lazy2 }, /* level 11 */
2274 { 0, 22, 20, 22, 5, 5, ZSTD_lazy2 }, /* level 12 */
2275 { 0, 22, 21, 22, 5, 5, ZSTD_lazy2 }, /* level 13 */
2276 { 0, 22, 22, 23, 5, 5, ZSTD_lazy2 }, /* level 14 */
2277 { 0, 23, 23, 23, 5, 5, ZSTD_lazy2 }, /* level 15 */
2278 { 0, 23, 21, 22, 5, 5, ZSTD_btlazy2 }, /* level 16 */
2279 { 0, 23, 24, 23, 4, 5, ZSTD_btlazy2 }, /* level 17 */
2280 { 0, 25, 24, 23, 5, 5, ZSTD_btlazy2 }, /* level 18 */
2281 { 0, 25, 26, 23, 5, 5, ZSTD_btlazy2 }, /* level 19 */
2282 { 0, 26, 27, 25, 9, 5, ZSTD_btlazy2 }, /* level 20 */
inikepc71568f2016-01-30 12:15:56 +01002283 { 0, 23, 21, 22, 5, 5, ZSTD_opt }, /* level 21 */
2284 { 0, 23, 24, 23, 4, 5, ZSTD_opt }, /* level 22 */
2285 { 0, 25, 26, 23, 5, 5, ZSTD_opt }, /* level 23 */
2286 { 0, 26, 27, 25, 9, 5, ZSTD_opt }, /* level 24 */
Yann Colletfd416f12016-01-30 03:14:15 +01002287},
2288{ /* for srcSize <= 256 KB */
2289 /* W, C, H, S, L, strat */
2290 { 0, 18, 13, 14, 1, 7, ZSTD_fast }, /* level 0 - never used */
2291 { 0, 18, 14, 15, 1, 6, ZSTD_fast }, /* level 1 */
2292 { 0, 18, 14, 15, 1, 5, ZSTD_fast }, /* level 2 */
2293 { 0, 18, 12, 15, 3, 4, ZSTD_greedy }, /* level 3 */
2294 { 0, 18, 13, 15, 4, 4, ZSTD_greedy }, /* level 4 */
2295 { 0, 18, 14, 15, 5, 4, ZSTD_greedy }, /* level 5 */
2296 { 0, 18, 13, 15, 4, 4, ZSTD_lazy }, /* level 6 */
2297 { 0, 18, 14, 16, 5, 4, ZSTD_lazy }, /* level 7 */
2298 { 0, 18, 15, 16, 6, 4, ZSTD_lazy }, /* level 8 */
2299 { 0, 18, 15, 15, 7, 4, ZSTD_lazy }, /* level 9 */
2300 { 0, 18, 16, 16, 7, 4, ZSTD_lazy }, /* level 10 */
2301 { 0, 18, 16, 16, 8, 4, ZSTD_lazy }, /* level 11 */
2302 { 0, 18, 17, 16, 8, 4, ZSTD_lazy }, /* level 12 */
2303 { 0, 18, 17, 16, 9, 4, ZSTD_lazy }, /* level 13 */
2304 { 0, 18, 18, 16, 9, 4, ZSTD_lazy }, /* level 14 */
2305 { 0, 18, 17, 17, 9, 4, ZSTD_lazy2 }, /* level 15 */
2306 { 0, 18, 18, 18, 9, 4, ZSTD_lazy2 }, /* level 16 */
2307 { 0, 18, 18, 18, 10, 4, ZSTD_lazy2 }, /* level 17 */
2308 { 0, 18, 18, 18, 11, 4, ZSTD_lazy2 }, /* level 18 */
2309 { 0, 18, 18, 18, 12, 4, ZSTD_lazy2 }, /* level 19 */
2310 { 0, 18, 18, 18, 13, 4, ZSTD_lazy2 }, /* level 20 */
inikepc71568f2016-01-30 12:15:56 +01002311 { 0, 18, 18, 18, 10, 4, ZSTD_lazy2 }, /* level 17 */
2312 { 0, 18, 18, 18, 11, 4, ZSTD_lazy2 }, /* level 18 */
2313 { 0, 18, 18, 18, 12, 4, ZSTD_lazy2 }, /* level 19 */
2314 { 0, 18, 18, 18, 13, 4, ZSTD_lazy2 }, /* level 20 */
Yann Colletfd416f12016-01-30 03:14:15 +01002315},
2316{ /* for srcSize <= 128 KB */
2317 /* W, C, H, S, L, strat */
2318 { 0, 17, 12, 12, 1, 4, ZSTD_fast }, /* level 0 - never used */
2319 { 0, 17, 12, 13, 1, 6, ZSTD_fast }, /* level 1 */
2320 { 0, 17, 14, 16, 1, 5, ZSTD_fast }, /* level 2 */
2321 { 0, 17, 15, 17, 1, 5, ZSTD_fast }, /* level 3 */
2322 { 0, 17, 13, 15, 2, 4, ZSTD_greedy }, /* level 4 */
2323 { 0, 17, 15, 17, 3, 4, ZSTD_greedy }, /* level 5 */
2324 { 0, 17, 14, 17, 3, 4, ZSTD_lazy }, /* level 6 */
2325 { 0, 17, 16, 17, 4, 4, ZSTD_lazy }, /* level 7 */
2326 { 0, 17, 16, 17, 4, 4, ZSTD_lazy2 }, /* level 8 */
2327 { 0, 17, 17, 16, 5, 4, ZSTD_lazy2 }, /* level 9 */
2328 { 0, 17, 17, 16, 6, 4, ZSTD_lazy2 }, /* level 10 */
2329 { 0, 17, 17, 16, 7, 4, ZSTD_lazy2 }, /* level 11 */
2330 { 0, 17, 17, 16, 8, 4, ZSTD_lazy2 }, /* level 12 */
2331 { 0, 17, 18, 16, 4, 4, ZSTD_btlazy2 }, /* level 13 */
2332 { 0, 17, 18, 16, 5, 4, ZSTD_btlazy2 }, /* level 14 */
2333 { 0, 17, 18, 16, 6, 4, ZSTD_btlazy2 }, /* level 15 */
2334 { 0, 17, 18, 16, 7, 4, ZSTD_btlazy2 }, /* level 16 */
2335 { 0, 17, 18, 16, 8, 4, ZSTD_btlazy2 }, /* level 17 */
2336 { 0, 17, 18, 16, 9, 4, ZSTD_btlazy2 }, /* level 18 */
2337 { 0, 17, 18, 16, 10, 4, ZSTD_btlazy2 }, /* level 19 */
2338 { 0, 17, 18, 18, 12, 4, ZSTD_btlazy2 }, /* level 20 */
inikepc71568f2016-01-30 12:15:56 +01002339 { 0, 17, 18, 16, 8, 4, ZSTD_btlazy2 }, /* level 17 */
2340 { 0, 17, 18, 16, 9, 4, ZSTD_btlazy2 }, /* level 18 */
2341 { 0, 17, 18, 16, 10, 4, ZSTD_btlazy2 }, /* level 19 */
2342 { 0, 17, 18, 18, 12, 4, ZSTD_btlazy2 }, /* level 20 */
Yann Colletfd416f12016-01-30 03:14:15 +01002343},
2344{ /* for srcSize <= 16 KB */
2345 /* W, C, H, S, L, strat */
2346 { 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
2347 { 0, 14, 14, 14, 1, 4, ZSTD_fast }, /* level 1 */
2348 { 0, 14, 14, 16, 1, 4, ZSTD_fast }, /* level 2 */
2349 { 0, 14, 14, 14, 5, 4, ZSTD_greedy }, /* level 3 */
2350 { 0, 14, 14, 14, 8, 4, ZSTD_greedy }, /* level 4 */
2351 { 0, 14, 11, 14, 6, 4, ZSTD_lazy }, /* level 5 */
2352 { 0, 14, 14, 13, 6, 5, ZSTD_lazy }, /* level 6 */
2353 { 0, 14, 14, 14, 7, 6, ZSTD_lazy }, /* level 7 */
2354 { 0, 14, 14, 14, 8, 4, ZSTD_lazy }, /* level 8 */
2355 { 0, 14, 14, 15, 9, 4, ZSTD_lazy }, /* level 9 */
2356 { 0, 14, 14, 15, 10, 4, ZSTD_lazy }, /* level 10 */
2357 { 0, 14, 15, 15, 6, 4, ZSTD_btlazy2 }, /* level 11 */
2358 { 0, 14, 15, 15, 7, 4, ZSTD_btlazy2 }, /* level 12 */
2359 { 0, 14, 15, 15, 8, 4, ZSTD_btlazy2 }, /* level 13 */
2360 { 0, 14, 15, 15, 9, 4, ZSTD_btlazy2 }, /* level 14 */
2361 { 0, 14, 15, 15, 10, 4, ZSTD_btlazy2 }, /* level 15 */
2362 { 0, 14, 15, 15, 11, 4, ZSTD_btlazy2 }, /* level 16 */
2363 { 0, 14, 15, 15, 12, 4, ZSTD_btlazy2 }, /* level 17 */
2364 { 0, 14, 15, 15, 13, 4, ZSTD_btlazy2 }, /* level 18 */
2365 { 0, 14, 15, 15, 14, 4, ZSTD_btlazy2 }, /* level 19 */
2366 { 0, 14, 15, 15, 15, 4, ZSTD_btlazy2 }, /* level 20 */
inikepc71568f2016-01-30 12:15:56 +01002367 { 0, 14, 15, 15, 12, 4, ZSTD_btlazy2 }, /* level 17 */
2368 { 0, 14, 15, 15, 13, 4, ZSTD_btlazy2 }, /* level 18 */
2369 { 0, 14, 15, 15, 14, 4, ZSTD_btlazy2 }, /* level 19 */
2370 { 0, 14, 15, 15, 15, 4, ZSTD_btlazy2 }, /* level 20 */
Yann Colletfd416f12016-01-30 03:14:15 +01002371},
2372};
2373
2374/*! ZSTD_getParams
2375* @return ZSTD_parameters structure for a selected compression level and srcSize.
2376* @srcSizeHint value is optional, select 0 if not known */
2377ZSTD_parameters ZSTD_getParams(int compressionLevel, U64 srcSizeHint)
2378{
2379 ZSTD_parameters result;
2380 int tableID = ((srcSizeHint-1) <= 256 KB) + ((srcSizeHint-1) <= 128 KB) + ((srcSizeHint-1) <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
2381 if (compressionLevel<=0) compressionLevel = 1;
2382 if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
2383 result = ZSTD_defaultParameters[tableID][compressionLevel];
2384 result.srcSize = srcSizeHint;
2385 return result;
2386}
2387