162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * LZ4 - Fast LZ compression algorithm
362306a36Sopenharmony_ci * Copyright (C) 2011 - 2016, Yann Collet.
462306a36Sopenharmony_ci * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
562306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
662306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are
762306a36Sopenharmony_ci * met:
862306a36Sopenharmony_ci *	* Redistributions of source code must retain the above copyright
962306a36Sopenharmony_ci *	  notice, this list of conditions and the following disclaimer.
1062306a36Sopenharmony_ci *	* Redistributions in binary form must reproduce the above
1162306a36Sopenharmony_ci * copyright notice, this list of conditions and the following disclaimer
1262306a36Sopenharmony_ci * in the documentation and/or other materials provided with the
1362306a36Sopenharmony_ci * distribution.
1462306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1562306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1662306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1762306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1862306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1962306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2062306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2162306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2262306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2362306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2462306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2562306a36Sopenharmony_ci * You can contact the author at :
2662306a36Sopenharmony_ci *	- LZ4 homepage : http://www.lz4.org
2762306a36Sopenharmony_ci *	- LZ4 source repository : https://github.com/lz4/lz4
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci *	Changed for kernel usage by:
3062306a36Sopenharmony_ci *	Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*-************************************
3462306a36Sopenharmony_ci *	Dependencies
3562306a36Sopenharmony_ci **************************************/
3662306a36Sopenharmony_ci#include <linux/lz4.h>
3762306a36Sopenharmony_ci#include "lz4defs.h"
3862306a36Sopenharmony_ci#include <linux/init.h>
3962306a36Sopenharmony_ci#include <linux/module.h>
4062306a36Sopenharmony_ci#include <linux/kernel.h>
4162306a36Sopenharmony_ci#include <asm/unaligned.h>
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*-*****************************
4462306a36Sopenharmony_ci *	Decompression functions
4562306a36Sopenharmony_ci *******************************/
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define DEBUGLOG(l, ...) {}	/* disabled */
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#ifndef assert
5062306a36Sopenharmony_ci#define assert(condition) ((void)0)
5162306a36Sopenharmony_ci#endif
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*
5462306a36Sopenharmony_ci * LZ4_decompress_generic() :
5562306a36Sopenharmony_ci * This generic decompression function covers all use cases.
5662306a36Sopenharmony_ci * It shall be instantiated several times, using different sets of directives.
5762306a36Sopenharmony_ci * Note that it is important for performance that this function really get inlined,
5862306a36Sopenharmony_ci * in order to remove useless branches during compilation optimization.
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_cistatic FORCE_INLINE int LZ4_decompress_generic(
6162306a36Sopenharmony_ci	 const char * const src,
6262306a36Sopenharmony_ci	 char * const dst,
6362306a36Sopenharmony_ci	 int srcSize,
6462306a36Sopenharmony_ci		/*
6562306a36Sopenharmony_ci		 * If endOnInput == endOnInputSize,
6662306a36Sopenharmony_ci		 * this value is `dstCapacity`
6762306a36Sopenharmony_ci		 */
6862306a36Sopenharmony_ci	 int outputSize,
6962306a36Sopenharmony_ci	 /* endOnOutputSize, endOnInputSize */
7062306a36Sopenharmony_ci	 endCondition_directive endOnInput,
7162306a36Sopenharmony_ci	 /* full, partial */
7262306a36Sopenharmony_ci	 earlyEnd_directive partialDecoding,
7362306a36Sopenharmony_ci	 /* noDict, withPrefix64k, usingExtDict */
7462306a36Sopenharmony_ci	 dict_directive dict,
7562306a36Sopenharmony_ci	 /* always <= dst, == dst when no prefix */
7662306a36Sopenharmony_ci	 const BYTE * const lowPrefix,
7762306a36Sopenharmony_ci	 /* only if dict == usingExtDict */
7862306a36Sopenharmony_ci	 const BYTE * const dictStart,
7962306a36Sopenharmony_ci	 /* note : = 0 if noDict */
8062306a36Sopenharmony_ci	 const size_t dictSize
8162306a36Sopenharmony_ci	 )
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	const BYTE *ip = (const BYTE *) src;
8462306a36Sopenharmony_ci	const BYTE * const iend = ip + srcSize;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	BYTE *op = (BYTE *) dst;
8762306a36Sopenharmony_ci	BYTE * const oend = op + outputSize;
8862306a36Sopenharmony_ci	BYTE *cpy;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
9162306a36Sopenharmony_ci	static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4};
9262306a36Sopenharmony_ci	static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	const int safeDecode = (endOnInput == endOnInputSize);
9562306a36Sopenharmony_ci	const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* Set up the "end" pointers for the shortcut. */
9862306a36Sopenharmony_ci	const BYTE *const shortiend = iend -
9962306a36Sopenharmony_ci		(endOnInput ? 14 : 8) /*maxLL*/ - 2 /*offset*/;
10062306a36Sopenharmony_ci	const BYTE *const shortoend = oend -
10162306a36Sopenharmony_ci		(endOnInput ? 14 : 8) /*maxLL*/ - 18 /*maxML*/;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	DEBUGLOG(5, "%s (srcSize:%i, dstSize:%i)", __func__,
10462306a36Sopenharmony_ci		 srcSize, outputSize);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/* Special cases */
10762306a36Sopenharmony_ci	assert(lowPrefix <= op);
10862306a36Sopenharmony_ci	assert(src != NULL);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* Empty output buffer */
11162306a36Sopenharmony_ci	if ((endOnInput) && (unlikely(outputSize == 0)))
11262306a36Sopenharmony_ci		return ((srcSize == 1) && (*ip == 0)) ? 0 : -1;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	if ((!endOnInput) && (unlikely(outputSize == 0)))
11562306a36Sopenharmony_ci		return (*ip == 0 ? 1 : -1);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if ((endOnInput) && unlikely(srcSize == 0))
11862306a36Sopenharmony_ci		return -1;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	/* Main Loop : decode sequences */
12162306a36Sopenharmony_ci	while (1) {
12262306a36Sopenharmony_ci		size_t length;
12362306a36Sopenharmony_ci		const BYTE *match;
12462306a36Sopenharmony_ci		size_t offset;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci		/* get literal length */
12762306a36Sopenharmony_ci		unsigned int const token = *ip++;
12862306a36Sopenharmony_ci		length = token>>ML_BITS;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		/* ip < iend before the increment */
13162306a36Sopenharmony_ci		assert(!endOnInput || ip <= iend);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci		/*
13462306a36Sopenharmony_ci		 * A two-stage shortcut for the most common case:
13562306a36Sopenharmony_ci		 * 1) If the literal length is 0..14, and there is enough
13662306a36Sopenharmony_ci		 * space, enter the shortcut and copy 16 bytes on behalf
13762306a36Sopenharmony_ci		 * of the literals (in the fast mode, only 8 bytes can be
13862306a36Sopenharmony_ci		 * safely copied this way).
13962306a36Sopenharmony_ci		 * 2) Further if the match length is 4..18, copy 18 bytes
14062306a36Sopenharmony_ci		 * in a similar manner; but we ensure that there's enough
14162306a36Sopenharmony_ci		 * space in the output for those 18 bytes earlier, upon
14262306a36Sopenharmony_ci		 * entering the shortcut (in other words, there is a
14362306a36Sopenharmony_ci		 * combined check for both stages).
14462306a36Sopenharmony_ci		 *
14562306a36Sopenharmony_ci		 * The & in the likely() below is intentionally not && so that
14662306a36Sopenharmony_ci		 * some compilers can produce better parallelized runtime code
14762306a36Sopenharmony_ci		 */
14862306a36Sopenharmony_ci		if ((endOnInput ? length != RUN_MASK : length <= 8)
14962306a36Sopenharmony_ci		   /*
15062306a36Sopenharmony_ci		    * strictly "less than" on input, to re-enter
15162306a36Sopenharmony_ci		    * the loop with at least one byte
15262306a36Sopenharmony_ci		    */
15362306a36Sopenharmony_ci		   && likely((endOnInput ? ip < shortiend : 1) &
15462306a36Sopenharmony_ci			     (op <= shortoend))) {
15562306a36Sopenharmony_ci			/* Copy the literals */
15662306a36Sopenharmony_ci			LZ4_memcpy(op, ip, endOnInput ? 16 : 8);
15762306a36Sopenharmony_ci			op += length; ip += length;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci			/*
16062306a36Sopenharmony_ci			 * The second stage:
16162306a36Sopenharmony_ci			 * prepare for match copying, decode full info.
16262306a36Sopenharmony_ci			 * If it doesn't work out, the info won't be wasted.
16362306a36Sopenharmony_ci			 */
16462306a36Sopenharmony_ci			length = token & ML_MASK; /* match length */
16562306a36Sopenharmony_ci			offset = LZ4_readLE16(ip);
16662306a36Sopenharmony_ci			ip += 2;
16762306a36Sopenharmony_ci			match = op - offset;
16862306a36Sopenharmony_ci			assert(match <= op); /* check overflow */
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci			/* Do not deal with overlapping matches. */
17162306a36Sopenharmony_ci			if ((length != ML_MASK) &&
17262306a36Sopenharmony_ci			    (offset >= 8) &&
17362306a36Sopenharmony_ci			    (dict == withPrefix64k || match >= lowPrefix)) {
17462306a36Sopenharmony_ci				/* Copy the match. */
17562306a36Sopenharmony_ci				LZ4_memcpy(op + 0, match + 0, 8);
17662306a36Sopenharmony_ci				LZ4_memcpy(op + 8, match + 8, 8);
17762306a36Sopenharmony_ci				LZ4_memcpy(op + 16, match + 16, 2);
17862306a36Sopenharmony_ci				op += length + MINMATCH;
17962306a36Sopenharmony_ci				/* Both stages worked, load the next token. */
18062306a36Sopenharmony_ci				continue;
18162306a36Sopenharmony_ci			}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci			/*
18462306a36Sopenharmony_ci			 * The second stage didn't work out, but the info
18562306a36Sopenharmony_ci			 * is ready. Propel it right to the point of match
18662306a36Sopenharmony_ci			 * copying.
18762306a36Sopenharmony_ci			 */
18862306a36Sopenharmony_ci			goto _copy_match;
18962306a36Sopenharmony_ci		}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci		/* decode literal length */
19262306a36Sopenharmony_ci		if (length == RUN_MASK) {
19362306a36Sopenharmony_ci			unsigned int s;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci			if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) {
19662306a36Sopenharmony_ci				/* overflow detection */
19762306a36Sopenharmony_ci				goto _output_error;
19862306a36Sopenharmony_ci			}
19962306a36Sopenharmony_ci			do {
20062306a36Sopenharmony_ci				s = *ip++;
20162306a36Sopenharmony_ci				length += s;
20262306a36Sopenharmony_ci			} while (likely(endOnInput
20362306a36Sopenharmony_ci				? ip < iend - RUN_MASK
20462306a36Sopenharmony_ci				: 1) & (s == 255));
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci			if ((safeDecode)
20762306a36Sopenharmony_ci			    && unlikely((uptrval)(op) +
20862306a36Sopenharmony_ci					length < (uptrval)(op))) {
20962306a36Sopenharmony_ci				/* overflow detection */
21062306a36Sopenharmony_ci				goto _output_error;
21162306a36Sopenharmony_ci			}
21262306a36Sopenharmony_ci			if ((safeDecode)
21362306a36Sopenharmony_ci			    && unlikely((uptrval)(ip) +
21462306a36Sopenharmony_ci					length < (uptrval)(ip))) {
21562306a36Sopenharmony_ci				/* overflow detection */
21662306a36Sopenharmony_ci				goto _output_error;
21762306a36Sopenharmony_ci			}
21862306a36Sopenharmony_ci		}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		/* copy literals */
22162306a36Sopenharmony_ci		cpy = op + length;
22262306a36Sopenharmony_ci		LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci		if (((endOnInput) && ((cpy > oend - MFLIMIT)
22562306a36Sopenharmony_ci			|| (ip + length > iend - (2 + 1 + LASTLITERALS))))
22662306a36Sopenharmony_ci			|| ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) {
22762306a36Sopenharmony_ci			if (partialDecoding) {
22862306a36Sopenharmony_ci				if (cpy > oend) {
22962306a36Sopenharmony_ci					/*
23062306a36Sopenharmony_ci					 * Partial decoding :
23162306a36Sopenharmony_ci					 * stop in the middle of literal segment
23262306a36Sopenharmony_ci					 */
23362306a36Sopenharmony_ci					cpy = oend;
23462306a36Sopenharmony_ci					length = oend - op;
23562306a36Sopenharmony_ci				}
23662306a36Sopenharmony_ci				if ((endOnInput)
23762306a36Sopenharmony_ci					&& (ip + length > iend)) {
23862306a36Sopenharmony_ci					/*
23962306a36Sopenharmony_ci					 * Error :
24062306a36Sopenharmony_ci					 * read attempt beyond
24162306a36Sopenharmony_ci					 * end of input buffer
24262306a36Sopenharmony_ci					 */
24362306a36Sopenharmony_ci					goto _output_error;
24462306a36Sopenharmony_ci				}
24562306a36Sopenharmony_ci			} else {
24662306a36Sopenharmony_ci				if ((!endOnInput)
24762306a36Sopenharmony_ci					&& (cpy != oend)) {
24862306a36Sopenharmony_ci					/*
24962306a36Sopenharmony_ci					 * Error :
25062306a36Sopenharmony_ci					 * block decoding must
25162306a36Sopenharmony_ci					 * stop exactly there
25262306a36Sopenharmony_ci					 */
25362306a36Sopenharmony_ci					goto _output_error;
25462306a36Sopenharmony_ci				}
25562306a36Sopenharmony_ci				if ((endOnInput)
25662306a36Sopenharmony_ci					&& ((ip + length != iend)
25762306a36Sopenharmony_ci					|| (cpy > oend))) {
25862306a36Sopenharmony_ci					/*
25962306a36Sopenharmony_ci					 * Error :
26062306a36Sopenharmony_ci					 * input must be consumed
26162306a36Sopenharmony_ci					 */
26262306a36Sopenharmony_ci					goto _output_error;
26362306a36Sopenharmony_ci				}
26462306a36Sopenharmony_ci			}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci			/*
26762306a36Sopenharmony_ci			 * supports overlapping memory regions; only matters
26862306a36Sopenharmony_ci			 * for in-place decompression scenarios
26962306a36Sopenharmony_ci			 */
27062306a36Sopenharmony_ci			LZ4_memmove(op, ip, length);
27162306a36Sopenharmony_ci			ip += length;
27262306a36Sopenharmony_ci			op += length;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci			/* Necessarily EOF when !partialDecoding.
27562306a36Sopenharmony_ci			 * When partialDecoding, it is EOF if we've either
27662306a36Sopenharmony_ci			 * filled the output buffer or
27762306a36Sopenharmony_ci			 * can't proceed with reading an offset for following match.
27862306a36Sopenharmony_ci			 */
27962306a36Sopenharmony_ci			if (!partialDecoding || (cpy == oend) || (ip >= (iend - 2)))
28062306a36Sopenharmony_ci				break;
28162306a36Sopenharmony_ci		} else {
28262306a36Sopenharmony_ci			/* may overwrite up to WILDCOPYLENGTH beyond cpy */
28362306a36Sopenharmony_ci			LZ4_wildCopy(op, ip, cpy);
28462306a36Sopenharmony_ci			ip += length;
28562306a36Sopenharmony_ci			op = cpy;
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		/* get offset */
28962306a36Sopenharmony_ci		offset = LZ4_readLE16(ip);
29062306a36Sopenharmony_ci		ip += 2;
29162306a36Sopenharmony_ci		match = op - offset;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		/* get matchlength */
29462306a36Sopenharmony_ci		length = token & ML_MASK;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci_copy_match:
29762306a36Sopenharmony_ci		if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) {
29862306a36Sopenharmony_ci			/* Error : offset outside buffers */
29962306a36Sopenharmony_ci			goto _output_error;
30062306a36Sopenharmony_ci		}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		/* costs ~1%; silence an msan warning when offset == 0 */
30362306a36Sopenharmony_ci		/*
30462306a36Sopenharmony_ci		 * note : when partialDecoding, there is no guarantee that
30562306a36Sopenharmony_ci		 * at least 4 bytes remain available in output buffer
30662306a36Sopenharmony_ci		 */
30762306a36Sopenharmony_ci		if (!partialDecoding) {
30862306a36Sopenharmony_ci			assert(oend > op);
30962306a36Sopenharmony_ci			assert(oend - op >= 4);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci			LZ4_write32(op, (U32)offset);
31262306a36Sopenharmony_ci		}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		if (length == ML_MASK) {
31562306a36Sopenharmony_ci			unsigned int s;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci			do {
31862306a36Sopenharmony_ci				s = *ip++;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci				if ((endOnInput) && (ip > iend - LASTLITERALS))
32162306a36Sopenharmony_ci					goto _output_error;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci				length += s;
32462306a36Sopenharmony_ci			} while (s == 255);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci			if ((safeDecode)
32762306a36Sopenharmony_ci				&& unlikely(
32862306a36Sopenharmony_ci					(uptrval)(op) + length < (uptrval)op)) {
32962306a36Sopenharmony_ci				/* overflow detection */
33062306a36Sopenharmony_ci				goto _output_error;
33162306a36Sopenharmony_ci			}
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		length += MINMATCH;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci		/* match starting within external dictionary */
33762306a36Sopenharmony_ci		if ((dict == usingExtDict) && (match < lowPrefix)) {
33862306a36Sopenharmony_ci			if (unlikely(op + length > oend - LASTLITERALS)) {
33962306a36Sopenharmony_ci				/* doesn't respect parsing restriction */
34062306a36Sopenharmony_ci				if (!partialDecoding)
34162306a36Sopenharmony_ci					goto _output_error;
34262306a36Sopenharmony_ci				length = min(length, (size_t)(oend - op));
34362306a36Sopenharmony_ci			}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci			if (length <= (size_t)(lowPrefix - match)) {
34662306a36Sopenharmony_ci				/*
34762306a36Sopenharmony_ci				 * match fits entirely within external
34862306a36Sopenharmony_ci				 * dictionary : just copy
34962306a36Sopenharmony_ci				 */
35062306a36Sopenharmony_ci				memmove(op, dictEnd - (lowPrefix - match),
35162306a36Sopenharmony_ci					length);
35262306a36Sopenharmony_ci				op += length;
35362306a36Sopenharmony_ci			} else {
35462306a36Sopenharmony_ci				/*
35562306a36Sopenharmony_ci				 * match stretches into both external
35662306a36Sopenharmony_ci				 * dictionary and current block
35762306a36Sopenharmony_ci				 */
35862306a36Sopenharmony_ci				size_t const copySize = (size_t)(lowPrefix - match);
35962306a36Sopenharmony_ci				size_t const restSize = length - copySize;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci				LZ4_memcpy(op, dictEnd - copySize, copySize);
36262306a36Sopenharmony_ci				op += copySize;
36362306a36Sopenharmony_ci				if (restSize > (size_t)(op - lowPrefix)) {
36462306a36Sopenharmony_ci					/* overlap copy */
36562306a36Sopenharmony_ci					BYTE * const endOfMatch = op + restSize;
36662306a36Sopenharmony_ci					const BYTE *copyFrom = lowPrefix;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci					while (op < endOfMatch)
36962306a36Sopenharmony_ci						*op++ = *copyFrom++;
37062306a36Sopenharmony_ci				} else {
37162306a36Sopenharmony_ci					LZ4_memcpy(op, lowPrefix, restSize);
37262306a36Sopenharmony_ci					op += restSize;
37362306a36Sopenharmony_ci				}
37462306a36Sopenharmony_ci			}
37562306a36Sopenharmony_ci			continue;
37662306a36Sopenharmony_ci		}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci		/* copy match within block */
37962306a36Sopenharmony_ci		cpy = op + length;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci		/*
38262306a36Sopenharmony_ci		 * partialDecoding :
38362306a36Sopenharmony_ci		 * may not respect endBlock parsing restrictions
38462306a36Sopenharmony_ci		 */
38562306a36Sopenharmony_ci		assert(op <= oend);
38662306a36Sopenharmony_ci		if (partialDecoding &&
38762306a36Sopenharmony_ci		    (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
38862306a36Sopenharmony_ci			size_t const mlen = min(length, (size_t)(oend - op));
38962306a36Sopenharmony_ci			const BYTE * const matchEnd = match + mlen;
39062306a36Sopenharmony_ci			BYTE * const copyEnd = op + mlen;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci			if (matchEnd > op) {
39362306a36Sopenharmony_ci				/* overlap copy */
39462306a36Sopenharmony_ci				while (op < copyEnd)
39562306a36Sopenharmony_ci					*op++ = *match++;
39662306a36Sopenharmony_ci			} else {
39762306a36Sopenharmony_ci				LZ4_memcpy(op, match, mlen);
39862306a36Sopenharmony_ci			}
39962306a36Sopenharmony_ci			op = copyEnd;
40062306a36Sopenharmony_ci			if (op == oend)
40162306a36Sopenharmony_ci				break;
40262306a36Sopenharmony_ci			continue;
40362306a36Sopenharmony_ci		}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		if (unlikely(offset < 8)) {
40662306a36Sopenharmony_ci			op[0] = match[0];
40762306a36Sopenharmony_ci			op[1] = match[1];
40862306a36Sopenharmony_ci			op[2] = match[2];
40962306a36Sopenharmony_ci			op[3] = match[3];
41062306a36Sopenharmony_ci			match += inc32table[offset];
41162306a36Sopenharmony_ci			LZ4_memcpy(op + 4, match, 4);
41262306a36Sopenharmony_ci			match -= dec64table[offset];
41362306a36Sopenharmony_ci		} else {
41462306a36Sopenharmony_ci			LZ4_copy8(op, match);
41562306a36Sopenharmony_ci			match += 8;
41662306a36Sopenharmony_ci		}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		op += 8;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci		if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) {
42162306a36Sopenharmony_ci			BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci			if (cpy > oend - LASTLITERALS) {
42462306a36Sopenharmony_ci				/*
42562306a36Sopenharmony_ci				 * Error : last LASTLITERALS bytes
42662306a36Sopenharmony_ci				 * must be literals (uncompressed)
42762306a36Sopenharmony_ci				 */
42862306a36Sopenharmony_ci				goto _output_error;
42962306a36Sopenharmony_ci			}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci			if (op < oCopyLimit) {
43262306a36Sopenharmony_ci				LZ4_wildCopy(op, match, oCopyLimit);
43362306a36Sopenharmony_ci				match += oCopyLimit - op;
43462306a36Sopenharmony_ci				op = oCopyLimit;
43562306a36Sopenharmony_ci			}
43662306a36Sopenharmony_ci			while (op < cpy)
43762306a36Sopenharmony_ci				*op++ = *match++;
43862306a36Sopenharmony_ci		} else {
43962306a36Sopenharmony_ci			LZ4_copy8(op, match);
44062306a36Sopenharmony_ci			if (length > 16)
44162306a36Sopenharmony_ci				LZ4_wildCopy(op + 8, match + 8, cpy);
44262306a36Sopenharmony_ci		}
44362306a36Sopenharmony_ci		op = cpy; /* wildcopy correction */
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	/* end of decoding */
44762306a36Sopenharmony_ci	if (endOnInput) {
44862306a36Sopenharmony_ci		/* Nb of output bytes decoded */
44962306a36Sopenharmony_ci		return (int) (((char *)op) - dst);
45062306a36Sopenharmony_ci	} else {
45162306a36Sopenharmony_ci		/* Nb of input bytes read */
45262306a36Sopenharmony_ci		return (int) (((const char *)ip) - src);
45362306a36Sopenharmony_ci	}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* Overflow error detected */
45662306a36Sopenharmony_ci_output_error:
45762306a36Sopenharmony_ci	return (int) (-(((const char *)ip) - src)) - 1;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ciint LZ4_decompress_safe(const char *source, char *dest,
46162306a36Sopenharmony_ci	int compressedSize, int maxDecompressedSize)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
46462306a36Sopenharmony_ci				      compressedSize, maxDecompressedSize,
46562306a36Sopenharmony_ci				      endOnInputSize, decode_full_block,
46662306a36Sopenharmony_ci				      noDict, (BYTE *)dest, NULL, 0);
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ciint LZ4_decompress_safe_partial(const char *src, char *dst,
47062306a36Sopenharmony_ci	int compressedSize, int targetOutputSize, int dstCapacity)
47162306a36Sopenharmony_ci{
47262306a36Sopenharmony_ci	dstCapacity = min(targetOutputSize, dstCapacity);
47362306a36Sopenharmony_ci	return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,
47462306a36Sopenharmony_ci				      endOnInputSize, partial_decode,
47562306a36Sopenharmony_ci				      noDict, (BYTE *)dst, NULL, 0);
47662306a36Sopenharmony_ci}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ciint LZ4_decompress_fast(const char *source, char *dest, int originalSize)
47962306a36Sopenharmony_ci{
48062306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest, 0, originalSize,
48162306a36Sopenharmony_ci				      endOnOutputSize, decode_full_block,
48262306a36Sopenharmony_ci				      withPrefix64k,
48362306a36Sopenharmony_ci				      (BYTE *)dest - 64 * KB, NULL, 0);
48462306a36Sopenharmony_ci}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci/* ===== Instantiate a few more decoding cases, used more than once. ===== */
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest,
48962306a36Sopenharmony_ci				      int compressedSize, int maxOutputSize)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
49262306a36Sopenharmony_ci				      compressedSize, maxOutputSize,
49362306a36Sopenharmony_ci				      endOnInputSize, decode_full_block,
49462306a36Sopenharmony_ci				      withPrefix64k,
49562306a36Sopenharmony_ci				      (BYTE *)dest - 64 * KB, NULL, 0);
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest,
49962306a36Sopenharmony_ci					       int compressedSize,
50062306a36Sopenharmony_ci					       int maxOutputSize,
50162306a36Sopenharmony_ci					       size_t prefixSize)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
50462306a36Sopenharmony_ci				      compressedSize, maxOutputSize,
50562306a36Sopenharmony_ci				      endOnInputSize, decode_full_block,
50662306a36Sopenharmony_ci				      noDict,
50762306a36Sopenharmony_ci				      (BYTE *)dest - prefixSize, NULL, 0);
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic int LZ4_decompress_safe_forceExtDict(const char *source, char *dest,
51162306a36Sopenharmony_ci					    int compressedSize, int maxOutputSize,
51262306a36Sopenharmony_ci					    const void *dictStart, size_t dictSize)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
51562306a36Sopenharmony_ci				      compressedSize, maxOutputSize,
51662306a36Sopenharmony_ci				      endOnInputSize, decode_full_block,
51762306a36Sopenharmony_ci				      usingExtDict, (BYTE *)dest,
51862306a36Sopenharmony_ci				      (const BYTE *)dictStart, dictSize);
51962306a36Sopenharmony_ci}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_cistatic int LZ4_decompress_fast_extDict(const char *source, char *dest,
52262306a36Sopenharmony_ci				       int originalSize,
52362306a36Sopenharmony_ci				       const void *dictStart, size_t dictSize)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
52662306a36Sopenharmony_ci				      0, originalSize,
52762306a36Sopenharmony_ci				      endOnOutputSize, decode_full_block,
52862306a36Sopenharmony_ci				      usingExtDict, (BYTE *)dest,
52962306a36Sopenharmony_ci				      (const BYTE *)dictStart, dictSize);
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci/*
53362306a36Sopenharmony_ci * The "double dictionary" mode, for use with e.g. ring buffers: the first part
53462306a36Sopenharmony_ci * of the dictionary is passed as prefix, and the second via dictStart + dictSize.
53562306a36Sopenharmony_ci * These routines are used only once, in LZ4_decompress_*_continue().
53662306a36Sopenharmony_ci */
53762306a36Sopenharmony_cistatic FORCE_INLINE
53862306a36Sopenharmony_ciint LZ4_decompress_safe_doubleDict(const char *source, char *dest,
53962306a36Sopenharmony_ci				   int compressedSize, int maxOutputSize,
54062306a36Sopenharmony_ci				   size_t prefixSize,
54162306a36Sopenharmony_ci				   const void *dictStart, size_t dictSize)
54262306a36Sopenharmony_ci{
54362306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
54462306a36Sopenharmony_ci				      compressedSize, maxOutputSize,
54562306a36Sopenharmony_ci				      endOnInputSize, decode_full_block,
54662306a36Sopenharmony_ci				      usingExtDict, (BYTE *)dest - prefixSize,
54762306a36Sopenharmony_ci				      (const BYTE *)dictStart, dictSize);
54862306a36Sopenharmony_ci}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_cistatic FORCE_INLINE
55162306a36Sopenharmony_ciint LZ4_decompress_fast_doubleDict(const char *source, char *dest,
55262306a36Sopenharmony_ci				   int originalSize, size_t prefixSize,
55362306a36Sopenharmony_ci				   const void *dictStart, size_t dictSize)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	return LZ4_decompress_generic(source, dest,
55662306a36Sopenharmony_ci				      0, originalSize,
55762306a36Sopenharmony_ci				      endOnOutputSize, decode_full_block,
55862306a36Sopenharmony_ci				      usingExtDict, (BYTE *)dest - prefixSize,
55962306a36Sopenharmony_ci				      (const BYTE *)dictStart, dictSize);
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci/* ===== streaming decompression functions ===== */
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ciint LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode,
56562306a36Sopenharmony_ci	const char *dictionary, int dictSize)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	LZ4_streamDecode_t_internal *lz4sd =
56862306a36Sopenharmony_ci		&LZ4_streamDecode->internal_donotuse;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	lz4sd->prefixSize = (size_t) dictSize;
57162306a36Sopenharmony_ci	lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize;
57262306a36Sopenharmony_ci	lz4sd->externalDict = NULL;
57362306a36Sopenharmony_ci	lz4sd->extDictSize	= 0;
57462306a36Sopenharmony_ci	return 1;
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci/*
57862306a36Sopenharmony_ci * *_continue() :
57962306a36Sopenharmony_ci * These decoding functions allow decompression of multiple blocks
58062306a36Sopenharmony_ci * in "streaming" mode.
58162306a36Sopenharmony_ci * Previously decoded blocks must still be available at the memory
58262306a36Sopenharmony_ci * position where they were decoded.
58362306a36Sopenharmony_ci * If it's not possible, save the relevant part of
58462306a36Sopenharmony_ci * decoded data into a safe buffer,
58562306a36Sopenharmony_ci * and indicate where it stands using LZ4_setStreamDecode()
58662306a36Sopenharmony_ci */
58762306a36Sopenharmony_ciint LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode,
58862306a36Sopenharmony_ci	const char *source, char *dest, int compressedSize, int maxOutputSize)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	LZ4_streamDecode_t_internal *lz4sd =
59162306a36Sopenharmony_ci		&LZ4_streamDecode->internal_donotuse;
59262306a36Sopenharmony_ci	int result;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	if (lz4sd->prefixSize == 0) {
59562306a36Sopenharmony_ci		/* The first call, no dictionary yet. */
59662306a36Sopenharmony_ci		assert(lz4sd->extDictSize == 0);
59762306a36Sopenharmony_ci		result = LZ4_decompress_safe(source, dest,
59862306a36Sopenharmony_ci			compressedSize, maxOutputSize);
59962306a36Sopenharmony_ci		if (result <= 0)
60062306a36Sopenharmony_ci			return result;
60162306a36Sopenharmony_ci		lz4sd->prefixSize = result;
60262306a36Sopenharmony_ci		lz4sd->prefixEnd = (BYTE *)dest + result;
60362306a36Sopenharmony_ci	} else if (lz4sd->prefixEnd == (BYTE *)dest) {
60462306a36Sopenharmony_ci		/* They're rolling the current segment. */
60562306a36Sopenharmony_ci		if (lz4sd->prefixSize >= 64 * KB - 1)
60662306a36Sopenharmony_ci			result = LZ4_decompress_safe_withPrefix64k(source, dest,
60762306a36Sopenharmony_ci				compressedSize, maxOutputSize);
60862306a36Sopenharmony_ci		else if (lz4sd->extDictSize == 0)
60962306a36Sopenharmony_ci			result = LZ4_decompress_safe_withSmallPrefix(source,
61062306a36Sopenharmony_ci				dest, compressedSize, maxOutputSize,
61162306a36Sopenharmony_ci				lz4sd->prefixSize);
61262306a36Sopenharmony_ci		else
61362306a36Sopenharmony_ci			result = LZ4_decompress_safe_doubleDict(source, dest,
61462306a36Sopenharmony_ci				compressedSize, maxOutputSize,
61562306a36Sopenharmony_ci				lz4sd->prefixSize,
61662306a36Sopenharmony_ci				lz4sd->externalDict, lz4sd->extDictSize);
61762306a36Sopenharmony_ci		if (result <= 0)
61862306a36Sopenharmony_ci			return result;
61962306a36Sopenharmony_ci		lz4sd->prefixSize += result;
62062306a36Sopenharmony_ci		lz4sd->prefixEnd  += result;
62162306a36Sopenharmony_ci	} else {
62262306a36Sopenharmony_ci		/*
62362306a36Sopenharmony_ci		 * The buffer wraps around, or they're
62462306a36Sopenharmony_ci		 * switching to another buffer.
62562306a36Sopenharmony_ci		 */
62662306a36Sopenharmony_ci		lz4sd->extDictSize = lz4sd->prefixSize;
62762306a36Sopenharmony_ci		lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
62862306a36Sopenharmony_ci		result = LZ4_decompress_safe_forceExtDict(source, dest,
62962306a36Sopenharmony_ci			compressedSize, maxOutputSize,
63062306a36Sopenharmony_ci			lz4sd->externalDict, lz4sd->extDictSize);
63162306a36Sopenharmony_ci		if (result <= 0)
63262306a36Sopenharmony_ci			return result;
63362306a36Sopenharmony_ci		lz4sd->prefixSize = result;
63462306a36Sopenharmony_ci		lz4sd->prefixEnd  = (BYTE *)dest + result;
63562306a36Sopenharmony_ci	}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	return result;
63862306a36Sopenharmony_ci}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ciint LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode,
64162306a36Sopenharmony_ci	const char *source, char *dest, int originalSize)
64262306a36Sopenharmony_ci{
64362306a36Sopenharmony_ci	LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse;
64462306a36Sopenharmony_ci	int result;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	if (lz4sd->prefixSize == 0) {
64762306a36Sopenharmony_ci		assert(lz4sd->extDictSize == 0);
64862306a36Sopenharmony_ci		result = LZ4_decompress_fast(source, dest, originalSize);
64962306a36Sopenharmony_ci		if (result <= 0)
65062306a36Sopenharmony_ci			return result;
65162306a36Sopenharmony_ci		lz4sd->prefixSize = originalSize;
65262306a36Sopenharmony_ci		lz4sd->prefixEnd = (BYTE *)dest + originalSize;
65362306a36Sopenharmony_ci	} else if (lz4sd->prefixEnd == (BYTE *)dest) {
65462306a36Sopenharmony_ci		if (lz4sd->prefixSize >= 64 * KB - 1 ||
65562306a36Sopenharmony_ci		    lz4sd->extDictSize == 0)
65662306a36Sopenharmony_ci			result = LZ4_decompress_fast(source, dest,
65762306a36Sopenharmony_ci						     originalSize);
65862306a36Sopenharmony_ci		else
65962306a36Sopenharmony_ci			result = LZ4_decompress_fast_doubleDict(source, dest,
66062306a36Sopenharmony_ci				originalSize, lz4sd->prefixSize,
66162306a36Sopenharmony_ci				lz4sd->externalDict, lz4sd->extDictSize);
66262306a36Sopenharmony_ci		if (result <= 0)
66362306a36Sopenharmony_ci			return result;
66462306a36Sopenharmony_ci		lz4sd->prefixSize += originalSize;
66562306a36Sopenharmony_ci		lz4sd->prefixEnd  += originalSize;
66662306a36Sopenharmony_ci	} else {
66762306a36Sopenharmony_ci		lz4sd->extDictSize = lz4sd->prefixSize;
66862306a36Sopenharmony_ci		lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
66962306a36Sopenharmony_ci		result = LZ4_decompress_fast_extDict(source, dest,
67062306a36Sopenharmony_ci			originalSize, lz4sd->externalDict, lz4sd->extDictSize);
67162306a36Sopenharmony_ci		if (result <= 0)
67262306a36Sopenharmony_ci			return result;
67362306a36Sopenharmony_ci		lz4sd->prefixSize = originalSize;
67462306a36Sopenharmony_ci		lz4sd->prefixEnd = (BYTE *)dest + originalSize;
67562306a36Sopenharmony_ci	}
67662306a36Sopenharmony_ci	return result;
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ciint LZ4_decompress_safe_usingDict(const char *source, char *dest,
68062306a36Sopenharmony_ci				  int compressedSize, int maxOutputSize,
68162306a36Sopenharmony_ci				  const char *dictStart, int dictSize)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	if (dictSize == 0)
68462306a36Sopenharmony_ci		return LZ4_decompress_safe(source, dest,
68562306a36Sopenharmony_ci					   compressedSize, maxOutputSize);
68662306a36Sopenharmony_ci	if (dictStart+dictSize == dest) {
68762306a36Sopenharmony_ci		if (dictSize >= 64 * KB - 1)
68862306a36Sopenharmony_ci			return LZ4_decompress_safe_withPrefix64k(source, dest,
68962306a36Sopenharmony_ci				compressedSize, maxOutputSize);
69062306a36Sopenharmony_ci		return LZ4_decompress_safe_withSmallPrefix(source, dest,
69162306a36Sopenharmony_ci			compressedSize, maxOutputSize, dictSize);
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci	return LZ4_decompress_safe_forceExtDict(source, dest,
69462306a36Sopenharmony_ci		compressedSize, maxOutputSize, dictStart, dictSize);
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ciint LZ4_decompress_fast_usingDict(const char *source, char *dest,
69862306a36Sopenharmony_ci				  int originalSize,
69962306a36Sopenharmony_ci				  const char *dictStart, int dictSize)
70062306a36Sopenharmony_ci{
70162306a36Sopenharmony_ci	if (dictSize == 0 || dictStart + dictSize == dest)
70262306a36Sopenharmony_ci		return LZ4_decompress_fast(source, dest, originalSize);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	return LZ4_decompress_fast_extDict(source, dest, originalSize,
70562306a36Sopenharmony_ci		dictStart, dictSize);
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci#ifndef STATIC
70962306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_safe);
71062306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_safe_partial);
71162306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_fast);
71262306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_setStreamDecode);
71362306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_safe_continue);
71462306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_fast_continue);
71562306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_safe_usingDict);
71662306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_decompress_fast_usingDict);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
71962306a36Sopenharmony_ciMODULE_DESCRIPTION("LZ4 decompressor");
72062306a36Sopenharmony_ci#endif
721