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