kusano 7d535a
/*
kusano 7d535a
   LZ4 - Fast LZ compression algorithm
kusano 7d535a
   Copyright (C) 2011-2015, Yann Collet.
kusano 7d535a
kusano 7d535a
   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
kusano 7d535a
kusano 7d535a
   Redistribution and use in source and binary forms, with or without
kusano 7d535a
   modification, are permitted provided that the following conditions are
kusano 7d535a
   met:
kusano 7d535a
kusano 7d535a
       * Redistributions of source code must retain the above copyright
kusano 7d535a
   notice, this list of conditions and the following disclaimer.
kusano 7d535a
       * Redistributions in binary form must reproduce the above
kusano 7d535a
   copyright notice, this list of conditions and the following disclaimer
kusano 7d535a
   in the documentation and/or other materials provided with the
kusano 7d535a
   distribution.
kusano 7d535a
kusano 7d535a
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
kusano 7d535a
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
kusano 7d535a
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
kusano 7d535a
   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
kusano 7d535a
   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
kusano 7d535a
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
kusano 7d535a
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
kusano 7d535a
   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
kusano 7d535a
   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
kusano 7d535a
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
kusano 7d535a
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kusano 7d535a
kusano 7d535a
   You can contact the author at :
kusano 7d535a
   - LZ4 source repository : https://github.com/Cyan4973/lz4
kusano 7d535a
   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
kusano 7d535a
*/
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Tuning parameters
kusano 7d535a
**************************************/
kusano 7d535a
/*
kusano 7d535a
 * HEAPMODE :
kusano 7d535a
 * Select how default compression functions will allocate memory for their hash table,
kusano 7d535a
 * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
kusano 7d535a
 */
kusano 7d535a
#define HEAPMODE 0
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * ACCELERATION_DEFAULT :
kusano 7d535a
 * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
kusano 7d535a
 */
kusano 7d535a
#define ACCELERATION_DEFAULT 1
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  CPU Feature Detection
kusano 7d535a
**************************************/
kusano 7d535a
/*
kusano 7d535a
 * LZ4_FORCE_SW_BITCOUNT
kusano 7d535a
 * Define this parameter if your target system or compiler does not support hardware bit count
kusano 7d535a
 */
kusano 7d535a
#if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for Windows CE does not support Hardware bit count */
kusano 7d535a
#  define LZ4_FORCE_SW_BITCOUNT
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Includes
kusano 7d535a
**************************************/
kusano 7d535a
#include "lz4.h"
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Compiler Options
kusano 7d535a
**************************************/
kusano 7d535a
#ifdef _MSC_VER    /* Visual Studio */
kusano 7d535a
#  define FORCE_INLINE static __forceinline
kusano 7d535a
#  include <intrin.h></intrin.h>
kusano 7d535a
#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
kusano 7d535a
#  pragma warning(disable : 4293)        /* disable: C4293: too large shift (32-bits) */
kusano 7d535a
#else
kusano 7d535a
#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */
kusano 7d535a
#    if defined(__GNUC__) || defined(__clang__)
kusano 7d535a
#      define FORCE_INLINE static inline __attribute__((always_inline))
kusano 7d535a
#    else
kusano 7d535a
#      define FORCE_INLINE static inline
kusano 7d535a
#    endif
kusano 7d535a
#  else
kusano 7d535a
#    define FORCE_INLINE static
kusano 7d535a
#  endif   /* __STDC_VERSION__ */
kusano 7d535a
#endif  /* _MSC_VER */
kusano 7d535a
kusano 7d535a
/* LZ4_GCC_VERSION is defined into lz4.h */
kusano 7d535a
#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
kusano 7d535a
#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )
kusano 7d535a
#else
kusano 7d535a
#  define expect(expr,value)    (expr)
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
#define likely(expr)     expect((expr) != 0, 1)
kusano 7d535a
#define unlikely(expr)   expect((expr) != 0, 0)
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Memory routines
kusano 7d535a
**************************************/
kusano 7d535a
#include <stdlib.h>   /* malloc, calloc, free */</stdlib.h>
kusano 7d535a
#define ALLOCATOR(n,s) calloc(n,s)
kusano 7d535a
#define FREEMEM        free
kusano 7d535a
#include <string.h>   /* memset, memcpy */</string.h>
kusano 7d535a
#define MEM_INIT       memset
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Basic Types
kusano 7d535a
**************************************/
kusano 7d535a
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */
kusano 7d535a
# include <stdint.h></stdint.h>
kusano 7d535a
  typedef  uint8_t BYTE;
kusano 7d535a
  typedef uint16_t U16;
kusano 7d535a
  typedef uint32_t U32;
kusano 7d535a
  typedef  int32_t S32;
kusano 7d535a
  typedef uint64_t U64;
kusano 7d535a
#else
kusano 7d535a
  typedef unsigned char       BYTE;
kusano 7d535a
  typedef unsigned short      U16;
kusano 7d535a
  typedef unsigned int        U32;
kusano 7d535a
  typedef   signed int        S32;
kusano 7d535a
  typedef unsigned long long  U64;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Reading and writing into memory
