162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * LZ4 HC - High Compression Mode of LZ4
362306a36Sopenharmony_ci * Copyright (C) 2011-2015, Yann Collet.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
662306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
762306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are
862306a36Sopenharmony_ci * met:
962306a36Sopenharmony_ci *	* Redistributions of source code must retain the above copyright
1062306a36Sopenharmony_ci *	  notice, this list of conditions and the following disclaimer.
1162306a36Sopenharmony_ci *	* Redistributions in binary form must reproduce the above
1262306a36Sopenharmony_ci * copyright notice, this list of conditions and the following disclaimer
1362306a36Sopenharmony_ci * in the documentation and/or other materials provided with the
1462306a36Sopenharmony_ci * distribution.
1562306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1662306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1762306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1862306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1962306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2062306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2162306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2262306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2362306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2462306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2562306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2662306a36Sopenharmony_ci * You can contact the author at :
2762306a36Sopenharmony_ci *	- LZ4 homepage : http://www.lz4.org
2862306a36Sopenharmony_ci *	- LZ4 source repository : https://github.com/lz4/lz4
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci *	Changed for kernel usage by:
3162306a36Sopenharmony_ci *	Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/*-************************************
3562306a36Sopenharmony_ci *	Dependencies
3662306a36Sopenharmony_ci **************************************/
3762306a36Sopenharmony_ci#include <linux/lz4.h>
3862306a36Sopenharmony_ci#include "lz4defs.h"
3962306a36Sopenharmony_ci#include <linux/module.h>
4062306a36Sopenharmony_ci#include <linux/kernel.h>
4162306a36Sopenharmony_ci#include <linux/string.h> /* memset */
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* *************************************
4462306a36Sopenharmony_ci *	Local Constants and types
4562306a36Sopenharmony_ci ***************************************/
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define OPTIMAL_ML (int)((ML_MASK - 1) + MINMATCH)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define HASH_FUNCTION(i)	(((i) * 2654435761U) \
5062306a36Sopenharmony_ci	>> ((MINMATCH*8) - LZ4HC_HASH_LOG))
5162306a36Sopenharmony_ci#define DELTANEXTU16(p)	chainTable[(U16)(p)] /* faster */
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic U32 LZ4HC_hashPtr(const void *ptr)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	return HASH_FUNCTION(LZ4_read32(ptr));
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/**************************************
5962306a36Sopenharmony_ci *	HC Compression
6062306a36Sopenharmony_ci **************************************/
6162306a36Sopenharmony_cistatic void LZ4HC_init(LZ4HC_CCtx_internal *hc4, const BYTE *start)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	memset((void *)hc4->hashTable, 0, sizeof(hc4->hashTable));
6462306a36Sopenharmony_ci	memset(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
6562306a36Sopenharmony_ci	hc4->nextToUpdate = 64 * KB;
6662306a36Sopenharmony_ci	hc4->base = start - 64 * KB;
6762306a36Sopenharmony_ci	hc4->end = start;
6862306a36Sopenharmony_ci	hc4->dictBase = start - 64 * KB;
6962306a36Sopenharmony_ci	hc4->dictLimit = 64 * KB;
7062306a36Sopenharmony_ci	hc4->lowLimit = 64 * KB;
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* Update chains up to ip (excluded) */
7462306a36Sopenharmony_cistatic FORCE_INLINE void LZ4HC_Insert(LZ4HC_CCtx_internal *hc4,
7562306a36Sopenharmony_ci	const BYTE *ip)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	U16 * const chainTable = hc4->chainTable;
7862306a36Sopenharmony_ci	U32 * const hashTable	= hc4->hashTable;
7962306a36Sopenharmony_ci	const BYTE * const base = hc4->base;
8062306a36Sopenharmony_ci	U32 const target = (U32)(ip - base);
8162306a36Sopenharmony_ci	U32 idx = hc4->nextToUpdate;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	while (idx < target) {
8462306a36Sopenharmony_ci		U32 const h = LZ4HC_hashPtr(base + idx);
8562306a36Sopenharmony_ci		size_t delta = idx - hashTable[h];
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci		if (delta > MAX_DISTANCE)
8862306a36Sopenharmony_ci			delta = MAX_DISTANCE;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci		DELTANEXTU16(idx) = (U16)delta;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci		hashTable[h] = idx;
9362306a36Sopenharmony_ci		idx++;
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	hc4->nextToUpdate = target;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_InsertAndFindBestMatch(
10062306a36Sopenharmony_ci	LZ4HC_CCtx_internal *hc4, /* Index table will be updated */
10162306a36Sopenharmony_ci	const BYTE *ip,
10262306a36Sopenharmony_ci	const BYTE * const iLimit,
10362306a36Sopenharmony_ci	const BYTE **matchpos,
10462306a36Sopenharmony_ci	const int maxNbAttempts)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	U16 * const chainTable = hc4->chainTable;
10762306a36Sopenharmony_ci	U32 * const HashTable = hc4->hashTable;
10862306a36Sopenharmony_ci	const BYTE * const base = hc4->base;
10962306a36Sopenharmony_ci	const BYTE * const dictBase = hc4->dictBase;
11062306a36Sopenharmony_ci	const U32 dictLimit = hc4->dictLimit;
11162306a36Sopenharmony_ci	const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))
11262306a36Sopenharmony_ci		? hc4->lowLimit
11362306a36Sopenharmony_ci		: (U32)(ip - base) - (64 * KB - 1);
11462306a36Sopenharmony_ci	U32 matchIndex;
11562306a36Sopenharmony_ci	int nbAttempts = maxNbAttempts;
11662306a36Sopenharmony_ci	size_t ml = 0;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* HC4 match finder */
11962306a36Sopenharmony_ci	LZ4HC_Insert(hc4, ip);
12062306a36Sopenharmony_ci	matchIndex = HashTable[LZ4HC_hashPtr(ip)];
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	while ((matchIndex >= lowLimit)
12362306a36Sopenharmony_ci		&& (nbAttempts)) {
12462306a36Sopenharmony_ci		nbAttempts--;
12562306a36Sopenharmony_ci		if (matchIndex >= dictLimit) {
12662306a36Sopenharmony_ci			const BYTE * const match = base + matchIndex;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci			if (*(match + ml) == *(ip + ml)
12962306a36Sopenharmony_ci				&& (LZ4_read32(match) == LZ4_read32(ip))) {
13062306a36Sopenharmony_ci				size_t const mlt = LZ4_count(ip + MINMATCH,
13162306a36Sopenharmony_ci					match + MINMATCH, iLimit) + MINMATCH;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci				if (mlt > ml) {
13462306a36Sopenharmony_ci					ml = mlt;
13562306a36Sopenharmony_ci					*matchpos = match;
13662306a36Sopenharmony_ci				}
13762306a36Sopenharmony_ci			}
13862306a36Sopenharmony_ci		} else {
13962306a36Sopenharmony_ci			const BYTE * const match = dictBase + matchIndex;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci			if (LZ4_read32(match) == LZ4_read32(ip)) {
14262306a36Sopenharmony_ci				size_t mlt;
14362306a36Sopenharmony_ci				const BYTE *vLimit = ip
14462306a36Sopenharmony_ci					+ (dictLimit - matchIndex);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci				if (vLimit > iLimit)
14762306a36Sopenharmony_ci					vLimit = iLimit;
14862306a36Sopenharmony_ci				mlt = LZ4_count(ip + MINMATCH,
14962306a36Sopenharmony_ci					match + MINMATCH, vLimit) + MINMATCH;
15062306a36Sopenharmony_ci				if ((ip + mlt == vLimit)
15162306a36Sopenharmony_ci					&& (vLimit < iLimit))
15262306a36Sopenharmony_ci					mlt += LZ4_count(ip + mlt,
15362306a36Sopenharmony_ci						base + dictLimit,
15462306a36Sopenharmony_ci						iLimit);
15562306a36Sopenharmony_ci				if (mlt > ml) {
15662306a36Sopenharmony_ci					/* virtual matchpos */
15762306a36Sopenharmony_ci					ml = mlt;
15862306a36Sopenharmony_ci					*matchpos = base + matchIndex;
15962306a36Sopenharmony_ci				}
16062306a36Sopenharmony_ci			}
16162306a36Sopenharmony_ci		}
16262306a36Sopenharmony_ci		matchIndex -= DELTANEXTU16(matchIndex);
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	return (int)ml;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_InsertAndGetWiderMatch(
16962306a36Sopenharmony_ci	LZ4HC_CCtx_internal *hc4,
17062306a36Sopenharmony_ci	const BYTE * const ip,
17162306a36Sopenharmony_ci	const BYTE * const iLowLimit,
17262306a36Sopenharmony_ci	const BYTE * const iHighLimit,
17362306a36Sopenharmony_ci	int longest,
17462306a36Sopenharmony_ci	const BYTE **matchpos,
17562306a36Sopenharmony_ci	const BYTE **startpos,
17662306a36Sopenharmony_ci	const int maxNbAttempts)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	U16 * const chainTable = hc4->chainTable;
17962306a36Sopenharmony_ci	U32 * const HashTable = hc4->hashTable;
18062306a36Sopenharmony_ci	const BYTE * const base = hc4->base;
18162306a36Sopenharmony_ci	const U32 dictLimit = hc4->dictLimit;
18262306a36Sopenharmony_ci	const BYTE * const lowPrefixPtr = base + dictLimit;
18362306a36Sopenharmony_ci	const U32 lowLimit = (hc4->lowLimit + 64 * KB > (U32)(ip - base))
18462306a36Sopenharmony_ci		? hc4->lowLimit
18562306a36Sopenharmony_ci		: (U32)(ip - base) - (64 * KB - 1);
18662306a36Sopenharmony_ci	const BYTE * const dictBase = hc4->dictBase;
18762306a36Sopenharmony_ci	U32 matchIndex;
18862306a36Sopenharmony_ci	int nbAttempts = maxNbAttempts;
18962306a36Sopenharmony_ci	int delta = (int)(ip - iLowLimit);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	/* First Match */
19262306a36Sopenharmony_ci	LZ4HC_Insert(hc4, ip);
19362306a36Sopenharmony_ci	matchIndex = HashTable[LZ4HC_hashPtr(ip)];
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	while ((matchIndex >= lowLimit)
19662306a36Sopenharmony_ci		&& (nbAttempts)) {
19762306a36Sopenharmony_ci		nbAttempts--;
19862306a36Sopenharmony_ci		if (matchIndex >= dictLimit) {
19962306a36Sopenharmony_ci			const BYTE *matchPtr = base + matchIndex;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci			if (*(iLowLimit + longest)
20262306a36Sopenharmony_ci				== *(matchPtr - delta + longest)) {
20362306a36Sopenharmony_ci				if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
20462306a36Sopenharmony_ci					int mlt = MINMATCH + LZ4_count(
20562306a36Sopenharmony_ci						ip + MINMATCH,
20662306a36Sopenharmony_ci						matchPtr + MINMATCH,
20762306a36Sopenharmony_ci						iHighLimit);
20862306a36Sopenharmony_ci					int back = 0;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci					while ((ip + back > iLowLimit)
21162306a36Sopenharmony_ci						&& (matchPtr + back > lowPrefixPtr)
21262306a36Sopenharmony_ci						&& (ip[back - 1] == matchPtr[back - 1]))
21362306a36Sopenharmony_ci						back--;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci					mlt -= back;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci					if (mlt > longest) {
21862306a36Sopenharmony_ci						longest = (int)mlt;
21962306a36Sopenharmony_ci						*matchpos = matchPtr + back;
22062306a36Sopenharmony_ci						*startpos = ip + back;
22162306a36Sopenharmony_ci					}
22262306a36Sopenharmony_ci				}
22362306a36Sopenharmony_ci			}
22462306a36Sopenharmony_ci		} else {
22562306a36Sopenharmony_ci			const BYTE * const matchPtr = dictBase + matchIndex;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci			if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {
22862306a36Sopenharmony_ci				size_t mlt;
22962306a36Sopenharmony_ci				int back = 0;
23062306a36Sopenharmony_ci				const BYTE *vLimit = ip + (dictLimit - matchIndex);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci				if (vLimit > iHighLimit)
23362306a36Sopenharmony_ci					vLimit = iHighLimit;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci				mlt = LZ4_count(ip + MINMATCH,
23662306a36Sopenharmony_ci					matchPtr + MINMATCH, vLimit) + MINMATCH;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci				if ((ip + mlt == vLimit) && (vLimit < iHighLimit))
23962306a36Sopenharmony_ci					mlt += LZ4_count(ip + mlt, base + dictLimit,
24062306a36Sopenharmony_ci						iHighLimit);
24162306a36Sopenharmony_ci				while ((ip + back > iLowLimit)
24262306a36Sopenharmony_ci					&& (matchIndex + back > lowLimit)
24362306a36Sopenharmony_ci					&& (ip[back - 1] == matchPtr[back - 1]))
24462306a36Sopenharmony_ci					back--;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci				mlt -= back;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci				if ((int)mlt > longest) {
24962306a36Sopenharmony_ci					longest = (int)mlt;
25062306a36Sopenharmony_ci					*matchpos = base + matchIndex + back;
25162306a36Sopenharmony_ci					*startpos = ip + back;
25262306a36Sopenharmony_ci				}
25362306a36Sopenharmony_ci			}
25462306a36Sopenharmony_ci		}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci		matchIndex -= DELTANEXTU16(matchIndex);
25762306a36Sopenharmony_ci	}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	return longest;
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistatic FORCE_INLINE int LZ4HC_encodeSequence(
26362306a36Sopenharmony_ci	const BYTE **ip,
26462306a36Sopenharmony_ci	BYTE **op,
26562306a36Sopenharmony_ci	const BYTE **anchor,
26662306a36Sopenharmony_ci	int matchLength,
26762306a36Sopenharmony_ci	const BYTE * const match,
26862306a36Sopenharmony_ci	limitedOutput_directive limitedOutputBuffer,
26962306a36Sopenharmony_ci	BYTE *oend)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	int length;
27262306a36Sopenharmony_ci	BYTE *token;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	/* Encode Literal length */
27562306a36Sopenharmony_ci	length = (int)(*ip - *anchor);
27662306a36Sopenharmony_ci	token = (*op)++;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if ((limitedOutputBuffer)
27962306a36Sopenharmony_ci		&& ((*op + (length>>8)
28062306a36Sopenharmony_ci			+ length + (2 + 1 + LASTLITERALS)) > oend)) {
28162306a36Sopenharmony_ci		/* Check output limit */
28262306a36Sopenharmony_ci		return 1;
28362306a36Sopenharmony_ci	}
28462306a36Sopenharmony_ci	if (length >= (int)RUN_MASK) {
28562306a36Sopenharmony_ci		int len;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		*token = (RUN_MASK<<ML_BITS);
28862306a36Sopenharmony_ci		len = length - RUN_MASK;
28962306a36Sopenharmony_ci		for (; len > 254 ; len -= 255)
29062306a36Sopenharmony_ci			*(*op)++ = 255;
29162306a36Sopenharmony_ci		*(*op)++ = (BYTE)len;
29262306a36Sopenharmony_ci	} else
29362306a36Sopenharmony_ci		*token = (BYTE)(length<<ML_BITS);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	/* Copy Literals */
29662306a36Sopenharmony_ci	LZ4_wildCopy(*op, *anchor, (*op) + length);
29762306a36Sopenharmony_ci	*op += length;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	/* Encode Offset */
30062306a36Sopenharmony_ci	LZ4_writeLE16(*op, (U16)(*ip - match));
30162306a36Sopenharmony_ci	*op += 2;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/* Encode MatchLength */
30462306a36Sopenharmony_ci	length = (int)(matchLength - MINMATCH);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	if ((limitedOutputBuffer)
30762306a36Sopenharmony_ci		&& (*op + (length>>8)
30862306a36Sopenharmony_ci			+ (1 + LASTLITERALS) > oend)) {
30962306a36Sopenharmony_ci		/* Check output limit */
31062306a36Sopenharmony_ci		return 1;
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (length >= (int)ML_MASK) {
31462306a36Sopenharmony_ci		*token += ML_MASK;
31562306a36Sopenharmony_ci		length -= ML_MASK;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci		for (; length > 509 ; length -= 510) {
31862306a36Sopenharmony_ci			*(*op)++ = 255;
31962306a36Sopenharmony_ci			*(*op)++ = 255;
32062306a36Sopenharmony_ci		}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		if (length > 254) {
32362306a36Sopenharmony_ci			length -= 255;
32462306a36Sopenharmony_ci			*(*op)++ = 255;
32562306a36Sopenharmony_ci		}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci		*(*op)++ = (BYTE)length;
32862306a36Sopenharmony_ci	} else
32962306a36Sopenharmony_ci		*token += (BYTE)(length);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* Prepare next loop */
33262306a36Sopenharmony_ci	*ip += matchLength;
33362306a36Sopenharmony_ci	*anchor = *ip;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	return 0;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic int LZ4HC_compress_generic(
33962306a36Sopenharmony_ci	LZ4HC_CCtx_internal *const ctx,
34062306a36Sopenharmony_ci	const char * const source,
34162306a36Sopenharmony_ci	char * const dest,
34262306a36Sopenharmony_ci	int const inputSize,
34362306a36Sopenharmony_ci	int const maxOutputSize,
34462306a36Sopenharmony_ci	int compressionLevel,
34562306a36Sopenharmony_ci	limitedOutput_directive limit
34662306a36Sopenharmony_ci	)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	const BYTE *ip = (const BYTE *) source;
34962306a36Sopenharmony_ci	const BYTE *anchor = ip;
35062306a36Sopenharmony_ci	const BYTE * const iend = ip + inputSize;
35162306a36Sopenharmony_ci	const BYTE * const mflimit = iend - MFLIMIT;
35262306a36Sopenharmony_ci	const BYTE * const matchlimit = (iend - LASTLITERALS);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	BYTE *op = (BYTE *) dest;
35562306a36Sopenharmony_ci	BYTE * const oend = op + maxOutputSize;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	unsigned int maxNbAttempts;
35862306a36Sopenharmony_ci	int ml, ml2, ml3, ml0;
35962306a36Sopenharmony_ci	const BYTE *ref = NULL;
36062306a36Sopenharmony_ci	const BYTE *start2 = NULL;
36162306a36Sopenharmony_ci	const BYTE *ref2 = NULL;
36262306a36Sopenharmony_ci	const BYTE *start3 = NULL;
36362306a36Sopenharmony_ci	const BYTE *ref3 = NULL;
36462306a36Sopenharmony_ci	const BYTE *start0;
36562306a36Sopenharmony_ci	const BYTE *ref0;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* init */
36862306a36Sopenharmony_ci	if (compressionLevel > LZ4HC_MAX_CLEVEL)
36962306a36Sopenharmony_ci		compressionLevel = LZ4HC_MAX_CLEVEL;
37062306a36Sopenharmony_ci	if (compressionLevel < 1)
37162306a36Sopenharmony_ci		compressionLevel = LZ4HC_DEFAULT_CLEVEL;
37262306a36Sopenharmony_ci	maxNbAttempts = 1 << (compressionLevel - 1);
37362306a36Sopenharmony_ci	ctx->end += inputSize;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	ip++;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* Main Loop */
37862306a36Sopenharmony_ci	while (ip < mflimit) {
37962306a36Sopenharmony_ci		ml = LZ4HC_InsertAndFindBestMatch(ctx, ip,
38062306a36Sopenharmony_ci			matchlimit, (&ref), maxNbAttempts);
38162306a36Sopenharmony_ci		if (!ml) {
38262306a36Sopenharmony_ci			ip++;
38362306a36Sopenharmony_ci			continue;
38462306a36Sopenharmony_ci		}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci		/* saved, in case we would skip too much */
38762306a36Sopenharmony_ci		start0 = ip;
38862306a36Sopenharmony_ci		ref0 = ref;
38962306a36Sopenharmony_ci		ml0 = ml;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci_Search2:
39262306a36Sopenharmony_ci		if (ip + ml < mflimit)
39362306a36Sopenharmony_ci			ml2 = LZ4HC_InsertAndGetWiderMatch(ctx,
39462306a36Sopenharmony_ci				ip + ml - 2, ip + 0,
39562306a36Sopenharmony_ci				matchlimit, ml, &ref2,
39662306a36Sopenharmony_ci				&start2, maxNbAttempts);
39762306a36Sopenharmony_ci		else
39862306a36Sopenharmony_ci			ml2 = ml;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci		if (ml2 == ml) {
40162306a36Sopenharmony_ci			/* No better match */
40262306a36Sopenharmony_ci			if (LZ4HC_encodeSequence(&ip, &op,
40362306a36Sopenharmony_ci				&anchor, ml, ref, limit, oend))
40462306a36Sopenharmony_ci				return 0;
40562306a36Sopenharmony_ci			continue;
40662306a36Sopenharmony_ci		}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci		if (start0 < ip) {
40962306a36Sopenharmony_ci			if (start2 < ip + ml0) {
41062306a36Sopenharmony_ci				/* empirical */
41162306a36Sopenharmony_ci				ip = start0;
41262306a36Sopenharmony_ci				ref = ref0;
41362306a36Sopenharmony_ci				ml = ml0;
41462306a36Sopenharmony_ci			}
41562306a36Sopenharmony_ci		}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci		/* Here, start0 == ip */
41862306a36Sopenharmony_ci		if ((start2 - ip) < 3) {
41962306a36Sopenharmony_ci			/* First Match too small : removed */
42062306a36Sopenharmony_ci			ml = ml2;
42162306a36Sopenharmony_ci			ip = start2;
42262306a36Sopenharmony_ci			ref = ref2;
42362306a36Sopenharmony_ci			goto _Search2;
42462306a36Sopenharmony_ci		}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci_Search3:
42762306a36Sopenharmony_ci		/*
42862306a36Sopenharmony_ci		* Currently we have :
42962306a36Sopenharmony_ci		* ml2 > ml1, and
43062306a36Sopenharmony_ci		* ip1 + 3 <= ip2 (usually < ip1 + ml1)
43162306a36Sopenharmony_ci		*/
43262306a36Sopenharmony_ci		if ((start2 - ip) < OPTIMAL_ML) {
43362306a36Sopenharmony_ci			int correction;
43462306a36Sopenharmony_ci			int new_ml = ml;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci			if (new_ml > OPTIMAL_ML)
43762306a36Sopenharmony_ci				new_ml = OPTIMAL_ML;
43862306a36Sopenharmony_ci			if (ip + new_ml > start2 + ml2 - MINMATCH)
43962306a36Sopenharmony_ci				new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci			correction = new_ml - (int)(start2 - ip);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci			if (correction > 0) {
44462306a36Sopenharmony_ci				start2 += correction;
44562306a36Sopenharmony_ci				ref2 += correction;
44662306a36Sopenharmony_ci				ml2 -= correction;
44762306a36Sopenharmony_ci			}
44862306a36Sopenharmony_ci		}
44962306a36Sopenharmony_ci		/*
45062306a36Sopenharmony_ci		 * Now, we have start2 = ip + new_ml,
45162306a36Sopenharmony_ci		 * with new_ml = min(ml, OPTIMAL_ML = 18)
45262306a36Sopenharmony_ci		 */
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci		if (start2 + ml2 < mflimit)
45562306a36Sopenharmony_ci			ml3 = LZ4HC_InsertAndGetWiderMatch(ctx,
45662306a36Sopenharmony_ci				start2 + ml2 - 3, start2,
45762306a36Sopenharmony_ci				matchlimit, ml2, &ref3, &start3,
45862306a36Sopenharmony_ci				maxNbAttempts);
45962306a36Sopenharmony_ci		else
46062306a36Sopenharmony_ci			ml3 = ml2;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci		if (ml3 == ml2) {
46362306a36Sopenharmony_ci			/* No better match : 2 sequences to encode */
46462306a36Sopenharmony_ci			/* ip & ref are known; Now for ml */
46562306a36Sopenharmony_ci			if (start2 < ip + ml)
46662306a36Sopenharmony_ci				ml = (int)(start2 - ip);
46762306a36Sopenharmony_ci			/* Now, encode 2 sequences */
46862306a36Sopenharmony_ci			if (LZ4HC_encodeSequence(&ip, &op, &anchor,
46962306a36Sopenharmony_ci				ml, ref, limit, oend))
47062306a36Sopenharmony_ci				return 0;
47162306a36Sopenharmony_ci			ip = start2;
47262306a36Sopenharmony_ci			if (LZ4HC_encodeSequence(&ip, &op, &anchor,
47362306a36Sopenharmony_ci				ml2, ref2, limit, oend))
47462306a36Sopenharmony_ci				return 0;
47562306a36Sopenharmony_ci			continue;
47662306a36Sopenharmony_ci		}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		if (start3 < ip + ml + 3) {
47962306a36Sopenharmony_ci			/* Not enough space for match 2 : remove it */
48062306a36Sopenharmony_ci			if (start3 >= (ip + ml)) {
48162306a36Sopenharmony_ci				/* can write Seq1 immediately
48262306a36Sopenharmony_ci				 * ==> Seq2 is removed,
48362306a36Sopenharmony_ci				 * so Seq3 becomes Seq1
48462306a36Sopenharmony_ci				 */
48562306a36Sopenharmony_ci				if (start2 < ip + ml) {
48662306a36Sopenharmony_ci					int correction = (int)(ip + ml - start2);
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci					start2 += correction;
48962306a36Sopenharmony_ci					ref2 += correction;
49062306a36Sopenharmony_ci					ml2 -= correction;
49162306a36Sopenharmony_ci					if (ml2 < MINMATCH) {
49262306a36Sopenharmony_ci						start2 = start3;
49362306a36Sopenharmony_ci						ref2 = ref3;
49462306a36Sopenharmony_ci						ml2 = ml3;
49562306a36Sopenharmony_ci					}
49662306a36Sopenharmony_ci				}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci				if (LZ4HC_encodeSequence(&ip, &op, &anchor,
49962306a36Sopenharmony_ci					ml, ref, limit, oend))
50062306a36Sopenharmony_ci					return 0;
50162306a36Sopenharmony_ci				ip = start3;
50262306a36Sopenharmony_ci				ref = ref3;
50362306a36Sopenharmony_ci				ml = ml3;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci				start0 = start2;
50662306a36Sopenharmony_ci				ref0 = ref2;
50762306a36Sopenharmony_ci				ml0 = ml2;
50862306a36Sopenharmony_ci				goto _Search2;
50962306a36Sopenharmony_ci			}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci			start2 = start3;
51262306a36Sopenharmony_ci			ref2 = ref3;
51362306a36Sopenharmony_ci			ml2 = ml3;
51462306a36Sopenharmony_ci			goto _Search3;
51562306a36Sopenharmony_ci		}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci		/*
51862306a36Sopenharmony_ci		* OK, now we have 3 ascending matches;
51962306a36Sopenharmony_ci		* let's write at least the first one
52062306a36Sopenharmony_ci		* ip & ref are known; Now for ml
52162306a36Sopenharmony_ci		*/
52262306a36Sopenharmony_ci		if (start2 < ip + ml) {
52362306a36Sopenharmony_ci			if ((start2 - ip) < (int)ML_MASK) {
52462306a36Sopenharmony_ci				int correction;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci				if (ml > OPTIMAL_ML)
52762306a36Sopenharmony_ci					ml = OPTIMAL_ML;
52862306a36Sopenharmony_ci				if (ip + ml > start2 + ml2 - MINMATCH)
52962306a36Sopenharmony_ci					ml = (int)(start2 - ip) + ml2 - MINMATCH;
53062306a36Sopenharmony_ci				correction = ml - (int)(start2 - ip);
53162306a36Sopenharmony_ci				if (correction > 0) {
53262306a36Sopenharmony_ci					start2 += correction;
53362306a36Sopenharmony_ci					ref2 += correction;
53462306a36Sopenharmony_ci					ml2 -= correction;
53562306a36Sopenharmony_ci				}
53662306a36Sopenharmony_ci			} else
53762306a36Sopenharmony_ci				ml = (int)(start2 - ip);
53862306a36Sopenharmony_ci		}
53962306a36Sopenharmony_ci		if (LZ4HC_encodeSequence(&ip, &op, &anchor, ml,
54062306a36Sopenharmony_ci			ref, limit, oend))
54162306a36Sopenharmony_ci			return 0;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci		ip = start2;
54462306a36Sopenharmony_ci		ref = ref2;
54562306a36Sopenharmony_ci		ml = ml2;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci		start2 = start3;
54862306a36Sopenharmony_ci		ref2 = ref3;
54962306a36Sopenharmony_ci		ml2 = ml3;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci		goto _Search3;
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* Encode Last Literals */
55562306a36Sopenharmony_ci	{
55662306a36Sopenharmony_ci		int lastRun = (int)(iend - anchor);
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci		if ((limit)
55962306a36Sopenharmony_ci			&& (((char *)op - dest) + lastRun + 1
56062306a36Sopenharmony_ci				+ ((lastRun + 255 - RUN_MASK)/255)
56162306a36Sopenharmony_ci					> (U32)maxOutputSize)) {
56262306a36Sopenharmony_ci			/* Check output limit */
56362306a36Sopenharmony_ci			return 0;
56462306a36Sopenharmony_ci		}
56562306a36Sopenharmony_ci		if (lastRun >= (int)RUN_MASK) {
56662306a36Sopenharmony_ci			*op++ = (RUN_MASK<<ML_BITS);
56762306a36Sopenharmony_ci			lastRun -= RUN_MASK;
56862306a36Sopenharmony_ci			for (; lastRun > 254 ; lastRun -= 255)
56962306a36Sopenharmony_ci				*op++ = 255;
57062306a36Sopenharmony_ci			*op++ = (BYTE) lastRun;
57162306a36Sopenharmony_ci		} else
57262306a36Sopenharmony_ci			*op++ = (BYTE)(lastRun<<ML_BITS);
57362306a36Sopenharmony_ci		LZ4_memcpy(op, anchor, iend - anchor);
57462306a36Sopenharmony_ci		op += iend - anchor;
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* End */
57862306a36Sopenharmony_ci	return (int) (((char *)op) - dest);
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_cistatic int LZ4_compress_HC_extStateHC(
58262306a36Sopenharmony_ci	void *state,
58362306a36Sopenharmony_ci	const char *src,
58462306a36Sopenharmony_ci	char *dst,
58562306a36Sopenharmony_ci	int srcSize,
58662306a36Sopenharmony_ci	int maxDstSize,
58762306a36Sopenharmony_ci	int compressionLevel)
58862306a36Sopenharmony_ci{
58962306a36Sopenharmony_ci	LZ4HC_CCtx_internal *ctx = &((LZ4_streamHC_t *)state)->internal_donotuse;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (((size_t)(state)&(sizeof(void *) - 1)) != 0) {
59262306a36Sopenharmony_ci		/* Error : state is not aligned
59362306a36Sopenharmony_ci		 * for pointers (32 or 64 bits)
59462306a36Sopenharmony_ci		 */
59562306a36Sopenharmony_ci		return 0;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	LZ4HC_init(ctx, (const BYTE *)src);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (maxDstSize < LZ4_compressBound(srcSize))
60162306a36Sopenharmony_ci		return LZ4HC_compress_generic(ctx, src, dst,
60262306a36Sopenharmony_ci			srcSize, maxDstSize, compressionLevel, limitedOutput);
60362306a36Sopenharmony_ci	else
60462306a36Sopenharmony_ci		return LZ4HC_compress_generic(ctx, src, dst,
60562306a36Sopenharmony_ci			srcSize, maxDstSize, compressionLevel, noLimit);
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ciint LZ4_compress_HC(const char *src, char *dst, int srcSize,
60962306a36Sopenharmony_ci	int maxDstSize, int compressionLevel, void *wrkmem)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	return LZ4_compress_HC_extStateHC(wrkmem, src, dst,
61262306a36Sopenharmony_ci		srcSize, maxDstSize, compressionLevel);
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_HC);
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci/**************************************
61762306a36Sopenharmony_ci *	Streaming Functions
61862306a36Sopenharmony_ci **************************************/
61962306a36Sopenharmony_civoid LZ4_resetStreamHC(LZ4_streamHC_t *LZ4_streamHCPtr, int compressionLevel)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	LZ4_streamHCPtr->internal_donotuse.base = NULL;
62262306a36Sopenharmony_ci	LZ4_streamHCPtr->internal_donotuse.compressionLevel = (unsigned int)compressionLevel;
62362306a36Sopenharmony_ci}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ciint LZ4_loadDictHC(LZ4_streamHC_t *LZ4_streamHCPtr,
62662306a36Sopenharmony_ci	const char *dictionary,
62762306a36Sopenharmony_ci	int dictSize)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	if (dictSize > 64 * KB) {
63262306a36Sopenharmony_ci		dictionary += dictSize - 64 * KB;
63362306a36Sopenharmony_ci		dictSize = 64 * KB;
63462306a36Sopenharmony_ci	}
63562306a36Sopenharmony_ci	LZ4HC_init(ctxPtr, (const BYTE *)dictionary);
63662306a36Sopenharmony_ci	if (dictSize >= 4)
63762306a36Sopenharmony_ci		LZ4HC_Insert(ctxPtr, (const BYTE *)dictionary + (dictSize - 3));
63862306a36Sopenharmony_ci	ctxPtr->end = (const BYTE *)dictionary + dictSize;
63962306a36Sopenharmony_ci	return dictSize;
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_loadDictHC);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci/* compression */
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic void LZ4HC_setExternalDict(
64662306a36Sopenharmony_ci	LZ4HC_CCtx_internal *ctxPtr,
64762306a36Sopenharmony_ci	const BYTE *newBlock)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	if (ctxPtr->end >= ctxPtr->base + 4) {
65062306a36Sopenharmony_ci		/* Referencing remaining dictionary content */
65162306a36Sopenharmony_ci		LZ4HC_Insert(ctxPtr, ctxPtr->end - 3);
65262306a36Sopenharmony_ci	}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	/*
65562306a36Sopenharmony_ci	 * Only one memory segment for extDict,
65662306a36Sopenharmony_ci	 * so any previous extDict is lost at this stage
65762306a36Sopenharmony_ci	 */
65862306a36Sopenharmony_ci	ctxPtr->lowLimit	= ctxPtr->dictLimit;
65962306a36Sopenharmony_ci	ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
66062306a36Sopenharmony_ci	ctxPtr->dictBase	= ctxPtr->base;
66162306a36Sopenharmony_ci	ctxPtr->base = newBlock - ctxPtr->dictLimit;
66262306a36Sopenharmony_ci	ctxPtr->end	= newBlock;
66362306a36Sopenharmony_ci	/* match referencing will resume from there */
66462306a36Sopenharmony_ci	ctxPtr->nextToUpdate = ctxPtr->dictLimit;
66562306a36Sopenharmony_ci}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_cistatic int LZ4_compressHC_continue_generic(
66862306a36Sopenharmony_ci	LZ4_streamHC_t *LZ4_streamHCPtr,
66962306a36Sopenharmony_ci	const char *source,
67062306a36Sopenharmony_ci	char *dest,
67162306a36Sopenharmony_ci	int inputSize,
67262306a36Sopenharmony_ci	int maxOutputSize,
67362306a36Sopenharmony_ci	limitedOutput_directive limit)
67462306a36Sopenharmony_ci{
67562306a36Sopenharmony_ci	LZ4HC_CCtx_internal *ctxPtr = &LZ4_streamHCPtr->internal_donotuse;
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	/* auto - init if forgotten */
67862306a36Sopenharmony_ci	if (ctxPtr->base == NULL)
67962306a36Sopenharmony_ci		LZ4HC_init(ctxPtr, (const BYTE *) source);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* Check overflow */
68262306a36Sopenharmony_ci	if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 * GB) {
68362306a36Sopenharmony_ci		size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base)
68462306a36Sopenharmony_ci			- ctxPtr->dictLimit;
68562306a36Sopenharmony_ci		if (dictSize > 64 * KB)
68662306a36Sopenharmony_ci			dictSize = 64 * KB;
68762306a36Sopenharmony_ci		LZ4_loadDictHC(LZ4_streamHCPtr,
68862306a36Sopenharmony_ci			(const char *)(ctxPtr->end) - dictSize, (int)dictSize);
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	/* Check if blocks follow each other */
69262306a36Sopenharmony_ci	if ((const BYTE *)source != ctxPtr->end)
69362306a36Sopenharmony_ci		LZ4HC_setExternalDict(ctxPtr, (const BYTE *)source);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	/* Check overlapping input/dictionary space */
69662306a36Sopenharmony_ci	{
69762306a36Sopenharmony_ci		const BYTE *sourceEnd = (const BYTE *) source + inputSize;
69862306a36Sopenharmony_ci		const BYTE * const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
69962306a36Sopenharmony_ci		const BYTE * const dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci		if ((sourceEnd > dictBegin)
70262306a36Sopenharmony_ci			&& ((const BYTE *)source < dictEnd)) {
70362306a36Sopenharmony_ci			if (sourceEnd > dictEnd)
70462306a36Sopenharmony_ci				sourceEnd = dictEnd;
70562306a36Sopenharmony_ci			ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci			if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4)
70862306a36Sopenharmony_ci				ctxPtr->lowLimit = ctxPtr->dictLimit;
70962306a36Sopenharmony_ci		}
71062306a36Sopenharmony_ci	}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	return LZ4HC_compress_generic(ctxPtr, source, dest,
71362306a36Sopenharmony_ci		inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ciint LZ4_compress_HC_continue(
71762306a36Sopenharmony_ci	LZ4_streamHC_t *LZ4_streamHCPtr,
71862306a36Sopenharmony_ci	const char *source,
71962306a36Sopenharmony_ci	char *dest,
72062306a36Sopenharmony_ci	int inputSize,
72162306a36Sopenharmony_ci	int maxOutputSize)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	if (maxOutputSize < LZ4_compressBound(inputSize))
72462306a36Sopenharmony_ci		return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,
72562306a36Sopenharmony_ci			source, dest, inputSize, maxOutputSize, limitedOutput);
72662306a36Sopenharmony_ci	else
72762306a36Sopenharmony_ci		return LZ4_compressHC_continue_generic(LZ4_streamHCPtr,
72862306a36Sopenharmony_ci			source, dest, inputSize, maxOutputSize, noLimit);
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_compress_HC_continue);
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci/* dictionary saving */
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ciint LZ4_saveDictHC(
73562306a36Sopenharmony_ci	LZ4_streamHC_t *LZ4_streamHCPtr,
73662306a36Sopenharmony_ci	char *safeBuffer,
73762306a36Sopenharmony_ci	int dictSize)
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	LZ4HC_CCtx_internal *const streamPtr = &LZ4_streamHCPtr->internal_donotuse;
74062306a36Sopenharmony_ci	int const prefixSize = (int)(streamPtr->end
74162306a36Sopenharmony_ci		- (streamPtr->base + streamPtr->dictLimit));
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (dictSize > 64 * KB)
74462306a36Sopenharmony_ci		dictSize = 64 * KB;
74562306a36Sopenharmony_ci	if (dictSize < 4)
74662306a36Sopenharmony_ci		dictSize = 0;
74762306a36Sopenharmony_ci	if (dictSize > prefixSize)
74862306a36Sopenharmony_ci		dictSize = prefixSize;
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_ci	memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	{
75362306a36Sopenharmony_ci		U32 const endIndex = (U32)(streamPtr->end - streamPtr->base);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci		streamPtr->end = (const BYTE *)safeBuffer + dictSize;
75662306a36Sopenharmony_ci		streamPtr->base = streamPtr->end - endIndex;
75762306a36Sopenharmony_ci		streamPtr->dictLimit = endIndex - dictSize;
75862306a36Sopenharmony_ci		streamPtr->lowLimit = endIndex - dictSize;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci		if (streamPtr->nextToUpdate < streamPtr->dictLimit)
76162306a36Sopenharmony_ci			streamPtr->nextToUpdate = streamPtr->dictLimit;
76262306a36Sopenharmony_ci	}
76362306a36Sopenharmony_ci	return dictSize;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ciEXPORT_SYMBOL(LZ4_saveDictHC);
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
76862306a36Sopenharmony_ciMODULE_DESCRIPTION("LZ4 HC compressor");
769