1333347Speter#include "svn_private_config.h"
2362181Sdim#ifdef SVN_INTERNAL_LZ4
3333347Speter/*
4333347Speter   LZ4 - Fast LZ compression algorithm
5333347Speter   Copyright (C) 2011-2016, Yann Collet.
6333347Speter
7333347Speter   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8333347Speter
9333347Speter   Redistribution and use in source and binary forms, with or without
10333347Speter   modification, are permitted provided that the following conditions are
11333347Speter   met:
12333347Speter
13333347Speter       * Redistributions of source code must retain the above copyright
14333347Speter   notice, this list of conditions and the following disclaimer.
15333347Speter       * Redistributions in binary form must reproduce the above
16333347Speter   copyright notice, this list of conditions and the following disclaimer
17333347Speter   in the documentation and/or other materials provided with the
18333347Speter   distribution.
19333347Speter
20333347Speter   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21333347Speter   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22333347Speter   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23333347Speter   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24333347Speter   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25333347Speter   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26333347Speter   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27333347Speter   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28333347Speter   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29333347Speter   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30333347Speter   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31333347Speter
32333347Speter   You can contact the author at :
33333347Speter    - LZ4 homepage : http://www.lz4.org
34333347Speter    - LZ4 source repository : https://github.com/lz4/lz4
35333347Speter*/
36333347Speter
37333347Speter
38333347Speter/*-************************************
39333347Speter*  Tuning parameters
40333347Speter**************************************/
41333347Speter/*
42333347Speter * HEAPMODE :
43333347Speter * Select how default compression functions will allocate memory for their hash table,
44333347Speter * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
45333347Speter */
46333347Speter#ifndef HEAPMODE
47333347Speter#  define HEAPMODE 0
48333347Speter#endif
49333347Speter
50333347Speter/*
51333347Speter * ACCELERATION_DEFAULT :
52333347Speter * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
53333347Speter */
54333347Speter#define ACCELERATION_DEFAULT 1
55333347Speter
56333347Speter
57333347Speter/*-************************************
58333347Speter*  CPU Feature Detection
59333347Speter**************************************/
60333347Speter/* LZ4_FORCE_MEMORY_ACCESS
61333347Speter * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
62333347Speter * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
63333347Speter * The below switch allow to select different access method for improved performance.
64333347Speter * Method 0 (default) : use `memcpy()`. Safe and portable.
65333347Speter * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
66333347Speter *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
67333347Speter * Method 2 : direct access. This method is portable but violate C standard.
68333347Speter *            It can generate buggy code on targets which generate assembly depending on alignment.
69333347Speter *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
70333347Speter * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
71333347Speter * Prefer these methods in priority order (0 > 1 > 2)
72333347Speter */
73333347Speter#ifndef LZ4_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
74333347Speter#  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
75333347Speter#    define LZ4_FORCE_MEMORY_ACCESS 2
76333347Speter#  elif defined(__INTEL_COMPILER) || \
77333347Speter  (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
78333347Speter#    define LZ4_FORCE_MEMORY_ACCESS 1
79333347Speter#  endif
80333347Speter#endif
81333347Speter
82333347Speter/*
83333347Speter * LZ4_FORCE_SW_BITCOUNT
84333347Speter * Define this parameter if your target system or compiler does not support hardware bit count
85333347Speter */
86333347Speter#if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for Windows CE does not support Hardware bit count */
87333347Speter#  define LZ4_FORCE_SW_BITCOUNT
88333347Speter#endif
89333347Speter
90333347Speter
91333347Speter/*-************************************
92333347Speter*  Dependency
93333347Speter**************************************/
94333347Speter#include "lz4internal.h"
95333347Speter/* see also "memory routines" below */
96333347Speter
97333347Speter/* Silence GCC's -Wmissing-prototypes warning. */
98333347Speterint LZ4_compress_fast_force(const char*, char*, int, int, int);
99333347Speterint LZ4_compress_forceExtDict (LZ4_stream_t*, const char*, char*, int);
100333347Speterint LZ4_decompress_safe_forceExtDict(const char*, char*, int, int, const char*, int);
101333347Speterint LZ4_uncompress (const char*, char*, int);
102333347Speterint LZ4_uncompress_unknownOutputSize (const char*, char*, int, int);
103333347Speter
104333347Speter/*-************************************
105333347Speter*  Compiler Options
106333347Speter**************************************/
107333347Speter#ifdef _MSC_VER    /* Visual Studio */
108333347Speter#  define FORCE_INLINE static __forceinline
109333347Speter#  include <intrin.h>
110333347Speter#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
111333347Speter#  pragma warning(disable : 4293)        /* disable: C4293: too large shift (32-bits) */
112333347Speter#else
113333347Speter#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */
114333347Speter#    if defined(__GNUC__) || defined(__clang__)
115333347Speter#      define FORCE_INLINE static inline __attribute__((always_inline))
116333347Speter#    else
117333347Speter#      define FORCE_INLINE static inline
118333347Speter#    endif
119333347Speter#  else
120333347Speter#    define FORCE_INLINE static
121333347Speter#  endif   /* __STDC_VERSION__ */
122333347Speter#endif  /* _MSC_VER */
123333347Speter
124333347Speter#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
125333347Speter#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )
126333347Speter#else
127333347Speter#  define expect(expr,value)    (expr)
128333347Speter#endif
129333347Speter
130333347Speter#define likely(expr)     expect((expr) != 0, 1)
131333347Speter#define unlikely(expr)   expect((expr) != 0, 0)
132333347Speter
133333347Speter
134333347Speter/*-************************************
135333347Speter*  Memory routines
136333347Speter**************************************/
137333347Speter#include <stdlib.h>   /* malloc, calloc, free */
138333347Speter#define ALLOCATOR(n,s) calloc(n,s)
139333347Speter#define FREEMEM        free
140333347Speter#include <string.h>   /* memset, memcpy */
141333347Speter#define MEM_INIT       memset
142333347Speter
143333347Speter
144333347Speter/*-************************************
145333347Speter*  Basic Types
146333347Speter**************************************/
147333347Speter#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
148333347Speter# include <stdint.h>
149333347Speter  typedef  uint8_t BYTE;
150333347Speter  typedef uint16_t U16;
151333347Speter  typedef uint32_t U32;
152333347Speter  typedef  int32_t S32;
153333347Speter  typedef uint64_t U64;
154333347Speter  typedef uintptr_t uptrval;
155333347Speter#else
156333347Speter  typedef unsigned char       BYTE;
157333347Speter  typedef unsigned short      U16;
158333347Speter  typedef unsigned int        U32;
159333347Speter  typedef   signed int        S32;
160333347Speter  typedef unsigned long long  U64;
161333347Speter  typedef size_t              uptrval;   /* generally true, except OpenVMS-64 */
162333347Speter#endif
163333347Speter
164333347Speter#if defined(__x86_64__)
165333347Speter  typedef U64    reg_t;   /* 64-bits in x32 mode */
166333347Speter#else
167333347Speter  typedef size_t reg_t;   /* 32-bits in x32 mode */
168333347Speter#endif
169333347Speter
170333347Speter/*-************************************
171333347Speter*  Reading and writing into memory
172333347Speter**************************************/
173333347Speterstatic unsigned LZ4_isLittleEndian(void)
174333347Speter{
175333347Speter    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental */
176333347Speter    return one.c[0];
177333347Speter}
178333347Speter
179333347Speter
180333347Speter#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
181333347Speter/* lie to the compiler about data alignment; use with caution */
182333347Speter
183333347Speterstatic U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }
184333347Speterstatic U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }
185333347Speterstatic reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; }
186333347Speter
187333347Speterstatic void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
188333347Speterstatic void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
189333347Speter
190333347Speter#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)
191333347Speter
192333347Speter/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
193333347Speter/* currently only defined for gcc and icc */
194333347Spetertypedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign;
195333347Speter
196333347Speterstatic U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
197333347Speterstatic U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
198333347Speterstatic reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; }
199333347Speter
200333347Speterstatic void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
201333347Speterstatic void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
202333347Speter
203333347Speter#else  /* safe and portable access through memcpy() */
204333347Speter
205333347Speterstatic U16 LZ4_read16(const void* memPtr)
206333347Speter{
207333347Speter    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
208333347Speter}
209333347Speter
210333347Speterstatic U32 LZ4_read32(const void* memPtr)
211333347Speter{
212333347Speter    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
213333347Speter}
214333347Speter
215333347Speterstatic reg_t LZ4_read_ARCH(const void* memPtr)
216333347Speter{
217333347Speter    reg_t val; memcpy(&val, memPtr, sizeof(val)); return val;
218333347Speter}
219333347Speter
220333347Speterstatic void LZ4_write16(void* memPtr, U16 value)
221333347Speter{
222333347Speter    memcpy(memPtr, &value, sizeof(value));
223333347Speter}
224333347Speter
225333347Speterstatic void LZ4_write32(void* memPtr, U32 value)
226333347Speter{
227333347Speter    memcpy(memPtr, &value, sizeof(value));
228333347Speter}
229333347Speter
230333347Speter#endif /* LZ4_FORCE_MEMORY_ACCESS */
231333347Speter
232333347Speter
233333347Speterstatic U16 LZ4_readLE16(const void* memPtr)
234333347Speter{
235333347Speter    if (LZ4_isLittleEndian()) {
236333347Speter        return LZ4_read16(memPtr);
237333347Speter    } else {
238333347Speter        const BYTE* p = (const BYTE*)memPtr;
239333347Speter        return (U16)((U16)p[0] + (p[1]<<8));
240333347Speter    }
241333347Speter}
242333347Speter
243333347Speterstatic void LZ4_writeLE16(void* memPtr, U16 value)
244333347Speter{
245333347Speter    if (LZ4_isLittleEndian()) {
246333347Speter        LZ4_write16(memPtr, value);
247333347Speter    } else {
248333347Speter        BYTE* p = (BYTE*)memPtr;
249333347Speter        p[0] = (BYTE) value;
250333347Speter        p[1] = (BYTE)(value>>8);
251333347Speter    }
252333347Speter}
253333347Speter
254333347Speterstatic void LZ4_copy8(void* dst, const void* src)
255333347Speter{
256333347Speter    memcpy(dst,src,8);
257333347Speter}
258333347Speter
259333347Speter/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
260333347Speterstatic void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
261333347Speter{
262333347Speter    BYTE* d = (BYTE*)dstPtr;
263333347Speter    const BYTE* s = (const BYTE*)srcPtr;
264333347Speter    BYTE* const e = (BYTE*)dstEnd;
265333347Speter
266333347Speter    do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
267333347Speter}
268333347Speter
269333347Speter
270333347Speter/*-************************************
271333347Speter*  Common Constants
272333347Speter**************************************/
273333347Speter#define MINMATCH 4
274333347Speter
275333347Speter#define WILDCOPYLENGTH 8
276333347Speter#define LASTLITERALS 5
277333347Speter#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
278333347Speterstatic const int LZ4_minLength = (MFLIMIT+1);
279333347Speter
280333347Speter#define KB *(1 <<10)
281333347Speter#define MB *(1 <<20)
282333347Speter#define GB *(1U<<30)
283333347Speter
284333347Speter#define MAXD_LOG 16
285333347Speter#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
286333347Speter
287333347Speter#define ML_BITS  4
288333347Speter#define ML_MASK  ((1U<<ML_BITS)-1)
289333347Speter#define RUN_BITS (8-ML_BITS)
290333347Speter#define RUN_MASK ((1U<<RUN_BITS)-1)
291333347Speter
292333347Speter
293333347Speter/*-************************************
294333347Speter*  Common Utils
295333347Speter**************************************/
296333347Speter#define LZ4_STATIC_ASSERT(c)    { enum { LZ4_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
297333347Speter
298333347Speter
299333347Speter/*-************************************
300333347Speter*  Common functions
301333347Speter**************************************/
302333347Speterstatic unsigned LZ4_NbCommonBytes (register reg_t val)
303333347Speter{
304333347Speter    if (LZ4_isLittleEndian()) {
305333347Speter        if (sizeof(val)==8) {
306333347Speter#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
307333347Speter            unsigned long r = 0;
308333347Speter            _BitScanForward64( &r, (U64)val );
309333347Speter            return (int)(r>>3);
310333347Speter#       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
311333347Speter            return (__builtin_ctzll((U64)val) >> 3);
312333347Speter#       else
313333347Speter            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 };
314333347Speter            return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
315333347Speter#       endif
316333347Speter        } else /* 32 bits */ {
317333347Speter#       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
318333347Speter            unsigned long r;
319333347Speter            _BitScanForward( &r, (U32)val );
320333347Speter            return (int)(r>>3);
321333347Speter#       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
322333347Speter            return (__builtin_ctz((U32)val) >> 3);
323333347Speter#       else
324333347Speter            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 };
325333347Speter            return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
326333347Speter#       endif
327333347Speter        }
328333347Speter    } else   /* Big Endian CPU */ {
329333347Speter        if (sizeof(val)==8) {
330333347Speter#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
331333347Speter            unsigned long r = 0;
332333347Speter            _BitScanReverse64( &r, val );
333333347Speter            return (unsigned)(r>>3);
334333347Speter#       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
335333347Speter            return (__builtin_clzll((U64)val) >> 3);
336333347Speter#       else
337333347Speter            unsigned r;
338333347Speter            if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
339333347Speter            if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
340333347Speter            r += (!val);
341333347Speter            return r;
342333347Speter#       endif
343333347Speter        } else /* 32 bits */ {
344333347Speter#       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
345333347Speter            unsigned long r = 0;
346333347Speter            _BitScanReverse( &r, (unsigned long)val );
347333347Speter            return (unsigned)(r>>3);
348333347Speter#       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
349333347Speter            return (__builtin_clz((U32)val) >> 3);
350333347Speter#       else
351333347Speter            unsigned r;
352333347Speter            if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
353333347Speter            r += (!val);
354333347Speter            return r;
355333347Speter#       endif
356333347Speter        }
357333347Speter    }
358333347Speter}
359333347Speter
360333347Speter#define STEPSIZE sizeof(reg_t)
361333347Speterstatic unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
362333347Speter{
363333347Speter    const BYTE* const pStart = pIn;
364333347Speter
365333347Speter    while (likely(pIn<pInLimit-(STEPSIZE-1))) {
366333347Speter        reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
367333347Speter        if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
368333347Speter        pIn += LZ4_NbCommonBytes(diff);
369333347Speter        return (unsigned)(pIn - pStart);
370333347Speter    }
371333347Speter
372333347Speter    if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
373333347Speter    if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
374333347Speter    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
375333347Speter    return (unsigned)(pIn - pStart);
376333347Speter}
377333347Speter
378333347Speter
379333347Speter#ifndef LZ4_COMMONDEFS_ONLY
380333347Speter/*-************************************
381333347Speter*  Local Constants
382333347Speter**************************************/
383333347Speterstatic const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
384333347Speterstatic const U32 LZ4_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */
385333347Speter
386333347Speter
387333347Speter/*-************************************
388333347Speter*  Local Structures and types
389333347Speter**************************************/
390333347Spetertypedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
391333347Spetertypedef enum { byPtr, byU32, byU16 } tableType_t;
392333347Speter
393333347Spetertypedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
394333347Spetertypedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
395333347Speter
396333347Spetertypedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
397333347Spetertypedef enum { full = 0, partial = 1 } earlyEnd_directive;
398333347Speter
399333347Speter
400333347Speter/*-************************************
401333347Speter*  Local Utils
402333347Speter**************************************/
403333347Speterint LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
404333347Speterconst char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
405333347Speterint LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }
406333347Speterint LZ4_sizeofState(void) { return LZ4_STREAMSIZE; }
407333347Speter
408333347Speter
409333347Speter/*-******************************
410333347Speter*  Compression functions
411333347Speter********************************/
412333347Speterstatic U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
413333347Speter{
414333347Speter    if (tableType == byU16)
415333347Speter        return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
416333347Speter    else
417333347Speter        return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
418333347Speter}
419333347Speter
420333347Speterstatic U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
421333347Speter{
422333347Speter    static const U64 prime5bytes = 889523592379ULL;
423333347Speter    static const U64 prime8bytes = 11400714785074694791ULL;
424333347Speter    const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
425333347Speter    if (LZ4_isLittleEndian())
426333347Speter        return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
427333347Speter    else
428333347Speter        return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
429333347Speter}
430333347Speter
431333347SpeterFORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
432333347Speter{
433333347Speter    if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);
434333347Speter    return LZ4_hash4(LZ4_read32(p), tableType);
435333347Speter}
436333347Speter
437333347Speterstatic void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
438333347Speter{
439333347Speter    switch (tableType)
440333347Speter    {
441333347Speter    case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
442333347Speter    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
443333347Speter    case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
444333347Speter    }
445333347Speter}
446333347Speter
447333347SpeterFORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
448333347Speter{
449333347Speter    U32 const h = LZ4_hashPosition(p, tableType);
450333347Speter    LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
451333347Speter}
452333347Speter
453333347Speterstatic const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
454333347Speter{
455333347Speter    if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
456333347Speter    if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
457333347Speter    { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; }   /* default, to ensure a return */
458333347Speter}
459333347Speter
460333347SpeterFORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
461333347Speter{
462333347Speter    U32 const h = LZ4_hashPosition(p, tableType);
463333347Speter    return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
464333347Speter}
465333347Speter
466333347Speter
467333347Speter/** LZ4_compress_generic() :
468333347Speter    inlined, to ensure branches are decided at compilation time */
469333347SpeterFORCE_INLINE int LZ4_compress_generic(
470333347Speter                 LZ4_stream_t_internal* const cctx,
471333347Speter                 const char* const source,
472333347Speter                 char* const dest,
473333347Speter                 const int inputSize,
474333347Speter                 const int maxOutputSize,
475333347Speter                 const limitedOutput_directive outputLimited,
476333347Speter                 const tableType_t tableType,
477333347Speter                 const dict_directive dict,
478333347Speter                 const dictIssue_directive dictIssue,
479333347Speter                 const U32 acceleration)
480333347Speter{
481333347Speter    const BYTE* ip = (const BYTE*) source;
482333347Speter    const BYTE* base;
483333347Speter    const BYTE* lowLimit;
484333347Speter    const BYTE* const lowRefLimit = ip - cctx->dictSize;
485333347Speter    const BYTE* const dictionary = cctx->dictionary;
486333347Speter    const BYTE* const dictEnd = dictionary + cctx->dictSize;
487333347Speter    const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source;
488333347Speter    const BYTE* anchor = (const BYTE*) source;
489333347Speter    const BYTE* const iend = ip + inputSize;
490333347Speter    const BYTE* const mflimit = iend - MFLIMIT;
491333347Speter    const BYTE* const matchlimit = iend - LASTLITERALS;
492333347Speter
493333347Speter    BYTE* op = (BYTE*) dest;
494333347Speter    BYTE* const olimit = op + maxOutputSize;
495333347Speter
496333347Speter    U32 forwardH;
497333347Speter
498333347Speter    /* Init conditions */
499333347Speter    if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0;   /* Unsupported inputSize, too large (or negative) */
500333347Speter    switch(dict)
501333347Speter    {
502333347Speter    case noDict:
503333347Speter    default:
504333347Speter        base = (const BYTE*)source;
505333347Speter        lowLimit = (const BYTE*)source;
506333347Speter        break;
507333347Speter    case withPrefix64k:
508333347Speter        base = (const BYTE*)source - cctx->currentOffset;
509333347Speter        lowLimit = (const BYTE*)source - cctx->dictSize;
510333347Speter        break;
511333347Speter    case usingExtDict:
512333347Speter        base = (const BYTE*)source - cctx->currentOffset;
513333347Speter        lowLimit = (const BYTE*)source;
514333347Speter        break;
515333347Speter    }
516333347Speter    if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
517333347Speter    if (inputSize<LZ4_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */
518333347Speter
519333347Speter    /* First Byte */
520333347Speter    LZ4_putPosition(ip, cctx->hashTable, tableType, base);
521333347Speter    ip++; forwardH = LZ4_hashPosition(ip, tableType);
522333347Speter
523333347Speter    /* Main Loop */
524333347Speter    for ( ; ; ) {
525333347Speter        ptrdiff_t refDelta = 0;
526333347Speter        const BYTE* match;
527333347Speter        BYTE* token;
528333347Speter
529333347Speter        /* Find a match */
530333347Speter        {   const BYTE* forwardIp = ip;
531333347Speter            unsigned step = 1;
532333347Speter            unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
533333347Speter            do {
534333347Speter                U32 const h = forwardH;
535333347Speter                ip = forwardIp;
536333347Speter                forwardIp += step;
537333347Speter                step = (searchMatchNb++ >> LZ4_skipTrigger);
538333347Speter
539333347Speter                if (unlikely(forwardIp > mflimit)) goto _last_literals;
540333347Speter
541333347Speter                match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);
542333347Speter                if (dict==usingExtDict) {
543333347Speter                    if (match < (const BYTE*)source) {
544333347Speter                        refDelta = dictDelta;
545333347Speter                        lowLimit = dictionary;
546333347Speter                    } else {
547333347Speter                        refDelta = 0;
548333347Speter                        lowLimit = (const BYTE*)source;
549333347Speter                }   }
550333347Speter                forwardH = LZ4_hashPosition(forwardIp, tableType);
551333347Speter                LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);
552333347Speter
553333347Speter            } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
554333347Speter                || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
555333347Speter                || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
556333347Speter        }
557333347Speter
558333347Speter        /* Catch up */
559333347Speter        while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
560333347Speter
561333347Speter        /* Encode Literals */
562333347Speter        {   unsigned const litLength = (unsigned)(ip - anchor);
563333347Speter            token = op++;
564333347Speter            if ((outputLimited) &&  /* Check output buffer overflow */
565333347Speter                (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
566333347Speter                return 0;
567333347Speter            if (litLength >= RUN_MASK) {
568333347Speter                int len = (int)litLength-RUN_MASK;
569333347Speter                *token = (RUN_MASK<<ML_BITS);
570333347Speter                for(; len >= 255 ; len-=255) *op++ = 255;
571333347Speter                *op++ = (BYTE)len;
572333347Speter            }
573333347Speter            else *token = (BYTE)(litLength<<ML_BITS);
574333347Speter
575333347Speter            /* Copy Literals */
576333347Speter            LZ4_wildCopy(op, anchor, op+litLength);
577333347Speter            op+=litLength;
578333347Speter        }
579333347Speter
580333347Speter_next_match:
581333347Speter        /* Encode Offset */
582333347Speter        LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
583333347Speter
584333347Speter        /* Encode MatchLength */
585333347Speter        {   unsigned matchCode;
586333347Speter
587333347Speter            if ((dict==usingExtDict) && (lowLimit==dictionary)) {
588333347Speter                const BYTE* limit;
589333347Speter                match += refDelta;
590333347Speter                limit = ip + (dictEnd-match);
591333347Speter                if (limit > matchlimit) limit = matchlimit;
592333347Speter                matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
593333347Speter                ip += MINMATCH + matchCode;
594333347Speter                if (ip==limit) {
595333347Speter                    unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit);
596333347Speter                    matchCode += more;
597333347Speter                    ip += more;
598333347Speter                }
599333347Speter            } else {
600333347Speter                matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
601333347Speter                ip += MINMATCH + matchCode;
602333347Speter            }
603333347Speter
604333347Speter            if ( outputLimited &&    /* Check output buffer overflow */
605333347Speter                (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) )
606333347Speter                return 0;
607333347Speter            if (matchCode >= ML_MASK) {
608333347Speter                *token += ML_MASK;
609333347Speter                matchCode -= ML_MASK;
610333347Speter                LZ4_write32(op, 0xFFFFFFFF);
611333347Speter                while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255;
612333347Speter                op += matchCode / 255;
613333347Speter                *op++ = (BYTE)(matchCode % 255);
614333347Speter            } else
615333347Speter                *token += (BYTE)(matchCode);
616333347Speter        }
617333347Speter
618333347Speter        anchor = ip;
619333347Speter
620333347Speter        /* Test end of chunk */
621333347Speter        if (ip > mflimit) break;
622333347Speter
623333347Speter        /* Fill table */
624333347Speter        LZ4_putPosition(ip-2, cctx->hashTable, tableType, base);
625333347Speter
626333347Speter        /* Test next position */
627333347Speter        match = LZ4_getPosition(ip, cctx->hashTable, tableType, base);
628333347Speter        if (dict==usingExtDict) {
629333347Speter            if (match < (const BYTE*)source) {
630333347Speter                refDelta = dictDelta;
631333347Speter                lowLimit = dictionary;
632333347Speter            } else {
633333347Speter                refDelta = 0;
634333347Speter                lowLimit = (const BYTE*)source;
635333347Speter        }   }
636333347Speter        LZ4_putPosition(ip, cctx->hashTable, tableType, base);
637333347Speter        if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
638333347Speter            && (match+MAX_DISTANCE>=ip)
639333347Speter            && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
640333347Speter        { token=op++; *token=0; goto _next_match; }
641333347Speter
642333347Speter        /* Prepare next loop */
643333347Speter        forwardH = LZ4_hashPosition(++ip, tableType);
644333347Speter    }
645333347Speter
646333347Speter_last_literals:
647333347Speter    /* Encode Last Literals */
648333347Speter    {   size_t const lastRun = (size_t)(iend - anchor);
649333347Speter        if ( (outputLimited) &&  /* Check output buffer overflow */
650333347Speter            ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) )
651333347Speter            return 0;
652333347Speter        if (lastRun >= RUN_MASK) {
653333347Speter            size_t accumulator = lastRun - RUN_MASK;
654333347Speter            *op++ = RUN_MASK << ML_BITS;
655333347Speter            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
656333347Speter            *op++ = (BYTE) accumulator;
657333347Speter        } else {
658333347Speter            *op++ = (BYTE)(lastRun<<ML_BITS);
659333347Speter        }
660333347Speter        memcpy(op, anchor, lastRun);
661333347Speter        op += lastRun;
662333347Speter    }
663333347Speter
664333347Speter    /* End */
665333347Speter    return (int) (((char*)op)-dest);
666333347Speter}
667333347Speter
668333347Speter
669333347Speterint LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
670333347Speter{
671333347Speter    LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;
672333347Speter    LZ4_resetStream((LZ4_stream_t*)state);
673333347Speter    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
674333347Speter
675333347Speter    if (maxOutputSize >= LZ4_compressBound(inputSize)) {
676333347Speter        if (inputSize < LZ4_64Klimit)
677333347Speter            return LZ4_compress_generic(ctx, source, dest, inputSize,             0,    notLimited,                        byU16, noDict, noDictIssue, acceleration);
678333347Speter        else
679333347Speter            return LZ4_compress_generic(ctx, source, dest, inputSize,             0,    notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
680333347Speter    } else {
681333347Speter        if (inputSize < LZ4_64Klimit)
682333347Speter            return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput,                        byU16, noDict, noDictIssue, acceleration);
683333347Speter        else
684333347Speter            return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
685333347Speter    }
686333347Speter}
687333347Speter
688333347Speter
689333347Speterint LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
690333347Speter{
691333347Speter#if (HEAPMODE)
692333347Speter    void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
693333347Speter#else
694333347Speter    LZ4_stream_t ctx;
695333347Speter    void* const ctxPtr = &ctx;
696333347Speter#endif
697333347Speter
698333347Speter    int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
699333347Speter
700333347Speter#if (HEAPMODE)
701333347Speter    FREEMEM(ctxPtr);
702333347Speter#endif
703333347Speter    return result;
704333347Speter}
705333347Speter
706333347Speter
707333347Speterint LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
708333347Speter{
709333347Speter    return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
710333347Speter}
711333347Speter
712333347Speter
713333347Speter/* hidden debug function */
714333347Speter/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
715333347Speterint LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
716333347Speter{
717333347Speter    LZ4_stream_t ctx;
718333347Speter    LZ4_resetStream(&ctx);
719333347Speter
720333347Speter    if (inputSize < LZ4_64Klimit)
721333347Speter        return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);
722333347Speter    else
723333347Speter        return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
724333347Speter}
725333347Speter
726333347Speter
727333347Speter/*-******************************
728333347Speter*  *_destSize() variant
729333347Speter********************************/
730333347Speter
731333347Speterstatic int LZ4_compress_destSize_generic(
732333347Speter                       LZ4_stream_t_internal* const ctx,
733333347Speter                 const char* const src,
734333347Speter                       char* const dst,
735333347Speter                       int*  const srcSizePtr,
736333347Speter                 const int targetDstSize,
737333347Speter                 const tableType_t tableType)
738333347Speter{
739333347Speter    const BYTE* ip = (const BYTE*) src;
740333347Speter    const BYTE* base = (const BYTE*) src;
741333347Speter    const BYTE* lowLimit = (const BYTE*) src;
742333347Speter    const BYTE* anchor = ip;
743333347Speter    const BYTE* const iend = ip + *srcSizePtr;
744333347Speter    const BYTE* const mflimit = iend - MFLIMIT;
745333347Speter    const BYTE* const matchlimit = iend - LASTLITERALS;
746333347Speter
747333347Speter    BYTE* op = (BYTE*) dst;
748333347Speter    BYTE* const oend = op + targetDstSize;
749333347Speter    BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
750333347Speter    BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
751333347Speter    BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
752333347Speter
753333347Speter    U32 forwardH;
754333347Speter
755333347Speter
756333347Speter    /* Init conditions */
757333347Speter    if (targetDstSize < 1) return 0;                                     /* Impossible to store anything */
758333347Speter    if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0;            /* Unsupported input size, too large (or negative) */
759333347Speter    if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
760333347Speter    if (*srcSizePtr<LZ4_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */
761333347Speter
762333347Speter    /* First Byte */
763333347Speter    *srcSizePtr = 0;
764333347Speter    LZ4_putPosition(ip, ctx->hashTable, tableType, base);
765333347Speter    ip++; forwardH = LZ4_hashPosition(ip, tableType);
766333347Speter
767333347Speter    /* Main Loop */
768333347Speter    for ( ; ; ) {
769333347Speter        const BYTE* match;
770333347Speter        BYTE* token;
771333347Speter
772333347Speter        /* Find a match */
773333347Speter        {   const BYTE* forwardIp = ip;
774333347Speter            unsigned step = 1;
775333347Speter            unsigned searchMatchNb = 1 << LZ4_skipTrigger;
776333347Speter
777333347Speter            do {
778333347Speter                U32 h = forwardH;
779333347Speter                ip = forwardIp;
780333347Speter                forwardIp += step;
781333347Speter                step = (searchMatchNb++ >> LZ4_skipTrigger);
782333347Speter
783333347Speter                if (unlikely(forwardIp > mflimit)) goto _last_literals;
784333347Speter
785333347Speter                match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base);
786333347Speter                forwardH = LZ4_hashPosition(forwardIp, tableType);
787333347Speter                LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base);
788333347Speter
789333347Speter            } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
790333347Speter                || (LZ4_read32(match) != LZ4_read32(ip)) );
791333347Speter        }
792333347Speter
793333347Speter        /* Catch up */
794333347Speter        while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
795333347Speter
796333347Speter        /* Encode Literal length */
797333347Speter        {   unsigned litLength = (unsigned)(ip - anchor);
798333347Speter            token = op++;
799333347Speter            if (op + ((litLength+240)/255) + litLength > oMaxLit) {
800333347Speter                /* Not enough space for a last match */
801333347Speter                op--;
802333347Speter                goto _last_literals;
803333347Speter            }
804333347Speter            if (litLength>=RUN_MASK) {
805333347Speter                unsigned len = litLength - RUN_MASK;
806333347Speter                *token=(RUN_MASK<<ML_BITS);
807333347Speter                for(; len >= 255 ; len-=255) *op++ = 255;
808333347Speter                *op++ = (BYTE)len;
809333347Speter            }
810333347Speter            else *token = (BYTE)(litLength<<ML_BITS);
811333347Speter
812333347Speter            /* Copy Literals */
813333347Speter            LZ4_wildCopy(op, anchor, op+litLength);
814333347Speter            op += litLength;
815333347Speter        }
816333347Speter
817333347Speter_next_match:
818333347Speter        /* Encode Offset */
819333347Speter        LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
820333347Speter
821333347Speter        /* Encode MatchLength */
822333347Speter        {   size_t matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
823333347Speter
824333347Speter            if (op + ((matchLength+240)/255) > oMaxMatch) {
825333347Speter                /* Match description too long : reduce it */
826333347Speter                matchLength = (15-1) + (oMaxMatch-op) * 255;
827333347Speter            }
828333347Speter            ip += MINMATCH + matchLength;
829333347Speter
830333347Speter            if (matchLength>=ML_MASK) {
831333347Speter                *token += ML_MASK;
832333347Speter                matchLength -= ML_MASK;
833333347Speter                while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
834333347Speter                *op++ = (BYTE)matchLength;
835333347Speter            }
836333347Speter            else *token += (BYTE)(matchLength);
837333347Speter        }
838333347Speter
839333347Speter        anchor = ip;
840333347Speter
841333347Speter        /* Test end of block */
842333347Speter        if (ip > mflimit) break;
843333347Speter        if (op > oMaxSeq) break;
844333347Speter
845333347Speter        /* Fill table */
846333347Speter        LZ4_putPosition(ip-2, ctx->hashTable, tableType, base);
847333347Speter
848333347Speter        /* Test next position */
849333347Speter        match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
850333347Speter        LZ4_putPosition(ip, ctx->hashTable, tableType, base);
851333347Speter        if ( (match+MAX_DISTANCE>=ip)
852333347Speter            && (LZ4_read32(match)==LZ4_read32(ip)) )
853333347Speter        { token=op++; *token=0; goto _next_match; }
854333347Speter
855333347Speter        /* Prepare next loop */
856333347Speter        forwardH = LZ4_hashPosition(++ip, tableType);
857333347Speter    }
858333347Speter
859333347Speter_last_literals:
860333347Speter    /* Encode Last Literals */
861333347Speter    {   size_t lastRunSize = (size_t)(iend - anchor);
862333347Speter        if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) {
863333347Speter            /* adapt lastRunSize to fill 'dst' */
864333347Speter            lastRunSize  = (oend-op) - 1;
865333347Speter            lastRunSize -= (lastRunSize+240)/255;
866333347Speter        }
867333347Speter        ip = anchor + lastRunSize;
868333347Speter
869333347Speter        if (lastRunSize >= RUN_MASK) {
870333347Speter            size_t accumulator = lastRunSize - RUN_MASK;
871333347Speter            *op++ = RUN_MASK << ML_BITS;
872333347Speter            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
873333347Speter            *op++ = (BYTE) accumulator;
874333347Speter        } else {
875333347Speter            *op++ = (BYTE)(lastRunSize<<ML_BITS);
876333347Speter        }
877333347Speter        memcpy(op, anchor, lastRunSize);
878333347Speter        op += lastRunSize;
879333347Speter    }
880333347Speter
881333347Speter    /* End */
882333347Speter    *srcSizePtr = (int) (((const char*)ip)-src);
883333347Speter    return (int) (((char*)op)-dst);
884333347Speter}
885333347Speter
886333347Speter
887333347Speterstatic int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
888333347Speter{
889333347Speter    LZ4_resetStream(state);
890333347Speter
891333347Speter    if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) {  /* compression success is guaranteed */
892333347Speter        return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
893333347Speter    } else {
894333347Speter        if (*srcSizePtr < LZ4_64Klimit)
895333347Speter            return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16);
896333347Speter        else
897333347Speter            return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr);
898333347Speter    }
899333347Speter}
900333347Speter
901333347Speter
902333347Speterint LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
903333347Speter{
904333347Speter#if (HEAPMODE)
905333347Speter    LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
906333347Speter#else
907333347Speter    LZ4_stream_t ctxBody;
908333347Speter    LZ4_stream_t* ctx = &ctxBody;
909333347Speter#endif
910333347Speter
911333347Speter    int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
912333347Speter
913333347Speter#if (HEAPMODE)
914333347Speter    FREEMEM(ctx);
915333347Speter#endif
916333347Speter    return result;
917333347Speter}
918333347Speter
919333347Speter
920333347Speter
921333347Speter/*-******************************
922333347Speter*  Streaming functions
923333347Speter********************************/
924333347Speter
925333347SpeterLZ4_stream_t* LZ4_createStream(void)
926333347Speter{
927333347Speter    LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
928333347Speter    LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal));    /* A compilation error here means LZ4_STREAMSIZE is not large enough */
929333347Speter    LZ4_resetStream(lz4s);
930333347Speter    return lz4s;
931333347Speter}
932333347Speter
933333347Spetervoid LZ4_resetStream (LZ4_stream_t* LZ4_stream)
934333347Speter{
935333347Speter    MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
936333347Speter}
937333347Speter
938333347Speterint LZ4_freeStream (LZ4_stream_t* LZ4_stream)
939333347Speter{
940333347Speter    FREEMEM(LZ4_stream);
941333347Speter    return (0);
942333347Speter}
943333347Speter
944333347Speter
945333347Speter#define HASH_UNIT sizeof(reg_t)
946333347Speterint LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
947333347Speter{
948333347Speter    LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse;
949333347Speter    const BYTE* p = (const BYTE*)dictionary;
950333347Speter    const BYTE* const dictEnd = p + dictSize;
951333347Speter    const BYTE* base;
952333347Speter
953333347Speter    if ((dict->initCheck) || (dict->currentOffset > 1 GB))  /* Uninitialized structure, or reuse overflow */
954333347Speter        LZ4_resetStream(LZ4_dict);
955333347Speter
956333347Speter    if (dictSize < (int)HASH_UNIT) {
957333347Speter        dict->dictionary = NULL;
958333347Speter        dict->dictSize = 0;
959333347Speter        return 0;
960333347Speter    }
961333347Speter
962333347Speter    if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
963333347Speter    dict->currentOffset += 64 KB;
964333347Speter    base = p - dict->currentOffset;
965333347Speter    dict->dictionary = p;
966333347Speter    dict->dictSize = (U32)(dictEnd - p);
967333347Speter    dict->currentOffset += dict->dictSize;
968333347Speter
969333347Speter    while (p <= dictEnd-HASH_UNIT) {
970333347Speter        LZ4_putPosition(p, dict->hashTable, byU32, base);
971333347Speter        p+=3;
972333347Speter    }
973333347Speter
974333347Speter    return dict->dictSize;
975333347Speter}
976333347Speter
977333347Speter
978333347Speterstatic void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
979333347Speter{
980333347Speter    if ((LZ4_dict->currentOffset > 0x80000000) ||
981333347Speter        ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) {   /* address space overflow */
982333347Speter        /* rescale hash table */
983333347Speter        U32 const delta = LZ4_dict->currentOffset - 64 KB;
984333347Speter        const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
985333347Speter        int i;
986333347Speter        for (i=0; i<LZ4_HASH_SIZE_U32; i++) {
987333347Speter            if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
988333347Speter            else LZ4_dict->hashTable[i] -= delta;
989333347Speter        }
990333347Speter        LZ4_dict->currentOffset = 64 KB;
991333347Speter        if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
992333347Speter        LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
993333347Speter    }
994333347Speter}
995333347Speter
996333347Speter
997333347Speterint LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
998333347Speter{
999333347Speter    LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse;
1000333347Speter    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
1001333347Speter
1002333347Speter    const BYTE* smallest = (const BYTE*) source;
1003333347Speter    if (streamPtr->initCheck) return 0;   /* Uninitialized structure detected */
1004333347Speter    if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
1005333347Speter    LZ4_renormDictT(streamPtr, smallest);
1006333347Speter    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
1007333347Speter
1008333347Speter    /* Check overlapping input/dictionary space */
1009333347Speter    {   const BYTE* sourceEnd = (const BYTE*) source + inputSize;
1010333347Speter        if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
1011333347Speter            streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
1012333347Speter            if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
1013333347Speter            if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
1014333347Speter            streamPtr->dictionary = dictEnd - streamPtr->dictSize;
1015333347Speter        }
1016333347Speter    }
1017333347Speter
1018333347Speter    /* prefix mode : source data follows dictionary */
1019333347Speter    if (dictEnd == (const BYTE*)source) {
1020333347Speter        int result;
1021333347Speter        if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
1022333347Speter            result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
1023333347Speter        else
1024333347Speter            result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
1025333347Speter        streamPtr->dictSize += (U32)inputSize;
1026333347Speter        streamPtr->currentOffset += (U32)inputSize;
1027333347Speter        return result;
1028333347Speter    }
1029333347Speter
1030333347Speter    /* external dictionary mode */
1031333347Speter    {   int result;
1032333347Speter        if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
1033333347Speter            result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
1034333347Speter        else
1035333347Speter            result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
1036333347Speter        streamPtr->dictionary = (const BYTE*)source;
1037333347Speter        streamPtr->dictSize = (U32)inputSize;
1038333347Speter        streamPtr->currentOffset += (U32)inputSize;
1039333347Speter        return result;
1040333347Speter    }
1041333347Speter}
1042333347Speter
1043333347Speter
1044333347Speter/* Hidden debug function, to force external dictionary mode */
1045333347Speterint LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
1046333347Speter{
1047333347Speter    LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse;
1048333347Speter    int result;
1049333347Speter    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
1050333347Speter
1051333347Speter    const BYTE* smallest = dictEnd;
1052333347Speter    if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
1053333347Speter    LZ4_renormDictT(streamPtr, smallest);
1054333347Speter
1055333347Speter    result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
1056333347Speter
1057333347Speter    streamPtr->dictionary = (const BYTE*)source;
1058333347Speter    streamPtr->dictSize = (U32)inputSize;
1059333347Speter    streamPtr->currentOffset += (U32)inputSize;
1060333347Speter
1061333347Speter    return result;
1062333347Speter}
1063333347Speter
1064333347Speter
1065333347Speter/*! LZ4_saveDict() :
1066333347Speter *  If previously compressed data block is not guaranteed to remain available at its memory location,
1067333347Speter *  save it into a safer place (char* safeBuffer).
1068333347Speter *  Note : you don't need to call LZ4_loadDict() afterwards,
1069333347Speter *         dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue().
1070333347Speter *  Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
1071333347Speter */
1072333347Speterint LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
1073333347Speter{
1074333347Speter    LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
1075333347Speter    const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
1076333347Speter
1077333347Speter    if ((U32)dictSize > 64 KB) dictSize = 64 KB;   /* useless to define a dictionary > 64 KB */
1078333347Speter    if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
1079333347Speter
1080333347Speter    memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
1081333347Speter
1082333347Speter    dict->dictionary = (const BYTE*)safeBuffer;
1083333347Speter    dict->dictSize = (U32)dictSize;
1084333347Speter
1085333347Speter    return dictSize;
1086333347Speter}
1087333347Speter
1088333347Speter
1089333347Speter
1090333347Speter/*-*****************************
1091333347Speter*  Decompression functions
1092333347Speter*******************************/
1093333347Speter/*! LZ4_decompress_generic() :
1094333347Speter *  This generic decompression function cover all use cases.
1095333347Speter *  It shall be instantiated several times, using different sets of directives
1096333347Speter *  Note that it is important this generic function is really inlined,
1097333347Speter *  in order to remove useless branches during compilation optimization.
1098333347Speter */
1099333347SpeterFORCE_INLINE int LZ4_decompress_generic(
1100333347Speter                 const char* const source,
1101333347Speter                 char* const dest,
1102333347Speter                 int inputSize,
1103333347Speter                 int outputSize,         /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
1104333347Speter
1105333347Speter                 int endOnInput,         /* endOnOutputSize, endOnInputSize */
1106333347Speter                 int partialDecoding,    /* full, partial */
1107333347Speter                 int targetOutputSize,   /* only used if partialDecoding==partial */
1108333347Speter                 int dict,               /* noDict, withPrefix64k, usingExtDict */
1109333347Speter                 const BYTE* const lowPrefix,  /* == dest when no prefix */
1110333347Speter                 const BYTE* const dictStart,  /* only if dict==usingExtDict */
1111333347Speter                 const size_t dictSize         /* note : = 0 if noDict */
1112333347Speter                 )
1113333347Speter{
1114333347Speter    /* Local Variables */
1115333347Speter    const BYTE* ip = (const BYTE*) source;
1116333347Speter    const BYTE* const iend = ip + inputSize;
1117333347Speter
1118333347Speter    BYTE* op = (BYTE*) dest;
1119333347Speter    BYTE* const oend = op + outputSize;
1120333347Speter    BYTE* cpy;
1121333347Speter    BYTE* oexit = op + targetOutputSize;
1122333347Speter    const BYTE* const lowLimit = lowPrefix - dictSize;
1123333347Speter
1124333347Speter    const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
1125333347Speter    const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};
1126333347Speter    const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
1127333347Speter
1128333347Speter    const int safeDecode = (endOnInput==endOnInputSize);
1129333347Speter    const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
1130333347Speter
1131333347Speter
1132333347Speter    /* Special cases */
1133333347Speter    if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT;                        /* targetOutputSize too high => decode everything */
1134333347Speter    if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1;  /* Empty output buffer */
1135333347Speter    if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
1136333347Speter
1137333347Speter    /* Main Loop : decode sequences */
1138333347Speter    while (1) {
1139333347Speter        size_t length;
1140333347Speter        const BYTE* match;
1141333347Speter        size_t offset;
1142333347Speter
1143333347Speter        /* get literal length */
1144333347Speter        unsigned const token = *ip++;
1145333347Speter        if ((length=(token>>ML_BITS)) == RUN_MASK) {
1146333347Speter            unsigned s;
1147333347Speter            do {
1148333347Speter                s = *ip++;
1149333347Speter                length += s;
1150333347Speter            } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) );
1151333347Speter            if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error;   /* overflow detection */
1152333347Speter            if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error;   /* overflow detection */
1153333347Speter        }
1154333347Speter
1155333347Speter        /* copy literals */
1156333347Speter        cpy = op+length;
1157333347Speter        if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
1158333347Speter            || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) )
1159333347Speter        {
1160333347Speter            if (partialDecoding) {
1161333347Speter                if (cpy > oend) goto _output_error;                           /* Error : write attempt beyond end of output buffer */
1162333347Speter                if ((endOnInput) && (ip+length > iend)) goto _output_error;   /* Error : read attempt beyond end of input buffer */
1163333347Speter            } else {
1164333347Speter                if ((!endOnInput) && (cpy != oend)) goto _output_error;       /* Error : block decoding must stop exactly there */
1165333347Speter                if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error;   /* Error : input must be consumed */
1166333347Speter            }
1167333347Speter            memcpy(op, ip, length);
1168333347Speter            ip += length;
1169333347Speter            op += length;
1170333347Speter            break;     /* Necessarily EOF, due to parsing restrictions */
1171333347Speter        }
1172333347Speter        LZ4_wildCopy(op, ip, cpy);
1173333347Speter        ip += length; op = cpy;
1174333347Speter
1175333347Speter        /* get offset */
1176333347Speter        offset = LZ4_readLE16(ip); ip+=2;
1177333347Speter        match = op - offset;
1178333347Speter        if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error;   /* Error : offset outside buffers */
1179333347Speter        LZ4_write32(op, (U32)offset);   /* costs ~1%; silence an msan warning when offset==0 */
1180333347Speter
1181333347Speter        /* get matchlength */
1182333347Speter        length = token & ML_MASK;
1183333347Speter        if (length == ML_MASK) {
1184333347Speter            unsigned s;
1185333347Speter            do {
1186333347Speter                s = *ip++;
1187333347Speter                if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
1188333347Speter                length += s;
1189333347Speter            } while (s==255);
1190333347Speter            if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error;   /* overflow detection */
1191333347Speter        }
1192333347Speter        length += MINMATCH;
1193333347Speter
1194333347Speter        /* check external dictionary */
1195333347Speter        if ((dict==usingExtDict) && (match < lowPrefix)) {
1196333347Speter            if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error;   /* doesn't respect parsing restriction */
1197333347Speter
1198333347Speter            if (length <= (size_t)(lowPrefix-match)) {
1199333347Speter                /* match can be copied as a single segment from external dictionary */
1200333347Speter                memmove(op, dictEnd - (lowPrefix-match), length);
1201333347Speter                op += length;
1202333347Speter            } else {
1203333347Speter                /* match encompass external dictionary and current block */
1204333347Speter                size_t const copySize = (size_t)(lowPrefix-match);
1205333347Speter                size_t const restSize = length - copySize;
1206333347Speter                memcpy(op, dictEnd - copySize, copySize);
1207333347Speter                op += copySize;
1208333347Speter                if (restSize > (size_t)(op-lowPrefix)) {  /* overlap copy */
1209333347Speter                    BYTE* const endOfMatch = op + restSize;
1210333347Speter                    const BYTE* copyFrom = lowPrefix;
1211333347Speter                    while (op < endOfMatch) *op++ = *copyFrom++;
1212333347Speter                } else {
1213333347Speter                    memcpy(op, lowPrefix, restSize);
1214333347Speter                    op += restSize;
1215333347Speter            }   }
1216333347Speter            continue;
1217333347Speter        }
1218333347Speter
1219333347Speter        /* copy match within block */
1220333347Speter        cpy = op + length;
1221333347Speter        if (unlikely(offset<8)) {
1222333347Speter            const int dec64 = dec64table[offset];
1223333347Speter            op[0] = match[0];
1224333347Speter            op[1] = match[1];
1225333347Speter            op[2] = match[2];
1226333347Speter            op[3] = match[3];
1227333347Speter            match += dec32table[offset];
1228333347Speter            memcpy(op+4, match, 4);
1229333347Speter            match -= dec64;
1230333347Speter        } else { LZ4_copy8(op, match); match+=8; }
1231333347Speter        op += 8;
1232333347Speter
1233333347Speter        if (unlikely(cpy>oend-12)) {
1234333347Speter            BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
1235333347Speter            if (cpy > oend-LASTLITERALS) goto _output_error;    /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
1236333347Speter            if (op < oCopyLimit) {
1237333347Speter                LZ4_wildCopy(op, match, oCopyLimit);
1238333347Speter                match += oCopyLimit - op;
1239333347Speter                op = oCopyLimit;
1240333347Speter            }
1241333347Speter            while (op<cpy) *op++ = *match++;
1242333347Speter        } else {
1243333347Speter            LZ4_copy8(op, match);
1244333347Speter            if (length>16) LZ4_wildCopy(op+8, match+8, cpy);
1245333347Speter        }
1246333347Speter        op=cpy;   /* correction */
1247333347Speter    }
1248333347Speter
1249333347Speter    /* end of decoding */
1250333347Speter    if (endOnInput)
1251333347Speter       return (int) (((char*)op)-dest);     /* Nb of output bytes decoded */
1252333347Speter    else
1253333347Speter       return (int) (((const char*)ip)-source);   /* Nb of input bytes read */
1254333347Speter
1255333347Speter    /* Overflow error detected */
1256333347Speter_output_error:
1257333347Speter    return (int) (-(((const char*)ip)-source))-1;
1258333347Speter}
1259333347Speter
1260333347Speter
1261333347Speterint LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
1262333347Speter{
1263333347Speter    return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
1264333347Speter}
1265333347Speter
1266333347Speterint LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
1267333347Speter{
1268333347Speter    return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
1269333347Speter}
1270333347Speter
1271333347Speterint LZ4_decompress_fast(const char* source, char* dest, int originalSize)
1272333347Speter{
1273333347Speter    return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
1274333347Speter}
1275333347Speter
1276333347Speter
1277333347Speter/*===== streaming decompression functions =====*/
1278333347Speter
1279333347Speter/*
1280333347Speter * If you prefer dynamic allocation methods,
1281333347Speter * LZ4_createStreamDecode()
1282333347Speter * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
1283333347Speter */
1284333347SpeterLZ4_streamDecode_t* LZ4_createStreamDecode(void)
1285333347Speter{
1286333347Speter    LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
1287333347Speter    return lz4s;
1288333347Speter}
1289333347Speter
1290333347Speterint LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
1291333347Speter{
1292333347Speter    FREEMEM(LZ4_stream);
1293333347Speter    return 0;
1294333347Speter}
1295333347Speter
1296333347Speter/*!
1297333347Speter * LZ4_setStreamDecode() :
1298333347Speter * Use this function to instruct where to find the dictionary.
1299333347Speter * This function is not necessary if previous data is still available where it was decoded.
1300333347Speter * Loading a size of 0 is allowed (same effect as no dictionary).
1301333347Speter * Return : 1 if OK, 0 if error
1302333347Speter */
1303333347Speterint LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
1304333347Speter{
1305333347Speter    LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
1306333347Speter    lz4sd->prefixSize = (size_t) dictSize;
1307333347Speter    lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
1308333347Speter    lz4sd->externalDict = NULL;
1309333347Speter    lz4sd->extDictSize  = 0;
1310333347Speter    return 1;
1311333347Speter}
1312333347Speter
1313333347Speter/*
1314333347Speter*_continue() :
1315333347Speter    These decoding functions allow decompression of multiple blocks in "streaming" mode.
1316333347Speter    Previously decoded blocks must still be available at the memory position where they were decoded.
1317333347Speter    If it's not possible, save the relevant part of decoded data into a safe buffer,
1318333347Speter    and indicate where it stands using LZ4_setStreamDecode()
1319333347Speter*/
1320333347Speterint LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
1321333347Speter{
1322333347Speter    LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
1323333347Speter    int result;
1324333347Speter
1325333347Speter    if (lz4sd->prefixEnd == (BYTE*)dest) {
1326333347Speter        result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
1327333347Speter                                        endOnInputSize, full, 0,
1328333347Speter                                        usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
1329333347Speter        if (result <= 0) return result;
1330333347Speter        lz4sd->prefixSize += result;
1331333347Speter        lz4sd->prefixEnd  += result;
1332333347Speter    } else {
1333333347Speter        lz4sd->extDictSize = lz4sd->prefixSize;
1334333347Speter        lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
1335333347Speter        result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
1336333347Speter                                        endOnInputSize, full, 0,
1337333347Speter                                        usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
1338333347Speter        if (result <= 0) return result;
1339333347Speter        lz4sd->prefixSize = result;
1340333347Speter        lz4sd->prefixEnd  = (BYTE*)dest + result;
1341333347Speter    }
1342333347Speter
1343333347Speter    return result;
1344333347Speter}
1345333347Speter
1346333347Speterint LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
1347333347Speter{
1348333347Speter    LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
1349333347Speter    int result;
1350333347Speter
1351333347Speter    if (lz4sd->prefixEnd == (BYTE*)dest) {
1352333347Speter        result = LZ4_decompress_generic(source, dest, 0, originalSize,
1353333347Speter                                        endOnOutputSize, full, 0,
1354333347Speter                                        usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
1355333347Speter        if (result <= 0) return result;
1356333347Speter        lz4sd->prefixSize += originalSize;
1357333347Speter        lz4sd->prefixEnd  += originalSize;
1358333347Speter    } else {
1359333347Speter        lz4sd->extDictSize = lz4sd->prefixSize;
1360333347Speter        lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
1361333347Speter        result = LZ4_decompress_generic(source, dest, 0, originalSize,
1362333347Speter                                        endOnOutputSize, full, 0,
1363333347Speter                                        usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
1364333347Speter        if (result <= 0) return result;
1365333347Speter        lz4sd->prefixSize = originalSize;
1366333347Speter        lz4sd->prefixEnd  = (BYTE*)dest + originalSize;
1367333347Speter    }
1368333347Speter
1369333347Speter    return result;
1370333347Speter}
1371333347Speter
1372333347Speter
1373333347Speter/*
1374333347SpeterAdvanced decoding functions :
1375333347Speter*_usingDict() :
1376333347Speter    These decoding functions work the same as "_continue" ones,
1377333347Speter    the dictionary must be explicitly provided within parameters
1378333347Speter*/
1379333347Speter
1380333347SpeterFORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
1381333347Speter{
1382333347Speter    if (dictSize==0)
1383333347Speter        return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
1384333347Speter    if (dictStart+dictSize == dest) {
1385333347Speter        if (dictSize >= (int)(64 KB - 1))
1386333347Speter            return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
1387333347Speter        return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
1388333347Speter    }
1389333347Speter    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
1390333347Speter}
1391333347Speter
1392333347Speterint LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
1393333347Speter{
1394333347Speter    return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
1395333347Speter}
1396333347Speter
1397333347Speterint LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
1398333347Speter{
1399333347Speter    return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
1400333347Speter}
1401333347Speter
1402333347Speter/* debug function */
1403333347Speterint LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
1404333347Speter{
1405333347Speter    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
1406333347Speter}
1407333347Speter
1408333347Speter
1409333347Speter/*=*************************************************
1410333347Speter*  Obsolete Functions
1411333347Speter***************************************************/
1412333347Speter/* obsolete compression functions */
1413333347Speterint LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
1414333347Speterint LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); }
1415333347Speterint LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }
1416333347Speterint LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); }
1417333347Speterint LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); }
1418333347Speterint LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); }
1419333347Speter
1420333347Speter/*
1421333347SpeterThese function names are deprecated and should no longer be used.
1422333347SpeterThey are only provided here for compatibility with older user programs.
1423333347Speter- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
1424333347Speter- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
1425333347Speter*/
1426333347Speterint LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
1427333347Speterint LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
1428333347Speter
1429333347Speter
1430333347Speter/* Obsolete Streaming functions */
1431333347Speter
1432333347Speterint LZ4_sizeofStreamState(void) { return LZ4_STREAMSIZE; }
1433333347Speter
1434333347Speterstatic void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base)
1435333347Speter{
1436333347Speter    MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t));
1437333347Speter    lz4ds->internal_donotuse.bufferStart = base;
1438333347Speter}
1439333347Speter
1440333347Speterint LZ4_resetStreamState(void* state, char* inputBuffer)
1441333347Speter{
1442333347Speter    if ((((uptrval)state) & 3) != 0) return 1;   /* Error : pointer is not aligned on 4-bytes boundary */
1443333347Speter    LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer);
1444333347Speter    return 0;
1445333347Speter}
1446333347Speter
1447333347Spetervoid* LZ4_create (char* inputBuffer)
1448333347Speter{
1449333347Speter    LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t));
1450333347Speter    LZ4_init (lz4ds, (BYTE*)inputBuffer);
1451333347Speter    return lz4ds;
1452333347Speter}
1453333347Speter
1454333347Speterchar* LZ4_slideInputBuffer (void* LZ4_Data)
1455333347Speter{
1456333347Speter    LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse;
1457333347Speter    int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB);
1458333347Speter    return (char*)(ctx->bufferStart + dictSize);
1459333347Speter}
1460333347Speter
1461333347Speter/* Obsolete streaming decompression functions */
1462333347Speter
1463333347Speterint LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
1464333347Speter{
1465333347Speter    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
1466333347Speter}
1467333347Speter
1468333347Speterint LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
1469333347Speter{
1470333347Speter    return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
1471333347Speter}
1472333347Speter
1473333347Speter#endif   /* LZ4_COMMONDEFS_ONLY */
1474333347Speter#else /* !SVN_INTERNAL_LZ4 */
1475333347Speter
1476333347Speter/* Silence OSX ranlib warnings about object files with no symbols. */
1477333347Speter#include <apr.h>
1478333347Speterextern const apr_uint32_t svn__fake__lz4internal;
1479333347Speterconst apr_uint32_t svn__fake__lz4internal = 0xdeadbeef;
1480333347Speter
1481333347Speter#endif /* SVN_INTERNAL_LZ4 */
1482