ROOTANA
Loading...
Searching...
No Matches
lz4.cxx
Go to the documentation of this file.
1/*
2 LZ4 - Fast LZ compression algorithm
3 Copyright (C) 2011-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 - LZ4 source repository : https://github.com/Cyan4973/lz4
32 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33*/
34
35
36/**************************************
37* Tuning parameters
38**************************************/
39/*
40 * HEAPMODE :
41 * Select how default compression functions will allocate memory for their hash table,
42 * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
43 */
44#define HEAPMODE 0
45
46/*
47 * ACCELERATION_DEFAULT :
48 * Select "acceleration" for MLZ4_compress_fast() when parameter value <= 0
49 */
50#define ACCELERATION_DEFAULT 1
51
52
53/**************************************
54* CPU Feature Detection
55**************************************/
56/*
57 * MLZ4_FORCE_SW_BITCOUNT
58 * Define this parameter if your target system or compiler does not support hardware bit count
59 */
60#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
61# define MLZ4_FORCE_SW_BITCOUNT
62#endif
63
64
65/**************************************
66* Includes
67**************************************/
68#include "mlz4.h"
69
70
71/**************************************
72* Compiler Options
73**************************************/
74#ifdef _MSC_VER /* Visual Studio */
75# define FORCE_INLINE static __forceinline
76# include <intrin.h>
77# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
78# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
79#else
80# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
81# if defined(__GNUC__) || defined(__clang__)
82# define FORCE_INLINE static inline __attribute__((always_inline))
83# else
84# define FORCE_INLINE static inline
85# endif
86# else
87# define FORCE_INLINE static
88# endif /* __STDC_VERSION__ */
89#endif /* _MSC_VER */
90
91/* MLZ4_GCC_VERSION is defined into lz4.h */
92#if (MLZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
93# define expect(expr,value) (__builtin_expect ((expr),(value)) )
94#else
95# define expect(expr,value) (expr)
96#endif
97
98#define likely(expr) expect((expr) != 0, 1)
99#define unlikely(expr) expect((expr) != 0, 0)
100
101
102/**************************************
103* Memory routines
104**************************************/
105#include <stdlib.h> /* malloc, calloc, free */
106#define ALLOCATOR(n,s) calloc(n,s)
107#define FREEMEM free
108#include <string.h> /* memset, memcpy */
109#define MEM_INIT memset
110
111
112/**************************************
113* Basic Types
114**************************************/
115#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
116# include <stdint.h>
117 typedef uint8_t BYTE;
118 typedef uint16_t U16;
119 typedef uint32_t U32;
120 typedef int32_t S32;
121 typedef uint64_t U64;
122#else
123 typedef unsigned char BYTE;
124 typedef unsigned short U16;
125 typedef unsigned int U32;
126 typedef signed int S32;
127 typedef unsigned long long U64;
128#endif
129
130
131/**************************************
132* Reading and writing into memory
133**************************************/
134#define STEPSIZE sizeof(size_t)
135
136static unsigned MLZ4_64bits(void) { return sizeof(void*)==8; }
137
138static unsigned MLZ4_isLittleEndian(void)
139{
140 const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
141 return one.c[0];
142}
143
144
145static U16 MLZ4_read16(const void* memPtr)
146{
147 U16 val16;
148 memcpy(&val16, memPtr, 2);
149 return val16;
150}
151
152static U16 MLZ4_readLE16(const void* memPtr)
153{
155 {
156 return MLZ4_read16(memPtr);
157 }
158 else
159 {
160 const BYTE* p = (const BYTE*)memPtr;
161 return (U16)((U16)p[0] + (p[1]<<8));
162 }
163}
164
165static void MLZ4_writeLE16(void* memPtr, U16 value)
166{
168 {
169 memcpy(memPtr, &value, 2);
170 }
171 else
172 {
173 BYTE* p = (BYTE*)memPtr;
174 p[0] = (BYTE) value;
175 p[1] = (BYTE)(value>>8);
176 }
177}
178
179static U32 MLZ4_read32(const void* memPtr)
180{
181 U32 val32;
182 memcpy(&val32, memPtr, 4);
183 return val32;
184}
185
186static U64 MLZ4_read64(const void* memPtr)
187{
188 U64 val64;
189 memcpy(&val64, memPtr, 8);
190 return val64;
191}
192
193static size_t MLZ4_read_ARCH(const void* p)
194{
195 if (MLZ4_64bits())
196 return (size_t)MLZ4_read64(p);
197 else
198 return (size_t)MLZ4_read32(p);
199}
200
201
202static void MLZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); }
203
204static void MLZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); }
205
206/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
207static void MLZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
208{
209 BYTE* d = (BYTE*)dstPtr;
210 const BYTE* s = (const BYTE*)srcPtr;
211 BYTE* e = (BYTE*)dstEnd;
212 do { MLZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
213}
214
215
216/**************************************
217* Common Constants
218**************************************/
219#define MINMATCH 4
220
221#define COPYLENGTH 8
222#define LASTLITERALS 5
223#define MFLIMIT (COPYLENGTH+MINMATCH)
224static const int MLZ4_minLength = (MFLIMIT+1);
225
226#define KB *(1 <<10)
227#define MB *(1 <<20)
228#define GB *(1U<<30)
229
230#define MAXD_LOG 16
231#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
232
233#define ML_BITS 4
234#define ML_MASK ((1U<<ML_BITS)-1)
235#define RUN_BITS (8-ML_BITS)
236#define RUN_MASK ((1U<<RUN_BITS)-1)
237
238
239/**************************************
240* Common Utils
241**************************************/
242#define MLZ4_STATIC_ASSERT(c) { enum { MLZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
243
244
245/**************************************
246* Common functions
247**************************************/
248static unsigned MLZ4_NbCommonBytes (size_t val)
249{
251 {
252 if (MLZ4_64bits())
253 {
254# if defined(_MSC_VER) && defined(_WIN64) && !defined(MLZ4_FORCE_SW_BITCOUNT)
255 unsigned long r = 0;
256 _BitScanForward64( &r, (U64)val );
257 return (int)(r>>3);
258# elif (defined(__clang__) || (MLZ4_GCC_VERSION >= 304)) && !defined(MLZ4_FORCE_SW_BITCOUNT)
259 return (__builtin_ctzll((U64)val) >> 3);
260# else
261 static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
262 return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
263# endif
264 }
265 else /* 32 bits */
266 {
267# if defined(_MSC_VER) && !defined(MLZ4_FORCE_SW_BITCOUNT)
268 unsigned long r;
269 _BitScanForward( &r, (U32)val );
270 return (int)(r>>3);
271# elif (defined(__clang__) || (MLZ4_GCC_VERSION >= 304)) && !defined(MLZ4_FORCE_SW_BITCOUNT)
272 return (__builtin_ctz((U32)val) >> 3);
273# else
274 static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
275 return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
276# endif
277 }
278 }
279 else /* Big Endian CPU */
280 {
281 if (MLZ4_64bits())
282 {
283# if defined(_MSC_VER) && defined(_WIN64) && !defined(MLZ4_FORCE_SW_BITCOUNT)
284 unsigned long r = 0;
285 _BitScanReverse64( &r, val );
286 return (unsigned)(r>>3);
287# elif (defined(__clang__) || (MLZ4_GCC_VERSION >= 304)) && !defined(MLZ4_FORCE_SW_BITCOUNT)
288 return (__builtin_clzll((U64)val) >> 3);
289# else
290 unsigned r;
291 if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
292 if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
293 r += (!val);
294 return r;
295# endif
296 }
297 else /* 32 bits */
298 {
299# if defined(_MSC_VER) && !defined(MLZ4_FORCE_SW_BITCOUNT)
300 unsigned long r = 0;
301 _BitScanReverse( &r, (unsigned long)val );
302 return (unsigned)(r>>3);
303# elif (defined(__clang__) || (MLZ4_GCC_VERSION >= 304)) && !defined(MLZ4_FORCE_SW_BITCOUNT)
304 return (__builtin_clz((U32)val) >> 3);
305# else
306 unsigned r;
307 if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
308 r += (!val);
309 return r;
310# endif
311 }
312 }
313}
314
315static unsigned MLZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
316{
317 const BYTE* const pStart = pIn;
318
319 while (likely(pIn<pInLimit-(STEPSIZE-1)))
320 {
321 size_t diff = MLZ4_read_ARCH(pMatch) ^ MLZ4_read_ARCH(pIn);
322 if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
323 pIn += MLZ4_NbCommonBytes(diff);
324 return (unsigned)(pIn - pStart);
325 }
326
327 if (MLZ4_64bits()) if ((pIn<(pInLimit-3)) && (MLZ4_read32(pMatch) == MLZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
328 if ((pIn<(pInLimit-1)) && (MLZ4_read16(pMatch) == MLZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
329 if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
330 return (unsigned)(pIn - pStart);
331}
332
333
334#ifndef MLZ4_COMMONDEFS_ONLY
335/**************************************
336* Local Constants
337**************************************/
338#define MLZ4_HASHLOG (MLZ4_MEMORY_USAGE-2)
339#define HASHTABLESIZE (1 << MLZ4_MEMORY_USAGE)
340#define HASH_SIZE_U32 (1 << MLZ4_HASHLOG) /* required as macro for static allocation */
341
342static const int MLZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
343static const U32 MLZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
344
345
346/**************************************
347* Local Structures and types
348**************************************/
349typedef struct {
350 U32 hashTable[HASH_SIZE_U32];
354 BYTE* bufferStart; /* obsolete, used for slideInputBuffer */
357
359typedef enum { byPtr, byU32, byU16 } tableType_t;
360
363
365typedef enum { full = 0, partial = 1 } earlyEnd_directive;
366
367
368/**************************************
369* Local Utils
370**************************************/
372int MLZ4_compressBound(int isize) { return MLZ4_COMPRESSBOUND(isize); }
374
375
376
377/********************************
378* Compression functions
379********************************/
380
381static U32 MLZ4_hashSequence(U32 sequence, tableType_t const tableType)
382{
383 if (tableType == byU16)
384 return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(MLZ4_HASHLOG+1)));
385 else
386 return (((sequence) * 2654435761U) >> ((MINMATCH*8)-MLZ4_HASHLOG));
387}
388
389static const U64 prime5bytes = 889523592379ULL;
390static U32 MLZ4_hashSequence64(size_t sequence, tableType_t const tableType)
391{
392 const U32 hashLog = (tableType == byU16) ? MLZ4_HASHLOG+1 : MLZ4_HASHLOG;
393 const U32 hashMask = (1<<hashLog) - 1;
394 return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
395}
396
397static U32 MLZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
398{
399 if (MLZ4_64bits())
400 return MLZ4_hashSequence64(sequence, tableType);
401 return MLZ4_hashSequence((U32)sequence, tableType);
402}
403
404static U32 MLZ4_hashPosition(const void* p, tableType_t tableType) { return MLZ4_hashSequenceT(MLZ4_read_ARCH(p), tableType); }
405
406static void MLZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
407{
408 switch (tableType)
409 {
410 case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
411 case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
412 case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
413 }
414}
415
416static void MLZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
417{
418 U32 h = MLZ4_hashPosition(p, tableType);
419 MLZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
420}
421
422static const BYTE* MLZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
423{
424 if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
425 if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
426 { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */
427}
428
429static const BYTE* MLZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
430{
431 U32 h = MLZ4_hashPosition(p, tableType);
432 return MLZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
433}
434
436 void* const ctx,
437 const char* const source,
438 char* const dest,
439 const int inputSize,
440 const int maxOutputSize,
441 const limitedOutput_directive outputLimited,
442 const tableType_t tableType,
443 const dict_directive dict,
444 const dictIssue_directive dictIssue,
445 const U32 acceleration)
446{
447 MLZ4_stream_t_internal* const dictPtr = (MLZ4_stream_t_internal*)ctx;
448
449 const BYTE* ip = (const BYTE*) source;
450 const BYTE* base;
451 const BYTE* lowLimit;
452 const BYTE* const lowRefLimit = ip - dictPtr->dictSize;
453 const BYTE* const dictionary = dictPtr->dictionary;
454 const BYTE* const dictEnd = dictionary + dictPtr->dictSize;
455 const size_t dictDelta = dictEnd - (const BYTE*)source;
456 const BYTE* anchor = (const BYTE*) source;
457 const BYTE* const iend = ip + inputSize;
458 const BYTE* const mflimit = iend - MFLIMIT;
459 const BYTE* const matchlimit = iend - LASTLITERALS;
460
461 BYTE* op = (BYTE*) dest;
462 BYTE* const olimit = op + maxOutputSize;
463
464 U32 forwardH;
465 size_t refDelta=0;
466
467 /* Init conditions */
468 if ((U32)inputSize > (U32)MLZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
469 switch(dict)
470 {
471 case noDict:
472 default:
473 base = (const BYTE*)source;
474 lowLimit = (const BYTE*)source;
475 break;
476 case withPrefix64k:
477 base = (const BYTE*)source - dictPtr->currentOffset;
478 lowLimit = (const BYTE*)source - dictPtr->dictSize;
479 break;
480 case usingExtDict:
481 base = (const BYTE*)source - dictPtr->currentOffset;
482 lowLimit = (const BYTE*)source;
483 break;
484 }
485 if ((tableType == byU16) && (inputSize>=MLZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
486 if (inputSize<MLZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
487
488 /* First Byte */
489 MLZ4_putPosition(ip, ctx, tableType, base);
490 ip++; forwardH = MLZ4_hashPosition(ip, tableType);
491
492 /* Main Loop */
493 for ( ; ; )
494 {
495 const BYTE* match;
496 BYTE* token;
497 {
498 const BYTE* forwardIp = ip;
499 unsigned step = 1;
500 unsigned searchMatchNb = acceleration << MLZ4_skipTrigger;
501
502 /* Find a match */
503 do {
504 U32 h = forwardH;
505 ip = forwardIp;
506 forwardIp += step;
507 step = (searchMatchNb++ >> MLZ4_skipTrigger);
508
509 if (unlikely(forwardIp > mflimit)) goto _last_literals;
510
511 match = MLZ4_getPositionOnHash(h, ctx, tableType, base);
512 if (dict==usingExtDict)
513 {
514 if (match<(const BYTE*)source)
515 {
516 refDelta = dictDelta;
517 lowLimit = dictionary;
518 }
519 else
520 {
521 refDelta = 0;
522 lowLimit = (const BYTE*)source;
523 }
524 }
525 forwardH = MLZ4_hashPosition(forwardIp, tableType);
526 MLZ4_putPositionOnHash(ip, h, ctx, tableType, base);
527
528 } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
529 || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
530 || (MLZ4_read32(match+refDelta) != MLZ4_read32(ip)) );
531 }
532
533 /* Catch up */
534 while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
535
536 {
537 /* Encode Literal length */
538 unsigned litLength = (unsigned)(ip - anchor);
539 token = op++;
540 if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
541 return 0; /* Check output limit */
542 if (litLength>=RUN_MASK)
543 {
544 int len = (int)litLength-RUN_MASK;
545 *token=(RUN_MASK<<ML_BITS);
546 for(; len >= 255 ; len-=255) *op++ = 255;
547 *op++ = (BYTE)len;
548 }
549 else *token = (BYTE)(litLength<<ML_BITS);
550
551 /* Copy Literals */
552 MLZ4_wildCopy(op, anchor, op+litLength);
553 op+=litLength;
554 }
555
556_next_match:
557 /* Encode Offset */
558 MLZ4_writeLE16(op, (U16)(ip-match)); op+=2;
559
560 /* Encode MatchLength */
561 {
562 unsigned matchLength;
563
564 if ((dict==usingExtDict) && (lowLimit==dictionary))
565 {
566 const BYTE* limit;
567 match += refDelta;
568 limit = ip + (dictEnd-match);
569 if (limit > matchlimit) limit = matchlimit;
570 matchLength = MLZ4_count(ip+MINMATCH, match+MINMATCH, limit);
571 ip += MINMATCH + matchLength;
572 if (ip==limit)
573 {
574 unsigned more = MLZ4_count(ip, (const BYTE*)source, matchlimit);
575 matchLength += more;
576 ip += more;
577 }
578 }
579 else
580 {
581 matchLength = MLZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
582 ip += MINMATCH + matchLength;
583 }
584
585 if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
586 return 0; /* Check output limit */
587 if (matchLength>=ML_MASK)
588 {
589 *token += ML_MASK;
590 matchLength -= ML_MASK;
591 for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
592 if (matchLength >= 255) { matchLength-=255; *op++ = 255; }
593 *op++ = (BYTE)matchLength;
594 }
595 else *token += (BYTE)(matchLength);
596 }
597
598 anchor = ip;
599
600 /* Test end of chunk */
601 if (ip > mflimit) break;
602
603 /* Fill table */
604 MLZ4_putPosition(ip-2, ctx, tableType, base);
605
606 /* Test next position */
607 match = MLZ4_getPosition(ip, ctx, tableType, base);
608 if (dict==usingExtDict)
609 {
610 if (match<(const BYTE*)source)
611 {
612 refDelta = dictDelta;
613 lowLimit = dictionary;
614 }
615 else
616 {
617 refDelta = 0;
618 lowLimit = (const BYTE*)source;
619 }
620 }
621 MLZ4_putPosition(ip, ctx, tableType, base);
622 if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
623 && (match+MAX_DISTANCE>=ip)
624 && (MLZ4_read32(match+refDelta)==MLZ4_read32(ip)) )
625 { token=op++; *token=0; goto _next_match; }
626
627 /* Prepare next loop */
628 forwardH = MLZ4_hashPosition(++ip, tableType);
629 }
630
631_last_literals:
632 /* Encode Last Literals */
633 {
634 const size_t lastRun = (size_t)(iend - anchor);
635 if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize))
636 return 0; /* Check output limit */
637 if (lastRun >= RUN_MASK)
638 {
639 size_t accumulator = lastRun - RUN_MASK;
640 *op++ = RUN_MASK << ML_BITS;
641 for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
642 *op++ = (BYTE) accumulator;
643 }
644 else
645 {
646 *op++ = (BYTE)(lastRun<<ML_BITS);
647 }
648 memcpy(op, anchor, lastRun);
649 op += lastRun;
650 }
651
652 /* End */
653 return (int) (((char*)op)-dest);
654}
655
656
657int MLZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
658{
660 if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
661
663 {
665 return MLZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration);
666 else
667 return MLZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, MLZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
668 }
669 else
670 {
673 else
675 }
676}
677
678
679int MLZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
680{
681#if (HEAPMODE)
682 void* ctxPtr = ALLOCATOR(1, sizeof(MLZ4_stream_t)); /* malloc-calloc always properly aligned */
683#else
684 MLZ4_stream_t ctx;
685 void* ctxPtr = &ctx;
686#endif
687
688 int result = MLZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
689
690#if (HEAPMODE)
691 FREEMEM(ctxPtr);
692#endif
693 return result;
694}
695
696
697int MLZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
698{
700}
701
702
703/* hidden debug function */
704/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
705int MLZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
706{
707 MLZ4_stream_t ctx;
708
709 MLZ4_resetStream(&ctx);
710
713 else
715}
716
717
718/********************************
719* destSize variant
720********************************/
721
723 void* const ctx,
724 const char* const src,
725 char* const dst,
726 int* const srcSizePtr,
727 const int targetDstSize,
728 const tableType_t tableType)
729{
730 const BYTE* ip = (const BYTE*) src;
731 const BYTE* base = (const BYTE*) src;
732 const BYTE* lowLimit = (const BYTE*) src;
733 const BYTE* anchor = ip;
734 const BYTE* const iend = ip + *srcSizePtr;
735 const BYTE* const mflimit = iend - MFLIMIT;
736 const BYTE* const matchlimit = iend - LASTLITERALS;
737
738 BYTE* op = (BYTE*) dst;
739 BYTE* const oend = op + targetDstSize;
740 BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
741 BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
742 BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
743
744 U32 forwardH;
745
746
747 /* Init conditions */
748 if (targetDstSize < 1) return 0; /* Impossible to store anything */
749 if ((U32)*srcSizePtr > (U32)MLZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */
750 if ((tableType == byU16) && (*srcSizePtr>=MLZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
751 if (*srcSizePtr<MLZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
752
753 /* First Byte */
754 *srcSizePtr = 0;
755 MLZ4_putPosition(ip, ctx, tableType, base);
756 ip++; forwardH = MLZ4_hashPosition(ip, tableType);
757
758 /* Main Loop */
759 for ( ; ; )
760 {
761 const BYTE* match;
762 BYTE* token;
763 {
764 const BYTE* forwardIp = ip;
765 unsigned step = 1;
766 unsigned searchMatchNb = 1 << MLZ4_skipTrigger;
767
768 /* Find a match */
769 do {
770 U32 h = forwardH;
771 ip = forwardIp;
772 forwardIp += step;
773 step = (searchMatchNb++ >> MLZ4_skipTrigger);
774
775 if (unlikely(forwardIp > mflimit))
776 goto _last_literals;
777
778 match = MLZ4_getPositionOnHash(h, ctx, tableType, base);
779 forwardH = MLZ4_hashPosition(forwardIp, tableType);
780 MLZ4_putPositionOnHash(ip, h, ctx, tableType, base);
781
782 } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
783 || (MLZ4_read32(match) != MLZ4_read32(ip)) );
784 }
785
786 /* Catch up */
787 while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
788
789 {
790 /* Encode Literal length */
791 unsigned litLength = (unsigned)(ip - anchor);
792 token = op++;
793 if (op + ((litLength+240)/255) + litLength > oMaxLit)
794 {
795 /* Not enough space for a last match */
796 op--;
797 goto _last_literals;
798 }
799 if (litLength>=RUN_MASK)
800 {
801 unsigned len = litLength - RUN_MASK;
802 *token=(RUN_MASK<<ML_BITS);
803 for(; len >= 255 ; len-=255) *op++ = 255;
804 *op++ = (BYTE)len;
805 }
806 else *token = (BYTE)(litLength<<ML_BITS);
807
808 /* Copy Literals */
809 MLZ4_wildCopy(op, anchor, op+litLength);
810 op += litLength;
811 }
812
813_next_match:
814 /* Encode Offset */
815 MLZ4_writeLE16(op, (U16)(ip-match)); op+=2;
816
817 /* Encode MatchLength */
818 {
819 size_t matchLength;
820
821 matchLength = MLZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
822
823 if (op + ((matchLength+240)/255) > oMaxMatch)
824 {
825 /* Match description too long : reduce it */
826 matchLength = (15-1) + (oMaxMatch-op) * 255;
827 }
828 //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
829 ip += MINMATCH + matchLength;
830
831 if (matchLength>=ML_MASK)
832 {
833 *token += ML_MASK;
834 matchLength -= ML_MASK;
835 while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
836 *op++ = (BYTE)matchLength;
837 }
838 else *token += (BYTE)(matchLength);
839 }
840
841 anchor = ip;
842
843 /* Test end of block */
844 if (ip > mflimit) break;
845 if (op > oMaxSeq) break;
846
847 /* Fill table */
848 MLZ4_putPosition(ip-2, ctx, tableType, base);
849
850 /* Test next position */
851 match = MLZ4_getPosition(ip, ctx, tableType, base);
852 MLZ4_putPosition(ip, ctx, tableType, base);
853 if ( (match+MAX_DISTANCE>=ip)
854 && (MLZ4_read32(match)==MLZ4_read32(ip)) )
855 { token=op++; *token=0; goto _next_match; }
856
857 /* Prepare next loop */
858 forwardH = MLZ4_hashPosition(++ip, tableType);
859 }
860
861_last_literals:
862 /* Encode Last Literals */
863 {
864 size_t lastRunSize = (size_t)(iend - anchor);
865 if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)
866 {
867 /* adapt lastRunSize to fill 'dst' */
868 lastRunSize = (oend-op) - 1;
869 lastRunSize -= (lastRunSize+240)/255;
870 }
871 ip = anchor + lastRunSize;
872
873 if (lastRunSize >= RUN_MASK)
874 {
875 size_t accumulator = lastRunSize - RUN_MASK;
876 *op++ = RUN_MASK << ML_BITS;
877 for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
878 *op++ = (BYTE) accumulator;
879 }
880 else
881 {
882 *op++ = (BYTE)(lastRunSize<<ML_BITS);
883 }
884 memcpy(op, anchor, lastRunSize);
885 op += lastRunSize;
886 }
887
888 /* End */
889 *srcSizePtr = (int) (((const char*)ip)-src);
890 return (int) (((char*)op)-dst);
891}
892
893
894static int MLZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
895{
897
898 if (targetDstSize >= MLZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
899 {
900 return MLZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
901 }
902 else
903 {
904 if (*srcSizePtr < MLZ4_64Klimit)
905 return MLZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
906 else
907 return MLZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, MLZ4_64bits() ? byU32 : byPtr);
908 }
909}
910
911
912int MLZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
913{
914#if (HEAPMODE)
915 void* ctx = ALLOCATOR(1, sizeof(MLZ4_stream_t)); /* malloc-calloc always properly aligned */
916#else
917 MLZ4_stream_t ctxBody;
918 void* ctx = &ctxBody;
919#endif
920
921 int result = MLZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
922
923#if (HEAPMODE)
924 FREEMEM(ctx);
925#endif
926 return result;
927}
928
929
930
931/********************************
932* Streaming functions
933********************************/
934
936{
938 MLZ4_STATIC_ASSERT(MLZ4_STREAMSIZE >= sizeof(MLZ4_stream_t_internal)); /* A compilation error here means MLZ4_STREAMSIZE is not large enough */
939 MLZ4_resetStream(lz4s);
940 return lz4s;
941}
942
944{
945 MEM_INIT(MLZ4_stream, 0, sizeof(MLZ4_stream_t));
946}
947
949{
950 FREEMEM(MLZ4_stream);
951 return (0);
952}
953
954
955#define HASH_UNIT sizeof(size_t)
956int MLZ4_loadDict (MLZ4_stream_t* MLZ4_dict, const char* dictionary, int dictSize)
957{
959 const BYTE* p = (const BYTE*)dictionary;
960 const BYTE* const dictEnd = p + dictSize;
961 const BYTE* base;
962
963 if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
964 MLZ4_resetStream(MLZ4_dict);
965
966 if (dictSize < (int)HASH_UNIT)
967 {
968 dict->dictionary = NULL;
969 dict->dictSize = 0;
970 return 0;
971 }
972
973 if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
974 dict->currentOffset += 64 KB;
975 base = p - dict->currentOffset;
976 dict->dictionary = p;
977 dict->dictSize = (U32)(dictEnd - p);
978 dict->currentOffset += dict->dictSize;
979
980 while (p <= dictEnd-HASH_UNIT)
981 {
982 MLZ4_putPosition(p, dict->hashTable, byU32, base);
983 p+=3;
984 }
985
986 return dict->dictSize;
987}
988
989
990static void MLZ4_renormDictT(MLZ4_stream_t_internal* MLZ4_dict, const BYTE* src)
991{
992 if ((MLZ4_dict->currentOffset > 0x80000000) ||
993 ((size_t)MLZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
994 {
995 /* rescale hash table */
996 U32 delta = MLZ4_dict->currentOffset - 64 KB;
997 const BYTE* dictEnd = MLZ4_dict->dictionary + MLZ4_dict->dictSize;
998 int i;
999 for (i=0; i<HASH_SIZE_U32; i++)
1000 {
1001 if (MLZ4_dict->hashTable[i] < delta) MLZ4_dict->hashTable[i]=0;
1002 else MLZ4_dict->hashTable[i] -= delta;
1003 }
1004 MLZ4_dict->currentOffset = 64 KB;
1005 if (MLZ4_dict->dictSize > 64 KB) MLZ4_dict->dictSize = 64 KB;
1006 MLZ4_dict->dictionary = dictEnd - MLZ4_dict->dictSize;
1007 }
1008}
1009
1010
1011int MLZ4_compress_fast_continue (MLZ4_stream_t* MLZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
1012{
1013 MLZ4_stream_t_internal* streamPtr = (MLZ4_stream_t_internal*)MLZ4_stream;
1014 const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
1015
1016 const BYTE* smallest = (const BYTE*) source;
1017 if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */
1018 if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
1019 MLZ4_renormDictT(streamPtr, smallest);
1020 if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
1021
1022 /* Check overlapping input/dictionary space */
1023 {
1024 const BYTE* sourceEnd = (const BYTE*) source + inputSize;
1025 if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))
1026 {
1027 streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
1028 if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
1029 if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
1030 streamPtr->dictionary = dictEnd - streamPtr->dictSize;
1031 }
1032 }
1033
1034 /* prefix mode : source data follows dictionary */
1035 if (dictEnd == (const BYTE*)source)
1036 {
1037 int result;
1038 if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
1040 else
1042 streamPtr->dictSize += (U32)inputSize;
1043 streamPtr->currentOffset += (U32)inputSize;
1044 return result;
1045 }
1046
1047 /* external dictionary mode */
1048 {
1049 int result;
1050 if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
1052 else
1054 streamPtr->dictionary = (const BYTE*)source;
1055 streamPtr->dictSize = (U32)inputSize;
1056 streamPtr->currentOffset += (U32)inputSize;
1057 return result;
1058 }
1059}
1060
1061
1062/* Hidden debug function, to force external dictionary mode */
1063int MLZ4_compress_forceExtDict (MLZ4_stream_t* MLZ4_dict, const char* source, char* dest, int inputSize)
1064{
1065 MLZ4_stream_t_internal* streamPtr = (MLZ4_stream_t_internal*)MLZ4_dict;
1066 int result;
1067 const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
1068
1069 const BYTE* smallest = dictEnd;
1070 if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
1071 MLZ4_renormDictT((MLZ4_stream_t_internal*)MLZ4_dict, smallest);
1072
1074
1075 streamPtr->dictionary = (const BYTE*)source;
1076 streamPtr->dictSize = (U32)inputSize;
1077 streamPtr->currentOffset += (U32)inputSize;
1078
1079 return result;
1080}
1081
1082
1083int MLZ4_saveDict (MLZ4_stream_t* MLZ4_dict, char* safeBuffer, int dictSize)
1084{
1086 const BYTE* previousDictEnd = dict->dictionary + dict->dictSize;
1087
1088 if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
1089 if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
1090
1091 memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
1092
1093 dict->dictionary = (const BYTE*)safeBuffer;
1094 dict->dictSize = (U32)dictSize;
1095
1096 return dictSize;
1097}
1098
1099
1100
1101/*******************************
1102* Decompression functions
1103*******************************/
1104/*
1105 * This generic decompression function cover all use cases.
1106 * It shall be instantiated several times, using different sets of directives
1107 * Note that it is essential this generic function is really inlined,
1108 * in order to remove useless branches during compilation optimization.
1109 */
1111 const char* const source,
1112 char* const dest,
1113 int inputSize,
1114 int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
1115
1116 int endOnInput, /* endOnOutputSize, endOnInputSize */
1117 int partialDecoding, /* full, partial */
1118 int targetOutputSize, /* only used if partialDecoding==partial */
1119 int dict, /* noDict, withPrefix64k, usingExtDict */
1120 const BYTE* const lowPrefix, /* == dest if dict == noDict */
1121 const BYTE* const dictStart, /* only if dict==usingExtDict */
1122 const size_t dictSize /* note : = 0 if noDict */
1123 )
1124{
1125 /* Local Variables */
1126 const BYTE* ip = (const BYTE*) source;
1127 const BYTE* const iend = ip + inputSize;
1128
1129 BYTE* op = (BYTE*) dest;
1130 BYTE* const oend = op + outputSize;
1131 BYTE* cpy;
1132 BYTE* oexit = op + targetOutputSize;
1133 const BYTE* const lowLimit = lowPrefix - dictSize;
1134
1135 const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
1136 const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
1137 const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
1138
1139 const int safeDecode = (endOnInput==endOnInputSize);
1140 const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
1141
1142
1143 /* Special cases */
1144 if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
1145 if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
1146 if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
1147
1148
1149 /* Main Loop */
1150 while (1)
1151 {
1152 unsigned token;
1153 size_t length;
1154 const BYTE* match;
1155
1156 /* get literal length */
1157 token = *ip++;
1158 if ((length=(token>>ML_BITS)) == RUN_MASK)
1159 {
1160 unsigned s;
1161 do
1162 {
1163 s = *ip++;
1164 length += s;
1165 }
1166 while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));
1167 if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
1168 if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
1169 }
1170
1171 /* copy literals */
1172 cpy = op+length;
1173 if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
1174 || ((!endOnInput) && (cpy>oend-COPYLENGTH)))
1175 {
1176 if (partialDecoding)
1177 {
1178 if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
1179 if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
1180 }
1181 else
1182 {
1183 if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
1184 if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
1185 }
1186 memcpy(op, ip, length);
1187 ip += length;
1188 op += length;
1189 break; /* Necessarily EOF, due to parsing restrictions */
1190 }
1191 MLZ4_wildCopy(op, ip, cpy);
1192 ip += length; op = cpy;
1193
1194 /* get offset */
1195 match = cpy - MLZ4_readLE16(ip); ip+=2;
1196 if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
1197
1198 /* get matchlength */
1199 length = token & ML_MASK;
1200 if (length == ML_MASK)
1201 {
1202 unsigned s;
1203 do
1204 {
1205 if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
1206 s = *ip++;
1207 length += s;
1208 } while (s==255);
1209 if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
1210 }
1211 length += MINMATCH;
1212
1213 /* check external dictionary */
1214 if ((dict==usingExtDict) && (match < lowPrefix))
1215 {
1216 if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
1217
1218 if (length <= (size_t)(lowPrefix-match))
1219 {
1220 /* match can be copied as a single segment from external dictionary */
1221 match = dictEnd - (lowPrefix-match);
1222 memmove(op, match, length); op += length;
1223 }
1224 else
1225 {
1226 /* match encompass external dictionary and current segment */
1227 size_t copySize = (size_t)(lowPrefix-match);
1228 memcpy(op, dictEnd - copySize, copySize);
1229 op += copySize;
1230 copySize = length - copySize;
1231 if (copySize > (size_t)(op-lowPrefix)) /* overlap within current segment */
1232 {
1233 BYTE* const endOfMatch = op + copySize;
1234 const BYTE* copyFrom = lowPrefix;
1235 while (op < endOfMatch) *op++ = *copyFrom++;
1236 }
1237 else
1238 {
1239 memcpy(op, lowPrefix, copySize);
1240 op += copySize;
1241 }
1242 }
1243 continue;
1244 }
1245
1246 /* copy repeated sequence */
1247 cpy = op + length;
1248 if (unlikely((op-match)<8))
1249 {
1250 const size_t dec64 = dec64table[op-match];
1251 op[0] = match[0];
1252 op[1] = match[1];
1253 op[2] = match[2];
1254 op[3] = match[3];
1255 match += dec32table[op-match];
1256 MLZ4_copy4(op+4, match);
1257 op += 8; match -= dec64;
1258 } else { MLZ4_copy8(op, match); op+=8; match+=8; }
1259
1260 if (unlikely(cpy>oend-12))
1261 {
1262 if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
1263 if (op < oend-8)
1264 {
1265 MLZ4_wildCopy(op, match, oend-8);
1266 match += (oend-8) - op;
1267 op = oend-8;
1268 }
1269 while (op<cpy) *op++ = *match++;
1270 }
1271 else
1272 MLZ4_wildCopy(op, match, cpy);
1273 op=cpy; /* correction */
1274 }
1275
1276 /* end of decoding */
1277 if (endOnInput)
1278 return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
1279 else
1280 return (int) (((const char*)ip)-source); /* Nb of input bytes read */
1281
1282 /* Overflow error detected */
1283_output_error:
1284 return (int) (-(((const char*)ip)-source))-1;
1285}
1286
1287
1288int MLZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
1289{
1290 return MLZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
1291}
1292
1293int MLZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
1294{
1295 return MLZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
1296}
1297
1298int MLZ4_decompress_fast(const char* source, char* dest, int originalSize)
1299{
1301}
1302
1303
1304/* streaming decompression functions */
1305
1313
1314/*
1315 * If you prefer dynamic allocation methods,
1316 * MLZ4_createStreamDecode()
1317 * provides a pointer (void*) towards an initialized MLZ4_streamDecode_t structure.
1318 */
1324
1326{
1327 FREEMEM(MLZ4_stream);
1328 return 0;
1329}
1330
1331/*
1332 * MLZ4_setStreamDecode
1333 * Use this function to instruct where to find the dictionary
1334 * This function is not necessary if previous data is still available where it was decoded.
1335 * Loading a size of 0 is allowed (same effect as no dictionary).
1336 * Return : 1 if OK, 0 if error
1337 */
1338int MLZ4_setStreamDecode (MLZ4_streamDecode_t* MLZ4_streamDecode, const char* dictionary, int dictSize)
1339{
1340 MLZ4_streamDecode_t_internal* lz4sd = (MLZ4_streamDecode_t_internal*) MLZ4_streamDecode;
1341 lz4sd->prefixSize = (size_t) dictSize;
1342 lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
1343 lz4sd->externalDict = NULL;
1344 lz4sd->extDictSize = 0;
1345 return 1;
1346}
1347
1348/*
1349*_continue() :
1350 These decoding functions allow decompression of multiple blocks in "streaming" mode.
1351 Previously decoded blocks must still be available at the memory position where they were decoded.
1352 If it's not possible, save the relevant part of decoded data into a safe buffer,
1353 and indicate where it stands using MLZ4_setStreamDecode()
1354*/
1355int MLZ4_decompress_safe_continue (MLZ4_streamDecode_t* MLZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
1356{
1357 MLZ4_streamDecode_t_internal* lz4sd = (MLZ4_streamDecode_t_internal*) MLZ4_streamDecode;
1358 int result;
1359
1360 if (lz4sd->prefixEnd == (BYTE*)dest)
1361 {
1363 endOnInputSize, full, 0,
1364 usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
1365 if (result <= 0) return result;
1366 lz4sd->prefixSize += result;
1367 lz4sd->prefixEnd += result;
1368 }
1369 else
1370 {
1371 lz4sd->extDictSize = lz4sd->prefixSize;
1372 lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
1374 endOnInputSize, full, 0,
1375 usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
1376 if (result <= 0) return result;
1377 lz4sd->prefixSize = result;
1378 lz4sd->prefixEnd = (BYTE*)dest + result;
1379 }
1380
1381 return result;
1382}
1383
1384int MLZ4_decompress_fast_continue (MLZ4_streamDecode_t* MLZ4_streamDecode, const char* source, char* dest, int originalSize)
1385{
1386 MLZ4_streamDecode_t_internal* lz4sd = (MLZ4_streamDecode_t_internal*) MLZ4_streamDecode;
1387 int result;
1388
1389 if (lz4sd->prefixEnd == (BYTE*)dest)
1390 {
1393 usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
1394 if (result <= 0) return result;
1395 lz4sd->prefixSize += originalSize;
1396 lz4sd->prefixEnd += originalSize;
1397 }
1398 else
1399 {
1400 lz4sd->extDictSize = lz4sd->prefixSize;
1401 lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
1404 usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
1405 if (result <= 0) return result;
1406 lz4sd->prefixSize = originalSize;
1407 lz4sd->prefixEnd = (BYTE*)dest + originalSize;
1408 }
1409
1410 return result;
1411}
1412
1413
1414/*
1415Advanced decoding functions :
1416*_usingDict() :
1417 These decoding functions work the same as "_continue" ones,
1418 the dictionary must be explicitly provided within parameters
1419*/
1420
1421FORCE_INLINE int MLZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
1422{
1423 if (dictSize==0)
1425 if (dictStart+dictSize == dest)
1426 {
1427 if (dictSize >= (int)(64 KB - 1))
1429 return MLZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
1430 }
1431 return MLZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
1432}
1433
1434int MLZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
1435{
1437}
1438
1439int MLZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
1440{
1441 return MLZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
1442}
1443
1444/* debug function */
1445int MLZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
1446{
1448}
1449
1450
1451/***************************************************
1452* Obsolete Functions
1453***************************************************/
1454/* obsolete compression functions */
1457int MLZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return MLZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }
1458int MLZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return MLZ4_compress_fast_extState(state, src, dst, srcSize, MLZ4_compressBound(srcSize), 1); }
1459int MLZ4_compress_limitedOutput_continue (MLZ4_stream_t* MLZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return MLZ4_compress_fast_continue(MLZ4_stream, src, dst, srcSize, maxDstSize, 1); }
1461
1462/*
1463These function names are deprecated and should no longer be used.
1464They are only provided here for compatibility with older user programs.
1465- MLZ4_uncompress is totally equivalent to MLZ4_decompress_fast
1466- MLZ4_uncompress_unknownOutputSize is totally equivalent to MLZ4_decompress_safe
1467*/
1468int MLZ4_uncompress (const char* source, char* dest, int outputSize) { return MLZ4_decompress_fast(source, dest, outputSize); }
1469int MLZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return MLZ4_decompress_safe(source, dest, isize, maxOutputSize); }
1470
1471
1472/* Obsolete Streaming functions */
1473
1475
1476static void MLZ4_init(MLZ4_stream_t_internal* lz4ds, BYTE* base)
1477{
1478 MEM_INIT(lz4ds, 0, MLZ4_STREAMSIZE);
1479 lz4ds->bufferStart = base;
1480}
1481
1482int MLZ4_resetStreamState(void* state, char* inputBuffer)
1483{
1484 if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */
1486 return 0;
1487}
1488
1490{
1491 void* lz4ds = ALLOCATOR(8, MLZ4_STREAMSIZE_U64);
1493 return lz4ds;
1494}
1495
1496char* MLZ4_slideInputBuffer (void* MLZ4_Data)
1497{
1499 int dictSize = MLZ4_saveDict((MLZ4_stream_t*)MLZ4_Data, (char*)ctx->bufferStart, 64 KB);
1500 return (char*)(ctx->bufferStart + dictSize);
1501}
1502
1503/* Obsolete streaming decompression functions */
1504
1509
1514
1515#endif /* MLZ4_COMMONDEFS_ONLY */
1516
uint8_t BYTE
char int compressedSize
Definition mlz4.h:354
#define MLZ4_STREAMSIZE
Definition mlz4.h:188
char int int maxDstSize
Definition mlz4.h:354
#define MLZ4_STREAMSIZE_U64
Definition mlz4.h:187
char * inputBuffer
Definition mlz4.h:350
#define MLZ4_VERSION_NUMBER
Definition mlz4.h:53
#define MLZ4_COMPRESSBOUND(isize)
Definition mlz4.h:106
char * dst
Definition mlz4.h:354
#define MLZ4_MAX_INPUT_SIZE
Definition mlz4.h:105
char int originalSize
Definition mlz4.h:355
const char * source
Definition mlz4hc.h:181
const char char int int maxOutputSize
Definition mlz4hc.h:182
const char char int inputSize
Definition mlz4hc.h:181
const char char * dest
Definition mlz4hc.h:181
#define MLZ4_STATIC_ASSERT(c)
Definition lz4.cxx:242
#define MAX_DISTANCE
Definition lz4.cxx:231
#define STEPSIZE
Definition lz4.cxx:134
void MLZ4_resetStream(MLZ4_stream_t *MLZ4_stream)
Definition lz4.cxx:943
int MLZ4_compress_limitedOutput_continue(MLZ4_stream_t *MLZ4_stream, const char *src, char *dst, int srcSize, int maxDstSize)
Definition lz4.cxx:1459
#define HASH_SIZE_U32
Definition lz4.cxx:340
int MLZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxOutputSize, const char *dictStart, int dictSize)
Definition lz4.cxx:1434
static unsigned MLZ4_64bits(void)
Definition lz4.cxx:136
static unsigned MLZ4_count(const BYTE *pIn, const BYTE *pMatch, const BYTE *pInLimit)
Definition lz4.cxx:315
#define COPYLENGTH
Definition lz4.cxx:221
static U64 MLZ4_read64(const void *memPtr)
Definition lz4.cxx:186
static void MLZ4_putPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
Definition lz4.cxx:416
#define KB
Definition lz4.cxx:226
#define MEM_INIT
Definition lz4.cxx:109
int MLZ4_compress_destSize(const char *src, char *dst, int *srcSizePtr, int targetDstSize)
Definition lz4.cxx:912
MLZ4_stream_t * MLZ4_createStream(void)
Definition lz4.cxx:935
endCondition_directive
Definition lz4.cxx:364
@ endOnInputSize
Definition lz4.cxx:364
@ endOnOutputSize
Definition lz4.cxx:364
unsigned long long U64
Definition lz4.cxx:127
earlyEnd_directive
Definition lz4.cxx:365
@ full
Definition lz4.cxx:365
@ partial
Definition lz4.cxx:365
#define ACCELERATION_DEFAULT
Definition lz4.cxx:50
int MLZ4_compress_withState(void *state, const char *src, char *dst, int srcSize)
Definition lz4.cxx:1458
int MLZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
Definition lz4.cxx:1293
#define MINMATCH
Definition lz4.cxx:219
static int MLZ4_compress_destSize_extState(void *state, const char *src, char *dst, int *srcSizePtr, int targetDstSize)
Definition lz4.cxx:894
#define FREEMEM
Definition lz4.cxx:107
int MLZ4_decompress_fast(const char *source, char *dest, int originalSize)
Definition lz4.cxx:1298
void * MLZ4_create(char *inputBuffer)
Definition lz4.cxx:1489
static void MLZ4_copy4(void *dstPtr, const void *srcPtr)
Definition lz4.cxx:202
static U32 MLZ4_hashSequence(U32 sequence, tableType_t const tableType)
Definition lz4.cxx:381
int MLZ4_compress_forceExtDict(MLZ4_stream_t *MLZ4_dict, const char *source, char *dest, int inputSize)
Definition lz4.cxx:1063
#define GB
Definition lz4.cxx:228
FORCE_INLINE int MLZ4_decompress_generic(const char *const source, char *const dest, int inputSize, int outputSize, int endOnInput, int partialDecoding, int targetOutputSize, int dict, const BYTE *const lowPrefix, const BYTE *const dictStart, const size_t dictSize)
Definition lz4.cxx:1110
unsigned char BYTE
Definition lz4.cxx:123
int MLZ4_compress_fast_force(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition lz4.cxx:705
int MLZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
Definition lz4.cxx:1288
static const U32 MLZ4_skipTrigger
Definition lz4.cxx:343
int MLZ4_freeStreamDecode(MLZ4_streamDecode_t *MLZ4_stream)
Definition lz4.cxx:1325
int MLZ4_resetStreamState(void *state, char *inputBuffer)
Definition lz4.cxx:1482
static void MLZ4_writeLE16(void *memPtr, U16 value)
Definition lz4.cxx:165
signed int S32
Definition lz4.cxx:126
int MLZ4_decompress_safe_continue(MLZ4_streamDecode_t *MLZ4_streamDecode, const char *source, char *dest, int compressedSize, int maxOutputSize)
Definition lz4.cxx:1355
static unsigned MLZ4_isLittleEndian(void)
Definition lz4.cxx:138
int MLZ4_sizeofState()
Definition lz4.cxx:373
int MLZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize)
Definition lz4.cxx:1469
static void MLZ4_copy8(void *dstPtr, const void *srcPtr)
Definition lz4.cxx:204
int MLZ4_setStreamDecode(MLZ4_streamDecode_t *MLZ4_streamDecode, const char *dictionary, int dictSize)
Definition lz4.cxx:1338
#define MFLIMIT
Definition lz4.cxx:223
int MLZ4_compress_limitedOutput(const char *source, char *dest, int inputSize, int maxOutputSize)
Definition lz4.cxx:1455
int MLZ4_decompress_fast_continue(MLZ4_streamDecode_t *MLZ4_streamDecode, const char *source, char *dest, int originalSize)
Definition lz4.cxx:1384
#define LASTLITERALS
Definition lz4.cxx:222
int MLZ4_loadDict(MLZ4_stream_t *MLZ4_dict, const char *dictionary, int dictSize)
Definition lz4.cxx:956
static U16 MLZ4_read16(const void *memPtr)
Definition lz4.cxx:145
MLZ4_streamDecode_t * MLZ4_createStreamDecode(void)
Definition lz4.cxx:1319
int MLZ4_decompress_safe_withPrefix64k(const char *source, char *dest, int compressedSize, int maxOutputSize)
Definition lz4.cxx:1505
int MLZ4_compress_fast(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition lz4.cxx:679
char * MLZ4_slideInputBuffer(void *MLZ4_Data)
Definition lz4.cxx:1496
int MLZ4_versionNumber(void)
Definition lz4.cxx:371
static U32 MLZ4_hashSequence64(size_t sequence, tableType_t const tableType)
Definition lz4.cxx:390
int MLZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition lz4.cxx:657
static U32 MLZ4_read32(const void *memPtr)
Definition lz4.cxx:179
static const BYTE * MLZ4_getPositionOnHash(U32 h, void *tableBase, tableType_t tableType, const BYTE *srcBase)
Definition lz4.cxx:422
dictIssue_directive
Definition lz4.cxx:362
@ noDictIssue
Definition lz4.cxx:362
@ dictSmall
Definition lz4.cxx:362
#define likely(expr)
Definition lz4.cxx:98
int MLZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart, int dictSize)
Definition lz4.cxx:1439
#define ML_BITS
Definition lz4.cxx:233
static unsigned MLZ4_NbCommonBytes(size_t val)
Definition lz4.cxx:248
#define ML_MASK
Definition lz4.cxx:234
static void MLZ4_putPositionOnHash(const BYTE *p, U32 h, void *tableBase, tableType_t const tableType, const BYTE *srcBase)
Definition lz4.cxx:406
int MLZ4_decompress_safe_forceExtDict(const char *source, char *dest, int compressedSize, int maxOutputSize, const char *dictStart, int dictSize)
Definition lz4.cxx:1445
static U32 MLZ4_hashPosition(const void *p, tableType_t tableType)
Definition lz4.cxx:404
int MLZ4_compress_continue(MLZ4_stream_t *MLZ4_stream, const char *source, char *dest, int inputSize)
Definition lz4.cxx:1460
#define HASH_UNIT
Definition lz4.cxx:955
int MLZ4_compress_limitedOutput_withState(void *state, const char *src, char *dst, int srcSize, int dstSize)
Definition lz4.cxx:1457
dict_directive
Definition lz4.cxx:361
@ noDict
Definition lz4.cxx:361
@ withPrefix64k
Definition lz4.cxx:361
@ usingExtDict
Definition lz4.cxx:361
static U16 MLZ4_readLE16(const void *memPtr)
Definition lz4.cxx:152
static const BYTE * MLZ4_getPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
Definition lz4.cxx:429
#define ALLOCATOR(n, s)
Definition lz4.cxx:106
limitedOutput_directive
Definition lz4.cxx:358
@ limitedOutput
Definition lz4.cxx:358
@ notLimited
Definition lz4.cxx:358
static size_t MLZ4_read_ARCH(const void *p)
Definition lz4.cxx:193
static const int MLZ4_64Klimit
Definition lz4.cxx:342
#define FORCE_INLINE
Definition lz4.cxx:87
FORCE_INLINE int MLZ4_decompress_usingDict_generic(const char *source, char *dest, int compressedSize, int maxOutputSize, int safe, const char *dictStart, int dictSize)
Definition lz4.cxx:1421
FORCE_INLINE int MLZ4_compress_generic(void *const ctx, const char *const source, char *const dest, const int inputSize, const int maxOutputSize, const limitedOutput_directive outputLimited, const tableType_t tableType, const dict_directive dict, const dictIssue_directive dictIssue, const U32 acceleration)
Definition lz4.cxx:435
unsigned int U32
Definition lz4.cxx:125
int MLZ4_sizeofStreamState()
Definition lz4.cxx:1474
int MLZ4_compress(const char *source, char *dest, int inputSize)
Definition lz4.cxx:1456
int MLZ4_compress_default(const char *source, char *dest, int inputSize, int maxOutputSize)
Definition lz4.cxx:697
int MLZ4_compressBound(int isize)
Definition lz4.cxx:372
#define MLZ4_HASHLOG
Definition lz4.cxx:338
#define unlikely(expr)
Definition lz4.cxx:99
static void MLZ4_renormDictT(MLZ4_stream_t_internal *MLZ4_dict, const BYTE *src)
Definition lz4.cxx:990
unsigned short U16
Definition lz4.cxx:124
int MLZ4_freeStream(MLZ4_stream_t *MLZ4_stream)
Definition lz4.cxx:948
static void MLZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd)
Definition lz4.cxx:207
static const int MLZ4_minLength
Definition lz4.cxx:224
tableType_t
Definition lz4.cxx:359
@ byU16
Definition lz4.cxx:359
@ byPtr
Definition lz4.cxx:359
@ byU32
Definition lz4.cxx:359
static int MLZ4_compress_destSize_generic(void *const ctx, const char *const src, char *const dst, int *const srcSizePtr, const int targetDstSize, const tableType_t tableType)
Definition lz4.cxx:722
#define RUN_MASK
Definition lz4.cxx:236
int MLZ4_decompress_fast_withPrefix64k(const char *source, char *dest, int originalSize)
Definition lz4.cxx:1510
int MLZ4_uncompress(const char *source, char *dest, int outputSize)
Definition lz4.cxx:1468
static U32 MLZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
Definition lz4.cxx:397
static const U64 prime5bytes
Definition lz4.cxx:389
int MLZ4_compress_fast_continue(MLZ4_stream_t *MLZ4_stream, const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
Definition lz4.cxx:1011
int MLZ4_saveDict(MLZ4_stream_t *MLZ4_dict, char *safeBuffer, int dictSize)
Definition lz4.cxx:1083
static void MLZ4_init(MLZ4_stream_t_internal *lz4ds, BYTE *base)
Definition lz4.cxx:1476
U32 hashTable[HASH_SIZE_U32]
Definition lz4.cxx:350
const BYTE * dictionary
Definition lz4.cxx:353
const BYTE * externalDict
Definition lz4.cxx:1308
static const int one
Definition xxhash.cxx:179