tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }