162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * LZ4 HC - High Compression Mode of LZ4 362306a36Sopenharmony_ci * Copyright (C) 2011-2015, Yann Collet. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php) 662306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 762306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are 862306a36Sopenharmony_ci * met: 962306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 1062306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1162306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above 1262306a36Sopenharmony_ci * copyright notice, this list of conditions and the following disclaimer 1362306a36Sopenharmony_ci * in the documentation and/or other materials provided with the 1462306a36Sopenharmony_ci * distribution. 1562306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1662306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1762306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1862306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1962306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2062306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2162306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2262306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2362306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2462306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2562306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2662306a36Sopenharmony_ci * You can contact the author at : 2762306a36Sopenharmony_ci * - LZ4 homepage : http://www.lz4.org 2862306a36Sopenharmony_ci * - LZ4 source repository : https://github.com/lz4/lz4 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Changed for kernel usage by: 3162306a36Sopenharmony_ci * Sven Schmidt <4sschmid@informatik.uni-hamburg.de> 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/*-************************************ 3562306a36Sopenharmony_ci * Dependencies 3662306a36Sopenharmony_ci **************************************/ 3762306a36Sopenharmony_ci#include <linux/lz4.h> 3862306a36Sopenharmony_ci#include "lz4defs.h" 3962306a36Sopenharmony_ci#include <linux/module.h> 4062306a36Sopenharmony_ci#include <linux/kernel.h> 4162306a36Sopenharmony_ci#include <linux/string.h> /* memset */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* ************************************* 4462306a36Sopenharmony_ci * Local Constants and types 4562306a36Sopenharmony_ci ***************************************/ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define OPTIMAL_ML (int)((ML_MASK - 1) + MINMATCH) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define HASH_FUNCTION(i) (((i) * 2654435761U) \ 5062306a36Sopenharmony_ci >> ((MINMATCH*8) - LZ4HC_HASH_LOG)) 5162306a36Sopenharmony_ci#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic U32 LZ4HC_hashPtr(const void *ptr) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci return HASH_FUNCTION(LZ4_read32(ptr)); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/************************************** 5962306a36Sopenharmony_ci * HC Compression 6062306a36Sopenharmony_ci **************************************/ 6162306a36Sopenharmony_cistatic void LZ4HC_init(LZ4HC_CCtx_internal *hc4, const BYTE *start) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci memset((void *)hc4->hashTable, 0, sizeof(hc4->hashTable)); 6462306a36Sopenharmony_ci memset(hc4->chainTable, 0xFF, sizeof(hc4->chainTable)); 6562306a36Sopenharmony_ci hc4->nextToUpdate = 64 * KB; 6662306a36Sopenharmony_ci hc4->base = start - 64 * KB; 6762306a36Sopenharmony_ci hc4->end = start; 6862306a36Sopenharmony_ci hc4->dictBase = start - 64 * KB; 6962306a36Sopenharmony_ci hc4->dictLimit = 64 * KB; 7062306a36Sopenharmony_ci hc4->lowLimit = 64 * KB; 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* Update chains up to ip (excluded) */ 7462306a36Sopenharmony_cistatic FORCE_INLINE void LZ4HC_Insert(LZ4HC_CCtx_internal *hc4, 7562306a36Sopenharmony_ci const BYTE *ip) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci U16 * const chainTable = hc4->chainTable; 7862306a36Sopenharmony_ci U32 * const hashTable = hc4->hashTable; 7962306a36Sopenharmony_ci const BYTE * const base = hc4->base; 8062306a36Sopenharmony_ci U32 const target = (U32)(ip - base); 8162306a36Sopenharmony_ci U32 idx = hc4->nextToUpdate; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci while (idx < target) { 8462306a36Sopenharmony_ci U32 const h = LZ4HC_hashPtr(base + idx); 8562306a36Sopenharmony_ci size_t delta = idx - hashTable[h]; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (delta > MAX_DISTANCE) 8862306a36Sopenharmony_ci delta = MAX_DISTANCE; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci DELTANEXTU16(idx) = (U16)delta; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci hashTable[h] = idx; 9362306a36Sopenharmony_ci idx++; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci hc4->nextToUpdate = target; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_InsertAndFindBestMatch( 10062306a36Sopenharmony_ci LZ4HC_CCtx_internal *hc4, /* Index table will be updated */ 10162306a36Sopenharmony_ci const BYTE *ip, 10262306a36Sopenharmony_ci const BYTE * const iLimit, 10362306a36Sopenharmony_ci const BYTE **matchpos, 10462306a36Sopenharmony_ci const int maxNbAttempts) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci U16 * const chainTable = hc4->chainTable; 10762306a36Sopenharmony_ci U32 * const HashTable = hc4->hashTable; 10862306a36Sopenharmony_ci const BYTE * const base = hc4->base; 10962306a36Sopenharmony_ci const BYTE * const dictBase = hc4->dictBase; 11062306a36Sopenharmony_ci const U32 dictLimit = hc4->dictLimit; 11162306a36Sopenharmony_ci const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base)) 11262306a36Sopenharmony_ci ? hc4->lowLimit 11362306a36Sopenharmony_ci : (U32)(ip - base) - (64 * KB - 1); 11462306a36Sopenharmony_ci U32 matchIndex; 11562306a36Sopenharmony_ci int nbAttempts = maxNbAttempts; 11662306a36Sopenharmony_ci size_t ml = 0; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* HC4 match finder */ 11962306a36Sopenharmony_ci LZ4HC_Insert(hc4, ip); 12062306a36Sopenharmony_ci matchIndex = HashTable[LZ4HC_hashPtr(ip)]; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci while ((matchIndex >= lowLimit) 12362306a36Sopenharmony_ci && (nbAttempts)) { 12462306a36Sopenharmony_ci nbAttempts--; 12562306a36Sopenharmony_ci if (matchIndex >= dictLimit) { 12662306a36Sopenharmony_ci const BYTE * const match = base + matchIndex; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci if (*(match + ml) == *(ip + ml) 12962306a36Sopenharmony_ci && (LZ4_read32(match) == LZ4_read32(ip))) { 13062306a36Sopenharmony_ci size_t const mlt = LZ4_count(ip + MINMATCH, 13162306a36Sopenharmony_ci match + MINMATCH, iLimit) + MINMATCH; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (mlt > ml) { 13462306a36Sopenharmony_ci ml = mlt; 13562306a36Sopenharmony_ci *matchpos = match; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci } else { 13962306a36Sopenharmony_ci const BYTE * const match = dictBase + matchIndex; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (LZ4_read32(match) == LZ4_read32(ip)) { 14262306a36Sopenharmony_ci size_t mlt; 14362306a36Sopenharmony_ci const BYTE *vLimit = ip 14462306a36Sopenharmony_ci + (dictLimit - matchIndex); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (vLimit > iLimit) 14762306a36Sopenharmony_ci vLimit = iLimit; 14862306a36Sopenharmony_ci mlt = LZ4_count(ip + MINMATCH, 14962306a36Sopenharmony_ci match + MINMATCH, vLimit) + MINMATCH; 15062306a36Sopenharmony_ci if ((ip + mlt == vLimit) 15162306a36Sopenharmony_ci && (vLimit < iLimit)) 15262306a36Sopenharmony_ci mlt += LZ4_count(ip + mlt, 15362306a36Sopenharmony_ci base + dictLimit, 15462306a36Sopenharmony_ci iLimit); 15562306a36Sopenharmony_ci if (mlt > ml) { 15662306a36Sopenharmony_ci /* virtual matchpos */ 15762306a36Sopenharmony_ci ml = mlt; 15862306a36Sopenharmony_ci *matchpos = base + matchIndex; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci matchIndex -= DELTANEXTU16(matchIndex); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci return (int)ml; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch( 16962306a36Sopenharmony_ci LZ4HC_CCtx_internal *hc4, 17062306a36Sopenharmony_ci const BYTE * const ip, 17162306a36Sopenharmony_ci const BYTE * const iLowLimit, 17262306a36Sopenharmony_ci const BYTE * const iHighLimit, 17362306a36Sopenharmony_ci int longest, 17462306a36Sopenharmony_ci const BYTE **matchpos, 17562306a36Sopenharmony_ci const BYTE **startpos, 17662306a36Sopenharmony_ci const int maxNbAttempts) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci U16 * const chainTable = hc4->chainTable; 17962306a36Sopenharmony_ci U32 * const HashTable = hc4->hashTable; 18062306a36Sopenharmony_ci const BYTE * const base = hc4->base; 18162306a36Sopenharmony_ci const U32 dictLimit = hc4->dictLimit; 18262306a36Sopenharmony_ci const BYTE * const lowPrefixPtr = base + dictLimit; 18362306a36Sopenharmony_ci const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base)) 18462306a36Sopenharmony_ci ? hc4->lowLimit 18562306a36Sopenharmony_ci : (U32)(ip - base) - (64 * KB - 1); 18662306a36Sopenharmony_ci const BYTE * const dictBase = hc4->dictBase; 18762306a36Sopenharmony_ci U32 matchIndex; 18862306a36Sopenharmony_ci int nbAttempts = maxNbAttempts; 18962306a36Sopenharmony_ci int delta = (int)(ip - iLowLimit); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* First Match */ 19262306a36Sopenharmony_ci LZ4HC_Insert(hc4, ip); 19362306a36Sopenharmony_ci matchIndex = HashTable[LZ4HC_hashPtr(ip)]; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci while ((matchIndex >= lowLimit) 19662306a36Sopenharmony_ci && (nbAttempts)) { 19762306a36Sopenharmony_ci nbAttempts--; 19862306a36Sopenharmony_ci if (matchIndex >= dictLimit) { 19962306a36Sopenharmony_ci const BYTE *matchPtr = base + matchIndex; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if (*(iLowLimit + longest) 20262306a36Sopenharmony_ci == *(matchPtr - delta + longest)) { 20362306a36Sopenharmony_ci if (LZ4_read32(matchPtr) == LZ4_read32(ip)) { 20462306a36Sopenharmony_ci int mlt = MINMATCH + LZ4_count( 20562306a36Sopenharmony_ci ip + MINMATCH, 20662306a36Sopenharmony_ci matchPtr + MINMATCH, 20762306a36Sopenharmony_ci iHighLimit); 20862306a36Sopenharmony_ci int back = 0; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci while ((ip + back > iLowLimit) 21162306a36Sopenharmony_ci && (matchPtr + back > lowPrefixPtr) 21262306a36Sopenharmony_ci && (ip[back - 1] == matchPtr[back - 1])) 21362306a36Sopenharmony_ci back--; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci mlt -= back; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (mlt > longest) { 21862306a36Sopenharmony_ci longest = (int)mlt; 21962306a36Sopenharmony_ci *matchpos = matchPtr + back; 22062306a36Sopenharmony_ci *startpos = ip + back; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci } else { 22562306a36Sopenharmony_ci const BYTE * const matchPtr = dictBase + matchIndex; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (LZ4_read32(matchPtr) == LZ4_read32(ip)) { 22862306a36Sopenharmony_ci size_t mlt; 22962306a36Sopenharmony_ci int back = 0; 23062306a36Sopenharmony_ci const BYTE *vLimit = ip + (dictLimit - matchIndex); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (vLimit > iHighLimit) 23362306a36Sopenharmony_ci vLimit = iHighLimit; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci mlt = LZ4_count(ip + MINMATCH, 23662306a36Sopenharmony_ci matchPtr + MINMATCH, vLimit) + MINMATCH; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if ((ip + mlt == vLimit) && (vLimit < iHighLimit)) 23962306a36Sopenharmony_ci mlt += LZ4_count(ip + mlt, base + dictLimit, 24062306a36Sopenharmony_ci iHighLimit); 24162306a36Sopenharmony_ci while ((ip + back > iLowLimit) 24262306a36Sopenharmony_ci && (matchIndex + back > lowLimit) 24362306a36Sopenharmony_ci && (ip[back - 1] == matchPtr[back - 1])) 24462306a36Sopenharmony_ci back--; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci mlt -= back; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if ((int)mlt > longest) { 24962306a36Sopenharmony_ci longest = (int)mlt; 25062306a36Sopenharmony_ci *matchpos = base + matchIndex + back; 25162306a36Sopenharmony_ci *startpos = ip + back; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci matchIndex -= DELTANEXTU16(matchIndex); 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return longest; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_encodeSequence( 26362306a36Sopenharmony_ci const BYTE **ip, 26462306a36Sopenharmony_ci BYTE **op, 26562306a36Sopenharmony_ci const BYTE **anchor, 26662306a36Sopenharmony_ci int matchLength, 26762306a36Sopenharmony_ci const BYTE * const match, 26862306a36Sopenharmony_ci limitedOutput_directive limitedOutputBuffer, 26962306a36Sopenharmony_ci BYTE *oend) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci int length; 27262306a36Sopenharmony_ci BYTE *token; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* Encode Literal length */ 27562306a36Sopenharmony_ci length = (int)(*ip - *anchor); 27662306a36Sopenharmony_ci token = (*op)++; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if ((limitedOutputBuffer) 27962306a36Sopenharmony_ci && ((*op + (length>>8) 28062306a36Sopenharmony_ci + length + (2 + 1 + LASTLITERALS)) > oend)) { 28162306a36Sopenharmony_ci /* Check output limit */ 28262306a36Sopenharmony_ci return 1; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci if (length >= (int)RUN_MASK) { 28562306a36Sopenharmony_ci int len; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci *token = (RUN_MASK<<ML_BITS); 28862306a36Sopenharmony_ci len = length - RUN_MASK; 28962306a36Sopenharmony_ci for (; len > 254 ; len -= 255) 29062306a36Sopenharmony_ci *(*op)++ = 255; 29162306a36Sopenharmony_ci *(*op)++ = (BYTE)len; 29262306a36Sopenharmony_ci } else 29362306a36Sopenharmony_ci *token = (BYTE)(length<<ML_BITS); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* Copy Literals */ 29662306a36Sopenharmony_ci LZ4_wildCopy(*op, *anchor, (*op) + length); 29762306a36Sopenharmony_ci *op += length; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* Encode Offset */ 30062306a36Sopenharmony_ci LZ4_writeLE16(*op, (U16)(*ip - match)); 30162306a36Sopenharmony_ci *op += 2; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* Encode MatchLength */ 30462306a36Sopenharmony_ci length = (int)(matchLength - MINMATCH); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if ((limitedOutputBuffer) 30762306a36Sopenharmony_ci && (*op + (length>>8) 30862306a36Sopenharmony_ci + (1 + LASTLITERALS) > oend)) { 30962306a36Sopenharmony_ci /* Check output limit */ 31062306a36Sopenharmony_ci return 1; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (length >= (int)ML_MASK) { 31462306a36Sopenharmony_ci *token += ML_MASK; 31562306a36Sopenharmony_ci length -= ML_MASK; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci for (; length > 509 ; length -= 510) { 31862306a36Sopenharmony_ci *(*op)++ = 255; 31962306a36Sopenharmony_ci *(*op)++ = 255; 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (length > 254) { 32362306a36Sopenharmony_ci length -= 255; 32462306a36Sopenharmony_ci *(*op)++ = 255; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci *(*op)++ = (BYTE)length; 32862306a36Sopenharmony_ci } else 32962306a36Sopenharmony_ci *token += (BYTE)(length); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* Prepare next loop */ 33262306a36Sopenharmony_ci *ip += matchLength; 33362306a36Sopenharmony_ci *anchor = *ip; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci return 0; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic int LZ4HC_compress_generic( 33962306a36Sopenharmony_ci LZ4HC_CCtx_internal *const ctx, 34062306a36Sopenharmony_ci const char * const source, 34162306a36Sopenharmony_ci char * const dest, 34262306a36Sopenharmony_ci int const inputSize, 34362306a36Sopenharmony_ci int const maxOutputSize, 34462306a36Sopenharmony_ci int compressionLevel, 34562306a36Sopenharmony_ci limitedOutput_directive limit 34662306a36Sopenharmony_ci ) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci const BYTE *ip = (const BYTE *) source; 34962306a36Sopenharmony_ci const BYTE *anchor = ip; 35062306a36Sopenharmony_ci const BYTE * const iend = ip + inputSize; 35162306a36Sopenharmony_ci const BYTE * const mflimit = iend - MFLIMIT; 35262306a36Sopenharmony_ci const BYTE * const matchlimit = (iend - LASTLITERALS); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci BYTE *op = (BYTE *) dest; 35562306a36Sopenharmony_ci BYTE * const oend = op + maxOutputSize; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci unsigned int maxNbAttempts; 35862306a36Sopenharmony_ci int ml, ml2, ml3, ml0; 35962306a36Sopenharmony_ci const BYTE *ref = NULL; 36062306a36Sopenharmony_ci const BYTE *start2 = NULL; 36162306a36Sopenharmony_ci const BYTE *ref2 = NULL; 36262306a36Sopenharmony_ci const BYTE *start3 = NULL; 36362306a36Sopenharmony_ci const BYTE *ref3 = NULL; 36462306a36Sopenharmony_ci const BYTE *start0; 36562306a36Sopenharmony_ci const BYTE *ref0; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* init */ 36862306a36Sopenharmony_ci if (compressionLevel > LZ4HC_MAX_CLEVEL) 36962306a36Sopenharmony_ci compressionLevel = LZ4HC_MAX_CLEVEL; 37062306a36Sopenharmony_ci if (compressionLevel < 1) 37162306a36Sopenharmony_ci compressionLevel = LZ4HC_DEFAULT_CLEVEL; 37262306a36Sopenharmony_ci maxNbAttempts = 1 << (compressionLevel - 1); 37362306a36Sopenharmony_ci ctx->end += inputSize; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci ip++; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Main Loop */ 37862306a36Sopenharmony_ci while (ip < mflimit) { 37962306a36Sopenharmony_ci ml = LZ4HC_InsertAndFindBestMatch(ctx, ip, 38062306a36Sopenharmony_ci matchlimit, (&ref), maxNbAttempts); 38162306a36Sopenharmony_ci if (!ml) { 38262306a36Sopenharmony_ci ip++; 38362306a36Sopenharmony_ci continue; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* saved, in case we would skip too much */ 38762306a36Sopenharmony_ci start0 = ip; 38862306a36Sopenharmony_ci ref0 = ref; 38962306a36Sopenharmony_ci ml0 = ml; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci_Search2: 39262306a36Sopenharmony_ci if (ip + ml < mflimit) 39362306a36Sopenharmony_ci ml2 = LZ4HC_InsertAndGetWiderMatch(ctx, 39462306a36Sopenharmony_ci ip + ml - 2, ip + 0, 39562306a36Sopenharmony_ci matchlimit, ml, &ref2, 39662306a36Sopenharmony_ci &start2, maxNbAttempts); 39762306a36Sopenharmony_ci else 39862306a36Sopenharmony_ci ml2 = ml; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (ml2 == ml) { 40162306a36Sopenharmony_ci /* No better match */ 40262306a36Sopenharmony_ci if (LZ4HC_encodeSequence(&ip, &op, 40362306a36Sopenharmony_ci &anchor, ml, ref, limit, oend)) 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci continue; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (start0 < ip) { 40962306a36Sopenharmony_ci if (start2 < ip + ml0) { 41062306a36Sopenharmony_ci /* empirical */ 41162306a36Sopenharmony_ci ip = start0; 41262306a36Sopenharmony_ci ref = ref0; 41362306a36Sopenharmony_ci ml = ml0; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* Here, start0 == ip */ 41862306a36Sopenharmony_ci if ((start2 - ip) < 3) { 41962306a36Sopenharmony_ci /* First Match too small : removed */ 42062306a36Sopenharmony_ci ml = ml2; 42162306a36Sopenharmony_ci ip = start2; 42262306a36Sopenharmony_ci ref = ref2; 42362306a36Sopenharmony_ci goto _Search2; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci_Search3: 42762306a36Sopenharmony_ci /* 42862306a36Sopenharmony_ci * Currently we have : 42962306a36Sopenharmony_ci * ml2 > ml1, and 43062306a36Sopenharmony_ci * ip1 + 3 <= ip2 (usually < ip1 + ml1) 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_ci if ((start2 - ip) < OPTIMAL_ML) { 43362306a36Sopenharmony_ci int correction; 43462306a36Sopenharmony_ci int new_ml = ml; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (new_ml > OPTIMAL_ML) 43762306a36Sopenharmony_ci new_ml = OPTIMAL_ML; 43862306a36Sopenharmony_ci if (ip + new_ml > start2 + ml2 - MINMATCH) 43962306a36Sopenharmony_ci new_ml = (int)(start2 - ip) + ml2 - MINMATCH; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci correction = new_ml - (int)(start2 - ip); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (correction > 0) { 44462306a36Sopenharmony_ci start2 += correction; 44562306a36Sopenharmony_ci ref2 += correction; 44662306a36Sopenharmony_ci ml2 -= correction; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * Now, we have start2 = ip + new_ml, 45162306a36Sopenharmony_ci * with new_ml = min(ml, OPTIMAL_ML = 18) 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (start2 + ml2 < mflimit) 45562306a36Sopenharmony_ci ml3 = LZ4HC_InsertAndGetWiderMatch(ctx, 45662306a36Sopenharmony_ci start2 + ml2 - 3, start2, 45762306a36Sopenharmony_ci matchlimit, ml2, &ref3, &start3, 45862306a36Sopenharmony_ci maxNbAttempts); 45962306a36Sopenharmony_ci else 46062306a36Sopenharmony_ci ml3 = ml2; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (ml3 == ml2) { 46362306a36Sopenharmony_ci /* No better match : 2 sequences to encode */ 46462306a36Sopenharmony_ci /* ip & ref are known; Now for ml */ 46562306a36Sopenharmony_ci if (start2 < ip + ml) 46662306a36Sopenharmony_ci ml = (int)(start2 - ip); 46762306a36Sopenharmony_ci /* Now, encode 2 sequences */ 46862306a36Sopenharmony_ci if (LZ4HC_encodeSequence(&ip, &op, &anchor, 46962306a36Sopenharmony_ci ml, ref, limit, oend)) 47062306a36Sopenharmony_ci return 0; 47162306a36Sopenharmony_ci ip = start2; 47262306a36Sopenharmony_ci if (LZ4HC_encodeSequence(&ip, &op, &anchor, 47362306a36Sopenharmony_ci ml2, ref2, limit, oend)) 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci continue; 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (start3 < ip + ml + 3) { 47962306a36Sopenharmony_ci /* Not enough space for match 2 : remove it */ 48062306a36Sopenharmony_ci if (start3 >= (ip + ml)) { 48162306a36Sopenharmony_ci /* can write Seq1 immediately 48262306a36Sopenharmony_ci * ==> Seq2 is removed, 48362306a36Sopenharmony_ci * so Seq3 becomes Seq1 48462306a36Sopenharmony_ci */ 48562306a36Sopenharmony_ci if (start2 < ip + ml) { 48662306a36Sopenharmony_ci int correction = (int)(ip + ml - start2); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci start2 += correction; 48962306a36Sopenharmony_ci ref2 += correction; 49062306a36Sopenharmony_ci ml2 -= correction; 49162306a36Sopenharmony_ci if (ml2 < MINMATCH) { 49262306a36Sopenharmony_ci start2 = start3; 49362306a36Sopenharmony_ci ref2 = ref3; 49462306a36Sopenharmony_ci ml2 = ml3; 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (LZ4HC_encodeSequence(&ip, &op, &anchor, 49962306a36Sopenharmony_ci ml, ref, limit, oend)) 50062306a36Sopenharmony_ci return 0; 50162306a36Sopenharmony_ci ip = start3; 50262306a36Sopenharmony_ci ref = ref3; 50362306a36Sopenharmony_ci ml = ml3; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci start0 = start2; 50662306a36Sopenharmony_ci ref0 = ref2; 50762306a36Sopenharmony_ci ml0 = ml2; 50862306a36Sopenharmony_ci goto _Search2; 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci start2 = start3; 51262306a36Sopenharmony_ci ref2 = ref3; 51362306a36Sopenharmony_ci ml2 = ml3; 51462306a36Sopenharmony_ci goto _Search3; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci /* 51862306a36Sopenharmony_ci * OK, now we have 3 ascending matches; 51962306a36Sopenharmony_ci * let's write at least the first one 52062306a36Sopenharmony_ci * ip & ref are known; Now for ml 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ci if (start2 < ip + ml) { 52362306a36Sopenharmony_ci if ((start2 - ip) < (int)ML_MASK) { 52462306a36Sopenharmony_ci int correction; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (ml > OPTIMAL_ML) 52762306a36Sopenharmony_ci ml = OPTIMAL_ML; 52862306a36Sopenharmony_ci if (ip + ml > start2 + ml2 - MINMATCH) 52962306a36Sopenharmony_ci ml = (int)(start2 - ip) + ml2 - MINMATCH; 53062306a36Sopenharmony_ci correction = ml - (int)(start2 - ip); 53162306a36Sopenharmony_ci if (correction > 0) { 53262306a36Sopenharmony_ci start2 += correction; 53362306a36Sopenharmony_ci ref2 += correction; 53462306a36Sopenharmony_ci ml2 -= correction; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci } else 53762306a36Sopenharmony_ci ml = (int)(start2 - ip); 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml, 54062306a36Sopenharmony_ci ref, limit, oend)) 54162306a36Sopenharmony_ci return 0; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci ip = start2; 54462306a36Sopenharmony_ci ref = ref2; 54562306a36Sopenharmony_ci ml = ml2; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci start2 = start3; 54862306a36Sopenharmony_ci ref2 = ref3; 54962306a36Sopenharmony_ci ml2 = ml3; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci goto _Search3; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* Encode Last Literals */ 55562306a36Sopenharmony_ci { 55662306a36Sopenharmony_ci int lastRun = (int)(iend - anchor); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if ((limit) 55962306a36Sopenharmony_ci && (((char *)op - dest) + lastRun + 1 56062306a36Sopenharmony_ci + ((lastRun + 255 - RUN_MASK)/255) 56162306a36Sopenharmony_ci > (U32)maxOutputSize)) { 56262306a36Sopenharmony_ci /* Check output limit */ 56362306a36Sopenharmony_ci return 0; 56462306a36Sopenharmony_ci } 56562306a36Sopenharmony_ci if (lastRun >= (int)RUN_MASK) { 56662306a36Sopenharmony_ci *op++ = (RUN_MASK<<ML_BITS); 56762306a36Sopenharmony_ci lastRun -= RUN_MASK; 56862306a36Sopenharmony_ci for (; lastRun > 254 ; lastRun -= 255) 56962306a36Sopenharmony_ci *op++ = 255; 57062306a36Sopenharmony_ci *op++ = (BYTE) lastRun; 57162306a36Sopenharmony_ci } else 57262306a36Sopenharmony_ci *op++ = (BYTE)(lastRun<<ML_BITS); 57362306a36Sopenharmony_ci LZ4_memcpy(op, anchor, iend - anchor); 57462306a36Sopenharmony_ci op += iend - anchor; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci /* End */ 57862306a36Sopenharmony_ci return (int) (((char *)op) - dest); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic int LZ4_compress_HC_extStateHC( 58262306a36Sopenharmony_ci void *state, 58362306a36Sopenharmony_ci const char *src, 58462306a36Sopenharmony_ci char *dst, 58562306a36Sopenharmony_ci int srcSize, 58662306a36Sopenharmony_ci int maxDstSize, 58762306a36Sopenharmony_ci int compressionLevel) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t *)state)->internal_donotuse; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (((size_t)(state)&(sizeof(void *) - 1)) != 0) { 59262306a36Sopenharmony_ci /* Error : state is not aligned 59362306a36Sopenharmony_ci * for pointers (32 or 64 bits) 59462306a36Sopenharmony_ci */ 59562306a36Sopenharmony_ci return 0; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci LZ4HC_init(ctx, (const BYTE *)src); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (maxDstSize < LZ4_compressBound(srcSize)) 60162306a36Sopenharmony_ci return LZ4HC_compress_generic(ctx, src, dst, 60262306a36Sopenharmony_ci srcSize, maxDstSize, compressionLevel, limitedOutput); 60362306a36Sopenharmony_ci else 60462306a36Sopenharmony_ci return LZ4HC_compress_generic(ctx, src, dst, 60562306a36Sopenharmony_ci srcSize, maxDstSize, compressionLevel, noLimit); 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ciint LZ4_compress_HC(const char *src, char *dst, int srcSize, 60962306a36Sopenharmony_ci int maxDstSize, int compressionLevel, void *wrkmem) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci return LZ4_compress_HC_extStateHC(wrkmem, src, dst, 61262306a36Sopenharmony_ci srcSize, maxDstSize, compressionLevel); 61362306a36Sopenharmony_ci} 61462306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_HC); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci/************************************** 61762306a36Sopenharmony_ci * Streaming Functions 61862306a36Sopenharmony_ci **************************************/ 61962306a36Sopenharmony_civoid LZ4_resetStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci LZ4_streamHCPtr->internal_donotuse.base = NULL; 62262306a36Sopenharmony_ci LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned int)compressionLevel; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciint LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr, 62662306a36Sopenharmony_ci const char *dictionary, 62762306a36Sopenharmony_ci int dictSize) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (dictSize > 64 * KB) { 63262306a36Sopenharmony_ci dictionary += dictSize - 64 * KB; 63362306a36Sopenharmony_ci dictSize = 64 * KB; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci LZ4HC_init(ctxPtr, (const BYTE *)dictionary); 63662306a36Sopenharmony_ci if (dictSize >= 4) 63762306a36Sopenharmony_ci LZ4HC_Insert(ctxPtr, (const BYTE *)dictionary + (dictSize - 3)); 63862306a36Sopenharmony_ci ctxPtr->end = (const BYTE *)dictionary + dictSize; 63962306a36Sopenharmony_ci return dictSize; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_loadDictHC); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci/* compression */ 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic void LZ4HC_setExternalDict( 64662306a36Sopenharmony_ci LZ4HC_CCtx_internal *ctxPtr, 64762306a36Sopenharmony_ci const BYTE *newBlock) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci if (ctxPtr->end >= ctxPtr->base + 4) { 65062306a36Sopenharmony_ci /* Referencing remaining dictionary content */ 65162306a36Sopenharmony_ci LZ4HC_Insert(ctxPtr, ctxPtr->end - 3); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* 65562306a36Sopenharmony_ci * Only one memory segment for extDict, 65662306a36Sopenharmony_ci * so any previous extDict is lost at this stage 65762306a36Sopenharmony_ci */ 65862306a36Sopenharmony_ci ctxPtr->lowLimit = ctxPtr->dictLimit; 65962306a36Sopenharmony_ci ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base); 66062306a36Sopenharmony_ci ctxPtr->dictBase = ctxPtr->base; 66162306a36Sopenharmony_ci ctxPtr->base = newBlock - ctxPtr->dictLimit; 66262306a36Sopenharmony_ci ctxPtr->end = newBlock; 66362306a36Sopenharmony_ci /* match referencing will resume from there */ 66462306a36Sopenharmony_ci ctxPtr->nextToUpdate = ctxPtr->dictLimit; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic int LZ4_compressHC_continue_generic( 66862306a36Sopenharmony_ci LZ4_streamHC_t *LZ4_streamHCPtr, 66962306a36Sopenharmony_ci const char *source, 67062306a36Sopenharmony_ci char *dest, 67162306a36Sopenharmony_ci int inputSize, 67262306a36Sopenharmony_ci int maxOutputSize, 67362306a36Sopenharmony_ci limitedOutput_directive limit) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* auto - init if forgotten */ 67862306a36Sopenharmony_ci if (ctxPtr->base == NULL) 67962306a36Sopenharmony_ci LZ4HC_init(ctxPtr, (const BYTE *) source); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* Check overflow */ 68262306a36Sopenharmony_ci if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 * GB) { 68362306a36Sopenharmony_ci size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) 68462306a36Sopenharmony_ci - ctxPtr->dictLimit; 68562306a36Sopenharmony_ci if (dictSize > 64 * KB) 68662306a36Sopenharmony_ci dictSize = 64 * KB; 68762306a36Sopenharmony_ci LZ4_loadDictHC(LZ4_streamHCPtr, 68862306a36Sopenharmony_ci (const char *)(ctxPtr->end) - dictSize, (int)dictSize); 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* Check if blocks follow each other */ 69262306a36Sopenharmony_ci if ((const BYTE *)source != ctxPtr->end) 69362306a36Sopenharmony_ci LZ4HC_setExternalDict(ctxPtr, (const BYTE *)source); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* Check overlapping input/dictionary space */ 69662306a36Sopenharmony_ci { 69762306a36Sopenharmony_ci const BYTE *sourceEnd = (const BYTE *) source + inputSize; 69862306a36Sopenharmony_ci const BYTE * const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit; 69962306a36Sopenharmony_ci const BYTE * const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if ((sourceEnd > dictBegin) 70262306a36Sopenharmony_ci && ((const BYTE *)source < dictEnd)) { 70362306a36Sopenharmony_ci if (sourceEnd > dictEnd) 70462306a36Sopenharmony_ci sourceEnd = dictEnd; 70562306a36Sopenharmony_ci ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) 70862306a36Sopenharmony_ci ctxPtr->lowLimit = ctxPtr->dictLimit; 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci return LZ4HC_compress_generic(ctxPtr, source, dest, 71362306a36Sopenharmony_ci inputSize, maxOutputSize, ctxPtr->compressionLevel, limit); 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ciint LZ4_compress_HC_continue( 71762306a36Sopenharmony_ci LZ4_streamHC_t *LZ4_streamHCPtr, 71862306a36Sopenharmony_ci const char *source, 71962306a36Sopenharmony_ci char *dest, 72062306a36Sopenharmony_ci int inputSize, 72162306a36Sopenharmony_ci int maxOutputSize) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci if (maxOutputSize < LZ4_compressBound(inputSize)) 72462306a36Sopenharmony_ci return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, 72562306a36Sopenharmony_ci source, dest, inputSize, maxOutputSize, limitedOutput); 72662306a36Sopenharmony_ci else 72762306a36Sopenharmony_ci return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, 72862306a36Sopenharmony_ci source, dest, inputSize, maxOutputSize, noLimit); 72962306a36Sopenharmony_ci} 73062306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_HC_continue); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci/* dictionary saving */ 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ciint LZ4_saveDictHC( 73562306a36Sopenharmony_ci LZ4_streamHC_t *LZ4_streamHCPtr, 73662306a36Sopenharmony_ci char *safeBuffer, 73762306a36Sopenharmony_ci int dictSize) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci LZ4HC_CCtx_internal *const streamPtr = &LZ4_streamHCPtr->internal_donotuse; 74062306a36Sopenharmony_ci int const prefixSize = (int)(streamPtr->end 74162306a36Sopenharmony_ci - (streamPtr->base + streamPtr->dictLimit)); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (dictSize > 64 * KB) 74462306a36Sopenharmony_ci dictSize = 64 * KB; 74562306a36Sopenharmony_ci if (dictSize < 4) 74662306a36Sopenharmony_ci dictSize = 0; 74762306a36Sopenharmony_ci if (dictSize > prefixSize) 74862306a36Sopenharmony_ci dictSize = prefixSize; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci memmove(safeBuffer, streamPtr->end - dictSize, dictSize); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci { 75362306a36Sopenharmony_ci U32 const endIndex = (U32)(streamPtr->end - streamPtr->base); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci streamPtr->end = (const BYTE *)safeBuffer + dictSize; 75662306a36Sopenharmony_ci streamPtr->base = streamPtr->end - endIndex; 75762306a36Sopenharmony_ci streamPtr->dictLimit = endIndex - dictSize; 75862306a36Sopenharmony_ci streamPtr->lowLimit = endIndex - dictSize; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci if (streamPtr->nextToUpdate < streamPtr->dictLimit) 76162306a36Sopenharmony_ci streamPtr->nextToUpdate = streamPtr->dictLimit; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci return dictSize; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_saveDictHC); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 76862306a36Sopenharmony_ciMODULE_DESCRIPTION("LZ4 HC compressor"); 769