cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lz4_compress.c (23384B)


      1/*
      2 * LZ4 - Fast LZ compression algorithm
      3 * Copyright (C) 2011 - 2016, Yann Collet.
      4 * BSD 2 - Clause License (http://www.opensource.org/licenses/bsd - license.php)
      5 * Redistribution and use in source and binary forms, with or without
      6 * modification, are permitted provided that the following conditions are
      7 * met:
      8 *	* Redistributions of source code must retain the above copyright
      9 *	  notice, this list of conditions and the following disclaimer.
     10 *	* Redistributions in binary form must reproduce the above
     11 * copyright notice, this list of conditions and the following disclaimer
     12 * in the documentation and/or other materials provided with the
     13 * distribution.
     14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25 * You can contact the author at :
     26 *	- LZ4 homepage : http://www.lz4.org
     27 *	- LZ4 source repository : https://github.com/lz4/lz4
     28 *
     29 *	Changed for kernel usage by:
     30 *	Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
     31 */
     32
     33/*-************************************
     34 *	Dependencies
     35 **************************************/
     36#include <linux/lz4.h>
     37#include "lz4defs.h"
     38#include <linux/module.h>
     39#include <linux/kernel.h>
     40#include <asm/unaligned.h>
     41
     42static const int LZ4_minLength = (MFLIMIT + 1);
     43static const int LZ4_64Klimit = ((64 * KB) + (MFLIMIT - 1));
     44
     45/*-******************************
     46 *	Compression functions
     47 ********************************/
     48static FORCE_INLINE U32 LZ4_hash4(
     49	U32 sequence,
     50	tableType_t const tableType)
     51{
     52	if (tableType == byU16)
     53		return ((sequence * 2654435761U)
     54			>> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
     55	else
     56		return ((sequence * 2654435761U)
     57			>> ((MINMATCH * 8) - LZ4_HASHLOG));
     58}
     59
     60static FORCE_INLINE U32 LZ4_hash5(
     61	U64 sequence,
     62	tableType_t const tableType)
     63{
     64	const U32 hashLog = (tableType == byU16)
     65		? LZ4_HASHLOG + 1
     66		: LZ4_HASHLOG;
     67
     68#if LZ4_LITTLE_ENDIAN
     69	static const U64 prime5bytes = 889523592379ULL;
     70
     71	return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));
     72#else
     73	static const U64 prime8bytes = 11400714785074694791ULL;
     74
     75	return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));
     76#endif
     77}
     78
     79static FORCE_INLINE U32 LZ4_hashPosition(
     80	const void *p,
     81	tableType_t const tableType)
     82{
     83#if LZ4_ARCH64
     84	if (tableType == byU32)
     85		return LZ4_hash5(LZ4_read_ARCH(p), tableType);
     86#endif
     87
     88	return LZ4_hash4(LZ4_read32(p), tableType);
     89}
     90
     91static void LZ4_putPositionOnHash(
     92	const BYTE *p,
     93	U32 h,
     94	void *tableBase,
     95	tableType_t const tableType,
     96	const BYTE *srcBase)
     97{
     98	switch (tableType) {
     99	case byPtr:
    100	{
    101		const BYTE **hashTable = (const BYTE **)tableBase;
    102
    103		hashTable[h] = p;
    104		return;
    105	}
    106	case byU32:
    107	{
    108		U32 *hashTable = (U32 *) tableBase;
    109
    110		hashTable[h] = (U32)(p - srcBase);
    111		return;
    112	}
    113	case byU16:
    114	{
    115		U16 *hashTable = (U16 *) tableBase;
    116
    117		hashTable[h] = (U16)(p - srcBase);
    118		return;
    119	}
    120	}
    121}
    122
    123static FORCE_INLINE void LZ4_putPosition(
    124	const BYTE *p,
    125	void *tableBase,
    126	tableType_t tableType,
    127	const BYTE *srcBase)
    128{
    129	U32 const h = LZ4_hashPosition(p, tableType);
    130
    131	LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
    132}
    133
    134static const BYTE *LZ4_getPositionOnHash(
    135	U32 h,
    136	void *tableBase,
    137	tableType_t tableType,
    138	const BYTE *srcBase)
    139{
    140	if (tableType == byPtr) {
    141		const BYTE **hashTable = (const BYTE **) tableBase;
    142
    143		return hashTable[h];
    144	}
    145
    146	if (tableType == byU32) {
    147		const U32 * const hashTable = (U32 *) tableBase;
    148
    149		return hashTable[h] + srcBase;
    150	}
    151
    152	{
    153		/* default, to ensure a return */
    154		const U16 * const hashTable = (U16 *) tableBase;
    155
    156		return hashTable[h] + srcBase;
    157	}
    158}
    159
    160static FORCE_INLINE const BYTE *LZ4_getPosition(
    161	const BYTE *p,
    162	void *tableBase,
    163	tableType_t tableType,
    164	const BYTE *srcBase)
    165{
    166	U32 const h = LZ4_hashPosition(p, tableType);
    167
    168	return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
    169}
    170
    171
    172/*
    173 * LZ4_compress_generic() :
    174 * inlined, to ensure branches are decided at compilation time
    175 */
    176static FORCE_INLINE int LZ4_compress_generic(
    177	LZ4_stream_t_internal * const dictPtr,
    178	const char * const source,
    179	char * const dest,
    180	const int inputSize,
    181	const int maxOutputSize,
    182	const limitedOutput_directive outputLimited,
    183	const tableType_t tableType,
    184	const dict_directive dict,
    185	const dictIssue_directive dictIssue,
    186	const U32 acceleration)
    187{
    188	const BYTE *ip = (const BYTE *) source;
    189	const BYTE *base;
    190	const BYTE *lowLimit;
    191	const BYTE * const lowRefLimit = ip - dictPtr->dictSize;
    192	const BYTE * const dictionary = dictPtr->dictionary;
    193	const BYTE * const dictEnd = dictionary + dictPtr->dictSize;
    194	const size_t dictDelta = dictEnd - (const BYTE *)source;
    195	const BYTE *anchor = (const BYTE *) source;
    196	const BYTE * const iend = ip + inputSize;
    197	const BYTE * const mflimit = iend - MFLIMIT;
    198	const BYTE * const matchlimit = iend - LASTLITERALS;
    199
    200	BYTE *op = (BYTE *) dest;
    201	BYTE * const olimit = op + maxOutputSize;
    202
    203	U32 forwardH;
    204	size_t refDelta = 0;
    205
    206	/* Init conditions */
    207	if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) {
    208		/* Unsupported inputSize, too large (or negative) */
    209		return 0;
    210	}
    211
    212	switch (dict) {
    213	case noDict:
    214	default:
    215		base = (const BYTE *)source;
    216		lowLimit = (const BYTE *)source;
    217		break;
    218	case withPrefix64k:
    219		base = (const BYTE *)source - dictPtr->currentOffset;
    220		lowLimit = (const BYTE *)source - dictPtr->dictSize;
    221		break;
    222	case usingExtDict:
    223		base = (const BYTE *)source - dictPtr->currentOffset;
    224		lowLimit = (const BYTE *)source;
    225		break;
    226	}
    227
    228	if ((tableType == byU16)
    229		&& (inputSize >= LZ4_64Klimit)) {
    230		/* Size too large (not within 64K limit) */
    231		return 0;
    232	}
    233
    234	if (inputSize < LZ4_minLength) {
    235		/* Input too small, no compression (all literals) */
    236		goto _last_literals;
    237	}
    238
    239	/* First Byte */
    240	LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
    241	ip++;
    242	forwardH = LZ4_hashPosition(ip, tableType);
    243
    244	/* Main Loop */
    245	for ( ; ; ) {
    246		const BYTE *match;
    247		BYTE *token;
    248
    249		/* Find a match */
    250		{
    251			const BYTE *forwardIp = ip;
    252			unsigned int step = 1;
    253			unsigned int searchMatchNb = acceleration << LZ4_SKIPTRIGGER;
    254
    255			do {
    256				U32 const h = forwardH;
    257
    258				ip = forwardIp;
    259				forwardIp += step;
    260				step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
    261
    262				if (unlikely(forwardIp > mflimit))
    263					goto _last_literals;
    264
    265				match = LZ4_getPositionOnHash(h,
    266					dictPtr->hashTable,
    267					tableType, base);
    268
    269				if (dict == usingExtDict) {
    270					if (match < (const BYTE *)source) {
    271						refDelta = dictDelta;
    272						lowLimit = dictionary;
    273					} else {
    274						refDelta = 0;
    275						lowLimit = (const BYTE *)source;
    276				}	 }
    277
    278				forwardH = LZ4_hashPosition(forwardIp,
    279					tableType);
    280
    281				LZ4_putPositionOnHash(ip, h, dictPtr->hashTable,
    282					tableType, base);
    283			} while (((dictIssue == dictSmall)
    284					? (match < lowRefLimit)
    285					: 0)
    286				|| ((tableType == byU16)
    287					? 0
    288					: (match + MAX_DISTANCE < ip))
    289				|| (LZ4_read32(match + refDelta)
    290					!= LZ4_read32(ip)));
    291		}
    292
    293		/* Catch up */
    294		while (((ip > anchor) & (match + refDelta > lowLimit))
    295				&& (unlikely(ip[-1] == match[refDelta - 1]))) {
    296			ip--;
    297			match--;
    298		}
    299
    300		/* Encode Literals */
    301		{
    302			unsigned const int litLength = (unsigned int)(ip - anchor);
    303
    304			token = op++;
    305
    306			if ((outputLimited) &&
    307				/* Check output buffer overflow */
    308				(unlikely(op + litLength +
    309					(2 + 1 + LASTLITERALS) +
    310					(litLength / 255) > olimit)))
    311				return 0;
    312
    313			if (litLength >= RUN_MASK) {
    314				int len = (int)litLength - RUN_MASK;
    315
    316				*token = (RUN_MASK << ML_BITS);
    317
    318				for (; len >= 255; len -= 255)
    319					*op++ = 255;
    320				*op++ = (BYTE)len;
    321			} else
    322				*token = (BYTE)(litLength << ML_BITS);
    323
    324			/* Copy Literals */
    325			LZ4_wildCopy(op, anchor, op + litLength);
    326			op += litLength;
    327		}
    328
    329_next_match:
    330		/* Encode Offset */
    331		LZ4_writeLE16(op, (U16)(ip - match));
    332		op += 2;
    333
    334		/* Encode MatchLength */
    335		{
    336			unsigned int matchCode;
    337
    338			if ((dict == usingExtDict)
    339				&& (lowLimit == dictionary)) {
    340				const BYTE *limit;
    341
    342				match += refDelta;
    343				limit = ip + (dictEnd - match);
    344
    345				if (limit > matchlimit)
    346					limit = matchlimit;
    347
    348				matchCode = LZ4_count(ip + MINMATCH,
    349					match + MINMATCH, limit);
    350
    351				ip += MINMATCH + matchCode;
    352
    353				if (ip == limit) {
    354					unsigned const int more = LZ4_count(ip,
    355						(const BYTE *)source,
    356						matchlimit);
    357
    358					matchCode += more;
    359					ip += more;
    360				}
    361			} else {
    362				matchCode = LZ4_count(ip + MINMATCH,
    363					match + MINMATCH, matchlimit);
    364				ip += MINMATCH + matchCode;
    365			}
    366
    367			if (outputLimited &&
    368				/* Check output buffer overflow */
    369				(unlikely(op +
    370					(1 + LASTLITERALS) +
    371					(matchCode >> 8) > olimit)))
    372				return 0;
    373
    374			if (matchCode >= ML_MASK) {
    375				*token += ML_MASK;
    376				matchCode -= ML_MASK;
    377				LZ4_write32(op, 0xFFFFFFFF);
    378
    379				while (matchCode >= 4 * 255) {
    380					op += 4;
    381					LZ4_write32(op, 0xFFFFFFFF);
    382					matchCode -= 4 * 255;
    383				}
    384
    385				op += matchCode / 255;
    386				*op++ = (BYTE)(matchCode % 255);
    387			} else
    388				*token += (BYTE)(matchCode);
    389		}
    390
    391		anchor = ip;
    392
    393		/* Test end of chunk */
    394		if (ip > mflimit)
    395			break;
    396
    397		/* Fill table */
    398		LZ4_putPosition(ip - 2, dictPtr->hashTable, tableType, base);
    399
    400		/* Test next position */
    401		match = LZ4_getPosition(ip, dictPtr->hashTable,
    402			tableType, base);
    403
    404		if (dict == usingExtDict) {
    405			if (match < (const BYTE *)source) {
    406				refDelta = dictDelta;
    407				lowLimit = dictionary;
    408			} else {
    409				refDelta = 0;
    410				lowLimit = (const BYTE *)source;
    411			}
    412		}
    413
    414		LZ4_putPosition(ip, dictPtr->hashTable, tableType, base);
    415
    416		if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1)
    417			&& (match + MAX_DISTANCE >= ip)
    418			&& (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
    419			token = op++;
    420			*token = 0;
    421			goto _next_match;
    422		}
    423
    424		/* Prepare next loop */
    425		forwardH = LZ4_hashPosition(++ip, tableType);
    426	}
    427
    428_last_literals:
    429	/* Encode Last Literals */
    430	{
    431		size_t const lastRun = (size_t)(iend - anchor);
    432
    433		if ((outputLimited) &&
    434			/* Check output buffer overflow */
    435			((op - (BYTE *)dest) + lastRun + 1 +
    436			((lastRun + 255 - RUN_MASK) / 255) > (U32)maxOutputSize))
    437			return 0;
    438
    439		if (lastRun >= RUN_MASK) {
    440			size_t accumulator = lastRun - RUN_MASK;
    441			*op++ = RUN_MASK << ML_BITS;
    442			for (; accumulator >= 255; accumulator -= 255)
    443				*op++ = 255;
    444			*op++ = (BYTE) accumulator;
    445		} else {
    446			*op++ = (BYTE)(lastRun << ML_BITS);
    447		}
    448
    449		LZ4_memcpy(op, anchor, lastRun);
    450
    451		op += lastRun;
    452	}
    453
    454	/* End */
    455	return (int) (((char *)op) - dest);
    456}
    457
    458static int LZ4_compress_fast_extState(
    459	void *state,
    460	const char *source,
    461	char *dest,
    462	int inputSize,
    463	int maxOutputSize,
    464	int acceleration)
    465{
    466	LZ4_stream_t_internal *ctx = &((LZ4_stream_t *)state)->internal_donotuse;
    467#if LZ4_ARCH64
    468	const tableType_t tableType = byU32;
    469#else
    470	const tableType_t tableType = byPtr;
    471#endif
    472
    473	LZ4_resetStream((LZ4_stream_t *)state);
    474
    475	if (acceleration < 1)
    476		acceleration = LZ4_ACCELERATION_DEFAULT;
    477
    478	if (maxOutputSize >= LZ4_COMPRESSBOUND(inputSize)) {
    479		if (inputSize < LZ4_64Klimit)
    480			return LZ4_compress_generic(ctx, source,
    481				dest, inputSize, 0,
    482				noLimit, byU16, noDict,
    483				noDictIssue, acceleration);
    484		else
    485			return LZ4_compress_generic(ctx, source,
    486				dest, inputSize, 0,
    487				noLimit, tableType, noDict,
    488				noDictIssue, acceleration);
    489	} else {
    490		if (inputSize < LZ4_64Klimit)
    491			return LZ4_compress_generic(ctx, source,
    492				dest, inputSize,
    493				maxOutputSize, limitedOutput, byU16, noDict,
    494				noDictIssue, acceleration);
    495		else
    496			return LZ4_compress_generic(ctx, source,
    497				dest, inputSize,
    498				maxOutputSize, limitedOutput, tableType, noDict,
    499				noDictIssue, acceleration);
    500	}
    501}
    502
    503int LZ4_compress_fast(const char *source, char *dest, int inputSize,
    504	int maxOutputSize, int acceleration, void *wrkmem)
    505{
    506	return LZ4_compress_fast_extState(wrkmem, source, dest, inputSize,
    507		maxOutputSize, acceleration);
    508}
    509EXPORT_SYMBOL(LZ4_compress_fast);
    510
    511int LZ4_compress_default(const char *source, char *dest, int inputSize,
    512	int maxOutputSize, void *wrkmem)
    513{
    514	return LZ4_compress_fast(source, dest, inputSize,
    515		maxOutputSize, LZ4_ACCELERATION_DEFAULT, wrkmem);
    516}
    517EXPORT_SYMBOL(LZ4_compress_default);
    518
    519/*-******************************
    520 *	*_destSize() variant
    521 ********************************/
    522static int LZ4_compress_destSize_generic(
    523	LZ4_stream_t_internal * const ctx,
    524	const char * const src,
    525	char * const dst,
    526	int * const srcSizePtr,
    527	const int targetDstSize,
    528	const tableType_t tableType)
    529{
    530	const BYTE *ip = (const BYTE *) src;
    531	const BYTE *base = (const BYTE *) src;
    532	const BYTE *lowLimit = (const BYTE *) src;
    533	const BYTE *anchor = ip;
    534	const BYTE * const iend = ip + *srcSizePtr;
    535	const BYTE * const mflimit = iend - MFLIMIT;
    536	const BYTE * const matchlimit = iend - LASTLITERALS;
    537
    538	BYTE *op = (BYTE *) dst;
    539	BYTE * const oend = op + targetDstSize;
    540	BYTE * const oMaxLit = op + targetDstSize - 2 /* offset */
    541		- 8 /* because 8 + MINMATCH == MFLIMIT */ - 1 /* token */;
    542	BYTE * const oMaxMatch = op + targetDstSize
    543		- (LASTLITERALS + 1 /* token */);
    544	BYTE * const oMaxSeq = oMaxLit - 1 /* token */;
    545
    546	U32 forwardH;
    547
    548	/* Init conditions */
    549	/* Impossible to store anything */
    550	if (targetDstSize < 1)
    551		return 0;
    552	/* Unsupported input size, too large (or negative) */
    553	if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE)
    554		return 0;
    555	/* Size too large (not within 64K limit) */
    556	if ((tableType == byU16) && (*srcSizePtr >= LZ4_64Klimit))
    557		return 0;
    558	/* Input too small, no compression (all literals) */
    559	if (*srcSizePtr < LZ4_minLength)
    560		goto _last_literals;
    561
    562	/* First Byte */
    563	*srcSizePtr = 0;
    564	LZ4_putPosition(ip, ctx->hashTable, tableType, base);
    565	ip++; forwardH = LZ4_hashPosition(ip, tableType);
    566
    567	/* Main Loop */
    568	for ( ; ; ) {
    569		const BYTE *match;
    570		BYTE *token;
    571
    572		/* Find a match */
    573		{
    574			const BYTE *forwardIp = ip;
    575			unsigned int step = 1;
    576			unsigned int searchMatchNb = 1 << LZ4_SKIPTRIGGER;
    577
    578			do {
    579				U32 h = forwardH;
    580
    581				ip = forwardIp;
    582				forwardIp += step;
    583				step = (searchMatchNb++ >> LZ4_SKIPTRIGGER);
    584
    585				if (unlikely(forwardIp > mflimit))
    586					goto _last_literals;
    587
    588				match = LZ4_getPositionOnHash(h, ctx->hashTable,
    589					tableType, base);
    590				forwardH = LZ4_hashPosition(forwardIp,
    591					tableType);
    592				LZ4_putPositionOnHash(ip, h,
    593					ctx->hashTable, tableType,
    594					base);
    595
    596			} while (((tableType == byU16)
    597				? 0
    598				: (match + MAX_DISTANCE < ip))
    599				|| (LZ4_read32(match) != LZ4_read32(ip)));
    600		}
    601
    602		/* Catch up */
    603		while ((ip > anchor)
    604			&& (match > lowLimit)
    605			&& (unlikely(ip[-1] == match[-1]))) {
    606			ip--;
    607			match--;
    608		}
    609
    610		/* Encode Literal length */
    611		{
    612			unsigned int litLength = (unsigned int)(ip - anchor);
    613
    614			token = op++;
    615			if (op + ((litLength + 240) / 255)
    616				+ litLength > oMaxLit) {
    617				/* Not enough space for a last match */
    618				op--;
    619				goto _last_literals;
    620			}
    621			if (litLength >= RUN_MASK) {
    622				unsigned int len = litLength - RUN_MASK;
    623				*token = (RUN_MASK<<ML_BITS);
    624				for (; len >= 255; len -= 255)
    625					*op++ = 255;
    626				*op++ = (BYTE)len;
    627			} else
    628				*token = (BYTE)(litLength << ML_BITS);
    629
    630			/* Copy Literals */
    631			LZ4_wildCopy(op, anchor, op + litLength);
    632			op += litLength;
    633		}
    634
    635_next_match:
    636		/* Encode Offset */
    637		LZ4_writeLE16(op, (U16)(ip - match)); op += 2;
    638
    639		/* Encode MatchLength */
    640		{
    641			size_t matchLength = LZ4_count(ip + MINMATCH,
    642			match + MINMATCH, matchlimit);
    643
    644			if (op + ((matchLength + 240)/255) > oMaxMatch) {
    645				/* Match description too long : reduce it */
    646				matchLength = (15 - 1) + (oMaxMatch - op) * 255;
    647			}
    648			ip += MINMATCH + matchLength;
    649
    650			if (matchLength >= ML_MASK) {
    651				*token += ML_MASK;
    652				matchLength -= ML_MASK;
    653				while (matchLength >= 255) {
    654					matchLength -= 255;
    655					*op++ = 255;
    656				}
    657				*op++ = (BYTE)matchLength;
    658			} else
    659				*token += (BYTE)(matchLength);
    660		}
    661
    662		anchor = ip;
    663
    664		/* Test end of block */
    665		if (ip > mflimit)
    666			break;
    667		if (op > oMaxSeq)
    668			break;
    669
    670		/* Fill table */
    671		LZ4_putPosition(ip - 2, ctx->hashTable, tableType, base);
    672
    673		/* Test next position */
    674		match = LZ4_getPosition(ip, ctx->hashTable, tableType, base);
    675		LZ4_putPosition(ip, ctx->hashTable, tableType, base);
    676
    677		if ((match + MAX_DISTANCE >= ip)
    678			&& (LZ4_read32(match) == LZ4_read32(ip))) {
    679			token = op++; *token = 0;
    680			goto _next_match;
    681		}
    682
    683		/* Prepare next loop */
    684		forwardH = LZ4_hashPosition(++ip, tableType);
    685	}
    686
    687_last_literals:
    688	/* Encode Last Literals */
    689	{
    690		size_t lastRunSize = (size_t)(iend - anchor);
    691
    692		if (op + 1 /* token */
    693			+ ((lastRunSize + 240) / 255) /* litLength */
    694			+ lastRunSize /* literals */ > oend) {
    695			/* adapt lastRunSize to fill 'dst' */
    696			lastRunSize	= (oend - op) - 1;
    697			lastRunSize -= (lastRunSize + 240) / 255;
    698		}
    699		ip = anchor + lastRunSize;
    700
    701		if (lastRunSize >= RUN_MASK) {
    702			size_t accumulator = lastRunSize - RUN_MASK;
    703
    704			*op++ = RUN_MASK << ML_BITS;
    705			for (; accumulator >= 255; accumulator -= 255)
    706				*op++ = 255;
    707			*op++ = (BYTE) accumulator;
    708		} else {
    709			*op++ = (BYTE)(lastRunSize<<ML_BITS);
    710		}
    711		LZ4_memcpy(op, anchor, lastRunSize);
    712		op += lastRunSize;
    713	}
    714
    715	/* End */
    716	*srcSizePtr = (int) (((const char *)ip) - src);
    717	return (int) (((char *)op) - dst);
    718}
    719
    720static int LZ4_compress_destSize_extState(
    721	LZ4_stream_t *state,
    722	const char *src,
    723	char *dst,
    724	int *srcSizePtr,
    725	int targetDstSize)
    726{
    727#if LZ4_ARCH64
    728	const tableType_t tableType = byU32;
    729#else
    730	const tableType_t tableType = byPtr;
    731#endif
    732
    733	LZ4_resetStream(state);
    734
    735	if (targetDstSize >= LZ4_COMPRESSBOUND(*srcSizePtr)) {
    736		/* compression success is guaranteed */
    737		return LZ4_compress_fast_extState(
    738			state, src, dst, *srcSizePtr,
    739			targetDstSize, 1);
    740	} else {
    741		if (*srcSizePtr < LZ4_64Klimit)
    742			return LZ4_compress_destSize_generic(
    743				&state->internal_donotuse,
    744				src, dst, srcSizePtr,
    745				targetDstSize, byU16);
    746		else
    747			return LZ4_compress_destSize_generic(
    748				&state->internal_donotuse,
    749				src, dst, srcSizePtr,
    750				targetDstSize, tableType);
    751	}
    752}
    753
    754
    755int LZ4_compress_destSize(
    756	const char *src,
    757	char *dst,
    758	int *srcSizePtr,
    759	int targetDstSize,
    760	void *wrkmem)
    761{
    762	return LZ4_compress_destSize_extState(wrkmem, src, dst, srcSizePtr,
    763		targetDstSize);
    764}
    765EXPORT_SYMBOL(LZ4_compress_destSize);
    766
    767/*-******************************
    768 *	Streaming functions
    769 ********************************/
    770void LZ4_resetStream(LZ4_stream_t *LZ4_stream)
    771{
    772	memset(LZ4_stream, 0, sizeof(LZ4_stream_t));
    773}
    774
    775int LZ4_loadDict(LZ4_stream_t *LZ4_dict,
    776	const char *dictionary, int dictSize)
    777{
    778	LZ4_stream_t_internal *dict = &LZ4_dict->internal_donotuse;
    779	const BYTE *p = (const BYTE *)dictionary;
    780	const BYTE * const dictEnd = p + dictSize;
    781	const BYTE *base;
    782
    783	if ((dict->initCheck)
    784		|| (dict->currentOffset > 1 * GB)) {
    785		/* Uninitialized structure, or reuse overflow */
    786		LZ4_resetStream(LZ4_dict);
    787	}
    788
    789	if (dictSize < (int)HASH_UNIT) {
    790		dict->dictionary = NULL;
    791		dict->dictSize = 0;
    792		return 0;
    793	}
    794
    795	if ((dictEnd - p) > 64 * KB)
    796		p = dictEnd - 64 * KB;
    797	dict->currentOffset += 64 * KB;
    798	base = p - dict->currentOffset;
    799	dict->dictionary = p;
    800	dict->dictSize = (U32)(dictEnd - p);
    801	dict->currentOffset += dict->dictSize;
    802
    803	while (p <= dictEnd - HASH_UNIT) {
    804		LZ4_putPosition(p, dict->hashTable, byU32, base);
    805		p += 3;
    806	}
    807
    808	return dict->dictSize;
    809}
    810EXPORT_SYMBOL(LZ4_loadDict);
    811
    812static void LZ4_renormDictT(LZ4_stream_t_internal *LZ4_dict,
    813	const BYTE *src)
    814{
    815	if ((LZ4_dict->currentOffset > 0x80000000) ||
    816		((uptrval)LZ4_dict->currentOffset > (uptrval)src)) {
    817		/* address space overflow */
    818		/* rescale hash table */
    819		U32 const delta = LZ4_dict->currentOffset - 64 * KB;
    820		const BYTE *dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
    821		int i;
    822
    823		for (i = 0; i < LZ4_HASH_SIZE_U32; i++) {
    824			if (LZ4_dict->hashTable[i] < delta)
    825				LZ4_dict->hashTable[i] = 0;
    826			else
    827				LZ4_dict->hashTable[i] -= delta;
    828		}
    829		LZ4_dict->currentOffset = 64 * KB;
    830		if (LZ4_dict->dictSize > 64 * KB)
    831			LZ4_dict->dictSize = 64 * KB;
    832		LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
    833	}
    834}
    835
    836int LZ4_saveDict(LZ4_stream_t *LZ4_dict, char *safeBuffer, int dictSize)
    837{
    838	LZ4_stream_t_internal * const dict = &LZ4_dict->internal_donotuse;
    839	const BYTE * const previousDictEnd = dict->dictionary + dict->dictSize;
    840
    841	if ((U32)dictSize > 64 * KB) {
    842		/* useless to define a dictionary > 64 * KB */
    843		dictSize = 64 * KB;
    844	}
    845	if ((U32)dictSize > dict->dictSize)
    846		dictSize = dict->dictSize;
    847
    848	memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
    849
    850	dict->dictionary = (const BYTE *)safeBuffer;
    851	dict->dictSize = (U32)dictSize;
    852
    853	return dictSize;
    854}
    855EXPORT_SYMBOL(LZ4_saveDict);
    856
    857int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source,
    858	char *dest, int inputSize, int maxOutputSize, int acceleration)
    859{
    860	LZ4_stream_t_internal *streamPtr = &LZ4_stream->internal_donotuse;
    861	const BYTE * const dictEnd = streamPtr->dictionary
    862		+ streamPtr->dictSize;
    863
    864	const BYTE *smallest = (const BYTE *) source;
    865
    866	if (streamPtr->initCheck) {
    867		/* Uninitialized structure detected */
    868		return 0;
    869	}
    870
    871	if ((streamPtr->dictSize > 0) && (smallest > dictEnd))
    872		smallest = dictEnd;
    873
    874	LZ4_renormDictT(streamPtr, smallest);
    875
    876	if (acceleration < 1)
    877		acceleration = LZ4_ACCELERATION_DEFAULT;
    878
    879	/* Check overlapping input/dictionary space */
    880	{
    881		const BYTE *sourceEnd = (const BYTE *) source + inputSize;
    882
    883		if ((sourceEnd > streamPtr->dictionary)
    884			&& (sourceEnd < dictEnd)) {
    885			streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
    886			if (streamPtr->dictSize > 64 * KB)
    887				streamPtr->dictSize = 64 * KB;
    888			if (streamPtr->dictSize < 4)
    889				streamPtr->dictSize = 0;
    890			streamPtr->dictionary = dictEnd - streamPtr->dictSize;
    891		}
    892	}
    893
    894	/* prefix mode : source data follows dictionary */
    895	if (dictEnd == (const BYTE *)source) {
    896		int result;
    897
    898		if ((streamPtr->dictSize < 64 * KB) &&
    899			(streamPtr->dictSize < streamPtr->currentOffset)) {
    900			result = LZ4_compress_generic(
    901				streamPtr, source, dest, inputSize,
    902				maxOutputSize, limitedOutput, byU32,
    903				withPrefix64k, dictSmall, acceleration);
    904		} else {
    905			result = LZ4_compress_generic(
    906				streamPtr, source, dest, inputSize,
    907				maxOutputSize, limitedOutput, byU32,
    908				withPrefix64k, noDictIssue, acceleration);
    909		}
    910		streamPtr->dictSize += (U32)inputSize;
    911		streamPtr->currentOffset += (U32)inputSize;
    912		return result;
    913	}
    914
    915	/* external dictionary mode */
    916	{
    917		int result;
    918
    919		if ((streamPtr->dictSize < 64 * KB) &&
    920			(streamPtr->dictSize < streamPtr->currentOffset)) {
    921			result = LZ4_compress_generic(
    922				streamPtr, source, dest, inputSize,
    923				maxOutputSize, limitedOutput, byU32,
    924				usingExtDict, dictSmall, acceleration);
    925		} else {
    926			result = LZ4_compress_generic(
    927				streamPtr, source, dest, inputSize,
    928				maxOutputSize, limitedOutput, byU32,
    929				usingExtDict, noDictIssue, acceleration);
    930		}
    931		streamPtr->dictionary = (const BYTE *)source;
    932		streamPtr->dictSize = (U32)inputSize;
    933		streamPtr->currentOffset += (U32)inputSize;
    934		return result;
    935	}
    936}
    937EXPORT_SYMBOL(LZ4_compress_fast_continue);
    938
    939MODULE_LICENSE("Dual BSD/GPL");
    940MODULE_DESCRIPTION("LZ4 compressor");