770 lines · c
1/*2 * LZ4 HC - High Compression Mode of LZ43 * Copyright (C) 2011-2015, Yann Collet.4 *5 * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)6 * Redistribution and use in source and binary forms, with or without7 * modification, are permitted provided that the following conditions are8 * met:9 * * Redistributions of source code must retain the above copyright10 * notice, this list of conditions and the following disclaimer.11 * * Redistributions in binary form must reproduce the above12 * copyright notice, this list of conditions and the following disclaimer13 * in the documentation and/or other materials provided with the14 * distribution.15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.26 * You can contact the author at :27 * - LZ4 homepage : http://www.lz4.org28 * - LZ4 source repository : https://github.com/lz4/lz429 *30 * Changed for kernel usage by:31 * Sven Schmidt <4sschmid@informatik.uni-hamburg.de>32 */33 34/*-************************************35 * Dependencies36 **************************************/37#include <linux/lz4.h>38#include "lz4defs.h"39#include <linux/module.h>40#include <linux/kernel.h>41#include <linux/string.h> /* memset */42 43/* *************************************44 * Local Constants and types45 ***************************************/46 47#define OPTIMAL_ML (int)((ML_MASK - 1) + MINMATCH)48 49#define HASH_FUNCTION(i) (((i) * 2654435761U) \50 >> ((MINMATCH*8) - LZ4HC_HASH_LOG))51#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */52 53static U32 LZ4HC_hashPtr(const void *ptr)54{55 return HASH_FUNCTION(LZ4_read32(ptr));56}57 58/**************************************59 * HC Compression60 **************************************/61static void LZ4HC_init(LZ4HC_CCtx_internal *hc4, const BYTE *start)62{63 memset((void *)hc4->hashTable, 0, sizeof(hc4->hashTable));64 memset(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));65 hc4->nextToUpdate = 64 * KB;66 hc4->base = start - 64 * KB;67 hc4->end = start;68 hc4->dictBase = start - 64 * KB;69 hc4->dictLimit = 64 * KB;70 hc4->lowLimit = 64 * KB;71}72 73/* Update chains up to ip (excluded) */74static FORCE_INLINE void LZ4HC_Insert(LZ4HC_CCtx_internal *hc4,75 const BYTE *ip)76{77 U16 * const chainTable = hc4->chainTable;78 U32 * const hashTable = hc4->hashTable;79 const BYTE * const base = hc4->base;80 U32 const target = (U32)(ip - base);81 U32 idx = hc4->nextToUpdate;82 83 while (idx < target) {84 U32 const h = LZ4HC_hashPtr(base + idx);85 size_t delta = idx - hashTable[h];86 87 if (delta > MAX_DISTANCE)88 delta = MAX_DISTANCE;89 90 DELTANEXTU16(idx) = (U16)delta;91 92 hashTable[h] = idx;93 idx++;94 }95 96 hc4->nextToUpdate = target;97}98 99static FORCE_INLINE int LZ4HC_InsertAndFindBestMatch(100 LZ4HC_CCtx_internal *hc4, /* Index table will be updated */101 const BYTE *ip,102 const BYTE * const iLimit,103 const BYTE **matchpos,104 const int maxNbAttempts)105{106 U16 * const chainTable = hc4->chainTable;107 U32 * const HashTable = hc4->hashTable;108 const BYTE * const base = hc4->base;109 const BYTE * const dictBase = hc4->dictBase;110 const U32 dictLimit = hc4->dictLimit;111 const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))112 ? hc4->lowLimit113 : (U32)(ip - base) - (64 * KB - 1);114 U32 matchIndex;115 int nbAttempts = maxNbAttempts;116 size_t ml = 0;117 118 /* HC4 match finder */119 LZ4HC_Insert(hc4, ip);120 matchIndex = HashTable[LZ4HC_hashPtr(ip)];121 122 while ((matchIndex >= lowLimit)123 && (nbAttempts)) {124 nbAttempts--;125 if (matchIndex >= dictLimit) {126 const BYTE * const match = base + matchIndex;127 128 if (*(match + ml) == *(ip + ml)129 && (LZ4_read32(match) == LZ4_read32(ip))) {130 size_t const mlt = LZ4_count(ip + MINMATCH,131 match + MINMATCH, iLimit) + MINMATCH;132 133 if (mlt > ml) {134 ml = mlt;135 *matchpos = match;136 }137 }138 } else {139 const BYTE * const match = dictBase + matchIndex;140 141 if (LZ4_read32(match) == LZ4_read32(ip)) {142 size_t mlt;143 const BYTE *vLimit = ip144 + (dictLimit - matchIndex);145 146 if (vLimit > iLimit)147 vLimit = iLimit;148 mlt = LZ4_count(ip + MINMATCH,149 match + MINMATCH, vLimit) + MINMATCH;150 if ((ip + mlt == vLimit)151 && (vLimit < iLimit))152 mlt += LZ4_count(ip + mlt,153 base + dictLimit,154 iLimit);155 if (mlt > ml) {156 /* virtual matchpos */157 ml = mlt;158 *matchpos = base + matchIndex;159 }160 }161 }162 matchIndex -= DELTANEXTU16(matchIndex);163 }164 165 return (int)ml;166}167 168static FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch(169 LZ4HC_CCtx_internal *hc4,170 const BYTE * const ip,171 const BYTE * const iLowLimit,172 const BYTE * const iHighLimit,173 int longest,174 const BYTE **matchpos,175 const BYTE **startpos,176 const int maxNbAttempts)177{178 U16 * const chainTable = hc4->chainTable;179 U32 * const HashTable = hc4->hashTable;180 const BYTE * const base = hc4->base;181 const U32 dictLimit = hc4->dictLimit;182 const BYTE * const lowPrefixPtr = base + dictLimit;183 const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))184 ? hc4->lowLimit185 : (U32)(ip - base) - (64 * KB - 1);186 const BYTE * const dictBase = hc4->dictBase;187 U32 matchIndex;188 int nbAttempts = maxNbAttempts;189 int delta = (int)(ip - iLowLimit);190 191 /* First Match */192 LZ4HC_Insert(hc4, ip);193 matchIndex = HashTable[LZ4HC_hashPtr(ip)];194 195 while ((matchIndex >= lowLimit)196 && (nbAttempts)) {197 nbAttempts--;198 if (matchIndex >= dictLimit) {199 const BYTE *matchPtr = base + matchIndex;200 201 if (*(iLowLimit + longest)202 == *(matchPtr - delta + longest)) {203 if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {204 int mlt = MINMATCH + LZ4_count(205 ip + MINMATCH,206 matchPtr + MINMATCH,207 iHighLimit);208 int back = 0;209 210 while ((ip + back > iLowLimit)211 && (matchPtr + back > lowPrefixPtr)212 && (ip[back - 1] == matchPtr[back - 1]))213 back--;214 215 mlt -= back;216 217 if (mlt > longest) {218 longest = (int)mlt;219 *matchpos = matchPtr + back;220 *startpos = ip + back;221 }222 }223 }224 } else {225 const BYTE * const matchPtr = dictBase + matchIndex;226 227 if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {228 size_t mlt;229 int back = 0;230 const BYTE *vLimit = ip + (dictLimit - matchIndex);231 232 if (vLimit > iHighLimit)233 vLimit = iHighLimit;234 235 mlt = LZ4_count(ip + MINMATCH,236 matchPtr + MINMATCH, vLimit) + MINMATCH;237 238 if ((ip + mlt == vLimit) && (vLimit < iHighLimit))239 mlt += LZ4_count(ip + mlt, base + dictLimit,240 iHighLimit);241 while ((ip + back > iLowLimit)242 && (matchIndex + back > lowLimit)243 && (ip[back - 1] == matchPtr[back - 1]))244 back--;245 246 mlt -= back;247 248 if ((int)mlt > longest) {249 longest = (int)mlt;250 *matchpos = base + matchIndex + back;251 *startpos = ip + back;252 }253 }254 }255 256 matchIndex -= DELTANEXTU16(matchIndex);257 }258 259 return longest;260}261 262static FORCE_INLINE int LZ4HC_encodeSequence(263 const BYTE **ip,264 BYTE **op,265 const BYTE **anchor,266 int matchLength,267 const BYTE * const match,268 limitedOutput_directive limitedOutputBuffer,269 BYTE *oend)270{271 int length;272 BYTE *token;273 274 /* Encode Literal length */275 length = (int)(*ip - *anchor);276 token = (*op)++;277 278 if ((limitedOutputBuffer)279 && ((*op + (length>>8)280 + length + (2 + 1 + LASTLITERALS)) > oend)) {281 /* Check output limit */282 return 1;283 }284 if (length >= (int)RUN_MASK) {285 int len;286 287 *token = (RUN_MASK<<ML_BITS);288 len = length - RUN_MASK;289 for (; len > 254 ; len -= 255)290 *(*op)++ = 255;291 *(*op)++ = (BYTE)len;292 } else293 *token = (BYTE)(length<<ML_BITS);294 295 /* Copy Literals */296 LZ4_wildCopy(*op, *anchor, (*op) + length);297 *op += length;298 299 /* Encode Offset */300 LZ4_writeLE16(*op, (U16)(*ip - match));301 *op += 2;302 303 /* Encode MatchLength */304 length = (int)(matchLength - MINMATCH);305 306 if ((limitedOutputBuffer)307 && (*op + (length>>8)308 + (1 + LASTLITERALS) > oend)) {309 /* Check output limit */310 return 1;311 }312 313 if (length >= (int)ML_MASK) {314 *token += ML_MASK;315 length -= ML_MASK;316 317 for (; length > 509 ; length -= 510) {318 *(*op)++ = 255;319 *(*op)++ = 255;320 }321 322 if (length > 254) {323 length -= 255;324 *(*op)++ = 255;325 }326 327 *(*op)++ = (BYTE)length;328 } else329 *token += (BYTE)(length);330 331 /* Prepare next loop */332 *ip += matchLength;333 *anchor = *ip;334 335 return 0;336}337 338static int LZ4HC_compress_generic(339 LZ4HC_CCtx_internal *const ctx,340 const char * const source,341 char * const dest,342 int const inputSize,343 int const maxOutputSize,344 int compressionLevel,345 limitedOutput_directive limit346 )347{348 const BYTE *ip = (const BYTE *) source;349 const BYTE *anchor = ip;350 const BYTE * const iend = ip + inputSize;351 const BYTE * const mflimit = iend - MFLIMIT;352 const BYTE * const matchlimit = (iend - LASTLITERALS);353 354 BYTE *op = (BYTE *) dest;355 BYTE * const oend = op + maxOutputSize;356 357 unsigned int maxNbAttempts;358 int ml, ml2, ml3, ml0;359 const BYTE *ref = NULL;360 const BYTE *start2 = NULL;361 const BYTE *ref2 = NULL;362 const BYTE *start3 = NULL;363 const BYTE *ref3 = NULL;364 const BYTE *start0;365 const BYTE *ref0;366 367 /* init */368 if (compressionLevel > LZ4HC_MAX_CLEVEL)369 compressionLevel = LZ4HC_MAX_CLEVEL;370 if (compressionLevel < 1)371 compressionLevel = LZ4HC_DEFAULT_CLEVEL;372 maxNbAttempts = 1 << (compressionLevel - 1);373 ctx->end += inputSize;374 375 ip++;376 377 /* Main Loop */378 while (ip < mflimit) {379 ml = LZ4HC_InsertAndFindBestMatch(ctx, ip,380 matchlimit, (&ref), maxNbAttempts);381 if (!ml) {382 ip++;383 continue;384 }385 386 /* saved, in case we would skip too much */387 start0 = ip;388 ref0 = ref;389 ml0 = ml;390 391_Search2:392 if (ip + ml < mflimit)393 ml2 = LZ4HC_InsertAndGetWiderMatch(ctx,394 ip + ml - 2, ip + 0,395 matchlimit, ml, &ref2,396 &start2, maxNbAttempts);397 else398 ml2 = ml;399 400 if (ml2 == ml) {401 /* No better match */402 if (LZ4HC_encodeSequence(&ip, &op,403 &anchor, ml, ref, limit, oend))404 return 0;405 continue;406 }407 408 if (start0 < ip) {409 if (start2 < ip + ml0) {410 /* empirical */411 ip = start0;412 ref = ref0;413 ml = ml0;414 }415 }416 417 /* Here, start0 == ip */418 if ((start2 - ip) < 3) {419 /* First Match too small : removed */420 ml = ml2;421 ip = start2;422 ref = ref2;423 goto _Search2;424 }425 426_Search3:427 /*428 * Currently we have :429 * ml2 > ml1, and430 * ip1 + 3 <= ip2 (usually < ip1 + ml1)431 */432 if ((start2 - ip) < OPTIMAL_ML) {433 int correction;434 int new_ml = ml;435 436 if (new_ml > OPTIMAL_ML)437 new_ml = OPTIMAL_ML;438 if (ip + new_ml > start2 + ml2 - MINMATCH)439 new_ml = (int)(start2 - ip) + ml2 - MINMATCH;440 441 correction = new_ml - (int)(start2 - ip);442 443 if (correction > 0) {444 start2 += correction;445 ref2 += correction;446 ml2 -= correction;447 }448 }449 /*450 * Now, we have start2 = ip + new_ml,451 * with new_ml = min(ml, OPTIMAL_ML = 18)452 */453 454 if (start2 + ml2 < mflimit)455 ml3 = LZ4HC_InsertAndGetWiderMatch(ctx,456 start2 + ml2 - 3, start2,457 matchlimit, ml2, &ref3, &start3,458 maxNbAttempts);459 else460 ml3 = ml2;461 462 if (ml3 == ml2) {463 /* No better match : 2 sequences to encode */464 /* ip & ref are known; Now for ml */465 if (start2 < ip + ml)466 ml = (int)(start2 - ip);467 /* Now, encode 2 sequences */468 if (LZ4HC_encodeSequence(&ip, &op, &anchor,469 ml, ref, limit, oend))470 return 0;471 ip = start2;472 if (LZ4HC_encodeSequence(&ip, &op, &anchor,473 ml2, ref2, limit, oend))474 return 0;475 continue;476 }477 478 if (start3 < ip + ml + 3) {479 /* Not enough space for match 2 : remove it */480 if (start3 >= (ip + ml)) {481 /* can write Seq1 immediately482 * ==> Seq2 is removed,483 * so Seq3 becomes Seq1484 */485 if (start2 < ip + ml) {486 int correction = (int)(ip + ml - start2);487 488 start2 += correction;489 ref2 += correction;490 ml2 -= correction;491 if (ml2 < MINMATCH) {492 start2 = start3;493 ref2 = ref3;494 ml2 = ml3;495 }496 }497 498 if (LZ4HC_encodeSequence(&ip, &op, &anchor,499 ml, ref, limit, oend))500 return 0;501 ip = start3;502 ref = ref3;503 ml = ml3;504 505 start0 = start2;506 ref0 = ref2;507 ml0 = ml2;508 goto _Search2;509 }510 511 start2 = start3;512 ref2 = ref3;513 ml2 = ml3;514 goto _Search3;515 }516 517 /*518 * OK, now we have 3 ascending matches;519 * let's write at least the first one520 * ip & ref are known; Now for ml521 */522 if (start2 < ip + ml) {523 if ((start2 - ip) < (int)ML_MASK) {524 int correction;525 526 if (ml > OPTIMAL_ML)527 ml = OPTIMAL_ML;528 if (ip + ml > start2 + ml2 - MINMATCH)529 ml = (int)(start2 - ip) + ml2 - MINMATCH;530 correction = ml - (int)(start2 - ip);531 if (correction > 0) {532 start2 += correction;533 ref2 += correction;534 ml2 -= correction;535 }536 } else537 ml = (int)(start2 - ip);538 }539 if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml,540 ref, limit, oend))541 return 0;542 543 ip = start2;544 ref = ref2;545 ml = ml2;546 547 start2 = start3;548 ref2 = ref3;549 ml2 = ml3;550 551 goto _Search3;552 }553 554 /* Encode Last Literals */555 {556 int lastRun = (int)(iend - anchor);557 558 if ((limit)559 && (((char *)op - dest) + lastRun + 1560 + ((lastRun + 255 - RUN_MASK)/255)561 > (U32)maxOutputSize)) {562 /* Check output limit */563 return 0;564 }565 if (lastRun >= (int)RUN_MASK) {566 *op++ = (RUN_MASK<<ML_BITS);567 lastRun -= RUN_MASK;568 for (; lastRun > 254 ; lastRun -= 255)569 *op++ = 255;570 *op++ = (BYTE) lastRun;571 } else572 *op++ = (BYTE)(lastRun<<ML_BITS);573 LZ4_memcpy(op, anchor, iend - anchor);574 op += iend - anchor;575 }576 577 /* End */578 return (int) (((char *)op) - dest);579}580 581static int LZ4_compress_HC_extStateHC(582 void *state,583 const char *src,584 char *dst,585 int srcSize,586 int maxDstSize,587 int compressionLevel)588{589 LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t *)state)->internal_donotuse;590 591 if (((size_t)(state)&(sizeof(void *) - 1)) != 0) {592 /* Error : state is not aligned593 * for pointers (32 or 64 bits)594 */595 return 0;596 }597 598 LZ4HC_init(ctx, (const BYTE *)src);599 600 if (maxDstSize < LZ4_compressBound(srcSize))601 return LZ4HC_compress_generic(ctx, src, dst,602 srcSize, maxDstSize, compressionLevel, limitedOutput);603 else604 return LZ4HC_compress_generic(ctx, src, dst,605 srcSize, maxDstSize, compressionLevel, noLimit);606}607 608int LZ4_compress_HC(const char *src, char *dst, int srcSize,609 int maxDstSize, int compressionLevel, void *wrkmem)610{611 return LZ4_compress_HC_extStateHC(wrkmem, src, dst,612 srcSize, maxDstSize, compressionLevel);613}614EXPORT_SYMBOL(LZ4_compress_HC);615 616/**************************************617 * Streaming Functions618 **************************************/619void LZ4_resetStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)620{621 LZ4_streamHCPtr->internal_donotuse.base = NULL;622 LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned int)compressionLevel;623}624EXPORT_SYMBOL(LZ4_resetStreamHC);625 626int LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr,627 const char *dictionary,628 int dictSize)629{630 LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;631 632 if (dictSize > 64 * KB) {633 dictionary += dictSize - 64 * KB;634 dictSize = 64 * KB;635 }636 LZ4HC_init(ctxPtr, (const BYTE *)dictionary);637 if (dictSize >= 4)638 LZ4HC_Insert(ctxPtr, (const BYTE *)dictionary + (dictSize - 3));639 ctxPtr->end = (const BYTE *)dictionary + dictSize;640 return dictSize;641}642EXPORT_SYMBOL(LZ4_loadDictHC);643 644/* compression */645 646static void LZ4HC_setExternalDict(647 LZ4HC_CCtx_internal *ctxPtr,648 const BYTE *newBlock)649{650 if (ctxPtr->end >= ctxPtr->base + 4) {651 /* Referencing remaining dictionary content */652 LZ4HC_Insert(ctxPtr, ctxPtr->end - 3);653 }654 655 /*656 * Only one memory segment for extDict,657 * so any previous extDict is lost at this stage658 */659 ctxPtr->lowLimit = ctxPtr->dictLimit;660 ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);661 ctxPtr->dictBase = ctxPtr->base;662 ctxPtr->base = newBlock - ctxPtr->dictLimit;663 ctxPtr->end = newBlock;664 /* match referencing will resume from there */665 ctxPtr->nextToUpdate = ctxPtr->dictLimit;666}667 668static int LZ4_compressHC_continue_generic(669 LZ4_streamHC_t *LZ4_streamHCPtr,670 const char *source,671 char *dest,672 int inputSize,673 int maxOutputSize,674 limitedOutput_directive limit)675{676 LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;677 678 /* auto - init if forgotten */679 if (ctxPtr->base == NULL)680 LZ4HC_init(ctxPtr, (const BYTE *) source);681 682 /* Check overflow */683 if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 * GB) {684 size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base)685 - ctxPtr->dictLimit;686 if (dictSize > 64 * KB)687 dictSize = 64 * KB;688 LZ4_loadDictHC(LZ4_streamHCPtr,689 (const char *)(ctxPtr->end) - dictSize, (int)dictSize);690 }691 692 /* Check if blocks follow each other */693 if ((const BYTE *)source != ctxPtr->end)694 LZ4HC_setExternalDict(ctxPtr, (const BYTE *)source);695 696 /* Check overlapping input/dictionary space */697 {698 const BYTE *sourceEnd = (const BYTE *) source + inputSize;699 const BYTE * const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;700 const BYTE * const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;701 702 if ((sourceEnd > dictBegin)703 && ((const BYTE *)source < dictEnd)) {704 if (sourceEnd > dictEnd)705 sourceEnd = dictEnd;706 ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);707 708 if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4)709 ctxPtr->lowLimit = ctxPtr->dictLimit;710 }711 }712 713 return LZ4HC_compress_generic(ctxPtr, source, dest,714 inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);715}716 717int LZ4_compress_HC_continue(718 LZ4_streamHC_t *LZ4_streamHCPtr,719 const char *source,720 char *dest,721 int inputSize,722 int maxOutputSize)723{724 if (maxOutputSize < LZ4_compressBound(inputSize))725 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,726 source, dest, inputSize, maxOutputSize, limitedOutput);727 else728 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,729 source, dest, inputSize, maxOutputSize, noLimit);730}731EXPORT_SYMBOL(LZ4_compress_HC_continue);732 733/* dictionary saving */734 735int LZ4_saveDictHC(736 LZ4_streamHC_t *LZ4_streamHCPtr,737 char *safeBuffer,738 int dictSize)739{740 LZ4HC_CCtx_internal *const streamPtr = &LZ4_streamHCPtr->internal_donotuse;741 int const prefixSize = (int)(streamPtr->end742 - (streamPtr->base + streamPtr->dictLimit));743 744 if (dictSize > 64 * KB)745 dictSize = 64 * KB;746 if (dictSize < 4)747 dictSize = 0;748 if (dictSize > prefixSize)749 dictSize = prefixSize;750 751 memmove(safeBuffer, streamPtr->end - dictSize, dictSize);752 753 {754 U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);755 756 streamPtr->end = (const BYTE *)safeBuffer + dictSize;757 streamPtr->base = streamPtr->end - endIndex;758 streamPtr->dictLimit = endIndex - dictSize;759 streamPtr->lowLimit = endIndex - dictSize;760 761 if (streamPtr->nextToUpdate < streamPtr->dictLimit)762 streamPtr->nextToUpdate = streamPtr->dictLimit;763 }764 return dictSize;765}766EXPORT_SYMBOL(LZ4_saveDictHC);767 768MODULE_LICENSE("Dual BSD/GPL");769MODULE_DESCRIPTION("LZ4 HC compressor");770