kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

lz4hc.c (93376B)


      1 /*
      2     LZ4 HC - High Compression Mode of LZ4
      3     Copyright (C) 2011-2020, Yann Collet.
      4 
      5     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
      6 
      7     Redistribution and use in source and binary forms, with or without
      8     modification, are permitted provided that the following conditions are
      9     met:
     10 
     11     * Redistributions of source code must retain the above copyright
     12     notice, this list of conditions and the following disclaimer.
     13     * Redistributions in binary form must reproduce the above
     14     copyright notice, this list of conditions and the following disclaimer
     15     in the documentation and/or other materials provided with the
     16     distribution.
     17 
     18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30     You can contact the author at :
     31        - LZ4 source repository : https://github.com/lz4/lz4
     32        - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
     33 */
     34 /* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
     35 
     36 
     37 /* *************************************
     38 *  Tuning Parameter
     39 ***************************************/
     40 
     41 /*! HEAPMODE :
     42  *  Select how stateless HC compression functions like `LZ4_compress_HC()`
     43  *  allocate memory for their workspace:
     44  *  in stack (0:fastest), or in heap (1:default, requires malloc()).
     45  *  Since workspace is rather large, heap mode is recommended.
     46 **/
     47 #ifndef LZ4HC_HEAPMODE
     48 #  define LZ4HC_HEAPMODE 1
     49 #endif
     50 
     51 
     52 /*===    Dependency    ===*/
     53 #define LZ4_HC_STATIC_LINKING_ONLY
     54 #include "lz4hc.h"
     55 #include <limits.h>
     56 
     57 
     58 /*===   Shared lz4.c code   ===*/
     59 #ifndef LZ4_SRC_INCLUDED
     60 # if defined(__GNUC__)
     61 #  pragma GCC diagnostic ignored "-Wunused-function"
     62 # endif
     63 # if defined (__clang__)
     64 #  pragma clang diagnostic ignored "-Wunused-function"
     65 # endif
     66 # define LZ4_COMMONDEFS_ONLY
     67 # include "lz4.c"   /* LZ4_count, constants, mem */
     68 #endif
     69 
     70 
     71 /*===   Enums   ===*/
     72 typedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;
     73 
     74 
     75 /*===   Constants   ===*/
     76 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
     77 #define LZ4_OPT_NUM   (1<<12)
     78 
     79 
     80 /*===   Macros   ===*/
     81 #define MIN(a,b)   ( (a) < (b) ? (a) : (b) )
     82 #define MAX(a,b)   ( (a) > (b) ? (a) : (b) )
     83 
     84 
     85 /*===   Levels definition   ===*/
     86 typedef enum { lz4mid, lz4hc, lz4opt } lz4hc_strat_e;
     87 typedef struct {
     88     lz4hc_strat_e strat;
     89     int nbSearches;
     90     U32 targetLength;
     91 } cParams_t;
     92 static const cParams_t k_clTable[LZ4HC_CLEVEL_MAX+1] = {
     93     { lz4mid,    2, 16 },  /* 0, unused */
     94     { lz4mid,    2, 16 },  /* 1, unused */
     95     { lz4mid,    2, 16 },  /* 2 */
     96     { lz4hc,     4, 16 },  /* 3 */
     97     { lz4hc,     8, 16 },  /* 4 */
     98     { lz4hc,    16, 16 },  /* 5 */
     99     { lz4hc,    32, 16 },  /* 6 */
    100     { lz4hc,    64, 16 },  /* 7 */
    101     { lz4hc,   128, 16 },  /* 8 */
    102     { lz4hc,   256, 16 },  /* 9 */
    103     { lz4opt,   96, 64 },  /*10==LZ4HC_CLEVEL_OPT_MIN*/
    104     { lz4opt,  512,128 },  /*11 */
    105     { lz4opt,16384,LZ4_OPT_NUM },  /* 12==LZ4HC_CLEVEL_MAX */
    106 };
    107 
    108 static cParams_t LZ4HC_getCLevelParams(int cLevel)
    109 {
    110     /* note : clevel convention is a bit different from lz4frame,
    111      * possibly something worth revisiting for consistency */
    112     if (cLevel < 1)
    113         cLevel = LZ4HC_CLEVEL_DEFAULT;
    114     cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel);
    115     return k_clTable[cLevel];
    116 }
    117 
    118 
    119 /*===   Hashing   ===*/
    120 #define LZ4HC_HASHSIZE 4
    121 #define HASH_FUNCTION(i)      (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
    122 static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
    123 
    124 #if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)
    125 /* lie to the compiler about data alignment; use with caution */
    126 static U64 LZ4_read64(const void* memPtr) { return *(const U64*) memPtr; }
    127 
    128 #elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)
    129 /* __pack instructions are safer, but compiler specific */
    130 LZ4_PACK(typedef struct { U64 u64; }) LZ4_unalign64;
    131 static U64 LZ4_read64(const void* ptr) { return ((const LZ4_unalign64*)ptr)->u64; }
    132 
    133 #else  /* safe and portable access using memcpy() */
    134 static U64 LZ4_read64(const void* memPtr)
    135 {
    136     U64 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;
    137 }
    138 
    139 #endif /* LZ4_FORCE_MEMORY_ACCESS */
    140 
    141 #define LZ4MID_HASHSIZE 8
    142 #define LZ4MID_HASHLOG (LZ4HC_HASH_LOG-1)
    143 #define LZ4MID_HASHTABLESIZE (1 << LZ4MID_HASHLOG)
    144 
    145 static U32 LZ4MID_hash4(U32 v) { return (v * 2654435761U) >> (32-LZ4MID_HASHLOG); }
    146 static U32 LZ4MID_hash4Ptr(const void* ptr) { return LZ4MID_hash4(LZ4_read32(ptr)); }
    147 /* note: hash7 hashes the lower 56-bits.
    148  * It presumes input was read using little endian.*/
    149 static U32 LZ4MID_hash7(U64 v) { return (U32)(((v  << (64-56)) * 58295818150454627ULL) >> (64-LZ4MID_HASHLOG)) ; }
    150 static U64 LZ4_readLE64(const void* memPtr);
    151 static U32 LZ4MID_hash8Ptr(const void* ptr) { return LZ4MID_hash7(LZ4_readLE64(ptr)); }
    152 
    153 static U64 LZ4_readLE64(const void* memPtr)
    154 {
    155     if (LZ4_isLittleEndian()) {
    156         return LZ4_read64(memPtr);
    157     } else {
    158         const BYTE* p = (const BYTE*)memPtr;
    159         /* note: relies on the compiler to simplify this expression */
    160         return (U64)p[0] | ((U64)p[1]<<8) | ((U64)p[2]<<16) | ((U64)p[3]<<24)
    161             | ((U64)p[4]<<32) | ((U64)p[5]<<40) | ((U64)p[6]<<48) | ((U64)p[7]<<56);
    162     }
    163 }
    164 
    165 
    166 /*===   Count match length   ===*/
    167 LZ4_FORCE_INLINE
    168 unsigned LZ4HC_NbCommonBytes32(U32 val)
    169 {
    170     assert(val != 0);
    171     if (LZ4_isLittleEndian()) {
    172 #     if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
    173         unsigned long r;
    174         _BitScanReverse(&r, val);
    175         return (unsigned)((31 - r) >> 3);
    176 #     elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
    177                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
    178                                         !defined(LZ4_FORCE_SW_BITCOUNT)
    179         return (unsigned)__builtin_clz(val) >> 3;
    180 #     else
    181         val >>= 8;
    182         val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |
    183               (val + 0x00FF0000)) >> 24;
    184         return (unsigned)val ^ 3;
    185 #     endif
    186     } else {
    187 #     if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)
    188         unsigned long r;
    189         _BitScanForward(&r, val);
    190         return (unsigned)(r >> 3);
    191 #     elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \
    192                             ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \
    193                                         !defined(LZ4_FORCE_SW_BITCOUNT)
    194         return (unsigned)__builtin_ctz(val) >> 3;
    195 #     else
    196         const U32 m = 0x01010101;
    197         return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;
    198 #     endif
    199     }
    200 }
    201 
    202 /** LZ4HC_countBack() :
    203  * @return : negative value, nb of common bytes before ip/match */
    204 LZ4_FORCE_INLINE
    205 int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match,
    206                     const BYTE* const iMin, const BYTE* const mMin)
    207 {
    208     int back = 0;
    209     int const min = (int)MAX(iMin - ip, mMin - match);
    210     assert(min <= 0);
    211     assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31));
    212     assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31));
    213 
    214     while ((back - min) > 3) {
    215         U32 const v = LZ4_read32(ip + back - 4) ^ LZ4_read32(match + back - 4);
    216         if (v) {
    217             return (back - (int)LZ4HC_NbCommonBytes32(v));
    218         } else back -= 4; /* 4-byte step */
    219     }
    220     /* check remainder if any */
    221     while ( (back > min)
    222          && (ip[back-1] == match[back-1]) )
    223             back--;
    224     return back;
    225 }
    226 
    227 /*===   Chain table updates   ===*/
    228 #define DELTANEXTU16(table, pos) table[(U16)(pos)]   /* faster */
    229 /* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */
    230 #define UPDATABLE(ip, op, anchor) &ip, &op, &anchor
    231 
    232 
    233 /**************************************
    234 *  Init
    235 **************************************/
    236 static void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4)
    237 {
    238     MEM_INIT(hc4->hashTable, 0, sizeof(hc4->hashTable));
    239     MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
    240 }
    241 
    242 static void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start)
    243 {
    244     size_t const bufferSize = (size_t)(hc4->end - hc4->prefixStart);
    245     size_t newStartingOffset = bufferSize + hc4->dictLimit;
    246     DEBUGLOG(5, "LZ4HC_init_internal");
    247     assert(newStartingOffset >= bufferSize);  /* check overflow */
    248     if (newStartingOffset > 1 GB) {
    249         LZ4HC_clearTables(hc4);
    250         newStartingOffset = 0;
    251     }
    252     newStartingOffset += 64 KB;
    253     hc4->nextToUpdate = (U32)newStartingOffset;
    254     hc4->prefixStart = start;
    255     hc4->end = start;
    256     hc4->dictStart = start;
    257     hc4->dictLimit = (U32)newStartingOffset;
    258     hc4->lowLimit = (U32)newStartingOffset;
    259 }
    260 
    261 
    262 /**************************************
    263 *  Encode
    264 **************************************/
    265 /* LZ4HC_encodeSequence() :
    266  * @return : 0 if ok,
    267  *           1 if buffer issue detected */
    268 LZ4_FORCE_INLINE int LZ4HC_encodeSequence (
    269     const BYTE** _ip,
    270     BYTE** _op,
    271     const BYTE** _anchor,
    272     int matchLength,
    273     int offset,
    274     limitedOutput_directive limit,
    275     BYTE* oend)
    276 {
    277 #define ip      (*_ip)
    278 #define op      (*_op)
    279 #define anchor  (*_anchor)
    280 
    281     size_t length;
    282     BYTE* const token = op++;
    283 
    284 #if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)
    285     static const BYTE* start = NULL;
    286     static U32 totalCost = 0;
    287     U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);
    288     U32 const ll = (U32)(ip - anchor);
    289     U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0;
    290     U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0;
    291     U32 const cost = 1 + llAdd + ll + 2 + mlAdd;
    292     if (start==NULL) start = anchor;  /* only works for single segment */
    293     /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */
    294     DEBUGLOG(6, "pos:%7u -- literals:%4u, match:%4i, offset:%5i, cost:%4u + %5u",
    295                 pos,
    296                 (U32)(ip - anchor), matchLength, offset,
    297                 cost, totalCost);
    298     totalCost += cost;
    299 #endif
    300 
    301     /* Encode Literal length */
    302     length = (size_t)(ip - anchor);
    303     LZ4_STATIC_ASSERT(notLimited == 0);
    304     /* Check output limit */
    305     if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {
    306         DEBUGLOG(6, "Not enough room to write %i literals (%i bytes remaining)",
    307                 (int)length, (int)(oend - op));
    308         return 1;
    309     }
    310     if (length >= RUN_MASK) {
    311         size_t len = length - RUN_MASK;
    312         *token = (RUN_MASK << ML_BITS);
    313         for(; len >= 255 ; len -= 255) *op++ = 255;
    314         *op++ = (BYTE)len;
    315     } else {
    316         *token = (BYTE)(length << ML_BITS);
    317     }
    318 
    319     /* Copy Literals */
    320     LZ4_wildCopy8(op, anchor, op + length);
    321     op += length;
    322 
    323     /* Encode Offset */
    324     assert(offset <= LZ4_DISTANCE_MAX );
    325     assert(offset > 0);
    326     LZ4_writeLE16(op, (U16)(offset)); op += 2;
    327 
    328     /* Encode MatchLength */
    329     assert(matchLength >= MINMATCH);
    330     length = (size_t)matchLength - MINMATCH;
    331     if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {
    332         DEBUGLOG(6, "Not enough room to write match length");
    333         return 1;   /* Check output limit */
    334     }
    335     if (length >= ML_MASK) {
    336         *token += ML_MASK;
    337         length -= ML_MASK;
    338         for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }
    339         if (length >= 255) { length -= 255; *op++ = 255; }
    340         *op++ = (BYTE)length;
    341     } else {
    342         *token += (BYTE)(length);
    343     }
    344 
    345     /* Prepare next loop */
    346     ip += matchLength;
    347     anchor = ip;
    348 
    349     return 0;
    350 
    351 #undef ip
    352 #undef op
    353 #undef anchor
    354 }
    355 
    356 
    357 typedef struct {
    358     int off;
    359     int len;
    360     int back;  /* negative value */
    361 } LZ4HC_match_t;
    362 
    363 LZ4HC_match_t LZ4HC_searchExtDict(const BYTE* ip, U32 ipIndex,
    364         const BYTE* const iLowLimit, const BYTE* const iHighLimit,
    365         const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex,
    366         int currentBestML, int nbAttempts)
    367 {
    368     size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
    369     U32 lDictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
    370     U32 matchIndex = lDictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;
    371     int offset = 0, sBack = 0;
    372     assert(lDictEndIndex <= 1 GB);
    373     if (lDictMatchIndex>0)
    374         DEBUGLOG(7, "lDictEndIndex = %zu, lDictMatchIndex = %u", lDictEndIndex, lDictMatchIndex);
    375     while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {
    376         const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + lDictMatchIndex;
    377 
    378         if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
    379             int mlt;
    380             int back = 0;
    381             const BYTE* vLimit = ip + (lDictEndIndex - lDictMatchIndex);
    382             if (vLimit > iHighLimit) vLimit = iHighLimit;
    383             mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
    384             back = (ip > iLowLimit) ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;
    385             mlt -= back;
    386             if (mlt > currentBestML) {
    387                 currentBestML = mlt;
    388                 offset = (int)(ipIndex - matchIndex);
    389                 sBack = back;
    390                 DEBUGLOG(7, "found match of length %i within extDictCtx", currentBestML);
    391         }   }
    392 
    393         {   U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, lDictMatchIndex);
    394             lDictMatchIndex -= nextOffset;
    395             matchIndex -= nextOffset;
    396     }   }
    397 
    398     {   LZ4HC_match_t md;
    399         md.len = currentBestML;
    400         md.off = offset;
    401         md.back = sBack;
    402         return md;
    403     }
    404 }
    405 
    406 typedef LZ4HC_match_t (*LZ4MID_searchIntoDict_f)(const BYTE* ip, U32 ipIndex,
    407         const BYTE* const iHighLimit,
    408         const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex);
    409 
    410 static LZ4HC_match_t LZ4MID_searchHCDict(const BYTE* ip, U32 ipIndex,
    411         const BYTE* const iHighLimit,
    412         const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex)
    413 {
    414     return LZ4HC_searchExtDict(ip,ipIndex,
    415                             ip, iHighLimit,
    416                             dictCtx, gDictEndIndex,
    417                             MINMATCH-1, 2);
    418 }
    419 
    420 static LZ4HC_match_t LZ4MID_searchExtDict(const BYTE* ip, U32 ipIndex,
    421         const BYTE* const iHighLimit,
    422         const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex)
    423 {
    424     size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
    425     const U32* const hash4Table = dictCtx->hashTable;
    426     const U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;
    427     DEBUGLOG(7, "LZ4MID_searchExtDict (ipIdx=%u)", ipIndex);
    428 
    429     /* search long match first */
    430     {   U32 l8DictMatchIndex = hash8Table[LZ4MID_hash8Ptr(ip)];
    431         U32 m8Index = l8DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;
    432         assert(lDictEndIndex <= 1 GB);
    433         if (ipIndex - m8Index <= LZ4_DISTANCE_MAX) {
    434             const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l8DictMatchIndex;
    435             const size_t safeLen = MIN(lDictEndIndex - l8DictMatchIndex, (size_t)(iHighLimit - ip));
    436             int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen);
    437             if (mlt >= MINMATCH) {
    438                 LZ4HC_match_t md;
    439                 DEBUGLOG(7, "Found long ExtDict match of len=%u", mlt);
    440                 md.len = mlt;
    441                 md.off = (int)(ipIndex - m8Index);
    442                 md.back = 0;
    443                 return md;
    444             }
    445         }
    446     }
    447 
    448     /* search for short match second */
    449     {   U32 l4DictMatchIndex = hash4Table[LZ4MID_hash4Ptr(ip)];
    450         U32 m4Index = l4DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;
    451         if (ipIndex - m4Index <= LZ4_DISTANCE_MAX) {
    452             const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l4DictMatchIndex;
    453             const size_t safeLen = MIN(lDictEndIndex - l4DictMatchIndex, (size_t)(iHighLimit - ip));
    454             int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen);
    455             if (mlt >= MINMATCH) {
    456                 LZ4HC_match_t md;
    457                 DEBUGLOG(7, "Found short ExtDict match of len=%u", mlt);
    458                 md.len = mlt;
    459                 md.off = (int)(ipIndex - m4Index);
    460                 md.back = 0;
    461                 return md;
    462             }
    463         }
    464     }
    465 
    466     /* nothing found */
    467     {   LZ4HC_match_t const md = {0, 0, 0 };
    468         return md;
    469     }
    470 }
    471 
    472 /**************************************
    473 *  Mid Compression (level 2)
    474 **************************************/
    475 
    476 LZ4_FORCE_INLINE void
    477 LZ4MID_addPosition(U32* hTable, U32 hValue, U32 index)
    478 {
    479     hTable[hValue] = index;
    480 }
    481 
    482 #define ADDPOS8(_p, _idx) LZ4MID_addPosition(hash8Table, LZ4MID_hash8Ptr(_p), _idx)
    483 #define ADDPOS4(_p, _idx) LZ4MID_addPosition(hash4Table, LZ4MID_hash4Ptr(_p), _idx)
    484 
    485 /* Fill hash tables with references into dictionary.
    486  * The resulting table is only exploitable by LZ4MID (level 2) */
    487 static void
    488 LZ4MID_fillHTable (LZ4HC_CCtx_internal* cctx, const void* dict, size_t size)
    489 {
    490     U32* const hash4Table = cctx->hashTable;
    491     U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;
    492     const BYTE* const prefixPtr = (const BYTE*)dict;
    493     U32 const prefixIdx = cctx->dictLimit;
    494     U32 const target = prefixIdx + (U32)size - LZ4MID_HASHSIZE;
    495     U32 idx = cctx->nextToUpdate;
    496     assert(dict == cctx->prefixStart);
    497     DEBUGLOG(4, "LZ4MID_fillHTable (size:%zu)", size);
    498     if (size <= LZ4MID_HASHSIZE)
    499         return;
    500 
    501     for (; idx < target; idx += 3) {
    502         ADDPOS4(prefixPtr+idx-prefixIdx, idx);
    503         ADDPOS8(prefixPtr+idx+1-prefixIdx, idx+1);
    504     }
    505 
    506     idx = (size > 32 KB + LZ4MID_HASHSIZE) ? target - 32 KB : cctx->nextToUpdate;
    507     for (; idx < target; idx += 1) {
    508         ADDPOS8(prefixPtr+idx-prefixIdx, idx);
    509     }
    510 
    511     cctx->nextToUpdate = target;
    512 }
    513 
    514 static LZ4MID_searchIntoDict_f select_searchDict_function(const LZ4HC_CCtx_internal* dictCtx)
    515 {
    516     if (dictCtx == NULL) return NULL;
    517     if (LZ4HC_getCLevelParams(dictCtx->compressionLevel).strat == lz4mid)
    518         return LZ4MID_searchExtDict;
    519     return LZ4MID_searchHCDict;
    520 }
    521 
    522 static int LZ4MID_compress (
    523     LZ4HC_CCtx_internal* const ctx,
    524     const char* const src,
    525     char* const dst,
    526     int* srcSizePtr,
    527     int const maxOutputSize,
    528     const limitedOutput_directive limit,
    529     const dictCtx_directive dict
    530     )
    531 {
    532     U32* const hash4Table = ctx->hashTable;
    533     U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;
    534     const BYTE* ip = (const BYTE*)src;
    535     const BYTE* anchor = ip;
    536     const BYTE* const iend = ip + *srcSizePtr;
    537     const BYTE* const mflimit = iend - MFLIMIT;
    538     const BYTE* const matchlimit = (iend - LASTLITERALS);
    539     const BYTE* const ilimit = (iend - LZ4MID_HASHSIZE);
    540     BYTE* op = (BYTE*)dst;
    541     BYTE* oend = op + maxOutputSize;
    542 
    543     const BYTE* const prefixPtr = ctx->prefixStart;
    544     const U32 prefixIdx = ctx->dictLimit;
    545     const U32 ilimitIdx = (U32)(ilimit - prefixPtr) + prefixIdx;
    546     const BYTE* const dictStart = ctx->dictStart;
    547     const U32 dictIdx = ctx->lowLimit;
    548     const U32 gDictEndIndex = ctx->lowLimit;
    549     const LZ4MID_searchIntoDict_f searchIntoDict = (dict == usingDictCtxHc) ? select_searchDict_function(ctx->dictCtx) : NULL;
    550     unsigned matchLength;
    551     unsigned matchDistance;
    552 
    553     /* input sanitization */
    554     DEBUGLOG(5, "LZ4MID_compress (%i bytes)", *srcSizePtr);
    555     if (dict == usingDictCtxHc) DEBUGLOG(5, "usingDictCtxHc");
    556     assert(*srcSizePtr >= 0);
    557     if (*srcSizePtr) assert(src != NULL);
    558     if (maxOutputSize) assert(dst != NULL);
    559     if (*srcSizePtr < 0) return 0;  /* invalid */
    560     if (maxOutputSize < 0) return 0; /* invalid */
    561     if (*srcSizePtr > LZ4_MAX_INPUT_SIZE) {
    562         /* forbidden: no input is allowed to be that large */
    563         return 0;
    564     }
    565     if (limit == fillOutput) oend -= LASTLITERALS;  /* Hack for support LZ4 format restriction */
    566     if (*srcSizePtr < LZ4_minLength)
    567         goto _lz4mid_last_literals;  /* Input too small, no compression (all literals) */
    568 
    569     /* main loop */
    570     while (ip <= mflimit) {
    571         const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;
    572         /* search long match */
    573         {   U32 const h8 = LZ4MID_hash8Ptr(ip);
    574             U32 const pos8 = hash8Table[h8];
    575             assert(h8 < LZ4MID_HASHTABLESIZE);
    576             assert(pos8 < ipIndex);
    577             LZ4MID_addPosition(hash8Table, h8, ipIndex);
    578             if (ipIndex - pos8 <= LZ4_DISTANCE_MAX) {
    579                 /* match candidate found */
    580                 if (pos8 >= prefixIdx) {
    581                     const BYTE* const matchPtr = prefixPtr + pos8 - prefixIdx;
    582                     assert(matchPtr < ip);
    583                     matchLength = LZ4_count(ip, matchPtr, matchlimit);
    584                     if (matchLength >= MINMATCH) {
    585                         DEBUGLOG(7, "found long match at pos %u (len=%u)", pos8, matchLength);
    586                         matchDistance = ipIndex - pos8;
    587                         goto _lz4mid_encode_sequence;
    588                     }
    589                 } else {
    590                     if (pos8 >= dictIdx) {
    591                         /* extDict match candidate */
    592                         const BYTE* const matchPtr = dictStart + (pos8 - dictIdx);
    593                         const size_t safeLen = MIN(prefixIdx - pos8, (size_t)(matchlimit - ip));
    594                         matchLength = LZ4_count(ip, matchPtr, ip + safeLen);
    595                         if (matchLength >= MINMATCH) {
    596                             DEBUGLOG(7, "found long match at ExtDict pos %u (len=%u)", pos8, matchLength);
    597                             matchDistance = ipIndex - pos8;
    598                             goto _lz4mid_encode_sequence;
    599                         }
    600                     }
    601                 }
    602         }   }
    603         /* search short match */
    604         {   U32 const h4 = LZ4MID_hash4Ptr(ip);
    605             U32 const pos4 = hash4Table[h4];
    606             assert(h4 < LZ4MID_HASHTABLESIZE);
    607             assert(pos4 < ipIndex);
    608             LZ4MID_addPosition(hash4Table, h4, ipIndex);
    609             if (ipIndex - pos4 <= LZ4_DISTANCE_MAX) {
    610                 /* match candidate found */
    611                 if (pos4 >= prefixIdx) {
    612                 /* only search within prefix */
    613                     const BYTE* const matchPtr = prefixPtr + (pos4 - prefixIdx);
    614                     assert(matchPtr < ip);
    615                     assert(matchPtr >= prefixPtr);
    616                     matchLength = LZ4_count(ip, matchPtr, matchlimit);
    617                     if (matchLength >= MINMATCH) {
    618                         /* short match found, let's just check ip+1 for longer */
    619                         U32 const h8 = LZ4MID_hash8Ptr(ip+1);
    620                         U32 const pos8 = hash8Table[h8];
    621                         U32 const m2Distance = ipIndex + 1 - pos8;
    622                         matchDistance = ipIndex - pos4;
    623                         if ( m2Distance <= LZ4_DISTANCE_MAX
    624                         && pos8 >= prefixIdx /* only search within prefix */
    625                         && likely(ip < mflimit)
    626                         ) {
    627                             const BYTE* const m2Ptr = prefixPtr + (pos8 - prefixIdx);
    628                             unsigned ml2 = LZ4_count(ip+1, m2Ptr, matchlimit);
    629                             if (ml2 > matchLength) {
    630                                 LZ4MID_addPosition(hash8Table, h8, ipIndex+1);
    631                                 ip++;
    632                                 matchLength = ml2;
    633                                 matchDistance = m2Distance;
    634                         }   }
    635                         goto _lz4mid_encode_sequence;
    636                     }
    637                 } else {
    638                     if (pos4 >= dictIdx) {
    639                         /* extDict match candidate */
    640                         const BYTE* const matchPtr = dictStart + (pos4 - dictIdx);
    641                         const size_t safeLen = MIN(prefixIdx - pos4, (size_t)(matchlimit - ip));
    642                         matchLength = LZ4_count(ip, matchPtr, ip + safeLen);
    643                         if (matchLength >= MINMATCH) {
    644                             DEBUGLOG(7, "found match at ExtDict pos %u (len=%u)", pos4, matchLength);
    645                             matchDistance = ipIndex - pos4;
    646                             goto _lz4mid_encode_sequence;
    647                         }
    648                     }
    649                 }
    650         }   }
    651         /* no match found in prefix */
    652         if ( (dict == usingDictCtxHc)
    653           && (ipIndex - gDictEndIndex < LZ4_DISTANCE_MAX - 8) ) {
    654             /* search a match into external dictionary */
    655             LZ4HC_match_t dMatch = searchIntoDict(ip, ipIndex,
    656                     matchlimit,
    657                     ctx->dictCtx, gDictEndIndex);
    658             if (dMatch.len >= MINMATCH) {
    659                 DEBUGLOG(7, "found Dictionary match (offset=%i)", dMatch.off);
    660                 assert(dMatch.back == 0);
    661                 matchLength = (unsigned)dMatch.len;
    662                 matchDistance = (unsigned)dMatch.off;
    663                 goto _lz4mid_encode_sequence;
    664             }
    665         }
    666         /* no match found */
    667         ip += 1 + ((ip-anchor) >> 9);  /* skip faster over incompressible data */
    668         continue;
    669 
    670 _lz4mid_encode_sequence:
    671         /* catch back */
    672         while (((ip > anchor) & ((U32)(ip-prefixPtr) > matchDistance)) && (unlikely(ip[-1] == ip[-(int)matchDistance-1]))) {
    673             ip--;  matchLength++;
    674         };
    675 
    676         /* fill table with beginning of match */
    677         ADDPOS8(ip+1, ipIndex+1);
    678         ADDPOS8(ip+2, ipIndex+2);
    679         ADDPOS4(ip+1, ipIndex+1);
    680 
    681         /* encode */
    682         {   BYTE* const saved_op = op;
    683             /* LZ4HC_encodeSequence always updates @op; on success, it updates @ip and @anchor */
    684             if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
    685                     (int)matchLength, (int)matchDistance,
    686                     limit, oend) ) {
    687                 op = saved_op;  /* restore @op value before failed LZ4HC_encodeSequence */
    688                 goto _lz4mid_dest_overflow;
    689             }
    690         }
    691 
    692         /* fill table with end of match */
    693         {   U32 endMatchIdx = (U32)(ip-prefixPtr) + prefixIdx;
    694             U32 pos_m2 = endMatchIdx - 2;
    695             if (pos_m2 < ilimitIdx) {
    696                 if (likely(ip - prefixPtr > 5)) {
    697                     ADDPOS8(ip-5, endMatchIdx - 5);
    698                 }
    699                 ADDPOS8(ip-3, endMatchIdx - 3);
    700                 ADDPOS8(ip-2, endMatchIdx - 2);
    701                 ADDPOS4(ip-2, endMatchIdx - 2);
    702                 ADDPOS4(ip-1, endMatchIdx - 1);
    703             }
    704         }
    705     }
    706 
    707 _lz4mid_last_literals:
    708     /* Encode Last Literals */
    709     {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */
    710         size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
    711         size_t const totalSize = 1 + llAdd + lastRunSize;
    712         if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */
    713         if (limit && (op + totalSize > oend)) {
    714             if (limit == limitedOutput) return 0;  /* not enough space in @dst */
    715             /* adapt lastRunSize to fill 'dest' */
    716             lastRunSize  = (size_t)(oend - op) - 1 /*token*/;
    717             llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
    718             lastRunSize -= llAdd;
    719         }
    720         DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
    721         ip = anchor + lastRunSize;  /* can be != iend if limit==fillOutput */
    722 
    723         if (lastRunSize >= RUN_MASK) {
    724             size_t accumulator = lastRunSize - RUN_MASK;
    725             *op++ = (RUN_MASK << ML_BITS);
    726             for(; accumulator >= 255 ; accumulator -= 255)
    727                 *op++ = 255;
    728             *op++ = (BYTE) accumulator;
    729         } else {
    730             *op++ = (BYTE)(lastRunSize << ML_BITS);
    731         }
    732         assert(lastRunSize <= (size_t)(oend - op));
    733         LZ4_memcpy(op, anchor, lastRunSize);
    734         op += lastRunSize;
    735     }
    736 
    737     /* End */
    738     DEBUGLOG(5, "compressed %i bytes into %i bytes", *srcSizePtr, (int)((char*)op - dst));
    739     assert(ip >= (const BYTE*)src);
    740     assert(ip <= iend);
    741     *srcSizePtr = (int)(ip - (const BYTE*)src);
    742     assert((char*)op >= dst);
    743     assert(op <= oend);
    744     assert((char*)op - dst < INT_MAX);
    745     return (int)((char*)op - dst);
    746 
    747 _lz4mid_dest_overflow:
    748     if (limit == fillOutput) {
    749         /* Assumption : @ip, @anchor, @optr and @matchLength must be set correctly */
    750         size_t const ll = (size_t)(ip - anchor);
    751         size_t const ll_addbytes = (ll + 240) / 255;
    752         size_t const ll_totalCost = 1 + ll_addbytes + ll;
    753         BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
    754         DEBUGLOG(6, "Last sequence is overflowing : %u literals, %u remaining space",
    755                 (unsigned)ll, (unsigned)(oend-op));
    756         if (op + ll_totalCost <= maxLitPos) {
    757             /* ll validated; now adjust match length */
    758             size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));
    759             size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);
    760             assert(maxMlSize < INT_MAX);
    761             if ((size_t)matchLength > maxMlSize) matchLength= (unsigned)maxMlSize;
    762             if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + matchLength >= MFLIMIT) {
    763             DEBUGLOG(6, "Let's encode a last sequence (ll=%u, ml=%u)", (unsigned)ll, matchLength);
    764                 LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
    765                         (int)matchLength, (int)matchDistance,
    766                         notLimited, oend);
    767         }   }
    768         DEBUGLOG(6, "Let's finish with a run of literals (%u bytes left)", (unsigned)(oend-op));
    769         goto _lz4mid_last_literals;
    770     }
    771     /* compression failed */
    772     return 0;
    773 }
    774 
    775 
    776 /**************************************
    777 *  HC Compression - Search
    778 **************************************/
    779 
    780 /* Update chains up to ip (excluded) */
    781 LZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
    782 {
    783     U16* const chainTable = hc4->chainTable;
    784     U32* const hashTable  = hc4->hashTable;
    785     const BYTE* const prefixPtr = hc4->prefixStart;
    786     U32 const prefixIdx = hc4->dictLimit;
    787     U32 const target = (U32)(ip - prefixPtr) + prefixIdx;
    788     U32 idx = hc4->nextToUpdate;
    789     assert(ip >= prefixPtr);
    790     assert(target >= prefixIdx);
    791 
    792     while (idx < target) {
    793         U32 const h = LZ4HC_hashPtr(prefixPtr+idx-prefixIdx);
    794         size_t delta = idx - hashTable[h];
    795         if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX;
    796         DELTANEXTU16(chainTable, idx) = (U16)delta;
    797         hashTable[h] = idx;
    798         idx++;
    799     }
    800 
    801     hc4->nextToUpdate = target;
    802 }
    803 
    804 #if defined(_MSC_VER)
    805 #  define LZ4HC_rotl32(x,r) _rotl(x,r)
    806 #else
    807 #  define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r)))
    808 #endif
    809 
    810 
    811 static U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern)
    812 {
    813     size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3;
    814     if (bitsToRotate == 0) return pattern;
    815     return LZ4HC_rotl32(pattern, (int)bitsToRotate);
    816 }
    817 
    818 /* LZ4HC_countPattern() :
    819  * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */
    820 static unsigned
    821 LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32)
    822 {
    823     const BYTE* const iStart = ip;
    824     reg_t const pattern = (sizeof(pattern)==8) ?
    825         (reg_t)pattern32 + (((reg_t)pattern32) << (sizeof(pattern)*4)) : pattern32;
    826 
    827     while (likely(ip < iEnd-(sizeof(pattern)-1))) {
    828         reg_t const diff = LZ4_read_ARCH(ip) ^ pattern;
    829         if (!diff) { ip+=sizeof(pattern); continue; }
    830         ip += LZ4_NbCommonBytes(diff);
    831         return (unsigned)(ip - iStart);
    832     }
    833 
    834     if (LZ4_isLittleEndian()) {
    835         reg_t patternByte = pattern;
    836         while ((ip<iEnd) && (*ip == (BYTE)patternByte)) {
    837             ip++; patternByte >>= 8;
    838         }
    839     } else {  /* big endian */
    840         U32 bitOffset = (sizeof(pattern)*8) - 8;
    841         while (ip < iEnd) {
    842             BYTE const byte = (BYTE)(pattern >> bitOffset);
    843             if (*ip != byte) break;
    844             ip ++; bitOffset -= 8;
    845     }   }
    846 
    847     return (unsigned)(ip - iStart);
    848 }
    849 
    850 /* LZ4HC_reverseCountPattern() :
    851  * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!)
    852  * read using natural platform endianness */
    853 static unsigned
    854 LZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern)
    855 {
    856     const BYTE* const iStart = ip;
    857 
    858     while (likely(ip >= iLow+4)) {
    859         if (LZ4_read32(ip-4) != pattern) break;
    860         ip -= 4;
    861     }
    862     {   const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianness */
    863         while (likely(ip>iLow)) {
    864             if (ip[-1] != *bytePtr) break;
    865             ip--; bytePtr--;
    866     }   }
    867     return (unsigned)(iStart - ip);
    868 }
    869 
    870 /* LZ4HC_protectDictEnd() :
    871  * Checks if the match is in the last 3 bytes of the dictionary, so reading the
    872  * 4 byte MINMATCH would overflow.
    873  * @returns true if the match index is okay.
    874  */
    875 static int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex)
    876 {
    877     return ((U32)((dictLimit - 1) - matchIndex) >= 3);
    878 }
    879 
    880 typedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e;
    881 typedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e;
    882 
    883 
    884 LZ4_FORCE_INLINE LZ4HC_match_t
    885 LZ4HC_InsertAndGetWiderMatch (
    886         LZ4HC_CCtx_internal* const hc4,
    887         const BYTE* const ip,
    888         const BYTE* const iLowLimit, const BYTE* const iHighLimit,
    889         int longest,
    890         const int maxNbAttempts,
    891         const int patternAnalysis, const int chainSwap,
    892         const dictCtx_directive dict,
    893         const HCfavor_e favorDecSpeed)
    894 {
    895     U16* const chainTable = hc4->chainTable;
    896     U32* const hashTable = hc4->hashTable;
    897     const LZ4HC_CCtx_internal* const dictCtx = hc4->dictCtx;
    898     const BYTE* const prefixPtr = hc4->prefixStart;
    899     const U32 prefixIdx = hc4->dictLimit;
    900     const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;
    901     const int withinStartDistance = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex);
    902     const U32 lowestMatchIndex = (withinStartDistance) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX;
    903     const BYTE* const dictStart = hc4->dictStart;
    904     const U32 dictIdx = hc4->lowLimit;
    905     const BYTE* const dictEnd = dictStart + prefixIdx - dictIdx;
    906     int const lookBackLength = (int)(ip-iLowLimit);
    907     int nbAttempts = maxNbAttempts;
    908     U32 matchChainPos = 0;
    909     U32 const pattern = LZ4_read32(ip);
    910     U32 matchIndex;
    911     repeat_state_e repeat = rep_untested;
    912     size_t srcPatternLength = 0;
    913     int offset = 0, sBack = 0;
    914 
    915     DEBUGLOG(7, "LZ4HC_InsertAndGetWiderMatch");
    916     /* First Match */
    917     LZ4HC_Insert(hc4, ip);  /* insert all prior positions up to ip (excluded) */
    918     matchIndex = hashTable[LZ4HC_hashPtr(ip)];
    919     DEBUGLOG(7, "First candidate match for pos %u found at index %u / %u (lowestMatchIndex)",
    920                 ipIndex, matchIndex, lowestMatchIndex);
    921 
    922     while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) {
    923         int matchLength=0;
    924         nbAttempts--;
    925         assert(matchIndex < ipIndex);
    926         if (favorDecSpeed && (ipIndex - matchIndex < 8)) {
    927             /* do nothing:
    928              * favorDecSpeed intentionally skips matches with offset < 8 */
    929         } else if (matchIndex >= prefixIdx) {   /* within current Prefix */
    930             const BYTE* const matchPtr = prefixPtr + (matchIndex - prefixIdx);
    931             assert(matchPtr < ip);
    932             assert(longest >= 1);
    933             if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) {
    934                 if (LZ4_read32(matchPtr) == pattern) {
    935                     int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, prefixPtr) : 0;
    936                     matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
    937                     matchLength -= back;
    938                     if (matchLength > longest) {
    939                         longest = matchLength;
    940                         offset = (int)(ipIndex - matchIndex);
    941                         sBack = back;
    942                         DEBUGLOG(7, "Found match of len=%i within prefix, offset=%i, back=%i", longest, offset, -back);
    943             }   }   }
    944         } else {   /* lowestMatchIndex <= matchIndex < dictLimit : within Ext Dict */
    945             const BYTE* const matchPtr = dictStart + (matchIndex - dictIdx);
    946             assert(matchIndex >= dictIdx);
    947             if ( likely(matchIndex <= prefixIdx - 4)
    948               && (LZ4_read32(matchPtr) == pattern) ) {
    949                 int back = 0;
    950                 const BYTE* vLimit = ip + (prefixIdx - matchIndex);
    951                 if (vLimit > iHighLimit) vLimit = iHighLimit;
    952                 matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
    953                 if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))
    954                     matchLength += LZ4_count(ip+matchLength, prefixPtr, iHighLimit);
    955                 back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0;
    956                 matchLength -= back;
    957                 if (matchLength > longest) {
    958                     longest = matchLength;
    959                     offset = (int)(ipIndex - matchIndex);
    960                     sBack = back;
    961                     DEBUGLOG(7, "Found match of len=%i within dict, offset=%i, back=%i", longest, offset, -back);
    962         }   }   }
    963 
    964         if (chainSwap && matchLength==longest) {   /* better match => select a better chain */
    965             assert(lookBackLength==0);   /* search forward only */
    966             if (matchIndex + (U32)longest <= ipIndex) {
    967                 int const kTrigger = 4;
    968                 U32 distanceToNextMatch = 1;
    969                 int const end = longest - MINMATCH + 1;
    970                 int step = 1;
    971                 int accel = 1 << kTrigger;
    972                 int pos;
    973                 for (pos = 0; pos < end; pos += step) {
    974                     U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos);
    975                     step = (accel++ >> kTrigger);
    976                     if (candidateDist > distanceToNextMatch) {
    977                         distanceToNextMatch = candidateDist;
    978                         matchChainPos = (U32)pos;
    979                         accel = 1 << kTrigger;
    980                 }   }
    981                 if (distanceToNextMatch > 1) {
    982                     if (distanceToNextMatch > matchIndex) break;   /* avoid overflow */
    983                     matchIndex -= distanceToNextMatch;
    984                     continue;
    985         }   }   }
    986 
    987         {   U32 const distNextMatch = DELTANEXTU16(chainTable, matchIndex);
    988             if (patternAnalysis && distNextMatch==1 && matchChainPos==0) {
    989                 U32 const matchCandidateIdx = matchIndex-1;
    990                 /* may be a repeated pattern */
    991                 if (repeat == rep_untested) {
    992                     if ( ((pattern & 0xFFFF) == (pattern >> 16))
    993                       &  ((pattern & 0xFF)   == (pattern >> 24)) ) {
    994                         DEBUGLOG(7, "Repeat pattern detected, char %02X", pattern >> 24);
    995                         repeat = rep_confirmed;
    996                         srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern);
    997                     } else {
    998                         repeat = rep_not;
    999                 }   }
   1000                 if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex)
   1001                   && LZ4HC_protectDictEnd(prefixIdx, matchCandidateIdx) ) {
   1002                     const int extDict = matchCandidateIdx < prefixIdx;
   1003                     const BYTE* const matchPtr = extDict ? dictStart + (matchCandidateIdx - dictIdx) : prefixPtr + (matchCandidateIdx - prefixIdx);
   1004                     if (LZ4_read32(matchPtr) == pattern) {  /* good candidate */
   1005                         const BYTE* const iLimit = extDict ? dictEnd : iHighLimit;
   1006                         size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern);
   1007                         if (extDict && matchPtr + forwardPatternLength == iLimit) {
   1008                             U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern);
   1009                             forwardPatternLength += LZ4HC_countPattern(prefixPtr, iHighLimit, rotatedPattern);
   1010                         }
   1011                         {   const BYTE* const lowestMatchPtr = extDict ? dictStart : prefixPtr;
   1012                             size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern);
   1013                             size_t currentSegmentLength;
   1014                             if (!extDict
   1015                               && matchPtr - backLength == prefixPtr
   1016                               && dictIdx < prefixIdx) {
   1017                                 U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern);
   1018                                 backLength += LZ4HC_reverseCountPattern(dictEnd, dictStart, rotatedPattern);
   1019                             }
   1020                             /* Limit backLength not go further than lowestMatchIndex */
   1021                             backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex);
   1022                             assert(matchCandidateIdx - backLength >= lowestMatchIndex);
   1023                             currentSegmentLength = backLength + forwardPatternLength;
   1024                             /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */
   1025                             if ( (currentSegmentLength >= srcPatternLength)   /* current pattern segment large enough to contain full srcPatternLength */
   1026                               && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */
   1027                                 U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength;  /* best position, full pattern, might be followed by more match */
   1028                                 if (LZ4HC_protectDictEnd(prefixIdx, newMatchIndex))
   1029                                     matchIndex = newMatchIndex;
   1030                                 else {
   1031                                     /* Can only happen if started in the prefix */
   1032                                     assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);
   1033                                     matchIndex = prefixIdx;
   1034                                 }
   1035                             } else {
   1036                                 U32 const newMatchIndex = matchCandidateIdx - (U32)backLength;   /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */
   1037                                 if (!LZ4HC_protectDictEnd(prefixIdx, newMatchIndex)) {
   1038                                     assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);
   1039                                     matchIndex = prefixIdx;
   1040                                 } else {
   1041                                     matchIndex = newMatchIndex;
   1042                                     if (lookBackLength==0) {  /* no back possible */
   1043                                         size_t const maxML = MIN(currentSegmentLength, srcPatternLength);
   1044                                         if ((size_t)longest < maxML) {
   1045                                             assert(prefixPtr - prefixIdx + matchIndex != ip);
   1046                                             if ((size_t)(ip - prefixPtr) + prefixIdx - matchIndex > LZ4_DISTANCE_MAX) break;
   1047                                             assert(maxML < 2 GB);
   1048                                             longest = (int)maxML;
   1049                                             offset = (int)(ipIndex - matchIndex);
   1050                                             assert(sBack == 0);
   1051                                             DEBUGLOG(7, "Found repeat pattern match of len=%i, offset=%i", longest, offset);
   1052                                         }
   1053                                         {   U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex);
   1054                                             if (distToNextPattern > matchIndex) break;  /* avoid overflow */
   1055                                             matchIndex -= distToNextPattern;
   1056                         }   }   }   }   }
   1057                         continue;
   1058                 }   }
   1059         }   }   /* PA optimization */
   1060 
   1061         /* follow current chain */
   1062         matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos);
   1063 
   1064     }  /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */
   1065 
   1066     if ( dict == usingDictCtxHc
   1067       && nbAttempts > 0
   1068       && withinStartDistance) {
   1069         size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;
   1070         U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];
   1071         assert(dictEndOffset <= 1 GB);
   1072         matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset;
   1073         if (dictMatchIndex>0) DEBUGLOG(7, "dictEndOffset = %zu, dictMatchIndex = %u => relative matchIndex = %i", dictEndOffset, dictMatchIndex, (int)dictMatchIndex - (int)dictEndOffset);
   1074         while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {
   1075             const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + dictMatchIndex;
   1076 
   1077             if (LZ4_read32(matchPtr) == pattern) {
   1078                 int mlt;
   1079                 int back = 0;
   1080                 const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex);
   1081                 if (vLimit > iHighLimit) vLimit = iHighLimit;
   1082                 mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
   1083                 back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;
   1084                 mlt -= back;
   1085                 if (mlt > longest) {
   1086                     longest = mlt;
   1087                     offset = (int)(ipIndex - matchIndex);
   1088                     sBack = back;
   1089                     DEBUGLOG(7, "found match of length %i within extDictCtx", longest);
   1090             }   }
   1091 
   1092             {   U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex);
   1093                 dictMatchIndex -= nextOffset;
   1094                 matchIndex -= nextOffset;
   1095     }   }   }
   1096 
   1097     {   LZ4HC_match_t md;
   1098         assert(longest >= 0);
   1099         md.len = longest;
   1100         md.off = offset;
   1101         md.back = sBack;
   1102         return md;
   1103     }
   1104 }
   1105 
   1106 LZ4_FORCE_INLINE LZ4HC_match_t
   1107 LZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4,   /* Index table will be updated */
   1108                        const BYTE* const ip, const BYTE* const iLimit,
   1109                        const int maxNbAttempts,
   1110                        const int patternAnalysis,
   1111                        const dictCtx_directive dict)
   1112 {
   1113     DEBUGLOG(7, "LZ4HC_InsertAndFindBestMatch");
   1114     /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
   1115      * but this won't be the case here, as we define iLowLimit==ip,
   1116      * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
   1117     return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio);
   1118 }
   1119 
   1120 
   1121 LZ4_FORCE_INLINE int LZ4HC_compress_hashChain (
   1122     LZ4HC_CCtx_internal* const ctx,
   1123     const char* const source,
   1124     char* const dest,
   1125     int* srcSizePtr,
   1126     int const maxOutputSize,
   1127     int maxNbAttempts,
   1128     const limitedOutput_directive limit,
   1129     const dictCtx_directive dict
   1130     )
   1131 {
   1132     const int inputSize = *srcSizePtr;
   1133     const int patternAnalysis = (maxNbAttempts > 128);   /* levels 9+ */
   1134 
   1135     const BYTE* ip = (const BYTE*) source;
   1136     const BYTE* anchor = ip;
   1137     const BYTE* const iend = ip + inputSize;
   1138     const BYTE* const mflimit = iend - MFLIMIT;
   1139     const BYTE* const matchlimit = (iend - LASTLITERALS);
   1140 
   1141     BYTE* optr = (BYTE*) dest;
   1142     BYTE* op = (BYTE*) dest;
   1143     BYTE* oend = op + maxOutputSize;
   1144 
   1145     const BYTE* start0;
   1146     const BYTE* start2 = NULL;
   1147     const BYTE* start3 = NULL;
   1148     LZ4HC_match_t m0, m1, m2, m3;
   1149     const LZ4HC_match_t nomatch = {0, 0, 0};
   1150 
   1151     /* init */
   1152     DEBUGLOG(5, "LZ4HC_compress_hashChain (dict?=>%i)", dict);
   1153     *srcSizePtr = 0;
   1154     if (limit == fillOutput) oend -= LASTLITERALS;                  /* Hack for support LZ4 format restriction */
   1155     if (inputSize < LZ4_minLength) goto _last_literals;             /* Input too small, no compression (all literals) */
   1156 
   1157     /* Main Loop */
   1158     while (ip <= mflimit) {
   1159         m1 = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, maxNbAttempts, patternAnalysis, dict);
   1160         if (m1.len<MINMATCH) { ip++; continue; }
   1161 
   1162         /* saved, in case we would skip too much */
   1163         start0 = ip; m0 = m1;
   1164 
   1165 _Search2:
   1166         DEBUGLOG(7, "_Search2 (currently found match of size %i)", m1.len);
   1167         if (ip+m1.len <= mflimit) {
   1168             start2 = ip + m1.len - 2;
   1169             m2 = LZ4HC_InsertAndGetWiderMatch(ctx,
   1170                             start2, ip + 0, matchlimit, m1.len,
   1171                             maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);
   1172             start2 += m2.back;
   1173         } else {
   1174             m2 = nomatch;  /* do not search further */
   1175         }
   1176 
   1177         if (m2.len <= m1.len) { /* No better match => encode ML1 immediately */
   1178             optr = op;
   1179             if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
   1180                     m1.len, m1.off,
   1181                     limit, oend) )
   1182                 goto _dest_overflow;
   1183             continue;
   1184         }
   1185 
   1186         if (start0 < ip) {   /* first match was skipped at least once */
   1187             if (start2 < ip + m0.len) {  /* squeezing ML1 between ML0(original ML1) and ML2 */
   1188                 ip = start0; m1 = m0;  /* restore initial Match1 */
   1189         }   }
   1190 
   1191         /* Here, start0==ip */
   1192         if ((start2 - ip) < 3) {  /* First Match too small : removed */
   1193             ip = start2;
   1194             m1 = m2;
   1195             goto _Search2;
   1196         }
   1197 
   1198 _Search3:
   1199         if ((start2 - ip) < OPTIMAL_ML) {
   1200             int correction;
   1201             int new_ml = m1.len;
   1202             if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
   1203             if (ip+new_ml > start2 + m2.len - MINMATCH)
   1204                 new_ml = (int)(start2 - ip) + m2.len - MINMATCH;
   1205             correction = new_ml - (int)(start2 - ip);
   1206             if (correction > 0) {
   1207                 start2 += correction;
   1208                 m2.len -= correction;
   1209             }
   1210         }
   1211 
   1212         if (start2 + m2.len <= mflimit) {
   1213             start3 = start2 + m2.len - 3;
   1214             m3 = LZ4HC_InsertAndGetWiderMatch(ctx,
   1215                             start3, start2, matchlimit, m2.len,
   1216                             maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);
   1217             start3 += m3.back;
   1218         } else {
   1219             m3 = nomatch;  /* do not search further */
   1220         }
   1221 
   1222         if (m3.len <= m2.len) {  /* No better match => encode ML1 and ML2 */
   1223             /* ip & ref are known; Now for ml */
   1224             if (start2 < ip+m1.len) m1.len = (int)(start2 - ip);
   1225             /* Now, encode 2 sequences */
   1226             optr = op;
   1227             if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
   1228                     m1.len, m1.off,
   1229                     limit, oend) )
   1230                 goto _dest_overflow;
   1231             ip = start2;
   1232             optr = op;
   1233             if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
   1234                     m2.len, m2.off,
   1235                     limit, oend) ) {
   1236                 m1 = m2;
   1237                 goto _dest_overflow;
   1238             }
   1239             continue;
   1240         }
   1241 
   1242         if (start3 < ip+m1.len+3) {  /* Not enough space for match 2 : remove it */
   1243             if (start3 >= (ip+m1.len)) {  /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
   1244                 if (start2 < ip+m1.len) {
   1245                     int correction = (int)(ip+m1.len - start2);
   1246                     start2 += correction;
   1247                     m2.len -= correction;
   1248                     if (m2.len < MINMATCH) {
   1249                         start2 = start3;
   1250                         m2 = m3;
   1251                     }
   1252                 }
   1253 
   1254                 optr = op;
   1255                 if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
   1256                         m1.len, m1.off,
   1257                         limit, oend) )
   1258                     goto _dest_overflow;
   1259                 ip  = start3;
   1260                 m1 = m3;
   1261 
   1262                 start0 = start2;
   1263                 m0 = m2;
   1264                 goto _Search2;
   1265             }
   1266 
   1267             start2 = start3;
   1268             m2 = m3;
   1269             goto _Search3;
   1270         }
   1271 
   1272         /*
   1273         * OK, now we have 3 ascending matches;
   1274         * let's write the first one ML1.
   1275         * ip & ref are known; Now decide ml.
   1276         */
   1277         if (start2 < ip+m1.len) {
   1278             if ((start2 - ip) < OPTIMAL_ML) {
   1279                 int correction;
   1280                 if (m1.len > OPTIMAL_ML) m1.len = OPTIMAL_ML;
   1281                 if (ip + m1.len > start2 + m2.len - MINMATCH)
   1282                     m1.len = (int)(start2 - ip) + m2.len - MINMATCH;
   1283                 correction = m1.len - (int)(start2 - ip);
   1284                 if (correction > 0) {
   1285                     start2 += correction;
   1286                     m2.len -= correction;
   1287                 }
   1288             } else {
   1289                 m1.len = (int)(start2 - ip);
   1290             }
   1291         }
   1292         optr = op;
   1293         if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),
   1294                 m1.len, m1.off,
   1295                 limit, oend) )
   1296             goto _dest_overflow;
   1297 
   1298         /* ML2 becomes ML1 */
   1299         ip = start2; m1 = m2;
   1300 
   1301         /* ML3 becomes ML2 */
   1302         start2 = start3; m2 = m3;
   1303 
   1304         /* let's find a new ML3 */
   1305         goto _Search3;
   1306     }
   1307 
   1308 _last_literals:
   1309     /* Encode Last Literals */
   1310     {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */
   1311         size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
   1312         size_t const totalSize = 1 + llAdd + lastRunSize;
   1313         if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */
   1314         if (limit && (op + totalSize > oend)) {
   1315             if (limit == limitedOutput) return 0;
   1316             /* adapt lastRunSize to fill 'dest' */
   1317             lastRunSize  = (size_t)(oend - op) - 1 /*token*/;
   1318             llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
   1319             lastRunSize -= llAdd;
   1320         }
   1321         DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
   1322         ip = anchor + lastRunSize;  /* can be != iend if limit==fillOutput */
   1323 
   1324         if (lastRunSize >= RUN_MASK) {
   1325             size_t accumulator = lastRunSize - RUN_MASK;
   1326             *op++ = (RUN_MASK << ML_BITS);
   1327             for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;
   1328             *op++ = (BYTE) accumulator;
   1329         } else {
   1330             *op++ = (BYTE)(lastRunSize << ML_BITS);
   1331         }
   1332         LZ4_memcpy(op, anchor, lastRunSize);
   1333         op += lastRunSize;
   1334     }
   1335 
   1336     /* End */
   1337     *srcSizePtr = (int) (((const char*)ip) - source);
   1338     return (int) (((char*)op)-dest);
   1339 
   1340 _dest_overflow:
   1341     if (limit == fillOutput) {
   1342         /* Assumption : @ip, @anchor, @optr and @m1 must be set correctly */
   1343         size_t const ll = (size_t)(ip - anchor);
   1344         size_t const ll_addbytes = (ll + 240) / 255;
   1345         size_t const ll_totalCost = 1 + ll_addbytes + ll;
   1346         BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
   1347         DEBUGLOG(6, "Last sequence overflowing");
   1348         op = optr;  /* restore correct out pointer */
   1349         if (op + ll_totalCost <= maxLitPos) {
   1350             /* ll validated; now adjust match length */
   1351             size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));
   1352             size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);
   1353             assert(maxMlSize < INT_MAX); assert(m1.len >= 0);
   1354             if ((size_t)m1.len > maxMlSize) m1.len = (int)maxMlSize;
   1355             if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + m1.len >= MFLIMIT) {
   1356                 LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, notLimited, oend);
   1357         }   }
   1358         goto _last_literals;
   1359     }
   1360     /* compression failed */
   1361     return 0;
   1362 }
   1363 
   1364 
   1365 static int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx,
   1366     const char* const source, char* dst,
   1367     int* srcSizePtr, int dstCapacity,
   1368     int const nbSearches, size_t sufficient_len,
   1369     const limitedOutput_directive limit, int const fullUpdate,
   1370     const dictCtx_directive dict,
   1371     const HCfavor_e favorDecSpeed);
   1372 
   1373 LZ4_FORCE_INLINE int
   1374 LZ4HC_compress_generic_internal (
   1375             LZ4HC_CCtx_internal* const ctx,
   1376             const char* const src,
   1377             char* const dst,
   1378             int* const srcSizePtr,
   1379             int const dstCapacity,
   1380             int cLevel,
   1381             const limitedOutput_directive limit,
   1382             const dictCtx_directive dict
   1383             )
   1384 {
   1385     DEBUGLOG(5, "LZ4HC_compress_generic_internal(src=%p, srcSize=%d)",
   1386                 src, *srcSizePtr);
   1387 
   1388     if (limit == fillOutput && dstCapacity < 1) return 0;   /* Impossible to store anything */
   1389     if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0;  /* Unsupported input size (too large or negative) */
   1390 
   1391     ctx->end += *srcSizePtr;
   1392     {   cParams_t const cParam = LZ4HC_getCLevelParams(cLevel);
   1393         HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio;
   1394         int result;
   1395 
   1396         if (cParam.strat == lz4mid) {
   1397             result = LZ4MID_compress(ctx,
   1398                                 src, dst, srcSizePtr, dstCapacity,
   1399                                 limit, dict);
   1400         } else if (cParam.strat == lz4hc) {
   1401             result = LZ4HC_compress_hashChain(ctx,
   1402                                 src, dst, srcSizePtr, dstCapacity,
   1403                                 cParam.nbSearches, limit, dict);
   1404         } else {
   1405             assert(cParam.strat == lz4opt);
   1406             result = LZ4HC_compress_optimal(ctx,
   1407                                 src, dst, srcSizePtr, dstCapacity,
   1408                                 cParam.nbSearches, cParam.targetLength, limit,
   1409                                 cLevel >= LZ4HC_CLEVEL_MAX,   /* ultra mode */
   1410                                 dict, favor);
   1411         }
   1412         if (result <= 0) ctx->dirty = 1;
   1413         return result;
   1414     }
   1415 }
   1416 
   1417 static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock);
   1418 
   1419 static int
   1420 LZ4HC_compress_generic_noDictCtx (
   1421         LZ4HC_CCtx_internal* const ctx,
   1422         const char* const src,
   1423         char* const dst,
   1424         int* const srcSizePtr,
   1425         int const dstCapacity,
   1426         int cLevel,
   1427         limitedOutput_directive limit
   1428         )
   1429 {
   1430     assert(ctx->dictCtx == NULL);
   1431     return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx);
   1432 }
   1433 
   1434 static int isStateCompatible(const LZ4HC_CCtx_internal* ctx1, const LZ4HC_CCtx_internal* ctx2)
   1435 {
   1436     int const isMid1 = LZ4HC_getCLevelParams(ctx1->compressionLevel).strat == lz4mid;
   1437     int const isMid2 = LZ4HC_getCLevelParams(ctx2->compressionLevel).strat == lz4mid;
   1438     return !(isMid1 ^ isMid2);
   1439 }
   1440 
   1441 static int
   1442 LZ4HC_compress_generic_dictCtx (
   1443         LZ4HC_CCtx_internal* const ctx,
   1444         const char* const src,
   1445         char* const dst,
   1446         int* const srcSizePtr,
   1447         int const dstCapacity,
   1448         int cLevel,
   1449         limitedOutput_directive limit
   1450         )
   1451 {
   1452     const size_t position = (size_t)(ctx->end - ctx->prefixStart) + (ctx->dictLimit - ctx->lowLimit);
   1453     assert(ctx->dictCtx != NULL);
   1454     if (position >= 64 KB) {
   1455         ctx->dictCtx = NULL;
   1456         return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
   1457     } else if (position == 0 && *srcSizePtr > 4 KB && isStateCompatible(ctx, ctx->dictCtx)) {
   1458         LZ4_memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal));
   1459         LZ4HC_setExternalDict(ctx, (const BYTE *)src);
   1460         ctx->compressionLevel = (short)cLevel;
   1461         return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
   1462     } else {
   1463         return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, usingDictCtxHc);
   1464     }
   1465 }
   1466 
   1467 static int
   1468 LZ4HC_compress_generic (
   1469         LZ4HC_CCtx_internal* const ctx,
   1470         const char* const src,
   1471         char* const dst,
   1472         int* const srcSizePtr,
   1473         int const dstCapacity,
   1474         int cLevel,
   1475         limitedOutput_directive limit
   1476         )
   1477 {
   1478     if (ctx->dictCtx == NULL) {
   1479         return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
   1480     } else {
   1481         return LZ4HC_compress_generic_dictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);
   1482     }
   1483 }
   1484 
   1485 
   1486 int LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); }
   1487 
   1488 static size_t LZ4_streamHC_t_alignment(void)
   1489 {
   1490 #if LZ4_ALIGN_TEST
   1491     typedef struct { char c; LZ4_streamHC_t t; } t_a;
   1492     return sizeof(t_a) - sizeof(LZ4_streamHC_t);
   1493 #else
   1494     return 1;  /* effectively disabled */
   1495 #endif
   1496 }
   1497 
   1498 /* state is presumed correctly initialized,
   1499  * in which case its size and alignment have already been validate */
   1500 int LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
   1501 {
   1502     LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
   1503     if (!LZ4_isAligned(state, LZ4_streamHC_t_alignment())) return 0;
   1504     LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel);
   1505     LZ4HC_init_internal (ctx, (const BYTE*)src);
   1506     if (dstCapacity < LZ4_compressBound(srcSize))
   1507         return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput);
   1508     else
   1509         return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, notLimited);
   1510 }
   1511 
   1512 int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
   1513 {
   1514     LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));
   1515     if (ctx==NULL) return 0;   /* init failure */
   1516     return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel);
   1517 }
   1518 
   1519 int LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)
   1520 {
   1521     int cSize;
   1522 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
   1523     LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t));
   1524     if (statePtr==NULL) return 0;
   1525 #else
   1526     LZ4_streamHC_t state;
   1527     LZ4_streamHC_t* const statePtr = &state;
   1528 #endif
   1529     DEBUGLOG(5, "LZ4_compress_HC")
   1530     cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel);
   1531 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
   1532     FREEMEM(statePtr);
   1533 #endif
   1534     return cSize;
   1535 }
   1536 
   1537 /* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */
   1538 int LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel)
   1539 {
   1540     LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));
   1541     if (ctx==NULL) return 0;   /* init failure */
   1542     LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source);
   1543     LZ4_setCompressionLevel(ctx, cLevel);
   1544     return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, fillOutput);
   1545 }
   1546 
   1547 
   1548 
   1549 /**************************************
   1550 *  Streaming Functions
   1551 **************************************/
   1552 /* allocation */
   1553 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
   1554 LZ4_streamHC_t* LZ4_createStreamHC(void)
   1555 {
   1556     LZ4_streamHC_t* const state =
   1557         (LZ4_streamHC_t*)ALLOC_AND_ZERO(sizeof(LZ4_streamHC_t));
   1558     if (state == NULL) return NULL;
   1559     LZ4_setCompressionLevel(state, LZ4HC_CLEVEL_DEFAULT);
   1560     return state;
   1561 }
   1562 
   1563 int LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr)
   1564 {
   1565     DEBUGLOG(4, "LZ4_freeStreamHC(%p)", LZ4_streamHCPtr);
   1566     if (!LZ4_streamHCPtr) return 0;  /* support free on NULL */
   1567     FREEMEM(LZ4_streamHCPtr);
   1568     return 0;
   1569 }
   1570 #endif
   1571 
   1572 
   1573 LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size)
   1574 {
   1575     LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer;
   1576     DEBUGLOG(4, "LZ4_initStreamHC(%p, %u)", buffer, (unsigned)size);
   1577     /* check conditions */
   1578     if (buffer == NULL) return NULL;
   1579     if (size < sizeof(LZ4_streamHC_t)) return NULL;
   1580     if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL;
   1581     /* init */
   1582     { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse);
   1583       MEM_INIT(hcstate, 0, sizeof(*hcstate)); }
   1584     LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT);
   1585     return LZ4_streamHCPtr;
   1586 }
   1587 
   1588 /* just a stub */
   1589 void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
   1590 {
   1591     LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));
   1592     LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);
   1593 }
   1594 
   1595 void LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
   1596 {
   1597     LZ4HC_CCtx_internal* const s = &LZ4_streamHCPtr->internal_donotuse;
   1598     DEBUGLOG(5, "LZ4_resetStreamHC_fast(%p, %d)", LZ4_streamHCPtr, compressionLevel);
   1599     if (s->dirty) {
   1600         LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));
   1601     } else {
   1602         assert(s->end >= s->prefixStart);
   1603         s->dictLimit += (U32)(s->end - s->prefixStart);
   1604         s->prefixStart = NULL;
   1605         s->end = NULL;
   1606         s->dictCtx = NULL;
   1607     }
   1608     LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);
   1609 }
   1610 
   1611 void LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
   1612 {
   1613     DEBUGLOG(5, "LZ4_setCompressionLevel(%p, %d)", LZ4_streamHCPtr, compressionLevel);
   1614     if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT;
   1615     if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX;
   1616     LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel;
   1617 }
   1618 
   1619 void LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor)
   1620 {
   1621     LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = (favor!=0);
   1622 }
   1623 
   1624 /* LZ4_loadDictHC() :
   1625  * LZ4_streamHCPtr is presumed properly initialized */
   1626 int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr,
   1627               const char* dictionary, int dictSize)
   1628 {
   1629     LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
   1630     cParams_t cp;
   1631     DEBUGLOG(4, "LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d, clevel=%d)", LZ4_streamHCPtr, dictionary, dictSize, ctxPtr->compressionLevel);
   1632     assert(dictSize >= 0);
   1633     assert(LZ4_streamHCPtr != NULL);
   1634     if (dictSize > 64 KB) {
   1635         dictionary += (size_t)dictSize - 64 KB;
   1636         dictSize = 64 KB;
   1637     }
   1638     /* need a full initialization, there are bad side-effects when using resetFast() */
   1639     {   int const cLevel = ctxPtr->compressionLevel;
   1640         LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));
   1641         LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel);
   1642         cp = LZ4HC_getCLevelParams(cLevel);
   1643     }
   1644     LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary);
   1645     ctxPtr->end = (const BYTE*)dictionary + dictSize;
   1646     if (cp.strat == lz4mid) {
   1647         LZ4MID_fillHTable (ctxPtr, dictionary, (size_t)dictSize);
   1648     } else {
   1649         if (dictSize >= LZ4HC_HASHSIZE) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);
   1650     }
   1651     return dictSize;
   1652 }
   1653 
   1654 void LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC_t *dictionary_stream) {
   1655     working_stream->internal_donotuse.dictCtx = dictionary_stream != NULL ? &(dictionary_stream->internal_donotuse) : NULL;
   1656 }
   1657 
   1658 /* compression */
   1659 
   1660 static void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
   1661 {
   1662     DEBUGLOG(4, "LZ4HC_setExternalDict(%p, %p)", ctxPtr, newBlock);
   1663     if ( (ctxPtr->end >= ctxPtr->prefixStart + 4)
   1664       && (LZ4HC_getCLevelParams(ctxPtr->compressionLevel).strat != lz4mid) ) {
   1665         LZ4HC_Insert (ctxPtr, ctxPtr->end-3);  /* Referencing remaining dictionary content */
   1666     }
   1667 
   1668     /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
   1669     ctxPtr->lowLimit  = ctxPtr->dictLimit;
   1670     ctxPtr->dictStart  = ctxPtr->prefixStart;
   1671     ctxPtr->dictLimit += (U32)(ctxPtr->end - ctxPtr->prefixStart);
   1672     ctxPtr->prefixStart = newBlock;
   1673     ctxPtr->end  = newBlock;
   1674     ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */
   1675 
   1676     /* cannot reference an extDict and a dictCtx at the same time */
   1677     ctxPtr->dictCtx = NULL;
   1678 }
   1679 
   1680 static int
   1681 LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
   1682                                  const char* src, char* dst,
   1683                                  int* srcSizePtr, int dstCapacity,
   1684                                  limitedOutput_directive limit)
   1685 {
   1686     LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
   1687     DEBUGLOG(5, "LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)",
   1688                 LZ4_streamHCPtr, src, *srcSizePtr, limit);
   1689     assert(ctxPtr != NULL);
   1690     /* auto-init if forgotten */
   1691     if (ctxPtr->prefixStart == NULL)
   1692         LZ4HC_init_internal (ctxPtr, (const BYTE*) src);
   1693 
   1694     /* Check overflow */
   1695     if ((size_t)(ctxPtr->end - ctxPtr->prefixStart) + ctxPtr->dictLimit > 2 GB) {
   1696         size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->prefixStart);
   1697         if (dictSize > 64 KB) dictSize = 64 KB;
   1698         LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
   1699     }
   1700 
   1701     /* Check if blocks follow each other */
   1702     if ((const BYTE*)src != ctxPtr->end)
   1703         LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src);
   1704 
   1705     /* Check overlapping input/dictionary space */
   1706     {   const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;
   1707         const BYTE* const dictBegin = ctxPtr->dictStart;
   1708         const BYTE* const dictEnd   = ctxPtr->dictStart + (ctxPtr->dictLimit - ctxPtr->lowLimit);
   1709         if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {
   1710             if (sourceEnd > dictEnd) sourceEnd = dictEnd;
   1711             ctxPtr->lowLimit += (U32)(sourceEnd - ctxPtr->dictStart);
   1712             ctxPtr->dictStart += (U32)(sourceEnd - ctxPtr->dictStart);
   1713             /* invalidate dictionary is it's too small */
   1714             if (ctxPtr->dictLimit - ctxPtr->lowLimit < LZ4HC_HASHSIZE) {
   1715                 ctxPtr->lowLimit = ctxPtr->dictLimit;
   1716                 ctxPtr->dictStart = ctxPtr->prefixStart;
   1717     }   }   }
   1718 
   1719     return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit);
   1720 }
   1721 
   1722 int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity)
   1723 {
   1724     DEBUGLOG(5, "LZ4_compress_HC_continue");
   1725     if (dstCapacity < LZ4_compressBound(srcSize))
   1726         return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput);
   1727     else
   1728         return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, notLimited);
   1729 }
   1730 
   1731 int LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize)
   1732 {
   1733     return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, fillOutput);
   1734 }
   1735 
   1736 
   1737 /* LZ4_saveDictHC :
   1738  * save history content
   1739  * into a user-provided buffer
   1740  * which is then used to continue compression
   1741  */
   1742 int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
   1743 {
   1744     LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
   1745     int const prefixSize = (int)(streamPtr->end - streamPtr->prefixStart);
   1746     DEBUGLOG(5, "LZ4_saveDictHC(%p, %p, %d)", LZ4_streamHCPtr, safeBuffer, dictSize);
   1747     assert(prefixSize >= 0);
   1748     if (dictSize > 64 KB) dictSize = 64 KB;
   1749     if (dictSize < 4) dictSize = 0;
   1750     if (dictSize > prefixSize) dictSize = prefixSize;
   1751     if (safeBuffer == NULL) assert(dictSize == 0);
   1752     if (dictSize > 0)
   1753         LZ4_memmove(safeBuffer, streamPtr->end - dictSize, (size_t)dictSize);
   1754     {   U32 const endIndex = (U32)(streamPtr->end - streamPtr->prefixStart) + streamPtr->dictLimit;
   1755         streamPtr->end = (safeBuffer == NULL) ? NULL : (const BYTE*)safeBuffer + dictSize;
   1756         streamPtr->prefixStart = (const BYTE*)safeBuffer;
   1757         streamPtr->dictLimit = endIndex - (U32)dictSize;
   1758         streamPtr->lowLimit = endIndex - (U32)dictSize;
   1759         streamPtr->dictStart = streamPtr->prefixStart;
   1760         if (streamPtr->nextToUpdate < streamPtr->dictLimit)
   1761             streamPtr->nextToUpdate = streamPtr->dictLimit;
   1762     }
   1763     return dictSize;
   1764 }
   1765 
   1766 
   1767 /* ================================================
   1768  *  LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX])
   1769  * ===============================================*/
   1770 typedef struct {
   1771     int price;
   1772     int off;
   1773     int mlen;
   1774     int litlen;
   1775 } LZ4HC_optimal_t;
   1776 
   1777 /* price in bytes */
   1778 LZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen)
   1779 {
   1780     int price = litlen;
   1781     assert(litlen >= 0);
   1782     if (litlen >= (int)RUN_MASK)
   1783         price += 1 + ((litlen-(int)RUN_MASK) / 255);
   1784     return price;
   1785 }
   1786 
   1787 /* requires mlen >= MINMATCH */
   1788 LZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen)
   1789 {
   1790     int price = 1 + 2 ; /* token + 16-bit offset */
   1791     assert(litlen >= 0);
   1792     assert(mlen >= MINMATCH);
   1793 
   1794     price += LZ4HC_literalsPrice(litlen);
   1795 
   1796     if (mlen >= (int)(ML_MASK+MINMATCH))
   1797         price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255);
   1798 
   1799     return price;
   1800 }
   1801 
   1802 LZ4_FORCE_INLINE LZ4HC_match_t
   1803 LZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx,
   1804                       const BYTE* ip, const BYTE* const iHighLimit,
   1805                       int minLen, int nbSearches,
   1806                       const dictCtx_directive dict,
   1807                       const HCfavor_e favorDecSpeed)
   1808 {
   1809     LZ4HC_match_t const match0 = { 0 , 0, 0 };
   1810     /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),
   1811      * but this won't be the case here, as we define iLowLimit==ip,
   1812     ** so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */
   1813     LZ4HC_match_t md = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed);
   1814     assert(md.back == 0);
   1815     if (md.len <= minLen) return match0;
   1816     if (favorDecSpeed) {
   1817         if ((md.len>18) & (md.len<=36)) md.len=18;   /* favor dec.speed (shortcut) */
   1818     }
   1819     return md;
   1820 }
   1821 
   1822 
   1823 static int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,
   1824                                     const char* const source,
   1825                                     char* dst,
   1826                                     int* srcSizePtr,
   1827                                     int dstCapacity,
   1828                                     int const nbSearches,
   1829                                     size_t sufficient_len,
   1830                                     const limitedOutput_directive limit,
   1831                                     int const fullUpdate,
   1832                                     const dictCtx_directive dict,
   1833                                     const HCfavor_e favorDecSpeed)
   1834 {
   1835     int retval = 0;
   1836 #define TRAILING_LITERALS 3
   1837 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
   1838     LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS));
   1839 #else
   1840     LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS];   /* ~64 KB, which is a bit large for stack... */
   1841 #endif
   1842 
   1843     const BYTE* ip = (const BYTE*) source;
   1844     const BYTE* anchor = ip;
   1845     const BYTE* const iend = ip + *srcSizePtr;
   1846     const BYTE* const mflimit = iend - MFLIMIT;
   1847     const BYTE* const matchlimit = iend - LASTLITERALS;
   1848     BYTE* op = (BYTE*) dst;
   1849     BYTE* opSaved = (BYTE*) dst;
   1850     BYTE* oend = op + dstCapacity;
   1851     int ovml = MINMATCH;  /* overflow - last sequence */
   1852     int ovoff = 0;
   1853 
   1854     /* init */
   1855 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
   1856     if (opt == NULL) goto _return_label;
   1857 #endif
   1858     DEBUGLOG(5, "LZ4HC_compress_optimal(dst=%p, dstCapa=%u)", dst, (unsigned)dstCapacity);
   1859     *srcSizePtr = 0;
   1860     if (limit == fillOutput) oend -= LASTLITERALS;   /* Hack for support LZ4 format restriction */
   1861     if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;
   1862 
   1863     /* Main Loop */
   1864     while (ip <= mflimit) {
   1865          int const llen = (int)(ip - anchor);
   1866          int best_mlen, best_off;
   1867          int cur, last_match_pos = 0;
   1868 
   1869          LZ4HC_match_t const firstMatch = LZ4HC_FindLongerMatch(ctx, ip, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);
   1870          if (firstMatch.len==0) { ip++; continue; }
   1871 
   1872          if ((size_t)firstMatch.len > sufficient_len) {
   1873              /* good enough solution : immediate encoding */
   1874              int const firstML = firstMatch.len;
   1875              opSaved = op;
   1876              if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, firstMatch.off, limit, oend) ) {  /* updates ip, op and anchor */
   1877                  ovml = firstML;
   1878                  ovoff = firstMatch.off;
   1879                  goto _dest_overflow;
   1880              }
   1881              continue;
   1882          }
   1883 
   1884          /* set prices for first positions (literals) */
   1885          {   int rPos;
   1886              for (rPos = 0 ; rPos < MINMATCH ; rPos++) {
   1887                  int const cost = LZ4HC_literalsPrice(llen + rPos);
   1888                  opt[rPos].mlen = 1;
   1889                  opt[rPos].off = 0;
   1890                  opt[rPos].litlen = llen + rPos;
   1891                  opt[rPos].price = cost;
   1892                  DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",
   1893                              rPos, cost, opt[rPos].litlen);
   1894          }   }
   1895          /* set prices using initial match */
   1896          {   int const matchML = firstMatch.len;   /* necessarily < sufficient_len < LZ4_OPT_NUM */
   1897              int const offset = firstMatch.off;
   1898              int mlen;
   1899              assert(matchML < LZ4_OPT_NUM);
   1900              for (mlen = MINMATCH ; mlen <= matchML ; mlen++) {
   1901                  int const cost = LZ4HC_sequencePrice(llen, mlen);
   1902                  opt[mlen].mlen = mlen;
   1903                  opt[mlen].off = offset;
   1904                  opt[mlen].litlen = llen;
   1905                  opt[mlen].price = cost;
   1906                  DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i) -- initial setup",
   1907                              mlen, cost, mlen);
   1908          }   }
   1909          last_match_pos = firstMatch.len;
   1910          {   int addLit;
   1911              for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {
   1912                  opt[last_match_pos+addLit].mlen = 1; /* literal */
   1913                  opt[last_match_pos+addLit].off = 0;
   1914                  opt[last_match_pos+addLit].litlen = addLit;
   1915                  opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);
   1916                  DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i) -- initial setup",
   1917                              last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);
   1918          }   }
   1919 
   1920          /* check further positions */
   1921          for (cur = 1; cur < last_match_pos; cur++) {
   1922              const BYTE* const curPtr = ip + cur;
   1923              LZ4HC_match_t newMatch;
   1924 
   1925              if (curPtr > mflimit) break;
   1926              DEBUGLOG(7, "rPos:%u[%u] vs [%u]%u",
   1927                      cur, opt[cur].price, opt[cur+1].price, cur+1);
   1928              if (fullUpdate) {
   1929                  /* not useful to search here if next position has same (or lower) cost */
   1930                  if ( (opt[cur+1].price <= opt[cur].price)
   1931                    /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */
   1932                    && (opt[cur+MINMATCH].price < opt[cur].price + 3/*min seq price*/) )
   1933                      continue;
   1934              } else {
   1935                  /* not useful to search here if next position has same (or lower) cost */
   1936                  if (opt[cur+1].price <= opt[cur].price) continue;
   1937              }
   1938 
   1939              DEBUGLOG(7, "search at rPos:%u", cur);
   1940              if (fullUpdate)
   1941                  newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);
   1942              else
   1943                  /* only test matches of minimum length; slightly faster, but misses a few bytes */
   1944                  newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, last_match_pos - cur, nbSearches, dict, favorDecSpeed);
   1945              if (!newMatch.len) continue;
   1946 
   1947              if ( ((size_t)newMatch.len > sufficient_len)
   1948                || (newMatch.len + cur >= LZ4_OPT_NUM) ) {
   1949                  /* immediate encoding */
   1950                  best_mlen = newMatch.len;
   1951                  best_off = newMatch.off;
   1952                  last_match_pos = cur + 1;
   1953                  goto encode;
   1954              }
   1955 
   1956              /* before match : set price with literals at beginning */
   1957              {   int const baseLitlen = opt[cur].litlen;
   1958                  int litlen;
   1959                  for (litlen = 1; litlen < MINMATCH; litlen++) {
   1960                      int const price = opt[cur].price - LZ4HC_literalsPrice(baseLitlen) + LZ4HC_literalsPrice(baseLitlen+litlen);
   1961                      int const pos = cur + litlen;
   1962                      if (price < opt[pos].price) {
   1963                          opt[pos].mlen = 1; /* literal */
   1964                          opt[pos].off = 0;
   1965                          opt[pos].litlen = baseLitlen+litlen;
   1966                          opt[pos].price = price;
   1967                          DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)",
   1968                                      pos, price, opt[pos].litlen);
   1969              }   }   }
   1970 
   1971              /* set prices using match at position = cur */
   1972              {   int const matchML = newMatch.len;
   1973                  int ml = MINMATCH;
   1974 
   1975                  assert(cur + newMatch.len < LZ4_OPT_NUM);
   1976                  for ( ; ml <= matchML ; ml++) {
   1977                      int const pos = cur + ml;
   1978                      int const offset = newMatch.off;
   1979                      int price;
   1980                      int ll;
   1981                      DEBUGLOG(7, "testing price rPos %i (last_match_pos=%i)",
   1982                                  pos, last_match_pos);
   1983                      if (opt[cur].mlen == 1) {
   1984                          ll = opt[cur].litlen;
   1985                          price = ((cur > ll) ? opt[cur - ll].price : 0)
   1986                                + LZ4HC_sequencePrice(ll, ml);
   1987                      } else {
   1988                          ll = 0;
   1989                          price = opt[cur].price + LZ4HC_sequencePrice(0, ml);
   1990                      }
   1991 
   1992                     assert((U32)favorDecSpeed <= 1);
   1993                      if (pos > last_match_pos+TRAILING_LITERALS
   1994                       || price <= opt[pos].price - (int)favorDecSpeed) {
   1995                          DEBUGLOG(7, "rPos:%3i => price:%3i (matchlen=%i)",
   1996                                      pos, price, ml);
   1997                          assert(pos < LZ4_OPT_NUM);
   1998                          if ( (ml == matchML)  /* last pos of last match */
   1999                            && (last_match_pos < pos) )
   2000                              last_match_pos = pos;
   2001                          opt[pos].mlen = ml;
   2002                          opt[pos].off = offset;
   2003                          opt[pos].litlen = ll;
   2004                          opt[pos].price = price;
   2005              }   }   }
   2006              /* complete following positions with literals */
   2007              {   int addLit;
   2008                  for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {
   2009                      opt[last_match_pos+addLit].mlen = 1; /* literal */
   2010                      opt[last_match_pos+addLit].off = 0;
   2011                      opt[last_match_pos+addLit].litlen = addLit;
   2012                      opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);
   2013                      DEBUGLOG(7, "rPos:%3i => price:%3i (litlen=%i)", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);
   2014              }   }
   2015          }  /* for (cur = 1; cur <= last_match_pos; cur++) */
   2016 
   2017          assert(last_match_pos < LZ4_OPT_NUM + TRAILING_LITERALS);
   2018          best_mlen = opt[last_match_pos].mlen;
   2019          best_off = opt[last_match_pos].off;
   2020          cur = last_match_pos - best_mlen;
   2021 
   2022 encode: /* cur, last_match_pos, best_mlen, best_off must be set */
   2023          assert(cur < LZ4_OPT_NUM);
   2024          assert(last_match_pos >= 1);  /* == 1 when only one candidate */
   2025          DEBUGLOG(6, "reverse traversal, looking for shortest path (last_match_pos=%i)", last_match_pos);
   2026          {   int candidate_pos = cur;
   2027              int selected_matchLength = best_mlen;
   2028              int selected_offset = best_off;
   2029              while (1) {  /* from end to beginning */
   2030                  int const next_matchLength = opt[candidate_pos].mlen;  /* can be 1, means literal */
   2031                  int const next_offset = opt[candidate_pos].off;
   2032                  DEBUGLOG(7, "pos %i: sequence length %i", candidate_pos, selected_matchLength);
   2033                  opt[candidate_pos].mlen = selected_matchLength;
   2034                  opt[candidate_pos].off = selected_offset;
   2035                  selected_matchLength = next_matchLength;
   2036                  selected_offset = next_offset;
   2037                  if (next_matchLength > candidate_pos) break; /* last match elected, first match to encode */
   2038                  assert(next_matchLength > 0);  /* can be 1, means literal */
   2039                  candidate_pos -= next_matchLength;
   2040          }   }
   2041 
   2042          /* encode all recorded sequences in order */
   2043          {   int rPos = 0;  /* relative position (to ip) */
   2044              while (rPos < last_match_pos) {
   2045                  int const ml = opt[rPos].mlen;
   2046                  int const offset = opt[rPos].off;
   2047                  if (ml == 1) { ip++; rPos++; continue; }  /* literal; note: can end up with several literals, in which case, skip them */
   2048                  rPos += ml;
   2049                  assert(ml >= MINMATCH);
   2050                  assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX));
   2051                  opSaved = op;
   2052                  if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, offset, limit, oend) ) {  /* updates ip, op and anchor */
   2053                      ovml = ml;
   2054                      ovoff = offset;
   2055                      goto _dest_overflow;
   2056          }   }   }
   2057      }  /* while (ip <= mflimit) */
   2058 
   2059 _last_literals:
   2060      /* Encode Last Literals */
   2061      {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */
   2062          size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;
   2063          size_t const totalSize = 1 + llAdd + lastRunSize;
   2064          if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */
   2065          if (limit && (op + totalSize > oend)) {
   2066              if (limit == limitedOutput) { /* Check output limit */
   2067                 retval = 0;
   2068                 goto _return_label;
   2069              }
   2070              /* adapt lastRunSize to fill 'dst' */
   2071              lastRunSize  = (size_t)(oend - op) - 1 /*token*/;
   2072              llAdd = (lastRunSize + 256 - RUN_MASK) / 256;
   2073              lastRunSize -= llAdd;
   2074          }
   2075          DEBUGLOG(6, "Final literal run : %i literals", (int)lastRunSize);
   2076          ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */
   2077 
   2078          if (lastRunSize >= RUN_MASK) {
   2079              size_t accumulator = lastRunSize - RUN_MASK;
   2080              *op++ = (RUN_MASK << ML_BITS);
   2081              for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;
   2082              *op++ = (BYTE) accumulator;
   2083          } else {
   2084              *op++ = (BYTE)(lastRunSize << ML_BITS);
   2085          }
   2086          LZ4_memcpy(op, anchor, lastRunSize);
   2087          op += lastRunSize;
   2088      }
   2089 
   2090      /* End */
   2091      *srcSizePtr = (int) (((const char*)ip) - source);
   2092      retval = (int) ((char*)op-dst);
   2093      goto _return_label;
   2094 
   2095 _dest_overflow:
   2096 if (limit == fillOutput) {
   2097      /* Assumption : ip, anchor, ovml and ovref must be set correctly */
   2098      size_t const ll = (size_t)(ip - anchor);
   2099      size_t const ll_addbytes = (ll + 240) / 255;
   2100      size_t const ll_totalCost = 1 + ll_addbytes + ll;
   2101      BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */
   2102      DEBUGLOG(6, "Last sequence overflowing (only %i bytes remaining)", (int)(oend-1-opSaved));
   2103      op = opSaved;  /* restore correct out pointer */
   2104      if (op + ll_totalCost <= maxLitPos) {
   2105          /* ll validated; now adjust match length */
   2106          size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));
   2107          size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);
   2108          assert(maxMlSize < INT_MAX); assert(ovml >= 0);
   2109          if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize;
   2110          if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) {
   2111              DEBUGLOG(6, "Space to end : %i + ml (%i)", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml);
   2112              DEBUGLOG(6, "Before : ip = %p, anchor = %p", ip, anchor);
   2113              LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovoff, notLimited, oend);
   2114              DEBUGLOG(6, "After : ip = %p, anchor = %p", ip, anchor);
   2115      }   }
   2116      goto _last_literals;
   2117 }
   2118 _return_label:
   2119 #if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
   2120      if (opt) FREEMEM(opt);
   2121 #endif
   2122      return retval;
   2123 }
   2124 
   2125 
   2126 /***************************************************
   2127 *  Deprecated Functions
   2128 ***************************************************/
   2129 
   2130 /* These functions currently generate deprecation warnings */
   2131 
   2132 /* Wrappers for deprecated compression functions */
   2133 int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
   2134 int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
   2135 int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
   2136 int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
   2137 int LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
   2138 int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
   2139 int LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
   2140 int LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
   2141 int LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }
   2142 int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
   2143 
   2144 
   2145 /* Deprecated streaming functions */
   2146 int LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); }
   2147 
   2148 /* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t)
   2149  * @return : 0 on success, !=0 if error */
   2150 int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
   2151 {
   2152     LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4));
   2153     if (hc4 == NULL) return 1;   /* init failed */
   2154     LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
   2155     return 0;
   2156 }
   2157 
   2158 #if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)
   2159 void* LZ4_createHC (const char* inputBuffer)
   2160 {
   2161     LZ4_streamHC_t* const hc4 = LZ4_createStreamHC();
   2162     if (hc4 == NULL) return NULL;   /* not enough memory */
   2163     LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
   2164     return hc4;
   2165 }
   2166 
   2167 int LZ4_freeHC (void* LZ4HC_Data)
   2168 {
   2169     if (!LZ4HC_Data) return 0;  /* support free on NULL */
   2170     FREEMEM(LZ4HC_Data);
   2171     return 0;
   2172 }
   2173 #endif
   2174 
   2175 int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel)
   2176 {
   2177     return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited);
   2178 }
   2179 
   2180 int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel)
   2181 {
   2182     return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput);
   2183 }
   2184 
   2185 char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
   2186 {
   2187     LZ4HC_CCtx_internal* const s = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
   2188     const BYTE* const bufferStart = s->prefixStart - s->dictLimit + s->lowLimit;
   2189     LZ4_resetStreamHC_fast((LZ4_streamHC_t*)LZ4HC_Data, s->compressionLevel);
   2190     /* ugly conversion trick, required to evade (const char*) -> (char*) cast-qual warning :( */
   2191     return (char*)(uptrval)bufferStart;
   2192 }