Home | History | Annotate | Download | only in lib
      1 /*
      2    LZ4 - Fast LZ compression algorithm
      3    Copyright (C) 2011-2016, Yann Collet.
      4 
      5    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
      6 
      7    Redistribution and use in source and binary forms, with or without
      8    modification, are permitted provided that the following conditions are
      9    met:
     10 
     11        * Redistributions of source code must retain the above copyright
     12    notice, this list of conditions and the following disclaimer.
     13        * Redistributions in binary form must reproduce the above
     14    copyright notice, this list of conditions and the following disclaimer
     15    in the documentation and/or other materials provided with the
     16    distribution.
     17 
     18    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30    You can contact the author at :
     31     - LZ4 homepage : http://www.lz4.org
     32     - LZ4 source repository : https://github.com/lz4/lz4
     33 */
     34 
     35 
     36 /*-************************************
     37 *  Tuning parameters
     38 **************************************/
     39 /*
     40  * HEAPMODE :
     41  * Select how default compression functions will allocate memory for their hash table,
     42  * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
     43  */
     44 #ifndef HEAPMODE
     45 #  define HEAPMODE 0
     46 #endif
     47 
     48 /*
     49  * ACCELERATION_DEFAULT :
     50  * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
     51  */
     52 #define ACCELERATION_DEFAULT 1
     53 
     54 
     55 /*-************************************
     56 *  CPU Feature Detection
     57 **************************************/
     58 /* LZ4_FORCE_MEMORY_ACCESS
     59  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
     60  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
     61  * The below switch allow to select different access method for improved performance.
     62  * Method 0 (default) : use `memcpy()`. Safe and portable.
     63  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
     64  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
     65  * Method 2 : direct access. This method is portable but violate C standard.
     66  *            It can generate buggy code on targets which generate assembly depending on alignment.
     67  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
     68  * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
     69  * Prefer these methods in priority order (0 > 1 > 2)
     70  */
     71 #ifndef LZ4_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
     72 #  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__) )
     73 #    define LZ4_FORCE_MEMORY_ACCESS 2
     74 #  elif defined(__INTEL_COMPILER) || \
     75   (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
     76 #    define LZ4_FORCE_MEMORY_ACCESS 1
     77 #  endif
     78 #endif
     79 
     80 /*
     81  * LZ4_FORCE_SW_BITCOUNT
     82  * Define this parameter if your target system or compiler does not support hardware bit count
     83  */
     84 #if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for Windows CE does not support Hardware bit count */
     85 #  define LZ4_FORCE_SW_BITCOUNT
     86 #endif
     87 
     88 
     89 /*-************************************
     90 *  Dependency
     91 **************************************/
     92 #include "lz4.h"
     93 /* see also "memory routines" below */
     94 
     95 
     96 /*-************************************
     97 *  Compiler Options
     98 **************************************/
     99 #ifdef _MSC_VER    /* Visual Studio */
    100 #  define FORCE_INLINE static __forceinline
    101 #  include <intrin.h>
    102 #  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */
    103 #  pragma warning(disable : 4293)        /* disable: C4293: too large shift (32-bits) */
    104 #else
    105 #  if defined(__GNUC__) || defined(__clang__)
    106 #    define FORCE_INLINE static inline __attribute__((always_inline))
    107 #  elif defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
    108 #    define FORCE_INLINE static inline
    109 #  else
    110 #    define FORCE_INLINE static
    111 #  endif
    112 #endif  /* _MSC_VER */
    113 
    114 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)
    115 #  define expect(expr,value)    (__builtin_expect ((expr),(value)) )
    116 #else
    117 #  define expect(expr,value)    (expr)
    118 #endif
    119 
    120 #define likely(expr)     expect((expr) != 0, 1)
    121 #define unlikely(expr)   expect((expr) != 0, 0)
    122 
    123 
    124 /*-************************************
    125 *  Memory routines
    126 **************************************/
    127 #include <stdlib.h>   /* malloc, calloc, free */
    128 #define ALLOCATOR(n,s) calloc(n,s)
    129 #define FREEMEM        free
    130 #include <string.h>   /* memset, memcpy */
    131 #define MEM_INIT       memset
    132 
    133 
    134 /*-************************************
    135 *  Basic Types
    136 **************************************/
    137 #if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
    138 # include <stdint.h>
    139   typedef  uint8_t BYTE;
    140   typedef uint16_t U16;
    141   typedef uint32_t U32;
    142   typedef  int32_t S32;
    143   typedef uint64_t U64;
    144   typedef uintptr_t uptrval;
    145 #else
    146   typedef unsigned char       BYTE;
    147   typedef unsigned short      U16;
    148   typedef unsigned int        U32;
    149   typedef   signed int        S32;
    150   typedef unsigned long long  U64;
    151   typedef size_t              uptrval;   /* generally true, except OpenVMS-64 */
    152 #endif
    153 
    154 #if defined(__x86_64__)
    155   typedef U64    reg_t;   /* 64-bits in x32 mode */
    156 #else
    157   typedef size_t reg_t;   /* 32-bits in x32 mode */
    158 #endif
    159 
    160 /*-************************************
    161 *  Reading and writing into memory
    162 **************************************/
    163 static unsigned LZ4_isLittleEndian(void)
    164 {
    165     const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental */
    166     return one.c[0];
    167 }
    168 
    169 
    170 #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
    171 /* lie to the compiler about data alignment; use with caution */
    172 
    173 static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }
    174 static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }
    175 static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; }
    176 
    177 static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
    178 static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
    179 
    180 #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)
    181 
    182 /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
    183 /* currently only defined for gcc and icc */
    184 typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign;
    185 
    186 static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
    187 static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
    188 static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; }
    189 
    190 static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
    191 static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
    192 
    193 #else  /* safe and portable access through memcpy() */
    194 
    195 static U16 LZ4_read16(const void* memPtr)
    196 {
    197     U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
    198 }
    199 
    200 static U32 LZ4_read32(const void* memPtr)
    201 {
    202     U32 val; memcpy(&val, memPtr, sizeof(val)); return val;
    203 }
    204 
    205 static reg_t LZ4_read_ARCH(const void* memPtr)
    206 {
    207     reg_t val; memcpy(&val, memPtr, sizeof(val)); return val;
    208 }
    209 
    210 static void LZ4_write16(void* memPtr, U16 value)
    211 {
    212     memcpy(memPtr, &value, sizeof(value));
    213 }
    214 
    215 static void LZ4_write32(void* memPtr, U32 value)
    216 {
    217     memcpy(memPtr, &value, sizeof(value));
    218 }
    219 
    220 #endif /* LZ4_FORCE_MEMORY_ACCESS */
    221 
    222 
    223 static U16 LZ4_readLE16(const void* memPtr)
    224 {
    225     if (LZ4_isLittleEndian()) {
    226         return LZ4_read16(memPtr);
    227     } else {
    228         const BYTE* p = (const BYTE*)memPtr;
    229         return (U16)((U16)p[0] + (p[1]<<8));
    230     }
    231 }
    232 
    233 static void LZ4_writeLE16(void* memPtr, U16 value)
    234 {
    235     if (LZ4_isLittleEndian()) {
    236         LZ4_write16(memPtr, value);
    237     } else {
    238         BYTE* p = (BYTE*)memPtr;
    239         p[0] = (BYTE) value;
    240         p[1] = (BYTE)(value>>8);
    241     }
    242 }
    243 
    244 static void LZ4_copy8(void* dst, const void* src)
    245 {
    246     memcpy(dst,src,8);
    247 }
    248 
    249 /* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */
    250 static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
    251 {
    252     BYTE* d = (BYTE*)dstPtr;
    253     const BYTE* s = (const BYTE*)srcPtr;
    254     BYTE* const e = (BYTE*)dstEnd;
    255 
    256     do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
    257 }
    258 
    259 
    260 /*-************************************
    261 *  Common Constants
    262 **************************************/
    263 #define MINMATCH 4
    264 
    265 #define WILDCOPYLENGTH 8
    266 #define LASTLITERALS 5
    267 #define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
    268 static const int LZ4_minLength = (MFLIMIT+1);
    269 
    270 #define KB *(1 <<10)
    271 #define MB *(1 <<20)
    272 #define GB *(1U<<30)
    273 
    274 #define MAXD_LOG 16
    275 #define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
    276 
    277 #define ML_BITS  4
    278 #define ML_MASK  ((1U<<ML_BITS)-1)
    279 #define RUN_BITS (8-ML_BITS)
    280 #define RUN_MASK ((1U<<RUN_BITS)-1)
    281 
    282 
    283 /*-************************************
    284 *  Common Utils
    285 **************************************/
    286 #define LZ4_STATIC_ASSERT(c)    { enum { LZ4_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */
    287 
    288 
    289 /*-************************************
    290 *  Common functions
    291 **************************************/
    292 static unsigned LZ4_NbCommonBytes (register reg_t val)
    293 {
    294     if (LZ4_isLittleEndian()) {
    295         if (sizeof(val)==8) {
    296 #       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
    297             unsigned long r = 0;
    298             _BitScanForward64( &r, (U64)val );
    299             return (int)(r>>3);
    300 #       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
    301             return (__builtin_ctzll((U64)val) >> 3);
    302 #       else
    303             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 };
    304             return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
    305 #       endif
    306         } else /* 32 bits */ {
    307 #       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
    308             unsigned long r;
    309             _BitScanForward( &r, (U32)val );
    310             return (int)(r>>3);
    311 #       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
    312             return (__builtin_ctz((U32)val) >> 3);
    313 #       else
    314             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 };
    315             return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
    316 #       endif
    317         }
    318     } else   /* Big Endian CPU */ {
    319         if (sizeof(val)==8) {
    320 #       if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
    321             unsigned long r = 0;
    322             _BitScanReverse64( &r, val );
    323             return (unsigned)(r>>3);
    324 #       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
    325             return (__builtin_clzll((U64)val) >> 3);
    326 #       else
    327             unsigned r;
    328             if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
    329             if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
    330             r += (!val);
    331             return r;
    332 #       endif
    333         } else /* 32 bits */ {
    334 #       if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
    335             unsigned long r = 0;
    336             _BitScanReverse( &r, (unsigned long)val );
    337             return (unsigned)(r>>3);
    338 #       elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT)
    339             return (__builtin_clz((U32)val) >> 3);
    340 #       else
    341             unsigned r;
    342             if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
    343             r += (!val);
    344             return r;
    345 #       endif
    346         }
    347     }
    348 }
    349 
    350 #define STEPSIZE sizeof(reg_t)
    351 static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
    352 {
    353     const BYTE* const pStart = pIn;
    354 
    355     while (likely(pIn<pInLimit-(STEPSIZE-1))) {
    356         reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
    357         if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
    358         pIn += LZ4_NbCommonBytes(diff);
    359         return (unsigned)(pIn - pStart);
    360     }
    361 
    362     if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
    363     if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
    364     if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
    365     return (unsigned)(pIn - pStart);
    366 }
    367 
    368 
    369 #ifndef LZ4_COMMONDEFS_ONLY
    370 /*-************************************
    371 *  Local Constants
    372 **************************************/
    373 static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
    374 static const U32 LZ4_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */
    375 
    376 
    377 /*-************************************
    378 *  Local Structures and types
    379 **************************************/
    380 typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
    381 typedef enum { byPtr, byU32, byU16 } tableType_t;
    382 
    383 typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
    384 typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
    385 
    386 typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
    387 typedef enum { full = 0, partial = 1 } earlyEnd_directive;
    388 
    389 
    390 /*-************************************
    391 *  Local Utils
    392 **************************************/
    393 int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
    394 const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }
    395 int LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }
    396 int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
    397 
    398 
    399 /*-******************************
    400 *  Compression functions
    401 ********************************/
    402 static U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
    403 {
    404     if (tableType == byU16)
    405         return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
    406     else
    407         return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
    408 }
    409 
    410 static U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
    411 {
    412     static const U64 prime5bytes = 889523592379ULL;
    413     static const U64 prime8bytes = 11400714785074694791ULL;
    414     const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;
    415     if (LZ4_isLittleEndian())
    416         return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
    417     else
    418         return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
    419 }
    420 
    421 FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)
    422 {
    423     if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);
    424     return LZ4_hash4(LZ4_read32(p), tableType);
    425 }
    426 
    427 static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)
    428 {
    429     switch (tableType)
    430     {
    431     case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
    432     case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
    433     case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
    434     }
    435 }
    436 
    437 FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
    438 {
    439     U32 const h = LZ4_hashPosition(p, tableType);
    440     LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
    441 }
    442 
    443 static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
    444 {
    445     if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }
    446     if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }
    447     { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; }   /* default, to ensure a return */
    448 }
    449 
    450 FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)
    451 {
    452     U32 const h = LZ4_hashPosition(p, tableType);
    453     return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
    454 }
    455 
    456 
    457 /** LZ4_compress_generic() :
    458     inlined, to ensure branches are decided at compilation time */
    459 FORCE_INLINE int LZ4_compress_generic(
    460                  LZ4_stream_t_internal* const cctx,
    461                  const char* const source,
    462                  char* const dest,
    463                  const int inputSize,
    464                  const int maxOutputSize,
    465                  const limitedOutput_directive outputLimited,
    466                  const tableType_t tableType,
    467                  const dict_directive dict,
    468                  const dictIssue_directive dictIssue,
    469                  const U32 acceleration)
    470 {
    471     const BYTE* ip = (const BYTE*) source;
    472     const BYTE* base;
    473     const BYTE* lowLimit;
    474     const BYTE* const lowRefLimit = ip - cctx->dictSize;
    475     const BYTE* const dictionary = cctx->dictionary;
    476     const BYTE* const dictEnd = dictionary + cctx->dictSize;
    477     const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source;
    478     const BYTE* anchor = (const BYTE*) source;
    479     const BYTE* const iend = ip + inputSize;
    480     const BYTE* const mflimit = iend - MFLIMIT;
    481     const BYTE* const matchlimit = iend - LASTLITERALS;
    482 
    483     BYTE* op = (BYTE*) dest;
    484     BYTE* const olimit = op + maxOutputSize;
    485 
    486     U32 forwardH;
    487 
    488     /* Init conditions */
    489     if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0;   /* Unsupported inputSize, too large (or negative) */
    490     switch(dict)
    491     {
    492     case noDict:
    493     default:
    494         base = (const BYTE*)source;
    495         lowLimit = (const BYTE*)source;
    496         break;
    497     case withPrefix64k:
    498         base = (const BYTE*)source - cctx->currentOffset;
    499         lowLimit = (const BYTE*)source - cctx->dictSize;
    500         break;
    501     case usingExtDict:
    502         base = (const BYTE*)source - cctx->currentOffset;
    503         lowLimit = (const BYTE*)source;
    504         break;
    505     }
    506     if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
    507     if (inputSize<LZ4_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */
    508 
    509     /* First Byte */
    510     LZ4_putPosition(ip, cctx->hashTable, tableType, base);
    511     ip++; forwardH = LZ4_hashPosition(ip, tableType);
    512 
    513     /* Main Loop */
    514     for ( ; ; ) {
    515         ptrdiff_t refDelta = 0;
    516         const BYTE* match;
    517         BYTE* token;
    518 
    519         /* Find a match */
    520         {   const BYTE* forwardIp = ip;
    521             unsigned step = 1;
    522             unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
    523             do {
    524                 U32 const h = forwardH;
    525                 ip = forwardIp;
    526                 forwardIp += step;
    527                 step = (searchMatchNb++ >> LZ4_skipTrigger);
    528 
    529                 if (unlikely(forwardIp > mflimit)) goto _last_literals;
    530 
    531                 match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base);
    532                 if (dict==usingExtDict) {
    533                     if (match < (const BYTE*)source) {
    534                         refDelta = dictDelta;
    535                         lowLimit = dictionary;
    536                     } else {
    537                         refDelta = 0;
    538                         lowLimit = (const BYTE*)source;
    539                 }   }
    540                 forwardH = LZ4_hashPosition(forwardIp, tableType);
    541                 LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base);
    542 
    543             } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
    544                 || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
    545                 || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
    546         }
    547 
    548         /* Catch up */
    549         while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
    550 
    551         /* Encode Literals */
    552         {   unsigned const litLength = (unsigned)(ip - anchor);
    553             token = op++;
    554             if ((outputLimited) &&  /* Check output buffer overflow */
    555                 (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))
    556                 return 0;
    557             if (litLength >= RUN_MASK) {
    558                 int len = (int)litLength-RUN_MASK;
    559                 *token = (RUN_MASK<<ML_BITS);
    560                 for(; len >= 255 ; len-=255) *op++ = 255;
    561                 *op++ = (BYTE)len;
    562             }
    563             else *token = (BYTE)(litLength<<ML_BITS);
    564 
    565             /* Copy Literals */
    566             LZ4_wildCopy(op, anchor, op+litLength);
    567             op+=litLength;
    568         }
    569 
    570 _next_match:
    571         /* Encode Offset */
    572         LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
    573 
    574         /* Encode MatchLength */
    575         {   unsigned matchCode;
    576 
    577             if ((dict==usingExtDict) && (lowLimit==dictionary)) {
    578                 const BYTE* limit;
    579                 match += refDelta;
    580                 limit = ip + (dictEnd-match);
    581                 if (limit > matchlimit) limit = matchlimit;
    582                 matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
    583                 ip += MINMATCH + matchCode;
    584                 if (ip==limit) {
    585                     unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit);
    586                     matchCode += more;
    587                     ip += more;
    588                 }
    589             } else {
    590                 matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
    591                 ip += MINMATCH + matchCode;
    592             }
    593 
    594             if ( outputLimited &&    /* Check output buffer overflow */
    595                 (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) )
    596                 return 0;
    597             if (matchCode >= ML_MASK) {
    598                 *token += ML_MASK;
    599                 matchCode -= ML_MASK;
    600                 LZ4_write32(op, 0xFFFFFFFF);
    601                 while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255;
    602                 op += matchCode / 255;
    603                 *op++ = (BYTE)(matchCode % 255);
    604             } else
    605                 *token += (BYTE)(matchCode);
    606         }
    607 
    608         anchor = ip;
    609 
    610         /* Test end of chunk */
    611         if (ip > mflimit) break;
    612 
    613         /* Fill table */
    614         LZ4_putPosition(ip-2, cctx->hashTable, tableType, base);
    615 
    616         /* Test next position */
    617         match = LZ4_getPosition(ip, cctx->hashTable, tableType, base);
    618         if (dict==usingExtDict) {
    619             if (match < (const BYTE*)source) {
    620                 refDelta = dictDelta;
    621                 lowLimit = dictionary;
    622             } else {
    623                 refDelta = 0;
    624                 lowLimit = (const BYTE*)source;
    625         }   }
    626         LZ4_putPosition(ip, cctx->hashTable, tableType, base);
    627         if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
    628             && (match+MAX_DISTANCE>=ip)
    629             && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
    630         { token=op++; *token=0; goto _next_match; }
    631 
    632         /* Prepare next loop */
    633         forwardH = LZ4_hashPosition(++ip, tableType);
    634     }
    635 
    636 _last_literals:
    637     /* Encode Last Literals */
    638     {   size_t const lastRun = (size_t)(iend - anchor);
    639         if ( (outputLimited) &&  /* Check output buffer overflow */
    640             ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) )
    641             return 0;
    642         if (lastRun >= RUN_MASK) {
    643             size_t accumulator = lastRun - RUN_MASK;
    644             *op++ = RUN_MASK << ML_BITS;
    645             for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
    646             *op++ = (BYTE) accumulator;
    647         } else {
    648             *op++ = (BYTE)(lastRun<<ML_BITS);
    649         }
    650         memcpy(op, anchor, lastRun);
    651         op += lastRun;
    652     }
    653 
    654     /* End */
    655     return (int) (((char*)op)-dest);
    656 }
    657 
    658 
    659 int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
    660 {
    661     LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse;
    662     LZ4_resetStream((LZ4_stream_t*)state);
    663     if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
    664 
    665     if (maxOutputSize >= LZ4_compressBound(inputSize)) {
    666         if (inputSize < LZ4_64Klimit)
    667             return LZ4_compress_generic(ctx, source, dest, inputSize,             0,    notLimited,                        byU16, noDict, noDictIssue, acceleration);
    668         else
    669             return LZ4_compress_generic(ctx, source, dest, inputSize,             0,    notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
    670     } else {
    671         if (inputSize < LZ4_64Klimit)
    672             return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput,                        byU16, noDict, noDictIssue, acceleration);
    673         else
    674             return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration);
    675     }
    676 }
    677 
    678 
    679 int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
    680 {
    681 #if (HEAPMODE)
    682     void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
    683 #else
    684     LZ4_stream_t ctx;
    685     void* const ctxPtr = &ctx;
    686 #endif
    687 
    688     int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
    689 
    690 #if (HEAPMODE)
    691     FREEMEM(ctxPtr);
    692 #endif
    693     return result;
    694 }
    695 
    696 
    697 int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)
    698 {
    699     return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
    700 }
    701 
    702 
    703 /* hidden debug function */
    704 /* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
    705 int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
    706 {
    707     LZ4_stream_t ctx;
    708     LZ4_resetStream(&ctx);
    709 
    710     if (inputSize < LZ4_64Klimit)
    711         return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);
    712     else
    713         return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration);
    714 }
    715 
    716 
    717 /*-******************************
    718 *  *_destSize() variant
    719 ********************************/
    720 
    721 static int LZ4_compress_destSize_generic(
    722                        LZ4_stream_t_internal* const ctx,
    723                  const char* const src,
    724                        char* const dst,
    725                        int*  const srcSizePtr,
    726                  const int targetDstSize,
    727                  const tableType_t tableType)
    728 {
    729     const BYTE* ip = (const BYTE*) src;
    730     const BYTE* base = (const BYTE*) src;
    731     const BYTE* lowLimit = (const BYTE*) src;
    732     const BYTE* anchor = ip;
    733     const BYTE* const iend = ip + *srcSizePtr;
    734     const BYTE* const mflimit = iend - MFLIMIT;
    735     const BYTE* const matchlimit = iend - LASTLITERALS;
    736 
    737     BYTE* op = (BYTE*) dst;
    738     BYTE* const oend = op + targetDstSize;
    739     BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
    740     BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
    741     BYTE* const oMaxSeq = oMaxLit - 1 /* token */;
    742 
    743     U32 forwardH;
    744 
    745 
    746     /* Init conditions */
    747     if (targetDstSize < 1) return 0;                                     /* Impossible to store anything */
    748     if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0;            /* Unsupported input size, too large (or negative) */
    749     if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0;   /* Size too large (not within 64K limit) */
    750     if (*srcSizePtr<LZ4_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */
    751 
    752     /* First Byte */
    753     *srcSizePtr = 0;
    754     LZ4_putPosition(ip, ctx->hashTable, tableType, base);
    755     ip++; forwardH = LZ4_hashPosition(ip, tableType);
    756 
    757     /* Main Loop */
    758     for ( ; ; ) {
    759         const BYTE* match;
    760         BYTE* token;
    761 
    762         /* Find a match */
    763         {   const BYTE* forwardIp = ip;
    764             unsigned step = 1;
    765             unsigned searchMatchNb = 1 << LZ4_skipTrigger;
    766 
    767             do {
    768                 U32 h = forwardH;
    769                 ip = forwardIp;
    770                 forwardIp += step;
    771                 step = (searchMatchNb++ >> LZ4_skipTrigger);
    772 
    773                 if (unlikely(forwardIp > mflimit)) goto _last_literals;
    774 
    775                 match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base);
    776                 forwardH = LZ4_hashPosition(forwardIp, tableType);
    777                 LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base);
    778 
    779             } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
    780                 || (LZ4_read32(match) != LZ4_read32(ip)) );
    781         }
    782 
    783         /* Catch up */
    784         while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }
    785 
    786         /* Encode Literal length */
    787         {   unsigned litLength = (unsigned)(ip - anchor);
    788             token = op++;
    789             if (op + ((litLength+240)/255) + litLength > oMaxLit) {
    790                 /* Not enough space for a last match */
    791                 op--;
    792                 goto _last_literals;
    793             }
    794             if (litLength>=RUN_MASK) {
    795                 unsigned len = litLength - RUN_MASK;
    796                 *token=(RUN_MASK<<ML_BITS);
    797                 for(; len >= 255 ; len-=255) *op++ = 255;
    798                 *op++ = (BYTE)len;
    799             }
    800             else *token = (BYTE)(litLength<<ML_BITS);
    801 
    802             /* Copy Literals */
    803             LZ4_wildCopy(op, anchor, op+litLength);
    804             op += litLength;
    805         }
    806 
    807 _next_match:
    808         /* Encode Offset */
    809         LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
    810 
    811         /* Encode MatchLength */
    812         {   size_t matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
    813 
    814             if (op + ((matchLength+240)/255) > oMaxMatch) {
    815                 /* Match description too long : reduce it */
    816                 matchLength = (15-1) + (oMaxMatch-op) * 255;
    817             }
    818             ip += MINMATCH + matchLength;
    819 
    820             if (matchLength>=ML_MASK) {
    821                 *token += ML_MASK;
    822                 matchLength -= ML_MASK;
    823                 while (matchLength >= 255) { matchLength-=255; *op++ = 255; }
    824                 *op++ = (BYTE)matchLength;
    825             }
    826             else *token += (BYTE)(matchLength);
    827         }
    828 
    829         anchor = ip;
    830 
    831         /* Test end of block */
    832         if (ip > mflimit) break;
    833         if (op > oMaxSeq) break;
    834 
    835         /* Fill table */
    836         LZ4_putPosition(ip-2, ctx->hashTable, tableType, base);
    837 
    838         /* Test next position */
    839         match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
    840         LZ4_putPosition(ip, ctx->hashTable, tableType, base);
    841         if ( (match+MAX_DISTANCE>=ip)
    842             && (LZ4_read32(match)==LZ4_read32(ip)) )
    843         { token=op++; *token=0; goto _next_match; }
    844 
    845         /* Prepare next loop */
    846         forwardH = LZ4_hashPosition(++ip, tableType);
    847     }
    848 
    849 _last_literals:
    850     /* Encode Last Literals */
    851     {   size_t lastRunSize = (size_t)(iend - anchor);
    852         if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) {
    853             /* adapt lastRunSize to fill 'dst' */
    854             lastRunSize  = (oend-op) - 1;
    855             lastRunSize -= (lastRunSize+240)/255;
    856         }
    857         ip = anchor + lastRunSize;
    858 
    859         if (lastRunSize >= RUN_MASK) {
    860             size_t accumulator = lastRunSize - RUN_MASK;
    861             *op++ = RUN_MASK << ML_BITS;
    862             for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;
    863             *op++ = (BYTE) accumulator;
    864         } else {
    865             *op++ = (BYTE)(lastRunSize<<ML_BITS);
    866         }
    867         memcpy(op, anchor, lastRunSize);
    868         op += lastRunSize;
    869     }
    870 
    871     /* End */
    872     *srcSizePtr = (int) (((const char*)ip)-src);
    873     return (int) (((char*)op)-dst);
    874 }
    875 
    876 
    877 static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)
    878 {
    879     LZ4_resetStream(state);
    880 
    881     if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) {  /* compression success is guaranteed */
    882         return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
    883     } else {
    884         if (*srcSizePtr < LZ4_64Klimit)
    885             return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16);
    886         else
    887             return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr);
    888     }
    889 }
    890 
    891 
    892 int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)
    893 {
    894 #if (HEAPMODE)
    895     LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */
    896 #else
    897     LZ4_stream_t ctxBody;
    898     LZ4_stream_t* ctx = &ctxBody;
    899 #endif
    900 
    901     int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
    902 
    903 #if (HEAPMODE)
    904     FREEMEM(ctx);
    905 #endif
    906     return result;
    907 }
    908 
    909 
    910 
    911 /*-******************************
    912 *  Streaming functions
    913 ********************************/
    914 
    915 LZ4_stream_t* LZ4_createStream(void)
    916 {
    917     LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
    918     LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal));    /* A compilation error here means LZ4_STREAMSIZE is not large enough */
    919     LZ4_resetStream(lz4s);
    920     return lz4s;
    921 }
    922 
    923 void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
    924 {
    925     MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t));
    926 }
    927 
    928 int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
    929 {
    930     FREEMEM(LZ4_stream);
    931     return (0);
    932 }
    933 
    934 
    935 #define HASH_UNIT sizeof(reg_t)
    936 int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)
    937 {
    938     LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse;
    939     const BYTE* p = (const BYTE*)dictionary;
    940     const BYTE* const dictEnd = p + dictSize;
    941     const BYTE* base;
    942 
    943     if ((dict->initCheck) || (dict->currentOffset > 1 GB))  /* Uninitialized structure, or reuse overflow */
    944         LZ4_resetStream(LZ4_dict);
    945 
    946     if (dictSize < (int)HASH_UNIT) {
    947         dict->dictionary = NULL;
    948         dict->dictSize = 0;
    949         return 0;
    950     }
    951 
    952     if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;
    953     dict->currentOffset += 64 KB;
    954     base = p - dict->currentOffset;
    955     dict->dictionary = p;
    956     dict->dictSize = (U32)(dictEnd - p);
    957     dict->currentOffset += dict->dictSize;
    958 
    959     while (p <= dictEnd-HASH_UNIT) {
    960         LZ4_putPosition(p, dict->hashTable, byU32, base);
    961         p+=3;
    962     }
    963 
    964     return dict->dictSize;
    965 }
    966 
    967 
    968 static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src)
    969 {
    970     if ((LZ4_dict->currentOffset > 0x80000000) ||
    971         ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) {   /* address space overflow */
    972         /* rescale hash table */
    973         U32 const delta = LZ4_dict->currentOffset - 64 KB;
    974         const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
    975         int i;
    976         for (i=0; i<LZ4_HASH_SIZE_U32; i++) {
    977             if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;
    978             else LZ4_dict->hashTable[i] -= delta;
    979         }
    980         LZ4_dict->currentOffset = 64 KB;
    981         if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;
    982         LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
    983     }
    984 }
    985 
    986 
    987 int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)
    988 {
    989     LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse;
    990     const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
    991 
    992     const BYTE* smallest = (const BYTE*) source;
    993     if (streamPtr->initCheck) return 0;   /* Uninitialized structure detected */
    994     if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;
    995     LZ4_renormDictT(streamPtr, smallest);
    996     if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;
    997 
    998     /* Check overlapping input/dictionary space */
    999     {   const BYTE* sourceEnd = (const BYTE*) source + inputSize;
   1000         if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
   1001             streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
   1002             if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;
   1003             if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;
   1004             streamPtr->dictionary = dictEnd - streamPtr->dictSize;
   1005         }
   1006     }
   1007 
   1008     /* prefix mode : source data follows dictionary */
   1009     if (dictEnd == (const BYTE*)source) {
   1010         int result;
   1011         if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
   1012             result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);
   1013         else
   1014             result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);
   1015         streamPtr->dictSize += (U32)inputSize;
   1016         streamPtr->currentOffset += (U32)inputSize;
   1017         return result;
   1018     }
   1019 
   1020     /* external dictionary mode */
   1021     {   int result;
   1022         if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
   1023             result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);
   1024         else
   1025             result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);
   1026         streamPtr->dictionary = (const BYTE*)source;
   1027         streamPtr->dictSize = (U32)inputSize;
   1028         streamPtr->currentOffset += (U32)inputSize;
   1029         return result;
   1030     }
   1031 }
   1032 
   1033 
   1034 /* Hidden debug function, to force external dictionary mode */
   1035 int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize)
   1036 {
   1037     LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse;
   1038     int result;
   1039     const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
   1040 
   1041     const BYTE* smallest = dictEnd;
   1042     if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;
   1043     LZ4_renormDictT(streamPtr, smallest);
   1044 
   1045     result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
   1046 
   1047     streamPtr->dictionary = (const BYTE*)source;
   1048     streamPtr->dictSize = (U32)inputSize;
   1049     streamPtr->currentOffset += (U32)inputSize;
   1050 
   1051     return result;
   1052 }
   1053 
   1054 
   1055 /*! LZ4_saveDict() :
   1056  *  If previously compressed data block is not guaranteed to remain available at its memory location,
   1057  *  save it into a safer place (char* safeBuffer).
   1058  *  Note : you don't need to call LZ4_loadDict() afterwards,
   1059  *         dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue().
   1060  *  Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.
   1061  */
   1062 int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
   1063 {
   1064     LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;
   1065     const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;
   1066 
   1067     if ((U32)dictSize > 64 KB) dictSize = 64 KB;   /* useless to define a dictionary > 64 KB */
   1068     if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;
   1069 
   1070     memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
   1071 
   1072     dict->dictionary = (const BYTE*)safeBuffer;
   1073     dict->dictSize = (U32)dictSize;
   1074 
   1075     return dictSize;
   1076 }
   1077 
   1078 
   1079 
   1080 /*-*****************************
   1081 *  Decompression functions
   1082 *******************************/
   1083 /*! LZ4_decompress_generic() :
   1084  *  This generic decompression function cover all use cases.
   1085  *  It shall be instantiated several times, using different sets of directives
   1086  *  Note that it is important this generic function is really inlined,
   1087  *  in order to remove useless branches during compilation optimization.
   1088  */
   1089 FORCE_INLINE int LZ4_decompress_generic(
   1090                  const char* const source,
   1091                  char* const dest,
   1092                  int inputSize,
   1093                  int outputSize,         /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
   1094 
   1095                  int endOnInput,         /* endOnOutputSize, endOnInputSize */
   1096                  int partialDecoding,    /* full, partial */
   1097                  int targetOutputSize,   /* only used if partialDecoding==partial */
   1098                  int dict,               /* noDict, withPrefix64k, usingExtDict */
   1099                  const BYTE* const lowPrefix,  /* == dest when no prefix */
   1100                  const BYTE* const dictStart,  /* only if dict==usingExtDict */
   1101                  const size_t dictSize         /* note : = 0 if noDict */
   1102                  )
   1103 {
   1104     /* Local Variables */
   1105     const BYTE* ip = (const BYTE*) source;
   1106     const BYTE* const iend = ip + inputSize;
   1107 
   1108     BYTE* op = (BYTE*) dest;
   1109     BYTE* const oend = op + outputSize;
   1110     BYTE* cpy;
   1111     BYTE* oexit = op + targetOutputSize;
   1112     const BYTE* const lowLimit = lowPrefix - dictSize;
   1113 
   1114     const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
   1115     const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};
   1116     const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
   1117 
   1118     const int safeDecode = (endOnInput==endOnInputSize);
   1119     const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
   1120 
   1121 
   1122     /* Special cases */
   1123     if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT;                        /* targetOutputSize too high => decode everything */
   1124     if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1;  /* Empty output buffer */
   1125     if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
   1126 
   1127     /* Main Loop : decode sequences */
   1128     while (1) {
   1129         size_t length;
   1130         const BYTE* match;
   1131         size_t offset;
   1132 
   1133         /* get literal length */
   1134         unsigned const token = *ip++;
   1135         if ((length=(token>>ML_BITS)) == RUN_MASK) {
   1136             unsigned s;
   1137             do {
   1138                 s = *ip++;
   1139                 length += s;
   1140             } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) );
   1141             if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error;   /* overflow detection */
   1142             if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error;   /* overflow detection */
   1143         }
   1144 
   1145         /* copy literals */
   1146         cpy = op+length;
   1147         if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
   1148             || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) )
   1149         {
   1150             if (partialDecoding) {
   1151                 if (cpy > oend) goto _output_error;                           /* Error : write attempt beyond end of output buffer */
   1152                 if ((endOnInput) && (ip+length > iend)) goto _output_error;   /* Error : read attempt beyond end of input buffer */
   1153             } else {
   1154                 if ((!endOnInput) && (cpy != oend)) goto _output_error;       /* Error : block decoding must stop exactly there */
   1155                 if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error;   /* Error : input must be consumed */
   1156             }
   1157             memcpy(op, ip, length);
   1158             ip += length;
   1159             op += length;
   1160             break;     /* Necessarily EOF, due to parsing restrictions */
   1161         }
   1162         LZ4_wildCopy(op, ip, cpy);
   1163         ip += length; op = cpy;
   1164 
   1165         /* get offset */
   1166         offset = LZ4_readLE16(ip); ip+=2;
   1167         match = op - offset;
   1168         if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error;   /* Error : offset outside buffers */
   1169         LZ4_write32(op, (U32)offset);   /* costs ~1%; silence an msan warning when offset==0 */
   1170 
   1171         /* get matchlength */
   1172         length = token & ML_MASK;
   1173         if (length == ML_MASK) {
   1174             unsigned s;
   1175             do {
   1176                 s = *ip++;
   1177                 if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
   1178                 length += s;
   1179             } while (s==255);
   1180             if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error;   /* overflow detection */
   1181         }
   1182         length += MINMATCH;
   1183 
   1184         /* check external dictionary */
   1185         if ((dict==usingExtDict) && (match < lowPrefix)) {
   1186             if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error;   /* doesn't respect parsing restriction */
   1187 
   1188             if (length <= (size_t)(lowPrefix-match)) {
   1189                 /* match can be copied as a single segment from external dictionary */
   1190                 memmove(op, dictEnd - (lowPrefix-match), length);
   1191                 op += length;
   1192             } else {
   1193                 /* match encompass external dictionary and current block */
   1194                 size_t const copySize = (size_t)(lowPrefix-match);
   1195                 size_t const restSize = length - copySize;
   1196                 memcpy(op, dictEnd - copySize, copySize);
   1197                 op += copySize;
   1198                 if (restSize > (size_t)(op-lowPrefix)) {  /* overlap copy */
   1199                     BYTE* const endOfMatch = op + restSize;
   1200                     const BYTE* copyFrom = lowPrefix;
   1201                     while (op < endOfMatch) *op++ = *copyFrom++;
   1202                 } else {
   1203                     memcpy(op, lowPrefix, restSize);
   1204                     op += restSize;
   1205             }   }
   1206             continue;
   1207         }
   1208 
   1209         /* copy match within block */
   1210         cpy = op + length;
   1211         if (unlikely(offset<8)) {
   1212             const int dec64 = dec64table[offset];
   1213             op[0] = match[0];
   1214             op[1] = match[1];
   1215             op[2] = match[2];
   1216             op[3] = match[3];
   1217             match += dec32table[offset];
   1218             memcpy(op+4, match, 4);
   1219             match -= dec64;
   1220         } else { LZ4_copy8(op, match); match+=8; }
   1221         op += 8;
   1222 
   1223         if (unlikely(cpy>oend-12)) {
   1224             BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
   1225             if (cpy > oend-LASTLITERALS) goto _output_error;    /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
   1226             if (op < oCopyLimit) {
   1227                 LZ4_wildCopy(op, match, oCopyLimit);
   1228                 match += oCopyLimit - op;
   1229                 op = oCopyLimit;
   1230             }
   1231             while (op<cpy) *op++ = *match++;
   1232         } else {
   1233             LZ4_copy8(op, match);
   1234             if (length>16) LZ4_wildCopy(op+8, match+8, cpy);
   1235         }
   1236         op=cpy;   /* correction */
   1237     }
   1238 
   1239     /* end of decoding */
   1240     if (endOnInput)
   1241        return (int) (((char*)op)-dest);     /* Nb of output bytes decoded */
   1242     else
   1243        return (int) (((const char*)ip)-source);   /* Nb of input bytes read */
   1244 
   1245     /* Overflow error detected */
   1246 _output_error:
   1247     return (int) (-(((const char*)ip)-source))-1;
   1248 }
   1249 
   1250 
   1251 int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)
   1252 {
   1253     return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);
   1254 }
   1255 
   1256 int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)
   1257 {
   1258     return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);
   1259 }
   1260 
   1261 int LZ4_decompress_fast(const char* source, char* dest, int originalSize)
   1262 {
   1263     return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB);
   1264 }
   1265 
   1266 
   1267 /*===== streaming decompression functions =====*/
   1268 
   1269 /*
   1270  * If you prefer dynamic allocation methods,
   1271  * LZ4_createStreamDecode()
   1272  * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
   1273  */
   1274 LZ4_streamDecode_t* LZ4_createStreamDecode(void)
   1275 {
   1276     LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
   1277     return lz4s;
   1278 }
   1279 
   1280 int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
   1281 {
   1282     FREEMEM(LZ4_stream);
   1283     return 0;
   1284 }
   1285 
   1286 /*!
   1287  * LZ4_setStreamDecode() :
   1288  * Use this function to instruct where to find the dictionary.
   1289  * This function is not necessary if previous data is still available where it was decoded.
   1290  * Loading a size of 0 is allowed (same effect as no dictionary).
   1291  * Return : 1 if OK, 0 if error
   1292  */
   1293 int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)
   1294 {
   1295     LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
   1296     lz4sd->prefixSize = (size_t) dictSize;
   1297     lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;
   1298     lz4sd->externalDict = NULL;
   1299     lz4sd->extDictSize  = 0;
   1300     return 1;
   1301 }
   1302 
   1303 /*
   1304 *_continue() :
   1305     These decoding functions allow decompression of multiple blocks in "streaming" mode.
   1306     Previously decoded blocks must still be available at the memory position where they were decoded.
   1307     If it's not possible, save the relevant part of decoded data into a safe buffer,
   1308     and indicate where it stands using LZ4_setStreamDecode()
   1309 */
   1310 int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)
   1311 {
   1312     LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
   1313     int result;
   1314 
   1315     if (lz4sd->prefixEnd == (BYTE*)dest) {
   1316         result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
   1317                                         endOnInputSize, full, 0,
   1318                                         usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
   1319         if (result <= 0) return result;
   1320         lz4sd->prefixSize += result;
   1321         lz4sd->prefixEnd  += result;
   1322     } else {
   1323         lz4sd->extDictSize = lz4sd->prefixSize;
   1324         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
   1325         result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,
   1326                                         endOnInputSize, full, 0,
   1327                                         usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
   1328         if (result <= 0) return result;
   1329         lz4sd->prefixSize = result;
   1330         lz4sd->prefixEnd  = (BYTE*)dest + result;
   1331     }
   1332 
   1333     return result;
   1334 }
   1335 
   1336 int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize)
   1337 {
   1338     LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;
   1339     int result;
   1340 
   1341     if (lz4sd->prefixEnd == (BYTE*)dest) {
   1342         result = LZ4_decompress_generic(source, dest, 0, originalSize,
   1343                                         endOnOutputSize, full, 0,
   1344                                         usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
   1345         if (result <= 0) return result;
   1346         lz4sd->prefixSize += originalSize;
   1347         lz4sd->prefixEnd  += originalSize;
   1348     } else {
   1349         lz4sd->extDictSize = lz4sd->prefixSize;
   1350         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
   1351         result = LZ4_decompress_generic(source, dest, 0, originalSize,
   1352                                         endOnOutputSize, full, 0,
   1353                                         usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize);
   1354         if (result <= 0) return result;
   1355         lz4sd->prefixSize = originalSize;
   1356         lz4sd->prefixEnd  = (BYTE*)dest + originalSize;
   1357     }
   1358 
   1359     return result;
   1360 }
   1361 
   1362 
   1363 /*
   1364 Advanced decoding functions :
   1365 *_usingDict() :
   1366     These decoding functions work the same as "_continue" ones,
   1367     the dictionary must be explicitly provided within parameters
   1368 */
   1369 
   1370 FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)
   1371 {
   1372     if (dictSize==0)
   1373         return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);
   1374     if (dictStart+dictSize == dest) {
   1375         if (dictSize >= (int)(64 KB - 1))
   1376             return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0);
   1377         return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);
   1378     }
   1379     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
   1380 }
   1381 
   1382 int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
   1383 {
   1384     return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
   1385 }
   1386 
   1387 int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)
   1388 {
   1389     return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
   1390 }
   1391 
   1392 /* debug function */
   1393 int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)
   1394 {
   1395     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);
   1396 }
   1397 
   1398 
   1399 /*=*************************************************
   1400 *  Obsolete Functions
   1401 ***************************************************/
   1402 /* obsolete compression functions */
   1403 int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); }
   1404 int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); }
   1405 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); }
   1406 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); }
   1407 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); }
   1408 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); }
   1409 
   1410 /*
   1411 These function names are deprecated and should no longer be used.
   1412 They are only provided here for compatibility with older user programs.
   1413 - LZ4_uncompress is totally equivalent to LZ4_decompress_fast
   1414 - LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
   1415 */
   1416 int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); }
   1417 int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); }
   1418 
   1419 
   1420 /* Obsolete Streaming functions */
   1421 
   1422 int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
   1423 
   1424 static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base)
   1425 {
   1426     MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t));
   1427     lz4ds->internal_donotuse.bufferStart = base;
   1428 }
   1429 
   1430 int LZ4_resetStreamState(void* state, char* inputBuffer)
   1431 {
   1432     if ((((uptrval)state) & 3) != 0) return 1;   /* Error : pointer is not aligned on 4-bytes boundary */
   1433     LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer);
   1434     return 0;
   1435 }
   1436 
   1437 void* LZ4_create (char* inputBuffer)
   1438 {
   1439     LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t));
   1440     LZ4_init (lz4ds, (BYTE*)inputBuffer);
   1441     return lz4ds;
   1442 }
   1443 
   1444 char* LZ4_slideInputBuffer (void* LZ4_Data)
   1445 {
   1446     LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse;
   1447     int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB);
   1448     return (char*)(ctx->bufferStart + dictSize);
   1449 }
   1450 
   1451 /* Obsolete streaming decompression functions */
   1452 
   1453 int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)
   1454 {
   1455     return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
   1456 }
   1457 
   1458 int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)
   1459 {
   1460     return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
   1461 }
   1462 
   1463 #endif   /* LZ4_COMMONDEFS_ONLY */
   1464