blob: 1671f4265cceb5c428307e7c3f85161b4efdd08f [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 Collet3a787da2015-10-25 19:42:03 +0100106 U32 maxDistance = ( 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
124 zc->nextToUpdate = maxDistance;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100125 zc->end = (const BYTE*)start;
Yann Collet083fcc82015-10-25 14:06:35 +0100126 zc->base = zc->end - maxDistance;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100127 zc->dictBase = zc->base;
Yann Collet083fcc82015-10-25 14:06:35 +0100128 zc->dictLimit = maxDistance;
129 zc->lowLimit = maxDistance;
130 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) ; }
146#define DELTANEXT(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);
168 size_t delta = idx - hashTable[h];
Yann Collet53fff6c2015-10-24 13:48:37 +0100169 DELTANEXT(idx) = (U32)delta;
Yann Collet083fcc82015-10-25 14:06:35 +0100170 hashTable[h] = idx;
Yann Colletf3eca252015-10-22 15:31:46 +0100171 idx++;
172 }
173
174 zc->nextToUpdate = target;
175}
176
177
178static size_t ZSTD_HC_insertAndFindBestMatch (
179 ZSTD_HC_CCtx* zc, /* Index table will be updated */
180 const BYTE* ip, const BYTE* const iLimit,
181 const BYTE** matchpos,
182 const U32 maxNbAttempts)
183{
Yann Collet083fcc82015-10-25 14:06:35 +0100184 U32* const hashTable = zc->hashTable;
185 const U32 hashLog = zc->params.hashLog;
Yann Collet53fff6c2015-10-24 13:48:37 +0100186 U32* const chainTable = zc->chainTable;
Yann Collet083fcc82015-10-25 14:06:35 +0100187 const U32 chainSize = (1 << zc->params.chainLog);
188 const U32 chainMask = chainSize-1;
Yann Colletf3eca252015-10-22 15:31:46 +0100189 const BYTE* const base = zc->base;
190 const BYTE* const dictBase = zc->dictBase;
191 const U32 dictLimit = zc->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100192 const U32 maxDistance = (1 << zc->params.windowLog);
193 const U32 lowLimit = (zc->lowLimit + maxDistance > (U32)(ip-base)) ? zc->lowLimit : (U32)(ip - base) - (maxDistance - 1);
Yann Colletf3eca252015-10-22 15:31:46 +0100194 U32 matchIndex;
195 const BYTE* match;
196 int nbAttempts=maxNbAttempts;
197 size_t ml=0;
198
199 /* HC4 match finder */
200 ZSTD_HC_insert(zc, ip);
Yann Collet083fcc82015-10-25 14:06:35 +0100201 matchIndex = hashTable[ZSTD_HC_hashPtr(ip, hashLog)];
Yann Colletf3eca252015-10-22 15:31:46 +0100202
203 while ((matchIndex>=lowLimit) && (nbAttempts))
204 {
205 nbAttempts--;
206 if (matchIndex >= dictLimit)
207 {
208 match = base + matchIndex;
209 if (*(match+ml) == *(ip+ml)
210 && (MEM_read32(match) == MEM_read32(ip)))
211 {
212 const size_t mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
213 if (mlt > ml) { ml = mlt; *matchpos = match; }
214 }
215 }
216 else
217 {
218 match = dictBase + matchIndex;
219 if (MEM_read32(match) == MEM_read32(ip))
220 {
221 size_t mlt;
222 const BYTE* vLimit = ip + (dictLimit - matchIndex);
223 if (vLimit > iLimit) vLimit = iLimit;
224 mlt = ZSTD_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
225 if ((ip+mlt == vLimit) && (vLimit < iLimit))
226 mlt += ZSTD_count(ip+mlt, base+dictLimit, iLimit);
227 if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
228 }
229 }
Yann Collet53fff6c2015-10-24 13:48:37 +0100230
Yann Collet083fcc82015-10-25 14:06:35 +0100231 if (base + matchIndex <= ip - chainSize) break;
Yann Collet53fff6c2015-10-24 13:48:37 +0100232 matchIndex -= DELTANEXT(matchIndex);
Yann Colletf3eca252015-10-22 15:31:46 +0100233 }
234
235 return ml;
236}
237
238
Yann Colletf3eca252015-10-22 15:31:46 +0100239static size_t ZSTD_HC_compressBlock(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
240{
241 seqStore_t* seqStorePtr = &(ctx->seqStore);
242 const BYTE* const istart = (const BYTE*)src;
Yann Colleted0a7812015-10-23 19:25:06 +0100243 const BYTE* ip = istart;
Yann Colletf3eca252015-10-22 15:31:46 +0100244 const BYTE* anchor = istart;
245 const BYTE* const iend = istart + srcSize;
246 const BYTE* const ilimit = iend - 8;
247
Yann Colleted0a7812015-10-23 19:25:06 +0100248 size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
Yann Collet083fcc82015-10-25 14:06:35 +0100249 const U32 maxSearches = 1 << ctx->params.searchLog;
Yann Colletf3eca252015-10-22 15:31:46 +0100250
251 /* init */
252 ZSTD_resetSeqStore(seqStorePtr);
Yann Colleted0a7812015-10-23 19:25:06 +0100253 if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
Yann Colletf3eca252015-10-22 15:31:46 +0100254
Yann Colleted0a7812015-10-23 19:25:06 +0100255 /* Match Loop */
Yann Colletf3eca252015-10-22 15:31:46 +0100256 while (ip < ilimit)
257 {
Yann Colleted0a7812015-10-23 19:25:06 +0100258 /* repcode */
259 if (MEM_read32(ip) == MEM_read32(ip - offset_2))
260 /* store sequence */
Yann Colletf3eca252015-10-22 15:31:46 +0100261 {
Yann Colleted0a7812015-10-23 19:25:06 +0100262 size_t matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend);
Yann Colletf3eca252015-10-22 15:31:46 +0100263 size_t litLength = ip-anchor;
Yann Colleted0a7812015-10-23 19:25:06 +0100264 size_t offset = offset_2;
Yann Colletf3eca252015-10-22 15:31:46 +0100265 offset_2 = offset_1;
Yann Colleted0a7812015-10-23 19:25:06 +0100266 offset_1 = offset;
267 ZSTD_storeSeq(seqStorePtr, litLength, anchor, 0, matchLength);
268 ip += matchLength+MINMATCH;
Yann Colletf3eca252015-10-22 15:31:46 +0100269 anchor = ip;
Yann Colleted0a7812015-10-23 19:25:06 +0100270 continue;
271 }
272
273 /* search */
274 {
275 const BYTE* match;
276 size_t matchLength = ZSTD_HC_insertAndFindBestMatch(ctx, ip, iend, &match, maxSearches);
277 if (!matchLength) { ip++; offset_2 = offset_1; continue; }
278 /* store sequence */
279 {
280 size_t litLength = ip-anchor;
281 size_t offset = ip-match;
282 if (offset == offset_2) offset = 0;
283 offset_2 = offset_1;
284 offset_1 = ip-match;
285 ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
286 ip += matchLength;
287 anchor = ip;
288 }
Yann Colletf3eca252015-10-22 15:31:46 +0100289 }
290 }
291
292 /* Last Literals */
293 {
294 size_t lastLLSize = iend - anchor;
295 memcpy(seqStorePtr->lit, anchor, lastLLSize);
296 seqStorePtr->lit += lastLLSize;
297 }
298
299 /* Finale compression stage */
300 return ZSTD_compressSequences((BYTE*)dst, maxDstSize,
301 seqStorePtr, srcSize);
302}
303
304static size_t ZSTD_HC_compress_generic (ZSTD_HC_CCtx* ctxPtr,
305 void* dst, size_t maxDstSize,
306 const void* src, size_t srcSize)
307{
308 static const size_t blockSize = 128 KB;
309 size_t remaining = srcSize;
310 const BYTE* ip = (const BYTE*)src;
311 BYTE* const ostart = (BYTE*)dst;
312 BYTE* op = ostart;
313 BYTE* const oend = op + maxDstSize;
314
315 while (remaining > blockSize)
316 {
317 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, blockSize);
318
319 if (cSize == 0)
320 {
321 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, blockSize); /* block is not compressible */
322 }
323 else
324 {
325 op[0] = (BYTE)(cSize>>16);
326 op[1] = (BYTE)(cSize>>8);
327 op[2] = (BYTE)cSize;
328 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
329 cSize += 3;
330 }
331
332 remaining -= blockSize;
333 ip += blockSize;
334 op += cSize;
335 if (ZSTD_isError(cSize)) return cSize;
336 }
337
338 /* last block */
339 {
340 size_t cSize = ZSTD_HC_compressBlock(ctxPtr, op+3, oend-op, ip, remaining);
341
342 if (cSize == 0)
343 {
344 cSize = ZSTD_noCompressBlock(op, maxDstSize, ip, remaining); /* block is not compressible */
345 }
346 else
347 {
348 op[0] = (BYTE)(cSize>>16);
349 op[1] = (BYTE)(cSize>>8);
350 op[2] = (BYTE)cSize;
351 op[0] += (BYTE)(bt_compressed << 6); /* is a compressed block */
352 cSize += 3;
353 }
354
355 op += cSize;
356 if (ZSTD_isError(cSize)) return cSize;
357 }
358
359 return op-ostart;
360}
361
362
363size_t ZSTD_HC_loadDict(ZSTD_HC_CCtx* ctx, const void* dictionary, size_t dictSize)
364{
365 /* TBD */
366 (void)ctx; (void)dictionary; (void)dictSize;
367 return 0;
368}
369
370static void ZSTD_HC_setExternalDict(ZSTD_HC_CCtx* ctxPtr, const void* newBlock)
371{
372 if (ctxPtr->end >= ctxPtr->base + 4)
373 ZSTD_HC_insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
374 /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
375 ctxPtr->lowLimit = ctxPtr->dictLimit;
376 ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
377 ctxPtr->dictBase = ctxPtr->base;
Yann Colleteeb8ba12015-10-22 16:55:40 +0100378 ctxPtr->base = (const BYTE*)newBlock - ctxPtr->dictLimit;
379 ctxPtr->end = (const BYTE*)newBlock;
Yann Colletf3eca252015-10-22 15:31:46 +0100380 ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
381}
382
383size_t ZSTD_HC_compress_continue (ZSTD_HC_CCtx* ctxPtr,
384 void* dst, size_t dstSize,
385 const void* src, size_t srcSize)
386{
Yann Collet083fcc82015-10-25 14:06:35 +0100387 const U32 maxDistance = 1 << ctxPtr->params.windowLog;
388
Yann Colletf3eca252015-10-22 15:31:46 +0100389 /* Check overflow */
390 if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
391 {
392 size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
Yann Collet083fcc82015-10-25 14:06:35 +0100393 if (dictSize > maxDistance) dictSize = maxDistance;
Yann Colletf3eca252015-10-22 15:31:46 +0100394
395 ZSTD_HC_loadDict(ctxPtr, ctxPtr->end - dictSize, dictSize);
396 }
397
398 /* Check if blocks follow each other */
399 if ((const BYTE*)src != ctxPtr->end)
400 ZSTD_HC_setExternalDict(ctxPtr, (const BYTE*)src);
401
402 /* Check overlapping src/dictionary space (typical of cycling buffers) */
403 {
404 const BYTE* sourceEnd = (const BYTE*) src + srcSize;
405 const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
406 const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
407 if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd))
408 {
409 if (sourceEnd > dictEnd) sourceEnd = dictEnd;
410 ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
411 if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
412 }
413 }
414
415 return ZSTD_HC_compress_generic (ctxPtr, dst, dstSize, src, srcSize);
416}
417
418
Yann Collet083fcc82015-10-25 14:06:35 +0100419size_t ZSTD_HC_compressBegin_advanced(ZSTD_HC_CCtx* ctx,
420 void* dst, size_t maxDstSize,
421 const ZSTD_HC_parameters params, const void* src)
Yann Colletf3eca252015-10-22 15:31:46 +0100422{
423 /* Sanity check */
424 if (maxDstSize < 4) return ERROR(dstSize_tooSmall);
425
426 /* Init */
Yann Collet083fcc82015-10-25 14:06:35 +0100427 ZSTD_HC_resetCCtx_advanced(ctx, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100428
429 /* Write Header */
430 MEM_writeLE32(dst, ZSTD_magicNumber);
431
432 return 4;
433}
434
Yann Collet083fcc82015-10-25 14:06:35 +0100435
436size_t ZSTD_HC_compressBegin(ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, unsigned compressionLevel, const void* src)
437{
438 if (compressionLevel==0) compressionLevel = ZSTD_HC_compressionLevel_default;
Yann Collet786f5b52015-10-26 15:45:58 +0100439 if (compressionLevel > ZSTD_HC_MAX_CLEVEL) compressionLevel = ZSTD_HC_MAX_CLEVEL;
Yann Collet083fcc82015-10-25 14:06:35 +0100440 return ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, ZSTD_HC_defaultParameters[compressionLevel], src);
441}
442
443
444size_t ZSTD_HC_compress_advanced (ZSTD_HC_CCtx* ctx,
445 void* dst, size_t maxDstSize,
446 const void* src, size_t srcSize,
447 ZSTD_HC_parameters params)
Yann Colletf3eca252015-10-22 15:31:46 +0100448{
449 BYTE* const ostart = (BYTE*)dst;
450 BYTE* op = ostart;
451
452 /* Header */
Yann Collet083fcc82015-10-25 14:06:35 +0100453 size_t oSize = ZSTD_HC_compressBegin_advanced(ctx, dst, maxDstSize, params, src);
Yann Colletf3eca252015-10-22 15:31:46 +0100454 if(ZSTD_isError(oSize)) return oSize;
455 op += oSize;
456 maxDstSize -= oSize;
457
458 /* body (compression) */
459 op += ZSTD_HC_compress_generic (ctx, op, maxDstSize, src, srcSize);
460 if(ZSTD_isError(oSize)) return oSize;
461 op += oSize;
462 maxDstSize -= oSize;
463
464 /* Close frame */
465 oSize = ZSTD_compressEnd((ZSTD_CCtx*)ctx, op, maxDstSize);
466 if(ZSTD_isError(oSize)) return oSize;
467 op += oSize;
468
469 return (op - ostart);
470}
471
Yann Collet083fcc82015-10-25 14:06:35 +0100472size_t ZSTD_HC_compressCCtx (ZSTD_HC_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
473{
Yann Collet786f5b52015-10-26 15:45:58 +0100474 if (compressionLevel==0) return ZSTD_compress(dst, maxDstSize, src, srcSize); /* fast mode */
475 if (compressionLevel > ZSTD_HC_MAX_CLEVEL) compressionLevel = ZSTD_HC_MAX_CLEVEL;
Yann Collet083fcc82015-10-25 14:06:35 +0100476 return ZSTD_HC_compress_advanced(ctx, dst, maxDstSize, src, srcSize, ZSTD_HC_defaultParameters[compressionLevel]);
477}
478
Yann Colletf3eca252015-10-22 15:31:46 +0100479size_t ZSTD_HC_compress(void* dst, size_t maxDstSize, const void* src, size_t srcSize, unsigned compressionLevel)
480{
Yann Collet53fff6c2015-10-24 13:48:37 +0100481 ZSTD_HC_CCtx* ctx = ZSTD_HC_createCCtx();
482 size_t result = ZSTD_HC_compressCCtx(ctx, dst, maxDstSize, src, srcSize, compressionLevel);
483 ZSTD_HC_freeCCtx(ctx);
484 return result;
Yann Colletf3eca252015-10-22 15:31:46 +0100485}
486
487
488
489/**************************************
490* Streaming Functions
491**************************************/
Yann Colletf3eca252015-10-22 15:31:46 +0100492/* dictionary saving */
493
494size_t ZSTD_HC_saveDict (ZSTD_HC_CCtx* ctx, void* safeBuffer, size_t dictSize)
495{
496 /* TBD */
497 (void)ctx; (void)safeBuffer; (void)dictSize;
498 return 0;
499}
500