Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * LZ4 - Fast LZ compression algorithm
0003  * Copyright (C) 2011 - 2016, Yann Collet.
0004  * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions are
0007  * met:
0008  *  * Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  *  * Redistributions in binary form must reproduce the above
0011  * copyright notice, this list of conditions and the following disclaimer
0012  * in the documentation and/or other materials provided with the
0013  * distribution.
0014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0015  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0016  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0017  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0018  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0019  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0020  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0021  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0022  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0024  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025  * You can contact the author at :
0026  *  - LZ4 homepage : http://www.lz4.org
0027  *  - LZ4 source repository : https://github.com/lz4/lz4
0028  *
0029  *  Changed for kernel usage by:
0030  *  Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
0031  */
0032 
0033 /*-************************************
0034  *  Dependencies
0035  **************************************/
0036 #include <linux/lz4.h>
0037 #include "lz4defs.h"
0038 #include <linux/init.h>
0039 #include <linux/module.h>
0040 #include <linux/kernel.h>
0041 #include <asm/unaligned.h>
0042 
0043 /*-*****************************
0044  *  Decompression functions
0045  *******************************/
0046 
0047 #define DEBUGLOG(l, ...) {} /* disabled */
0048 
0049 #ifndef assert
0050 #define assert(condition) ((void)0)
0051 #endif
0052 
0053 /*
0054  * LZ4_decompress_generic() :
0055  * This generic decompression function covers all use cases.
0056  * It shall be instantiated several times, using different sets of directives.
0057  * Note that it is important for performance that this function really get inlined,
0058  * in order to remove useless branches during compilation optimization.
0059  */
0060 static FORCE_INLINE int LZ4_decompress_generic(
0061      const char * const src,
0062      char * const dst,
0063      int srcSize,
0064         /*
0065          * If endOnInput == endOnInputSize,
0066          * this value is `dstCapacity`
0067          */
0068      int outputSize,
0069      /* endOnOutputSize, endOnInputSize */
0070      endCondition_directive endOnInput,
0071      /* full, partial */
0072      earlyEnd_directive partialDecoding,
0073      /* noDict, withPrefix64k, usingExtDict */
0074      dict_directive dict,
0075      /* always <= dst, == dst when no prefix */
0076      const BYTE * const lowPrefix,
0077      /* only if dict == usingExtDict */
0078      const BYTE * const dictStart,
0079      /* note : = 0 if noDict */
0080      const size_t dictSize
0081      )
0082 {
0083     const BYTE *ip = (const BYTE *) src;
0084     const BYTE * const iend = ip + srcSize;
0085 
0086     BYTE *op = (BYTE *) dst;
0087     BYTE * const oend = op + outputSize;
0088     BYTE *cpy;
0089 
0090     const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
0091     static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
0092     static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
0093 
0094     const int safeDecode = (endOnInput == endOnInputSize);
0095     const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
0096 
0097     /* Set up the "end" pointers for the shortcut. */
0098     const BYTE *const shortiend = iend -
0099         (endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/;
0100     const BYTE *const shortoend = oend -
0101         (endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/;
0102 
0103     DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__,
0104          srcSize, outputSize);
0105 
0106     /* Special cases */
0107     assert(lowPrefix <= op);
0108     assert(src != NULL);
0109 
0110     /* Empty output buffer */
0111     if ((endOnInput) && (unlikely(outputSize == 0)))
0112         return ((srcSize == 1) && (*ip == 0)) ? 0 : -1;
0113 
0114     if ((!endOnInput) && (unlikely(outputSize == 0)))
0115         return (*ip == 0 ? 1 : -1);
0116 
0117     if ((endOnInput) && unlikely(srcSize == 0))
0118         return -1;
0119 
0120     /* Main Loop : decode sequences */
0121     while (1) {
0122         size_t length;
0123         const BYTE *match;
0124         size_t offset;
0125 
0126         /* get literal length */
0127         unsigned int const token = *ip++;
0128         length = token>>ML_BITS;
0129 
0130         /* ip < iend before the increment */
0131         assert(!endOnInput || ip <= iend);
0132 
0133         /*
0134          * A two-stage shortcut for the most common case:
0135          * 1) If the literal length is 0..14, and there is enough
0136          * space, enter the shortcut and copy 16 bytes on behalf
0137          * of the literals (in the fast mode, only 8 bytes can be
0138          * safely copied this way).
0139          * 2) Further if the match length is 4..18, copy 18 bytes
0140          * in a similar manner; but we ensure that there's enough
0141          * space in the output for those 18 bytes earlier, upon
0142          * entering the shortcut (in other words, there is a
0143          * combined check for both stages).
0144          *
0145          * The & in the likely() below is intentionally not && so that
0146          * some compilers can produce better parallelized runtime code
0147          */
0148         if ((endOnInput ? length != RUN_MASK : length <= 8)
0149            /*
0150             * strictly "less than" on input, to re-enter
0151             * the loop with at least one byte
0152             */
0153            && likely((endOnInput ? ip < shortiend : 1) &
0154                  (op <= shortoend))) {
0155             /* Copy the literals */
0156             LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
0157             op += length; ip += length;
0158 
0159             /*
0160              * The second stage:
0161              * prepare for match copying, decode full info.
0162              * If it doesn't work out, the info won't be wasted.
0163              */
0164             length = token & ML_MASK; /* match length */
0165             offset = LZ4_readLE16(ip);
0166             ip += 2;
0167             match = op - offset;
0168             assert(match <= op); /* check overflow */
0169 
0170             /* Do not deal with overlapping matches. */
0171             if ((length != ML_MASK) &&
0172                 (offset >= 8) &&
0173                 (dict == withPrefix64k || match >= lowPrefix)) {
0174                 /* Copy the match. */
0175                 LZ4_memcpy(op + 0, match + 0, 8);
0176                 LZ4_memcpy(op + 8, match + 8, 8);
0177                 LZ4_memcpy(op + 16, match + 16, 2);
0178                 op += length + MINMATCH;
0179                 /* Both stages worked, load the next token. */
0180                 continue;
0181             }
0182 
0183             /*
0184              * The second stage didn't work out, but the info
0185              * is ready. Propel it right to the point of match
0186              * copying.
0187              */
0188             goto _copy_match;
0189         }
0190 
0191         /* decode literal length */
0192         if (length == RUN_MASK) {
0193             unsigned int s;
0194 
0195             if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) {
0196                 /* overflow detection */
0197                 goto _output_error;
0198             }
0199             do {
0200                 s = *ip++;
0201                 length += s;
0202             } while (likely(endOnInput
0203                 ? ip < iend - RUN_MASK
0204                 : 1) & (s == 255));
0205 
0206             if ((safeDecode)
0207                 && unlikely((uptrval)(op) +
0208                     length < (uptrval)(op))) {
0209                 /* overflow detection */
0210                 goto _output_error;
0211             }
0212             if ((safeDecode)
0213                 && unlikely((uptrval)(ip) +
0214                     length < (uptrval)(ip))) {
0215                 /* overflow detection */
0216                 goto _output_error;
0217             }
0218         }
0219 
0220         /* copy literals */
0221         cpy = op + length;
0222         LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
0223 
0224         if (((endOnInput) && ((cpy > oend - MFLIMIT)
0225             || (ip + length > iend - (2 + 1 + LASTLITERALS))))
0226             || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
0227             if (partialDecoding) {
0228                 if (cpy > oend) {
0229                     /*
0230                      * Partial decoding :
0231                      * stop in the middle of literal segment
0232                      */
0233                     cpy = oend;
0234                     length = oend - op;
0235                 }
0236                 if ((endOnInput)
0237                     && (ip + length > iend)) {
0238                     /*
0239                      * Error :
0240                      * read attempt beyond
0241                      * end of input buffer
0242                      */
0243                     goto _output_error;
0244                 }
0245             } else {
0246                 if ((!endOnInput)
0247                     && (cpy != oend)) {
0248                     /*
0249                      * Error :
0250                      * block decoding must
0251                      * stop exactly there
0252                      */
0253                     goto _output_error;
0254                 }
0255                 if ((endOnInput)
0256                     && ((ip + length != iend)
0257                     || (cpy > oend))) {
0258                     /*
0259                      * Error :
0260                      * input must be consumed
0261                      */
0262                     goto _output_error;
0263                 }
0264             }
0265 
0266             /*
0267              * supports overlapping memory regions; only matters
0268              * for in-place decompression scenarios
0269              */
0270             LZ4_memmove(op, ip, length);
0271             ip += length;
0272             op += length;
0273 
0274             /* Necessarily EOF when !partialDecoding.
0275              * When partialDecoding, it is EOF if we've either
0276              * filled the output buffer or
0277              * can't proceed with reading an offset for following match.
0278              */
0279             if (!partialDecoding || (cpy == oend) || (ip >= (iend - 2)))
0280                 break;
0281         } else {
0282             /* may overwrite up to WILDCOPYLENGTH beyond cpy */
0283             LZ4_wildCopy(op, ip, cpy);
0284             ip += length;
0285             op = cpy;
0286         }
0287 
0288         /* get offset */
0289         offset = LZ4_readLE16(ip);
0290         ip += 2;
0291         match = op - offset;
0292 
0293         /* get matchlength */
0294         length = token & ML_MASK;
0295 
0296 _copy_match:
0297         if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) {
0298             /* Error : offset outside buffers */
0299             goto _output_error;
0300         }
0301 
0302         /* costs ~1%; silence an msan warning when offset == 0 */
0303         /*
0304          * note : when partialDecoding, there is no guarantee that
0305          * at least 4 bytes remain available in output buffer
0306          */
0307         if (!partialDecoding) {
0308             assert(oend > op);
0309             assert(oend - op >= 4);
0310 
0311             LZ4_write32(op, (U32)offset);
0312         }
0313 
0314         if (length == ML_MASK) {
0315             unsigned int s;
0316 
0317             do {
0318                 s = *ip++;
0319 
0320                 if ((endOnInput) && (ip > iend - LASTLITERALS))
0321                     goto _output_error;
0322 
0323                 length += s;
0324             } while (s == 255);
0325 
0326             if ((safeDecode)
0327                 && unlikely(
0328                     (uptrval)(op) + length < (uptrval)op)) {
0329                 /* overflow detection */
0330                 goto _output_error;
0331             }
0332         }
0333 
0334         length += MINMATCH;
0335 
0336         /* match starting within external dictionary */
0337         if ((dict == usingExtDict) && (match < lowPrefix)) {
0338             if (unlikely(op + length > oend - LASTLITERALS)) {
0339                 /* doesn't respect parsing restriction */
0340                 if (!partialDecoding)
0341                     goto _output_error;
0342                 length = min(length, (size_t)(oend - op));
0343             }
0344 
0345             if (length <= (size_t)(lowPrefix - match)) {
0346                 /*
0347                  * match fits entirely within external
0348                  * dictionary : just copy
0349                  */
0350                 memmove(op, dictEnd - (lowPrefix - match),
0351                     length);
0352                 op += length;
0353             } else {
0354                 /*
0355                  * match stretches into both external
0356                  * dictionary and current block
0357                  */
0358                 size_t const copySize = (size_t)(lowPrefix - match);
0359                 size_t const restSize = length - copySize;
0360 
0361                 LZ4_memcpy(op, dictEnd - copySize, copySize);
0362                 op += copySize;
0363                 if (restSize > (size_t)(op - lowPrefix)) {
0364                     /* overlap copy */
0365                     BYTE * const endOfMatch = op + restSize;
0366                     const BYTE *copyFrom = lowPrefix;
0367 
0368                     while (op < endOfMatch)
0369                         *op++ = *copyFrom++;
0370                 } else {
0371                     LZ4_memcpy(op, lowPrefix, restSize);
0372                     op += restSize;
0373                 }
0374             }
0375             continue;
0376         }
0377 
0378         /* copy match within block */
0379         cpy = op + length;
0380 
0381         /*
0382          * partialDecoding :
0383          * may not respect endBlock parsing restrictions
0384          */
0385         assert(op <= oend);
0386         if (partialDecoding &&
0387             (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
0388             size_t const mlen = min(length, (size_t)(oend - op));
0389             const BYTE * const matchEnd = match + mlen;
0390             BYTE * const copyEnd = op + mlen;
0391 
0392             if (matchEnd > op) {
0393                 /* overlap copy */
0394                 while (op < copyEnd)
0395                     *op++ = *match++;
0396             } else {
0397                 LZ4_memcpy(op, match, mlen);
0398             }
0399             op = copyEnd;
0400             if (op == oend)
0401                 break;
0402             continue;
0403         }
0404 
0405         if (unlikely(offset < 8)) {
0406             op[0] = match[0];
0407             op[1] = match[1];
0408             op[2] = match[2];
0409             op[3] = match[3];
0410             match += inc32table[offset];
0411             LZ4_memcpy(op + 4, match, 4);
0412             match -= dec64table[offset];
0413         } else {
0414             LZ4_copy8(op, match);
0415             match += 8;
0416         }
0417 
0418         op += 8;
0419 
0420         if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
0421             BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
0422 
0423             if (cpy > oend - LASTLITERALS) {
0424                 /*
0425                  * Error : last LASTLITERALS bytes
0426                  * must be literals (uncompressed)
0427                  */
0428                 goto _output_error;
0429             }
0430 
0431             if (op < oCopyLimit) {
0432                 LZ4_wildCopy(op, match, oCopyLimit);
0433                 match += oCopyLimit - op;
0434                 op = oCopyLimit;
0435             }
0436             while (op < cpy)
0437                 *op++ = *match++;
0438         } else {
0439             LZ4_copy8(op, match);
0440             if (length > 16)
0441                 LZ4_wildCopy(op + 8, match + 8, cpy);
0442         }
0443         op = cpy; /* wildcopy correction */
0444     }
0445 
0446     /* end of decoding */
0447     if (endOnInput) {
0448         /* Nb of output bytes decoded */
0449         return (int) (((char *)op) - dst);
0450     } else {
0451         /* Nb of input bytes read */
0452         return (int) (((const char *)ip) - src);
0453     }
0454 
0455     /* Overflow error detected */
0456 _output_error:
0457     return (int) (-(((const char *)ip) - src)) - 1;
0458 }
0459 
0460 int LZ4_decompress_safe(const char *source, char *dest,
0461     int compressedSize, int maxDecompressedSize)
0462 {
0463     return LZ4_decompress_generic(source, dest,
0464                       compressedSize, maxDecompressedSize,
0465                       endOnInputSize, decode_full_block,
0466                       noDict, (BYTE *)dest, NULL, 0);
0467 }
0468 
0469 int LZ4_decompress_safe_partial(const char *src, char *dst,
0470     int compressedSize, int targetOutputSize, int dstCapacity)
0471 {
0472     dstCapacity = min(targetOutputSize, dstCapacity);
0473     return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
0474                       endOnInputSize, partial_decode,
0475                       noDict, (BYTE *)dst, NULL, 0);
0476 }
0477 
0478 int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
0479 {
0480     return LZ4_decompress_generic(source, dest, 0, originalSize,
0481                       endOnOutputSize, decode_full_block,
0482                       withPrefix64k,
0483                       (BYTE *)dest - 64 * KB, NULL, 0);
0484 }
0485 
0486 /* ===== Instantiate a few more decoding cases, used more than once. ===== */
0487 
0488 static int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest,
0489                       int compressedSize, int maxOutputSize)
0490 {
0491     return LZ4_decompress_generic(source, dest,
0492                       compressedSize, maxOutputSize,
0493                       endOnInputSize, decode_full_block,
0494                       withPrefix64k,
0495                       (BYTE *)dest - 64 * KB, NULL, 0);
0496 }
0497 
0498 static int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest,
0499                            int compressedSize,
0500                            int maxOutputSize,
0501                            size_t prefixSize)
0502 {
0503     return LZ4_decompress_generic(source, dest,
0504                       compressedSize, maxOutputSize,
0505                       endOnInputSize, decode_full_block,
0506                       noDict,
0507                       (BYTE *)dest - prefixSize, NULL, 0);
0508 }
0509 
0510 static int LZ4_decompress_safe_forceExtDict(const char *source, char *dest,
0511                         int compressedSize, int maxOutputSize,
0512                         const void *dictStart, size_t dictSize)
0513 {
0514     return LZ4_decompress_generic(source, dest,
0515                       compressedSize, maxOutputSize,
0516                       endOnInputSize, decode_full_block,
0517                       usingExtDict, (BYTE *)dest,
0518                       (const BYTE *)dictStart, dictSize);
0519 }
0520 
0521 static int LZ4_decompress_fast_extDict(const char *source, char *dest,
0522                        int originalSize,
0523                        const void *dictStart, size_t dictSize)
0524 {
0525     return LZ4_decompress_generic(source, dest,
0526                       0, originalSize,
0527                       endOnOutputSize, decode_full_block,
0528                       usingExtDict, (BYTE *)dest,
0529                       (const BYTE *)dictStart, dictSize);
0530 }
0531 
0532 /*
0533  * The "double dictionary" mode, for use with e.g. ring buffers: the first part
0534  * of the dictionary is passed as prefix, and the second via dictStart + dictSize.
0535  * These routines are used only once, in LZ4_decompress_*_continue().
0536  */
0537 static FORCE_INLINE
0538 int LZ4_decompress_safe_doubleDict(const char *source, char *dest,
0539                    int compressedSize, int maxOutputSize,
0540                    size_t prefixSize,
0541                    const void *dictStart, size_t dictSize)
0542 {
0543     return LZ4_decompress_generic(source, dest,
0544                       compressedSize, maxOutputSize,
0545                       endOnInputSize, decode_full_block,
0546                       usingExtDict, (BYTE *)dest - prefixSize,
0547                       (const BYTE *)dictStart, dictSize);
0548 }
0549 
0550 static FORCE_INLINE
0551 int LZ4_decompress_fast_doubleDict(const char *source, char *dest,
0552                    int originalSize, size_t prefixSize,
0553                    const void *dictStart, size_t dictSize)
0554 {
0555     return LZ4_decompress_generic(source, dest,
0556                       0, originalSize,
0557                       endOnOutputSize, decode_full_block,
0558                       usingExtDict, (BYTE *)dest - prefixSize,
0559                       (const BYTE *)dictStart, dictSize);
0560 }
0561 
0562 /* ===== streaming decompression functions ===== */
0563 
0564 int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode,
0565     const char *dictionary, int dictSize)
0566 {
0567     LZ4_streamDecode_t_internal *lz4sd =
0568         &LZ4_streamDecode->internal_donotuse;
0569 
0570     lz4sd->prefixSize = (size_t) dictSize;
0571     lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize;
0572     lz4sd->externalDict = NULL;
0573     lz4sd->extDictSize  = 0;
0574     return 1;
0575 }
0576 
0577 /*
0578  * *_continue() :
0579  * These decoding functions allow decompression of multiple blocks
0580  * in "streaming" mode.
0581  * Previously decoded blocks must still be available at the memory
0582  * position where they were decoded.
0583  * If it's not possible, save the relevant part of
0584  * decoded data into a safe buffer,
0585  * and indicate where it stands using LZ4_setStreamDecode()
0586  */
0587 int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode,
0588     const char *source, char *dest, int compressedSize, int maxOutputSize)
0589 {
0590     LZ4_streamDecode_t_internal *lz4sd =
0591         &LZ4_streamDecode->internal_donotuse;
0592     int result;
0593 
0594     if (lz4sd->prefixSize == 0) {
0595         /* The first call, no dictionary yet. */
0596         assert(lz4sd->extDictSize == 0);
0597         result = LZ4_decompress_safe(source, dest,
0598             compressedSize, maxOutputSize);
0599         if (result <= 0)
0600             return result;
0601         lz4sd->prefixSize = result;
0602         lz4sd->prefixEnd = (BYTE *)dest + result;
0603     } else if (lz4sd->prefixEnd == (BYTE *)dest) {
0604         /* They're rolling the current segment. */
0605         if (lz4sd->prefixSize >= 64 * KB - 1)
0606             result = LZ4_decompress_safe_withPrefix64k(source, dest,
0607                 compressedSize, maxOutputSize);
0608         else if (lz4sd->extDictSize == 0)
0609             result = LZ4_decompress_safe_withSmallPrefix(source,
0610                 dest, compressedSize, maxOutputSize,
0611                 lz4sd->prefixSize);
0612         else
0613             result = LZ4_decompress_safe_doubleDict(source, dest,
0614                 compressedSize, maxOutputSize,
0615                 lz4sd->prefixSize,
0616                 lz4sd->externalDict, lz4sd->extDictSize);
0617         if (result <= 0)
0618             return result;
0619         lz4sd->prefixSize += result;
0620         lz4sd->prefixEnd  += result;
0621     } else {
0622         /*
0623          * The buffer wraps around, or they're
0624          * switching to another buffer.
0625          */
0626         lz4sd->extDictSize = lz4sd->prefixSize;
0627         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
0628         result = LZ4_decompress_safe_forceExtDict(source, dest,
0629             compressedSize, maxOutputSize,
0630             lz4sd->externalDict, lz4sd->extDictSize);
0631         if (result <= 0)
0632             return result;
0633         lz4sd->prefixSize = result;
0634         lz4sd->prefixEnd  = (BYTE *)dest + result;
0635     }
0636 
0637     return result;
0638 }
0639 
0640 int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode,
0641     const char *source, char *dest, int originalSize)
0642 {
0643     LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
0644     int result;
0645 
0646     if (lz4sd->prefixSize == 0) {
0647         assert(lz4sd->extDictSize == 0);
0648         result = LZ4_decompress_fast(source, dest, originalSize);
0649         if (result <= 0)
0650             return result;
0651         lz4sd->prefixSize = originalSize;
0652         lz4sd->prefixEnd = (BYTE *)dest + originalSize;
0653     } else if (lz4sd->prefixEnd == (BYTE *)dest) {
0654         if (lz4sd->prefixSize >= 64 * KB - 1 ||
0655             lz4sd->extDictSize == 0)
0656             result = LZ4_decompress_fast(source, dest,
0657                              originalSize);
0658         else
0659             result = LZ4_decompress_fast_doubleDict(source, dest,
0660                 originalSize, lz4sd->prefixSize,
0661                 lz4sd->externalDict, lz4sd->extDictSize);
0662         if (result <= 0)
0663             return result;
0664         lz4sd->prefixSize += originalSize;
0665         lz4sd->prefixEnd  += originalSize;
0666     } else {
0667         lz4sd->extDictSize = lz4sd->prefixSize;
0668         lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
0669         result = LZ4_decompress_fast_extDict(source, dest,
0670             originalSize, lz4sd->externalDict, lz4sd->extDictSize);
0671         if (result <= 0)
0672             return result;
0673         lz4sd->prefixSize = originalSize;
0674         lz4sd->prefixEnd = (BYTE *)dest + originalSize;
0675     }
0676     return result;
0677 }
0678 
0679 int LZ4_decompress_safe_usingDict(const char *source, char *dest,
0680                   int compressedSize, int maxOutputSize,
0681                   const char *dictStart, int dictSize)
0682 {
0683     if (dictSize == 0)
0684         return LZ4_decompress_safe(source, dest,
0685                        compressedSize, maxOutputSize);
0686     if (dictStart+dictSize == dest) {
0687         if (dictSize >= 64 * KB - 1)
0688             return LZ4_decompress_safe_withPrefix64k(source, dest,
0689                 compressedSize, maxOutputSize);
0690         return LZ4_decompress_safe_withSmallPrefix(source, dest,
0691             compressedSize, maxOutputSize, dictSize);
0692     }
0693     return LZ4_decompress_safe_forceExtDict(source, dest,
0694         compressedSize, maxOutputSize, dictStart, dictSize);
0695 }
0696 
0697 int LZ4_decompress_fast_usingDict(const char *source, char *dest,
0698                   int originalSize,
0699                   const char *dictStart, int dictSize)
0700 {
0701     if (dictSize == 0 || dictStart + dictSize == dest)
0702         return LZ4_decompress_fast(source, dest, originalSize);
0703 
0704     return LZ4_decompress_fast_extDict(source, dest, originalSize,
0705         dictStart, dictSize);
0706 }
0707 
0708 #ifndef STATIC
0709 EXPORT_SYMBOL(LZ4_decompress_safe);
0710 EXPORT_SYMBOL(LZ4_decompress_safe_partial);
0711 EXPORT_SYMBOL(LZ4_decompress_fast);
0712 EXPORT_SYMBOL(LZ4_setStreamDecode);
0713 EXPORT_SYMBOL(LZ4_decompress_safe_continue);
0714 EXPORT_SYMBOL(LZ4_decompress_fast_continue);
0715 EXPORT_SYMBOL(LZ4_decompress_safe_usingDict);
0716 EXPORT_SYMBOL(LZ4_decompress_fast_usingDict);
0717 
0718 MODULE_LICENSE("Dual BSD/GPL");
0719 MODULE_DESCRIPTION("LZ4 decompressor");
0720 #endif