blob: 5a79b9f8b7e99a2e90a043c721584c6c236680ef [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
67struct ZSTD_HC_CCtx_s
68{
Yann Colletf3eca252015-10-22 15:31:46 +010069 const BYTE* end; /* next block here to continue on current prefix */
Yann Colleteeb8ba12015-10-22 16:55:40 +010070 const BYTE* base; /* All regular indexes relative to this position */
71 const BYTE* dictBase; /* extDict indexes relative to this position */
Yann Colletf3eca252015-10-22 15:31:46 +010072 U32 dictLimit; /* below that point, need extDict */
Yann Colleteeb8ba12015-10-22 16:55:40 +010073 U32 lowLimit; /* below that point, no more data */
Yann Colletf3eca252015-10-22 15:31:46 +010074 U32 nextToUpdate; /* index from which to continue dictionary update */
Yann Collet083fcc82015-10-25 14:06:35 +010075 ZSTD_HC_parameters params;
76 U32 hashTableLog;
77 U32 chainTableLog;
78 U32* hashTable;
79 U32* chainTable;
Yann Colleteeb8ba12015-10-22 16:55:40 +010080 seqStore_t seqStore; /* sequences storage ptrs */
Yann Colletf3eca252015-10-22 15:31:46 +010081 BYTE buffer[WORKPLACESIZE];
82};
83
84
85ZSTD_HC_CCtx* ZSTD_HC_createCCtx(void)
86{
Yann Collet083fcc82015-10-25 14:06:35 +010087 ZSTD_HC_CCtx* ctx = (ZSTD_HC_CCtx*) malloc(sizeof(ZSTD_HC_CCtx));
88 ctx->hashTable = NULL;
89 ctx->chainTable = NULL;
90 ctx->hashTableLog = 0;
91 ctx->chainTableLog = 0;
92 return ctx;
Yann Colletf3eca252015-10-22 15:31:46 +010093}
94
Yann Collet083fcc82015-10-25 14:06:35 +010095size_t ZSTD_HC_freeCCtx(ZSTD_HC_CCtx* cctx)
Yann Colletf3eca252015-10-22 15:31:46 +010096{
Yann Collet083fcc82015-10-25 14:06:35 +010097 free(cctx->hashTable);
98 free(cctx->chainTable);
99 free(cctx);
100 return 0;
101}
102
103static void ZSTD_HC_resetCCtx_advanced (ZSTD_HC_CCtx* zc,
104 const ZSTD_HC_parameters params, const void* start)
105{
Yann Collet342892c2015-10-26 17:44:04 +0100106 U32 outOfReach = ( 1 << params.searchLog) + 1;
Yann Collet083fcc82015-10-25 14:06:35 +0100107
108 if (zc->hashTableLog < params.hashLog)
109 {
110 free(zc->hashTable);
111 zc->hashTableLog = params.hashLog;
112 zc->hashTable = (U32*) malloc ( (1 << zc->hashTableLog) * sizeof(U32) );
113 }
114 memset(zc->hashTable, 0, (1 << params.hashLog) * sizeof(U32) );
115
116 if (zc->chainTableLog < params.chainLog)
117 {
118 free(zc->chainTable);
119 zc->chainTableLog = params.chainLog;
120 zc->chainTable = (U32*) malloc ( (1 << zc->chainTableLog) * sizeof(U32) );
121 }
122 memset(zc->chainTable, 0, (1 << params.chainLog) * sizeof(U32) );
123
Yann Collet342892c2015-10-26 17:44:04 +0100124 zc->nextToUpdate = outOfReach;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100125 zc->end = (const BYTE*)start;
Yann Collet342892c2015-10-26 17:44:04 +0100126 zc->base = zc->end - outOfReach;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100127 zc->dictBase = zc->base;
Yann Collet342892c2015-10-26 17:44:04 +0100128 zc->dictLimit = outOfReach;
129 zc->lowLimit = outOfReach;
Yann Collet083fcc82015-10-25 14:06:35 +0100130 zc->params = params;
Yann Colletf3eca252015-10-22 15:31:46 +0100131 zc->seqStore.buffer = zc->buffer;
132 zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
133 zc->seqStore.offCodeStart = (BYTE*) (zc->seqStore.offsetStart + (BLOCKSIZE>>2));
134 zc->seqStore.litStart = zc->seqStore.offCodeStart + (BLOCKSIZE>>2);
135 zc->seqStore.litLengthStart = zc->seqStore.litStart + BLOCKSIZE;
136 zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + (BLOCKSIZE>>2);
137 zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + (BLOCKSIZE>>2);
138}
139
Yann Collet083fcc82015-10-25 14:06:35 +0100140
Yann Colletf3eca252015-10-22 15:31:46 +0100141/* *************************************
142* Local Macros
143***************************************/
Yann Collet083fcc82015-10-25 14:06:35 +0100144#define KNUTH 2654435761U
145static U32 ZSTD_HC_hash(U32 u, U32 h) { return (u * KNUTH) >> (32-h) ; }
Yann Colletd55a7e02015-10-27 03:06:40 +0100146#define NEXT_IN_CHAIN(d) chainTable[(d) & chainMask] /* flexible, CHAINSIZE dependent */
Yann Colletf3eca252015-10-22 15:31:46 +0100147
Yann Collet083fcc82015-10-25 14:06:35 +0100148static U32 ZSTD_HC_hashPtr(const void* ptr, U32 h) { return ZSTD_HC_hash(MEM_read32(ptr), h); }
Yann Colletf3eca252015-10-22 15:31:46 +0100149
150
151/* *************************************
152* HC Compression
153***************************************/
154/* Update chains up to ip (excluded) */
155static void ZSTD_HC_insert (ZSTD_HC_CCtx* zc, const BYTE* ip)
156{
Yann Collet083fcc82015-10-25 14:06:35 +0100157 U32* const hashTable = zc->hashTable;
158 const U32 hashLog = zc->params.hashLog;
159 U32* const chainTable = zc->chainTable;
160 const U32 chainMask = (1 << zc->params.chainLog) - 1;
Yann Colletf3eca252015-10-22 15:31:46 +0100161 const BYTE* const base = zc->base;
162 const U32 target = (U32)(ip - base);
163 U32 idx = zc->nextToUpdate;
164
165 while(idx < target)
166 {
Yann Collet083fcc82015-10-25 14:06:35 +0100167 U32 h = ZSTD_HC_hashPtr(base+idx, hashLog);
Yann Colletd55a7e02015-10-27 03:06:40 +0100168 NEXT_IN_CHAIN(idx) = hashTable[h];
Yann Collet083fcc82015-10-25 14:06:35 +0100169 hashTable[h] = idx;
Yann Colletf3eca252015-10-22 15:31:46 +0100170 idx++;
171 }
172
173 zc->nextToUpdate = target;
174}
175
176
177static size_t ZSTD_HC_insertAndFindBestMatch (
178 ZSTD_HC_CCtx* zc, /* Index table will be updated */
179 const BYTE* ip, const BYTE* const iLimit,
180 const BYTE** matchpos,
181 const U32 maxNbAttempts)
182{
Yann Collet083fcc82015-10-25 14:06:35 +0100183 U32* const hashTable = zc->hashTable;
184 const U32 hashLog = zc->params.hashLog;
Yann Collet53fff6c2015-10-24 13:48:37 +0100185 U32* const chainTable = zc->chainTable;
Yann Collet083fcc82015-10-25 14:06:35 +0100186 const U32 chainSize = (1 << zc->params.chainLog);
187 const U32 chainMask = chainSize-1;
Yann Colletf3eca252015-10-22 15:31:46 +0100188 const BYTE* const base = zc->base;
189 const BYTE* const dictBase = zc->dictBase;
190 const U32 dictLimit = zc->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100191 const U32 maxDistance = (1 << zc->params.windowLog);
192 const U32 lowLimit = (zc->lowLimit + maxDistance > (U32)(ip-base)) ? zc->lowLimit : (U32)(ip - base) - (maxDistance - 1);
Yann Colletf3eca252015-10-22 15:31:46 +0100193 U32 matchIndex;
194 const BYTE* match;
195 int nbAttempts=maxNbAttempts;
196 size_t ml=0;
197
198 /* HC4 match finder */
199 ZSTD_HC_insert(zc, ip);
Yann Collet083fcc82015-10-25 14:06:35 +0100200 matchIndex = hashTable[ZSTD_HC_hashPtr(ip, hashLog)];
Yann Colletf3eca252015-10-22 15:31:46 +0100201
202 while ((matchIndex>=lowLimit) && (nbAttempts))
203 {
204 nbAttempts--;
205 if (matchIndex >= dictLimit)
206 {
207 match = base + matchIndex;
208 if (*(match+ml) == *(ip+ml)
209 && (MEM_read32(match) == MEM_read32(ip)))
210 {
211 const size_t mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
212 if (mlt > ml) { ml = mlt; *matchpos = match; }
213 }
214 }
215 else
216 {
217 match = dictBase + matchIndex;
218 if (MEM_read32(match) == MEM_read32(ip))
219 {
220 size_t mlt;
221 const BYTE* vLimit = ip + (dictLimit - matchIndex);
222 if (vLimit > iLimit) vLimit = iLimit;
223 mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
224 if ((ip+mlt == vLimit) && (vLimit < iLimit))
225 mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit);
226 if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
227 }
228 }
Yann Collet53fff6c2015-10-24 13:48:37 +0100229
Yann Collet083fcc82015-10-25 14:06:35 +0100230 if (base + matchIndex <= ip - chainSize) break;
Yann Colletd55a7e02015-10-27 03:06:40 +0100231 matchIndex = NEXT_IN_CHAIN(matchIndex);
Yann Colletf3eca252015-10-22 15:31:46 +0100232 }
233
234 return ml;
235}
236
237
Yann Colletf3eca252015-10-22 15:31:46 +0100238static size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
239{
240 seqStore_t* seqStorePtr = &(ctx->seqStore);
241 const BYTE* const istart = (const BYTE*)src;
Yann Colleted0a7812015-10-23 19:25:06 +0100242 const BYTE* ip = istart;
Yann Colletf3eca252015-10-22 15:31:46 +0100243 const BYTE* anchor = istart;
244 const BYTE* const iend = istart + srcSize;
245 const BYTE* const ilimit = iend - 8;
246
Yann Colleted0a7812015-10-23 19:25:06 +0100247 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet083fcc82015-10-25 14:06:35 +0100248 const U32 maxSearches = 1 << ctx->params.searchLog;
Yann Colletf3eca252015-10-22 15:31:46 +0100249
250 /* init */
251 ZSTD_resetSeqStore(seqStorePtr);
Yann Colleted0a7812015-10-23 19:25:06 +0100252 if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
Yann Colletf3eca252015-10-22 15:31:46 +0100253
Yann Colleted0a7812015-10-23 19:25:06 +0100254 /* Match Loop */
Yann Colletf3eca252015-10-22 15:31:46 +0100255 while (ip < ilimit)
256 {
Yann Colleted0a7812015-10-23 19:25:06 +0100257 /* repcode */
258 if (MEM_read32(ip) == MEM_read32(ip - offset_2))
259 /* store sequence */
Yann Colletf3eca252015-10-22 15:31:46 +0100260 {
Yann Collet342892c2015-10-26 17:44:04 +0100261 size_t matchLength = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
Yann Colletf3eca252015-10-22 15:31:46 +0100262 size_t litLength = ip-anchor;
Yann Colleted0a7812015-10-23 19:25:06 +0100263 size_t offset = offset_2;
Yann Colletf3eca252015-10-22 15:31:46 +0100264 offset_2 = offset_1;
Yann Colleted0a7812015-10-23 19:25:06 +0100265 offset_1 = offset;
266 ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength);
267 ip += matchLength+MINMATCH;
Yann Colletf3eca252015-10-22 15:31:46 +0100268 anchor = ip;
Yann Colleted0a7812015-10-23 19:25:06 +0100269 continue;
270 }
271
Yann Collet342892c2015-10-26 17:44:04 +0100272 /* repcode at ip+1 */
273 if (MEM_read32(ip+1) == MEM_read32(ip+1 - offset_1))
274 {
275 size_t matchLength = ZSTD_count(ip+1+MINMATCH, ip+1+MINMATCH-offset_1, iend);
276 size_t litLength = ip+1-anchor;
277 offset_2 = offset_1;
278 ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength);
279 ip += 1+matchLength+MINMATCH;
280 anchor = ip;
281 continue;
282 }
283
Yann Colleted0a7812015-10-23 19:25:06 +0100284 /* search */
285 {
286 const BYTE* match;
287 size_t matchLength = ZSTD_HC_insertAndFindBestMatch(ctx, ip, iend, &match, maxSearches);
288 if (!matchLength) { ip++; offset_2 = offset_1; continue; }
289 /* store sequence */
290 {
291 size_t litLength = ip-anchor;
Yann Colleted0a7812015-10-23 19:25:06 +0100292 offset_2 = offset_1;
293 offset_1 = ip-match;
Yann Collet342892c2015-10-26 17:44:04 +0100294 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset_1, matchLength-MINMATCH);
Yann Colleted0a7812015-10-23 19:25:06 +0100295 ip += matchLength;
296 anchor = ip;
297 }
Yann Colletf3eca252015-10-22 15:31:46 +0100298 }
299 }
300
301 /* Last Literals */
302 {
303 size_t lastLLSize = iend - anchor;
304 memcpy(seqStorePtr->lit, anchor, lastLLSize);
305 seqStorePtr->lit += lastLLSize;
306 }
307
Yann Collet2c6992e2015-10-27 12:18:00 +0100308 /* Final compression stage */
Yann Colletf3eca252015-10-22 15:31:46 +0100309 return ZSTD_compressSequences((BYTE*)dst, maxDstSize,
310 seqStorePtr, srcSize);
311}
312
313static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr,
314 void* dst, size_t maxDstSize,
315 const void* src, size_t srcSize)
316{
317 static const size_t blockSize = 128 KB;
318 size_t remaining = srcSize;
319 const BYTE* ip = (const BYTE*)src;
320 BYTE* const ostart = (BYTE*)dst;
321 BYTE* op = ostart;
322 BYTE* const oend = op + maxDstSize;
323
324 while (remaining > blockSize)
325 {
326 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, blockSize);
327
328 if (cSize == 0)
329 {
330 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */
331 }
332 else
333 {
334 op[0] = (BYTE)(cSize>>16);
335 op[1] = (BYTE)(cSize>>8);
336 op[2] = (BYTE)cSize;
337 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
338 cSize += 3;
339 }
340
341 remaining -= blockSize;
342 ip += blockSize;
343 op += cSize;
344 if (ZSTD_isError(cSize)) return cSize;
345 }
346
347 /* last block */
348 {
349 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, remaining);
350
351 if (cSize == 0)
352 {
353 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, remaining); /* block is not compressible */
354 }
355 else
356 {
357 op[0] = (BYTE)(cSize>>16);
358 op[1] = (BYTE)(cSize>>8);
359 op[2] = (BYTE)cSize;
360 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
361 cSize += 3;
362 }
363
364 op += cSize;
365 if (ZSTD_isError(cSize)) return cSize;
366 }
367
368 return op-ostart;
369}
370
371
372size_t ZSTD_HC_loadDict(ZSTD_HC_CCtx* ctx, const void* dictionary, size_t dictSize)
373{
374 /* TBD */
375 (void)ctx; (void)dictionary; (void)dictSize;
376 return 0;
377}
378
379static void ZSTD_HC_setExternalDict(ZSTD_HC_CCtx* ctxPtr, const void* newBlock)
380{
381 if (ctxPtr->end >= ctxPtr->base + 4)
382 ZSTD_HC_insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
383 /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
384 ctxPtr->lowLimit = ctxPtr->dictLimit;
385 ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
386 ctxPtr->dictBase = ctxPtr->base;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100387 ctxPtr->base = (const BYTE*)newBlock - ctxPtr->dictLimit;
388 ctxPtr->end = (const BYTE*)newBlock;
Yann Colletf3eca252015-10-22 15:31:46 +0100389 ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
390}
391
392size_t ZSTD_HC_compress_continue (ZSTD_HC_CCtx* ctxPtr,
393 void* dst, size_t dstSize,
394 const void* src, size_t srcSize)
395{
Yann Collet083fcc82015-10-25 14:06:35 +0100396 const U32 maxDistance = 1 << ctxPtr->params.windowLog;
397
Yann Colletf3eca252015-10-22 15:31:46 +0100398 /* Check overflow */
399 if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
400 {
401 size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100402 if (dictSize > maxDistance) dictSize = maxDistance;
Yann Colletf3eca252015-10-22 15:31:46 +0100403
404 ZSTD_HC_loadDict(ctxPtr, ctxPtr->end - dictSize, dictSize);
405 }
406
407 /* Check if blocks follow each other */
408 if ((const BYTE*)src != ctxPtr->end)
409 ZSTD_HC_setExternalDict(ctxPtr, (const BYTE*)src);
410
411 /* Check overlapping src/dictionary space (typical of cycling buffers) */
412 {
413 const BYTE* sourceEnd = (const BYTE*) src + srcSize;
414 const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
415 const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
416 if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd))
417 {
418 if (sourceEnd > dictEnd) sourceEnd = dictEnd;
419 ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
420 if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
421 }
422 }
423
424 return ZSTD_HC_compress_generic (ctxPtr, dst, dstSize, src, srcSize);
425}
426
427
Yann Collet083fcc82015-10-25 14:06:35 +0100428size_t ZSTD_HC_compressBegin_advanced(ZSTD_HC_CCtx* ctx,
429 void* dst, size_t maxDstSize,
430 const ZSTD_HC_parameters params, const void* src)
Yann Colletf3eca252015-10-22 15:31:46 +0100431{
432 /* Sanity check */
433 if (maxDstSize < 4) return ERROR(dstSize_tooSmall);
434
435 /* Init */
Yann Collet083fcc82015-10-25 14:06:35 +0100436 ZSTD_HC_resetCCtx_advanced(ctx, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100437
438 /* Write Header */
439 MEM_writeLE32(dst, ZSTD_magicNumber);
440
441 return 4;
442}
443
Yann Collet083fcc82015-10-25 14:06:35 +0100444
445size_t ZSTD_HC_compressBegin(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, unsigned compressionLevel, const void* src)
446{
447 if (compressionLevel==0) compressionLevel = ZSTD_HC_compressionLevel_default;
Yann Collet786f5b52015-10-26 15:45:58 +0100448 if (compressionLevel > ZSTD_HC_MAX_CLEVEL) compressionLevel = ZSTD_HC_MAX_CLEVEL;
Yann Collet083fcc82015-10-25 14:06:35 +0100449 return ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, ZSTD_HC_defaultParameters[compressionLevel], src);
450}
451
452
453size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx,
454 void* dst, size_t maxDstSize,
455 const void* src, size_t srcSize,
456 ZSTD_HC_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +0100457{
458 BYTE* const ostart = (BYTE*)dst;
459 BYTE* op = ostart;
460
461 /* Header */
Yann Collet083fcc82015-10-25 14:06:35 +0100462 size_t oSize = ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100463 if(ZSTD_isError(oSize)) return oSize;
464 op += oSize;
465 maxDstSize -= oSize;
466
467 /* body (compression) */
468 op += ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize);
469 if(ZSTD_isError(oSize)) return oSize;
470 op += oSize;
471 maxDstSize -= oSize;
472
473 /* Close frame */
474 oSize = ZSTD_compressEnd((ZSTD_CCtx*)ctx, op, maxDstSize);
475 if(ZSTD_isError(oSize)) return oSize;
476 op += oSize;
477
478 return (op - ostart);
479}
480
Yann Collet083fcc82015-10-25 14:06:35 +0100481size_t ZSTD_HC_compressCCtx (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
482{
Yann Collet786f5b52015-10-26 15:45:58 +0100483 if (compressionLevel==0) return ZSTD_compress(dst, maxDstSize, src, srcSize); /* fast mode */
484 if (compressionLevel > ZSTD_HC_MAX_CLEVEL) compressionLevel = ZSTD_HC_MAX_CLEVEL;
Yann Collet083fcc82015-10-25 14:06:35 +0100485 return ZSTD_HC_compress_advanced(ctx, dst, maxDstSize, src, srcSize, ZSTD_HC_defaultParameters[compressionLevel]);
486}
487
Yann Colletf3eca252015-10-22 15:31:46 +0100488size_t ZSTD_HC_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
489{
Yann Collet53fff6c2015-10-24 13:48:37 +0100490 ZSTD_HC_CCtx* ctx = ZSTD_HC_createCCtx();
491 size_t result = ZSTD_HC_compressCCtx(ctx, dst, maxDstSize, src, srcSize, compressionLevel);
492 ZSTD_HC_freeCCtx(ctx);
493 return result;
Yann Colletf3eca252015-10-22 15:31:46 +0100494}
495
496
497
498/**************************************
499* Streaming Functions
500**************************************/
Yann Colletf3eca252015-10-22 15:31:46 +0100501/* dictionary saving */
502
503size_t ZSTD_HC_saveDict (ZSTD_HC_CCtx* ctx, void* safeBuffer, size_t dictSize)
504{
505 /* TBD */
506 (void)ctx; (void)safeBuffer; (void)dictSize;
507 return 0;
508}
509