blob: 3409a17b3e70fe7d4dc0c4933467aee0e681f9b5 [file] [log] [blame]
Yann Colletf3eca252015-10-22 15:31:46 +01001/*
2 ZSTD HC - High Compression Mode of Zstandard
3 Copyright (C) 2015, Yann Collet.
4
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
35/* *************************************
36* Includes
37***************************************/
38#include <stdlib.h> /* malloc */
39#include <string.h> /* memset */
Yann Collet083fcc82015-10-25 14:06:35 +010040#include "zstdhc_static.h"
Yann Colletf3eca252015-10-22 15:31:46 +010041#include "zstd_static.h"
42#include "mem.h"
43
44
45/* *************************************
46* Tuning Parameter
47***************************************/
48static const U32 ZSTD_HC_compressionLevel_default = 9;
49
50
51/* *************************************
52* Local Constants
53***************************************/
54#define MINMATCH 4
Yann Collet53fff6c2015-10-24 13:48:37 +010055#define MAXD_LOG 26
Yann Colletf3eca252015-10-22 15:31:46 +010056
57#define KB *1024
58#define MB *1024*1024
59#define GB *(1ULL << 30)
60
61/* *************************************
62* Local Types
63***************************************/
64#define BLOCKSIZE (128 KB) /* define, for static allocation */
65#define WORKPLACESIZE (BLOCKSIZE*3)
66
Yann Collet083fcc82015-10-25 14:06:35 +010067#define MAX_CLEVEL 20
68static const ZSTD_HC_parameters ZSTD_HC_defaultParameters[MAX_CLEVEL] = {
69 /* W, C, H, S */
70 { 19, 18, 17 , 1},
71 { 19, 18, 17 , 1},
72 { 19, 18, 17 , 2},
73 { 19, 18, 17 , 3},
74 { 19, 18, 17 , 4},
75 { 19, 18, 17 , 5},
76 { 19, 18, 17 , 6},
77 { 19, 18, 17 , 7},
78 { 19, 18, 17 , 8},
79 { 19, 18, 17 , 9},
80 { 19, 18, 17 ,10},
81 { 19, 18, 17 ,11},
82 { 19, 18, 17 ,12},
83 { 19, 18, 17 ,13},
84 { 19, 18, 17 ,14},
85 { 19, 18, 17 ,15},
86 { 19, 18, 17 ,16},
87 { 19, 18, 17 ,17},
88 { 19, 18, 17 ,18},
89 { 19, 18, 17 ,19},
90};
91
Yann Colletf3eca252015-10-22 15:31:46 +010092struct ZSTD_HC_CCtx_s
93{
Yann Colletf3eca252015-10-22 15:31:46 +010094 const BYTE* end; /* next block here to continue on current prefix */
Yann Colleteeb8ba12015-10-22 16:55:40 +010095 const BYTE* base; /* All regular indexes relative to this position */
96 const BYTE* dictBase; /* extDict indexes relative to this position */
Yann Colletf3eca252015-10-22 15:31:46 +010097 U32 dictLimit; /* below that point, need extDict */
Yann Colleteeb8ba12015-10-22 16:55:40 +010098 U32 lowLimit; /* below that point, no more data */
Yann Colletf3eca252015-10-22 15:31:46 +010099 U32 nextToUpdate; /* index from which to continue dictionary update */
Yann Collet083fcc82015-10-25 14:06:35 +0100100 ZSTD_HC_parameters params;
101 U32 hashTableLog;
102 U32 chainTableLog;
103 U32* hashTable;
104 U32* chainTable;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100105 seqStore_t seqStore; /* sequences storage ptrs */
Yann Colletf3eca252015-10-22 15:31:46 +0100106 BYTE buffer[WORKPLACESIZE];
107};
108
109
110ZSTD_HC_CCtx* ZSTD_HC_createCCtx(void)
111{
Yann Collet083fcc82015-10-25 14:06:35 +0100112 ZSTD_HC_CCtx* ctx = (ZSTD_HC_CCtx*) malloc(sizeof(ZSTD_HC_CCtx));
113 ctx->hashTable = NULL;
114 ctx->chainTable = NULL;
115 ctx->hashTableLog = 0;
116 ctx->chainTableLog = 0;
117 return ctx;
Yann Colletf3eca252015-10-22 15:31:46 +0100118}
119
Yann Collet083fcc82015-10-25 14:06:35 +0100120size_t ZSTD_HC_freeCCtx(ZSTD_HC_CCtx* cctx)
Yann Colletf3eca252015-10-22 15:31:46 +0100121{
Yann Collet083fcc82015-10-25 14:06:35 +0100122 free(cctx->hashTable);
123 free(cctx->chainTable);
124 free(cctx);
125 return 0;
126}
127
128static void ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc,
129 const ZSTD_HC_parameters params, const void* start)
130{
131 size_t maxDistance = ( 1 << params.searchLog) + 1;
132
133 if (zc->hashTableLog < params.hashLog)
134 {
135 free(zc->hashTable);
136 zc->hashTableLog = params.hashLog;
137 zc->hashTable = (U32*) malloc ( (1 << zc->hashTableLog) * sizeof(U32) );
138 }
139 memset(zc->hashTable, 0, (1 << params.hashLog) * sizeof(U32) );
140
141 if (zc->chainTableLog < params.chainLog)
142 {
143 free(zc->chainTable);
144 zc->chainTableLog = params.chainLog;
145 zc->chainTable = (U32*) malloc ( (1 << zc->chainTableLog) * sizeof(U32) );
146 }
147 memset(zc->chainTable, 0, (1 << params.chainLog) * sizeof(U32) );
148
149 zc->nextToUpdate = maxDistance;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100150 zc->end = (const BYTE*)start;
Yann Collet083fcc82015-10-25 14:06:35 +0100151 zc->base = zc->end - maxDistance;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100152 zc->dictBase = zc->base;
Yann Collet083fcc82015-10-25 14:06:35 +0100153 zc->dictLimit = maxDistance;
154 zc->lowLimit = maxDistance;
155 zc->params = params;
Yann Colletf3eca252015-10-22 15:31:46 +0100156 zc->seqStore.buffer = zc->buffer;
157 zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
158 zc->seqStore.offCodeStart = (BYTE*) (zc->seqStore.offsetStart + (BLOCKSIZE>>2));
159 zc->seqStore.litStart = zc->seqStore.offCodeStart + (BLOCKSIZE>>2);
160 zc->seqStore.litLengthStart = zc->seqStore.litStart + BLOCKSIZE;
161 zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + (BLOCKSIZE>>2);
162 zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + (BLOCKSIZE>>2);
163}
164
Yann Collet083fcc82015-10-25 14:06:35 +0100165
Yann Colletf3eca252015-10-22 15:31:46 +0100166/* *************************************
167* Local Macros
168***************************************/
Yann Collet083fcc82015-10-25 14:06:35 +0100169#define KNUTH 2654435761U
170static U32 ZSTD_HC_hash(U32 u, U32 h) { return (u * KNUTH) >> (32-h) ; }
171#define DELTANEXT(d) chainTable[(d) & chainMask] /* flexible, CHAINSIZE dependent */
Yann Colletf3eca252015-10-22 15:31:46 +0100172
Yann Collet083fcc82015-10-25 14:06:35 +0100173static U32 ZSTD_HC_hashPtr(const void* ptr, U32 h) { return ZSTD_HC_hash(MEM_read32(ptr), h); }
Yann Colletf3eca252015-10-22 15:31:46 +0100174
175
176/* *************************************
177* HC Compression
178***************************************/
179/* Update chains up to ip (excluded) */
180static void ZSTD_HC_insert (ZSTD_HC_CCtx* zc, const BYTE* ip)
181{
Yann Collet083fcc82015-10-25 14:06:35 +0100182 U32* const hashTable = zc->hashTable;
183 const U32 hashLog = zc->params.hashLog;
184 U32* const chainTable = zc->chainTable;
185 const U32 chainMask = (1 << zc->params.chainLog) - 1;
Yann Colletf3eca252015-10-22 15:31:46 +0100186 const BYTE* const base = zc->base;
187 const U32 target = (U32)(ip - base);
188 U32 idx = zc->nextToUpdate;
189
190 while(idx < target)
191 {
Yann Collet083fcc82015-10-25 14:06:35 +0100192 U32 h = ZSTD_HC_hashPtr(base+idx, hashLog);
193 size_t delta = idx - hashTable[h];
Yann Collet53fff6c2015-10-24 13:48:37 +0100194 DELTANEXT(idx) = (U32)delta;
Yann Collet083fcc82015-10-25 14:06:35 +0100195 hashTable[h] = idx;
Yann Colletf3eca252015-10-22 15:31:46 +0100196 idx++;
197 }
198
199 zc->nextToUpdate = target;
200}
201
202
203static size_t ZSTD_HC_insertAndFindBestMatch (
204 ZSTD_HC_CCtx* zc, /* Index table will be updated */
205 const BYTE* ip, const BYTE* const iLimit,
206 const BYTE** matchpos,
207 const U32 maxNbAttempts)
208{
Yann Collet083fcc82015-10-25 14:06:35 +0100209 U32* const hashTable = zc->hashTable;
210 const U32 hashLog = zc->params.hashLog;
Yann Collet53fff6c2015-10-24 13:48:37 +0100211 U32* const chainTable = zc->chainTable;
Yann Collet083fcc82015-10-25 14:06:35 +0100212 const U32 chainSize = (1 << zc->params.chainLog);
213 const U32 chainMask = chainSize-1;
Yann Colletf3eca252015-10-22 15:31:46 +0100214 const BYTE* const base = zc->base;
215 const BYTE* const dictBase = zc->dictBase;
216 const U32 dictLimit = zc->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100217 const U32 maxDistance = (1 << zc->params.windowLog);
218 const U32 lowLimit = (zc->lowLimit + maxDistance > (U32)(ip-base)) ? zc->lowLimit : (U32)(ip - base) - (maxDistance - 1);
Yann Colletf3eca252015-10-22 15:31:46 +0100219 U32 matchIndex;
220 const BYTE* match;
221 int nbAttempts=maxNbAttempts;
222 size_t ml=0;
223
224 /* HC4 match finder */
225 ZSTD_HC_insert(zc, ip);
Yann Collet083fcc82015-10-25 14:06:35 +0100226 matchIndex = hashTable[ZSTD_HC_hashPtr(ip, hashLog)];
Yann Colletf3eca252015-10-22 15:31:46 +0100227
228 while ((matchIndex>=lowLimit) && (nbAttempts))
229 {
230 nbAttempts--;
231 if (matchIndex >= dictLimit)
232 {
233 match = base + matchIndex;
234 if (*(match+ml) == *(ip+ml)
235 && (MEM_read32(match) == MEM_read32(ip)))
236 {
237 const size_t mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
238 if (mlt > ml) { ml = mlt; *matchpos = match; }
239 }
240 }
241 else
242 {
243 match = dictBase + matchIndex;
244 if (MEM_read32(match) == MEM_read32(ip))
245 {
246 size_t mlt;
247 const BYTE* vLimit = ip + (dictLimit - matchIndex);
248 if (vLimit > iLimit) vLimit = iLimit;
249 mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
250 if ((ip+mlt == vLimit) && (vLimit < iLimit))
251 mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit);
252 if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
253 }
254 }
Yann Collet53fff6c2015-10-24 13:48:37 +0100255
Yann Collet083fcc82015-10-25 14:06:35 +0100256 if (base + matchIndex <= ip - chainSize) break;
Yann Collet53fff6c2015-10-24 13:48:37 +0100257 matchIndex -= DELTANEXT(matchIndex);
Yann Colletf3eca252015-10-22 15:31:46 +0100258 }
259
260 return ml;
261}
262
263
Yann Colletf3eca252015-10-22 15:31:46 +0100264static size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
265{
266 seqStore_t* seqStorePtr = &(ctx->seqStore);
267 const BYTE* const istart = (const BYTE*)src;
Yann Colleted0a7812015-10-23 19:25:06 +0100268 const BYTE* ip = istart;
Yann Colletf3eca252015-10-22 15:31:46 +0100269 const BYTE* anchor = istart;
270 const BYTE* const iend = istart + srcSize;
271 const BYTE* const ilimit = iend - 8;
272
Yann Colleted0a7812015-10-23 19:25:06 +0100273 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet083fcc82015-10-25 14:06:35 +0100274 const U32 maxSearches = 1 << ctx->params.searchLog;
Yann Colletf3eca252015-10-22 15:31:46 +0100275
276 /* init */
277 ZSTD_resetSeqStore(seqStorePtr);
Yann Colleted0a7812015-10-23 19:25:06 +0100278 if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
Yann Colletf3eca252015-10-22 15:31:46 +0100279
Yann Colleted0a7812015-10-23 19:25:06 +0100280 /* Match Loop */
Yann Colletf3eca252015-10-22 15:31:46 +0100281 while (ip < ilimit)
282 {
Yann Colleted0a7812015-10-23 19:25:06 +0100283 /* repcode */
284 if (MEM_read32(ip) == MEM_read32(ip - offset_2))
285 /* store sequence */
Yann Colletf3eca252015-10-22 15:31:46 +0100286 {
Yann Colleted0a7812015-10-23 19:25:06 +0100287 size_t matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend);
Yann Colletf3eca252015-10-22 15:31:46 +0100288 size_t litLength = ip-anchor;
Yann Colleted0a7812015-10-23 19:25:06 +0100289 size_t offset = offset_2;
Yann Colletf3eca252015-10-22 15:31:46 +0100290 offset_2 = offset_1;
Yann Colleted0a7812015-10-23 19:25:06 +0100291 offset_1 = offset;
292 ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength);
293 ip += matchLength+MINMATCH;
Yann Colletf3eca252015-10-22 15:31:46 +0100294 anchor = ip;
Yann Colleted0a7812015-10-23 19:25:06 +0100295 continue;
296 }
297
298 /* search */
299 {
300 const BYTE* match;
301 size_t matchLength = ZSTD_HC_insertAndFindBestMatch(ctx, ip, iend, &match, maxSearches);
302 if (!matchLength) { ip++; offset_2 = offset_1; continue; }
303 /* store sequence */
304 {
305 size_t litLength = ip-anchor;
306 size_t offset = ip-match;
307 if (offset == offset_2) offset = 0;
308 offset_2 = offset_1;
309 offset_1 = ip-match;
310 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
311 ip += matchLength;
312 anchor = ip;
313 }
Yann Colletf3eca252015-10-22 15:31:46 +0100314 }
315 }
316
317 /* Last Literals */
318 {
319 size_t lastLLSize = iend - anchor;
320 memcpy(seqStorePtr->lit, anchor, lastLLSize);
321 seqStorePtr->lit += lastLLSize;
322 }
323
324 /* Finale compression stage */
325 return ZSTD_compressSequences((BYTE*)dst, maxDstSize,
326 seqStorePtr, srcSize);
327}
328
329static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr,
330 void* dst, size_t maxDstSize,
331 const void* src, size_t srcSize)
332{
333 static const size_t blockSize = 128 KB;
334 size_t remaining = srcSize;
335 const BYTE* ip = (const BYTE*)src;
336 BYTE* const ostart = (BYTE*)dst;
337 BYTE* op = ostart;
338 BYTE* const oend = op + maxDstSize;
339
340 while (remaining > blockSize)
341 {
342 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, blockSize);
343
344 if (cSize == 0)
345 {
346 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */
347 }
348 else
349 {
350 op[0] = (BYTE)(cSize>>16);
351 op[1] = (BYTE)(cSize>>8);
352 op[2] = (BYTE)cSize;
353 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
354 cSize += 3;
355 }
356
357 remaining -= blockSize;
358 ip += blockSize;
359 op += cSize;
360 if (ZSTD_isError(cSize)) return cSize;
361 }
362
363 /* last block */
364 {
365 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, remaining);
366
367 if (cSize == 0)
368 {
369 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, remaining); /* block is not compressible */
370 }
371 else
372 {
373 op[0] = (BYTE)(cSize>>16);
374 op[1] = (BYTE)(cSize>>8);
375 op[2] = (BYTE)cSize;
376 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
377 cSize += 3;
378 }
379
380 op += cSize;
381 if (ZSTD_isError(cSize)) return cSize;
382 }
383
384 return op-ostart;
385}
386
387
388size_t ZSTD_HC_loadDict(ZSTD_HC_CCtx* ctx, const void* dictionary, size_t dictSize)
389{
390 /* TBD */
391 (void)ctx; (void)dictionary; (void)dictSize;
392 return 0;
393}
394
395static void ZSTD_HC_setExternalDict(ZSTD_HC_CCtx* ctxPtr, const void* newBlock)
396{
397 if (ctxPtr->end >= ctxPtr->base + 4)
398 ZSTD_HC_insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
399 /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
400 ctxPtr->lowLimit = ctxPtr->dictLimit;
401 ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
402 ctxPtr->dictBase = ctxPtr->base;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100403 ctxPtr->base = (const BYTE*)newBlock - ctxPtr->dictLimit;
404 ctxPtr->end = (const BYTE*)newBlock;
Yann Colletf3eca252015-10-22 15:31:46 +0100405 ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
406}
407
408size_t ZSTD_HC_compress_continue (ZSTD_HC_CCtx* ctxPtr,
409 void* dst, size_t dstSize,
410 const void* src, size_t srcSize)
411{
Yann Collet083fcc82015-10-25 14:06:35 +0100412 const U32 maxDistance = 1 << ctxPtr->params.windowLog;
413
Yann Colletf3eca252015-10-22 15:31:46 +0100414 /* Check overflow */
415 if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
416 {
417 size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100418 if (dictSize > maxDistance) dictSize = maxDistance;
Yann Colletf3eca252015-10-22 15:31:46 +0100419
420 ZSTD_HC_loadDict(ctxPtr, ctxPtr->end - dictSize, dictSize);
421 }
422
423 /* Check if blocks follow each other */
424 if ((const BYTE*)src != ctxPtr->end)
425 ZSTD_HC_setExternalDict(ctxPtr, (const BYTE*)src);
426
427 /* Check overlapping src/dictionary space (typical of cycling buffers) */
428 {
429 const BYTE* sourceEnd = (const BYTE*) src + srcSize;
430 const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
431 const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
432 if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd))
433 {
434 if (sourceEnd > dictEnd) sourceEnd = dictEnd;
435 ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
436 if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
437 }
438 }
439
440 return ZSTD_HC_compress_generic (ctxPtr, dst, dstSize, src, srcSize);
441}
442
443
Yann Collet083fcc82015-10-25 14:06:35 +0100444size_t ZSTD_HC_compressBegin_advanced(ZSTD_HC_CCtx* ctx,
445 void* dst, size_t maxDstSize,
446 const ZSTD_HC_parameters params, const void* src)
Yann Colletf3eca252015-10-22 15:31:46 +0100447{
448 /* Sanity check */
449 if (maxDstSize < 4) return ERROR(dstSize_tooSmall);
450
451 /* Init */
Yann Collet083fcc82015-10-25 14:06:35 +0100452 ZSTD_HC_resetCCtx_advanced(ctx, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100453
454 /* Write Header */
455 MEM_writeLE32(dst, ZSTD_magicNumber);
456
457 return 4;
458}
459
Yann Collet083fcc82015-10-25 14:06:35 +0100460
461size_t ZSTD_HC_compressBegin(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, unsigned compressionLevel, const void* src)
462{
463 if (compressionLevel==0) compressionLevel = ZSTD_HC_compressionLevel_default;
464 if (compressionLevel > MAX_CLEVEL) compressionLevel = MAX_CLEVEL;
465 return ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, ZSTD_HC_defaultParameters[compressionLevel], src);
466}
467
468
469size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx,
470 void* dst, size_t maxDstSize,
471 const void* src, size_t srcSize,
472 ZSTD_HC_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +0100473{
474 BYTE* const ostart = (BYTE*)dst;
475 BYTE* op = ostart;
476
477 /* Header */
Yann Collet083fcc82015-10-25 14:06:35 +0100478 size_t oSize = ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100479 if(ZSTD_isError(oSize)) return oSize;
480 op += oSize;
481 maxDstSize -= oSize;
482
483 /* body (compression) */
484 op += ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize);
485 if(ZSTD_isError(oSize)) return oSize;
486 op += oSize;
487 maxDstSize -= oSize;
488
489 /* Close frame */
490 oSize = ZSTD_compressEnd((ZSTD_CCtx*)ctx, op, maxDstSize);
491 if(ZSTD_isError(oSize)) return oSize;
492 op += oSize;
493
494 return (op - ostart);
495}
496
Yann Collet083fcc82015-10-25 14:06:35 +0100497size_t ZSTD_HC_compressCCtx (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
498{
499 if (compressionLevel==0) compressionLevel = ZSTD_HC_compressionLevel_default;
500 if (compressionLevel > MAX_CLEVEL) compressionLevel = MAX_CLEVEL;
501 return ZSTD_HC_compress_advanced(ctx, dst, maxDstSize, src, srcSize, ZSTD_HC_defaultParameters[compressionLevel]);
502}
503
Yann Colletf3eca252015-10-22 15:31:46 +0100504size_t ZSTD_HC_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
505{
Yann Collet53fff6c2015-10-24 13:48:37 +0100506 ZSTD_HC_CCtx* ctx = ZSTD_HC_createCCtx();
507 size_t result = ZSTD_HC_compressCCtx(ctx, dst, maxDstSize, src, srcSize, compressionLevel);
508 ZSTD_HC_freeCCtx(ctx);
509 return result;
Yann Colletf3eca252015-10-22 15:31:46 +0100510}
511
512
513
514/**************************************
515* Streaming Functions
516**************************************/
Yann Colletf3eca252015-10-22 15:31:46 +0100517/* dictionary saving */
518
519size_t ZSTD_HC_saveDict (ZSTD_HC_CCtx* ctx, void* safeBuffer, size_t dictSize)
520{
521 /* TBD */
522 (void)ctx; (void)safeBuffer; (void)dictSize;
523 return 0;
524}
525