CMSIS2000  0.0.7
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lz4hc.c
Go to the documentation of this file.
1 /*
2  LZ4 HC - High Compression Mode of LZ4
3  Copyright (C) 2011-2012, Yann Collet.
4  BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are
8  met:
9 
10  * Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above
13  copyright notice, this list of conditions and the following disclaimer
14  in the documentation and/or other materials provided with the
15  distribution.
16 
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29  You can contact the author at :
30  - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
31  - LZ4 source repository : http://code.google.com/p/lz4/
32 */
33 
34 
35 //**************************************
36 // CPU Feature Detection
37 //**************************************
38 // 32 or 64 bits ?
39 #if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || defined(__LP64__) || defined(_LP64) ) // Detects 64 bits mode
40 # define LZ4_ARCH64 1
41 #else
42 # define LZ4_ARCH64 0
43 #endif
44 
45 // Little Endian or Big Endian ?
46 // Overwrite the #define below if you know your architecture endianess
47 #if defined (__GLIBC__)
48 # include <endian.h>
49 # if (__BYTE_ORDER == __BIG_ENDIAN)
50 # define LZ4_BIG_ENDIAN 1
51 # endif
52 #elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))
53 # define LZ4_BIG_ENDIAN 1
54 #elif defined(__sparc) || defined(__sparc__) \
55  || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \
56  || defined(__hpux) || defined(__hppa) \
57  || defined(_MIPSEB) || defined(__s390__)
58 # define LZ4_BIG_ENDIAN 1
59 #else
60 // Little Endian assumed. PDP Endian and other very rare endian format are unsupported.
61 #endif
62 
63 // Unaligned memory access is automatically enabled for "common" CPU, such as x86.
64 // For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected
65 // If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance
66 #if defined(__ARM_FEATURE_UNALIGNED)
67 # define LZ4_FORCE_UNALIGNED_ACCESS 1
68 #endif
69 
70 // Define this parameter if your target system or compiler does not support hardware bit count
71 #if defined(_MSC_VER) && defined(_WIN32_WCE) // Visual Studio for Windows CE does not support Hardware bit count
72 # define LZ4_FORCE_SW_BITCOUNT
73 #endif
74 
75 
76 //**************************************
77 // Compiler Options
78 //**************************************
79 #if __STDC_VERSION__ >= 199901L // C99
80  /* "restrict" is a known keyword */
81 #else
82 # define restrict // Disable restrict
83 #endif
84 
85 #ifdef _MSC_VER
86 # define inline __inline // Visual is not C99, but supports some kind of inline
87 # define forceinline __forceinline
88 # include <intrin.h> // For Visual 2005
89 # if LZ4_ARCH64 // 64-bit
90 # pragma intrinsic(_BitScanForward64) // For Visual 2005
91 # pragma intrinsic(_BitScanReverse64) // For Visual 2005
92 # else
93 # pragma intrinsic(_BitScanForward) // For Visual 2005
94 # pragma intrinsic(_BitScanReverse) // For Visual 2005
95 # endif
96 #else
97 # ifdef __GNUC__
98 # define forceinline inline __attribute__((always_inline))
99 # else
100 # define forceinline inline
101 # endif
102 #endif
103 
104 #ifdef _MSC_VER // Visual Studio
105 #define lz4_bswap16(x) _byteswap_ushort(x)
106 #else
107 #define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)))
108 #endif
109 
110 
111 //**************************************
112 // Includes
113 //**************************************
114 #include <stdlib.h> // calloc, free
115 #include <string.h> // memset, memcpy
116 #include "lz4hc.h"
117 
118 #define ALLOCATOR(s) calloc(1,s)
119 #define FREEMEM free
120 #define MEM_INIT memset
121 
122 
123 //**************************************
124 // Basic Types
125 //**************************************
126 #if defined(_MSC_VER) // Visual Studio does not support 'stdint' natively
127 #define BYTE unsigned __int8
128 #define U16 unsigned __int16
129 #define U32 unsigned __int32
130 #define S32 __int32
131 #define U64 unsigned __int64
132 #else
133 #include <stdint.h>
134 #define BYTE uint8_t
135 #define U16 uint16_t
136 #define U32 uint32_t
137 #define S32 int32_t
138 #define U64 uint64_t
139 #endif
140 
141 #ifndef LZ4_FORCE_UNALIGNED_ACCESS
142 #pragma pack(push, 1)
143 #endif
144 
145 typedef struct _U16_S { U16 v; } U16_S;
146 typedef struct _U32_S { U32 v; } U32_S;
147 typedef struct _U64_S { U64 v; } U64_S;
148 
149 #ifndef LZ4_FORCE_UNALIGNED_ACCESS
150 #pragma pack(pop)
151 #endif
152 
153 #define A64(x) (((U64_S *)(x))->v)
154 #define A32(x) (((U32_S *)(x))->v)
155 #define A16(x) (((U16_S *)(x))->v)
156 
157 
158 //**************************************
159 // Constants
160 //**************************************
161 #define MINMATCH 4
162 
163 #define DICTIONARY_LOGSIZE 16
164 #define MAXD (1<<DICTIONARY_LOGSIZE)
165 #define MAXD_MASK ((U32)(MAXD - 1))
166 #define MAX_DISTANCE (MAXD - 1)
167 
168 #define HASH_LOG (DICTIONARY_LOGSIZE-1)
169 #define HASHTABLESIZE (1 << HASH_LOG)
170 #define HASH_MASK (HASHTABLESIZE - 1)
171 
172 #define MAX_NB_ATTEMPTS 256
173 
174 #define ML_BITS 4
175 #define ML_MASK (size_t)((1U<<ML_BITS)-1)
176 #define RUN_BITS (8-ML_BITS)
177 #define RUN_MASK ((1U<<RUN_BITS)-1)
178 
179 #define COPYLENGTH 8
180 #define LASTLITERALS 5
181 #define MFLIMIT (COPYLENGTH+MINMATCH)
182 #define MINLENGTH (MFLIMIT+1)
183 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
184 
185 
186 //**************************************
187 // Architecture-specific macros
188 //**************************************
189 #if LZ4_ARCH64 // 64-bit
190 #define STEPSIZE 8
191 #define LZ4_COPYSTEP(s,d) A64(d) = A64(s); d+=8; s+=8;
192 #define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d)
193 #define UARCH U64
194 #define AARCH A64
195 #define HTYPE U32
196 #define INITBASE(b,s) const BYTE* const b = s
197 #else // 32-bit
198 #define STEPSIZE 4
199 #define LZ4_COPYSTEP(s,d) A32(d) = A32(s); d+=4; s+=4;
200 #define LZ4_COPYPACKET(s,d) LZ4_COPYSTEP(s,d); LZ4_COPYSTEP(s,d);
201 #define UARCH U32
202 #define AARCH A32
203 #define HTYPE const BYTE*
204 #define INITBASE(b,s) const int b = 0
205 #endif
206 
207 #if defined(LZ4_BIG_ENDIAN)
208 #define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
209 #define LZ4_WRITE_LITTLEENDIAN_16(p,i) { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }
210 #else // Little Endian
211 #define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }
212 #define LZ4_WRITE_LITTLEENDIAN_16(p,v) { A16(p) = v; p+=2; }
213 #endif
214 
215 
216 //************************************************************
217 // Local Types
218 //************************************************************
219 typedef struct
220 {
221  const BYTE* base;
222  HTYPE hashTable[HASHTABLESIZE];
223  U16 chainTable[MAXD];
226 
227 
228 //**************************************
229 // Macros
230 //**************************************
231 #define LZ4_WILDCOPY(s,d,e) do { LZ4_COPYPACKET(s,d) } while (d<e);
232 #define LZ4_BLINDCOPY(s,d,l) { BYTE* e=d+l; LZ4_WILDCOPY(s,d,e); d=e; }
233 #define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
234 #define HASH_VALUE(p) HASH_FUNCTION(A32(p))
235 #define HASH_POINTER(p) (HashTable[HASH_VALUE(p)] + base)
236 #define DELTANEXT(p) chainTable[(size_t)(p) & MAXD_MASK]
237 #define GETNEXT(p) ((p) - (size_t)DELTANEXT(p))
238 
239 
240 //**************************************
241 // Private functions
242 //**************************************
243 #if LZ4_ARCH64
244 
245 inline static int LZ4_NbCommonBytes (register U64 val)
246 {
247 #if defined(LZ4_BIG_ENDIAN)
248  #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
249  unsigned long r = 0;
250  _BitScanReverse64( &r, val );
251  return (int)(r>>3);
252  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
253  return (__builtin_clzll(val) >> 3);
254  #else
255  int r;
256  if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
257  if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
258  r += (!val);
259  return r;
260  #endif
261 #else
262  #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
263  unsigned long r = 0;
264  _BitScanForward64( &r, val );
265  return (int)(r>>3);
266  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
267  return (__builtin_ctzll(val) >> 3);
268  #else
269  static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
270  return DeBruijnBytePos[((U64)((val & -val) * 0x0218A392CDABBD3F)) >> 58];
271  #endif
272 #endif
273 }
274 
275 #else
276 
277 inline static int LZ4_NbCommonBytes (register U32 val)
278 {
279 #if defined(LZ4_BIG_ENDIAN)
280  #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
281  unsigned long r;
282  _BitScanReverse( &r, val );
283  return (int)(r>>3);
284  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
285  return (__builtin_clz(val) >> 3);
286  #else
287  int r;
288  if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
289  r += (!val);
290  return r;
291  #endif
292 #else
293  #if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
294  unsigned long r;
295  _BitScanForward( &r, val );
296  return (int)(r>>3);
297  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
298  return (__builtin_ctz(val) >> 3);
299  #else
300  static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
301  return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
302  #endif
303 #endif
304 }
305 
306 #endif
307 
308 
309 inline static int LZ4HC_Init (LZ4HC_Data_Structure* hc4, const BYTE* base)
310 {
311  MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
312  MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
313  hc4->nextToUpdate = base + LZ4_ARCH64;
314  hc4->base = base;
315  return 1;
316 }
317 
318 
319 inline static void* LZ4HC_Create (const BYTE* base)
320 {
321  void* hc4 = ALLOCATOR(sizeof(LZ4HC_Data_Structure));
322 
323  LZ4HC_Init ((LZ4HC_Data_Structure*)hc4, base);
324  return hc4;
325 }
326 
327 
328 inline static int LZ4HC_Free (void** LZ4HC_Data)
329 {
330  FREEMEM(*LZ4HC_Data);
331  *LZ4HC_Data = NULL;
332  return (1);
333 }
334 
335 
336 // Update chains up to ip (excluded)
337 forceinline static void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
338 {
339  U16* chainTable = hc4->chainTable;
340  HTYPE* HashTable = hc4->hashTable;
341  INITBASE(base,hc4->base);
342 
343  while(hc4->nextToUpdate < ip)
344  {
345  const BYTE* p = hc4->nextToUpdate;
346  size_t delta = (p) - HASH_POINTER(p);
347  if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
348  DELTANEXT(p) = (U16)delta;
349  HashTable[HASH_VALUE(p)] = (p) - base;
350  hc4->nextToUpdate++;
351  }
352 }
353 
354 
355 forceinline static size_t LZ4HC_CommonLength (const BYTE* p1, const BYTE* p2, const BYTE* const matchlimit)
356 {
357  const BYTE* p1t = p1;
358 
359  while (p1t<matchlimit-(STEPSIZE-1))
360  {
361  UARCH diff = AARCH(p2) ^ AARCH(p1t);
362  if (!diff) { p1t+=STEPSIZE; p2+=STEPSIZE; continue; }
363  p1t += LZ4_NbCommonBytes(diff);
364  return (p1t - p1);
365  }
366  if (LZ4_ARCH64) if ((p1t<(matchlimit-3)) && (A32(p2) == A32(p1t))) { p1t+=4; p2+=4; }
367  if ((p1t<(matchlimit-1)) && (A16(p2) == A16(p1t))) { p1t+=2; p2+=2; }
368  if ((p1t<matchlimit) && (*p2 == *p1t)) p1t++;
369  return (p1t - p1);
370 }
371 
372 
373 forceinline static int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* const matchlimit, const BYTE** matchpos)
374 {
375  U16* const chainTable = hc4->chainTable;
376  HTYPE* const HashTable = hc4->hashTable;
377  const BYTE* ref;
378  INITBASE(base,hc4->base);
379  int nbAttempts=MAX_NB_ATTEMPTS;
380  size_t repl=0, ml=0;
381  U16 delta;
382 
383  // HC4 match finder
384  LZ4HC_Insert(hc4, ip);
385  ref = HASH_POINTER(ip);
386 
387 #define REPEAT_OPTIMIZATION
388 #ifdef REPEAT_OPTIMIZATION
389  // Detect repetitive sequences of length <= 4
390  if (ref >= ip-4) // potential repetition
391  {
392  if (A32(ref) == A32(ip)) // confirmed
393  {
394  delta = (U16)(ip-ref);
395  repl = ml = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;
396  *matchpos = ref;
397  }
398  ref = GETNEXT(ref);
399  }
400 #endif
401 
402  while ((ref >= ip-MAX_DISTANCE) && (nbAttempts))
403  {
404  nbAttempts--;
405  if (*(ref+ml) == *(ip+ml))
406  if (A32(ref) == A32(ip))
407  {
408  size_t mlt = LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit) + MINMATCH;
409  if (mlt > ml) { ml = mlt; *matchpos = ref; }
410  }
411  ref = GETNEXT(ref);
412  }
413 
414 #ifdef REPEAT_OPTIMIZATION
415  // Complete table
416  if (repl)
417  {
418  const BYTE* ptr = ip;
419  const BYTE* end;
420 
421  end = ip + repl - (MINMATCH-1);
422  while(ptr < end-delta)
423  {
424  DELTANEXT(ptr) = delta; // Pre-Load
425  ptr++;
426  }
427  do
428  {
429  DELTANEXT(ptr) = delta;
430  HashTable[HASH_VALUE(ptr)] = (ptr) - base; // Head of chain
431  ptr++;
432  } while(ptr < end);
433  hc4->nextToUpdate = end;
434  }
435 #endif
436 
437  return (int)ml;
438 }
439 
440 
441 forceinline static int LZ4HC_InsertAndGetWiderMatch (LZ4HC_Data_Structure* hc4, const BYTE* ip, const BYTE* startLimit, const BYTE* matchlimit, int longest, const BYTE** matchpos, const BYTE** startpos)
442 {
443  U16* const chainTable = hc4->chainTable;
444  HTYPE* const HashTable = hc4->hashTable;
445  INITBASE(base,hc4->base);
446  const BYTE* ref;
447  int nbAttempts = MAX_NB_ATTEMPTS;
448  int delta = (int)(ip-startLimit);
449 
450  // First Match
451  LZ4HC_Insert(hc4, ip);
452  ref = HASH_POINTER(ip);
453 
454  while ((ref >= ip-MAX_DISTANCE) && (nbAttempts))
455  {
456  nbAttempts--;
457  if (*(startLimit + longest) == *(ref - delta + longest))
458  if (A32(ref) == A32(ip))
459  {
460 #if 1
461  const BYTE* reft = ref+MINMATCH;
462  const BYTE* ipt = ip+MINMATCH;
463  const BYTE* startt = ip;
464 
465  while (ipt<matchlimit-(STEPSIZE-1))
466  {
467  UARCH diff = AARCH(reft) ^ AARCH(ipt);
468  if (!diff) { ipt+=STEPSIZE; reft+=STEPSIZE; continue; }
469  ipt += LZ4_NbCommonBytes(diff);
470  goto _endCount;
471  }
472  if (LZ4_ARCH64) if ((ipt<(matchlimit-3)) && (A32(reft) == A32(ipt))) { ipt+=4; reft+=4; }
473  if ((ipt<(matchlimit-1)) && (A16(reft) == A16(ipt))) { ipt+=2; reft+=2; }
474  if ((ipt<matchlimit) && (*reft == *ipt)) ipt++;
475 _endCount:
476  reft = ref;
477 #else
478  // Easier for code maintenance, but unfortunately slower too
479  const BYTE* startt = ip;
480  const BYTE* reft = ref;
481  const BYTE* ipt = ip + MINMATCH + LZ4HC_CommonLength(ip+MINMATCH, ref+MINMATCH, matchlimit);
482 #endif
483 
484  while ((startt>startLimit) && (reft > hc4->base) && (startt[-1] == reft[-1])) {startt--; reft--;}
485 
486  if ((ipt-startt) > longest)
487  {
488  longest = (int)(ipt-startt);
489  *matchpos = reft;
490  *startpos = startt;
491  }
492  }
493  ref = GETNEXT(ref);
494  }
495 
496  return longest;
497 }
498 
499 
500 forceinline static int LZ4_encodeSequence(const BYTE** ip, BYTE** op, const BYTE** anchor, int ml, const BYTE* ref)
501 {
502  int length, len;
503  BYTE* token;
504 
505  // Encode Literal length
506  length = (int)(*ip - *anchor);
507  token = (*op)++;
508  if (length>=(int)RUN_MASK) { *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; }
509  else *token = (length<<ML_BITS);
510 
511  // Copy Literals
512  LZ4_BLINDCOPY(*anchor, *op, length);
513 
514  // Encode Offset
515  LZ4_WRITE_LITTLEENDIAN_16(*op,(U16)(*ip-ref));
516 
517  // Encode MatchLength
518  len = (int)(ml-MINMATCH);
519  if (len>=(int)ML_MASK) { *token+=ML_MASK; len-=ML_MASK; for(; len > 509 ; len-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (len > 254) { len-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)len; }
520  else *token += len;
521 
522  // Prepare next loop
523  *ip += ml;
524  *anchor = *ip;
525 
526  return 0;
527 }
528 
529 
530 //****************************
531 // Compression CODE
532 //****************************
533 
535  const char* source,
536  char* dest,
537  int isize)
538 {
539  const BYTE* ip = (const BYTE*) source;
540  const BYTE* anchor = ip;
541  const BYTE* const iend = ip + isize;
542  const BYTE* const mflimit = iend - MFLIMIT;
543  const BYTE* const matchlimit = (iend - LASTLITERALS);
544 
545  BYTE* op = (BYTE*) dest;
546 
547  int ml, ml2, ml3, ml0;
548  const BYTE* ref=NULL;
549  const BYTE* start2=NULL;
550  const BYTE* ref2=NULL;
551  const BYTE* start3=NULL;
552  const BYTE* ref3=NULL;
553  const BYTE* start0;
554  const BYTE* ref0;
555 
556  ip++;
557 
558  // Main Loop
559  while (ip < mflimit)
560  {
561  ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref));
562  if (!ml) { ip++; continue; }
563 
564  // saved, in case we would skip too much
565  start0 = ip;
566  ref0 = ref;
567  ml0 = ml;
568 
569 _Search2:
570  if (ip+ml < mflimit)
571  ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);
572  else ml2 = ml;
573 
574  if (ml2 == ml) // No better match
575  {
576  LZ4_encodeSequence(&ip, &op, &anchor, ml, ref);
577  continue;
578  }
579 
580  if (start0 < ip)
581  {
582  if (start2 < ip + ml0) // empirical
583  {
584  ip = start0;
585  ref = ref0;
586  ml = ml0;
587  }
588  }
589 
590  // Here, start0==ip
591  if ((start2 - ip) < 3) // First Match too small : removed
592  {
593  ml = ml2;
594  ip = start2;
595  ref =ref2;
596  goto _Search2;
597  }
598 
599 _Search3:
600  // Currently we have :
601  // ml2 > ml1, and
602  // ip1+3 <= ip2 (usually < ip1+ml1)
603  if ((start2 - ip) < OPTIMAL_ML)
604  {
605  int correction;
606  int new_ml = ml;
607  if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
608  if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
609  correction = new_ml - (int)(start2 - ip);
610  if (correction > 0)
611  {
612  start2 += correction;
613  ref2 += correction;
614  ml2 -= correction;
615  }
616  }
617  // Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18)
618 
619  if (start2 + ml2 < mflimit)
620  ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);
621  else ml3 = ml2;
622 
623  if (ml3 == ml2) // No better match : 2 sequences to encode
624  {
625  // ip & ref are known; Now for ml
626  if (start2 < ip+ml) ml = (int)(start2 - ip);
627  // Now, encode 2 sequences
628  LZ4_encodeSequence(&ip, &op, &anchor, ml, ref);
629  ip = start2;
630  LZ4_encodeSequence(&ip, &op, &anchor, ml2, ref2);
631  continue;
632  }
633 
634  if (start3 < ip+ml+3) // Not enough space for match 2 : remove it
635  {
636  if (start3 >= (ip+ml)) // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
637  {
638  if (start2 < ip+ml)
639  {
640  int correction = (int)(ip+ml - start2);
641  start2 += correction;
642  ref2 += correction;
643  ml2 -= correction;
644  if (ml2 < MINMATCH)
645  {
646  start2 = start3;
647  ref2 = ref3;
648  ml2 = ml3;
649  }
650  }
651 
652  LZ4_encodeSequence(&ip, &op, &anchor, ml, ref);
653  ip = start3;
654  ref = ref3;
655  ml = ml3;
656 
657  start0 = start2;
658  ref0 = ref2;
659  ml0 = ml2;
660  goto _Search2;
661  }
662 
663  start2 = start3;
664  ref2 = ref3;
665  ml2 = ml3;
666  goto _Search3;
667  }
668 
669  // OK, now we have 3 ascending matches; let's write at least the first one
670  // ip & ref are known; Now for ml
671  if (start2 < ip+ml)
672  {
673  if ((start2 - ip) < (int)ML_MASK)
674  {
675  int correction;
676  if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
677  if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
678  correction = ml - (int)(start2 - ip);
679  if (correction > 0)
680  {
681  start2 += correction;
682  ref2 += correction;
683  ml2 -= correction;
684  }
685  }
686  else
687  {
688  ml = (int)(start2 - ip);
689  }
690  }
691  LZ4_encodeSequence(&ip, &op, &anchor, ml, ref);
692 
693  ip = start2;
694  ref = ref2;
695  ml = ml2;
696 
697  start2 = start3;
698  ref2 = ref3;
699  ml2 = ml3;
700 
701  goto _Search3;
702 
703  }
704 
705  // Encode Last Literals
706  {
707  int lastRun = (int)(iend - anchor);
708  if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
709  else *op++ = (lastRun<<ML_BITS);
710  memcpy(op, anchor, iend - anchor);
711  op += iend-anchor;
712  }
713 
714  // End
715  return (int) (((char*)op)-dest);
716 }
717 
718 
719 int LZ4_compressHC(const char* source,
720  char* dest,
721  int isize)
722 {
723  void* ctx = LZ4HC_Create((const BYTE*)source);
724  int result = LZ4_compressHCCtx(ctx, source, dest, isize);
725  LZ4HC_Free (&ctx);
726 
727  return result;
728 }
729 
730