1fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet./*
22a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    LZ4 HC - High Compression Mode of LZ4
38b233b228dbda484d1d545c5a3ecaf06aef3e930Yann Collet    Copyright (C) 2011-2016, Yann Collet.
42a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet
52a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
62a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet
72a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    Redistribution and use in source and binary forms, with or without
82a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    modification, are permitted provided that the following conditions are
92a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    met:
102a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet
112a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    * Redistributions of source code must retain the above copyright
122a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    notice, this list of conditions and the following disclaimer.
132a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    * Redistributions in binary form must reproduce the above
142a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    copyright notice, this list of conditions and the following disclaimer
152a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    in the documentation and/or other materials provided with the
162a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    distribution.
172a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet
182a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
192a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
202a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
212a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
222a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
232a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
242a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
252a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
262a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
272a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
282a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
292a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet
302a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    You can contact the author at :
3184cedb4632ab87fbb108b4f7ed6e9ec164b6a4d4Przemyslaw Skibinski       - LZ4 source repository : https://github.com/lz4/lz4
322a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet       - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.*/
3494542d845884c922f809725807ecbd2cf7454aceYann Collet/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */
3569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
3669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
372c80138121550c719cb0a622f6a8a304d283960cYann Collet/* *************************************
382a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Tuning Parameter
392c80138121550c719cb0a622f6a8a304d283960cYann Collet***************************************/
4069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
412c80138121550c719cb0a622f6a8a304d283960cYann Collet/*!
422c80138121550c719cb0a622f6a8a304d283960cYann Collet * HEAPMODE :
432c80138121550c719cb0a622f6a8a304d283960cYann Collet * Select how default compression function will allocate workplace memory,
442c80138121550c719cb0a622f6a8a304d283960cYann Collet * in stack (0:fastest), or in heap (1:requires malloc()).
452c80138121550c719cb0a622f6a8a304d283960cYann Collet * Since workplace is rather large, heap mode is recommended.
462c80138121550c719cb0a622f6a8a304d283960cYann Collet */
4794542d845884c922f809725807ecbd2cf7454aceYann Collet#ifndef LZ4HC_HEAPMODE
4894542d845884c922f809725807ecbd2cf7454aceYann Collet#  define LZ4HC_HEAPMODE 1
4994542d845884c922f809725807ecbd2cf7454aceYann Collet#endif
5069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
512c80138121550c719cb0a622f6a8a304d283960cYann Collet
522c80138121550c719cb0a622f6a8a304d283960cYann Collet/* *************************************
5394542d845884c922f809725807ecbd2cf7454aceYann Collet*  Dependency
542c80138121550c719cb0a622f6a8a304d283960cYann Collet***************************************/
5533dca250ee0afa3aec58bf3bf1a34b09bebf3fb5Yann Collet#include "lz4hc.h"
56fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
57fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
582c80138121550c719cb0a622f6a8a304d283960cYann Collet/* *************************************
592a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Compiler Options
602c80138121550c719cb0a622f6a8a304d283960cYann Collet***************************************/
61326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#if defined(__GNUC__)
62326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#  pragma GCC diagnostic ignored "-Wunused-function"
63fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#endif
64fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
65326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#if defined (__clang__)
66326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#  pragma clang diagnostic ignored "-Wunused-function"
67fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#endif
68fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
69fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
702c80138121550c719cb0a622f6a8a304d283960cYann Collet/* *************************************
712a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Common LZ4 definition
722c80138121550c719cb0a622f6a8a304d283960cYann Collet***************************************/
73326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#define LZ4_COMMONDEFS_ONLY
74326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#include "lz4.c"
75fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
76fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
772c80138121550c719cb0a622f6a8a304d283960cYann Collet/* *************************************
782a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Constants
792c80138121550c719cb0a622f6a8a304d283960cYann Collet***************************************/
80fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
81fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
82fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
8369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
842a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Macros
8569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
8685aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell#define HASH_FUNCTION(i)       (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))
871833be1cf0e545f8b24bb4a786e274a9e419e280Przemyslaw Skibinski#define DELTANEXTMAXD(p)       chainTable[(p) & LZ4HC_MAXD_MASK]    /* flexible, LZ4HC_MAXD dependent */
882a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet#define DELTANEXTU16(p)        chainTable[(U16)(p)]   /* faster */
89fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
90326cada9fadeedccef8934e11144f343ecdcabcbYann Colletstatic U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
91fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
92fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
93fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
94326cada9fadeedccef8934e11144f343ecdcabcbYann Collet/**************************************
952a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  HC Compression
96326cada9fadeedccef8934e11144f343ecdcabcbYann Collet**************************************/
97874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Colletstatic void LZ4HC_init (LZ4HC_CCtx_internal* hc4, const BYTE* start)
98fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
99fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
100fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
101312d88249feee4c1b7511ac9fffce10ed6802ba7Przemyslaw Skibinski    hc4->nextToUpdate = 64 KB;
10265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->base = start - 64 KB;
10365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->end = start;
10465ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->dictBase = start - 64 KB;
105e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    hc4->dictLimit = 64 KB;
106e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    hc4->lowLimit = 64 KB;
107fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
108fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
109fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
11069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Update chains up to ip (excluded) */
111874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann ColletFORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)
112fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
1135871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    U16* const chainTable = hc4->chainTable;
1145871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    U32* const hashTable  = hc4->hashTable;
115d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
1165871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    U32 const target = (U32)(ip - base);
117d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32 idx = hc4->nextToUpdate;
118fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
1195871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    while (idx < target) {
1205871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        U32 const h = LZ4HC_hashPtr(base+idx);
1215871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        size_t delta = idx - hashTable[h];
122fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
1232a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        DELTANEXTU16(idx) = (U16)delta;
1245871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        hashTable[h] = idx;
125d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet        idx++;
126fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
1277ac18ad9dc5a5555f9129659c007fe9141e422b0Yann Collet
128d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    hc4->nextToUpdate = target;
129fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
130fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
131fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
132874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann ColletFORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_CCtx_internal* hc4,   /* Index table will be updated */
133508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const BYTE* ip, const BYTE* const iLimit,
134508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const BYTE** matchpos,
135508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const int maxNbAttempts)
136fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
137fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    U16* const chainTable = hc4->chainTable;
138d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32* const HashTable = hc4->hashTable;
139d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
140e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    const BYTE* const dictBase = hc4->dictBase;
141e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    const U32 dictLimit = hc4->dictLimit;
142508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
143e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    U32 matchIndex;
14469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    int nbAttempts=maxNbAttempts;
145d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    size_t ml=0;
146fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
147508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* HC4 match finder */
148fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    LZ4HC_Insert(hc4, ip);
1493dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
150fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
1515871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    while ((matchIndex>=lowLimit) && (nbAttempts)) {
152fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        nbAttempts--;
1535871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (matchIndex >= dictLimit) {
15494542d845884c922f809725807ecbd2cf7454aceYann Collet            const BYTE* const match = base + matchIndex;
1553dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            if (*(match+ml) == *(ip+ml)
156326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                && (LZ4_read32(match) == LZ4_read32(ip)))
1573dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            {
1585871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                size_t const mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
1593dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (mlt > ml) { ml = mlt; *matchpos = match; }
1603dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            }
1615871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        } else {
16294542d845884c922f809725807ecbd2cf7454aceYann Collet            const BYTE* const match = dictBase + matchIndex;
1635871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (LZ4_read32(match) == LZ4_read32(ip)) {
1643dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                size_t mlt;
1653dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                const BYTE* vLimit = ip + (dictLimit - matchIndex);
1663dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (vLimit > iLimit) vLimit = iLimit;
167326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
1683dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((ip+mlt == vLimit) && (vLimit < iLimit))
169326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                    mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
1708a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */
1713dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            }
172fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
1732a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        matchIndex -= DELTANEXTU16(matchIndex);
174fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
175fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
176fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return (int)ml;
177fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
178fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
179fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
180d239a23337e5eba41f557b48eb26f0db81b28f26Yann ColletFORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
181874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* hc4,
182002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const ip,
183002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const iLowLimit,
184002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const iHighLimit,
185508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int longest,
186508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** matchpos,
187508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** startpos,
188508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const int maxNbAttempts)
189fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
190d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U16* const chainTable = hc4->chainTable;
191d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32* const HashTable = hc4->hashTable;
192d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
1933dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    const U32 dictLimit = hc4->dictLimit;
194002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const lowPrefixPtr = base + dictLimit;
195508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
1963dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    const BYTE* const dictBase = hc4->dictBase;
1973dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    U32   matchIndex;
19869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    int nbAttempts = maxNbAttempts;
1993dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    int delta = (int)(ip-iLowLimit);
200fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
201e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet
202508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* First Match */
203fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    LZ4HC_Insert(hc4, ip);
2043dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
205fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
2065871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    while ((matchIndex>=lowLimit) && (nbAttempts)) {
207fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        nbAttempts--;
2085871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (matchIndex >= dictLimit) {
209002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet            const BYTE* matchPtr = base + matchIndex;
2105871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (*(iLowLimit + longest) == *(matchPtr - delta + longest)) {
2115871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
212002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
213002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    int back = 0;
214002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet
2155871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                    while ((ip+back > iLowLimit)
216002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                           && (matchPtr+back > lowPrefixPtr)
217002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                           && (ip[back-1] == matchPtr[back-1]))
218002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                            back--;
219fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
220002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    mlt -= back;
221fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
2225871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                    if (mlt > longest) {
223002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        longest = (int)mlt;
224002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        *matchpos = matchPtr+back;
225002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        *startpos = ip+back;
226508855c48826aa0544a907f02b52515aabba5e16Yann Collet                    }
2273dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                }
2285871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            }
2295871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        } else {
230258a5e7fa44825488fe4683f3a04c36fc944a23fYann Collet            const BYTE* const matchPtr = dictBase + matchIndex;
2315871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
2323dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                size_t mlt;
233508855c48826aa0544a907f02b52515aabba5e16Yann Collet                int back=0;
2343dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                const BYTE* vLimit = ip + (dictLimit - matchIndex);
2353dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (vLimit > iHighLimit) vLimit = iHighLimit;
236002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
2373dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
238326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                    mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
239002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
240508855c48826aa0544a907f02b52515aabba5e16Yann Collet                mlt -= back;
2413dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
242fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
243fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
2442a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        matchIndex -= DELTANEXTU16(matchIndex);
245fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
246fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
247fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return longest;
248fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
249fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
250fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
251fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
252fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
2538a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#define LZ4HC_DEBUG 0
2548a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#if LZ4HC_DEBUG
2558a9fb8cf3229c9a704c982667c63ac440b8487baYann Colletstatic unsigned debug = 0;
2568a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#endif
257508855c48826aa0544a907f02b52515aabba5e16Yann Collet
258fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.FORCE_INLINE int LZ4HC_encodeSequence (
259508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** ip,
260508855c48826aa0544a907f02b52515aabba5e16Yann Collet    BYTE** op,
261508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** anchor,
262508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int matchLength,
263508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE* const match,
264508855c48826aa0544a907f02b52515aabba5e16Yann Collet    limitedOutput_directive limitedOutputBuffer,
265508855c48826aa0544a907f02b52515aabba5e16Yann Collet    BYTE* oend)
266fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
267fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    int length;
268fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* token;
269fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
2708a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#if LZ4HC_DEBUG
2718a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet    if (debug) printf("literal : %u  --  match : %u  --  offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
2728a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#endif
273e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet
27469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Literal length */
275fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    length = (int)(*ip - *anchor);
276fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    token = (*op)++;
277e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1;   /* Check output limit */
278fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; }
279fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    else *token = (BYTE)(length<<ML_BITS);
280fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
28169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Copy Literals */
282326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    LZ4_wildCopy(*op, *anchor, (*op) + length);
283326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    *op += length;
284fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
28569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Offset */
286326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
287fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
28869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode MatchLength */
289fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    length = (int)(matchLength-MINMATCH);
290e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1;   /* Check output limit */
29164f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet    if (length>=(int)ML_MASK) {
29264f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        *token += ML_MASK;
29364f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        length -= ML_MASK;
29464f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; }
29564f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        if (length > 254) { length-=255; *(*op)++ = 255; }
29664f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        *(*op)++ = (BYTE)length;
29764f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet    } else {
29864f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet        *token += (BYTE)(length);
29964f556e610b68e6781e05d2d6470ebf8b8dff45cYann Collet    }
300fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
30169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Prepare next loop */
302fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    *ip += matchLength;
303fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    *anchor = *ip;
304fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
305fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return 0;
306fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
307fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
308c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski#include "lz4opt.h"
309fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
310c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinskistatic int LZ4HC_compress_hashChain (
311874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* const ctx,
312c7ab95faa5aabec7e2c01e66ce164865d7c79bbfYann Collet    const char* const source,
313c7ab95faa5aabec7e2c01e66ce164865d7c79bbfYann Collet    char* const dest,
314c7ab95faa5aabec7e2c01e66ce164865d7c79bbfYann Collet    int const inputSize,
315c7ab95faa5aabec7e2c01e66ce164865d7c79bbfYann Collet    int const maxOutputSize,
316e3fee94742f9027aa2d27fae6458ce285889552ePrzemyslaw Skibinski    unsigned maxNbAttempts,
317508855c48826aa0544a907f02b52515aabba5e16Yann Collet    limitedOutput_directive limit
318508855c48826aa0544a907f02b52515aabba5e16Yann Collet    )
319fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
320fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ip = (const BYTE*) source;
321fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* anchor = ip;
322fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const iend = ip + inputSize;
323fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const mflimit = iend - MFLIMIT;
324fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const matchlimit = (iend - LASTLITERALS);
325fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
326fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* op = (BYTE*) dest;
327fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* const oend = op + maxOutputSize;
328fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
329fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    int   ml, ml2, ml3, ml0;
3305871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    const BYTE* ref = NULL;
3315871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    const BYTE* start2 = NULL;
3325871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    const BYTE* ref2 = NULL;
3335871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    const BYTE* start3 = NULL;
3345871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    const BYTE* ref3 = NULL;
335fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* start0;
336fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ref0;
337fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
338d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    /* init */
339fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    ctx->end += inputSize;
340fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
341fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    ip++;
342fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
34369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Main Loop */
3445871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    while (ip < mflimit) {
34569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
346fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (!ml) { ip++; continue; }
347fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
34869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* saved, in case we would skip too much */
349fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        start0 = ip;
350fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref0 = ref;
351fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml0 = ml;
352fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
353fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet._Search2:
354fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (ip+ml < mflimit)
355c7ab95faa5aabec7e2c01e66ce164865d7c79bbfYann Collet            ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 0, matchlimit, ml, &ref2, &start2, maxNbAttempts);
356fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else ml2 = ml;
357fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
3585871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (ml2 == ml) { /* No better match */
359fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
360fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            continue;
361fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
362fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
3635871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (start0 < ip) {
3645871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (start2 < ip + ml0) {  /* empirical */
365fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ip = start0;
366fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref = ref0;
367fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml = ml0;
368fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
369fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
370fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
37169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* Here, start0==ip */
3725871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if ((start2 - ip) < 3) {  /* First Match too small : removed */
373fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ml = ml2;
374fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ip = start2;
375fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ref =ref2;
376fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            goto _Search2;
377fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
378fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
379fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet._Search3:
38069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /*
381508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * Currently we have :
382508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ml2 > ml1, and
383508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ip1+3 <= ip2 (usually < ip1+ml1)
384508855c48826aa0544a907f02b52515aabba5e16Yann Collet        */
3855871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if ((start2 - ip) < OPTIMAL_ML) {
386fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            int correction;
387fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            int new_ml = ml;
388fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
389fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
390fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            correction = new_ml - (int)(start2 - ip);
3915871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (correction > 0) {
392fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                start2 += correction;
393fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref2 += correction;
394fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml2 -= correction;
395fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
396fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
39769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
398fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
399fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (start2 + ml2 < mflimit)
40069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
401fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else ml3 = ml2;
402fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
4035871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (ml3 == ml2) {  /* No better match : 2 sequences to encode */
40469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            /* ip & ref are known; Now for ml */
405fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (start2 < ip+ml)  ml = (int)(start2 - ip);
40669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            /* Now, encode 2 sequences */
407fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
408fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ip = start2;
409fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
410fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            continue;
411fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
412fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
4135871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (start3 < ip+ml+3) {  /* Not enough space for match 2 : remove it */
4145871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if (start3 >= (ip+ml)) {  /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
4155871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                if (start2 < ip+ml) {
416fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    int correction = (int)(ip+ml - start2);
417fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    start2 += correction;
418fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ref2 += correction;
419fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ml2 -= correction;
4205871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                    if (ml2 < MINMATCH) {
421fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        start2 = start3;
422fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        ref2 = ref3;
423fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        ml2 = ml3;
424fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    }
425fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                }
426fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
427fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
428fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ip  = start3;
429fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref = ref3;
430fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml  = ml3;
431fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
432fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                start0 = start2;
433fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref0 = ref2;
434fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml0 = ml2;
435fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                goto _Search2;
436fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
437fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
438fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            start2 = start3;
439fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ref2 = ref3;
440fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ml2 = ml3;
441fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            goto _Search3;
442fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
443fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
44469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /*
445508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * OK, now we have 3 ascending matches; let's write at least the first one
446508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ip & ref are known; Now for ml
447508855c48826aa0544a907f02b52515aabba5e16Yann Collet        */
4485871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if (start2 < ip+ml) {
4495871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            if ((start2 - ip) < (int)ML_MASK) {
450fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                int correction;
451fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
452fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
453fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                correction = ml - (int)(start2 - ip);
4545871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet                if (correction > 0) {
455fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    start2 += correction;
456fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ref2 += correction;
457fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ml2 -= correction;
458fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                }
4595871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet            } else {
460fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml = (int)(start2 - ip);
461fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
462fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
463fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
464fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
465fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ip = start2;
466fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref = ref2;
467fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml = ml2;
468fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
469fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        start2 = start3;
470fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref2 = ref3;
471fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml2 = ml3;
472fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
473fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        goto _Search3;
474fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
475fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
47669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Last Literals */
4775871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    {   int lastRun = (int)(iend - anchor);
47869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */
479fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
480fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else *op++ = (BYTE)(lastRun<<ML_BITS);
481fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        memcpy(op, anchor, iend - anchor);
482fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        op += iend-anchor;
483fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
484fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
48569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* End */
486fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return (int) (((char*)op)-dest);
487fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
488fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
4891c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinskistatic int LZ4HC_getSearchNum(int compressionLevel)
4901c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski{
4911c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski    switch (compressionLevel) {
4921c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski        default: return 0; /* unused */
4931c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski        case 11: return 128;
4941c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski        case 12: return 1<<10;
4951c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski    }
4961c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski}
497fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
498c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinskistatic int LZ4HC_compress_generic (
499c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    LZ4HC_CCtx_internal* const ctx,
500c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    const char* const source,
501c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    char* const dest,
502c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    int const inputSize,
503c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    int const maxOutputSize,
504c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    int compressionLevel,
505c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    limitedOutput_directive limit
506c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    )
507c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski{
50852cac9a97342641315c76cfb861206d6acd631a8Yann Collet    if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT;
509e3fee94742f9027aa2d27fae6458ce285889552ePrzemyslaw Skibinski    if (compressionLevel > 9) {
510c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski        switch (compressionLevel) {
511e3fee94742f9027aa2d27fae6458ce285889552ePrzemyslaw Skibinski            case 10: return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (16-1), limit);
5121c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski            case 11: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, 128, 0);
5132113ead176e0032c7ba04aa93f3bcc3d04ba6142Przemyslaw Skibinski            default:
5141c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski            case 12: ctx->searchNum = LZ4HC_getSearchNum(compressionLevel); return LZ4HC_compress_optimal(ctx, source, dest, inputSize, maxOutputSize, limit, LZ4_OPT_NUM, 1);
515c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski        }
516c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski    }
517e3fee94742f9027aa2d27fae6458ce285889552ePrzemyslaw Skibinski    return LZ4HC_compress_hashChain(ctx, source, dest, inputSize, maxOutputSize, 1 << (compressionLevel-1), limit);
518c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski}
519c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski
520c1ef7a177fae1f5435f191cbdebb0c59fb81d8ffPrzemyslaw Skibinski
52194542d845884c922f809725807ecbd2cf7454aceYann Colletint LZ4_sizeofStateHC(void) { return sizeof(LZ4_streamHC_t); }
522fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
523e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
524fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
525874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
52669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */
52785aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4HC_init (ctx, (const BYTE*)src);
528e05088d0eb500d8d673e081929620e538df3d718Yann Collet    if (maxDstSize < LZ4_compressBound(srcSize))
52985aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell        return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
530be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    else
53185aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell        return LZ4HC_compress_generic (ctx, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
532fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
533fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
534e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
535fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
53694542d845884c922f809725807ecbd2cf7454aceYann Collet#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
53784b97f90b81195590700fb791b83165d9e8cc1cdYann Collet    LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t));
5382c80138121550c719cb0a622f6a8a304d283960cYann Collet#else
53985aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4_streamHC_t state;
54085aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4_streamHC_t* const statePtr = &state;
5412c80138121550c719cb0a622f6a8a304d283960cYann Collet#endif
54294542d845884c922f809725807ecbd2cf7454aceYann Collet    int const cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, maxDstSize, compressionLevel);
54394542d845884c922f809725807ecbd2cf7454aceYann Collet#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1
5442c80138121550c719cb0a622f6a8a304d283960cYann Collet    free(statePtr);
5452c80138121550c719cb0a622f6a8a304d283960cYann Collet#endif
5462c80138121550c719cb0a622f6a8a304d283960cYann Collet    return cSize;
547fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
548fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
549fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
55065ee6b09c4392814167e7a039d9312aabdb5119bYann Collet
551d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/**************************************
5522a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Streaming Functions
5532a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet**************************************/
554d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* allocation */
555d239a23337e5eba41f557b48eb26f0db81b28f26Yann ColletLZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
556be9d248851ecd712a8911526b009c5d0c948ee21Yann Colletint             LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
557fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
558d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
559d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* initialization */
560d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletvoid LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
561fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
562874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4_STATIC_ASSERT(sizeof(LZ4HC_CCtx_internal) <= sizeof(size_t) * LZ4_STREAMHCSIZE_SIZET);   /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
56385aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4_streamHCPtr->internal_donotuse.base = NULL;
56485aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned)compressionLevel;
5651c80b9af4edf94f93582d40bae0856d13eacbf11Przemyslaw Skibinski    LZ4_streamHCPtr->internal_donotuse.searchNum = LZ4HC_getSearchNum(compressionLevel);
56669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.}
56769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
568d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
56969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{
570874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
5715871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    if (dictSize > 64 KB) {
57261289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        dictionary += dictSize - 64 KB;
57361289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        dictSize = 64 KB;
57461289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    }
57565ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
57665ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->end = (const BYTE*)dictionary + dictSize;
57712aae846b3006d7cd76a1197992eab1a0e995466Przemyslaw Skibinski    if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
57812aae846b3006d7cd76a1197992eab1a0e995466Przemyslaw Skibinski        LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
57912aae846b3006d7cd76a1197992eab1a0e995466Przemyslaw Skibinski    else
58012aae846b3006d7cd76a1197992eab1a0e995466Przemyslaw Skibinski        if (dictSize >= 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);
58161289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    return dictSize;
582d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
583d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
584d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
585d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* compression */
586d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
587874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Colletstatic void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)
58865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet{
58952cac9a97342641315c76cfb861206d6acd631a8Yann Collet    if (ctxPtr->compressionLevel >= LZ4HC_CLEVEL_OPT_MIN)
5904f050b68d817776e3c1fac6c449b5f2b2adfbcb9Przemyslaw Skibinski        LZ4HC_updateBinTree(ctxPtr, ctxPtr->end - MFLIMIT, ctxPtr->end - LASTLITERALS);
5914f050b68d817776e3c1fac6c449b5f2b2adfbcb9Przemyslaw Skibinski    else
5924f050b68d817776e3c1fac6c449b5f2b2adfbcb9Przemyslaw Skibinski        if (ctxPtr->end >= ctxPtr->base + 4) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */
593838ed341f94aa68c0bce8ee181e33a87274d2202Przemyslaw Skibinski
59465ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
59565ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->lowLimit  = ctxPtr->dictLimit;
59665ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
59765ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->dictBase  = ctxPtr->base;
59865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->base = newBlock - ctxPtr->dictLimit;
59965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->end  = newBlock;
600312d88249feee4c1b7511ac9fffce10ed6802ba7Przemyslaw Skibinski    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */
60165ee6b09c4392814167e7a039d9312aabdb5119bYann Collet}
60265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet
60385aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrellstatic int LZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,
604e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet                                            const char* source, char* dest,
605e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet                                            int inputSize, int maxOutputSize, limitedOutput_directive limit)
606e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet{
607874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
608e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet    /* auto-init if forgotten */
6095871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    if (ctxPtr->base == NULL) LZ4HC_init (ctxPtr, (const BYTE*) source);
610e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
611508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check overflow */
6125871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {
61365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
614508855c48826aa0544a907f02b52515aabba5e16Yann Collet        if (dictSize > 64 KB) dictSize = 64 KB;
61585aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell        LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
616508855c48826aa0544a907f02b52515aabba5e16Yann Collet    }
617508855c48826aa0544a907f02b52515aabba5e16Yann Collet
618508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check if blocks follow each other */
6195871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    if ((const BYTE*)source != ctxPtr->end) LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
620e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
621508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check overlapping input/dictionary space */
6225871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    {   const BYTE* sourceEnd = (const BYTE*) source + inputSize;
6235871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
6245871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        const BYTE* const dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;
6255871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet        if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) {
6262b421e97d4e7cfbefdc007bf30133b0de7e7e14eYann Collet            if (sourceEnd > dictEnd) sourceEnd = dictEnd;
62765ee6b09c4392814167e7a039d9312aabdb5119bYann Collet            ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
62865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet            if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
629e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet        }
630e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet    }
631e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
63265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
633e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet}
634e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
635e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
636d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
637be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    if (maxOutputSize < LZ4_compressBound(inputSize))
63885aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell        return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
639be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    else
64085aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell        return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
641d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
642d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
643d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
644d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* dictionary saving */
645d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
646d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
647d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
648874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
6495871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    int const prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
650d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    if (dictSize > 64 KB) dictSize = 64 KB;
65161289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    if (dictSize < 4) dictSize = 0;
65261289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    if (dictSize > prefixSize) dictSize = prefixSize;
65381fdd9df23821d5db8331e66478e2617b470820cYann Collet    memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
6545871585b6a28c6582d1626b8d07bb1a53a4cbd9dYann Collet    {   U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
65561289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->end = (const BYTE*)safeBuffer + dictSize;
65661289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->base = streamPtr->end - endIndex;
65761289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->dictLimit = endIndex - dictSize;
65861289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->lowLimit = endIndex - dictSize;
65995cc6cef6444b202a93ba414b7a9996eb2c72ca3Yann Collet        if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
66061289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    }
661d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return dictSize;
662fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
663fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
664d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
665d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/***********************************
6662a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Deprecated Functions
6672a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet***********************************/
66894542d845884c922f809725807ecbd2cf7454aceYann Collet/* These functions currently generate deprecation warnings */
669be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet/* Deprecated compression functions */
670e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
671e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
672e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
673e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
674e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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); }
675e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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); }
676e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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); }
677e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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); }
678e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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)); }
679e05088d0eb500d8d673e081929620e538df3d718Yann Colletint 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); }
680be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet
681be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet
682be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet/* Deprecated streaming functions */
683d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
684d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
6851c3e633c48766c58df949887297dc5838170a33fYann Colletint LZ4_resetStreamStateHC(void* state, char* inputBuffer)
686d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
687874f3e095b1d64ab3545a3f2a3f7403a44ebb3bbYann Collet    LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;
688d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1;   /* Error : pointer is not aligned for pointer (32 or 64 bits) */
68985aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4HC_init(ctx, (const BYTE*)inputBuffer);
69085aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    ctx->inputBuffer = (BYTE*)inputBuffer;
691d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return 0;
692d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
693d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
6941c3e633c48766c58df949887297dc5838170a33fYann Colletvoid* LZ4_createHC (char* inputBuffer)
695d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
69685aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4_streamHC_t* hc4 = (LZ4_streamHC_t*)ALLOCATOR(1, sizeof(LZ4_streamHC_t));
697aa1350e1399c808d2de83668249fff83fe70a24eYann Collet    if (hc4 == NULL) return NULL;   /* not enough memory */
69885aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    LZ4HC_init (&hc4->internal_donotuse, (const BYTE*)inputBuffer);
69985aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    hc4->internal_donotuse.inputBuffer = (BYTE*)inputBuffer;
700d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return hc4;
701d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
702d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
70394542d845884c922f809725807ecbd2cf7454aceYann Colletint LZ4_freeHC (void* LZ4HC_Data) { FREEMEM(LZ4HC_Data); return 0; }
704d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
705d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
706d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
70785aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, 0, compressionLevel, noLimit);
708d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
709fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
71069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
71169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{
71285aeb0e4bb9c0b8dd6f6caa00ac2d9c7a4452660Nick Terrell    return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
71369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.}
714d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
715d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletchar* LZ4_slideInputBufferHC(void* LZ4HC_Data)
716d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
71794542d845884c922f809725807ecbd2cf7454aceYann Collet    LZ4HC_CCtx_internal* const hc4 = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;
71894542d845884c922f809725807ecbd2cf7454aceYann Collet    int const dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
71965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    return (char*)(hc4->inputBuffer + dictSize);
720d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
721