2 LZ4 HC - High Compression Mode of LZ4
3 Copyright (C) 2011-2017, Yann Collet.
5 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
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
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.
30 You can contact the author at :
31 - LZ4 source repository : https://github.com/lz4/lz4
32 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
34 /* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
37 /* *************************************
39 ***************************************/
42 * Select how default compression function will allocate workplace memory,
43 * in stack (0:fastest), or in heap (1:requires malloc()).
44 * Since workplace is rather large, heap mode is recommended.
46 #ifndef LZ4HC_HEAPMODE
47 # define LZ4HC_HEAPMODE 1
51 /*=== Dependency ===*/
52 #define LZ4_HC_STATIC_LINKING_ONLY
56 /*=== Common LZ4 definitions ===*/
58 # pragma GCC diagnostic ignored "-Wunused-function"
60 #if defined (__clang__)
61 # pragma clang diagnostic ignored "-Wunused-function"
65 typedef enum { noDictCtx
, usingDictCtxHc
} dictCtx_directive
;
68 #define LZ4_COMMONDEFS_ONLY
69 #ifndef LZ4_SRC_INCLUDED
70 #include "lz4.c" /* LZ4_count, constants, mem */
74 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
75 #define LZ4_OPT_NUM (1<<12)
79 #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
80 #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
81 #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
82 #define DELTANEXTMAXD(p) chainTable[(p) & LZ4HC_MAXD_MASK] /* flexible, LZ4HC_MAXD dependent */
83 #define DELTANEXTU16(table, pos) table[(U16)(pos)] /* faster */
84 /* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */
85 #define UPDATABLE(ip, op, anchor) &ip, &op, &anchor
87 static U32
LZ4HC_hashPtr(const void *ptr
) { return HASH_FUNCTION(LZ4_read32(ptr
)); }
90 /**************************************
92 **************************************/
93 static void LZ4HC_clearTables(LZ4HC_CCtx_internal
*hc4
) {
94 MEM_INIT((void *)hc4
->hashTable
, 0, sizeof(hc4
->hashTable
));
95 MEM_INIT(hc4
->chainTable
, 0xFF, sizeof(hc4
->chainTable
));
98 static void LZ4HC_init_internal(LZ4HC_CCtx_internal
*hc4
, const BYTE
*start
) {
99 uptrval startingOffset
= (uptrval
)(hc4
->end
- hc4
->base
);
100 if (startingOffset
> 1 GB
) {
101 LZ4HC_clearTables(hc4
);
104 startingOffset
+= 64 KB
;
105 hc4
->nextToUpdate
= (U32
) startingOffset
;
106 hc4
->base
= start
- startingOffset
;
108 hc4
->dictBase
= start
- startingOffset
;
109 hc4
->dictLimit
= (U32
) startingOffset
;
110 hc4
->lowLimit
= (U32
) startingOffset
;
114 /* Update chains up to ip (excluded) */
115 LZ4_FORCE_INLINE
void LZ4HC_Insert(LZ4HC_CCtx_internal
*hc4
, const BYTE
*ip
) {
116 U16
*const chainTable
= hc4
->chainTable
;
117 U32
*const hashTable
= hc4
->hashTable
;
118 const BYTE
*const base
= hc4
->base
;
119 U32
const target
= (U32
)(ip
- base
);
120 U32 idx
= hc4
->nextToUpdate
;
122 while (idx
< target
) {
123 U32
const h
= LZ4HC_hashPtr(base
+ idx
);
124 size_t delta
= idx
- hashTable
[h
];
125 if (delta
> LZ4_DISTANCE_MAX
) delta
= LZ4_DISTANCE_MAX
;
126 DELTANEXTU16(chainTable
, idx
) = (U16
)delta
;
131 hc4
->nextToUpdate
= target
;
134 /** LZ4HC_countBack() :
135 * @return : negative value, nb of common bytes before ip/match */
137 int LZ4HC_countBack(const BYTE
*const ip
, const BYTE
*const match
,
138 const BYTE
*const iMin
, const BYTE
*const mMin
) {
140 int const min
= (int)MAX(iMin
- ip
, mMin
- match
);
143 assert((size_t)(ip
- iMin
) < (1U << 31));
144 assert(match
>= mMin
);
145 assert((size_t)(match
- mMin
) < (1U << 31));
147 && (ip
[back
- 1] == match
[back
- 1]))
152 #if defined(_MSC_VER)
153 # define LZ4HC_rotl32(x,r) _rotl(x,r)
155 # define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r)))
159 static U32
LZ4HC_rotatePattern(size_t const rotate
, U32
const pattern
) {
160 size_t const bitsToRotate
= (rotate
& (sizeof(pattern
) - 1)) << 3;
161 if (bitsToRotate
== 0)
163 return LZ4HC_rotl32(pattern
, (int)bitsToRotate
);
166 /* LZ4HC_countPattern() :
167 * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */
169 LZ4HC_countPattern(const BYTE
*ip
, const BYTE
*const iEnd
, U32
const pattern32
) {
170 const BYTE
*const iStart
= ip
;
171 reg_t
const pattern
= (sizeof(pattern
) == 8) ? (reg_t
)pattern32
+ (((reg_t
)pattern32
) << 32) : pattern32
;
173 while (likely(ip
< iEnd
- (sizeof(pattern
) - 1))) {
174 reg_t
const diff
= LZ4_read_ARCH(ip
) ^ pattern
;
175 if (!diff
) { ip
+= sizeof(pattern
); continue; }
176 ip
+= LZ4_NbCommonBytes(diff
);
177 return (unsigned)(ip
- iStart
);
180 if (LZ4_isLittleEndian()) {
181 reg_t patternByte
= pattern
;
182 while ((ip
< iEnd
) && (*ip
== (BYTE
)patternByte
)) {
186 } else { /* big endian */
187 U32 bitOffset
= (sizeof(pattern
) * 8) - 8;
189 BYTE
const byte
= (BYTE
)(pattern
>> bitOffset
);
190 if (*ip
!= byte
) break;
196 return (unsigned)(ip
- iStart
);
199 /* LZ4HC_reverseCountPattern() :
200 * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!)
201 * read using natural platform endianess */
203 LZ4HC_reverseCountPattern(const BYTE
*ip
, const BYTE
*const iLow
, U32 pattern
) {
204 const BYTE
*const iStart
= ip
;
206 while (likely(ip
>= iLow
+ 4)) {
207 if (LZ4_read32(ip
- 4) != pattern
) break;
211 const BYTE
*bytePtr
= (const BYTE
*)(&pattern
) + 3; /* works for any endianess */
212 while (likely(ip
> iLow
)) {
213 if (ip
[-1] != *bytePtr
) break;
218 return (unsigned)(iStart
- ip
);
221 /* LZ4HC_protectDictEnd() :
222 * Checks if the match is in the last 3 bytes of the dictionary, so reading the
223 * 4 byte MINMATCH would overflow.
224 * @returns true if the match index is okay.
226 static int LZ4HC_protectDictEnd(U32
const dictLimit
, U32
const matchIndex
) {
227 return ((U32
)((dictLimit
- 1) - matchIndex
) >= 3);
230 typedef enum { rep_untested
, rep_not
, rep_confirmed
} repeat_state_e
;
231 typedef enum { favorCompressionRatio
= 0, favorDecompressionSpeed
} HCfavor_e
;
234 LZ4HC_InsertAndGetWiderMatch(
235 LZ4HC_CCtx_internal
*hc4
,
236 const BYTE
*const ip
,
237 const BYTE
*const iLowLimit
,
238 const BYTE
*const iHighLimit
,
240 const BYTE
**matchpos
,
241 const BYTE
**startpos
,
242 const int maxNbAttempts
,
243 const int patternAnalysis
,
245 const dictCtx_directive dict
,
246 const HCfavor_e favorDecSpeed
) {
247 U16
*const chainTable
= hc4
->chainTable
;
248 U32
*const HashTable
= hc4
->hashTable
;
249 const LZ4HC_CCtx_internal
*const dictCtx
= hc4
->dictCtx
;
250 const BYTE
*const base
= hc4
->base
;
251 const U32 dictLimit
= hc4
->dictLimit
;
252 const BYTE
*const lowPrefixPtr
= base
+ dictLimit
;
253 const U32 ipIndex
= (U32
)(ip
- base
);
254 const U32 lowestMatchIndex
= (hc4
->lowLimit
+ (LZ4_DISTANCE_MAX
+ 1) > ipIndex
) ? hc4
->lowLimit
: ipIndex
- LZ4_DISTANCE_MAX
;
255 const BYTE
*const dictBase
= hc4
->dictBase
;
256 int const lookBackLength
= (int)(ip
- iLowLimit
);
257 int nbAttempts
= maxNbAttempts
;
258 U32 matchChainPos
= 0;
259 U32
const pattern
= LZ4_read32(ip
);
261 repeat_state_e repeat
= rep_untested
;
262 size_t srcPatternLength
= 0;
264 DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch");
266 LZ4HC_Insert(hc4
, ip
);
267 matchIndex
= HashTable
[LZ4HC_hashPtr(ip
)];
268 DEBUGLOG(7, "First match at index %u / %u (lowestMatchIndex)",
269 matchIndex
, lowestMatchIndex
);
271 while ((matchIndex
>= lowestMatchIndex
) && (nbAttempts
> 0)) {
274 assert(matchIndex
< ipIndex
);
275 if (favorDecSpeed
&& (ipIndex
- matchIndex
< 8)) {
277 } else if (matchIndex
>= dictLimit
) { /* within current Prefix */
278 const BYTE
*const matchPtr
= base
+ matchIndex
;
279 assert(matchPtr
>= lowPrefixPtr
);
280 assert(matchPtr
< ip
);
281 assert(longest
>= 1);
282 if (LZ4_read16(iLowLimit
+ longest
- 1) == LZ4_read16(matchPtr
- lookBackLength
+ longest
- 1)) {
283 if (LZ4_read32(matchPtr
) == pattern
) {
284 int const back
= lookBackLength
? LZ4HC_countBack(ip
, matchPtr
, iLowLimit
, lowPrefixPtr
) : 0;
285 matchLength
= MINMATCH
+ (int)LZ4_count(ip
+ MINMATCH
, matchPtr
+ MINMATCH
, iHighLimit
);
287 if (matchLength
> longest
) {
288 longest
= matchLength
;
289 *matchpos
= matchPtr
+ back
;
290 *startpos
= ip
+ back
;
294 } else { /* lowestMatchIndex <= matchIndex < dictLimit */
295 const BYTE
*const matchPtr
= dictBase
+ matchIndex
;
296 if (LZ4_read32(matchPtr
) == pattern
) {
297 const BYTE
*const dictStart
= dictBase
+ hc4
->lowLimit
;
299 const BYTE
*vLimit
= ip
+ (dictLimit
- matchIndex
);
300 if (vLimit
> iHighLimit
) vLimit
= iHighLimit
;
301 matchLength
= (int)LZ4_count(ip
+ MINMATCH
, matchPtr
+ MINMATCH
, vLimit
) + MINMATCH
;
302 if ((ip
+ matchLength
== vLimit
) && (vLimit
< iHighLimit
))
303 matchLength
+= LZ4_count(ip
+ matchLength
, lowPrefixPtr
, iHighLimit
);
304 back
= lookBackLength
? LZ4HC_countBack(ip
, matchPtr
, iLowLimit
, dictStart
) : 0;
306 if (matchLength
> longest
) {
307 longest
= matchLength
;
308 *matchpos
= base
+ matchIndex
+ back
; /* virtual pos, relative to ip, to retrieve offset */
309 *startpos
= ip
+ back
;
314 if (chainSwap
&& matchLength
== longest
) { /* better match => select a better chain */
315 assert(lookBackLength
== 0); /* search forward only */
316 if (matchIndex
+ (U32
)longest
<= ipIndex
) {
317 int const kTrigger
= 4;
318 U32 distanceToNextMatch
= 1;
319 int const end
= longest
- MINMATCH
+ 1;
321 int accel
= 1 << kTrigger
;
323 for (pos
= 0; pos
< end
; pos
+= step
) {
324 U32
const candidateDist
= DELTANEXTU16(chainTable
, matchIndex
+ (U32
)pos
);
325 step
= (accel
++ >> kTrigger
);
326 if (candidateDist
> distanceToNextMatch
) {
327 distanceToNextMatch
= candidateDist
;
328 matchChainPos
= (U32
)pos
;
329 accel
= 1 << kTrigger
;
332 if (distanceToNextMatch
> 1) {
333 if (distanceToNextMatch
> matchIndex
) break; /* avoid overflow */
334 matchIndex
-= distanceToNextMatch
;
341 U32
const distNextMatch
= DELTANEXTU16(chainTable
, matchIndex
);
342 if (patternAnalysis
&& distNextMatch
== 1 && matchChainPos
== 0) {
343 U32
const matchCandidateIdx
= matchIndex
- 1;
344 /* may be a repeated pattern */
345 if (repeat
== rep_untested
) {
346 if (((pattern
& 0xFFFF) == (pattern
>> 16))
347 & ((pattern
& 0xFF) == (pattern
>> 24))) {
348 repeat
= rep_confirmed
;
349 srcPatternLength
= LZ4HC_countPattern(ip
+ sizeof(pattern
), iHighLimit
, pattern
) + sizeof(pattern
);
354 if ((repeat
== rep_confirmed
) && (matchCandidateIdx
>= lowestMatchIndex
)
355 && LZ4HC_protectDictEnd(dictLimit
, matchCandidateIdx
)) {
356 const int extDict
= matchCandidateIdx
< dictLimit
;
357 const BYTE
*const matchPtr
= (extDict
? dictBase
: base
) + matchCandidateIdx
;
358 if (LZ4_read32(matchPtr
) == pattern
) { /* good candidate */
359 const BYTE
*const dictStart
= dictBase
+ hc4
->lowLimit
;
360 const BYTE
*const iLimit
= extDict
? dictBase
+ dictLimit
: iHighLimit
;
361 size_t forwardPatternLength
= LZ4HC_countPattern(matchPtr
+ sizeof(pattern
), iLimit
, pattern
) + sizeof(pattern
);
362 if (extDict
&& matchPtr
+ forwardPatternLength
== iLimit
) {
363 U32
const rotatedPattern
= LZ4HC_rotatePattern(forwardPatternLength
, pattern
);
364 forwardPatternLength
+= LZ4HC_countPattern(lowPrefixPtr
, iHighLimit
, rotatedPattern
);
367 const BYTE
*const lowestMatchPtr
= extDict
? dictStart
: lowPrefixPtr
;
368 size_t backLength
= LZ4HC_reverseCountPattern(matchPtr
, lowestMatchPtr
, pattern
);
369 size_t currentSegmentLength
;
370 if (!extDict
&& matchPtr
- backLength
== lowPrefixPtr
&& hc4
->lowLimit
< dictLimit
) {
371 U32
const rotatedPattern
= LZ4HC_rotatePattern((U32
)(-(int)backLength
), pattern
);
372 backLength
+= LZ4HC_reverseCountPattern(dictBase
+ dictLimit
, dictStart
, rotatedPattern
);
374 /* Limit backLength not go further than lowestMatchIndex */
375 backLength
= matchCandidateIdx
- MAX(matchCandidateIdx
- (U32
)backLength
, lowestMatchIndex
);
376 assert(matchCandidateIdx
- backLength
>= lowestMatchIndex
);
377 currentSegmentLength
= backLength
+ forwardPatternLength
;
378 /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */
379 if ((currentSegmentLength
>= srcPatternLength
) /* current pattern segment large enough to contain full srcPatternLength */
380 && (forwardPatternLength
<= srcPatternLength
)) { /* haven't reached this position yet */
381 U32
const newMatchIndex
= matchCandidateIdx
+ (U32
)forwardPatternLength
- (U32
)srcPatternLength
; /* best position, full pattern, might be followed by more match */
382 if (LZ4HC_protectDictEnd(dictLimit
, newMatchIndex
))
383 matchIndex
= newMatchIndex
;
385 /* Can only happen if started in the prefix */
386 assert(newMatchIndex
>= dictLimit
- 3 && newMatchIndex
< dictLimit
&& !extDict
);
387 matchIndex
= dictLimit
;
390 U32
const newMatchIndex
= matchCandidateIdx
- (U32
)backLength
; /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */
391 if (!LZ4HC_protectDictEnd(dictLimit
, newMatchIndex
)) {
392 assert(newMatchIndex
>= dictLimit
- 3 && newMatchIndex
< dictLimit
&& !extDict
);
393 matchIndex
= dictLimit
;
395 matchIndex
= newMatchIndex
;
396 if (lookBackLength
== 0) { /* no back possible */
397 size_t const maxML
= MIN(currentSegmentLength
, srcPatternLength
);
398 if ((size_t)longest
< maxML
) {
399 assert(base
+ matchIndex
!= ip
);
400 if ((size_t)(ip
- base
) - matchIndex
> LZ4_DISTANCE_MAX
) break;
401 assert(maxML
< 2 GB
);
402 longest
= (int)maxML
;
403 *matchpos
= base
+ matchIndex
; /* virtual pos, relative to ip, to retrieve offset */
407 U32
const distToNextPattern
= DELTANEXTU16(chainTable
, matchIndex
);
408 if (distToNextPattern
> matchIndex
) break; /* avoid overflow */
409 matchIndex
-= distToNextPattern
;
419 } /* PA optimization */
421 /* follow current chain */
422 matchIndex
-= DELTANEXTU16(chainTable
, matchIndex
+ matchChainPos
);
424 } /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */
426 if (dict
== usingDictCtxHc
428 && ipIndex
- lowestMatchIndex
< LZ4_DISTANCE_MAX
) {
429 size_t const dictEndOffset
= (size_t)(dictCtx
->end
- dictCtx
->base
);
430 U32 dictMatchIndex
= dictCtx
->hashTable
[LZ4HC_hashPtr(ip
)];
431 assert(dictEndOffset
<= 1 GB
);
432 matchIndex
= dictMatchIndex
+ lowestMatchIndex
- (U32
)dictEndOffset
;
433 while (ipIndex
- matchIndex
<= LZ4_DISTANCE_MAX
&& nbAttempts
--) {
434 const BYTE
*const matchPtr
= dictCtx
->base
+ dictMatchIndex
;
436 if (LZ4_read32(matchPtr
) == pattern
) {
439 const BYTE
*vLimit
= ip
+ (dictEndOffset
- dictMatchIndex
);
440 if (vLimit
> iHighLimit
) vLimit
= iHighLimit
;
441 mlt
= (int)LZ4_count(ip
+ MINMATCH
, matchPtr
+ MINMATCH
, vLimit
) + MINMATCH
;
442 back
= lookBackLength
? LZ4HC_countBack(ip
, matchPtr
, iLowLimit
, dictCtx
->base
+ dictCtx
->dictLimit
) : 0;
446 *matchpos
= base
+ matchIndex
+ back
;
447 *startpos
= ip
+ back
;
452 U32
const nextOffset
= DELTANEXTU16(dictCtx
->chainTable
, dictMatchIndex
);
453 dictMatchIndex
-= nextOffset
;
454 matchIndex
-= nextOffset
;
463 int LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal
*const hc4
, /* Index table will be updated */
464 const BYTE
*const ip
, const BYTE
*const iLimit
,
465 const BYTE
**matchpos
,
466 const int maxNbAttempts
,
467 const int patternAnalysis
,
468 const dictCtx_directive dict
) {
469 const BYTE
*uselessPtr
= ip
;
470 /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
471 * but this won't be the case here, as we define iLowLimit==ip,
472 * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
473 return LZ4HC_InsertAndGetWiderMatch(hc4
, ip
, ip
, iLimit
, MINMATCH
- 1, matchpos
, &uselessPtr
, maxNbAttempts
, patternAnalysis
, 0 /*chainSwap*/, dict
, favorCompressionRatio
);
476 /* LZ4HC_encodeSequence() :
478 * 1 if buffer issue detected */
479 LZ4_FORCE_INLINE
int LZ4HC_encodeSequence(
484 const BYTE
*const match
,
485 limitedOutput_directive limit
,
488 BYTE
*const token
= (*op
)++;
490 #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)
491 static const BYTE
*start
= NULL
;
492 static U32 totalCost
= 0;
493 U32
const pos
= (start
== NULL
) ? 0 : (U32
)(*anchor
- start
);
494 U32
const ll
= (U32
)(*ip
- *anchor
);
495 U32
const llAdd
= (ll
>= 15) ? ((ll
- 15) / 255) + 1 : 0;
496 U32
const mlAdd
= (matchLength
>= 19) ? ((matchLength
- 19) / 255) + 1 : 0;
497 U32
const cost
= 1 + llAdd
+ ll
+ 2 + mlAdd
;
498 if (start
== NULL
) start
= *anchor
; /* only works for single segment */
499 /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */
500 DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5u, cost:%4u + %5u",
502 (U32
)(*ip
- *anchor
), matchLength
, (U32
)(*ip
- match
),
507 /* Encode Literal length */
508 length
= (size_t)(*ip
- *anchor
);
509 LZ4_STATIC_ASSERT(notLimited
== 0);
510 /* Check output limit */
511 if (limit
&& ((*op
+ (length
/ 255) + length
+ (2 + 1 + LASTLITERALS
)) > oend
)) {
512 DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",
513 (int)length
, (int)(oend
- *op
));
516 if (length
>= RUN_MASK
) {
517 size_t len
= length
- RUN_MASK
;
518 *token
= (RUN_MASK
<< ML_BITS
);
519 for (; len
>= 255 ; len
-= 255) * (*op
)++ = 255;
520 *(*op
)++ = (BYTE
)len
;
522 *token
= (BYTE
)(length
<< ML_BITS
);
526 LZ4_wildCopy8(*op
, *anchor
, (*op
) + length
);
530 assert((*ip
- match
) <= LZ4_DISTANCE_MAX
); /* note : consider providing offset as a value, rather than as a pointer difference */
531 LZ4_writeLE16(*op
, (U16
)(*ip
- match
));
534 /* Encode MatchLength */
535 assert(matchLength
>= MINMATCH
);
536 length
= (size_t)matchLength
- MINMATCH
;
537 if (limit
&& (*op
+ (length
/ 255) + (1 + LASTLITERALS
) > oend
)) {
538 DEBUGLOG(6, "Not enough room to write match length");
539 return 1; /* Check output limit */
541 if (length
>= ML_MASK
) {
544 for (; length
>= 510 ; length
-= 510) { *(*op
)++ = 255; *(*op
)++ = 255; }
545 if (length
>= 255) { length
-= 255; *(*op
)++ = 255; }
546 *(*op
)++ = (BYTE
)length
;
548 *token
+= (BYTE
)(length
);
551 /* Prepare next loop */
558 LZ4_FORCE_INLINE
int LZ4HC_compress_hashChain(
559 LZ4HC_CCtx_internal
*const ctx
,
560 const char *const src
,
563 int const maxOutputSize
,
565 const limitedOutput_directive limit
,
566 const dictCtx_directive dict
568 const int inputSize
= *srcSizePtr
;
569 const int patternAnalysis
= (maxNbAttempts
> 128); /* levels 9+ */
571 const BYTE
*ip
= (const BYTE
*) src
;
572 const BYTE
*anchor
= ip
;
573 const BYTE
*const iend
= ip
+ inputSize
;
574 const BYTE
*const mflimit
= iend
- MFLIMIT
;
575 const BYTE
*const matchlimit
= (iend
- LASTLITERALS
);
577 BYTE
*optr
= (BYTE
*) dst
;
578 BYTE
*op
= (BYTE
*) dst
;
579 BYTE
*oend
= op
+ maxOutputSize
;
581 int ml0
, ml
, ml2
, ml3
;
584 const BYTE
*ref
= NULL
;
585 const BYTE
*start2
= NULL
;
586 const BYTE
*ref2
= NULL
;
587 const BYTE
*start3
= NULL
;
588 const BYTE
*ref3
= NULL
;
592 if (limit
== fillOutput
) oend
-= LASTLITERALS
; /* Hack for support LZ4 format restriction */
593 if (inputSize
< LZ4_minLength
) goto _last_literals
; /* Input too small, no compression (all literals) */
596 while (ip
<= mflimit
) {
597 ml
= LZ4HC_InsertAndFindBestMatch(ctx
, ip
, matchlimit
, &ref
, maxNbAttempts
, patternAnalysis
, dict
);
598 if (ml
< MINMATCH
) { ip
++; continue; }
600 /* saved, in case we would skip too much */
606 if (ip
+ ml
<= mflimit
) {
607 ml2
= LZ4HC_InsertAndGetWiderMatch(ctx
,
608 ip
+ ml
- 2, ip
+ 0, matchlimit
, ml
, &ref2
, &start2
,
609 maxNbAttempts
, patternAnalysis
, 0, dict
, favorCompressionRatio
);
614 if (ml2
== ml
) { /* No better match => encode ML1 */
616 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ref
, limit
, oend
)) goto _dest_overflow
;
620 if (start0
< ip
) { /* first match was skipped at least once */
621 if (start2
< ip
+ ml0
) { /* squeezing ML1 between ML0(original ML1) and ML2 */
624 ml
= ml0
; /* restore initial ML1 */
628 /* Here, start0==ip */
629 if ((start2
- ip
) < 3) { /* First Match too small : removed */
637 /* At this stage, we have :
639 * ip1+3 <= ip2 (usually < ip1+ml1) */
640 if ((start2
- ip
) < OPTIMAL_ML
) {
643 if (new_ml
> OPTIMAL_ML
) new_ml
= OPTIMAL_ML
;
644 if (ip
+ new_ml
> start2
+ ml2
- MINMATCH
) new_ml
= (int)(start2
- ip
) + ml2
- MINMATCH
;
645 correction
= new_ml
- (int)(start2
- ip
);
646 if (correction
> 0) {
647 start2
+= correction
;
652 /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
654 if (start2
+ ml2
<= mflimit
) {
655 ml3
= LZ4HC_InsertAndGetWiderMatch(ctx
,
656 start2
+ ml2
- 3, start2
, matchlimit
, ml2
, &ref3
, &start3
,
657 maxNbAttempts
, patternAnalysis
, 0, dict
, favorCompressionRatio
);
662 if (ml3
== ml2
) { /* No better match => encode ML1 and ML2 */
663 /* ip & ref are known; Now for ml */
664 if (start2
< ip
+ ml
) ml
= (int)(start2
- ip
);
665 /* Now, encode 2 sequences */
667 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ref
, limit
, oend
)) goto _dest_overflow
;
670 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml2
, ref2
, limit
, oend
)) {
678 if (start3
< ip
+ ml
+ 3) { /* Not enough space for match 2 : remove it */
679 if (start3
>= (ip
+ ml
)) { /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
680 if (start2
< ip
+ ml
) {
681 int correction
= (int)(ip
+ ml
- start2
);
682 start2
+= correction
;
685 if (ml2
< MINMATCH
) {
693 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ref
, limit
, oend
)) goto _dest_overflow
;
711 * OK, now we have 3 ascending matches;
712 * let's write the first one ML1.
713 * ip & ref are known; Now decide ml.
715 if (start2
< ip
+ ml
) {
716 if ((start2
- ip
) < OPTIMAL_ML
) {
718 if (ml
> OPTIMAL_ML
) ml
= OPTIMAL_ML
;
719 if (ip
+ ml
> start2
+ ml2
- MINMATCH
) ml
= (int)(start2
- ip
) + ml2
- MINMATCH
;
720 correction
= ml
- (int)(start2
- ip
);
721 if (correction
> 0) {
722 start2
+= correction
;
727 ml
= (int)(start2
- ip
);
731 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ref
, limit
, oend
)) goto _dest_overflow
;
733 /* ML2 becomes ML1 */
738 /* ML3 becomes ML2 */
743 /* let's find a new ML3 */
748 /* Encode Last Literals */
750 size_t lastRunSize
= (size_t)(iend
- anchor
); /* literals */
751 size_t llAdd
= (lastRunSize
+ 255 - RUN_MASK
) / 255;
752 size_t const totalSize
= 1 + llAdd
+ lastRunSize
;
753 if (limit
== fillOutput
) oend
+= LASTLITERALS
; /* restore correct value */
754 if (limit
&& (op
+ totalSize
> oend
)) {
755 if (limit
== limitedOutput
) return 0;
756 /* adapt lastRunSize to fill 'dest' */
757 lastRunSize
= (size_t)(oend
- op
) - 1 /*token*/;
758 llAdd
= (lastRunSize
+ 256 - RUN_MASK
) / 256;
759 lastRunSize
-= llAdd
;
761 DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize
);
762 ip
= anchor
+ lastRunSize
; /* can be != iend if limit==fillOutput */
764 if (lastRunSize
>= RUN_MASK
) {
765 size_t accumulator
= lastRunSize
- RUN_MASK
;
766 *op
++ = (RUN_MASK
<< ML_BITS
);
767 for (; accumulator
>= 255 ; accumulator
-= 255) * op
++ = 255;
768 *op
++ = (BYTE
) accumulator
;
770 *op
++ = (BYTE
)(lastRunSize
<< ML_BITS
);
772 memcpy(op
, anchor
, lastRunSize
);
777 *srcSizePtr
= (int)(((const char *)ip
) - src
);
778 return (int)(((char *)op
) - dst
);
781 if (limit
== fillOutput
) {
782 /* Assumption : ip, anchor, ml and ref must be set correctly */
783 size_t const ll
= (size_t)(ip
- anchor
);
784 size_t const ll_addbytes
= (ll
+ 240) / 255;
785 size_t const ll_totalCost
= 1 + ll_addbytes
+ ll
;
786 BYTE
*const maxLitPos
= oend
- 3; /* 2 for offset, 1 for token */
787 DEBUGLOG(6, "Last sequence overflowing");
788 op
= optr
; /* restore correct out pointer */
789 if (op
+ ll_totalCost
<= maxLitPos
) {
790 /* ll validated; now adjust match length */
791 size_t const bytesLeftForMl
= (size_t)(maxLitPos
- (op
+ ll_totalCost
));
792 size_t const maxMlSize
= MINMATCH
+ (ML_MASK
- 1) + (bytesLeftForMl
* 255);
793 assert(maxMlSize
< INT_MAX
);
795 if ((size_t)ml
> maxMlSize
) ml
= (int)maxMlSize
;
796 if ((oend
+ LASTLITERALS
) - (op
+ ll_totalCost
+ 2) - 1 + ml
>= MFLIMIT
) {
797 LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ref
, notLimited
, oend
);
802 /* compression failed */
807 static int LZ4HC_compress_optimal(LZ4HC_CCtx_internal
*ctx
,
808 const char *const src
, char *dst
,
809 int *srcSizePtr
, int dstCapacity
,
810 int const nbSearches
, size_t sufficient_len
,
811 const limitedOutput_directive limit
, int const fullUpdate
,
812 const dictCtx_directive dict
,
813 HCfavor_e favorDecSpeed
);
816 LZ4_FORCE_INLINE
int LZ4HC_compress_generic_internal(
817 LZ4HC_CCtx_internal
*const ctx
,
818 const char *const src
,
820 int *const srcSizePtr
,
821 int const dstCapacity
,
823 const limitedOutput_directive limit
,
824 const dictCtx_directive dict
826 typedef enum { lz4hc
, lz4opt
} lz4hc_strat_e
;
832 static const cParams_t clTable
[LZ4HC_CLEVEL_MAX
+ 1] = {
833 { lz4hc
, 2, 16 }, /* 0, unused */
834 { lz4hc
, 2, 16 }, /* 1, unused */
835 { lz4hc
, 2, 16 }, /* 2, unused */
836 { lz4hc
, 4, 16 }, /* 3 */
837 { lz4hc
, 8, 16 }, /* 4 */
838 { lz4hc
, 16, 16 }, /* 5 */
839 { lz4hc
, 32, 16 }, /* 6 */
840 { lz4hc
, 64, 16 }, /* 7 */
841 { lz4hc
, 128, 16 }, /* 8 */
842 { lz4hc
, 256, 16 }, /* 9 */
843 { lz4opt
, 96, 64 }, /*10==LZ4HC_CLEVEL_OPT_MIN*/
844 { lz4opt
, 512, 128 }, /*11 */
845 { lz4opt
, 16384, LZ4_OPT_NUM
}, /* 12==LZ4HC_CLEVEL_MAX */
848 DEBUGLOG(4, "LZ4HC_compress_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",
849 ctx
, src
, *srcSizePtr
, limit
);
851 if (limit
== fillOutput
&& dstCapacity
< 1) return 0; /* Impossible to store anything */
852 if ((U32
)*srcSizePtr
> (U32
)LZ4_MAX_INPUT_SIZE
) return 0; /* Unsupported input size (too large or negative) */
854 ctx
->end
+= *srcSizePtr
;
855 if (cLevel
< 1) cLevel
= LZ4HC_CLEVEL_DEFAULT
; /* note : convention is different from lz4frame, maybe something to review */
856 cLevel
= MIN(LZ4HC_CLEVEL_MAX
, cLevel
);
858 cParams_t
const cParam
= clTable
[cLevel
];
859 HCfavor_e
const favor
= ctx
->favorDecSpeed
? favorDecompressionSpeed
: favorCompressionRatio
;
862 if (cParam
.strat
== lz4hc
) {
863 result
= LZ4HC_compress_hashChain(ctx
,
864 src
, dst
, srcSizePtr
, dstCapacity
,
865 cParam
.nbSearches
, limit
, dict
);
867 assert(cParam
.strat
== lz4opt
);
868 result
= LZ4HC_compress_optimal(ctx
,
869 src
, dst
, srcSizePtr
, dstCapacity
,
870 cParam
.nbSearches
, cParam
.targetLength
, limit
,
871 cLevel
== LZ4HC_CLEVEL_MAX
, /* ultra mode */
874 if (result
<= 0) ctx
->dirty
= 1;
879 static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal
*ctxPtr
, const BYTE
*newBlock
);
882 LZ4HC_compress_generic_noDictCtx(
883 LZ4HC_CCtx_internal
*const ctx
,
884 const char *const src
,
886 int *const srcSizePtr
,
887 int const dstCapacity
,
889 limitedOutput_directive limit
891 assert(ctx
->dictCtx
== NULL
);
892 return LZ4HC_compress_generic_internal(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
, noDictCtx
);
896 LZ4HC_compress_generic_dictCtx(
897 LZ4HC_CCtx_internal
*const ctx
,
898 const char *const src
,
900 int *const srcSizePtr
,
901 int const dstCapacity
,
903 limitedOutput_directive limit
905 const size_t position
= (size_t)(ctx
->end
- ctx
->base
) - ctx
->lowLimit
;
906 assert(ctx
->dictCtx
!= NULL
);
907 if (position
>= 64 KB
) {
909 return LZ4HC_compress_generic_noDictCtx(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
);
910 } else if (position
== 0 && *srcSizePtr
> 4 KB
) {
911 memcpy(ctx
, ctx
->dictCtx
, sizeof(LZ4HC_CCtx_internal
));
912 LZ4HC_setExternalDict(ctx
, (const BYTE
*)src
);
913 ctx
->compressionLevel
= (short)cLevel
;
914 return LZ4HC_compress_generic_noDictCtx(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
);
916 return LZ4HC_compress_generic_internal(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
, usingDictCtxHc
);
921 LZ4HC_compress_generic(
922 LZ4HC_CCtx_internal
*const ctx
,
923 const char *const src
,
925 int *const srcSizePtr
,
926 int const dstCapacity
,
928 limitedOutput_directive limit
930 if (ctx
->dictCtx
== NULL
) {
931 return LZ4HC_compress_generic_noDictCtx(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
);
933 return LZ4HC_compress_generic_dictCtx(ctx
, src
, dst
, srcSizePtr
, dstCapacity
, cLevel
, limit
);
938 int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t
); }
940 #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :
941 * it reports an aligment of 8-bytes,
942 * while actually aligning LZ4_streamHC_t on 4 bytes. */
943 static size_t LZ4_streamHC_t_alignment(void) {
944 typedef struct { char c
; LZ4_streamHC_t t
; } t_a
;
945 return sizeof(t_a
) - sizeof(LZ4_streamHC_t
);
949 /* state is presumed correctly initialized,
950 * in which case its size and alignment have already been validate */
951 int LZ4_compress_HC_extStateHC_fastReset(void *state
, const char *src
, char *dst
, int srcSize
, int dstCapacity
, int compressionLevel
) {
952 LZ4HC_CCtx_internal
*const ctx
= &((LZ4_streamHC_t
*)state
)->internal_donotuse
;
953 #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :
954 * it reports an aligment of 8-bytes,
955 * while actually aligning LZ4_streamHC_t on 4 bytes. */
956 assert(((size_t)state
& (LZ4_streamHC_t_alignment() - 1)) == 0); /* check alignment */
958 if (((size_t)(state
) & (sizeof(void *) -1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
959 LZ4_resetStreamHC_fast((LZ4_streamHC_t
*)state
, compressionLevel
);
960 LZ4HC_init_internal(ctx
, (const BYTE
*)src
);
961 if (dstCapacity
< LZ4_compressBound(srcSize
))
962 return LZ4HC_compress_generic(ctx
, src
, dst
, &srcSize
, dstCapacity
, compressionLevel
, limitedOutput
);
964 return LZ4HC_compress_generic(ctx
, src
, dst
, &srcSize
, dstCapacity
, compressionLevel
, notLimited
);
967 int LZ4_compress_HC_extStateHC(void *state
, const char *src
, char *dst
, int srcSize
, int dstCapacity
, int compressionLevel
) {
968 LZ4_streamHC_t
*const ctx
= LZ4_initStreamHC(state
, sizeof(*ctx
));
969 if (ctx
== NULL
) return 0; /* init failure */
970 return LZ4_compress_HC_extStateHC_fastReset(state
, src
, dst
, srcSize
, dstCapacity
, compressionLevel
);
973 int LZ4_compress_HC(const char *src
, char *dst
, int srcSize
, int dstCapacity
, int compressionLevel
) {
974 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
975 LZ4_streamHC_t
*const statePtr
= (LZ4_streamHC_t
*)ALLOC(sizeof(LZ4_streamHC_t
));
977 LZ4_streamHC_t state
;
978 LZ4_streamHC_t
*const statePtr
= &state
;
980 int const cSize
= LZ4_compress_HC_extStateHC(statePtr
, src
, dst
, srcSize
, dstCapacity
, compressionLevel
);
981 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
987 /* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */
988 int LZ4_compress_HC_destSize(void *state
, const char *src
, char *dst
, int *sourceSizePtr
, int targetDestSize
, int cLevel
) {
989 LZ4_streamHC_t
*const ctx
= LZ4_initStreamHC(state
, sizeof(*ctx
));
990 if (ctx
== NULL
) return 0; /* init failure */
991 LZ4HC_init_internal(&ctx
->internal_donotuse
, (const BYTE
*) src
);
992 LZ4_setCompressionLevel(ctx
, cLevel
);
993 return LZ4HC_compress_generic(&ctx
->internal_donotuse
, src
, dst
, sourceSizePtr
, targetDestSize
, cLevel
, fillOutput
);
998 /**************************************
999 * Streaming Functions
1000 **************************************/
1002 LZ4_streamHC_t
*LZ4_createStreamHC(void) {
1003 LZ4_streamHC_t
*const state
= (LZ4_streamHC_t
*)ALLOC(sizeof(LZ4_streamHC_t
));
1004 if (LZ4_initStreamHC(state
, sizeof(*state
)) == NULL
) {
1011 int LZ4_freeStreamHC(LZ4_streamHC_t
*LZ4_streamHCPtr
) {
1012 DEBUGLOG(4, "LZ4_freeStreamHC(%p)", LZ4_streamHCPtr
);
1013 if (!LZ4_streamHCPtr
) return 0; /* support free on NULL */
1014 FREEMEM(LZ4_streamHCPtr
);
1018 // Skip AddressSanitizer which breaks compilation strangely on
1019 // lz4/lz4hc.c: error: writing 2 bytes into a region of size 1 [-Werror=stringop-overflow=]
1020 // | LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = 0;
1021 ATTRIBUTE_NO_SANITIZE_ADDRESS
1022 LZ4_streamHC_t
*LZ4_initStreamHC(void *buffer
, size_t size
) {
1023 LZ4_streamHC_t
*const LZ4_streamHCPtr
= (LZ4_streamHC_t
*)buffer
;
1024 if (buffer
== NULL
) return NULL
;
1025 if (size
< sizeof(LZ4_streamHC_t
)) return NULL
;
1026 #ifndef _MSC_VER /* for some reason, Visual fails the aligment test on 32-bit x86 :
1027 * it reports an aligment of 8-bytes,
1028 * while actually aligning LZ4_streamHC_t on 4 bytes. */
1029 if (((size_t)buffer
) & (LZ4_streamHC_t_alignment() - 1)) return NULL
; /* alignment check */
1031 /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
1032 LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal
) <= LZ4_STREAMHCSIZE
);
1033 DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", LZ4_streamHCPtr
, (unsigned)size
);
1034 /* end-base will trigger a clearTable on starting compression */
1035 LZ4_streamHCPtr
->internal_donotuse
.end
= (const BYTE
*)(ptrdiff_t) -1;
1036 LZ4_streamHCPtr
->internal_donotuse
.base
= NULL
;
1037 LZ4_streamHCPtr
->internal_donotuse
.dictCtx
= NULL
;
1038 LZ4_streamHCPtr
->internal_donotuse
.favorDecSpeed
= 0;
1039 LZ4_streamHCPtr
->internal_donotuse
.dirty
= 0;
1040 LZ4_setCompressionLevel(LZ4_streamHCPtr
, LZ4HC_CLEVEL_DEFAULT
);
1041 return LZ4_streamHCPtr
;
1045 void LZ4_resetStreamHC(LZ4_streamHC_t
*LZ4_streamHCPtr
, int compressionLevel
) {
1046 LZ4_initStreamHC(LZ4_streamHCPtr
, sizeof(*LZ4_streamHCPtr
));
1047 LZ4_setCompressionLevel(LZ4_streamHCPtr
, compressionLevel
);
1050 void LZ4_resetStreamHC_fast(LZ4_streamHC_t
*LZ4_streamHCPtr
, int compressionLevel
) {
1051 DEBUGLOG(4, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr
, compressionLevel
);
1052 if (LZ4_streamHCPtr
->internal_donotuse
.dirty
) {
1053 LZ4_initStreamHC(LZ4_streamHCPtr
, sizeof(*LZ4_streamHCPtr
));
1055 /* preserve end - base : can trigger clearTable's threshold */
1056 LZ4_streamHCPtr
->internal_donotuse
.end
-= (uptrval
)LZ4_streamHCPtr
->internal_donotuse
.base
;
1057 LZ4_streamHCPtr
->internal_donotuse
.base
= NULL
;
1058 LZ4_streamHCPtr
->internal_donotuse
.dictCtx
= NULL
;
1060 LZ4_setCompressionLevel(LZ4_streamHCPtr
, compressionLevel
);
1063 void LZ4_setCompressionLevel(LZ4_streamHC_t
*LZ4_streamHCPtr
, int compressionLevel
) {
1064 DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr
, compressionLevel
);
1065 if (compressionLevel
< 1) compressionLevel
= LZ4HC_CLEVEL_DEFAULT
;
1066 if (compressionLevel
> LZ4HC_CLEVEL_MAX
) compressionLevel
= LZ4HC_CLEVEL_MAX
;
1067 LZ4_streamHCPtr
->internal_donotuse
.compressionLevel
= (short)compressionLevel
;
1070 void LZ4_favorDecompressionSpeed(LZ4_streamHC_t
*LZ4_streamHCPtr
, int favor
) {
1071 LZ4_streamHCPtr
->internal_donotuse
.favorDecSpeed
= (favor
!= 0);
1074 /* LZ4_loadDictHC() :
1075 * LZ4_streamHCPtr is presumed properly initialized */
1076 int LZ4_loadDictHC(LZ4_streamHC_t
*LZ4_streamHCPtr
,
1077 const char *dictionary
, int dictSize
) {
1078 LZ4HC_CCtx_internal
*const ctxPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
1079 DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d)", LZ4_streamHCPtr
, dictionary
, dictSize
);
1080 assert(LZ4_streamHCPtr
!= NULL
);
1081 if (dictSize
> 64 KB
) {
1082 dictionary
+= (size_t)dictSize
- 64 KB
;
1085 /* need a full initialization, there are bad side-effects when using resetFast() */
1087 int const cLevel
= ctxPtr
->compressionLevel
;
1088 LZ4_initStreamHC(LZ4_streamHCPtr
, sizeof(*LZ4_streamHCPtr
));
1089 LZ4_setCompressionLevel(LZ4_streamHCPtr
, cLevel
);
1091 LZ4HC_init_internal(ctxPtr
, (const BYTE
*)dictionary
);
1092 ctxPtr
->end
= (const BYTE
*)dictionary
+ dictSize
;
1093 if (dictSize
>= 4) LZ4HC_Insert(ctxPtr
, ctxPtr
->end
- 3);
1097 void LZ4_attach_HC_dictionary(LZ4_streamHC_t
*working_stream
, const LZ4_streamHC_t
*dictionary_stream
) {
1098 working_stream
->internal_donotuse
.dictCtx
= dictionary_stream
!= NULL
? &(dictionary_stream
->internal_donotuse
) : NULL
;
1103 static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal
*ctxPtr
, const BYTE
*newBlock
) {
1104 DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr
, newBlock
);
1105 if (ctxPtr
->end
>= ctxPtr
->base
+ ctxPtr
->dictLimit
+ 4)
1106 LZ4HC_Insert(ctxPtr
, ctxPtr
->end
- 3); /* Referencing remaining dictionary content */
1108 /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
1109 ctxPtr
->lowLimit
= ctxPtr
->dictLimit
;
1110 ctxPtr
->dictLimit
= (U32
)(ctxPtr
->end
- ctxPtr
->base
);
1111 ctxPtr
->dictBase
= ctxPtr
->base
;
1112 ctxPtr
->base
= newBlock
- ctxPtr
->dictLimit
;
1113 ctxPtr
->end
= newBlock
;
1114 ctxPtr
->nextToUpdate
= ctxPtr
->dictLimit
; /* match referencing will resume from there */
1116 /* cannot reference an extDict and a dictCtx at the same time */
1117 ctxPtr
->dictCtx
= NULL
;
1120 static int LZ4_compressHC_continue_generic(LZ4_streamHC_t
*LZ4_streamHCPtr
,
1121 const char *src
, char *dst
,
1122 int *srcSizePtr
, int dstCapacity
,
1123 limitedOutput_directive limit
) {
1124 LZ4HC_CCtx_internal
*const ctxPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
1125 DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",
1126 LZ4_streamHCPtr
, src
, *srcSizePtr
, limit
);
1127 assert(ctxPtr
!= NULL
);
1128 /* auto-init if forgotten */
1129 if (ctxPtr
->base
== NULL
) LZ4HC_init_internal(ctxPtr
, (const BYTE
*) src
);
1131 /* Check overflow */
1132 if ((size_t)(ctxPtr
->end
- ctxPtr
->base
) > 2 GB
) {
1133 size_t dictSize
= (size_t)(ctxPtr
->end
- ctxPtr
->base
) - ctxPtr
->dictLimit
;
1134 if (dictSize
> 64 KB
) dictSize
= 64 KB
;
1135 LZ4_loadDictHC(LZ4_streamHCPtr
, (const char *)(ctxPtr
->end
) - dictSize
, (int)dictSize
);
1138 /* Check if blocks follow each other */
1139 if ((const BYTE
*)src
!= ctxPtr
->end
)
1140 LZ4HC_setExternalDict(ctxPtr
, (const BYTE
*)src
);
1142 /* Check overlapping input/dictionary space */
1144 const BYTE
*sourceEnd
= (const BYTE
*) src
+ *srcSizePtr
;
1145 const BYTE
*const dictBegin
= ctxPtr
->dictBase
+ ctxPtr
->lowLimit
;
1146 const BYTE
*const dictEnd
= ctxPtr
->dictBase
+ ctxPtr
->dictLimit
;
1147 if ((sourceEnd
> dictBegin
) && ((const BYTE
*)src
< dictEnd
)) {
1148 if (sourceEnd
> dictEnd
) sourceEnd
= dictEnd
;
1149 ctxPtr
->lowLimit
= (U32
)(sourceEnd
- ctxPtr
->dictBase
);
1150 if (ctxPtr
->dictLimit
- ctxPtr
->lowLimit
< 4) ctxPtr
->lowLimit
= ctxPtr
->dictLimit
;
1154 return LZ4HC_compress_generic(ctxPtr
, src
, dst
, srcSizePtr
, dstCapacity
, ctxPtr
->compressionLevel
, limit
);
1157 int LZ4_compress_HC_continue(LZ4_streamHC_t
*LZ4_streamHCPtr
, const char *src
, char *dst
, int srcSize
, int dstCapacity
) {
1158 if (dstCapacity
< LZ4_compressBound(srcSize
))
1159 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr
, src
, dst
, &srcSize
, dstCapacity
, limitedOutput
);
1161 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr
, src
, dst
, &srcSize
, dstCapacity
, notLimited
);
1164 int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t
*LZ4_streamHCPtr
, const char *src
, char *dst
, int *srcSizePtr
, int targetDestSize
) {
1165 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr
, src
, dst
, srcSizePtr
, targetDestSize
, fillOutput
);
1170 /* dictionary saving */
1172 int LZ4_saveDictHC(LZ4_streamHC_t
*LZ4_streamHCPtr
, char *safeBuffer
, int dictSize
) {
1173 LZ4HC_CCtx_internal
*const streamPtr
= &LZ4_streamHCPtr
->internal_donotuse
;
1174 int const prefixSize
= (int)(streamPtr
->end
- (streamPtr
->base
+ streamPtr
->dictLimit
));
1175 DEBUGLOG(4, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr
, safeBuffer
, dictSize
);
1176 if (dictSize
> 64 KB
) dictSize
= 64 KB
;
1177 if (dictSize
< 4) dictSize
= 0;
1178 if (dictSize
> prefixSize
) dictSize
= prefixSize
;
1179 memmove(safeBuffer
, streamPtr
->end
- dictSize
, dictSize
);
1181 U32
const endIndex
= (U32
)(streamPtr
->end
- streamPtr
->base
);
1182 streamPtr
->end
= (const BYTE
*)safeBuffer
+ dictSize
;
1183 streamPtr
->base
= streamPtr
->end
- endIndex
;
1184 streamPtr
->dictLimit
= endIndex
- (U32
)dictSize
;
1185 streamPtr
->lowLimit
= endIndex
- (U32
)dictSize
;
1186 if (streamPtr
->nextToUpdate
< streamPtr
->dictLimit
) streamPtr
->nextToUpdate
= streamPtr
->dictLimit
;
1192 /***************************************************
1193 * Deprecated Functions
1194 ***************************************************/
1196 /* These functions currently generate deprecation warnings */
1198 /* Wrappers for deprecated compression functions */
1199 int LZ4_compressHC(const char *src
, char *dst
, int srcSize
) { return LZ4_compress_HC(src
, dst
, srcSize
, LZ4_compressBound(srcSize
), 0); }
1200 int LZ4_compressHC_limitedOutput(const char *src
, char *dst
, int srcSize
, int maxDstSize
) { return LZ4_compress_HC(src
, dst
, srcSize
, maxDstSize
, 0); }
1201 int LZ4_compressHC2(const char *src
, char *dst
, int srcSize
, int cLevel
) { return LZ4_compress_HC(src
, dst
, srcSize
, LZ4_compressBound(srcSize
), cLevel
); }
1202 int LZ4_compressHC2_limitedOutput(const char *src
, char *dst
, int srcSize
, int maxDstSize
, int cLevel
) { return LZ4_compress_HC(src
, dst
, srcSize
, maxDstSize
, cLevel
); }
1203 int LZ4_compressHC_withStateHC(void *state
, const char *src
, char *dst
, int srcSize
) { return LZ4_compress_HC_extStateHC(state
, src
, dst
, srcSize
, LZ4_compressBound(srcSize
), 0); }
1204 int LZ4_compressHC_limitedOutput_withStateHC(void *state
, const char *src
, char *dst
, int srcSize
, int maxDstSize
) { return LZ4_compress_HC_extStateHC(state
, src
, dst
, srcSize
, maxDstSize
, 0); }
1205 int LZ4_compressHC2_withStateHC(void *state
, const char *src
, char *dst
, int srcSize
, int cLevel
) { return LZ4_compress_HC_extStateHC(state
, src
, dst
, srcSize
, LZ4_compressBound(srcSize
), cLevel
); }
1206 int LZ4_compressHC2_limitedOutput_withStateHC(void *state
, const char *src
, char *dst
, int srcSize
, int maxDstSize
, int cLevel
) { return LZ4_compress_HC_extStateHC(state
, src
, dst
, srcSize
, maxDstSize
, cLevel
); }
1207 int LZ4_compressHC_continue(LZ4_streamHC_t
*ctx
, const char *src
, char *dst
, int srcSize
) { return LZ4_compress_HC_continue(ctx
, src
, dst
, srcSize
, LZ4_compressBound(srcSize
)); }
1208 int LZ4_compressHC_limitedOutput_continue(LZ4_streamHC_t
*ctx
, const char *src
, char *dst
, int srcSize
, int maxDstSize
) { return LZ4_compress_HC_continue(ctx
, src
, dst
, srcSize
, maxDstSize
); }
1211 /* Deprecated streaming functions */
1212 int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE
; }
1214 /* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t)
1215 * @return : 0 on success, !=0 if error */
1216 int LZ4_resetStreamStateHC(void *state
, char *inputBuffer
) {
1217 LZ4_streamHC_t
*const hc4
= LZ4_initStreamHC(state
, sizeof(*hc4
));
1218 if (hc4
== NULL
) return 1; /* init failed */
1219 LZ4HC_init_internal(&hc4
->internal_donotuse
, (const BYTE
*)inputBuffer
);
1223 void *LZ4_createHC(const char *inputBuffer
) {
1224 LZ4_streamHC_t
*const hc4
= LZ4_createStreamHC();
1225 if (hc4
== NULL
) return NULL
; /* not enough memory */
1226 LZ4HC_init_internal(&hc4
->internal_donotuse
, (const BYTE
*)inputBuffer
);
1230 int LZ4_freeHC(void *LZ4HC_Data
) {
1231 if (!LZ4HC_Data
) return 0; /* support free on NULL */
1232 FREEMEM(LZ4HC_Data
);
1236 int LZ4_compressHC2_continue(void *LZ4HC_Data
, const char *src
, char *dst
, int srcSize
, int cLevel
) {
1237 return LZ4HC_compress_generic(&((LZ4_streamHC_t
*)LZ4HC_Data
)->internal_donotuse
, src
, dst
, &srcSize
, 0, cLevel
, notLimited
);
1240 int LZ4_compressHC2_limitedOutput_continue(void *LZ4HC_Data
, const char *src
, char *dst
, int srcSize
, int dstCapacity
, int cLevel
) {
1241 return LZ4HC_compress_generic(&((LZ4_streamHC_t
*)LZ4HC_Data
)->internal_donotuse
, src
, dst
, &srcSize
, dstCapacity
, cLevel
, limitedOutput
);
1244 char *LZ4_slideInputBufferHC(void *LZ4HC_Data
) {
1245 LZ4_streamHC_t
*ctx
= (LZ4_streamHC_t
*)LZ4HC_Data
;
1246 const BYTE
*bufferStart
= ctx
->internal_donotuse
.base
+ ctx
->internal_donotuse
.lowLimit
;
1247 LZ4_resetStreamHC_fast(ctx
, ctx
->internal_donotuse
.compressionLevel
);
1248 /* avoid const char * -> char * conversion warning :( */
1249 return (char *)(uptrval
)bufferStart
;
1253 /* ================================================
1254 * LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX])
1255 * ===============================================*/
1263 /* price in bytes */
1264 LZ4_FORCE_INLINE
int LZ4HC_literalsPrice(int const litlen
) {
1266 assert(litlen
>= 0);
1267 if (litlen
>= (int)RUN_MASK
)
1268 price
+= 1 + ((litlen
- (int)RUN_MASK
) / 255);
1273 /* requires mlen >= MINMATCH */
1274 LZ4_FORCE_INLINE
int LZ4HC_sequencePrice(int litlen
, int mlen
) {
1275 int price
= 1 + 2 ; /* token + 16-bit offset */
1276 assert(litlen
>= 0);
1277 assert(mlen
>= MINMATCH
);
1279 price
+= LZ4HC_literalsPrice(litlen
);
1281 if (mlen
>= (int)(ML_MASK
+ MINMATCH
))
1282 price
+= 1 + ((mlen
- (int)(ML_MASK
+ MINMATCH
)) / 255);
1293 LZ4_FORCE_INLINE LZ4HC_match_t
1294 LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal
*const ctx
,
1295 const BYTE
*ip
, const BYTE
*const iHighLimit
,
1296 int minLen
, int nbSearches
,
1297 const dictCtx_directive dict
,
1298 const HCfavor_e favorDecSpeed
) {
1299 LZ4HC_match_t match
= { 0, 0 };
1300 const BYTE
*matchPtr
= NULL
;
1301 /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
1302 * but this won't be the case here, as we define iLowLimit==ip,
1303 * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
1304 int matchLength
= LZ4HC_InsertAndGetWiderMatch(ctx
, ip
, ip
, iHighLimit
, minLen
, &matchPtr
, &ip
, nbSearches
, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict
, favorDecSpeed
);
1305 if (matchLength
<= minLen
) return match
;
1306 if (favorDecSpeed
) {
1307 if ((matchLength
> 18) & (matchLength
<= 36)) matchLength
= 18; /* favor shortcut */
1309 match
.len
= matchLength
;
1310 match
.off
= (int)(ip
- matchPtr
);
1315 static int LZ4HC_compress_optimal(LZ4HC_CCtx_internal
*ctx
,
1316 const char *const src
,
1320 int const nbSearches
,
1321 size_t sufficient_len
,
1322 const limitedOutput_directive limit
,
1323 int const fullUpdate
,
1324 const dictCtx_directive dict
,
1325 const HCfavor_e favorDecSpeed
) {
1327 #define TRAILING_LITERALS 3
1328 #ifdef LZ4HC_HEAPMODE
1329 LZ4HC_optimal_t
*const opt
= (LZ4HC_optimal_t
*)malloc(sizeof(LZ4HC_optimal_t
) * (LZ4_OPT_NUM
+ TRAILING_LITERALS
));
1331 LZ4HC_optimal_t opt
[LZ4_OPT_NUM
+ TRAILING_LITERALS
]; /* ~64 KB, which is a bit large for stack... */
1334 const BYTE
*ip
= (const BYTE
*) src
;
1335 const BYTE
*anchor
= ip
;
1336 const BYTE
*const iend
= ip
+ *srcSizePtr
;
1337 const BYTE
*const mflimit
= iend
- MFLIMIT
;
1338 const BYTE
*const matchlimit
= iend
- LASTLITERALS
;
1339 BYTE
*op
= (BYTE
*) dst
;
1340 BYTE
*opSaved
= (BYTE
*) dst
;
1341 BYTE
*oend
= op
+ dstCapacity
;
1342 int ovml
= MINMATCH
; /* overflow - last sequence */
1343 const BYTE
*ovref
= NULL
;
1346 #ifdef LZ4HC_HEAPMODE
1347 if (opt
== NULL
) goto _return_label
;
1349 DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst
, (unsigned)dstCapacity
);
1351 if (limit
== fillOutput
) oend
-= LASTLITERALS
; /* Hack for support LZ4 format restriction */
1352 if (sufficient_len
>= LZ4_OPT_NUM
) sufficient_len
= LZ4_OPT_NUM
- 1;
1355 while (ip
<= mflimit
) {
1356 int const llen
= (int)(ip
- anchor
);
1357 int best_mlen
, best_off
;
1358 int cur
, last_match_pos
= 0;
1360 LZ4HC_match_t
const firstMatch
= LZ4HC_FindLongerMatch(ctx
, ip
, matchlimit
, MINMATCH
- 1, nbSearches
, dict
, favorDecSpeed
);
1361 if (firstMatch
.len
== 0) { ip
++; continue; }
1363 if ((size_t)firstMatch
.len
> sufficient_len
) {
1364 /* good enough solution : immediate encoding */
1365 int const firstML
= firstMatch
.len
;
1366 const BYTE
*const matchPos
= ip
- firstMatch
.off
;
1368 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), firstML
, matchPos
, limit
, oend
)) { /* updates ip, op and anchor */
1371 goto _dest_overflow
;
1376 /* set prices for first positions (literals) */
1379 for (rPos
= 0 ; rPos
< MINMATCH
; rPos
++) {
1380 int const cost
= LZ4HC_literalsPrice(llen
+ rPos
);
1383 opt
[rPos
].litlen
= llen
+ rPos
;
1384 opt
[rPos
].price
= cost
;
1385 DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",
1386 rPos
, cost
, opt
[rPos
].litlen
);
1389 /* set prices using initial match */
1391 int mlen
= MINMATCH
;
1392 int const matchML
= firstMatch
.len
; /* necessarily < sufficient_len < LZ4_OPT_NUM */
1393 int const offset
= firstMatch
.off
;
1394 assert(matchML
< LZ4_OPT_NUM
);
1395 for (; mlen
<= matchML
; mlen
++) {
1396 int const cost
= LZ4HC_sequencePrice(llen
, mlen
);
1397 opt
[mlen
].mlen
= mlen
;
1398 opt
[mlen
].off
= offset
;
1399 opt
[mlen
].litlen
= llen
;
1400 opt
[mlen
].price
= cost
;
1401 DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i) -- initial setup",
1405 last_match_pos
= firstMatch
.len
;
1408 for (addLit
= 1; addLit
<= TRAILING_LITERALS
; addLit
++) {
1409 opt
[last_match_pos
+ addLit
].mlen
= 1; /* literal */
1410 opt
[last_match_pos
+ addLit
].off
= 0;
1411 opt
[last_match_pos
+ addLit
].litlen
= addLit
;
1412 opt
[last_match_pos
+ addLit
].price
= opt
[last_match_pos
].price
+ LZ4HC_literalsPrice(addLit
);
1413 DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",
1414 last_match_pos
+ addLit
, opt
[last_match_pos
+ addLit
].price
, addLit
);
1418 /* check further positions */
1419 for (cur
= 1; cur
< last_match_pos
; cur
++) {
1420 const BYTE
*const curPtr
= ip
+ cur
;
1421 LZ4HC_match_t newMatch
;
1423 if (curPtr
> mflimit
) break;
1424 DEBUGLOG(7, "rPos:%u[%u] vs [%u]%u",
1425 cur
, opt
[cur
].price
, opt
[cur
+ 1].price
, cur
+ 1);
1427 /* not useful to search here if next position has same (or lower) cost */
1428 if ((opt
[cur
+ 1].price
<= opt
[cur
].price
)
1429 /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */
1430 && (opt
[cur
+ MINMATCH
].price
< opt
[cur
].price
+ 3/*min seq price*/))
1433 /* not useful to search here if next position has same (or lower) cost */
1434 if (opt
[cur
+ 1].price
<= opt
[cur
].price
) continue;
1437 DEBUGLOG(7, "search at rPos:%u", cur
);
1439 newMatch
= LZ4HC_FindLongerMatch(ctx
, curPtr
, matchlimit
, MINMATCH
- 1, nbSearches
, dict
, favorDecSpeed
);
1441 /* only test matches of minimum length; slightly faster, but misses a few bytes */
1442 newMatch
= LZ4HC_FindLongerMatch(ctx
, curPtr
, matchlimit
, last_match_pos
- cur
, nbSearches
, dict
, favorDecSpeed
);
1443 if (!newMatch
.len
) continue;
1445 if (((size_t)newMatch
.len
> sufficient_len
)
1446 || (newMatch
.len
+ cur
>= LZ4_OPT_NUM
)) {
1447 /* immediate encoding */
1448 best_mlen
= newMatch
.len
;
1449 best_off
= newMatch
.off
;
1450 last_match_pos
= cur
+ 1;
1454 /* before match : set price with literals at beginning */
1456 int const baseLitlen
= opt
[cur
].litlen
;
1458 for (litlen
= 1; litlen
< MINMATCH
; litlen
++) {
1459 int const price
= opt
[cur
].price
- LZ4HC_literalsPrice(baseLitlen
) + LZ4HC_literalsPrice(baseLitlen
+ litlen
);
1460 int const pos
= cur
+ litlen
;
1461 if (price
< opt
[pos
].price
) {
1462 opt
[pos
].mlen
= 1; /* literal */
1464 opt
[pos
].litlen
= baseLitlen
+ litlen
;
1465 opt
[pos
].price
= price
;
1466 DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)",
1467 pos
, price
, opt
[pos
].litlen
);
1472 /* set prices using match at position = cur */
1474 int const matchML
= newMatch
.len
;
1477 assert(cur
+ newMatch
.len
< LZ4_OPT_NUM
);
1478 for (; ml
<= matchML
; ml
++) {
1479 int const pos
= cur
+ ml
;
1480 int const offset
= newMatch
.off
;
1483 DEBUGLOG(7, "testing price rPos %i (last_match_pos=%i)",
1484 pos
, last_match_pos
);
1485 if (opt
[cur
].mlen
== 1) {
1486 ll
= opt
[cur
].litlen
;
1487 price
= ((cur
> ll
) ? opt
[cur
- ll
].price
: 0)
1488 + LZ4HC_sequencePrice(ll
, ml
);
1491 price
= opt
[cur
].price
+ LZ4HC_sequencePrice(0, ml
);
1494 assert((U32
)favorDecSpeed
<= 1);
1495 if (pos
> last_match_pos
+ TRAILING_LITERALS
1496 || price
<= opt
[pos
].price
- (int)favorDecSpeed
) {
1497 DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i)",
1499 assert(pos
< LZ4_OPT_NUM
);
1500 if ((ml
== matchML
) /* last pos of last match */
1501 && (last_match_pos
< pos
))
1502 last_match_pos
= pos
;
1504 opt
[pos
].off
= offset
;
1505 opt
[pos
].litlen
= ll
;
1506 opt
[pos
].price
= price
;
1510 /* complete following positions with literals */
1513 for (addLit
= 1; addLit
<= TRAILING_LITERALS
; addLit
++) {
1514 opt
[last_match_pos
+ addLit
].mlen
= 1; /* literal */
1515 opt
[last_match_pos
+ addLit
].off
= 0;
1516 opt
[last_match_pos
+ addLit
].litlen
= addLit
;
1517 opt
[last_match_pos
+ addLit
].price
= opt
[last_match_pos
].price
+ LZ4HC_literalsPrice(addLit
);
1518 DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", last_match_pos
+ addLit
, opt
[last_match_pos
+ addLit
].price
, addLit
);
1521 } /* for (cur = 1; cur <= last_match_pos; cur++) */
1523 assert(last_match_pos
< LZ4_OPT_NUM
+ TRAILING_LITERALS
);
1524 best_mlen
= opt
[last_match_pos
].mlen
;
1525 best_off
= opt
[last_match_pos
].off
;
1526 cur
= last_match_pos
- best_mlen
;
1528 encode
: /* cur, last_match_pos, best_mlen, best_off must be set */
1529 assert(cur
< LZ4_OPT_NUM
);
1530 assert(last_match_pos
>= 1); /* == 1 when only one candidate */
1531 DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos
);
1533 int candidate_pos
= cur
;
1534 int selected_matchLength
= best_mlen
;
1535 int selected_offset
= best_off
;
1536 while (1) { /* from end to beginning */
1537 int const next_matchLength
= opt
[candidate_pos
].mlen
; /* can be 1, means literal */
1538 int const next_offset
= opt
[candidate_pos
].off
;
1539 DEBUGLOG(7, "pos %i: sequence length %i", candidate_pos
, selected_matchLength
);
1540 opt
[candidate_pos
].mlen
= selected_matchLength
;
1541 opt
[candidate_pos
].off
= selected_offset
;
1542 selected_matchLength
= next_matchLength
;
1543 selected_offset
= next_offset
;
1544 if (next_matchLength
> candidate_pos
) break; /* last match elected, first match to encode */
1545 assert(next_matchLength
> 0); /* can be 1, means literal */
1546 candidate_pos
-= next_matchLength
;
1550 /* encode all recorded sequences in order */
1552 int rPos
= 0; /* relative position (to ip) */
1553 while (rPos
< last_match_pos
) {
1554 int const ml
= opt
[rPos
].mlen
;
1555 int const offset
= opt
[rPos
].off
;
1556 if (ml
== 1) { ip
++; rPos
++; continue; } /* literal; note: can end up with several literals, in which case, skip them */
1558 assert(ml
>= MINMATCH
);
1559 assert((offset
>= 1) && (offset
<= LZ4_DISTANCE_MAX
));
1561 if (LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ml
, ip
- offset
, limit
, oend
)) { /* updates ip, op and anchor */
1563 ovref
= ip
- offset
;
1564 goto _dest_overflow
;
1568 } /* while (ip <= mflimit) */
1571 /* Encode Last Literals */
1573 size_t lastRunSize
= (size_t)(iend
- anchor
); /* literals */
1574 size_t llAdd
= (lastRunSize
+ 255 - RUN_MASK
) / 255;
1575 size_t const totalSize
= 1 + llAdd
+ lastRunSize
;
1576 if (limit
== fillOutput
) oend
+= LASTLITERALS
; /* restore correct value */
1577 if (limit
&& (op
+ totalSize
> oend
)) {
1578 if (limit
== limitedOutput
) { /* Check output limit */
1582 /* adapt lastRunSize to fill 'dst' */
1583 lastRunSize
= (size_t)(oend
- op
) - 1 /*token*/;
1584 llAdd
= (lastRunSize
+ 256 - RUN_MASK
) / 256;
1585 lastRunSize
-= llAdd
;
1587 DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize
);
1588 ip
= anchor
+ lastRunSize
; /* can be != iend if limit==fillOutput */
1590 if (lastRunSize
>= RUN_MASK
) {
1591 size_t accumulator
= lastRunSize
- RUN_MASK
;
1592 *op
++ = (RUN_MASK
<< ML_BITS
);
1593 for (; accumulator
>= 255 ; accumulator
-= 255) * op
++ = 255;
1594 *op
++ = (BYTE
) accumulator
;
1596 *op
++ = (BYTE
)(lastRunSize
<< ML_BITS
);
1598 memcpy(op
, anchor
, lastRunSize
);
1603 *srcSizePtr
= (int)(((const char *)ip
) - src
);
1604 retval
= (int)((char *)op
- dst
);
1608 if (limit
== fillOutput
) {
1609 /* Assumption : ip, anchor, ovml and ovref must be set correctly */
1610 size_t const ll
= (size_t)(ip
- anchor
);
1611 size_t const ll_addbytes
= (ll
+ 240) / 255;
1612 size_t const ll_totalCost
= 1 + ll_addbytes
+ ll
;
1613 BYTE
*const maxLitPos
= oend
- 3; /* 2 for offset, 1 for token */
1614 DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend
- 1 - opSaved
));
1615 op
= opSaved
; /* restore correct out pointer */
1616 if (op
+ ll_totalCost
<= maxLitPos
) {
1617 /* ll validated; now adjust match length */
1618 size_t const bytesLeftForMl
= (size_t)(maxLitPos
- (op
+ ll_totalCost
));
1619 size_t const maxMlSize
= MINMATCH
+ (ML_MASK
- 1) + (bytesLeftForMl
* 255);
1620 assert(maxMlSize
< INT_MAX
);
1622 if ((size_t)ovml
> maxMlSize
) ovml
= (int)maxMlSize
;
1623 if ((oend
+ LASTLITERALS
) - (op
+ ll_totalCost
+ 2) - 1 + ovml
>= MFLIMIT
) {
1624 DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend
+ LASTLITERALS
) - (op
+ ll_totalCost
+ 2) - 1), ovml
);
1625 DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip
, anchor
);
1626 LZ4HC_encodeSequence(UPDATABLE(ip
, op
, anchor
), ovml
, ovref
, notLimited
, oend
);
1627 DEBUGLOG(6, "After : ip = %p, anchor = %p", ip
, anchor
);
1630 goto _last_literals
;
1633 #ifdef LZ4HC_HEAPMODE