lz4hc.c
Go to the documentation of this file.
00001 /*
00002     LZ4 HC - High Compression Mode of LZ4
00003     Copyright (C) 2011-2015, Yann Collet.
00004 
00005     BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
00006 
00007     Redistribution and use in source and binary forms, with or without
00008     modification, are permitted provided that the following conditions are
00009     met:
00010 
00011     * Redistributions of source code must retain the above copyright
00012     notice, this list of conditions and the following disclaimer.
00013     * Redistributions in binary form must reproduce the above
00014     copyright notice, this list of conditions and the following disclaimer
00015     in the documentation and/or other materials provided with the
00016     distribution.
00017 
00018     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030     You can contact the author at :
00031        - LZ4 source repository : https://github.com/Cyan4973/lz4
00032        - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
00033 */
00034 
00035 
00036 
00037 /**************************************
00038 *  Tuning Parameter
00039 **************************************/
00040 static const int LZ4HC_compressionLevel_default = 9;
00041 
00042 
00043 /**************************************
00044 *  Includes
00045 **************************************/
00046 #include "lz4hc.h"
00047 
00048 
00049 /**************************************
00050 *  Local Compiler Options
00051 **************************************/
00052 #if defined(__GNUC__)
00053 #  pragma GCC diagnostic ignored "-Wunused-function"
00054 #endif
00055 
00056 #if defined (__clang__)
00057 #  pragma clang diagnostic ignored "-Wunused-function"
00058 #endif
00059 
00060 
00061 /**************************************
00062 *  Common LZ4 definition
00063 **************************************/
00064 #define LZ4_COMMONDEFS_ONLY
00065 #include "lz4.c"
00066 
00067 
00068 /**************************************
00069 *  Local Constants
00070 **************************************/
00071 #define DICTIONARY_LOGSIZE 16
00072 #define MAXD (1<<DICTIONARY_LOGSIZE)
00073 #define MAXD_MASK (MAXD - 1)
00074 
00075 #define HASH_LOG (DICTIONARY_LOGSIZE-1)
00076 #define HASHTABLESIZE (1 << HASH_LOG)
00077 #define HASH_MASK (HASHTABLESIZE - 1)
00078 
00079 #define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
00080 
00081 static const int g_maxCompressionLevel = 16;
00082 
00083 
00084 /**************************************
00085 *  Local Types
00086 **************************************/
00087 typedef struct
00088 {
00089     U32   hashTable[HASHTABLESIZE];
00090     U16   chainTable[MAXD];
00091     const BYTE* end;        /* next block here to continue on current prefix */
00092     const BYTE* base;       /* All index relative to this position */
00093     const BYTE* dictBase;   /* alternate base for extDict */
00094     BYTE* inputBuffer;      /* deprecated */
00095     U32   dictLimit;        /* below that point, need extDict */
00096     U32   lowLimit;         /* below that point, no more dict */
00097     U32   nextToUpdate;     /* index from which to continue dictionary update */
00098     U32   compressionLevel;
00099 } LZ4HC_Data_Structure;
00100 
00101 
00102 /**************************************
00103 *  Local Macros
00104 **************************************/
00105 #define HASH_FUNCTION(i)       (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
00106 //#define DELTANEXTU16(p)        chainTable[(p) & MAXD_MASK]   /* flexible, MAXD dependent */
00107 #define DELTANEXTU16(p)        chainTable[(U16)(p)]   /* faster */
00108 
00109 static U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }
00110 
00111 
00112 
00113 /**************************************
00114 *  HC Compression
00115 **************************************/
00116 static void LZ4HC_init (LZ4HC_Data_Structure* hc4, const BYTE* start)
00117 {
00118     MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
00119     MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
00120     hc4->nextToUpdate = 64 KB;
00121     hc4->base = start - 64 KB;
00122     hc4->end = start;
00123     hc4->dictBase = start - 64 KB;
00124     hc4->dictLimit = 64 KB;
00125     hc4->lowLimit = 64 KB;
00126 }
00127 
00128 
00129 /* Update chains up to ip (excluded) */
00130 FORCE_INLINE void LZ4HC_Insert (LZ4HC_Data_Structure* hc4, const BYTE* ip)
00131 {
00132     U16* chainTable = hc4->chainTable;
00133     U32* HashTable  = hc4->hashTable;
00134     const BYTE* const base = hc4->base;
00135     const U32 target = (U32)(ip - base);
00136     U32 idx = hc4->nextToUpdate;
00137 
00138     while(idx < target)
00139     {
00140         U32 h = LZ4HC_hashPtr(base+idx);
00141         size_t delta = idx - HashTable[h];
00142         if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
00143         DELTANEXTU16(idx) = (U16)delta;
00144         HashTable[h] = idx;
00145         idx++;
00146     }
00147 
00148     hc4->nextToUpdate = target;
00149 }
00150 
00151 
00152 FORCE_INLINE int LZ4HC_InsertAndFindBestMatch (LZ4HC_Data_Structure* hc4,   /* Index table will be updated */
00153                                                const BYTE* ip, const BYTE* const iLimit,
00154                                                const BYTE** matchpos,
00155                                                const int maxNbAttempts)
00156 {
00157     U16* const chainTable = hc4->chainTable;
00158     U32* const HashTable = hc4->hashTable;
00159     const BYTE* const base = hc4->base;
00160     const BYTE* const dictBase = hc4->dictBase;
00161     const U32 dictLimit = hc4->dictLimit;
00162     const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
00163     U32 matchIndex;
00164     const BYTE* match;
00165     int nbAttempts=maxNbAttempts;
00166     size_t ml=0;
00167 
00168     /* HC4 match finder */
00169     LZ4HC_Insert(hc4, ip);
00170     matchIndex = HashTable[LZ4HC_hashPtr(ip)];
00171 
00172     while ((matchIndex>=lowLimit) && (nbAttempts))
00173     {
00174         nbAttempts--;
00175         if (matchIndex >= dictLimit)
00176         {
00177             match = base + matchIndex;
00178             if (*(match+ml) == *(ip+ml)
00179                 && (LZ4_read32(match) == LZ4_read32(ip)))
00180             {
00181                 size_t mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
00182                 if (mlt > ml) { ml = mlt; *matchpos = match; }
00183             }
00184         }
00185         else
00186         {
00187             match = dictBase + matchIndex;
00188             if (LZ4_read32(match) == LZ4_read32(ip))
00189             {
00190                 size_t mlt;
00191                 const BYTE* vLimit = ip + (dictLimit - matchIndex);
00192                 if (vLimit > iLimit) vLimit = iLimit;
00193                 mlt = LZ4_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
00194                 if ((ip+mlt == vLimit) && (vLimit < iLimit))
00195                     mlt += LZ4_count(ip+mlt, base+dictLimit, iLimit);
00196                 if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */
00197             }
00198         }
00199         matchIndex -= DELTANEXTU16(matchIndex);
00200     }
00201 
00202     return (int)ml;
00203 }
00204 
00205 
00206 FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch (
00207     LZ4HC_Data_Structure* hc4,
00208     const BYTE* const ip,
00209     const BYTE* const iLowLimit,
00210     const BYTE* const iHighLimit,
00211     int longest,
00212     const BYTE** matchpos,
00213     const BYTE** startpos,
00214     const int maxNbAttempts)
00215 {
00216     U16* const chainTable = hc4->chainTable;
00217     U32* const HashTable = hc4->hashTable;
00218     const BYTE* const base = hc4->base;
00219     const U32 dictLimit = hc4->dictLimit;
00220     const BYTE* const lowPrefixPtr = base + dictLimit;
00221     const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
00222     const BYTE* const dictBase = hc4->dictBase;
00223     U32   matchIndex;
00224     int nbAttempts = maxNbAttempts;
00225     int delta = (int)(ip-iLowLimit);
00226 
00227 
00228     /* First Match */
00229     LZ4HC_Insert(hc4, ip);
00230     matchIndex = HashTable[LZ4HC_hashPtr(ip)];
00231 
00232     while ((matchIndex>=lowLimit) && (nbAttempts))
00233     {
00234         nbAttempts--;
00235         if (matchIndex >= dictLimit)
00236         {
00237             const BYTE* matchPtr = base + matchIndex;
00238             if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
00239                 if (LZ4_read32(matchPtr) == LZ4_read32(ip))
00240                 {
00241                     int mlt = MINMATCH + LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
00242                     int back = 0;
00243 
00244                     while ((ip+back>iLowLimit)
00245                            && (matchPtr+back > lowPrefixPtr)
00246                            && (ip[back-1] == matchPtr[back-1]))
00247                             back--;
00248 
00249                     mlt -= back;
00250 
00251                     if (mlt > longest)
00252                     {
00253                         longest = (int)mlt;
00254                         *matchpos = matchPtr+back;
00255                         *startpos = ip+back;
00256                     }
00257                 }
00258         }
00259         else
00260         {
00261             const BYTE* matchPtr = dictBase + matchIndex;
00262             if (LZ4_read32(matchPtr) == LZ4_read32(ip))
00263             {
00264                 size_t mlt;
00265                 int back=0;
00266                 const BYTE* vLimit = ip + (dictLimit - matchIndex);
00267                 if (vLimit > iHighLimit) vLimit = iHighLimit;
00268                 mlt = LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
00269                 if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
00270                     mlt += LZ4_count(ip+mlt, base+dictLimit, iHighLimit);
00271                 while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
00272                 mlt -= back;
00273                 if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
00274             }
00275         }
00276         matchIndex -= DELTANEXTU16(matchIndex);
00277     }
00278 
00279     return longest;
00280 }
00281 
00282 
00283 typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
00284 
00285 #define LZ4HC_DEBUG 0
00286 #if LZ4HC_DEBUG
00287 static unsigned debug = 0;
00288 #endif
00289 
00290 FORCE_INLINE int LZ4HC_encodeSequence (
00291     const BYTE** ip,
00292     BYTE** op,
00293     const BYTE** anchor,
00294     int matchLength,
00295     const BYTE* const match,
00296     limitedOutput_directive limitedOutputBuffer,
00297     BYTE* oend)
00298 {
00299     int length;
00300     BYTE* token;
00301 
00302 #if LZ4HC_DEBUG
00303     if (debug) printf("literal : %u  --  match : %u  --  offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
00304 #endif
00305 
00306     /* Encode Literal length */
00307     length = (int)(*ip - *anchor);
00308     token = (*op)++;
00309     if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1;   /* Check output limit */
00310     if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; }
00311     else *token = (BYTE)(length<<ML_BITS);
00312 
00313     /* Copy Literals */
00314     LZ4_wildCopy(*op, *anchor, (*op) + length);
00315     *op += length;
00316 
00317     /* Encode Offset */
00318     LZ4_writeLE16(*op, (U16)(*ip-match)); *op += 2;
00319 
00320     /* Encode MatchLength */
00321     length = (int)(matchLength-MINMATCH);
00322     if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1;   /* Check output limit */
00323     if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }
00324     else *token += (BYTE)(length);
00325 
00326     /* Prepare next loop */
00327     *ip += matchLength;
00328     *anchor = *ip;
00329 
00330     return 0;
00331 }
00332 
00333 
00334 static int LZ4HC_compress_generic (
00335     void* ctxvoid,
00336     const char* source,
00337     char* dest,
00338     int inputSize,
00339     int maxOutputSize,
00340     int compressionLevel,
00341     limitedOutput_directive limit
00342     )
00343 {
00344     LZ4HC_Data_Structure* ctx = (LZ4HC_Data_Structure*) ctxvoid;
00345     const BYTE* ip = (const BYTE*) source;
00346     const BYTE* anchor = ip;
00347     const BYTE* const iend = ip + inputSize;
00348     const BYTE* const mflimit = iend - MFLIMIT;
00349     const BYTE* const matchlimit = (iend - LASTLITERALS);
00350 
00351     BYTE* op = (BYTE*) dest;
00352     BYTE* const oend = op + maxOutputSize;
00353 
00354     unsigned maxNbAttempts;
00355     int   ml, ml2, ml3, ml0;
00356     const BYTE* ref=NULL;
00357     const BYTE* start2=NULL;
00358     const BYTE* ref2=NULL;
00359     const BYTE* start3=NULL;
00360     const BYTE* ref3=NULL;
00361     const BYTE* start0;
00362     const BYTE* ref0;
00363 
00364 
00365     /* init */
00366     if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel;
00367     if (compressionLevel < 1) compressionLevel = LZ4HC_compressionLevel_default;
00368     maxNbAttempts = 1 << (compressionLevel-1);
00369     ctx->end += inputSize;
00370 
00371     ip++;
00372 
00373     /* Main Loop */
00374     while (ip < mflimit)
00375     {
00376         ml = LZ4HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
00377         if (!ml) { ip++; continue; }
00378 
00379         /* saved, in case we would skip too much */
00380         start0 = ip;
00381         ref0 = ref;
00382         ml0 = ml;
00383 
00384 _Search2:
00385         if (ip+ml < mflimit)
00386             ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts);
00387         else ml2 = ml;
00388 
00389         if (ml2 == ml)  /* No better match */
00390         {
00391             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
00392             continue;
00393         }
00394 
00395         if (start0 < ip)
00396         {
00397             if (start2 < ip + ml0)   /* empirical */
00398             {
00399                 ip = start0;
00400                 ref = ref0;
00401                 ml = ml0;
00402             }
00403         }
00404 
00405         /* Here, start0==ip */
00406         if ((start2 - ip) < 3)   /* First Match too small : removed */
00407         {
00408             ml = ml2;
00409             ip = start2;
00410             ref =ref2;
00411             goto _Search2;
00412         }
00413 
00414 _Search3:
00415         /*
00416         * Currently we have :
00417         * ml2 > ml1, and
00418         * ip1+3 <= ip2 (usually < ip1+ml1)
00419         */
00420         if ((start2 - ip) < OPTIMAL_ML)
00421         {
00422             int correction;
00423             int new_ml = ml;
00424             if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
00425             if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
00426             correction = new_ml - (int)(start2 - ip);
00427             if (correction > 0)
00428             {
00429                 start2 += correction;
00430                 ref2 += correction;
00431                 ml2 -= correction;
00432             }
00433         }
00434         /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
00435 
00436         if (start2 + ml2 < mflimit)
00437             ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
00438         else ml3 = ml2;
00439 
00440         if (ml3 == ml2) /* No better match : 2 sequences to encode */
00441         {
00442             /* ip & ref are known; Now for ml */
00443             if (start2 < ip+ml)  ml = (int)(start2 - ip);
00444             /* Now, encode 2 sequences */
00445             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
00446             ip = start2;
00447             if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
00448             continue;
00449         }
00450 
00451         if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */
00452         {
00453             if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
00454             {
00455                 if (start2 < ip+ml)
00456                 {
00457                     int correction = (int)(ip+ml - start2);
00458                     start2 += correction;
00459                     ref2 += correction;
00460                     ml2 -= correction;
00461                     if (ml2 < MINMATCH)
00462                     {
00463                         start2 = start3;
00464                         ref2 = ref3;
00465                         ml2 = ml3;
00466                     }
00467                 }
00468 
00469                 if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
00470                 ip  = start3;
00471                 ref = ref3;
00472                 ml  = ml3;
00473 
00474                 start0 = start2;
00475                 ref0 = ref2;
00476                 ml0 = ml2;
00477                 goto _Search2;
00478             }
00479 
00480             start2 = start3;
00481             ref2 = ref3;
00482             ml2 = ml3;
00483             goto _Search3;
00484         }
00485 
00486         /*
00487         * OK, now we have 3 ascending matches; let's write at least the first one
00488         * ip & ref are known; Now for ml
00489         */
00490         if (start2 < ip+ml)
00491         {
00492             if ((start2 - ip) < (int)ML_MASK)
00493             {
00494                 int correction;
00495                 if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
00496                 if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
00497                 correction = ml - (int)(start2 - ip);
00498                 if (correction > 0)
00499                 {
00500                     start2 += correction;
00501                     ref2 += correction;
00502                     ml2 -= correction;
00503                 }
00504             }
00505             else
00506             {
00507                 ml = (int)(start2 - ip);
00508             }
00509         }
00510         if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
00511 
00512         ip = start2;
00513         ref = ref2;
00514         ml = ml2;
00515 
00516         start2 = start3;
00517         ref2 = ref3;
00518         ml2 = ml3;
00519 
00520         goto _Search3;
00521     }
00522 
00523     /* Encode Last Literals */
00524     {
00525         int lastRun = (int)(iend - anchor);
00526         if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */
00527         if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
00528         else *op++ = (BYTE)(lastRun<<ML_BITS);
00529         memcpy(op, anchor, iend - anchor);
00530         op += iend-anchor;
00531     }
00532 
00533     /* End */
00534     return (int) (((char*)op)-dest);
00535 }
00536 
00537 
00538 int LZ4_sizeofStateHC(void) { return sizeof(LZ4HC_Data_Structure); }
00539 
00540 int LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
00541 {
00542     if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */
00543     LZ4HC_init ((LZ4HC_Data_Structure*)state, (const BYTE*)src);
00544     if (maxDstSize < LZ4_compressBound(srcSize))
00545         return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
00546     else
00547         return LZ4HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
00548 }
00549 
00550 int LZ4_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
00551 {
00552     LZ4HC_Data_Structure state;
00553     return LZ4_compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel);
00554 }
00555 
00556 
00557 
00558 /**************************************
00559 *  Streaming Functions
00560 **************************************/
00561 /* allocation */
00562 LZ4_streamHC_t* LZ4_createStreamHC(void) { return (LZ4_streamHC_t*)malloc(sizeof(LZ4_streamHC_t)); }
00563 int             LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr) { free(LZ4_streamHCPtr); return 0; }
00564 
00565 
00566 /* initialization */
00567 void LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)
00568 {
00569     LZ4_STATIC_ASSERT(sizeof(LZ4HC_Data_Structure) <= sizeof(LZ4_streamHC_t));   /* if compilation fails here, LZ4_STREAMHCSIZE must be increased */
00570     ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->base = NULL;
00571     ((LZ4HC_Data_Structure*)LZ4_streamHCPtr)->compressionLevel = (unsigned)compressionLevel;
00572 }
00573 
00574 int LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, const char* dictionary, int dictSize)
00575 {
00576     LZ4HC_Data_Structure* ctxPtr = (LZ4HC_Data_Structure*) LZ4_streamHCPtr;
00577     if (dictSize > 64 KB)
00578     {
00579         dictionary += dictSize - 64 KB;
00580         dictSize = 64 KB;
00581     }
00582     LZ4HC_init (ctxPtr, (const BYTE*)dictionary);
00583     if (dictSize >= 4) LZ4HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));
00584     ctxPtr->end = (const BYTE*)dictionary + dictSize;
00585     return dictSize;
00586 }
00587 
00588 
00589 /* compression */
00590 
00591 static void LZ4HC_setExternalDict(LZ4HC_Data_Structure* ctxPtr, const BYTE* newBlock)
00592 {
00593     if (ctxPtr->end >= ctxPtr->base + 4)
00594         LZ4HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */
00595     /* Only one memory segment for extDict, so any previous extDict is lost at this stage */
00596     ctxPtr->lowLimit  = ctxPtr->dictLimit;
00597     ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
00598     ctxPtr->dictBase  = ctxPtr->base;
00599     ctxPtr->base = newBlock - ctxPtr->dictLimit;
00600     ctxPtr->end  = newBlock;
00601     ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */
00602 }
00603 
00604 static int LZ4_compressHC_continue_generic (LZ4HC_Data_Structure* ctxPtr,
00605                                             const char* source, char* dest,
00606                                             int inputSize, int maxOutputSize, limitedOutput_directive limit)
00607 {
00608     /* auto-init if forgotten */
00609     if (ctxPtr->base == NULL)
00610         LZ4HC_init (ctxPtr, (const BYTE*) source);
00611 
00612     /* Check overflow */
00613     if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
00614     {
00615         size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
00616         if (dictSize > 64 KB) dictSize = 64 KB;
00617 
00618         LZ4_loadDictHC((LZ4_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
00619     }
00620 
00621     /* Check if blocks follow each other */
00622     if ((const BYTE*)source != ctxPtr->end)
00623         LZ4HC_setExternalDict(ctxPtr, (const BYTE*)source);
00624 
00625     /* Check overlapping input/dictionary space */
00626     {
00627         const BYTE* sourceEnd = (const BYTE*) source + inputSize;
00628         const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
00629         const BYTE* dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;
00630         if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))
00631         {
00632             if (sourceEnd > dictEnd) sourceEnd = dictEnd;
00633             ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
00634             if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
00635         }
00636     }
00637 
00638     return LZ4HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
00639 }
00640 
00641 int LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
00642 {
00643     if (maxOutputSize < LZ4_compressBound(inputSize))
00644         return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
00645     else
00646         return LZ4_compressHC_continue_generic ((LZ4HC_Data_Structure*)LZ4_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
00647 }
00648 
00649 
00650 /* dictionary saving */
00651 
00652 int LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)
00653 {
00654     LZ4HC_Data_Structure* streamPtr = (LZ4HC_Data_Structure*)LZ4_streamHCPtr;
00655     int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
00656     if (dictSize > 64 KB) dictSize = 64 KB;
00657     if (dictSize < 4) dictSize = 0;
00658     if (dictSize > prefixSize) dictSize = prefixSize;
00659     memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
00660     {
00661         U32 endIndex = (U32)(streamPtr->end - streamPtr->base);
00662         streamPtr->end = (const BYTE*)safeBuffer + dictSize;
00663         streamPtr->base = streamPtr->end - endIndex;
00664         streamPtr->dictLimit = endIndex - dictSize;
00665         streamPtr->lowLimit = endIndex - dictSize;
00666         if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
00667     }
00668     return dictSize;
00669 }
00670 
00671 
00672 /***********************************
00673 *  Deprecated Functions
00674 ***********************************/
00675 /* Deprecated compression functions */
00676 /* These functions are planned to start generate warnings by r131 approximately */
00677 int LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }
00678 int LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }
00679 int LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }
00680 int LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
00681 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); }
00682 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); }
00683 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); }
00684 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); }
00685 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)); }
00686 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); }
00687 
00688 
00689 /* Deprecated streaming functions */
00690 /* These functions currently generate deprecation warnings */
00691 int LZ4_sizeofStreamStateHC(void) { return LZ4_STREAMHCSIZE; }
00692 
00693 int LZ4_resetStreamStateHC(void* state, char* inputBuffer)
00694 {
00695     if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1;   /* Error : pointer is not aligned for pointer (32 or 64 bits) */
00696     LZ4HC_init((LZ4HC_Data_Structure*)state, (const BYTE*)inputBuffer);
00697     ((LZ4HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer;
00698     return 0;
00699 }
00700 
00701 void* LZ4_createHC (char* inputBuffer)
00702 {
00703     void* hc4 = ALLOCATOR(1, sizeof(LZ4HC_Data_Structure));
00704     if (hc4 == NULL) return NULL;   /* not enough memory */
00705     LZ4HC_init ((LZ4HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
00706     ((LZ4HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer;
00707     return hc4;
00708 }
00709 
00710 int LZ4_freeHC (void* LZ4HC_Data)
00711 {
00712     FREEMEM(LZ4HC_Data);
00713     return (0);
00714 }
00715 
00716 int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
00717 {
00718     return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, 0, compressionLevel, noLimit);
00719 }
00720 
00721 int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
00722 {
00723     return LZ4HC_compress_generic (LZ4HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
00724 }
00725 
00726 char* LZ4_slideInputBufferHC(void* LZ4HC_Data)
00727 {
00728     LZ4HC_Data_Structure* hc4 = (LZ4HC_Data_Structure*)LZ4HC_Data;
00729     int dictSize = LZ4_saveDictHC((LZ4_streamHC_t*)LZ4HC_Data, (char*)(hc4->inputBuffer), 64 KB);
00730     return (char*)(hc4->inputBuffer + dictSize);
00731 }


rtabmap
Author(s): Mathieu Labbe
autogenerated on Sat Jul 23 2016 11:44:16