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