lz4hc.c revision 1c3e633c48766c58df949887297dc5838170a33f
1fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet./*
22a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    LZ4 HC - High Compression Mode of LZ4
32a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    Copyright (C) 2011-2015, 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 :
312a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet       - LZ4 source repository : https://github.com/Cyan4973/lz4
322a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet       - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.*/
34fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
3569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
3669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
3769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
382a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Tuning Parameter
3969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
40002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Colletstatic const int LZ4HC_compressionLevel_default = 9;
4169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
4269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
4369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
442a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Includes
4569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
4633dca250ee0afa3aec58bf3bf1a34b09bebf3fb5Yann Collet#include "lz4hc.h"
47fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
48fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
4969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
502a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Compiler Options
5169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
52326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#if defined(__GNUC__)
53326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#  pragma GCC diagnostic ignored "-Wunused-function"
54fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#endif
55fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
56326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#if defined (__clang__)
57326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#  pragma clang diagnostic ignored "-Wunused-function"
58fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#endif
59fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
60fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
61326cada9fadeedccef8934e11144f343ecdcabcbYann Collet/**************************************
622a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Common LZ4 definition
63326cada9fadeedccef8934e11144f343ecdcabcbYann Collet**************************************/
64326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#define LZ4_COMMONDEFS_ONLY
65326cada9fadeedccef8934e11144f343ecdcabcbYann Collet#include "lz4.c"
66fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
67fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
6869dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
692a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Constants
7069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
71fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define DICTIONARY_LOGSIZE 16
72fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define MAXD (1<<DICTIONARY_LOGSIZE)
732a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet#define MAXD_MASK (MAXD - 1)
74fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
75fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define HASH_LOG (DICTIONARY_LOGSIZE-1)
76fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define HASHTABLESIZE (1 << HASH_LOG)
77fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define HASH_MASK (HASHTABLESIZE - 1)
78fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
79fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
80fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
81c5decf7562a3b4065922ae6460b7785eb91366f8Yann Colletstatic const int g_maxCompressionLevel = 16;
82c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet
83fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
8469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
852a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Types
8669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
87fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.typedef struct
88fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
892a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    U32   hashTable[HASHTABLESIZE];
90d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U16   chainTable[MAXD];
9133dca250ee0afa3aec58bf3bf1a34b09bebf3fb5Yann Collet    const BYTE* end;        /* next block here to continue on current prefix */
9261289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    const BYTE* base;       /* All index relative to this position */
9361289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    const BYTE* dictBase;   /* alternate base for extDict */
941c3e633c48766c58df949887297dc5838170a33fYann Collet    BYTE* inputBuffer;      /* deprecated */
9561289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    U32   dictLimit;        /* below that point, need extDict */
9661289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    U32   lowLimit;         /* below that point, no more dict */
972a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet    U32   nextToUpdate;     /* index from which to continue dictionary update */
98d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32   compressionLevel;
99fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.} LZ4HC_Data_Structure;
100fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
101fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
10269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./**************************************
1032a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Local Macros
10469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.**************************************/
105fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.#define HASH_FUNCTION(i)       (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
1062a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet//#define DELTANEXTU16(p)        chainTable[(p) & MAXD_MASK]   /* flexible, MAXD dependent */
1072a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet#define DELTANEXTU16(p)        chainTable[(U16)(p)]   /* faster */
108fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
109326cada9fadeedccef8934e11144f343ecdcabcbYann Colletstatic U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
110fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
111fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
112fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
113326cada9fadeedccef8934e11144f343ecdcabcbYann Collet/**************************************
1142a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  HC Compression
115326cada9fadeedccef8934e11144f343ecdcabcbYann Collet**************************************/
11665ee6b09c4392814167e7a039d9312aabdb5119bYann Colletstatic void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start)
117fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
118fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
119fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
120e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    hc4->nextToUpdate = 64 KB;
12165ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->base = start - 64 KB;
12265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->end = start;
12365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    hc4->dictBase = start - 64 KB;
124e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    hc4->dictLimit = 64 KB;
125e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    hc4->lowLimit = 64 KB;
126fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
127fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
128fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
12969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet./* Update chains up to ip (excluded) */
130fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
131fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
132d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U16* chainTable = hc4->chainTable;
133d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32* HashTable  = hc4->hashTable;
134d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
1353dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    const U32 target = (U32)(ip - base);
136d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32 idx = hc4->nextToUpdate;
137fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
138d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    while(idx < target)
139fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    {
1403dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        U32 h = LZ4HC_hashPtr(base+idx);
141d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet        size_t delta = idx - HashTable[h];
142fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
1432a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        DELTANEXTU16(idx) = (U16)delta;
144d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet        HashTable[h] = idx;
145d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet        idx++;
146fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
1477ac18ad9dc5a5555f9129659c007fe9141e422b0Yann Collet
148d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    hc4->nextToUpdate = target;
149fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
150fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
151fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
1528a9fb8cf3229c9a704c982667c63ac440b8487baYann ColletFORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4,   /* Index table will be updated */
153508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const BYTE* ip, const BYTE* const iLimit,
154508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const BYTE** matchpos,
155508855c48826aa0544a907f02b52515aabba5e16Yann Collet                                               const int maxNbAttempts)
156fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
157fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    U16* const chainTable = hc4->chainTable;
158d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32* const HashTable = hc4->hashTable;
159d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
160e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    const BYTE* const dictBase = hc4->dictBase;
161e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    const U32 dictLimit = hc4->dictLimit;
162508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
163e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    U32 matchIndex;
164d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* match;
16569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    int nbAttempts=maxNbAttempts;
166d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    size_t ml=0;
167fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
168508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* HC4 match finder */
169fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    LZ4HC_Insert(hc4, ip);
1703dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
171fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
172e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    while ((matchIndex>=lowLimit) && (nbAttempts))
173fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    {
174fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        nbAttempts--;
1753dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        if (matchIndex >= dictLimit)
176fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
1773dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            match = base + matchIndex;
1783dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            if (*(match+ml) == *(ip+ml)
179326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                && (LZ4_read32(match) == LZ4_read32(ip)))
1803dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            {
181326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                size_t mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
1823dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (mlt > ml) { ml = mlt; *matchpos = match; }
1833dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            }
1843dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        }
1853dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        else
1863dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        {
1873dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            match = dictBase + matchIndex;
188326cada9fadeedccef8934e11144f343ecdcabcbYann Collet            if (LZ4_read32(match) == LZ4_read32(ip))
1893dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            {
1903dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                size_t mlt;
1913dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                const BYTE* vLimit = ip + (dictLimit - matchIndex);
1923dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (vLimit > iLimit) vLimit = iLimit;
193326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
1943dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((ip+mlt == vLimit) && (vLimit < iLimit))
195326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                    mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
1968a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */
1973dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet            }
198fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
1992a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        matchIndex -= DELTANEXTU16(matchIndex);
200fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
201fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
202fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return (int)ml;
203fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
204fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
205fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
206d239a23337e5eba41f557b48eb26f0db81b28f26Yann ColletFORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
207508855c48826aa0544a907f02b52515aabba5e16Yann Collet    LZ4HC_Data_Structure* hc4,
208002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const ip,
209002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const iLowLimit,
210002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const iHighLimit,
211508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int longest,
212508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** matchpos,
213508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** startpos,
214508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const int maxNbAttempts)
215fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
216d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U16* const chainTable = hc4->chainTable;
217d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    U32* const HashTable = hc4->hashTable;
218d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    const BYTE* const base = hc4->base;
2193dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    const U32 dictLimit = hc4->dictLimit;
220002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet    const BYTE* const lowPrefixPtr = base + dictLimit;
221508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
2223dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    const BYTE* const dictBase = hc4->dictBase;
2233dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    U32   matchIndex;
22469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    int nbAttempts = maxNbAttempts;
2253dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    int delta = (int)(ip-iLowLimit);
226fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
227e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet
228508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* First Match */
229fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    LZ4HC_Insert(hc4, ip);
2303dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet    matchIndex = HashTable[LZ4HC_hashPtr(ip)];
231fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
232e450018588560537c2c4b4b2dd3515a9ef3a83f7Yann Collet    while ((matchIndex>=lowLimit) && (nbAttempts))
233fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    {
234fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        nbAttempts--;
2353dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        if (matchIndex >= dictLimit)
236fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
237002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet            const BYTE* matchPtr = base + matchIndex;
238002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet            if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
239002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                if (LZ4_read32(matchPtr) == LZ4_read32(ip))
240508855c48826aa0544a907f02b52515aabba5e16Yann Collet                {
241002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
242002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    int back = 0;
243002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet
244002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    while ((ip+back>iLowLimit)
245002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                           && (matchPtr+back > lowPrefixPtr)
246002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                           && (ip[back-1] == matchPtr[back-1]))
247002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                            back--;
248fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
249002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    mlt -= back;
250fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
251002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                    if (mlt > longest)
252508855c48826aa0544a907f02b52515aabba5e16Yann Collet                    {
253002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        longest = (int)mlt;
254002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        *matchpos = matchPtr+back;
255002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                        *startpos = ip+back;
256508855c48826aa0544a907f02b52515aabba5e16Yann Collet                    }
2573dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                }
2583dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        }
2593dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        else
2603dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet        {
261002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet            const BYTE* matchPtr = dictBase + matchIndex;
262002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet            if (LZ4_read32(matchPtr) == LZ4_read32(ip))
263fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
2643dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                size_t mlt;
265508855c48826aa0544a907f02b52515aabba5e16Yann Collet                int back=0;
2663dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                const BYTE* vLimit = ip + (dictLimit - matchIndex);
2673dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if (vLimit > iHighLimit) vLimit = iHighLimit;
268002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
2693dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
270326cada9fadeedccef8934e11144f343ecdcabcbYann Collet                    mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
271002ec60f0feadc07a25a6f18a7b2b4ace3c1b718Yann Collet                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
272508855c48826aa0544a907f02b52515aabba5e16Yann Collet                mlt -= back;
2733dab5f476a2e5a0cd4cd9a859e94a5110abda23dYann Collet                if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
274fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
275fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
2762a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet        matchIndex -= DELTANEXTU16(matchIndex);
277fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
278fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
279fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return longest;
280fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
281fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
282fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
283fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
284fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
2858a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#define LZ4HC_DEBUG 0
2868a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#if LZ4HC_DEBUG
2878a9fb8cf3229c9a704c982667c63ac440b8487baYann Colletstatic unsigned debug = 0;
2888a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#endif
289508855c48826aa0544a907f02b52515aabba5e16Yann Collet
290fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.FORCE_INLINE int LZ4HC_encodeSequence (
291508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** ip,
292508855c48826aa0544a907f02b52515aabba5e16Yann Collet    BYTE** op,
293508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE** anchor,
294508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int matchLength,
295508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const BYTE* const match,
296508855c48826aa0544a907f02b52515aabba5e16Yann Collet    limitedOutput_directive limitedOutputBuffer,
297508855c48826aa0544a907f02b52515aabba5e16Yann Collet    BYTE* oend)
298fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
299fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    int length;
300fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* token;
301fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
3028a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#if LZ4HC_DEBUG
3038a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet    if (debug) printf("literal : %u  --  match : %u  --  offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
3048a9fb8cf3229c9a704c982667c63ac440b8487baYann Collet#endif
305e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet
30669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Literal length */
307fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    length = (int)(*ip - *anchor);
308fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    token = (*op)++;
309e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1;   /* Check output limit */
310fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.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; }
311fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    else *token = (BYTE)(length<<ML_BITS);
312fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
31369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Copy Literals */
314326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    LZ4_wildCopy(*op, *anchor, (*op) + length);
315326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    *op += length;
316fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
31769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Offset */
318326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
319fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
32069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode MatchLength */
321fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    length = (int)(matchLength-MINMATCH);
322e2a985f52444ad2e1438d2a71575185f31a08540Yann Collet    if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1;   /* Check output limit */
323fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }
324fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    else *token += (BYTE)(length);
325fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
32669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Prepare next loop */
327fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    *ip += matchLength;
328fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    *anchor = *ip;
329fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
330fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return 0;
331fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
332fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
333fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
334fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.static int LZ4HC_compress_generic (
335508855c48826aa0544a907f02b52515aabba5e16Yann Collet    void* ctxvoid,
336508855c48826aa0544a907f02b52515aabba5e16Yann Collet    const char* source,
337508855c48826aa0544a907f02b52515aabba5e16Yann Collet    char* dest,
338508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int inputSize,
339508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int maxOutputSize,
340508855c48826aa0544a907f02b52515aabba5e16Yann Collet    int compressionLevel,
341508855c48826aa0544a907f02b52515aabba5e16Yann Collet    limitedOutput_directive limit
342508855c48826aa0544a907f02b52515aabba5e16Yann Collet    )
343fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
344fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid;
345fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ip = (const BYTE*) source;
346fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* anchor = ip;
347fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const iend = ip + inputSize;
348fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const mflimit = iend - MFLIMIT;
349fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* const matchlimit = (iend - LASTLITERALS);
350fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
351fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* op = (BYTE*) dest;
352fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    BYTE* const oend = op + maxOutputSize;
353fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
354d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    unsigned maxNbAttempts;
355fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    int   ml, ml2, ml3, ml0;
356fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ref=NULL;
357fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* start2=NULL;
358fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ref2=NULL;
359fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* start3=NULL;
360fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ref3=NULL;
361fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* start0;
362fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    const BYTE* ref0;
363fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
364fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
365d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    /* init */
366c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet    if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel;
367c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet    if (compressionLevel < 1) compressionLevel = LZ4HC_compressionLevel_default;
368c5decf7562a3b4065922ae6460b7785eb91366f8Yann Collet    maxNbAttempts = 1 << (compressionLevel-1);
369fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    ctx->end += inputSize;
370fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
371fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    ip++;
372fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
37369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Main Loop */
374fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    while (ip < mflimit)
375fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    {
37669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
377fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (!ml) { ip++; continue; }
378fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
37969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* saved, in case we would skip too much */
380fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        start0 = ip;
381fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref0 = ref;
382fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml0 = ml;
383fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
384fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet._Search2:
385fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (ip+ml < mflimit)
38669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts);
387fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else ml2 = ml;
388fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
38969dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if (ml2 == ml)  /* No better match */
390fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
391fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
392fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            continue;
393fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
394fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
395fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (start0 < ip)
396fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
39769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            if (start2 < ip + ml0)   /* empirical */
398fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
399fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ip = start0;
400fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref = ref0;
401fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml = ml0;
402fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
403fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
404fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
40569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* Here, start0==ip */
40669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if ((start2 - ip) < 3)   /* First Match too small : removed */
407fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
408fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ml = ml2;
409fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ip = start2;
410fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ref =ref2;
411fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            goto _Search2;
412fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
413fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
414fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet._Search3:
41569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /*
416508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * Currently we have :
417508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ml2 > ml1, and
418508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ip1+3 <= ip2 (usually < ip1+ml1)
419508855c48826aa0544a907f02b52515aabba5e16Yann Collet        */
420fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if ((start2 - ip) < OPTIMAL_ML)
421fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
422fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            int correction;
423fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            int new_ml = ml;
424fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
425fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
426fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            correction = new_ml - (int)(start2 - ip);
427fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (correction > 0)
428fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
429fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                start2 += correction;
430fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref2 += correction;
431fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml2 -= correction;
432fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
433fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
43469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
435fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
436fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (start2 + ml2 < mflimit)
43769dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
438fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else ml3 = ml2;
439fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
44069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if (ml3 == ml2) /* No better match : 2 sequences to encode */
441fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
44269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            /* ip & ref are known; Now for ml */
443fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (start2 < ip+ml)  ml = (int)(start2 - ip);
44469dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            /* Now, encode 2 sequences */
445fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
446fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ip = start2;
447fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
448fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            continue;
449fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
450fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
45169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */
452fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
45369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.            if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
454fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
455fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (start2 < ip+ml)
456fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                {
457fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    int correction = (int)(ip+ml - start2);
458fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    start2 += correction;
459fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ref2 += correction;
460fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ml2 -= correction;
461fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    if (ml2 < MINMATCH)
462fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    {
463fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        start2 = start3;
464fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        ref2 = ref3;
465fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                        ml2 = ml3;
466fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    }
467fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                }
468fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
469fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
470fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ip  = start3;
471fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref = ref3;
472fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml  = ml3;
473fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
474fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                start0 = start2;
475fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ref0 = ref2;
476fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml0 = ml2;
477fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                goto _Search2;
478fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
479fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
480fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            start2 = start3;
481fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ref2 = ref3;
482fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            ml2 = ml3;
483fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            goto _Search3;
484fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
485fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
48669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        /*
487508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * OK, now we have 3 ascending matches; let's write at least the first one
488508855c48826aa0544a907f02b52515aabba5e16Yann Collet        * ip & ref are known; Now for ml
489508855c48826aa0544a907f02b52515aabba5e16Yann Collet        */
490fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (start2 < ip+ml)
491fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        {
492fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            if ((start2 - ip) < (int)ML_MASK)
493fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
494fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                int correction;
495fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
496fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
497fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                correction = ml - (int)(start2 - ip);
498fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                if (correction > 0)
499fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                {
500fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    start2 += correction;
501fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ref2 += correction;
502fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                    ml2 -= correction;
503fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                }
504fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
505fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            else
506fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            {
507fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.                ml = (int)(start2 - ip);
508fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.            }
509fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        }
510fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
511fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
512fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ip = start2;
513fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref = ref2;
514fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml = ml2;
515fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
516fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        start2 = start3;
517fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ref2 = ref3;
518fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        ml2 = ml3;
519fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
520fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        goto _Search3;
521fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
522fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
52369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* Encode Last Literals */
524fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    {
525fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        int lastRun = (int)(iend - anchor);
52669dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */
527fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
528fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        else *op++ = (BYTE)(lastRun<<ML_BITS);
529fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        memcpy(op, anchor, iend - anchor);
530fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.        op += iend-anchor;
531fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    }
532fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
53369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    /* End */
534fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.    return (int) (((char*)op)-dest);
535fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
536fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
537fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
538e2a985f52444ad2e1438d2a71575185f31a08540Yann Colletint LZ4_sizeofStateHC(void) { return sizeof(LZ4HC_Data_Structure); }
539fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
540e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
541fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
54269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */
543e05088d0eb500d8d673e081929620e538df3d718Yann Collet    LZ4HC_init ((LZ4HC_Data_Structure*)state, (const BYTE*)src);
544e05088d0eb500d8d673e081929620e538df3d718Yann Collet    if (maxDstSize < LZ4_compressBound(srcSize))
545e05088d0eb500d8d673e081929620e538df3d718Yann Collet        return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
546be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    else
547e05088d0eb500d8d673e081929620e538df3d718Yann Collet        return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
548fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
549fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
550e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
551fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
552be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    LZ4HC_Data_Structure state;
553e05088d0eb500d8d673e081929620e538df3d718Yann Collet    return LZ4_compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel);
554fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
555fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
556fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
55765ee6b09c4392814167e7a039d9312aabdb5119bYann Collet
558d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/**************************************
5592a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Streaming Functions
5602a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet**************************************/
561d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* allocation */
562d239a23337e5eba41f557b48eb26f0db81b28f26Yann ColletLZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
563be9d248851ecd712a8911526b009c5d0c948ee21Yann Colletint             LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
564fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
565d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
566d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* initialization */
567d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletvoid LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
568fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.{
569a357f434f06de70e5d670b8669becccb09f4c7a6Yann Collet    LZ4_STATIC_ASSERT(sizeof(LZ4HC_Data_Structure) <= sizeof(LZ4_streamHC_t));   /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
570d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->base = NULL;
571d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->compressionLevel = (unsigned)compressionLevel;
57269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.}
57369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.
574d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
57569dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{
57665ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    LZ4HC_Data_Structure* ctxPtr = (LZ4HC_Data_Structure*) LZ4_streamHCPtr;
57761289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    if (dictSize > 64 KB)
57861289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    {
57961289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        dictionary += dictSize - 64 KB;
58061289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        dictSize = 64 KB;
58161289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    }
58265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
58365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    if (dictSize >= 4) LZ4HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));
58465ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->end = (const BYTE*)dictionary + dictSize;
58561289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    return dictSize;
586d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
587d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
588d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
589d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* compression */
590d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
59165ee6b09c4392814167e7a039d9312aabdb5119bYann Colletstatic void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newBlock)
59265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet{
59365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    if (ctxPtr->end >= ctxPtr->base + 4)
59465ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        LZ4HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */
59565ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
59665ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->lowLimit  = ctxPtr->dictLimit;
59765ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
59865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->dictBase  = ctxPtr->base;
59965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->base = newBlock - ctxPtr->dictLimit;
60065ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->end  = newBlock;
60165ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */
60265ee6b09c4392814167e7a039d9312aabdb5119bYann Collet}
60365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet
60465ee6b09c4392814167e7a039d9312aabdb5119bYann Colletstatic int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr,
605e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet                                            const char* source, char* dest,
606e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet                                            int inputSize, int maxOutputSize, limitedOutput_directive limit)
607e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet{
608e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet    /* auto-init if forgotten */
60965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    if (ctxPtr->base == NULL)
61065ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        LZ4HC_init (ctxPtr, (const BYTE*) source);
611e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
612508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check overflow */
61365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
614508855c48826aa0544a907f02b52515aabba5e16Yann Collet    {
61565ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
616508855c48826aa0544a907f02b52515aabba5e16Yann Collet        if (dictSize > 64 KB) dictSize = 64 KB;
617508855c48826aa0544a907f02b52515aabba5e16Yann Collet
61865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        LZ4_loadDictHC((LZ4_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
619508855c48826aa0544a907f02b52515aabba5e16Yann Collet    }
620508855c48826aa0544a907f02b52515aabba5e16Yann Collet
621508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check if blocks follow each other */
622d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet    if ((const BYTE*)source != ctxPtr->end)
623d6dc0a410d0be93551f247eeb871603d2db11c17Yann Collet        LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
624e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
625508855c48826aa0544a907f02b52515aabba5e16Yann Collet    /* Check overlapping input/dictionary space */
626e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet    {
627e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet        const BYTE* sourceEnd = (const BYTE*) source + inputSize;
62865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
62965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet        const BYTE* dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;
6301c3e633c48766c58df949887297dc5838170a33fYann Collet        if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))
631e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet        {
6322b421e97d4e7cfbefdc007bf30133b0de7e7e14eYann Collet            if (sourceEnd > dictEnd) sourceEnd = dictEnd;
63365ee6b09c4392814167e7a039d9312aabdb5119bYann Collet            ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
63465ee6b09c4392814167e7a039d9312aabdb5119bYann Collet            if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
635e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet        }
636e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet    }
637e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
63865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
639e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet}
640e2c84118f52cefe48fd2f751e66ad3ecd904f7b9Yann Collet
641e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
642d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
643be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    if (maxOutputSize < LZ4_compressBound(inputSize))
644be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet        return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
645be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet    else
646be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet        return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
647d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
648d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
649d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
650d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/* dictionary saving */
651d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
652d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
653d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
65461289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    LZ4HC_Data_Structure* streamPtr = (LZ4HC_Data_Structure*)LZ4_streamHCPtr;
65561289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
656d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    if (dictSize > 64 KB) dictSize = 64 KB;
65761289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    if (dictSize < 4) dictSize = 0;
65861289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    if (dictSize > prefixSize) dictSize = prefixSize;
65981fdd9df23821d5db8331e66478e2617b470820cYann Collet    memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
66061289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    {
66161289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        U32 endIndex = (U32)(streamPtr->end - streamPtr->base);
66261289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->end = (const BYTE*)safeBuffer + dictSize;
66361289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->base = streamPtr->end - endIndex;
66461289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->dictLimit = endIndex - dictSize;
66561289dea1d94510a4d6386bc44c08d3d15083123Yann Collet        streamPtr->lowLimit = endIndex - dictSize;
66695cc6cef6444b202a93ba414b7a9996eb2c72ca3Yann Collet        if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
66761289dea1d94510a4d6386bc44c08d3d15083123Yann Collet    }
668d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return dictSize;
669fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.}
670fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
671d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
672d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet/***********************************
6732a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet*  Deprecated Functions
6742a974d73c35476eb66275dd0d9448a6efa51bf56Yann Collet***********************************/
675be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet/* Deprecated compression functions */
676b805d581b97be95fcc000134a54aa7c591b3ef09Yann Collet/* These functions are planned to start generate warnings by r131 approximately */
677e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
678e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
679e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
680e05088d0eb500d8d673e081929620e538df3d718Yann Colletint LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
681e05088d0eb500d8d673e081929620e538df3d718Yann 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); }
682e05088d0eb500d8d673e081929620e538df3d718Yann 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); }
683e05088d0eb500d8d673e081929620e538df3d718Yann 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); }
684e05088d0eb500d8d673e081929620e538df3d718Yann 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); }
685e05088d0eb500d8d673e081929620e538df3d718Yann 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)); }
686e05088d0eb500d8d673e081929620e538df3d718Yann 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); }
687be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet
688be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet
689be9d248851ecd712a8911526b009c5d0c948ee21Yann Collet/* Deprecated streaming functions */
690e05088d0eb500d8d673e081929620e538df3d718Yann Collet/* These functions currently generate deprecation warnings */
691d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
692d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
6931c3e633c48766c58df949887297dc5838170a33fYann Colletint LZ4_resetStreamStateHC(void* state, char* inputBuffer)
694d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
695d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1;   /* Error : pointer is not aligned for pointer (32 or 64 bits) */
696d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    LZ4HC_init((LZ4HC_Data_Structure*)state, (const BYTE*)inputBuffer);
6971c3e633c48766c58df949887297dc5838170a33fYann Collet    ((LZ4HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer;
698d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return 0;
699d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
700d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
7011c3e633c48766c58df949887297dc5838170a33fYann Colletvoid* LZ4_createHC (char* inputBuffer)
702d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
703326cada9fadeedccef8934e11144f343ecdcabcbYann Collet    void* hc4 = ALLOCATOR(1, sizeof(LZ4HC_Data_Structure));
704d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    LZ4HC_init ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
7051c3e633c48766c58df949887297dc5838170a33fYann Collet    ((LZ4HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer;
706d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return hc4;
707d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
708d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
709d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_freeHC (void* LZ4HC_Data)
710d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
711d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    FREEMEM(LZ4HC_Data);
712d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return (0);
713d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
714d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
715d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletint LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
716d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
717d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, compressionLevel, noLimit);
718d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
719fb38ddaacb150e05b9d73c2a08d052ce746e37bayann.collet.
72069dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
72169dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.{
72269dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.    return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
72369dc85b8abe78246bea91a5ba1205e4c07b96a97yann.collet.}
724d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet
725d239a23337e5eba41f557b48eb26f0db81b28f26Yann Colletchar* LZ4_slideInputBufferHC(void* LZ4HC_Data)
726d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet{
727d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet    LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data;
72865ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    int dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
72965ee6b09c4392814167e7a039d9312aabdb5119bYann Collet    return (char*)(hc4->inputBuffer + dictSize);
730d239a23337e5eba41f557b48eb26f0db81b28f26Yann Collet}
731