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