0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/lz4.h>
0038 #include "lz4defs.h"
0039 #include <linux/module.h>
0040 #include <linux/kernel.h>
0041 #include <linux/string.h> /* memset */
0042
0043
0044
0045
0046
0047 #define OPTIMAL_ML (int)((ML_MASK - 1) + MINMATCH)
0048
0049 #define HASH_FUNCTION(i) (((i) * 2654435761U) \
0050 >> ((MINMATCH*8) - LZ4HC_HASH_LOG))
0051 #define DELTANEXTU16(p) chainTable[(U16)(p)]
0052
0053 static U32 LZ4HC_hashPtr(const void *ptr)
0054 {
0055 return HASH_FUNCTION(LZ4_read32(ptr));
0056 }
0057
0058
0059
0060
0061 static void LZ4HC_init(LZ4HC_CCtx_internal *hc4, const BYTE *start)
0062 {
0063 memset((void *)hc4->hashTable, 0, sizeof(hc4->hashTable));
0064 memset(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
0065 hc4->nextToUpdate = 64 * KB;
0066 hc4->base = start - 64 * KB;
0067 hc4->end = start;
0068 hc4->dictBase = start - 64 * KB;
0069 hc4->dictLimit = 64 * KB;
0070 hc4->lowLimit = 64 * KB;
0071 }
0072
0073
0074 static FORCE_INLINE void LZ4HC_Insert(LZ4HC_CCtx_internal *hc4,
0075 const BYTE *ip)
0076 {
0077 U16 * const chainTable = hc4->chainTable;
0078 U32 * const hashTable = hc4->hashTable;
0079 const BYTE * const base = hc4->base;
0080 U32 const target = (U32)(ip - base);
0081 U32 idx = hc4->nextToUpdate;
0082
0083 while (idx < target) {
0084 U32 const h = LZ4HC_hashPtr(base + idx);
0085 size_t delta = idx - hashTable[h];
0086
0087 if (delta > MAX_DISTANCE)
0088 delta = MAX_DISTANCE;
0089
0090 DELTANEXTU16(idx) = (U16)delta;
0091
0092 hashTable[h] = idx;
0093 idx++;
0094 }
0095
0096 hc4->nextToUpdate = target;
0097 }
0098
0099 static FORCE_INLINE int LZ4HC_InsertAndFindBestMatch(
0100 LZ4HC_CCtx_internal *hc4,
0101 const BYTE *ip,
0102 const BYTE * const iLimit,
0103 const BYTE **matchpos,
0104 const int maxNbAttempts)
0105 {
0106 U16 * const chainTable = hc4->chainTable;
0107 U32 * const HashTable = hc4->hashTable;
0108 const BYTE * const base = hc4->base;
0109 const BYTE * const dictBase = hc4->dictBase;
0110 const U32 dictLimit = hc4->dictLimit;
0111 const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))
0112 ? hc4->lowLimit
0113 : (U32)(ip - base) - (64 * KB - 1);
0114 U32 matchIndex;
0115 int nbAttempts = maxNbAttempts;
0116 size_t ml = 0;
0117
0118
0119 LZ4HC_Insert(hc4, ip);
0120 matchIndex = HashTable[LZ4HC_hashPtr(ip)];
0121
0122 while ((matchIndex >= lowLimit)
0123 && (nbAttempts)) {
0124 nbAttempts--;
0125 if (matchIndex >= dictLimit) {
0126 const BYTE * const match = base + matchIndex;
0127
0128 if (*(match + ml) == *(ip + ml)
0129 && (LZ4_read32(match) == LZ4_read32(ip))) {
0130 size_t const mlt = LZ4_count(ip + MINMATCH,
0131 match + MINMATCH, iLimit) + MINMATCH;
0132
0133 if (mlt > ml) {
0134 ml = mlt;
0135 *matchpos = match;
0136 }
0137 }
0138 } else {
0139 const BYTE * const match = dictBase + matchIndex;
0140
0141 if (LZ4_read32(match) == LZ4_read32(ip)) {
0142 size_t mlt;
0143 const BYTE *vLimit = ip
0144 + (dictLimit - matchIndex);
0145
0146 if (vLimit > iLimit)
0147 vLimit = iLimit;
0148 mlt = LZ4_count(ip + MINMATCH,
0149 match + MINMATCH, vLimit) + MINMATCH;
0150 if ((ip + mlt == vLimit)
0151 && (vLimit < iLimit))
0152 mlt += LZ4_count(ip + mlt,
0153 base + dictLimit,
0154 iLimit);
0155 if (mlt > ml) {
0156
0157 ml = mlt;
0158 *matchpos = base + matchIndex;
0159 }
0160 }
0161 }
0162 matchIndex -= DELTANEXTU16(matchIndex);
0163 }
0164
0165 return (int)ml;
0166 }
0167
0168 static FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch(
0169 LZ4HC_CCtx_internal *hc4,
0170 const BYTE * const ip,
0171 const BYTE * const iLowLimit,
0172 const BYTE * const iHighLimit,
0173 int longest,
0174 const BYTE **matchpos,
0175 const BYTE **startpos,
0176 const int maxNbAttempts)
0177 {
0178 U16 * const chainTable = hc4->chainTable;
0179 U32 * const HashTable = hc4->hashTable;
0180 const BYTE * const base = hc4->base;
0181 const U32 dictLimit = hc4->dictLimit;
0182 const BYTE * const lowPrefixPtr = base + dictLimit;
0183 const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))
0184 ? hc4->lowLimit
0185 : (U32)(ip - base) - (64 * KB - 1);
0186 const BYTE * const dictBase = hc4->dictBase;
0187 U32 matchIndex;
0188 int nbAttempts = maxNbAttempts;
0189 int delta = (int)(ip - iLowLimit);
0190
0191
0192 LZ4HC_Insert(hc4, ip);
0193 matchIndex = HashTable[LZ4HC_hashPtr(ip)];
0194
0195 while ((matchIndex >= lowLimit)
0196 && (nbAttempts)) {
0197 nbAttempts--;
0198 if (matchIndex >= dictLimit) {
0199 const BYTE *matchPtr = base + matchIndex;
0200
0201 if (*(iLowLimit + longest)
0202 == *(matchPtr - delta + longest)) {
0203 if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
0204 int mlt = MINMATCH + LZ4_count(
0205 ip + MINMATCH,
0206 matchPtr + MINMATCH,
0207 iHighLimit);
0208 int back = 0;
0209
0210 while ((ip + back > iLowLimit)
0211 && (matchPtr + back > lowPrefixPtr)
0212 && (ip[back - 1] == matchPtr[back - 1]))
0213 back--;
0214
0215 mlt -= back;
0216
0217 if (mlt > longest) {
0218 longest = (int)mlt;
0219 *matchpos = matchPtr + back;
0220 *startpos = ip + back;
0221 }
0222 }
0223 }
0224 } else {
0225 const BYTE * const matchPtr = dictBase + matchIndex;
0226
0227 if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
0228 size_t mlt;
0229 int back = 0;
0230 const BYTE *vLimit = ip + (dictLimit - matchIndex);
0231
0232 if (vLimit > iHighLimit)
0233 vLimit = iHighLimit;
0234
0235 mlt = LZ4_count(ip + MINMATCH,
0236 matchPtr + MINMATCH, vLimit) + MINMATCH;
0237
0238 if ((ip + mlt == vLimit) && (vLimit < iHighLimit))
0239 mlt += LZ4_count(ip + mlt, base + dictLimit,
0240 iHighLimit);
0241 while ((ip + back > iLowLimit)
0242 && (matchIndex + back > lowLimit)
0243 && (ip[back - 1] == matchPtr[back - 1]))
0244 back--;
0245
0246 mlt -= back;
0247
0248 if ((int)mlt > longest) {
0249 longest = (int)mlt;
0250 *matchpos = base + matchIndex + back;
0251 *startpos = ip + back;
0252 }
0253 }
0254 }
0255
0256 matchIndex -= DELTANEXTU16(matchIndex);
0257 }
0258
0259 return longest;
0260 }
0261
0262 static FORCE_INLINE int LZ4HC_encodeSequence(
0263 const BYTE **ip,
0264 BYTE **op,
0265 const BYTE **anchor,
0266 int matchLength,
0267 const BYTE * const match,
0268 limitedOutput_directive limitedOutputBuffer,
0269 BYTE *oend)
0270 {
0271 int length;
0272 BYTE *token;
0273
0274
0275 length = (int)(*ip - *anchor);
0276 token = (*op)++;
0277
0278 if ((limitedOutputBuffer)
0279 && ((*op + (length>>8)
0280 + length + (2 + 1 + LASTLITERALS)) > oend)) {
0281
0282 return 1;
0283 }
0284 if (length >= (int)RUN_MASK) {
0285 int len;
0286
0287 *token = (RUN_MASK<<ML_BITS);
0288 len = length - RUN_MASK;
0289 for (; len > 254 ; len -= 255)
0290 *(*op)++ = 255;
0291 *(*op)++ = (BYTE)len;
0292 } else
0293 *token = (BYTE)(length<<ML_BITS);
0294
0295
0296 LZ4_wildCopy(*op, *anchor, (*op) + length);
0297 *op += length;
0298
0299
0300 LZ4_writeLE16(*op, (U16)(*ip - match));
0301 *op += 2;
0302
0303
0304 length = (int)(matchLength - MINMATCH);
0305
0306 if ((limitedOutputBuffer)
0307 && (*op + (length>>8)
0308 + (1 + LASTLITERALS) > oend)) {
0309
0310 return 1;
0311 }
0312
0313 if (length >= (int)ML_MASK) {
0314 *token += ML_MASK;
0315 length -= ML_MASK;
0316
0317 for (; length > 509 ; length -= 510) {
0318 *(*op)++ = 255;
0319 *(*op)++ = 255;
0320 }
0321
0322 if (length > 254) {
0323 length -= 255;
0324 *(*op)++ = 255;
0325 }
0326
0327 *(*op)++ = (BYTE)length;
0328 } else
0329 *token += (BYTE)(length);
0330
0331
0332 *ip += matchLength;
0333 *anchor = *ip;
0334
0335 return 0;
0336 }
0337
0338 static int LZ4HC_compress_generic(
0339 LZ4HC_CCtx_internal *const ctx,
0340 const char * const source,
0341 char * const dest,
0342 int const inputSize,
0343 int const maxOutputSize,
0344 int compressionLevel,
0345 limitedOutput_directive limit
0346 )
0347 {
0348 const BYTE *ip = (const BYTE *) source;
0349 const BYTE *anchor = ip;
0350 const BYTE * const iend = ip + inputSize;
0351 const BYTE * const mflimit = iend - MFLIMIT;
0352 const BYTE * const matchlimit = (iend - LASTLITERALS);
0353
0354 BYTE *op = (BYTE *) dest;
0355 BYTE * const oend = op + maxOutputSize;
0356
0357 unsigned int maxNbAttempts;
0358 int ml, ml2, ml3, ml0;
0359 const BYTE *ref = NULL;
0360 const BYTE *start2 = NULL;
0361 const BYTE *ref2 = NULL;
0362 const BYTE *start3 = NULL;
0363 const BYTE *ref3 = NULL;
0364 const BYTE *start0;
0365 const BYTE *ref0;
0366
0367
0368 if (compressionLevel > LZ4HC_MAX_CLEVEL)
0369 compressionLevel = LZ4HC_MAX_CLEVEL;
0370 if (compressionLevel < 1)
0371 compressionLevel = LZ4HC_DEFAULT_CLEVEL;
0372 maxNbAttempts = 1 << (compressionLevel - 1);
0373 ctx->end += inputSize;
0374
0375 ip++;
0376
0377
0378 while (ip < mflimit) {
0379 ml = LZ4HC_InsertAndFindBestMatch(ctx, ip,
0380 matchlimit, (&ref), maxNbAttempts);
0381 if (!ml) {
0382 ip++;
0383 continue;
0384 }
0385
0386
0387 start0 = ip;
0388 ref0 = ref;
0389 ml0 = ml;
0390
0391 _Search2:
0392 if (ip + ml < mflimit)
0393 ml2 = LZ4HC_InsertAndGetWiderMatch(ctx,
0394 ip + ml - 2, ip + 0,
0395 matchlimit, ml, &ref2,
0396 &start2, maxNbAttempts);
0397 else
0398 ml2 = ml;
0399
0400 if (ml2 == ml) {
0401
0402 if (LZ4HC_encodeSequence(&ip, &op,
0403 &anchor, ml, ref, limit, oend))
0404 return 0;
0405 continue;
0406 }
0407
0408 if (start0 < ip) {
0409 if (start2 < ip + ml0) {
0410
0411 ip = start0;
0412 ref = ref0;
0413 ml = ml0;
0414 }
0415 }
0416
0417
0418 if ((start2 - ip) < 3) {
0419
0420 ml = ml2;
0421 ip = start2;
0422 ref = ref2;
0423 goto _Search2;
0424 }
0425
0426 _Search3:
0427
0428
0429
0430
0431
0432 if ((start2 - ip) < OPTIMAL_ML) {
0433 int correction;
0434 int new_ml = ml;
0435
0436 if (new_ml > OPTIMAL_ML)
0437 new_ml = OPTIMAL_ML;
0438 if (ip + new_ml > start2 + ml2 - MINMATCH)
0439 new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
0440
0441 correction = new_ml - (int)(start2 - ip);
0442
0443 if (correction > 0) {
0444 start2 += correction;
0445 ref2 += correction;
0446 ml2 -= correction;
0447 }
0448 }
0449
0450
0451
0452
0453
0454 if (start2 + ml2 < mflimit)
0455 ml3 = LZ4HC_InsertAndGetWiderMatch(ctx,
0456 start2 + ml2 - 3, start2,
0457 matchlimit, ml2, &ref3, &start3,
0458 maxNbAttempts);
0459 else
0460 ml3 = ml2;
0461
0462 if (ml3 == ml2) {
0463
0464
0465 if (start2 < ip + ml)
0466 ml = (int)(start2 - ip);
0467
0468 if (LZ4HC_encodeSequence(&ip, &op, &anchor,
0469 ml, ref, limit, oend))
0470 return 0;
0471 ip = start2;
0472 if (LZ4HC_encodeSequence(&ip, &op, &anchor,
0473 ml2, ref2, limit, oend))
0474 return 0;
0475 continue;
0476 }
0477
0478 if (start3 < ip + ml + 3) {
0479
0480 if (start3 >= (ip + ml)) {
0481
0482
0483
0484
0485 if (start2 < ip + ml) {
0486 int correction = (int)(ip + ml - start2);
0487
0488 start2 += correction;
0489 ref2 += correction;
0490 ml2 -= correction;
0491 if (ml2 < MINMATCH) {
0492 start2 = start3;
0493 ref2 = ref3;
0494 ml2 = ml3;
0495 }
0496 }
0497
0498 if (LZ4HC_encodeSequence(&ip, &op, &anchor,
0499 ml, ref, limit, oend))
0500 return 0;
0501 ip = start3;
0502 ref = ref3;
0503 ml = ml3;
0504
0505 start0 = start2;
0506 ref0 = ref2;
0507 ml0 = ml2;
0508 goto _Search2;
0509 }
0510
0511 start2 = start3;
0512 ref2 = ref3;
0513 ml2 = ml3;
0514 goto _Search3;
0515 }
0516
0517
0518
0519
0520
0521
0522 if (start2 < ip + ml) {
0523 if ((start2 - ip) < (int)ML_MASK) {
0524 int correction;
0525
0526 if (ml > OPTIMAL_ML)
0527 ml = OPTIMAL_ML;
0528 if (ip + ml > start2 + ml2 - MINMATCH)
0529 ml = (int)(start2 - ip) + ml2 - MINMATCH;
0530 correction = ml - (int)(start2 - ip);
0531 if (correction > 0) {
0532 start2 += correction;
0533 ref2 += correction;
0534 ml2 -= correction;
0535 }
0536 } else
0537 ml = (int)(start2 - ip);
0538 }
0539 if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml,
0540 ref, limit, oend))
0541 return 0;
0542
0543 ip = start2;
0544 ref = ref2;
0545 ml = ml2;
0546
0547 start2 = start3;
0548 ref2 = ref3;
0549 ml2 = ml3;
0550
0551 goto _Search3;
0552 }
0553
0554
0555 {
0556 int lastRun = (int)(iend - anchor);
0557
0558 if ((limit)
0559 && (((char *)op - dest) + lastRun + 1
0560 + ((lastRun + 255 - RUN_MASK)/255)
0561 > (U32)maxOutputSize)) {
0562
0563 return 0;
0564 }
0565 if (lastRun >= (int)RUN_MASK) {
0566 *op++ = (RUN_MASK<<ML_BITS);
0567 lastRun -= RUN_MASK;
0568 for (; lastRun > 254 ; lastRun -= 255)
0569 *op++ = 255;
0570 *op++ = (BYTE) lastRun;
0571 } else
0572 *op++ = (BYTE)(lastRun<<ML_BITS);
0573 LZ4_memcpy(op, anchor, iend - anchor);
0574 op += iend - anchor;
0575 }
0576
0577
0578 return (int) (((char *)op) - dest);
0579 }
0580
0581 static int LZ4_compress_HC_extStateHC(
0582 void *state,
0583 const char *src,
0584 char *dst,
0585 int srcSize,
0586 int maxDstSize,
0587 int compressionLevel)
0588 {
0589 LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t *)state)->internal_donotuse;
0590
0591 if (((size_t)(state)&(sizeof(void *) - 1)) != 0) {
0592
0593
0594
0595 return 0;
0596 }
0597
0598 LZ4HC_init(ctx, (const BYTE *)src);
0599
0600 if (maxDstSize < LZ4_compressBound(srcSize))
0601 return LZ4HC_compress_generic(ctx, src, dst,
0602 srcSize, maxDstSize, compressionLevel, limitedOutput);
0603 else
0604 return LZ4HC_compress_generic(ctx, src, dst,
0605 srcSize, maxDstSize, compressionLevel, noLimit);
0606 }
0607
0608 int LZ4_compress_HC(const char *src, char *dst, int srcSize,
0609 int maxDstSize, int compressionLevel, void *wrkmem)
0610 {
0611 return LZ4_compress_HC_extStateHC(wrkmem, src, dst,
0612 srcSize, maxDstSize, compressionLevel);
0613 }
0614 EXPORT_SYMBOL(LZ4_compress_HC);
0615
0616
0617
0618
0619 void LZ4_resetStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)
0620 {
0621 LZ4_streamHCPtr->internal_donotuse.base = NULL;
0622 LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned int)compressionLevel;
0623 }
0624
0625 int LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr,
0626 const char *dictionary,
0627 int dictSize)
0628 {
0629 LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
0630
0631 if (dictSize > 64 * KB) {
0632 dictionary += dictSize - 64 * KB;
0633 dictSize = 64 * KB;
0634 }
0635 LZ4HC_init(ctxPtr, (const BYTE *)dictionary);
0636 if (dictSize >= 4)
0637 LZ4HC_Insert(ctxPtr, (const BYTE *)dictionary + (dictSize - 3));
0638 ctxPtr->end = (const BYTE *)dictionary + dictSize;
0639 return dictSize;
0640 }
0641 EXPORT_SYMBOL(LZ4_loadDictHC);
0642
0643
0644
0645 static void LZ4HC_setExternalDict(
0646 LZ4HC_CCtx_internal *ctxPtr,
0647 const BYTE *newBlock)
0648 {
0649 if (ctxPtr->end >= ctxPtr->base + 4) {
0650
0651 LZ4HC_Insert(ctxPtr, ctxPtr->end - 3);
0652 }
0653
0654
0655
0656
0657
0658 ctxPtr->lowLimit = ctxPtr->dictLimit;
0659 ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
0660 ctxPtr->dictBase = ctxPtr->base;
0661 ctxPtr->base = newBlock - ctxPtr->dictLimit;
0662 ctxPtr->end = newBlock;
0663
0664 ctxPtr->nextToUpdate = ctxPtr->dictLimit;
0665 }
0666
0667 static int LZ4_compressHC_continue_generic(
0668 LZ4_streamHC_t *LZ4_streamHCPtr,
0669 const char *source,
0670 char *dest,
0671 int inputSize,
0672 int maxOutputSize,
0673 limitedOutput_directive limit)
0674 {
0675 LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
0676
0677
0678 if (ctxPtr->base == NULL)
0679 LZ4HC_init(ctxPtr, (const BYTE *) source);
0680
0681
0682 if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 * GB) {
0683 size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base)
0684 - ctxPtr->dictLimit;
0685 if (dictSize > 64 * KB)
0686 dictSize = 64 * KB;
0687 LZ4_loadDictHC(LZ4_streamHCPtr,
0688 (const char *)(ctxPtr->end) - dictSize, (int)dictSize);
0689 }
0690
0691
0692 if ((const BYTE *)source != ctxPtr->end)
0693 LZ4HC_setExternalDict(ctxPtr, (const BYTE *)source);
0694
0695
0696 {
0697 const BYTE *sourceEnd = (const BYTE *) source + inputSize;
0698 const BYTE * const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
0699 const BYTE * const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
0700
0701 if ((sourceEnd > dictBegin)
0702 && ((const BYTE *)source < dictEnd)) {
0703 if (sourceEnd > dictEnd)
0704 sourceEnd = dictEnd;
0705 ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
0706
0707 if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4)
0708 ctxPtr->lowLimit = ctxPtr->dictLimit;
0709 }
0710 }
0711
0712 return LZ4HC_compress_generic(ctxPtr, source, dest,
0713 inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
0714 }
0715
0716 int LZ4_compress_HC_continue(
0717 LZ4_streamHC_t *LZ4_streamHCPtr,
0718 const char *source,
0719 char *dest,
0720 int inputSize,
0721 int maxOutputSize)
0722 {
0723 if (maxOutputSize < LZ4_compressBound(inputSize))
0724 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,
0725 source, dest, inputSize, maxOutputSize, limitedOutput);
0726 else
0727 return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,
0728 source, dest, inputSize, maxOutputSize, noLimit);
0729 }
0730 EXPORT_SYMBOL(LZ4_compress_HC_continue);
0731
0732
0733
0734 int LZ4_saveDictHC(
0735 LZ4_streamHC_t *LZ4_streamHCPtr,
0736 char *safeBuffer,
0737 int dictSize)
0738 {
0739 LZ4HC_CCtx_internal *const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
0740 int const prefixSize = (int)(streamPtr->end
0741 - (streamPtr->base + streamPtr->dictLimit));
0742
0743 if (dictSize > 64 * KB)
0744 dictSize = 64 * KB;
0745 if (dictSize < 4)
0746 dictSize = 0;
0747 if (dictSize > prefixSize)
0748 dictSize = prefixSize;
0749
0750 memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
0751
0752 {
0753 U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
0754
0755 streamPtr->end = (const BYTE *)safeBuffer + dictSize;
0756 streamPtr->base = streamPtr->end - endIndex;
0757 streamPtr->dictLimit = endIndex - dictSize;
0758 streamPtr->lowLimit = endIndex - dictSize;
0759
0760 if (streamPtr->nextToUpdate < streamPtr->dictLimit)
0761 streamPtr->nextToUpdate = streamPtr->dictLimit;
0762 }
0763 return dictSize;
0764 }
0765 EXPORT_SYMBOL(LZ4_saveDictHC);
0766
0767 MODULE_LICENSE("Dual BSD/GPL");
0768 MODULE_DESCRIPTION("LZ4 HC compressor");