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/module.h>
3962306a36Sopenharmony_ci#include <linux/kernel.h>
4062306a36Sopenharmony_ci#include <asm/unaligned.h>
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic const int LZ4_minLength = (MFLIMIT + 1);
4362306a36Sopenharmony_cistatic const int LZ4_64Klimit = ((64 * KB) + (MFLIMIT - 1));
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/*-******************************
4662306a36Sopenharmony_ci *	Compression functions
4762306a36Sopenharmony_ci ********************************/
4862306a36Sopenharmony_cistatic FORCE_INLINE U32 LZ4_hash4(
4962306a36Sopenharmony_ci	U32 sequence,
5062306a36Sopenharmony_ci	tableType_t const tableType)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	if (tableType == byU16)
5362306a36Sopenharmony_ci		return ((sequence * 2654435761U)
5462306a36Sopenharmony_ci			>> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
5562306a36Sopenharmony_ci	else
5662306a36Sopenharmony_ci		return ((sequence * 2654435761U)
5762306a36Sopenharmony_ci			>> ((MINMATCH * 8) - LZ4_HASHLOG));
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic FORCE_INLINE U32 LZ4_hash5(
6162306a36Sopenharmony_ci	U64 sequence,
6262306a36Sopenharmony_ci	tableType_t const tableType)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	const U32 hashLog = (tableType == byU16)
6562306a36Sopenharmony_ci		? LZ4_HASHLOG + 1
6662306a36Sopenharmony_ci		: LZ4_HASHLOG;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#if LZ4_LITTLE_ENDIAN
6962306a36Sopenharmony_ci	static const U64 prime5bytes = 889523592379ULL;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
7262306a36Sopenharmony_ci#else
7362306a36Sopenharmony_ci	static const U64 prime8bytes = 11400714785074694791ULL;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
7662306a36Sopenharmony_ci#endif
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic FORCE_INLINE U32 LZ4_hashPosition(
8062306a36Sopenharmony_ci	const void *p,
8162306a36Sopenharmony_ci	tableType_t const tableType)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci#if LZ4_ARCH64
8462306a36Sopenharmony_ci	if (tableType == byU32)
8562306a36Sopenharmony_ci		return LZ4_hash5(LZ4_read_ARCH(p), tableType);
8662306a36Sopenharmony_ci#endif
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	return LZ4_hash4(LZ4_read32(p), tableType);
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic void LZ4_putPositionOnHash(
9262306a36Sopenharmony_ci	const BYTE *p,
9362306a36Sopenharmony_ci	U32 h,
9462306a36Sopenharmony_ci	void *tableBase,
9562306a36Sopenharmony_ci	tableType_t const tableType,
9662306a36Sopenharmony_ci	const BYTE *srcBase)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	switch (tableType) {
9962306a36Sopenharmony_ci	case byPtr:
10062306a36Sopenharmony_ci	{
10162306a36Sopenharmony_ci		const BYTE **hashTable = (const BYTE **)tableBase;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		hashTable[h] = p;
10462306a36Sopenharmony_ci		return;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci	case byU32:
10762306a36Sopenharmony_ci	{
10862306a36Sopenharmony_ci		U32 *hashTable = (U32 *) tableBase;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		hashTable[h] = (U32)(p - srcBase);
11162306a36Sopenharmony_ci		return;
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci	case byU16:
11462306a36Sopenharmony_ci	{
11562306a36Sopenharmony_ci		U16 *hashTable = (U16 *) tableBase;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		hashTable[h] = (U16)(p - srcBase);
11862306a36Sopenharmony_ci		return;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic FORCE_INLINE void LZ4_putPosition(
12462306a36Sopenharmony_ci	const BYTE *p,
12562306a36Sopenharmony_ci	void *tableBase,
12662306a36Sopenharmony_ci	tableType_t tableType,
12762306a36Sopenharmony_ci	const BYTE *srcBase)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	U32 const h = LZ4_hashPosition(p, tableType);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic const BYTE *LZ4_getPositionOnHash(
13562306a36Sopenharmony_ci	U32 h,
13662306a36Sopenharmony_ci	void *tableBase,
13762306a36Sopenharmony_ci	tableType_t tableType,
13862306a36Sopenharmony_ci	const BYTE *srcBase)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	if (tableType == byPtr) {
14162306a36Sopenharmony_ci		const BYTE **hashTable = (const BYTE **) tableBase;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		return hashTable[h];
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (tableType == byU32) {
14762306a36Sopenharmony_ci		const U32 * const hashTable = (U32 *) tableBase;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		return hashTable[h] + srcBase;
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	{
15362306a36Sopenharmony_ci		/* default, to ensure a return */
15462306a36Sopenharmony_ci		const U16 * const hashTable = (U16 *) tableBase;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		return hashTable[h] + srcBase;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic FORCE_INLINE const BYTE *LZ4_getPosition(
16162306a36Sopenharmony_ci	const BYTE *p,
16262306a36Sopenharmony_ci	void *tableBase,
16362306a36Sopenharmony_ci	tableType_t tableType,
16462306a36Sopenharmony_ci	const BYTE *srcBase)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	U32 const h = LZ4_hashPosition(p, tableType);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci/*
17362306a36Sopenharmony_ci * LZ4_compress_generic() :
17462306a36Sopenharmony_ci * inlined, to ensure branches are decided at compilation time
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_cistatic FORCE_INLINE int LZ4_compress_generic(
17762306a36Sopenharmony_ci	LZ4_stream_t_internal * const dictPtr,
17862306a36Sopenharmony_ci	const char * const source,
17962306a36Sopenharmony_ci	char * const dest,
18062306a36Sopenharmony_ci	const int inputSize,
18162306a36Sopenharmony_ci	const int maxOutputSize,
18262306a36Sopenharmony_ci	const limitedOutput_directive outputLimited,
18362306a36Sopenharmony_ci	const tableType_t tableType,
18462306a36Sopenharmony_ci	const dict_directive dict,
18562306a36Sopenharmony_ci	const dictIssue_directive dictIssue,
18662306a36Sopenharmony_ci	const U32 acceleration)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	const BYTE *ip = (const BYTE *) source;
18962306a36Sopenharmony_ci	const BYTE *base;
19062306a36Sopenharmony_ci	const BYTE *lowLimit;
19162306a36Sopenharmony_ci	const BYTE * const lowRefLimit = ip - dictPtr->dictSize;
19262306a36Sopenharmony_ci	const BYTE * const dictionary = dictPtr->dictionary;
19362306a36Sopenharmony_ci	const BYTE * const dictEnd = dictionary + dictPtr->dictSize;
19462306a36Sopenharmony_ci	const size_t dictDelta = dictEnd - (const BYTE *)source;
19562306a36Sopenharmony_ci	const BYTE *anchor = (const BYTE *) source;
19662306a36Sopenharmony_ci	const BYTE * const iend = ip + inputSize;
19762306a36Sopenharmony_ci	const BYTE * const mflimit = iend - MFLIMIT;
19862306a36Sopenharmony_ci	const BYTE * const matchlimit = iend - LASTLITERALS;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	BYTE *op = (BYTE *) dest;
20162306a36Sopenharmony_ci	BYTE * const olimit = op + maxOutputSize;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	U32 forwardH;
20462306a36Sopenharmony_ci	size_t refDelta = 0;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	/* Init conditions */
20762306a36Sopenharmony_ci	if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) {
20862306a36Sopenharmony_ci		/* Unsupported inputSize, too large (or negative) */
20962306a36Sopenharmony_ci		return 0;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	switch (dict) {
21362306a36Sopenharmony_ci	case noDict:
21462306a36Sopenharmony_ci	default:
21562306a36Sopenharmony_ci		base = (const BYTE *)source;
21662306a36Sopenharmony_ci		lowLimit = (const BYTE *)source;
21762306a36Sopenharmony_ci		break;
21862306a36Sopenharmony_ci	case withPrefix64k:
21962306a36Sopenharmony_ci		base = (const BYTE *)source - dictPtr->currentOffset;
22062306a36Sopenharmony_ci		lowLimit = (const BYTE *)source - dictPtr->dictSize;
22162306a36Sopenharmony_ci		break;
22262306a36Sopenharmony_ci	case usingExtDict:
22362306a36Sopenharmony_ci		base = (const BYTE *)source - dictPtr->currentOffset;
22462306a36Sopenharmony_ci		lowLimit = (const BYTE *)source;
22562306a36Sopenharmony_ci		break;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if ((tableType == byU16)
22962306a36Sopenharmony_ci		&& (inputSize >= LZ4_64Klimit)) {
23062306a36Sopenharmony_ci		/* Size too large (not within 64K limit) */
23162306a36Sopenharmony_ci		return 0;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (inputSize < LZ4_minLength) {
23562306a36Sopenharmony_ci		/* Input too small, no compression (all literals) */
23662306a36Sopenharmony_ci		goto _last_literals;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* First Byte */
24062306a36Sopenharmony_ci	LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
24162306a36Sopenharmony_ci	ip++;
24262306a36Sopenharmony_ci	forwardH = LZ4_hashPosition(ip, tableType);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* Main Loop */
24562306a36Sopenharmony_ci	for ( ; ; ) {
24662306a36Sopenharmony_ci		const BYTE *match;
24762306a36Sopenharmony_ci		BYTE *token;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci		/* Find a match */
25062306a36Sopenharmony_ci		{
25162306a36Sopenharmony_ci			const BYTE *forwardIp = ip;
25262306a36Sopenharmony_ci			unsigned int step = 1;
25362306a36Sopenharmony_ci			unsigned int searchMatchNb = acceleration << LZ4_SKIPTRIGGER;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci			do {
25662306a36Sopenharmony_ci				U32 const h = forwardH;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci				ip = forwardIp;
25962306a36Sopenharmony_ci				forwardIp += step;
26062306a36Sopenharmony_ci				step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci				if (unlikely(forwardIp > mflimit))
26362306a36Sopenharmony_ci					goto _last_literals;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci				match = LZ4_getPositionOnHash(h,
26662306a36Sopenharmony_ci					dictPtr->hashTable,
26762306a36Sopenharmony_ci					tableType, base);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci				if (dict == usingExtDict) {
27062306a36Sopenharmony_ci					if (match < (const BYTE *)source) {
27162306a36Sopenharmony_ci						refDelta = dictDelta;
27262306a36Sopenharmony_ci						lowLimit = dictionary;
27362306a36Sopenharmony_ci					} else {
27462306a36Sopenharmony_ci						refDelta = 0;
27562306a36Sopenharmony_ci						lowLimit = (const BYTE *)source;
27662306a36Sopenharmony_ci				}	 }
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci				forwardH = LZ4_hashPosition(forwardIp,
27962306a36Sopenharmony_ci					tableType);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci				LZ4_putPositionOnHash(ip, h, dictPtr->hashTable,
28262306a36Sopenharmony_ci					tableType, base);
28362306a36Sopenharmony_ci			} while (((dictIssue == dictSmall)
28462306a36Sopenharmony_ci					? (match < lowRefLimit)
28562306a36Sopenharmony_ci					: 0)
28662306a36Sopenharmony_ci				|| ((tableType == byU16)
28762306a36Sopenharmony_ci					? 0
28862306a36Sopenharmony_ci					: (match + MAX_DISTANCE < ip))
28962306a36Sopenharmony_ci				|| (LZ4_read32(match + refDelta)
29062306a36Sopenharmony_ci					!= LZ4_read32(ip)));
29162306a36Sopenharmony_ci		}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		/* Catch up */
29462306a36Sopenharmony_ci		while (((ip > anchor) & (match + refDelta > lowLimit))
29562306a36Sopenharmony_ci				&& (unlikely(ip[-1] == match[refDelta - 1]))) {
29662306a36Sopenharmony_ci			ip--;
29762306a36Sopenharmony_ci			match--;
29862306a36Sopenharmony_ci		}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		/* Encode Literals */
30162306a36Sopenharmony_ci		{
30262306a36Sopenharmony_ci			unsigned const int litLength = (unsigned int)(ip - anchor);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci			token = op++;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci			if ((outputLimited) &&
30762306a36Sopenharmony_ci				/* Check output buffer overflow */
30862306a36Sopenharmony_ci				(unlikely(op + litLength +
30962306a36Sopenharmony_ci					(2 + 1 + LASTLITERALS) +
31062306a36Sopenharmony_ci					(litLength / 255) > olimit)))
31162306a36Sopenharmony_ci				return 0;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci			if (litLength >= RUN_MASK) {
31462306a36Sopenharmony_ci				int len = (int)litLength - RUN_MASK;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci				*token = (RUN_MASK << ML_BITS);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci				for (; len >= 255; len -= 255)
31962306a36Sopenharmony_ci					*op++ = 255;
32062306a36Sopenharmony_ci				*op++ = (BYTE)len;
32162306a36Sopenharmony_ci			} else
32262306a36Sopenharmony_ci				*token = (BYTE)(litLength << ML_BITS);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci			/* Copy Literals */
32562306a36Sopenharmony_ci			LZ4_wildCopy(op, anchor, op + litLength);
32662306a36Sopenharmony_ci			op += litLength;
32762306a36Sopenharmony_ci		}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci_next_match:
33062306a36Sopenharmony_ci		/* Encode Offset */
33162306a36Sopenharmony_ci		LZ4_writeLE16(op, (U16)(ip - match));
33262306a36Sopenharmony_ci		op += 2;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		/* Encode MatchLength */
33562306a36Sopenharmony_ci		{
33662306a36Sopenharmony_ci			unsigned int matchCode;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci			if ((dict == usingExtDict)
33962306a36Sopenharmony_ci				&& (lowLimit == dictionary)) {
34062306a36Sopenharmony_ci				const BYTE *limit;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci				match += refDelta;
34362306a36Sopenharmony_ci				limit = ip + (dictEnd - match);
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci				if (limit > matchlimit)
34662306a36Sopenharmony_ci					limit = matchlimit;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci				matchCode = LZ4_count(ip + MINMATCH,
34962306a36Sopenharmony_ci					match + MINMATCH, limit);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci				ip += MINMATCH + matchCode;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci				if (ip == limit) {
35462306a36Sopenharmony_ci					unsigned const int more = LZ4_count(ip,
35562306a36Sopenharmony_ci						(const BYTE *)source,
35662306a36Sopenharmony_ci						matchlimit);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci					matchCode += more;
35962306a36Sopenharmony_ci					ip += more;
36062306a36Sopenharmony_ci				}
36162306a36Sopenharmony_ci			} else {
36262306a36Sopenharmony_ci				matchCode = LZ4_count(ip + MINMATCH,
36362306a36Sopenharmony_ci					match + MINMATCH, matchlimit);
36462306a36Sopenharmony_ci				ip += MINMATCH + matchCode;
36562306a36Sopenharmony_ci			}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci			if (outputLimited &&
36862306a36Sopenharmony_ci				/* Check output buffer overflow */
36962306a36Sopenharmony_ci				(unlikely(op +
37062306a36Sopenharmony_ci					(1 + LASTLITERALS) +
37162306a36Sopenharmony_ci					(matchCode >> 8) > olimit)))
37262306a36Sopenharmony_ci				return 0;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci			if (matchCode >= ML_MASK) {
37562306a36Sopenharmony_ci				*token += ML_MASK;
37662306a36Sopenharmony_ci				matchCode -= ML_MASK;
37762306a36Sopenharmony_ci				LZ4_write32(op, 0xFFFFFFFF);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci				while (matchCode >= 4 * 255) {
38062306a36Sopenharmony_ci					op += 4;
38162306a36Sopenharmony_ci					LZ4_write32(op, 0xFFFFFFFF);
38262306a36Sopenharmony_ci					matchCode -= 4 * 255;
38362306a36Sopenharmony_ci				}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci				op += matchCode / 255;
38662306a36Sopenharmony_ci				*op++ = (BYTE)(matchCode % 255);
38762306a36Sopenharmony_ci			} else
38862306a36Sopenharmony_ci				*token += (BYTE)(matchCode);
38962306a36Sopenharmony_ci		}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		anchor = ip;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci		/* Test end of chunk */
39462306a36Sopenharmony_ci		if (ip > mflimit)
39562306a36Sopenharmony_ci			break;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		/* Fill table */
39862306a36Sopenharmony_ci		LZ4_putPosition(ip - 2, dictPtr->hashTable, tableType, base);
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci		/* Test next position */
40162306a36Sopenharmony_ci		match = LZ4_getPosition(ip, dictPtr->hashTable,
40262306a36Sopenharmony_ci			tableType, base);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		if (dict == usingExtDict) {
40562306a36Sopenharmony_ci			if (match < (const BYTE *)source) {
40662306a36Sopenharmony_ci				refDelta = dictDelta;
40762306a36Sopenharmony_ci				lowLimit = dictionary;
40862306a36Sopenharmony_ci			} else {
40962306a36Sopenharmony_ci				refDelta = 0;
41062306a36Sopenharmony_ci				lowLimit = (const BYTE *)source;
41162306a36Sopenharmony_ci			}
41262306a36Sopenharmony_ci		}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci		LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci		if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1)
41762306a36Sopenharmony_ci			&& (match + MAX_DISTANCE >= ip)
41862306a36Sopenharmony_ci			&& (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
41962306a36Sopenharmony_ci			token = op++;
42062306a36Sopenharmony_ci			*token = 0;
42162306a36Sopenharmony_ci			goto _next_match;
42262306a36Sopenharmony_ci		}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		/* Prepare next loop */
42562306a36Sopenharmony_ci		forwardH = LZ4_hashPosition(++ip, tableType);
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci_last_literals:
42962306a36Sopenharmony_ci	/* Encode Last Literals */
43062306a36Sopenharmony_ci	{
43162306a36Sopenharmony_ci		size_t const lastRun = (size_t)(iend - anchor);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci		if ((outputLimited) &&
43462306a36Sopenharmony_ci			/* Check output buffer overflow */
43562306a36Sopenharmony_ci			((op - (BYTE *)dest) + lastRun + 1 +
43662306a36Sopenharmony_ci			((lastRun + 255 - RUN_MASK) / 255) > (U32)maxOutputSize))
43762306a36Sopenharmony_ci			return 0;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci		if (lastRun >= RUN_MASK) {
44062306a36Sopenharmony_ci			size_t accumulator = lastRun - RUN_MASK;
44162306a36Sopenharmony_ci			*op++ = RUN_MASK << ML_BITS;
44262306a36Sopenharmony_ci			for (; accumulator >= 255; accumulator -= 255)
44362306a36Sopenharmony_ci				*op++ = 255;
44462306a36Sopenharmony_ci			*op++ = (BYTE) accumulator;
44562306a36Sopenharmony_ci		} else {
44662306a36Sopenharmony_ci			*op++ = (BYTE)(lastRun << ML_BITS);
44762306a36Sopenharmony_ci		}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci		LZ4_memcpy(op, anchor, lastRun);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci		op += lastRun;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	/* End */
45562306a36Sopenharmony_ci	return (int) (((char *)op) - dest);
45662306a36Sopenharmony_ci}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cistatic int LZ4_compress_fast_extState(
45962306a36Sopenharmony_ci	void *state,
46062306a36Sopenharmony_ci	const char *source,
46162306a36Sopenharmony_ci	char *dest,
46262306a36Sopenharmony_ci	int inputSize,
46362306a36Sopenharmony_ci	int maxOutputSize,
46462306a36Sopenharmony_ci	int acceleration)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	LZ4_stream_t_internal *ctx = &((LZ4_stream_t *)state)->internal_donotuse;
46762306a36Sopenharmony_ci#if LZ4_ARCH64
46862306a36Sopenharmony_ci	const tableType_t tableType = byU32;
46962306a36Sopenharmony_ci#else
47062306a36Sopenharmony_ci	const tableType_t tableType = byPtr;
47162306a36Sopenharmony_ci#endif
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	LZ4_resetStream((LZ4_stream_t *)state);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	if (acceleration < 1)
47662306a36Sopenharmony_ci		acceleration = LZ4_ACCELERATION_DEFAULT;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	if (maxOutputSize >= LZ4_COMPRESSBOUND(inputSize)) {
47962306a36Sopenharmony_ci		if (inputSize < LZ4_64Klimit)
48062306a36Sopenharmony_ci			return LZ4_compress_generic(ctx, source,
48162306a36Sopenharmony_ci				dest, inputSize, 0,
48262306a36Sopenharmony_ci				noLimit, byU16, noDict,
48362306a36Sopenharmony_ci				noDictIssue, acceleration);
48462306a36Sopenharmony_ci		else
48562306a36Sopenharmony_ci			return LZ4_compress_generic(ctx, source,
48662306a36Sopenharmony_ci				dest, inputSize, 0,
48762306a36Sopenharmony_ci				noLimit, tableType, noDict,
48862306a36Sopenharmony_ci				noDictIssue, acceleration);
48962306a36Sopenharmony_ci	} else {
49062306a36Sopenharmony_ci		if (inputSize < LZ4_64Klimit)
49162306a36Sopenharmony_ci			return LZ4_compress_generic(ctx, source,
49262306a36Sopenharmony_ci				dest, inputSize,
49362306a36Sopenharmony_ci				maxOutputSize, limitedOutput, byU16, noDict,
49462306a36Sopenharmony_ci				noDictIssue, acceleration);
49562306a36Sopenharmony_ci		else
49662306a36Sopenharmony_ci			return LZ4_compress_generic(ctx, source,
49762306a36Sopenharmony_ci				dest, inputSize,
49862306a36Sopenharmony_ci				maxOutputSize, limitedOutput, tableType, noDict,
49962306a36Sopenharmony_ci				noDictIssue, acceleration);
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ciint LZ4_compress_fast(const char *source, char *dest, int inputSize,
50462306a36Sopenharmony_ci	int maxOutputSize, int acceleration, void *wrkmem)
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	return LZ4_compress_fast_extState(wrkmem, source, dest, inputSize,
50762306a36Sopenharmony_ci		maxOutputSize, acceleration);
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_fast);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ciint LZ4_compress_default(const char *source, char *dest, int inputSize,
51262306a36Sopenharmony_ci	int maxOutputSize, void *wrkmem)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	return LZ4_compress_fast(source, dest, inputSize,
51562306a36Sopenharmony_ci		maxOutputSize, LZ4_ACCELERATION_DEFAULT, wrkmem);
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_default);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci/*-******************************
52062306a36Sopenharmony_ci *	*_destSize() variant
52162306a36Sopenharmony_ci ********************************/
52262306a36Sopenharmony_cistatic int LZ4_compress_destSize_generic(
52362306a36Sopenharmony_ci	LZ4_stream_t_internal * const ctx,
52462306a36Sopenharmony_ci	const char * const src,
52562306a36Sopenharmony_ci	char * const dst,
52662306a36Sopenharmony_ci	int * const srcSizePtr,
52762306a36Sopenharmony_ci	const int targetDstSize,
52862306a36Sopenharmony_ci	const tableType_t tableType)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	const BYTE *ip = (const BYTE *) src;
53162306a36Sopenharmony_ci	const BYTE *base = (const BYTE *) src;
53262306a36Sopenharmony_ci	const BYTE *lowLimit = (const BYTE *) src;
53362306a36Sopenharmony_ci	const BYTE *anchor = ip;
53462306a36Sopenharmony_ci	const BYTE * const iend = ip + *srcSizePtr;
53562306a36Sopenharmony_ci	const BYTE * const mflimit = iend - MFLIMIT;
53662306a36Sopenharmony_ci	const BYTE * const matchlimit = iend - LASTLITERALS;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	BYTE *op = (BYTE *) dst;
53962306a36Sopenharmony_ci	BYTE * const oend = op + targetDstSize;
54062306a36Sopenharmony_ci	BYTE * const oMaxLit = op + targetDstSize - 2 /* offset */
54162306a36Sopenharmony_ci		- 8 /* because 8 + MINMATCH == MFLIMIT */ - 1 /* token */;
54262306a36Sopenharmony_ci	BYTE * const oMaxMatch = op + targetDstSize
54362306a36Sopenharmony_ci		- (LASTLITERALS + 1 /* token */);
54462306a36Sopenharmony_ci	BYTE * const oMaxSeq = oMaxLit - 1 /* token */;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	U32 forwardH;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/* Init conditions */
54962306a36Sopenharmony_ci	/* Impossible to store anything */
55062306a36Sopenharmony_ci	if (targetDstSize < 1)
55162306a36Sopenharmony_ci		return 0;
55262306a36Sopenharmony_ci	/* Unsupported input size, too large (or negative) */
55362306a36Sopenharmony_ci	if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE)
55462306a36Sopenharmony_ci		return 0;
55562306a36Sopenharmony_ci	/* Size too large (not within 64K limit) */
55662306a36Sopenharmony_ci	if ((tableType == byU16) && (*srcSizePtr >= LZ4_64Klimit))
55762306a36Sopenharmony_ci		return 0;
55862306a36Sopenharmony_ci	/* Input too small, no compression (all literals) */
55962306a36Sopenharmony_ci	if (*srcSizePtr < LZ4_minLength)
56062306a36Sopenharmony_ci		goto _last_literals;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* First Byte */
56362306a36Sopenharmony_ci	*srcSizePtr = 0;
56462306a36Sopenharmony_ci	LZ4_putPosition(ip, ctx->hashTable, tableType, base);
56562306a36Sopenharmony_ci	ip++; forwardH = LZ4_hashPosition(ip, tableType);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	/* Main Loop */
56862306a36Sopenharmony_ci	for ( ; ; ) {
56962306a36Sopenharmony_ci		const BYTE *match;
57062306a36Sopenharmony_ci		BYTE *token;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci		/* Find a match */
57362306a36Sopenharmony_ci		{
57462306a36Sopenharmony_ci			const BYTE *forwardIp = ip;
57562306a36Sopenharmony_ci			unsigned int step = 1;
57662306a36Sopenharmony_ci			unsigned int searchMatchNb = 1 << LZ4_SKIPTRIGGER;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci			do {
57962306a36Sopenharmony_ci				U32 h = forwardH;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci				ip = forwardIp;
58262306a36Sopenharmony_ci				forwardIp += step;
58362306a36Sopenharmony_ci				step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci				if (unlikely(forwardIp > mflimit))
58662306a36Sopenharmony_ci					goto _last_literals;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci				match = LZ4_getPositionOnHash(h, ctx->hashTable,
58962306a36Sopenharmony_ci					tableType, base);
59062306a36Sopenharmony_ci				forwardH = LZ4_hashPosition(forwardIp,
59162306a36Sopenharmony_ci					tableType);
59262306a36Sopenharmony_ci				LZ4_putPositionOnHash(ip, h,
59362306a36Sopenharmony_ci					ctx->hashTable, tableType,
59462306a36Sopenharmony_ci					base);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci			} while (((tableType == byU16)
59762306a36Sopenharmony_ci				? 0
59862306a36Sopenharmony_ci				: (match + MAX_DISTANCE < ip))
59962306a36Sopenharmony_ci				|| (LZ4_read32(match) != LZ4_read32(ip)));
60062306a36Sopenharmony_ci		}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci		/* Catch up */
60362306a36Sopenharmony_ci		while ((ip > anchor)
60462306a36Sopenharmony_ci			&& (match > lowLimit)
60562306a36Sopenharmony_ci			&& (unlikely(ip[-1] == match[-1]))) {
60662306a36Sopenharmony_ci			ip--;
60762306a36Sopenharmony_ci			match--;
60862306a36Sopenharmony_ci		}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci		/* Encode Literal length */
61162306a36Sopenharmony_ci		{
61262306a36Sopenharmony_ci			unsigned int litLength = (unsigned int)(ip - anchor);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci			token = op++;
61562306a36Sopenharmony_ci			if (op + ((litLength + 240) / 255)
61662306a36Sopenharmony_ci				+ litLength > oMaxLit) {
61762306a36Sopenharmony_ci				/* Not enough space for a last match */
61862306a36Sopenharmony_ci				op--;
61962306a36Sopenharmony_ci				goto _last_literals;
62062306a36Sopenharmony_ci			}
62162306a36Sopenharmony_ci			if (litLength >= RUN_MASK) {
62262306a36Sopenharmony_ci				unsigned int len = litLength - RUN_MASK;
62362306a36Sopenharmony_ci				*token = (RUN_MASK<<ML_BITS);
62462306a36Sopenharmony_ci				for (; len >= 255; len -= 255)
62562306a36Sopenharmony_ci					*op++ = 255;
62662306a36Sopenharmony_ci				*op++ = (BYTE)len;
62762306a36Sopenharmony_ci			} else
62862306a36Sopenharmony_ci				*token = (BYTE)(litLength << ML_BITS);
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci			/* Copy Literals */
63162306a36Sopenharmony_ci			LZ4_wildCopy(op, anchor, op + litLength);
63262306a36Sopenharmony_ci			op += litLength;
63362306a36Sopenharmony_ci		}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci_next_match:
63662306a36Sopenharmony_ci		/* Encode Offset */
63762306a36Sopenharmony_ci		LZ4_writeLE16(op, (U16)(ip - match)); op += 2;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci		/* Encode MatchLength */
64062306a36Sopenharmony_ci		{
64162306a36Sopenharmony_ci			size_t matchLength = LZ4_count(ip + MINMATCH,
64262306a36Sopenharmony_ci			match + MINMATCH, matchlimit);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci			if (op + ((matchLength + 240)/255) > oMaxMatch) {
64562306a36Sopenharmony_ci				/* Match description too long : reduce it */
64662306a36Sopenharmony_ci				matchLength = (15 - 1) + (oMaxMatch - op) * 255;
64762306a36Sopenharmony_ci			}
64862306a36Sopenharmony_ci			ip += MINMATCH + matchLength;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci			if (matchLength >= ML_MASK) {
65162306a36Sopenharmony_ci				*token += ML_MASK;
65262306a36Sopenharmony_ci				matchLength -= ML_MASK;
65362306a36Sopenharmony_ci				while (matchLength >= 255) {
65462306a36Sopenharmony_ci					matchLength -= 255;
65562306a36Sopenharmony_ci					*op++ = 255;
65662306a36Sopenharmony_ci				}
65762306a36Sopenharmony_ci				*op++ = (BYTE)matchLength;
65862306a36Sopenharmony_ci			} else
65962306a36Sopenharmony_ci				*token += (BYTE)(matchLength);
66062306a36Sopenharmony_ci		}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci		anchor = ip;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci		/* Test end of block */
66562306a36Sopenharmony_ci		if (ip > mflimit)
66662306a36Sopenharmony_ci			break;
66762306a36Sopenharmony_ci		if (op > oMaxSeq)
66862306a36Sopenharmony_ci			break;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci		/* Fill table */
67162306a36Sopenharmony_ci		LZ4_putPosition(ip - 2, ctx->hashTable, tableType, base);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci		/* Test next position */
67462306a36Sopenharmony_ci		match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
67562306a36Sopenharmony_ci		LZ4_putPosition(ip, ctx->hashTable, tableType, base);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci		if ((match + MAX_DISTANCE >= ip)
67862306a36Sopenharmony_ci			&& (LZ4_read32(match) == LZ4_read32(ip))) {
67962306a36Sopenharmony_ci			token = op++; *token = 0;
68062306a36Sopenharmony_ci			goto _next_match;
68162306a36Sopenharmony_ci		}
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci		/* Prepare next loop */
68462306a36Sopenharmony_ci		forwardH = LZ4_hashPosition(++ip, tableType);
68562306a36Sopenharmony_ci	}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci_last_literals:
68862306a36Sopenharmony_ci	/* Encode Last Literals */
68962306a36Sopenharmony_ci	{
69062306a36Sopenharmony_ci		size_t lastRunSize = (size_t)(iend - anchor);
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci		if (op + 1 /* token */
69362306a36Sopenharmony_ci			+ ((lastRunSize + 240) / 255) /* litLength */
69462306a36Sopenharmony_ci			+ lastRunSize /* literals */ > oend) {
69562306a36Sopenharmony_ci			/* adapt lastRunSize to fill 'dst' */
69662306a36Sopenharmony_ci			lastRunSize	= (oend - op) - 1;
69762306a36Sopenharmony_ci			lastRunSize -= (lastRunSize + 240) / 255;
69862306a36Sopenharmony_ci		}
69962306a36Sopenharmony_ci		ip = anchor + lastRunSize;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci		if (lastRunSize >= RUN_MASK) {
70262306a36Sopenharmony_ci			size_t accumulator = lastRunSize - RUN_MASK;
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci			*op++ = RUN_MASK << ML_BITS;
70562306a36Sopenharmony_ci			for (; accumulator >= 255; accumulator -= 255)
70662306a36Sopenharmony_ci				*op++ = 255;
70762306a36Sopenharmony_ci			*op++ = (BYTE) accumulator;
70862306a36Sopenharmony_ci		} else {
70962306a36Sopenharmony_ci			*op++ = (BYTE)(lastRunSize<<ML_BITS);
71062306a36Sopenharmony_ci		}
71162306a36Sopenharmony_ci		LZ4_memcpy(op, anchor, lastRunSize);
71262306a36Sopenharmony_ci		op += lastRunSize;
71362306a36Sopenharmony_ci	}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* End */
71662306a36Sopenharmony_ci	*srcSizePtr = (int) (((const char *)ip) - src);
71762306a36Sopenharmony_ci	return (int) (((char *)op) - dst);
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic int LZ4_compress_destSize_extState(
72162306a36Sopenharmony_ci	LZ4_stream_t *state,
72262306a36Sopenharmony_ci	const char *src,
72362306a36Sopenharmony_ci	char *dst,
72462306a36Sopenharmony_ci	int *srcSizePtr,
72562306a36Sopenharmony_ci	int targetDstSize)
72662306a36Sopenharmony_ci{
72762306a36Sopenharmony_ci#if LZ4_ARCH64
72862306a36Sopenharmony_ci	const tableType_t tableType = byU32;
72962306a36Sopenharmony_ci#else
73062306a36Sopenharmony_ci	const tableType_t tableType = byPtr;
73162306a36Sopenharmony_ci#endif
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_ci	LZ4_resetStream(state);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	if (targetDstSize >= LZ4_COMPRESSBOUND(*srcSizePtr)) {
73662306a36Sopenharmony_ci		/* compression success is guaranteed */
73762306a36Sopenharmony_ci		return LZ4_compress_fast_extState(
73862306a36Sopenharmony_ci			state, src, dst, *srcSizePtr,
73962306a36Sopenharmony_ci			targetDstSize, 1);
74062306a36Sopenharmony_ci	} else {
74162306a36Sopenharmony_ci		if (*srcSizePtr < LZ4_64Klimit)
74262306a36Sopenharmony_ci			return LZ4_compress_destSize_generic(
74362306a36Sopenharmony_ci				&state->internal_donotuse,
74462306a36Sopenharmony_ci				src, dst, srcSizePtr,
74562306a36Sopenharmony_ci				targetDstSize, byU16);
74662306a36Sopenharmony_ci		else
74762306a36Sopenharmony_ci			return LZ4_compress_destSize_generic(
74862306a36Sopenharmony_ci				&state->internal_donotuse,
74962306a36Sopenharmony_ci				src, dst, srcSizePtr,
75062306a36Sopenharmony_ci				targetDstSize, tableType);
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ciint LZ4_compress_destSize(
75662306a36Sopenharmony_ci	const char *src,
75762306a36Sopenharmony_ci	char *dst,
75862306a36Sopenharmony_ci	int *srcSizePtr,
75962306a36Sopenharmony_ci	int targetDstSize,
76062306a36Sopenharmony_ci	void *wrkmem)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	return LZ4_compress_destSize_extState(wrkmem, src, dst, srcSizePtr,
76362306a36Sopenharmony_ci		targetDstSize);
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_destSize);
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci/*-******************************
76862306a36Sopenharmony_ci *	Streaming functions
76962306a36Sopenharmony_ci ********************************/
77062306a36Sopenharmony_civoid LZ4_resetStream(LZ4_stream_t *LZ4_stream)
77162306a36Sopenharmony_ci{
77262306a36Sopenharmony_ci	memset(LZ4_stream, 0, sizeof(LZ4_stream_t));
77362306a36Sopenharmony_ci}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ciint LZ4_loadDict(LZ4_stream_t *LZ4_dict,
77662306a36Sopenharmony_ci	const char *dictionary, int dictSize)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	LZ4_stream_t_internal *dict = &LZ4_dict->internal_donotuse;
77962306a36Sopenharmony_ci	const BYTE *p = (const BYTE *)dictionary;
78062306a36Sopenharmony_ci	const BYTE * const dictEnd = p + dictSize;
78162306a36Sopenharmony_ci	const BYTE *base;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	if ((dict->initCheck)
78462306a36Sopenharmony_ci		|| (dict->currentOffset > 1 * GB)) {
78562306a36Sopenharmony_ci		/* Uninitialized structure, or reuse overflow */
78662306a36Sopenharmony_ci		LZ4_resetStream(LZ4_dict);
78762306a36Sopenharmony_ci	}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	if (dictSize < (int)HASH_UNIT) {
79062306a36Sopenharmony_ci		dict->dictionary = NULL;
79162306a36Sopenharmony_ci		dict->dictSize = 0;
79262306a36Sopenharmony_ci		return 0;
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if ((dictEnd - p) > 64 * KB)
79662306a36Sopenharmony_ci		p = dictEnd - 64 * KB;
79762306a36Sopenharmony_ci	dict->currentOffset += 64 * KB;
79862306a36Sopenharmony_ci	base = p - dict->currentOffset;
79962306a36Sopenharmony_ci	dict->dictionary = p;
80062306a36Sopenharmony_ci	dict->dictSize = (U32)(dictEnd - p);
80162306a36Sopenharmony_ci	dict->currentOffset += dict->dictSize;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	while (p <= dictEnd - HASH_UNIT) {
80462306a36Sopenharmony_ci		LZ4_putPosition(p, dict->hashTable, byU32, base);
80562306a36Sopenharmony_ci		p += 3;
80662306a36Sopenharmony_ci	}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	return dict->dictSize;
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_loadDict);
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_cistatic void LZ4_renormDictT(LZ4_stream_t_internal *LZ4_dict,
81362306a36Sopenharmony_ci	const BYTE *src)
81462306a36Sopenharmony_ci{
81562306a36Sopenharmony_ci	if ((LZ4_dict->currentOffset > 0x80000000) ||
81662306a36Sopenharmony_ci		((uptrval)LZ4_dict->currentOffset > (uptrval)src)) {
81762306a36Sopenharmony_ci		/* address space overflow */
81862306a36Sopenharmony_ci		/* rescale hash table */
81962306a36Sopenharmony_ci		U32 const delta = LZ4_dict->currentOffset - 64 * KB;
82062306a36Sopenharmony_ci		const BYTE *dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
82162306a36Sopenharmony_ci		int i;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci		for (i = 0; i < LZ4_HASH_SIZE_U32; i++) {
82462306a36Sopenharmony_ci			if (LZ4_dict->hashTable[i] < delta)
82562306a36Sopenharmony_ci				LZ4_dict->hashTable[i] = 0;
82662306a36Sopenharmony_ci			else
82762306a36Sopenharmony_ci				LZ4_dict->hashTable[i] -= delta;
82862306a36Sopenharmony_ci		}
82962306a36Sopenharmony_ci		LZ4_dict->currentOffset = 64 * KB;
83062306a36Sopenharmony_ci		if (LZ4_dict->dictSize > 64 * KB)
83162306a36Sopenharmony_ci			LZ4_dict->dictSize = 64 * KB;
83262306a36Sopenharmony_ci		LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
83362306a36Sopenharmony_ci	}
83462306a36Sopenharmony_ci}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ciint LZ4_saveDict(LZ4_stream_t *LZ4_dict, char *safeBuffer, int dictSize)
83762306a36Sopenharmony_ci{
83862306a36Sopenharmony_ci	LZ4_stream_t_internal * const dict = &LZ4_dict->internal_donotuse;
83962306a36Sopenharmony_ci	const BYTE * const previousDictEnd = dict->dictionary + dict->dictSize;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	if ((U32)dictSize > 64 * KB) {
84262306a36Sopenharmony_ci		/* useless to define a dictionary > 64 * KB */
84362306a36Sopenharmony_ci		dictSize = 64 * KB;
84462306a36Sopenharmony_ci	}
84562306a36Sopenharmony_ci	if ((U32)dictSize > dict->dictSize)
84662306a36Sopenharmony_ci		dictSize = dict->dictSize;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	dict->dictionary = (const BYTE *)safeBuffer;
85162306a36Sopenharmony_ci	dict->dictSize = (U32)dictSize;
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	return dictSize;
85462306a36Sopenharmony_ci}
85562306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_saveDict);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ciint LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source,
85862306a36Sopenharmony_ci	char *dest, int inputSize, int maxOutputSize, int acceleration)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci	LZ4_stream_t_internal *streamPtr = &LZ4_stream->internal_donotuse;
86162306a36Sopenharmony_ci	const BYTE * const dictEnd = streamPtr->dictionary
86262306a36Sopenharmony_ci		+ streamPtr->dictSize;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	const BYTE *smallest = (const BYTE *) source;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	if (streamPtr->initCheck) {
86762306a36Sopenharmony_ci		/* Uninitialized structure detected */
86862306a36Sopenharmony_ci		return 0;
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	if ((streamPtr->dictSize > 0) && (smallest > dictEnd))
87262306a36Sopenharmony_ci		smallest = dictEnd;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	LZ4_renormDictT(streamPtr, smallest);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	if (acceleration < 1)
87762306a36Sopenharmony_ci		acceleration = LZ4_ACCELERATION_DEFAULT;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* Check overlapping input/dictionary space */
88062306a36Sopenharmony_ci	{
88162306a36Sopenharmony_ci		const BYTE *sourceEnd = (const BYTE *) source + inputSize;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci		if ((sourceEnd > streamPtr->dictionary)
88462306a36Sopenharmony_ci			&& (sourceEnd < dictEnd)) {
88562306a36Sopenharmony_ci			streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
88662306a36Sopenharmony_ci			if (streamPtr->dictSize > 64 * KB)
88762306a36Sopenharmony_ci				streamPtr->dictSize = 64 * KB;
88862306a36Sopenharmony_ci			if (streamPtr->dictSize < 4)
88962306a36Sopenharmony_ci				streamPtr->dictSize = 0;
89062306a36Sopenharmony_ci			streamPtr->dictionary = dictEnd - streamPtr->dictSize;
89162306a36Sopenharmony_ci		}
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	/* prefix mode : source data follows dictionary */
89562306a36Sopenharmony_ci	if (dictEnd == (const BYTE *)source) {
89662306a36Sopenharmony_ci		int result;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci		if ((streamPtr->dictSize < 64 * KB) &&
89962306a36Sopenharmony_ci			(streamPtr->dictSize < streamPtr->currentOffset)) {
90062306a36Sopenharmony_ci			result = LZ4_compress_generic(
90162306a36Sopenharmony_ci				streamPtr, source, dest, inputSize,
90262306a36Sopenharmony_ci				maxOutputSize, limitedOutput, byU32,
90362306a36Sopenharmony_ci				withPrefix64k, dictSmall, acceleration);
90462306a36Sopenharmony_ci		} else {
90562306a36Sopenharmony_ci			result = LZ4_compress_generic(
90662306a36Sopenharmony_ci				streamPtr, source, dest, inputSize,
90762306a36Sopenharmony_ci				maxOutputSize, limitedOutput, byU32,
90862306a36Sopenharmony_ci				withPrefix64k, noDictIssue, acceleration);
90962306a36Sopenharmony_ci		}
91062306a36Sopenharmony_ci		streamPtr->dictSize += (U32)inputSize;
91162306a36Sopenharmony_ci		streamPtr->currentOffset += (U32)inputSize;
91262306a36Sopenharmony_ci		return result;
91362306a36Sopenharmony_ci	}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	/* external dictionary mode */
91662306a36Sopenharmony_ci	{
91762306a36Sopenharmony_ci		int result;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci		if ((streamPtr->dictSize < 64 * KB) &&
92062306a36Sopenharmony_ci			(streamPtr->dictSize < streamPtr->currentOffset)) {
92162306a36Sopenharmony_ci			result = LZ4_compress_generic(
92262306a36Sopenharmony_ci				streamPtr, source, dest, inputSize,
92362306a36Sopenharmony_ci				maxOutputSize, limitedOutput, byU32,
92462306a36Sopenharmony_ci				usingExtDict, dictSmall, acceleration);
92562306a36Sopenharmony_ci		} else {
92662306a36Sopenharmony_ci			result = LZ4_compress_generic(
92762306a36Sopenharmony_ci				streamPtr, source, dest, inputSize,
92862306a36Sopenharmony_ci				maxOutputSize, limitedOutput, byU32,
92962306a36Sopenharmony_ci				usingExtDict, noDictIssue, acceleration);
93062306a36Sopenharmony_ci		}
93162306a36Sopenharmony_ci		streamPtr->dictionary = (const BYTE *)source;
93262306a36Sopenharmony_ci		streamPtr->dictSize = (U32)inputSize;
93362306a36Sopenharmony_ci		streamPtr->currentOffset += (U32)inputSize;
93462306a36Sopenharmony_ci		return result;
93562306a36Sopenharmony_ci	}
93662306a36Sopenharmony_ci}
93762306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_fast_continue);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
94062306a36Sopenharmony_ciMODULE_DESCRIPTION("LZ4 compressor");
941