kusano 7d535a
**************************************/
kusano 7d535a
#define STEPSIZE sizeof(size_t)
kusano 7d535a
kusano 7d535a
static unsigned LZ4_64bits(void) { return sizeof(void*)==8; }
kusano 7d535a
kusano 7d535a
static unsigned LZ4_isLittleEndian(void)
kusano 7d535a
{
kusano 7d535a
    const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
kusano 7d535a
    return one.c[0];
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static U16 LZ4_read16(const void* memPtr)
kusano 7d535a
{
kusano 7d535a
    U16 val16;
kusano 7d535a
    memcpy(&val16, memPtr, 2);
kusano 7d535a
    return val16;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U16 LZ4_readLE16(const void* memPtr)
kusano 7d535a
{
kusano 7d535a
    if (LZ4_isLittleEndian())
kusano 7d535a
    {
kusano 7d535a
        return LZ4_read16(memPtr);
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        const BYTE* p = (const BYTE*)memPtr;
kusano 7d535a
        return (U16)((U16)p[0] + (p[1]<<8));
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void LZ4_writeLE16(void* memPtr, U16 value)
kusano 7d535a
{
kusano 7d535a
    if (LZ4_isLittleEndian())
kusano 7d535a
    {
kusano 7d535a
        memcpy(memPtr, &value, 2);
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        BYTE* p = (BYTE*)memPtr;
kusano 7d535a
        p[0] = (BYTE) value;
kusano 7d535a
        p[1] = (BYTE)(value>>8);
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U32 LZ4_read32(const void* memPtr)
kusano 7d535a
{
kusano 7d535a
    U32 val32;
kusano 7d535a
    memcpy(&val32, memPtr, 4);
kusano 7d535a
    return val32;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U64 LZ4_read64(const void* memPtr)
kusano 7d535a
{
kusano 7d535a
    U64 val64;
kusano 7d535a
    memcpy(&val64, memPtr, 8);
kusano 7d535a
    return val64;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static size_t LZ4_read_ARCH(const void* p)
kusano 7d535a
{
kusano 7d535a
    if (LZ4_64bits())
kusano 7d535a
        return (size_t)LZ4_read64(p);
kusano 7d535a
    else
kusano 7d535a
        return (size_t)LZ4_read32(p);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static void LZ4_copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); }
kusano 7d535a
kusano 7d535a
static void LZ4_copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); }
kusano 7d535a
kusano 7d535a
/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
kusano 7d535a
static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
kusano 7d535a
{
kusano 7d535a
    BYTE* d = (BYTE*)dstPtr;
kusano 7d535a
    const BYTE* s = (const BYTE*)srcPtr;
kusano 7d535a
    BYTE* e = (BYTE*)dstEnd;
kusano 7d535a
    do { LZ4_copy8(d,s); d+=8; s+=8; } while (d
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Common Constants
kusano 7d535a
**************************************/
kusano 7d535a
#define MINMATCH 4
kusano 7d535a
kusano 7d535a
#define COPYLENGTH 8
kusano 7d535a
#define LASTLITERALS 5
kusano 7d535a
#define MFLIMIT (COPYLENGTH+MINMATCH)
kusano 7d535a
static const int LZ4_minLength = (MFLIMIT+1);
kusano 7d535a
kusano 7d535a
#define KB *(1 <<10)
kusano 7d535a
#define MB *(1 <<20)
kusano 7d535a
#define GB *(1U<<30)
kusano 7d535a
kusano 7d535a
#define MAXD_LOG 16
kusano 7d535a
#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
kusano 7d535a
kusano 7d535a
#define ML_BITS  4
kusano 7d535a
#define ML_MASK  ((1U<
kusano 7d535a
#define RUN_BITS (8-ML_BITS)
kusano 7d535a
#define RUN_MASK ((1U<
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Common Utils
kusano 7d535a
**************************************/
kusano 7d535a
#define LZ4_STATIC_ASSERT(c)    { enum { LZ4_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Common functions
kusano 7d535a
**************************************/
kusano 7d535a
static unsigned LZ4_NbCommonBytes (register size_t val)
kusano 7d535a
{
kusano 7d535a
    if (LZ4_isLittleEndian())
kusano 7d535a
    {
kusano 7d535a
        if (LZ4_64bits())
kusano 7d535a
        {
kusano 7d535a
#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            unsigned long r = 0;
kusano 7d535a
            _BitScanForward64( &r, (U64)val );
kusano 7d535a
            return (int)(r>>3);
kusano 7d535a
#       elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            return (__builtin_ctzll((U64)val) >> 3);
kusano 7d535a
#       else
kusano 7d535a
            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 };
kusano 7d535a
            return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
kusano 7d535a
#       endif
kusano 7d535a
        }
kusano 7d535a
        else /* 32 bits */
kusano 7d535a
        {
kusano 7d535a
#       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            unsigned long r;
kusano 7d535a
            _BitScanForward( &r, (U32)val );
kusano 7d535a
            return (int)(r>>3);
kusano 7d535a
#       elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            return (__builtin_ctz((U32)val) >> 3);
kusano 7d535a
#       else
kusano 7d535a
            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 };
kusano 7d535a
            return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
kusano 7d535a
#       endif
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
    else   /* Big Endian CPU */
kusano 7d535a
    {
kusano 7d535a
        if (LZ4_64bits())
kusano 7d535a
        {
kusano 7d535a
#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            unsigned long r = 0;
kusano 7d535a
            _BitScanReverse64( &r, val );
kusano 7d535a
            return (unsigned)(r>>3);
kusano 7d535a
#       elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            return (__builtin_clzll((U64)val) >> 3);
kusano 7d535a
#       else
kusano 7d535a
            unsigned r;
kusano 7d535a
            if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
kusano 7d535a
            if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
kusano 7d535a
            r += (!val);
kusano 7d535a
            return r;
kusano 7d535a
#       endif
kusano 7d535a
        }
kusano 7d535a
        else /* 32 bits */
kusano 7d535a
        {
kusano 7d535a
#       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            unsigned long r = 0;
kusano 7d535a
            _BitScanReverse( &r, (unsigned long)val );
kusano 7d535a
            return (unsigned)(r>>3);
kusano 7d535a
#       elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
kusano 7d535a
            return (__builtin_clz((U32)val) >> 3);
kusano 7d535a
#       else
kusano 7d535a
            unsigned r;
kusano 7d535a
            if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
kusano 7d535a
            r += (!val);
kusano 7d535a
            return r;
kusano 7d535a
#       endif
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
kusano 7d535a
{
kusano 7d535a
    const BYTE* const pStart = pIn;
kusano 7d535a
kusano 7d535a
    while (likely(pIn
kusano 7d535a
    {
kusano 7d535a
        size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
kusano 7d535a
        if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
kusano 7d535a
        pIn += LZ4_NbCommonBytes(diff);
kusano 7d535a
        return (unsigned)(pIn - pStart);
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
kusano 7d535a
    if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
kusano 7d535a
    if ((pIn
kusano 7d535a
    return (unsigned)(pIn - pStart);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#ifndef LZ4_COMMONDEFS_ONLY
kusano 7d535a
/**************************************
kusano 7d535a
*  Local Constants
kusano 7d535a
**************************************/
kusano 7d535a
#define LZ4_HASHLOG   (LZ4_MEMORY_USAGE-2)
kusano 7d535a
#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
kusano 7d535a
#define HASH_SIZE_U32 (1 << LZ4_HASHLOG)       /* required as macro for static allocation */
kusano 7d535a
kusano 7d535a
static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
kusano 7d535a
static const U32 LZ4_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Local Structures and types
kusano 7d535a
**************************************/
kusano 7d535a
typedef struct {
kusano 7d535a
    U32 hashTable[HASH_SIZE_U32];
kusano 7d535a
    U32 currentOffset;
kusano 7d535a
    U32 initCheck;
kusano 7d535a
    const BYTE* dictionary;
kusano 7d535a
    BYTE* bufferStart;   /* obsolete, used for slideInputBuffer */
kusano 7d535a
    U32 dictSize;
kusano 7d535a
} LZ4_stream_t_internal;
kusano 7d535a
kusano 7d535a
typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
kusano 7d535a
typedef enum { byPtr, byU32, byU16 } tableType_t;
kusano 7d535a
kusano 7d535a
typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
kusano 7d535a
typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
kusano 7d535a
kusano 7d535a
typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
kusano 7d535a
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
kusano 7d535a
kusano 7d535a
kusano 7d535a
/**************************************
kusano 7d535a
*  Local Utils
kusano 7d535a
**************************************/
kusano 7d535a
int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
kusano 7d535a
int LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }
kusano 7d535a
int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
kusano 7d535a
kusano 7d535a
kusano 7d535a
kusano 7d535a
/********************************
kusano 7d535a
*  Compression functions
kusano 7d535a
********************************/
kusano 7d535a
kusano 7d535a
static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
kusano 7d535a
{
kusano 7d535a
    if (tableType == byU16)
kusano 7d535a
        return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
kusano 7d535a
    else
kusano 7d535a
        return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static const U64 prime5bytes = 889523592379ULL;
kusano 7d535a
static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
kusano 7d535a
{
kusano 7d535a
    const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
kusano 7d535a
    const U32 hashMask = (1<
kusano 7d535a
    return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
kusano 7d535a
{
kusano 7d535a
    if (LZ4_64bits())
kusano 7d535a
        return LZ4_hashSequence64(sequence, tableType);
kusano 7d535a
    return LZ4_hashSequence((U32)sequence, tableType);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static U32 LZ4_hashPosition(const void* p, tableType_t tableType) { return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType); }
kusano 7d535a
kusano 7d535a
static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
kusano 7d535a
{
kusano 7d535a
    switch (tableType)
kusano 7d535a
    {
kusano 7d535a
    case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
kusano 7d535a
    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
kusano 7d535a
    case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
kusano 7d535a
{
kusano 7d535a
    U32 h = LZ4_hashPosition(p, tableType);
kusano 7d535a
    LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
kusano 7d535a
{
kusano 7d535a
    if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
kusano 7d535a
    if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
kusano 7d535a
    { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; }   /* default, to ensure a return */
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
kusano 7d535a
{
kusano 7d535a
    U32 h = LZ4_hashPosition(p, tableType);
kusano 7d535a
    return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
FORCE_INLINE int LZ4_compress_generic(
kusano 7d535a
                 void* const ctx,
kusano 7d535a
                 const char* const source,
kusano 7d535a
                 char* const dest,
kusano 7d535a
                 const int inputSize,
kusano 7d535a
                 const int maxOutputSize,
kusano 7d535a
                 const limitedOutput_directive outputLimited,
kusano 7d535a
                 const tableType_t tableType,
kusano 7d535a
                 const dict_directive dict,
kusano 7d535a
                 const dictIssue_directive dictIssue,
kusano 7d535a
                 const U32 acceleration)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx;
kusano 7d535a
kusano 7d535a
    const BYTE* ip = (const BYTE*) source;
kusano 7d535a
    const BYTE* base;
kusano 7d535a
    const BYTE* lowLimit;
kusano 7d535a
    const BYTE* const lowRefLimit = ip - dictPtr->dictSize;
kusano 7d535a
    const BYTE* const dictionary = dictPtr->dictionary;
kusano 7d535a
    const BYTE* const dictEnd = dictionary + dictPtr->dictSize;
kusano 7d535a
    const size_t dictDelta = dictEnd - (const BYTE*)source;
kusano 7d535a
    const BYTE* anchor = (const BYTE*) source;
kusano 7d535a
    const BYTE* const iend = ip + inputSize;
kusano 7d535a
    const BYTE* const mflimit = iend - MFLIMIT;
kusano 7d535a
    const BYTE* const matchlimit = iend - LASTLITERALS;
kusano 7d535a
kusano 7d535a
    BYTE* op = (BYTE*) dest;
kusano 7d535a
    BYTE* const olimit = op + maxOutputSize;
kusano 7d535a
kusano 7d535a
    U32 forwardH;
kusano 7d535a
    size_t refDelta=0;
kusano 7d535a
kusano 7d535a
    /* Init conditions */
kusano 7d535a
    if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0;   /* Unsupported input size, too large (or negative) */
kusano 7d535a
    switch(dict)
kusano 7d535a
    {
kusano 7d535a
    case noDict:
kusano 7d535a
    default:
kusano 7d535a
        base = (const BYTE*)source;
kusano 7d535a
        lowLimit = (const BYTE*)source;
kusano 7d535a
        break;
kusano 7d535a
    case withPrefix64k:
kusano 7d535a
        base = (const BYTE*)source - dictPtr->currentOffset;
kusano 7d535a
        lowLimit = (const BYTE*)source - dictPtr->dictSize;
kusano 7d535a
        break;
kusano 7d535a
    case usingExtDict:
kusano 7d535a
        base = (const BYTE*)source - dictPtr->currentOffset;
kusano 7d535a
        lowLimit = (const BYTE*)source;
kusano 7d535a
        break;
kusano 7d535a
    }
kusano 7d535a
    if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
kusano 7d535a
    if (inputSize
kusano 7d535a
kusano 7d535a
    /* First Byte */
kusano 7d535a
    LZ4_putPosition(ip, ctx, tableType, base);
kusano 7d535a
    ip++; forwardH = LZ4_hashPosition(ip, tableType);
kusano 7d535a
kusano 7d535a
    /* Main Loop */
kusano 7d535a
    for ( ; ; )
kusano 7d535a
    {
kusano 7d535a
        const BYTE* match;
kusano 7d535a
        BYTE* token;
kusano 7d535a
        {
kusano 7d535a
            const BYTE* forwardIp = ip;
kusano 7d535a
            unsigned step = 1;
kusano 7d535a
            unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
kusano 7d535a
kusano 7d535a
            /* Find a match */
kusano 7d535a
            do {
kusano 7d535a
                U32 h = forwardH;
kusano 7d535a
                ip = forwardIp;
kusano 7d535a
                forwardIp += step;
kusano 7d535a
                step = (searchMatchNb++ >> LZ4_skipTrigger);
kusano 7d535a
kusano 7d535a
                if (unlikely(forwardIp > mflimit)) goto _last_literals;
kusano 7d535a
kusano 7d535a
                match = LZ4_getPositionOnHash(h, ctx, tableType, base);
kusano 7d535a
                if (dict==usingExtDict)
kusano 7d535a
                {
kusano 7d535a
                    if (match<(const BYTE*)source)
kusano 7d535a
                    {
kusano 7d535a
                        refDelta = dictDelta;
kusano 7d535a
                        lowLimit = dictionary;
kusano 7d535a
                    }
kusano 7d535a
                    else
kusano 7d535a
                    {
kusano 7d535a
                        refDelta = 0;
kusano 7d535a
                        lowLimit = (const BYTE*)source;
kusano 7d535a
                    }
kusano 7d535a
                }
kusano 7d535a
                forwardH = LZ4_hashPosition(forwardIp, tableType);
kusano 7d535a
                LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
kusano 7d535a
kusano 7d535a
            } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
kusano 7d535a
                || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
kusano 7d535a
                || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Catch up */
kusano 7d535a
        while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
kusano 7d535a
kusano 7d535a
        {
kusano 7d535a
            /* Encode Literal length */
kusano 7d535a
            unsigned litLength = (unsigned)(ip - anchor);
kusano 7d535a
            token = op++;
kusano 7d535a
            if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
kusano 7d535a
                return 0;   /* Check output limit */
kusano 7d535a
            if (litLength>=RUN_MASK)
kusano 7d535a
            {
kusano 7d535a
                int len = (int)litLength-RUN_MASK;
kusano 7d535a
                *token=(RUN_MASK<
kusano 7d535a
                for(; len >= 255 ; len-=255) *op++ = 255;
kusano 7d535a
                *op++ = (BYTE)len;
kusano 7d535a
            }
kusano 7d535a
            else *token = (BYTE)(litLength<
kusano 7d535a
kusano 7d535a
            /* Copy Literals */
kusano 7d535a
            LZ4_wildCopy(op, anchor, op+litLength);
kusano 7d535a
            op+=litLength;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
_next_match:
kusano 7d535a
        /* Encode Offset */
kusano 7d535a
        LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
kusano 7d535a
kusano 7d535a
        /* Encode MatchLength */
kusano 7d535a
        {
kusano 7d535a
            unsigned matchLength;
kusano 7d535a
kusano 7d535a
            if ((dict==usingExtDict) && (lowLimit==dictionary))
kusano 7d535a
            {
kusano 7d535a
                const BYTE* limit;
kusano 7d535a
                match += refDelta;
kusano 7d535a
                limit = ip + (dictEnd-match);
kusano 7d535a
                if (limit > matchlimit) limit = matchlimit;
kusano 7d535a
                matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
kusano 7d535a
                ip += MINMATCH + matchLength;
kusano 7d535a
                if (ip==limit)
kusano 7d535a
                {
kusano 7d535a
                    unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit);
kusano 7d535a
                    matchLength += more;
kusano 7d535a
                    ip += more;
kusano 7d535a
                }
kusano 7d535a
            }
kusano 7d535a
            else
kusano 7d535a
            {
kusano 7d535a
                matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
kusano 7d535a
                ip += MINMATCH + matchLength;
kusano 7d535a
            }
kusano 7d535a
kusano 7d535a
            if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
kusano 7d535a
                return 0;    /* Check output limit */
kusano 7d535a
            if (matchLength>=ML_MASK)
kusano 7d535a
            {
kusano 7d535a
                *token += ML_MASK;
kusano 7d535a
                matchLength -= ML_MASK;
kusano 7d535a
                for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
kusano 7d535a
                if (matchLength >= 255) { matchLength-=255; *op++ = 255; }
kusano 7d535a
                *op++ = (BYTE)matchLength;
kusano 7d535a
            }
kusano 7d535a
            else *token += (BYTE)(matchLength);
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        anchor = ip;
kusano 7d535a
kusano 7d535a
        /* Test end of chunk */
kusano 7d535a
        if (ip > mflimit) break;
kusano 7d535a
kusano 7d535a
        /* Fill table */
kusano 7d535a
        LZ4_putPosition(ip-2, ctx, tableType, base);
kusano 7d535a
kusano 7d535a
        /* Test next position */
kusano 7d535a
        match = LZ4_getPosition(ip, ctx, tableType, base);
kusano 7d535a
        if (dict==usingExtDict)
kusano 7d535a
        {
kusano 7d535a
            if (match<(const BYTE*)source)
kusano 7d535a
            {
kusano 7d535a
                refDelta = dictDelta;
kusano 7d535a
                lowLimit = dictionary;
kusano 7d535a
            }
kusano 7d535a
            else
kusano 7d535a
            {
kusano 7d535a
                refDelta = 0;
kusano 7d535a
                lowLimit = (const BYTE*)source;
kusano 7d535a
            }
kusano 7d535a
        }
kusano 7d535a
        LZ4_putPosition(ip, ctx, tableType, base);
kusano 7d535a
        if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
kusano 7d535a
            && (match+MAX_DISTANCE>=ip)
kusano 7d535a
            && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
kusano 7d535a
        { token=op++; *token=0; goto _next_match; }
kusano 7d535a
kusano 7d535a
        /* Prepare next loop */
kusano 7d535a
        forwardH = LZ4_hashPosition(++ip, tableType);
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
_last_literals:
kusano 7d535a
    /* Encode Last Literals */
kusano 7d535a
    {
kusano 7d535a
        const size_t lastRun = (size_t)(iend - anchor);
kusano 7d535a
        if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize))
kusano 7d535a
            return 0;   /* Check output limit */
kusano 7d535a
        if (lastRun >= RUN_MASK)
kusano 7d535a
        {
kusano 7d535a
            size_t accumulator = lastRun - RUN_MASK;
kusano 7d535a
            *op++ = RUN_MASK << ML_BITS;
kusano 7d535a
            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
kusano 7d535a
            *op++ = (BYTE) accumulator;
kusano 7d535a
        }
kusano 7d535a
        else
kusano 7d535a
        {
kusano 7d535a
            *op++ = (BYTE)(lastRun<
kusano 7d535a
        }
kusano 7d535a
        memcpy(op, anchor, lastRun);
kusano 7d535a
        op += lastRun;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* End */
kusano 7d535a
    return (int) (((char*)op)-dest);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
kusano 7d535a
{
kusano 7d535a
    LZ4_resetStream((LZ4_stream_t*)state);
kusano 7d535a
    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
kusano 7d535a
kusano 7d535a
    if (maxOutputSize >= LZ4_compressBound(inputSize))
kusano 7d535a
    {
kusano 7d535a
        if (inputSize < LZ4_64Klimit)
kusano 7d535a
            return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16,                        noDict, noDictIssue, acceleration);
kusano 7d535a
        else
kusano 7d535a
            return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        if (inputSize < LZ4_64Klimit)
kusano 7d535a
            return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);
kusano 7d535a
        else
kusano 7d535a
            return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
kusano 7d535a
{
kusano 7d535a
#if (HEAPMODE)
kusano 7d535a
    void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
kusano 7d535a
#else
kusano 7d535a
    LZ4_stream_t ctx;
kusano 7d535a
    void* ctxPtr = &ctx;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
kusano 7d535a
kusano 7d535a
#if (HEAPMODE)
kusano 7d535a
    FREEMEM(ctxPtr);
kusano 7d535a
#endif
kusano 7d535a
    return result;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* hidden debug function */
kusano 7d535a
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
kusano 7d535a
int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t ctx;
kusano 7d535a
kusano 7d535a
    LZ4_resetStream(&ctx);
kusano 7d535a
kusano 7d535a
    if (inputSize < LZ4_64Klimit)
kusano 7d535a
        return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);
kusano 7d535a
    else
kusano 7d535a
        return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/********************************
kusano 7d535a
*  destSize variant
kusano 7d535a
********************************/
kusano 7d535a
kusano 7d535a
static int LZ4_compress_destSize_generic(
kusano 7d535a
                       void* const ctx,
kusano 7d535a
                 const char* const src,
kusano 7d535a
                       char* const dst,
kusano 7d535a
                       int*  const srcSizePtr,
kusano 7d535a
                 const int targetDstSize,
kusano 7d535a
                 const tableType_t tableType)
kusano 7d535a
{
kusano 7d535a
    const BYTE* ip = (const BYTE*) src;
kusano 7d535a
    const BYTE* base = (const BYTE*) src;
kusano 7d535a
    const BYTE* lowLimit = (const BYTE*) src;
kusano 7d535a
    const BYTE* anchor = ip;
kusano 7d535a
    const BYTE* const iend = ip + *srcSizePtr;
kusano 7d535a
    const BYTE* const mflimit = iend - MFLIMIT;
kusano 7d535a
    const BYTE* const matchlimit = iend - LASTLITERALS;
kusano 7d535a
kusano 7d535a
    BYTE* op = (BYTE*) dst;
kusano 7d535a
    BYTE* const oend = op + targetDstSize;
kusano 7d535a
    BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
kusano 7d535a
    BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
kusano 7d535a
    BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
kusano 7d535a
kusano 7d535a
    U32 forwardH;
kusano 7d535a
kusano 7d535a
kusano 7d535a
    /* Init conditions */
kusano 7d535a
    if (targetDstSize < 1) return 0;                                     /* Impossible to store anything */
kusano 7d535a
    if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0;            /* Unsupported input size, too large (or negative) */
kusano 7d535a
    if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
kusano 7d535a
    if (*srcSizePtr
kusano 7d535a
kusano 7d535a
    /* First Byte */
kusano 7d535a
    *srcSizePtr = 0;
kusano 7d535a
    LZ4_putPosition(ip, ctx, tableType, base);
kusano 7d535a
    ip++; forwardH = LZ4_hashPosition(ip, tableType);
kusano 7d535a
kusano 7d535a
    /* Main Loop */
kusano 7d535a
    for ( ; ; )
kusano 7d535a
    {
kusano 7d535a
        const BYTE* match;
kusano 7d535a
        BYTE* token;
kusano 7d535a
        {
kusano 7d535a
            const BYTE* forwardIp = ip;
kusano 7d535a
            unsigned step = 1;
kusano 7d535a
            unsigned searchMatchNb = 1 << LZ4_skipTrigger;
kusano 7d535a
kusano 7d535a
            /* Find a match */
kusano 7d535a
            do {
kusano 7d535a
                U32 h = forwardH;
kusano 7d535a
                ip = forwardIp;
kusano 7d535a
                forwardIp += step;
kusano 7d535a
                step = (searchMatchNb++ >> LZ4_skipTrigger);
kusano 7d535a
kusano 7d535a
                if (unlikely(forwardIp > mflimit))
kusano 7d535a
                    goto _last_literals;
kusano 7d535a
kusano 7d535a
                match = LZ4_getPositionOnHash(h, ctx, tableType, base);
kusano 7d535a
                forwardH = LZ4_hashPosition(forwardIp, tableType);
kusano 7d535a
                LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
kusano 7d535a
kusano 7d535a
            } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
kusano 7d535a
                || (LZ4_read32(match) != LZ4_read32(ip)) );
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* Catch up */
kusano 7d535a
        while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
kusano 7d535a
kusano 7d535a
        {
kusano 7d535a
            /* Encode Literal length */
kusano 7d535a
            unsigned litLength = (unsigned)(ip - anchor);
kusano 7d535a
            token = op++;
kusano 7d535a
            if (op + ((litLength+240)/255) + litLength > oMaxLit)
kusano 7d535a
            {
kusano 7d535a
                /* Not enough space for a last match */
kusano 7d535a
                op--;
kusano 7d535a
                goto _last_literals;
kusano 7d535a
            }
kusano 7d535a
            if (litLength>=RUN_MASK)
kusano 7d535a
            {
kusano 7d535a
                unsigned len = litLength - RUN_MASK;
kusano 7d535a
                *token=(RUN_MASK<
kusano 7d535a
                for(; len >= 255 ; len-=255) *op++ = 255;
kusano 7d535a
                *op++ = (BYTE)len;
kusano 7d535a
            }
kusano 7d535a
            else *token = (BYTE)(litLength<
kusano 7d535a
kusano 7d535a
            /* Copy Literals */
kusano 7d535a
            LZ4_wildCopy(op, anchor, op+litLength);
kusano 7d535a
            op += litLength;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
_next_match:
kusano 7d535a
        /* Encode Offset */
kusano 7d535a
        LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
kusano 7d535a
kusano 7d535a
        /* Encode MatchLength */
kusano 7d535a
        {
kusano 7d535a
            size_t matchLength;
kusano 7d535a
kusano 7d535a
            matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
kusano 7d535a
kusano 7d535a
            if (op + ((matchLength+240)/255) > oMaxMatch)
kusano 7d535a
            {
kusano 7d535a
                /* Match description too long : reduce it */
kusano 7d535a
                matchLength = (15-1) + (oMaxMatch-op) * 255;
kusano 7d535a
            }
kusano 7d535a
            //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);
kusano 7d535a
            ip += MINMATCH + matchLength;
kusano 7d535a
kusano 7d535a
            if (matchLength>=ML_MASK)
kusano 7d535a
            {
kusano 7d535a
                *token += ML_MASK;
kusano 7d535a
                matchLength -= ML_MASK;
kusano 7d535a
                while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
kusano 7d535a
                *op++ = (BYTE)matchLength;
kusano 7d535a
            }
kusano 7d535a
            else *token += (BYTE)(matchLength);
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        anchor = ip;
kusano 7d535a
kusano 7d535a
        /* Test end of block */
kusano 7d535a
        if (ip > mflimit) break;
kusano 7d535a
        if (op > oMaxSeq) break;
kusano 7d535a
kusano 7d535a
        /* Fill table */
kusano 7d535a
        LZ4_putPosition(ip-2, ctx, tableType, base);
kusano 7d535a
kusano 7d535a
        /* Test next position */
kusano 7d535a
        match = LZ4_getPosition(ip, ctx, tableType, base);
kusano 7d535a
        LZ4_putPosition(ip, ctx, tableType, base);
kusano 7d535a
        if ( (match+MAX_DISTANCE>=ip)
kusano 7d535a
            && (LZ4_read32(match)==LZ4_read32(ip)) )
kusano 7d535a
        { token=op++; *token=0; goto _next_match; }
kusano 7d535a
kusano 7d535a
        /* Prepare next loop */
kusano 7d535a
        forwardH = LZ4_hashPosition(++ip, tableType);
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
_last_literals:
kusano 7d535a
    /* Encode Last Literals */
kusano 7d535a
    {
kusano 7d535a
        size_t lastRunSize = (size_t)(iend - anchor);
kusano 7d535a
        if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)
kusano 7d535a
        {
kusano 7d535a
            /* adapt lastRunSize to fill 'dst' */
kusano 7d535a
            lastRunSize  = (oend-op) - 1;
kusano 7d535a
            lastRunSize -= (lastRunSize+240)/255;
kusano 7d535a
        }
kusano 7d535a
        ip = anchor + lastRunSize;
kusano 7d535a
kusano 7d535a
        if (lastRunSize >= RUN_MASK)
kusano 7d535a
        {
kusano 7d535a
            size_t accumulator = lastRunSize - RUN_MASK;
kusano 7d535a
            *op++ = RUN_MASK << ML_BITS;
kusano 7d535a
            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
kusano 7d535a
            *op++ = (BYTE) accumulator;
kusano 7d535a
        }
kusano 7d535a
        else
kusano 7d535a
        {
kusano 7d535a
            *op++ = (BYTE)(lastRunSize<
kusano 7d535a
        }
kusano 7d535a
        memcpy(op, anchor, lastRunSize);
kusano 7d535a
        op += lastRunSize;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* End */
kusano 7d535a
    *srcSizePtr = (int) (((const char*)ip)-src);
kusano 7d535a
    return (int) (((char*)op)-dst);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static int LZ4_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_resetStream((LZ4_stream_t*)state);
kusano 7d535a
kusano 7d535a
    if (targetDstSize >= LZ4_compressBound(*srcSizePtr))   /* compression success is guaranteed */
kusano 7d535a
    {
kusano 7d535a
        return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        if (*srcSizePtr < LZ4_64Klimit)
kusano 7d535a
            return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
kusano 7d535a
        else
kusano 7d535a
            return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, LZ4_64bits() ? byU32 : byPtr);
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
kusano 7d535a
{
kusano 7d535a
#if (HEAPMODE)
kusano 7d535a
    void* ctx = ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
kusano 7d535a
#else
kusano 7d535a
    LZ4_stream_t ctxBody;
kusano 7d535a
    void* ctx = &ctxBody;
kusano 7d535a
#endif
kusano 7d535a
kusano 7d535a
    int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
kusano 7d535a
kusano 7d535a
#if (HEAPMODE)
kusano 7d535a
    FREEMEM(ctx);
kusano 7d535a
#endif
kusano 7d535a
    return result;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
kusano 7d535a
/********************************
kusano 7d535a
*  Streaming functions
kusano 7d535a
********************************/
kusano 7d535a
kusano 7d535a
LZ4_stream_t* LZ4_createStream(void)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
kusano 7d535a
    LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal));    /* A compilation error here means LZ4_STREAMSIZE is not large enough */
kusano 7d535a
    LZ4_resetStream(lz4s);
kusano 7d535a
    return lz4s;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
kusano 7d535a
{
kusano 7d535a
    MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
kusano 7d535a
{
kusano 7d535a
    FREEMEM(LZ4_stream);
kusano 7d535a
    return (0);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
#define HASH_UNIT sizeof(size_t)
kusano 7d535a
int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
kusano 7d535a
    const BYTE* p = (const BYTE*)dictionary;
kusano 7d535a
    const BYTE* const dictEnd = p + dictSize;
kusano 7d535a
    const BYTE* base;
kusano 7d535a
kusano 7d535a
    if ((dict->initCheck) || (dict->currentOffset > 1 GB))  /* Uninitialized structure, or reuse overflow */
kusano 7d535a
        LZ4_resetStream(LZ4_dict);
kusano 7d535a
kusano 7d535a
    if (dictSize < (int)HASH_UNIT)
kusano 7d535a
    {
kusano 7d535a
        dict->dictionary = NULL;
kusano 7d535a
        dict->dictSize = 0;
kusano 7d535a
        return 0;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
kusano 7d535a
    dict->currentOffset += 64 KB;
kusano 7d535a
    base = p - dict->currentOffset;
kusano 7d535a
    dict->dictionary = p;
kusano 7d535a
    dict->dictSize = (U32)(dictEnd - p);
kusano 7d535a
    dict->currentOffset += dict->dictSize;
kusano 7d535a
kusano 7d535a
    while (p <= dictEnd-HASH_UNIT)
kusano 7d535a
    {
kusano 7d535a
        LZ4_putPosition(p, dict->hashTable, byU32, base);
kusano 7d535a
        p+=3;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    return dict->dictSize;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
kusano 7d535a
{
kusano 7d535a
    if ((LZ4_dict->currentOffset > 0x80000000) ||
kusano 7d535a
        ((size_t)LZ4_dict->currentOffset > (size_t)src))   /* address space overflow */
kusano 7d535a
    {
kusano 7d535a
        /* rescale hash table */
kusano 7d535a
        U32 delta = LZ4_dict->currentOffset - 64 KB;
kusano 7d535a
        const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
kusano 7d535a
        int i;
kusano 7d535a
        for (i=0; i
kusano 7d535a
        {
kusano 7d535a
            if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
kusano 7d535a
            else LZ4_dict->hashTable[i] -= delta;
kusano 7d535a
        }
kusano 7d535a
        LZ4_dict->currentOffset = 64 KB;
kusano 7d535a
        if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
kusano 7d535a
        LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream;
kusano 7d535a
    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
kusano 7d535a
kusano 7d535a
    const BYTE* smallest = (const BYTE*) source;
kusano 7d535a
    if (streamPtr->initCheck) return 0;   /* Uninitialized structure detected */
kusano 7d535a
    if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
kusano 7d535a
    LZ4_renormDictT(streamPtr, smallest);
kusano 7d535a
    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
kusano 7d535a
kusano 7d535a
    /* Check overlapping input/dictionary space */
kusano 7d535a
    {
kusano 7d535a
        const BYTE* sourceEnd = (const BYTE*) source + inputSize;
kusano 7d535a
        if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))
kusano 7d535a
        {
kusano 7d535a
            streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
kusano 7d535a
            if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
kusano 7d535a
            if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
kusano 7d535a
            streamPtr->dictionary = dictEnd - streamPtr->dictSize;
kusano 7d535a
        }
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* prefix mode : source data follows dictionary */
kusano 7d535a
    if (dictEnd == (const BYTE*)source)
kusano 7d535a
    {
kusano 7d535a
        int result;
kusano 7d535a
        if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
kusano 7d535a
            result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
kusano 7d535a
        else
kusano 7d535a
            result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
kusano 7d535a
        streamPtr->dictSize += (U32)inputSize;
kusano 7d535a
        streamPtr->currentOffset += (U32)inputSize;
kusano 7d535a
        return result;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* external dictionary mode */
kusano 7d535a
    {
kusano 7d535a
        int result;
kusano 7d535a
        if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
kusano 7d535a
            result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
kusano 7d535a
        else
kusano 7d535a
            result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
kusano 7d535a
        streamPtr->dictionary = (const BYTE*)source;
kusano 7d535a
        streamPtr->dictSize = (U32)inputSize;
kusano 7d535a
        streamPtr->currentOffset += (U32)inputSize;
kusano 7d535a
        return result;
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* Hidden debug function, to force external dictionary mode */
kusano 7d535a
int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict;
kusano 7d535a
    int result;
kusano 7d535a
    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
kusano 7d535a
kusano 7d535a
    const BYTE* smallest = dictEnd;
kusano 7d535a
    if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
kusano 7d535a
    LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest);
kusano 7d535a
kusano 7d535a
    result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
kusano 7d535a
kusano 7d535a
    streamPtr->dictionary = (const BYTE*)source;
kusano 7d535a
    streamPtr->dictSize = (U32)inputSize;
kusano 7d535a
    streamPtr->currentOffset += (U32)inputSize;
kusano 7d535a
kusano 7d535a
    return result;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict;
kusano 7d535a
    const BYTE* previousDictEnd = dict->dictionary + dict->dictSize;
kusano 7d535a
kusano 7d535a
    if ((U32)dictSize > 64 KB) dictSize = 64 KB;   /* useless to define a dictionary > 64 KB */
kusano 7d535a
    if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
kusano 7d535a
kusano 7d535a
    memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
kusano 7d535a
kusano 7d535a
    dict->dictionary = (const BYTE*)safeBuffer;
kusano 7d535a
    dict->dictSize = (U32)dictSize;
kusano 7d535a
kusano 7d535a
    return dictSize;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*******************************
kusano 7d535a
*  Decompression functions
kusano 7d535a
*******************************/
kusano 7d535a
/*
kusano 7d535a
 * This generic decompression function cover all use cases.
kusano 7d535a
 * It shall be instantiated several times, using different sets of directives
kusano 7d535a
 * Note that it is essential this generic function is really inlined,
kusano 7d535a
 * in order to remove useless branches during compilation optimization.
kusano 7d535a
 */
kusano 7d535a
FORCE_INLINE int LZ4_decompress_generic(
kusano 7d535a
                 const char* const source,
kusano 7d535a
                 char* const dest,
kusano 7d535a
                 int inputSize,
kusano 7d535a
                 int outputSize,         /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
kusano 7d535a
kusano 7d535a
                 int endOnInput,         /* endOnOutputSize, endOnInputSize */
kusano 7d535a
                 int partialDecoding,    /* full, partial */
kusano 7d535a
                 int targetOutputSize,   /* only used if partialDecoding==partial */
kusano 7d535a
                 int dict,               /* noDict, withPrefix64k, usingExtDict */
kusano 7d535a
                 const BYTE* const lowPrefix,  /* == dest if dict == noDict */
kusano 7d535a
                 const BYTE* const dictStart,  /* only if dict==usingExtDict */
kusano 7d535a
                 const size_t dictSize         /* note : = 0 if noDict */
kusano 7d535a
                 )
kusano 7d535a
{
kusano 7d535a
    /* Local Variables */
kusano 7d535a
    const BYTE* ip = (const BYTE*) source;
kusano 7d535a
    const BYTE* const iend = ip + inputSize;
kusano 7d535a
kusano 7d535a
    BYTE* op = (BYTE*) dest;
kusano 7d535a
    BYTE* const oend = op + outputSize;
kusano 7d535a
    BYTE* cpy;
kusano 7d535a
    BYTE* oexit = op + targetOutputSize;
kusano 7d535a
    const BYTE* const lowLimit = lowPrefix - dictSize;
kusano 7d535a
kusano 7d535a
    const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
kusano 7d535a
    const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
kusano 7d535a
    const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
kusano 7d535a
kusano 7d535a
    const int safeDecode = (endOnInput==endOnInputSize);
kusano 7d535a
    const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
kusano 7d535a
kusano 7d535a
kusano 7d535a
    /* Special cases */
kusano 7d535a
    if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT;                         /* targetOutputSize too high => decode everything */
kusano 7d535a
    if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1;  /* Empty output buffer */
kusano 7d535a
    if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
kusano 7d535a
kusano 7d535a
kusano 7d535a
    /* Main Loop */
kusano 7d535a
    while (1)
kusano 7d535a
    {
kusano 7d535a
        unsigned token;
kusano 7d535a
        size_t length;
kusano 7d535a
        const BYTE* match;
kusano 7d535a
kusano 7d535a
        /* get literal length */
kusano 7d535a
        token = *ip++;
kusano 7d535a
        if ((length=(token>>ML_BITS)) == RUN_MASK)
kusano 7d535a
        {
kusano 7d535a
            unsigned s;
kusano 7d535a
            do
kusano 7d535a
            {
kusano 7d535a
                s = *ip++;
kusano 7d535a
                length += s;
kusano 7d535a
            }
kusano 7d535a
            while (likely((endOnInput)?ip
kusano 7d535a
            if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error;   /* overflow detection */
kusano 7d535a
            if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error;   /* overflow detection */
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* copy literals */
kusano 7d535a
        cpy = op+length;
kusano 7d535a
        if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
kusano 7d535a
            || ((!endOnInput) && (cpy>oend-COPYLENGTH)))
kusano 7d535a
        {
kusano 7d535a
            if (partialDecoding)
kusano 7d535a
            {
kusano 7d535a
                if (cpy > oend) goto _output_error;                           /* Error : write attempt beyond end of output buffer */
kusano 7d535a
                if ((endOnInput) && (ip+length > iend)) goto _output_error;   /* Error : read attempt beyond end of input buffer */
kusano 7d535a
            }
kusano 7d535a
            else
kusano 7d535a
            {
kusano 7d535a
                if ((!endOnInput) && (cpy != oend)) goto _output_error;       /* Error : block decoding must stop exactly there */
kusano 7d535a
                if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error;   /* Error : input must be consumed */
kusano 7d535a
            }
kusano 7d535a
            memcpy(op, ip, length);
kusano 7d535a
            ip += length;
kusano 7d535a
            op += length;
kusano 7d535a
            break;     /* Necessarily EOF, due to parsing restrictions */
kusano 7d535a
        }
kusano 7d535a
        LZ4_wildCopy(op, ip, cpy);
kusano 7d535a
        ip += length; op = cpy;
kusano 7d535a
kusano 7d535a
        /* get offset */
kusano 7d535a
        match = cpy - LZ4_readLE16(ip); ip+=2;
kusano 7d535a
        if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error;   /* Error : offset outside destination buffer */
kusano 7d535a
kusano 7d535a
        /* get matchlength */
kusano 7d535a
        length = token & ML_MASK;
kusano 7d535a
        if (length == ML_MASK)
kusano 7d535a
        {
kusano 7d535a
            unsigned s;
kusano 7d535a
            do
kusano 7d535a
            {
kusano 7d535a
                if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
kusano 7d535a
                s = *ip++;
kusano 7d535a
                length += s;
kusano 7d535a
            } while (s==255);
kusano 7d535a
            if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error;   /* overflow detection */
kusano 7d535a
        }
kusano 7d535a
        length += MINMATCH;
kusano 7d535a
kusano 7d535a
        /* check external dictionary */
kusano 7d535a
        if ((dict==usingExtDict) && (match < lowPrefix))
kusano 7d535a
        {
kusano 7d535a
            if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error;   /* doesn't respect parsing restriction */
kusano 7d535a
kusano 7d535a
            if (length <= (size_t)(lowPrefix-match))
kusano 7d535a
            {
kusano 7d535a
                /* match can be copied as a single segment from external dictionary */
kusano 7d535a
                match = dictEnd - (lowPrefix-match);
kusano 7d535a
                memmove(op, match, length); op += length;
kusano 7d535a
            }
kusano 7d535a
            else
kusano 7d535a
            {
kusano 7d535a
                /* match encompass external dictionary and current segment */
kusano 7d535a
                size_t copySize = (size_t)(lowPrefix-match);
kusano 7d535a
                memcpy(op, dictEnd - copySize, copySize);
kusano 7d535a
                op += copySize;
kusano 7d535a
                copySize = length - copySize;
kusano 7d535a
                if (copySize > (size_t)(op-lowPrefix))   /* overlap within current segment */
kusano 7d535a
                {
kusano 7d535a
                    BYTE* const endOfMatch = op + copySize;
kusano 7d535a
                    const BYTE* copyFrom = lowPrefix;
kusano 7d535a
                    while (op < endOfMatch) *op++ = *copyFrom++;
kusano 7d535a
                }
kusano 7d535a
                else
kusano 7d535a
                {
kusano 7d535a
                    memcpy(op, lowPrefix, copySize);
kusano 7d535a
                    op += copySize;
kusano 7d535a
                }
kusano 7d535a
            }
kusano 7d535a
            continue;
kusano 7d535a
        }
kusano 7d535a
kusano 7d535a
        /* copy repeated sequence */
kusano 7d535a
        cpy = op + length;
kusano 7d535a
        if (unlikely((op-match)<8))
kusano 7d535a
        {
kusano 7d535a
            const size_t dec64 = dec64table[op-match];
kusano 7d535a
            op[0] = match[0];
kusano 7d535a
            op[1] = match[1];
kusano 7d535a
            op[2] = match[2];
kusano 7d535a
            op[3] = match[3];
kusano 7d535a
            match += dec32table[op-match];
kusano 7d535a
            LZ4_copy4(op+4, match);
kusano 7d535a
            op += 8; match -= dec64;
kusano 7d535a
        } else { LZ4_copy8(op, match); op+=8; match+=8; }
kusano 7d535a
kusano 7d535a
        if (unlikely(cpy>oend-12))
kusano 7d535a
        {
kusano 7d535a
            if (cpy > oend-LASTLITERALS) goto _output_error;    /* Error : last LASTLITERALS bytes must be literals */
kusano 7d535a
            if (op < oend-8)
kusano 7d535a
            {
kusano 7d535a
                LZ4_wildCopy(op, match, oend-8);
kusano 7d535a
                match += (oend-8) - op;
kusano 7d535a
                op = oend-8;
kusano 7d535a
            }
kusano 7d535a
            while (op
kusano 7d535a
        }
kusano 7d535a
        else
kusano 7d535a
            LZ4_wildCopy(op, match, cpy);
kusano 7d535a
        op=cpy;   /* correction */
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    /* end of decoding */
kusano 7d535a
    if (endOnInput)
kusano 7d535a
       return (int) (((char*)op)-dest);     /* Nb of output bytes decoded */
kusano 7d535a
    else
kusano 7d535a
       return (int) (((const char*)ip)-source);   /* Nb of input bytes read */
kusano 7d535a
kusano 7d535a
    /* Overflow error detected */
kusano 7d535a
_output_error:
kusano 7d535a
    return (int) (-(((const char*)ip)-source))-1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* streaming decompression functions */
kusano 7d535a
kusano 7d535a
typedef struct
kusano 7d535a
{
kusano 7d535a
    const BYTE* externalDict;
kusano 7d535a
    size_t extDictSize;
kusano 7d535a
    const BYTE* prefixEnd;
kusano 7d535a
    size_t prefixSize;
kusano 7d535a
} LZ4_streamDecode_t_internal;
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * If you prefer dynamic allocation methods,
kusano 7d535a
 * LZ4_createStreamDecode()
kusano 7d535a
 * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
kusano 7d535a
 */
kusano 7d535a
LZ4_streamDecode_t* LZ4_createStreamDecode(void)
kusano 7d535a
{
kusano 7d535a
    LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
kusano 7d535a
    return lz4s;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
kusano 7d535a
{
kusano 7d535a
    FREEMEM(LZ4_stream);
kusano 7d535a
    return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
 * LZ4_setStreamDecode
kusano 7d535a
 * Use this function to instruct where to find the dictionary
kusano 7d535a
 * This function is not necessary if previous data is still available where it was decoded.
kusano 7d535a
 * Loading a size of 0 is allowed (same effect as no dictionary).
kusano 7d535a
 * Return : 1 if OK, 0 if error
kusano 7d535a
 */
kusano 7d535a
int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
kusano 7d535a
    lz4sd->prefixSize = (size_t) dictSize;
kusano 7d535a
    lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
kusano 7d535a
    lz4sd->externalDict = NULL;
kusano 7d535a
    lz4sd->extDictSize  = 0;
kusano 7d535a
    return 1;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
*_continue() :
kusano 7d535a
    These decoding functions allow decompression of multiple blocks in "streaming" mode.
kusano 7d535a
    Previously decoded blocks must still be available at the memory position where they were decoded.
kusano 7d535a
    If it's not possible, save the relevant part of decoded data into a safe buffer,
kusano 7d535a
    and indicate where it stands using LZ4_setStreamDecode()
kusano 7d535a
*/
kusano 7d535a
int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
kusano 7d535a
    int result;
kusano 7d535a
kusano 7d535a
    if (lz4sd->prefixEnd == (BYTE*)dest)
kusano 7d535a
    {
kusano 7d535a
        result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
kusano 7d535a
                                        endOnInputSize, full, 0,
kusano 7d535a
                                        usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
kusano 7d535a
        if (result <= 0) return result;
kusano 7d535a
        lz4sd->prefixSize += result;
kusano 7d535a
        lz4sd->prefixEnd  += result;
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        lz4sd->extDictSize = lz4sd->prefixSize;
kusano 7d535a
        lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
kusano 7d535a
        result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
kusano 7d535a
                                        endOnInputSize, full, 0,
kusano 7d535a
                                        usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
kusano 7d535a
        if (result <= 0) return result;
kusano 7d535a
        lz4sd->prefixSize = result;
kusano 7d535a
        lz4sd->prefixEnd  = (BYTE*)dest + result;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    return result;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
kusano 7d535a
{
kusano 7d535a
    LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode;
kusano 7d535a
    int result;
kusano 7d535a
kusano 7d535a
    if (lz4sd->prefixEnd == (BYTE*)dest)
kusano 7d535a
    {
kusano 7d535a
        result = LZ4_decompress_generic(source, dest, 0, originalSize,
kusano 7d535a
                                        endOnOutputSize, full, 0,
kusano 7d535a
                                        usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
kusano 7d535a
        if (result <= 0) return result;
kusano 7d535a
        lz4sd->prefixSize += originalSize;
kusano 7d535a
        lz4sd->prefixEnd  += originalSize;
kusano 7d535a
    }
kusano 7d535a
    else
kusano 7d535a
    {
kusano 7d535a
        lz4sd->extDictSize = lz4sd->prefixSize;
kusano 7d535a
        lz4sd->externalDict = (BYTE*)dest - lz4sd->extDictSize;
kusano 7d535a
        result = LZ4_decompress_generic(source, dest, 0, originalSize,
kusano 7d535a
                                        endOnOutputSize, full, 0,
kusano 7d535a
                                        usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
kusano 7d535a
        if (result <= 0) return result;
kusano 7d535a
        lz4sd->prefixSize = originalSize;
kusano 7d535a
        lz4sd->prefixEnd  = (BYTE*)dest + originalSize;
kusano 7d535a
    }
kusano 7d535a
kusano 7d535a
    return result;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
Advanced decoding functions :
kusano 7d535a
*_usingDict() :
kusano 7d535a
    These decoding functions work the same as "_continue" ones,
kusano 7d535a
    the dictionary must be explicitly provided within parameters
kusano 7d535a
*/
kusano 7d535a
kusano 7d535a
FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
kusano 7d535a
{
kusano 7d535a
    if (dictSize==0)
kusano 7d535a
        return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
kusano 7d535a
    if (dictStart+dictSize == dest)
kusano 7d535a
    {
kusano 7d535a
        if (dictSize >= (int)(64 KB - 1))
kusano 7d535a
            return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
kusano 7d535a
        return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
kusano 7d535a
    }
kusano 7d535a
    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/* debug function */
kusano 7d535a
int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***************************************************
kusano 7d535a
*  Obsolete Functions
kusano 7d535a
***************************************************/
kusano 7d535a
/* obsolete compression functions */
kusano 7d535a
int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
kusano 7d535a
int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); }
kusano 7d535a
int 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); }
kusano 7d535a
int 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); }
kusano 7d535a
int 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); }
kusano 7d535a
int 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); }
kusano 7d535a
kusano 7d535a
/*
kusano 7d535a
These function names are deprecated and should no longer be used.
kusano 7d535a
They are only provided here for compatibility with older user programs.
kusano 7d535a
- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
kusano 7d535a
- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
kusano 7d535a
*/
kusano 7d535a
int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
kusano 7d535a
int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
kusano 7d535a
kusano 7d535a
kusano 7d535a
/* Obsolete Streaming functions */
kusano 7d535a
kusano 7d535a
int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
kusano 7d535a
kusano 7d535a
static void LZ4_init(LZ4_stream_t_internal* lz4ds, BYTE* base)
kusano 7d535a
{
kusano 7d535a
    MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE);
kusano 7d535a
    lz4ds->bufferStart = base;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_resetStreamState(void* state, char* inputBuffer)
kusano 7d535a
{
kusano 7d535a
    if ((((size_t)state) & 3) != 0) return 1;   /* Error : pointer is not aligned on 4-bytes boundary */
kusano 7d535a
    LZ4_init((LZ4_stream_t_internal*)state, (BYTE*)inputBuffer);
kusano 7d535a
    return 0;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
void* LZ4_create (char* inputBuffer)
kusano 7d535a
{
kusano 7d535a
    void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64);
kusano 7d535a
    LZ4_init ((LZ4_stream_t_internal*)lz4ds, (BYTE*)inputBuffer);
kusano 7d535a
    return lz4ds;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
char* LZ4_slideInputBuffer (void* LZ4_Data)
kusano 7d535a
{
kusano 7d535a
    LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data;
kusano 7d535a
    int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB);
kusano 7d535a
    return (char*)(ctx->bufferStart + dictSize);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/* Obsolete streaming decompression functions */
kusano 7d535a
kusano 7d535a
int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
kusano 7d535a
{
kusano 7d535a
    return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#endif   /* LZ4_COMMONDEFS_ONLY */
kusano 7d535a