xref: /freebsd/sys/contrib/openzfs/module/zfs/lz4.c (revision aebc96831f152a9da5f2c919103d571e80d3fade)
1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * LZ4 - Fast LZ compression algorithm
3eda14cbcSMatt Macy  * Header File
4eda14cbcSMatt Macy  * Copyright (C) 2011-2013, Yann Collet.
5eda14cbcSMatt Macy  * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6eda14cbcSMatt Macy  *
7eda14cbcSMatt Macy  * Redistribution and use in source and binary forms, with or without
8eda14cbcSMatt Macy  * modification, are permitted provided that the following conditions are
9eda14cbcSMatt Macy  * met:
10eda14cbcSMatt Macy  *
11eda14cbcSMatt Macy  *     * Redistributions of source code must retain the above copyright
12eda14cbcSMatt Macy  * notice, this list of conditions and the following disclaimer.
13eda14cbcSMatt Macy  *     * Redistributions in binary form must reproduce the above
14eda14cbcSMatt Macy  * copyright notice, this list of conditions and the following disclaimer
15eda14cbcSMatt Macy  * in the documentation and/or other materials provided with the
16eda14cbcSMatt Macy  * distribution.
17eda14cbcSMatt Macy  *
18eda14cbcSMatt Macy  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19eda14cbcSMatt Macy  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20eda14cbcSMatt Macy  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21eda14cbcSMatt Macy  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22eda14cbcSMatt Macy  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23eda14cbcSMatt Macy  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24eda14cbcSMatt Macy  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25eda14cbcSMatt Macy  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26eda14cbcSMatt Macy  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27eda14cbcSMatt Macy  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28eda14cbcSMatt Macy  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29eda14cbcSMatt Macy  *
30eda14cbcSMatt Macy  * You can contact the author at :
31eda14cbcSMatt Macy  * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
32eda14cbcSMatt Macy  * - LZ4 source repository : http://code.google.com/p/lz4/
33eda14cbcSMatt Macy  */
34eda14cbcSMatt Macy 
35eda14cbcSMatt Macy #include <sys/zfs_context.h>
36eda14cbcSMatt Macy #include <sys/zio_compress.h>
37eda14cbcSMatt Macy 
38eda14cbcSMatt Macy static int real_LZ4_compress(const char *source, char *dest, int isize,
39eda14cbcSMatt Macy     int osize);
40eda14cbcSMatt Macy static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
41eda14cbcSMatt Macy     int isize, int maxOutputSize);
42eda14cbcSMatt Macy static int LZ4_compressCtx(void *ctx, const char *source, char *dest,
43eda14cbcSMatt Macy     int isize, int osize);
44eda14cbcSMatt Macy static int LZ4_compress64kCtx(void *ctx, const char *source, char *dest,
45eda14cbcSMatt Macy     int isize, int osize);
46eda14cbcSMatt Macy 
47*aebc9683SMateusz Guzik static void *lz4_alloc(int flags);
48*aebc9683SMateusz Guzik static void lz4_free(void *ctx);
49eda14cbcSMatt Macy 
50eda14cbcSMatt Macy /*ARGSUSED*/
51eda14cbcSMatt Macy size_t
52eda14cbcSMatt Macy lz4_compress_zfs(void *s_start, void *d_start, size_t s_len,
53eda14cbcSMatt Macy     size_t d_len, int n)
54eda14cbcSMatt Macy {
55eda14cbcSMatt Macy 	uint32_t bufsiz;
56eda14cbcSMatt Macy 	char *dest = d_start;
57eda14cbcSMatt Macy 
58eda14cbcSMatt Macy 	ASSERT(d_len >= sizeof (bufsiz));
59eda14cbcSMatt Macy 
60eda14cbcSMatt Macy 	bufsiz = real_LZ4_compress(s_start, &dest[sizeof (bufsiz)], s_len,
61eda14cbcSMatt Macy 	    d_len - sizeof (bufsiz));
62eda14cbcSMatt Macy 
63eda14cbcSMatt Macy 	/* Signal an error if the compression routine returned zero. */
64eda14cbcSMatt Macy 	if (bufsiz == 0)
65eda14cbcSMatt Macy 		return (s_len);
66eda14cbcSMatt Macy 
67eda14cbcSMatt Macy 	/*
68eda14cbcSMatt Macy 	 * The exact compressed size is needed by the decompression routine,
69eda14cbcSMatt Macy 	 * so it is stored at the start of the buffer. Note that this may be
70eda14cbcSMatt Macy 	 * less than the compressed block size, which is rounded up to a
71eda14cbcSMatt Macy 	 * multiple of 1<<ashift.
72eda14cbcSMatt Macy 	 */
73eda14cbcSMatt Macy 	*(uint32_t *)dest = BE_32(bufsiz);
74eda14cbcSMatt Macy 
75eda14cbcSMatt Macy 	return (bufsiz + sizeof (bufsiz));
76eda14cbcSMatt Macy }
77eda14cbcSMatt Macy 
78eda14cbcSMatt Macy /*ARGSUSED*/
79eda14cbcSMatt Macy int
80eda14cbcSMatt Macy lz4_decompress_zfs(void *s_start, void *d_start, size_t s_len,
81eda14cbcSMatt Macy     size_t d_len, int n)
82eda14cbcSMatt Macy {
83eda14cbcSMatt Macy 	const char *src = s_start;
84eda14cbcSMatt Macy 	uint32_t bufsiz = BE_IN32(src);
85eda14cbcSMatt Macy 
86eda14cbcSMatt Macy 	/* invalid compressed buffer size encoded at start */
87eda14cbcSMatt Macy 	if (bufsiz + sizeof (bufsiz) > s_len)
88eda14cbcSMatt Macy 		return (1);
89eda14cbcSMatt Macy 
90eda14cbcSMatt Macy 	/*
91eda14cbcSMatt Macy 	 * Returns 0 on success (decompression function returned non-negative)
92eda14cbcSMatt Macy 	 * and non-zero on failure (decompression function returned negative).
93eda14cbcSMatt Macy 	 */
94eda14cbcSMatt Macy 	return (LZ4_uncompress_unknownOutputSize(&src[sizeof (bufsiz)],
95eda14cbcSMatt Macy 	    d_start, bufsiz, d_len) < 0);
96eda14cbcSMatt Macy }
97eda14cbcSMatt Macy 
98eda14cbcSMatt Macy /*
99eda14cbcSMatt Macy  * LZ4 API Description:
100eda14cbcSMatt Macy  *
101eda14cbcSMatt Macy  * Simple Functions:
102eda14cbcSMatt Macy  * real_LZ4_compress() :
103eda14cbcSMatt Macy  * 	isize  : is the input size. Max supported value is ~1.9GB
104eda14cbcSMatt Macy  * 	return : the number of bytes written in buffer dest
105eda14cbcSMatt Macy  *		 or 0 if the compression fails (if LZ4_COMPRESSMIN is set).
106eda14cbcSMatt Macy  * 	note : destination buffer must be already allocated.
107eda14cbcSMatt Macy  * 		destination buffer must be sized to handle worst cases
108eda14cbcSMatt Macy  * 		situations (input data not compressible) worst case size
109eda14cbcSMatt Macy  * 		evaluation is provided by function LZ4_compressBound().
110eda14cbcSMatt Macy  *
111eda14cbcSMatt Macy  * real_LZ4_uncompress() :
112eda14cbcSMatt Macy  * 	osize  : is the output size, therefore the original size
113eda14cbcSMatt Macy  * 	return : the number of bytes read in the source buffer.
114eda14cbcSMatt Macy  * 		If the source stream is malformed, the function will stop
115eda14cbcSMatt Macy  * 		decoding and return a negative result, indicating the byte
116eda14cbcSMatt Macy  * 		position of the faulty instruction. This function never
117eda14cbcSMatt Macy  * 		writes beyond dest + osize, and is therefore protected
118eda14cbcSMatt Macy  * 		against malicious data packets.
119eda14cbcSMatt Macy  * 	note : destination buffer must be already allocated
120eda14cbcSMatt Macy  *	note : real_LZ4_uncompress() is not used in ZFS so its code
121eda14cbcSMatt Macy  *	       is not present here.
122eda14cbcSMatt Macy  *
123eda14cbcSMatt Macy  * Advanced Functions
124eda14cbcSMatt Macy  *
125eda14cbcSMatt Macy  * LZ4_compressBound() :
126eda14cbcSMatt Macy  * 	Provides the maximum size that LZ4 may output in a "worst case"
127eda14cbcSMatt Macy  * 	scenario (input data not compressible) primarily useful for memory
128eda14cbcSMatt Macy  * 	allocation of output buffer.
129eda14cbcSMatt Macy  *
130eda14cbcSMatt Macy  * 	isize  : is the input size. Max supported value is ~1.9GB
131eda14cbcSMatt Macy  * 	return : maximum output size in a "worst case" scenario
132eda14cbcSMatt Macy  * 	note : this function is limited by "int" range (2^31-1)
133eda14cbcSMatt Macy  *
134eda14cbcSMatt Macy  * LZ4_uncompress_unknownOutputSize() :
135eda14cbcSMatt Macy  * 	isize  : is the input size, therefore the compressed size
136eda14cbcSMatt Macy  * 	maxOutputSize : is the size of the destination buffer (which must be
137eda14cbcSMatt Macy  * 		already allocated)
138eda14cbcSMatt Macy  * 	return : the number of bytes decoded in the destination buffer
139eda14cbcSMatt Macy  * 		(necessarily <= maxOutputSize). If the source stream is
140eda14cbcSMatt Macy  * 		malformed, the function will stop decoding and return a
141eda14cbcSMatt Macy  * 		negative result, indicating the byte position of the faulty
142eda14cbcSMatt Macy  * 		instruction. This function never writes beyond dest +
143eda14cbcSMatt Macy  * 		maxOutputSize, and is therefore protected against malicious
144eda14cbcSMatt Macy  * 		data packets.
145eda14cbcSMatt Macy  * 	note   : Destination buffer must be already allocated.
146eda14cbcSMatt Macy  *		This version is slightly slower than real_LZ4_uncompress()
147eda14cbcSMatt Macy  *
148eda14cbcSMatt Macy  * LZ4_compressCtx() :
149eda14cbcSMatt Macy  * 	This function explicitly handles the CTX memory structure.
150eda14cbcSMatt Macy  *
151eda14cbcSMatt Macy  * 	ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated
152eda14cbcSMatt Macy  * 	by the caller (either on the stack or using kmem_cache_alloc). Passing
153eda14cbcSMatt Macy  * 	NULL isn't valid.
154eda14cbcSMatt Macy  *
155eda14cbcSMatt Macy  * LZ4_compress64kCtx() :
156eda14cbcSMatt Macy  * 	Same as LZ4_compressCtx(), but specific to small inputs (<64KB).
157eda14cbcSMatt Macy  * 	isize *Must* be <64KB, otherwise the output will be corrupted.
158eda14cbcSMatt Macy  *
159eda14cbcSMatt Macy  * 	ILLUMOS CHANGES: the CTX memory structure must be explicitly allocated
160eda14cbcSMatt Macy  * 	by the caller (either on the stack or using kmem_cache_alloc). Passing
161eda14cbcSMatt Macy  * 	NULL isn't valid.
162eda14cbcSMatt Macy  */
163eda14cbcSMatt Macy 
164eda14cbcSMatt Macy /*
165eda14cbcSMatt Macy  * Tuning parameters
166eda14cbcSMatt Macy  */
167eda14cbcSMatt Macy 
168eda14cbcSMatt Macy /*
169eda14cbcSMatt Macy  * COMPRESSIONLEVEL: Increasing this value improves compression ratio
170eda14cbcSMatt Macy  *	 Lowering this value reduces memory usage. Reduced memory usage
171eda14cbcSMatt Macy  *	typically improves speed, due to cache effect (ex: L1 32KB for Intel,
172eda14cbcSMatt Macy  *	L1 64KB for AMD). Memory usage formula : N->2^(N+2) Bytes
173eda14cbcSMatt Macy  *	(examples : 12 -> 16KB ; 17 -> 512KB)
174eda14cbcSMatt Macy  */
175eda14cbcSMatt Macy #define	COMPRESSIONLEVEL 12
176eda14cbcSMatt Macy 
177eda14cbcSMatt Macy /*
178eda14cbcSMatt Macy  * NOTCOMPRESSIBLE_CONFIRMATION: Decreasing this value will make the
179eda14cbcSMatt Macy  *	algorithm skip faster data segments considered "incompressible".
180eda14cbcSMatt Macy  *	This may decrease compression ratio dramatically, but will be
181eda14cbcSMatt Macy  *	faster on incompressible data. Increasing this value will make
182eda14cbcSMatt Macy  *	the algorithm search more before declaring a segment "incompressible".
183eda14cbcSMatt Macy  *	This could improve compression a bit, but will be slower on
184eda14cbcSMatt Macy  *	incompressible data. The default value (6) is recommended.
185eda14cbcSMatt Macy  */
186eda14cbcSMatt Macy #define	NOTCOMPRESSIBLE_CONFIRMATION 6
187eda14cbcSMatt Macy 
188eda14cbcSMatt Macy /*
189eda14cbcSMatt Macy  * BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE: This will provide a boost to
190eda14cbcSMatt Macy  * performance for big endian cpu, but the resulting compressed stream
191eda14cbcSMatt Macy  * will be incompatible with little-endian CPU. You can set this option
192eda14cbcSMatt Macy  * to 1 in situations where data will stay within closed environment.
193eda14cbcSMatt Macy  * This option is useless on Little_Endian CPU (such as x86).
194eda14cbcSMatt Macy  */
195eda14cbcSMatt Macy /* #define	BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */
196eda14cbcSMatt Macy 
197eda14cbcSMatt Macy /*
198eda14cbcSMatt Macy  * CPU Feature Detection
199eda14cbcSMatt Macy  */
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy /* 32 or 64 bits ? */
202eda14cbcSMatt Macy #if defined(_LP64)
203eda14cbcSMatt Macy #define	LZ4_ARCH64 1
204eda14cbcSMatt Macy #else
205eda14cbcSMatt Macy #define	LZ4_ARCH64 0
206eda14cbcSMatt Macy #endif
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy /*
209eda14cbcSMatt Macy  * Little Endian or Big Endian?
210eda14cbcSMatt Macy  * Note: overwrite the below #define if you know your architecture endianness.
211eda14cbcSMatt Macy  */
212eda14cbcSMatt Macy #if defined(_ZFS_BIG_ENDIAN)
213eda14cbcSMatt Macy #define	LZ4_BIG_ENDIAN 1
214eda14cbcSMatt Macy #else
215eda14cbcSMatt Macy /*
216eda14cbcSMatt Macy  * Little Endian assumed. PDP Endian and other very rare endian format
217eda14cbcSMatt Macy  * are unsupported.
218eda14cbcSMatt Macy  */
219eda14cbcSMatt Macy #undef LZ4_BIG_ENDIAN
220eda14cbcSMatt Macy #endif
221eda14cbcSMatt Macy 
222eda14cbcSMatt Macy /*
223eda14cbcSMatt Macy  * Unaligned memory access is automatically enabled for "common" CPU,
224eda14cbcSMatt Macy  * such as x86. For others CPU, the compiler will be more cautious, and
225eda14cbcSMatt Macy  * insert extra code to ensure aligned access is respected. If you know
226eda14cbcSMatt Macy  * your target CPU supports unaligned memory access, you may want to
227eda14cbcSMatt Macy  * force this option manually to improve performance
228eda14cbcSMatt Macy  */
229eda14cbcSMatt Macy #if defined(__ARM_FEATURE_UNALIGNED)
230eda14cbcSMatt Macy #define	LZ4_FORCE_UNALIGNED_ACCESS 1
231eda14cbcSMatt Macy #endif
232eda14cbcSMatt Macy 
233eda14cbcSMatt Macy /*
234eda14cbcSMatt Macy  * Illumos : we can't use GCC's __builtin_ctz family of builtins in the
235eda14cbcSMatt Macy  * kernel
236eda14cbcSMatt Macy  * Linux : we can use GCC's __builtin_ctz family of builtins in the
237eda14cbcSMatt Macy  * kernel
238eda14cbcSMatt Macy  */
239eda14cbcSMatt Macy #undef	LZ4_FORCE_SW_BITCOUNT
240eda14cbcSMatt Macy #if defined(__sparc)
241eda14cbcSMatt Macy #define	LZ4_FORCE_SW_BITCOUNT
242eda14cbcSMatt Macy #endif
243eda14cbcSMatt Macy 
244eda14cbcSMatt Macy /*
245eda14cbcSMatt Macy  * Compiler Options
246eda14cbcSMatt Macy  */
247eda14cbcSMatt Macy /* Disable restrict */
248eda14cbcSMatt Macy #define	restrict
249eda14cbcSMatt Macy 
250eda14cbcSMatt Macy /*
251eda14cbcSMatt Macy  * Linux : GCC_VERSION is defined as of 3.9-rc1, so undefine it.
252eda14cbcSMatt Macy  * torvalds/linux@3f3f8d2f48acfd8ed3b8e6b7377935da57b27b16
253eda14cbcSMatt Macy  */
254eda14cbcSMatt Macy #ifdef GCC_VERSION
255eda14cbcSMatt Macy #undef GCC_VERSION
256eda14cbcSMatt Macy #endif
257eda14cbcSMatt Macy 
258eda14cbcSMatt Macy #define	GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
259eda14cbcSMatt Macy 
260eda14cbcSMatt Macy #if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
261eda14cbcSMatt Macy #define	expect(expr, value)    (__builtin_expect((expr), (value)))
262eda14cbcSMatt Macy #else
263eda14cbcSMatt Macy #define	expect(expr, value)    (expr)
264eda14cbcSMatt Macy #endif
265eda14cbcSMatt Macy 
266eda14cbcSMatt Macy #ifndef likely
267eda14cbcSMatt Macy #define	likely(expr)	expect((expr) != 0, 1)
268eda14cbcSMatt Macy #endif
269eda14cbcSMatt Macy 
270eda14cbcSMatt Macy #ifndef unlikely
271eda14cbcSMatt Macy #define	unlikely(expr)	expect((expr) != 0, 0)
272eda14cbcSMatt Macy #endif
273eda14cbcSMatt Macy 
274eda14cbcSMatt Macy #define	lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | \
275eda14cbcSMatt Macy 	(((x) & 0xffu) << 8)))
276eda14cbcSMatt Macy 
277eda14cbcSMatt Macy /* Basic types */
278eda14cbcSMatt Macy #define	BYTE	uint8_t
279eda14cbcSMatt Macy #define	U16	uint16_t
280eda14cbcSMatt Macy #define	U32	uint32_t
281eda14cbcSMatt Macy #define	S32	int32_t
282eda14cbcSMatt Macy #define	U64	uint64_t
283eda14cbcSMatt Macy 
284eda14cbcSMatt Macy #ifndef LZ4_FORCE_UNALIGNED_ACCESS
285eda14cbcSMatt Macy #pragma pack(1)
286eda14cbcSMatt Macy #endif
287eda14cbcSMatt Macy 
288eda14cbcSMatt Macy typedef struct _U16_S {
289eda14cbcSMatt Macy 	U16 v;
290eda14cbcSMatt Macy } U16_S;
291eda14cbcSMatt Macy typedef struct _U32_S {
292eda14cbcSMatt Macy 	U32 v;
293eda14cbcSMatt Macy } U32_S;
294eda14cbcSMatt Macy typedef struct _U64_S {
295eda14cbcSMatt Macy 	U64 v;
296eda14cbcSMatt Macy } U64_S;
297eda14cbcSMatt Macy 
298eda14cbcSMatt Macy #ifndef LZ4_FORCE_UNALIGNED_ACCESS
299eda14cbcSMatt Macy #pragma pack()
300eda14cbcSMatt Macy #endif
301eda14cbcSMatt Macy 
302eda14cbcSMatt Macy #define	A64(x) (((U64_S *)(x))->v)
303eda14cbcSMatt Macy #define	A32(x) (((U32_S *)(x))->v)
304eda14cbcSMatt Macy #define	A16(x) (((U16_S *)(x))->v)
305eda14cbcSMatt Macy 
306eda14cbcSMatt Macy /*
307eda14cbcSMatt Macy  * Constants
308eda14cbcSMatt Macy  */
309eda14cbcSMatt Macy #define	MINMATCH 4
310eda14cbcSMatt Macy 
311eda14cbcSMatt Macy #define	HASH_LOG COMPRESSIONLEVEL
312eda14cbcSMatt Macy #define	HASHTABLESIZE (1 << HASH_LOG)
313eda14cbcSMatt Macy #define	HASH_MASK (HASHTABLESIZE - 1)
314eda14cbcSMatt Macy 
315eda14cbcSMatt Macy #define	SKIPSTRENGTH (NOTCOMPRESSIBLE_CONFIRMATION > 2 ? \
316eda14cbcSMatt Macy 	NOTCOMPRESSIBLE_CONFIRMATION : 2)
317eda14cbcSMatt Macy 
318eda14cbcSMatt Macy #define	COPYLENGTH 8
319eda14cbcSMatt Macy #define	LASTLITERALS 5
320eda14cbcSMatt Macy #define	MFLIMIT (COPYLENGTH + MINMATCH)
321eda14cbcSMatt Macy #define	MINLENGTH (MFLIMIT + 1)
322eda14cbcSMatt Macy 
323eda14cbcSMatt Macy #define	MAXD_LOG 16
324eda14cbcSMatt Macy #define	MAX_DISTANCE ((1 << MAXD_LOG) - 1)
325eda14cbcSMatt Macy 
326eda14cbcSMatt Macy #define	ML_BITS 4
327eda14cbcSMatt Macy #define	ML_MASK ((1U<<ML_BITS)-1)
328eda14cbcSMatt Macy #define	RUN_BITS (8-ML_BITS)
329eda14cbcSMatt Macy #define	RUN_MASK ((1U<<RUN_BITS)-1)
330eda14cbcSMatt Macy 
331eda14cbcSMatt Macy 
332eda14cbcSMatt Macy /*
333eda14cbcSMatt Macy  * Architecture-specific macros
334eda14cbcSMatt Macy  */
335eda14cbcSMatt Macy #if LZ4_ARCH64
336eda14cbcSMatt Macy #define	STEPSIZE 8
337eda14cbcSMatt Macy #define	UARCH U64
338eda14cbcSMatt Macy #define	AARCH A64
339eda14cbcSMatt Macy #define	LZ4_COPYSTEP(s, d)	A64(d) = A64(s); d += 8; s += 8;
340eda14cbcSMatt Macy #define	LZ4_COPYPACKET(s, d)	LZ4_COPYSTEP(s, d)
341eda14cbcSMatt Macy #define	LZ4_SECURECOPY(s, d, e)	if (d < e) LZ4_WILDCOPY(s, d, e)
342eda14cbcSMatt Macy #define	HTYPE U32
343eda14cbcSMatt Macy #define	INITBASE(base)		const BYTE* const base = ip
344eda14cbcSMatt Macy #else /* !LZ4_ARCH64 */
345eda14cbcSMatt Macy #define	STEPSIZE 4
346eda14cbcSMatt Macy #define	UARCH U32
347eda14cbcSMatt Macy #define	AARCH A32
348eda14cbcSMatt Macy #define	LZ4_COPYSTEP(s, d)	A32(d) = A32(s); d += 4; s += 4;
349eda14cbcSMatt Macy #define	LZ4_COPYPACKET(s, d)	LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);
350eda14cbcSMatt Macy #define	LZ4_SECURECOPY		LZ4_WILDCOPY
351eda14cbcSMatt Macy #define	HTYPE const BYTE *
352eda14cbcSMatt Macy #define	INITBASE(base)		const int base = 0
353eda14cbcSMatt Macy #endif /* !LZ4_ARCH64 */
354eda14cbcSMatt Macy 
355eda14cbcSMatt Macy #if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))
356eda14cbcSMatt Macy #define	LZ4_READ_LITTLEENDIAN_16(d, s, p) \
357eda14cbcSMatt Macy 	{ U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
358eda14cbcSMatt Macy #define	LZ4_WRITE_LITTLEENDIAN_16(p, i) \
359eda14cbcSMatt Macy 	{ U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; }
360eda14cbcSMatt Macy #else
361eda14cbcSMatt Macy #define	LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); }
362eda14cbcSMatt Macy #define	LZ4_WRITE_LITTLEENDIAN_16(p, v)  { A16(p) = v; p += 2; }
363eda14cbcSMatt Macy #endif
364eda14cbcSMatt Macy 
365eda14cbcSMatt Macy 
366eda14cbcSMatt Macy /* Local structures */
367eda14cbcSMatt Macy struct refTables {
368eda14cbcSMatt Macy 	HTYPE hashTable[HASHTABLESIZE];
369eda14cbcSMatt Macy };
370eda14cbcSMatt Macy 
371eda14cbcSMatt Macy 
372eda14cbcSMatt Macy /* Macros */
373eda14cbcSMatt Macy #define	LZ4_HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH * 8) - \
374eda14cbcSMatt Macy 	HASH_LOG))
375eda14cbcSMatt Macy #define	LZ4_HASH_VALUE(p) LZ4_HASH_FUNCTION(A32(p))
376eda14cbcSMatt Macy #define	LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
377eda14cbcSMatt Macy #define	LZ4_BLINDCOPY(s, d, l) { BYTE* e = (d) + l; LZ4_WILDCOPY(s, d, e); \
378eda14cbcSMatt Macy 	d = e; }
379eda14cbcSMatt Macy 
380eda14cbcSMatt Macy 
381eda14cbcSMatt Macy /* Private functions */
382eda14cbcSMatt Macy #if LZ4_ARCH64
383eda14cbcSMatt Macy 
384eda14cbcSMatt Macy static inline int
385eda14cbcSMatt Macy LZ4_NbCommonBytes(register U64 val)
386eda14cbcSMatt Macy {
387eda14cbcSMatt Macy #if defined(LZ4_BIG_ENDIAN)
388eda14cbcSMatt Macy #if ((defined(__GNUC__) && (GCC_VERSION >= 304)) || defined(__clang__)) && \
389eda14cbcSMatt Macy 	!defined(LZ4_FORCE_SW_BITCOUNT)
390eda14cbcSMatt Macy 	return (__builtin_clzll(val) >> 3);
391eda14cbcSMatt Macy #else
392eda14cbcSMatt Macy 	int r;
393eda14cbcSMatt Macy 	if (!(val >> 32)) {
394eda14cbcSMatt Macy 		r = 4;
395eda14cbcSMatt Macy 	} else {
396eda14cbcSMatt Macy 		r = 0;
397eda14cbcSMatt Macy 		val >>= 32;
398eda14cbcSMatt Macy 	}
399eda14cbcSMatt Macy 	if (!(val >> 16)) {
400eda14cbcSMatt Macy 		r += 2;
401eda14cbcSMatt Macy 		val >>= 8;
402eda14cbcSMatt Macy 	} else {
403eda14cbcSMatt Macy 		val >>= 24;
404eda14cbcSMatt Macy 	}
405eda14cbcSMatt Macy 	r += (!val);
406eda14cbcSMatt Macy 	return (r);
407eda14cbcSMatt Macy #endif
408eda14cbcSMatt Macy #else
409eda14cbcSMatt Macy #if ((defined(__GNUC__) && (GCC_VERSION >= 304)) || defined(__clang__)) && \
410eda14cbcSMatt Macy 	!defined(LZ4_FORCE_SW_BITCOUNT)
411eda14cbcSMatt Macy 	return (__builtin_ctzll(val) >> 3);
412eda14cbcSMatt Macy #else
413eda14cbcSMatt Macy 	static const int DeBruijnBytePos[64] =
414eda14cbcSMatt Macy 	    { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5,
415eda14cbcSMatt Macy 		3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5,
416eda14cbcSMatt Macy 		5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4,
417eda14cbcSMatt Macy 		4, 5, 7, 2, 6, 5, 7, 6, 7, 7
418eda14cbcSMatt Macy 	};
419eda14cbcSMatt Macy 	return DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >>
420eda14cbcSMatt Macy 	    58];
421eda14cbcSMatt Macy #endif
422eda14cbcSMatt Macy #endif
423eda14cbcSMatt Macy }
424eda14cbcSMatt Macy 
425eda14cbcSMatt Macy #else
426eda14cbcSMatt Macy 
427eda14cbcSMatt Macy static inline int
428eda14cbcSMatt Macy LZ4_NbCommonBytes(register U32 val)
429eda14cbcSMatt Macy {
430eda14cbcSMatt Macy #if defined(LZ4_BIG_ENDIAN)
431eda14cbcSMatt Macy #if ((defined(__GNUC__) && (GCC_VERSION >= 304)) || defined(__clang__)) && \
432eda14cbcSMatt Macy 	!defined(LZ4_FORCE_SW_BITCOUNT)
433eda14cbcSMatt Macy 	return (__builtin_clz(val) >> 3);
434eda14cbcSMatt Macy #else
435eda14cbcSMatt Macy 	int r;
436eda14cbcSMatt Macy 	if (!(val >> 16)) {
437eda14cbcSMatt Macy 		r = 2;
438eda14cbcSMatt Macy 		val >>= 8;
439eda14cbcSMatt Macy 	} else {
440eda14cbcSMatt Macy 		r = 0;
441eda14cbcSMatt Macy 		val >>= 24;
442eda14cbcSMatt Macy 	}
443eda14cbcSMatt Macy 	r += (!val);
444eda14cbcSMatt Macy 	return (r);
445eda14cbcSMatt Macy #endif
446eda14cbcSMatt Macy #else
447eda14cbcSMatt Macy #if defined(__GNUC__) && (GCC_VERSION >= 304) && \
448eda14cbcSMatt Macy 	!defined(LZ4_FORCE_SW_BITCOUNT)
449eda14cbcSMatt Macy 	return (__builtin_ctz(val) >> 3);
450eda14cbcSMatt Macy #else
451eda14cbcSMatt Macy 	static const int DeBruijnBytePos[32] = {
452eda14cbcSMatt Macy 		0, 0, 3, 0, 3, 1, 3, 0,
453eda14cbcSMatt Macy 		3, 2, 2, 1, 3, 2, 0, 1,
454eda14cbcSMatt Macy 		3, 3, 1, 2, 2, 2, 2, 0,
455eda14cbcSMatt Macy 		3, 1, 2, 0, 1, 0, 1, 1
456eda14cbcSMatt Macy 	};
457eda14cbcSMatt Macy 	return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >>
458eda14cbcSMatt Macy 	    27];
459eda14cbcSMatt Macy #endif
460eda14cbcSMatt Macy #endif
461eda14cbcSMatt Macy }
462eda14cbcSMatt Macy 
463eda14cbcSMatt Macy #endif
464eda14cbcSMatt Macy 
465eda14cbcSMatt Macy /* Compression functions */
466eda14cbcSMatt Macy 
467eda14cbcSMatt Macy /*ARGSUSED*/
468eda14cbcSMatt Macy static int
469eda14cbcSMatt Macy LZ4_compressCtx(void *ctx, const char *source, char *dest, int isize,
470eda14cbcSMatt Macy     int osize)
471eda14cbcSMatt Macy {
472eda14cbcSMatt Macy 	struct refTables *srt = (struct refTables *)ctx;
473eda14cbcSMatt Macy 	HTYPE *HashTable = (HTYPE *) (srt->hashTable);
474eda14cbcSMatt Macy 
475eda14cbcSMatt Macy 	const BYTE *ip = (BYTE *) source;
476eda14cbcSMatt Macy 	INITBASE(base);
477eda14cbcSMatt Macy 	const BYTE *anchor = ip;
478eda14cbcSMatt Macy 	const BYTE *const iend = ip + isize;
479eda14cbcSMatt Macy 	const BYTE *const oend = (BYTE *) dest + osize;
480eda14cbcSMatt Macy 	const BYTE *const mflimit = iend - MFLIMIT;
481eda14cbcSMatt Macy #define	matchlimit (iend - LASTLITERALS)
482eda14cbcSMatt Macy 
483eda14cbcSMatt Macy 	BYTE *op = (BYTE *) dest;
484eda14cbcSMatt Macy 
485eda14cbcSMatt Macy 	int len, length;
486eda14cbcSMatt Macy 	const int skipStrength = SKIPSTRENGTH;
487eda14cbcSMatt Macy 	U32 forwardH;
488eda14cbcSMatt Macy 
489eda14cbcSMatt Macy 
490eda14cbcSMatt Macy 	/* Init */
491eda14cbcSMatt Macy 	if (isize < MINLENGTH)
492eda14cbcSMatt Macy 		goto _last_literals;
493eda14cbcSMatt Macy 
494eda14cbcSMatt Macy 	/* First Byte */
495eda14cbcSMatt Macy 	HashTable[LZ4_HASH_VALUE(ip)] = ip - base;
496eda14cbcSMatt Macy 	ip++;
497eda14cbcSMatt Macy 	forwardH = LZ4_HASH_VALUE(ip);
498eda14cbcSMatt Macy 
499eda14cbcSMatt Macy 	/* Main Loop */
500eda14cbcSMatt Macy 	for (;;) {
501eda14cbcSMatt Macy 		int findMatchAttempts = (1U << skipStrength) + 3;
502eda14cbcSMatt Macy 		const BYTE *forwardIp = ip;
503eda14cbcSMatt Macy 		const BYTE *ref;
504eda14cbcSMatt Macy 		BYTE *token;
505eda14cbcSMatt Macy 
506eda14cbcSMatt Macy 		/* Find a match */
507eda14cbcSMatt Macy 		do {
508eda14cbcSMatt Macy 			U32 h = forwardH;
509eda14cbcSMatt Macy 			int step = findMatchAttempts++ >> skipStrength;
510eda14cbcSMatt Macy 			ip = forwardIp;
511eda14cbcSMatt Macy 			forwardIp = ip + step;
512eda14cbcSMatt Macy 
513eda14cbcSMatt Macy 			if (unlikely(forwardIp > mflimit)) {
514eda14cbcSMatt Macy 				goto _last_literals;
515eda14cbcSMatt Macy 			}
516eda14cbcSMatt Macy 
517eda14cbcSMatt Macy 			forwardH = LZ4_HASH_VALUE(forwardIp);
518eda14cbcSMatt Macy 			ref = base + HashTable[h];
519eda14cbcSMatt Macy 			HashTable[h] = ip - base;
520eda14cbcSMatt Macy 
521eda14cbcSMatt Macy 		} while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip)));
522eda14cbcSMatt Macy 
523eda14cbcSMatt Macy 		/* Catch up */
524eda14cbcSMatt Macy 		while ((ip > anchor) && (ref > (BYTE *) source) &&
525eda14cbcSMatt Macy 		    unlikely(ip[-1] == ref[-1])) {
526eda14cbcSMatt Macy 			ip--;
527eda14cbcSMatt Macy 			ref--;
528eda14cbcSMatt Macy 		}
529eda14cbcSMatt Macy 
530eda14cbcSMatt Macy 		/* Encode Literal length */
531eda14cbcSMatt Macy 		length = ip - anchor;
532eda14cbcSMatt Macy 		token = op++;
533eda14cbcSMatt Macy 
534eda14cbcSMatt Macy 		/* Check output limit */
535eda14cbcSMatt Macy 		if (unlikely(op + length + (2 + 1 + LASTLITERALS) +
536eda14cbcSMatt Macy 		    (length >> 8) > oend))
537eda14cbcSMatt Macy 			return (0);
538eda14cbcSMatt Macy 
539eda14cbcSMatt Macy 		if (length >= (int)RUN_MASK) {
540eda14cbcSMatt Macy 			*token = (RUN_MASK << ML_BITS);
541eda14cbcSMatt Macy 			len = length - RUN_MASK;
542eda14cbcSMatt Macy 			for (; len > 254; len -= 255)
543eda14cbcSMatt Macy 				*op++ = 255;
544eda14cbcSMatt Macy 			*op++ = (BYTE)len;
545eda14cbcSMatt Macy 		} else
546eda14cbcSMatt Macy 			*token = (length << ML_BITS);
547eda14cbcSMatt Macy 
548eda14cbcSMatt Macy 		/* Copy Literals */
549eda14cbcSMatt Macy 		LZ4_BLINDCOPY(anchor, op, length);
550eda14cbcSMatt Macy 
551eda14cbcSMatt Macy 		_next_match:
552eda14cbcSMatt Macy 		/* Encode Offset */
553eda14cbcSMatt Macy 		LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);
554eda14cbcSMatt Macy 
555eda14cbcSMatt Macy 		/* Start Counting */
556eda14cbcSMatt Macy 		ip += MINMATCH;
557eda14cbcSMatt Macy 		ref += MINMATCH;	/* MinMatch verified */
558eda14cbcSMatt Macy 		anchor = ip;
559eda14cbcSMatt Macy 		while (likely(ip < matchlimit - (STEPSIZE - 1))) {
560eda14cbcSMatt Macy 			UARCH diff = AARCH(ref) ^ AARCH(ip);
561eda14cbcSMatt Macy 			if (!diff) {
562eda14cbcSMatt Macy 				ip += STEPSIZE;
563eda14cbcSMatt Macy 				ref += STEPSIZE;
564eda14cbcSMatt Macy 				continue;
565eda14cbcSMatt Macy 			}
566eda14cbcSMatt Macy 			ip += LZ4_NbCommonBytes(diff);
567eda14cbcSMatt Macy 			goto _endCount;
568eda14cbcSMatt Macy 		}
569eda14cbcSMatt Macy #if LZ4_ARCH64
570eda14cbcSMatt Macy 		if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {
571eda14cbcSMatt Macy 			ip += 4;
572eda14cbcSMatt Macy 			ref += 4;
573eda14cbcSMatt Macy 		}
574eda14cbcSMatt Macy #endif
575eda14cbcSMatt Macy 		if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {
576eda14cbcSMatt Macy 			ip += 2;
577eda14cbcSMatt Macy 			ref += 2;
578eda14cbcSMatt Macy 		}
579eda14cbcSMatt Macy 		if ((ip < matchlimit) && (*ref == *ip))
580eda14cbcSMatt Macy 			ip++;
581eda14cbcSMatt Macy 		_endCount:
582eda14cbcSMatt Macy 
583eda14cbcSMatt Macy 		/* Encode MatchLength */
584eda14cbcSMatt Macy 		len = (ip - anchor);
585eda14cbcSMatt Macy 		/* Check output limit */
586eda14cbcSMatt Macy 		if (unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend))
587eda14cbcSMatt Macy 			return (0);
588eda14cbcSMatt Macy 		if (len >= (int)ML_MASK) {
589eda14cbcSMatt Macy 			*token += ML_MASK;
590eda14cbcSMatt Macy 			len -= ML_MASK;
591eda14cbcSMatt Macy 			for (; len > 509; len -= 510) {
592eda14cbcSMatt Macy 				*op++ = 255;
593eda14cbcSMatt Macy 				*op++ = 255;
594eda14cbcSMatt Macy 			}
595eda14cbcSMatt Macy 			if (len > 254) {
596eda14cbcSMatt Macy 				len -= 255;
597eda14cbcSMatt Macy 				*op++ = 255;
598eda14cbcSMatt Macy 			}
599eda14cbcSMatt Macy 			*op++ = (BYTE)len;
600eda14cbcSMatt Macy 		} else
601eda14cbcSMatt Macy 			*token += len;
602eda14cbcSMatt Macy 
603eda14cbcSMatt Macy 		/* Test end of chunk */
604eda14cbcSMatt Macy 		if (ip > mflimit) {
605eda14cbcSMatt Macy 			anchor = ip;
606eda14cbcSMatt Macy 			break;
607eda14cbcSMatt Macy 		}
608eda14cbcSMatt Macy 		/* Fill table */
609eda14cbcSMatt Macy 		HashTable[LZ4_HASH_VALUE(ip - 2)] = ip - 2 - base;
610eda14cbcSMatt Macy 
611eda14cbcSMatt Macy 		/* Test next position */
612eda14cbcSMatt Macy 		ref = base + HashTable[LZ4_HASH_VALUE(ip)];
613eda14cbcSMatt Macy 		HashTable[LZ4_HASH_VALUE(ip)] = ip - base;
614eda14cbcSMatt Macy 		if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) {
615eda14cbcSMatt Macy 			token = op++;
616eda14cbcSMatt Macy 			*token = 0;
617eda14cbcSMatt Macy 			goto _next_match;
618eda14cbcSMatt Macy 		}
619eda14cbcSMatt Macy 		/* Prepare next loop */
620eda14cbcSMatt Macy 		anchor = ip++;
621eda14cbcSMatt Macy 		forwardH = LZ4_HASH_VALUE(ip);
622eda14cbcSMatt Macy 	}
623eda14cbcSMatt Macy 
624eda14cbcSMatt Macy 	_last_literals:
625eda14cbcSMatt Macy 	/* Encode Last Literals */
626eda14cbcSMatt Macy 	{
627eda14cbcSMatt Macy 		int lastRun = iend - anchor;
628eda14cbcSMatt Macy 		if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) >
629eda14cbcSMatt Macy 		    oend)
630eda14cbcSMatt Macy 			return (0);
631eda14cbcSMatt Macy 		if (lastRun >= (int)RUN_MASK) {
632eda14cbcSMatt Macy 			*op++ = (RUN_MASK << ML_BITS);
633eda14cbcSMatt Macy 			lastRun -= RUN_MASK;
634eda14cbcSMatt Macy 			for (; lastRun > 254; lastRun -= 255) {
635eda14cbcSMatt Macy 				*op++ = 255;
636eda14cbcSMatt Macy 			}
637eda14cbcSMatt Macy 			*op++ = (BYTE)lastRun;
638eda14cbcSMatt Macy 		} else
639eda14cbcSMatt Macy 			*op++ = (lastRun << ML_BITS);
640eda14cbcSMatt Macy 		(void) memcpy(op, anchor, iend - anchor);
641eda14cbcSMatt Macy 		op += iend - anchor;
642eda14cbcSMatt Macy 	}
643eda14cbcSMatt Macy 
644eda14cbcSMatt Macy 	/* End */
645eda14cbcSMatt Macy 	return (int)(((char *)op) - dest);
646eda14cbcSMatt Macy }
647eda14cbcSMatt Macy 
648eda14cbcSMatt Macy 
649eda14cbcSMatt Macy 
650eda14cbcSMatt Macy /* Note : this function is valid only if isize < LZ4_64KLIMIT */
651eda14cbcSMatt Macy #define	LZ4_64KLIMIT ((1 << 16) + (MFLIMIT - 1))
652eda14cbcSMatt Macy #define	HASHLOG64K (HASH_LOG + 1)
653eda14cbcSMatt Macy #define	HASH64KTABLESIZE (1U << HASHLOG64K)
654eda14cbcSMatt Macy #define	LZ4_HASH64K_FUNCTION(i)	(((i) * 2654435761U) >> ((MINMATCH*8) - \
655eda14cbcSMatt Macy 	HASHLOG64K))
656eda14cbcSMatt Macy #define	LZ4_HASH64K_VALUE(p)	LZ4_HASH64K_FUNCTION(A32(p))
657eda14cbcSMatt Macy 
658eda14cbcSMatt Macy /*ARGSUSED*/
659eda14cbcSMatt Macy static int
660eda14cbcSMatt Macy LZ4_compress64kCtx(void *ctx, const char *source, char *dest, int isize,
661eda14cbcSMatt Macy     int osize)
662eda14cbcSMatt Macy {
663eda14cbcSMatt Macy 	struct refTables *srt = (struct refTables *)ctx;
664eda14cbcSMatt Macy 	U16 *HashTable = (U16 *) (srt->hashTable);
665eda14cbcSMatt Macy 
666eda14cbcSMatt Macy 	const BYTE *ip = (BYTE *) source;
667eda14cbcSMatt Macy 	const BYTE *anchor = ip;
668eda14cbcSMatt Macy 	const BYTE *const base = ip;
669eda14cbcSMatt Macy 	const BYTE *const iend = ip + isize;
670eda14cbcSMatt Macy 	const BYTE *const oend = (BYTE *) dest + osize;
671eda14cbcSMatt Macy 	const BYTE *const mflimit = iend - MFLIMIT;
672eda14cbcSMatt Macy #define	matchlimit (iend - LASTLITERALS)
673eda14cbcSMatt Macy 
674eda14cbcSMatt Macy 	BYTE *op = (BYTE *) dest;
675eda14cbcSMatt Macy 
676eda14cbcSMatt Macy 	int len, length;
677eda14cbcSMatt Macy 	const int skipStrength = SKIPSTRENGTH;
678eda14cbcSMatt Macy 	U32 forwardH;
679eda14cbcSMatt Macy 
680eda14cbcSMatt Macy 	/* Init */
681eda14cbcSMatt Macy 	if (isize < MINLENGTH)
682eda14cbcSMatt Macy 		goto _last_literals;
683eda14cbcSMatt Macy 
684eda14cbcSMatt Macy 	/* First Byte */
685eda14cbcSMatt Macy 	ip++;
686eda14cbcSMatt Macy 	forwardH = LZ4_HASH64K_VALUE(ip);
687eda14cbcSMatt Macy 
688eda14cbcSMatt Macy 	/* Main Loop */
689eda14cbcSMatt Macy 	for (;;) {
690eda14cbcSMatt Macy 		int findMatchAttempts = (1U << skipStrength) + 3;
691eda14cbcSMatt Macy 		const BYTE *forwardIp = ip;
692eda14cbcSMatt Macy 		const BYTE *ref;
693eda14cbcSMatt Macy 		BYTE *token;
694eda14cbcSMatt Macy 
695eda14cbcSMatt Macy 		/* Find a match */
696eda14cbcSMatt Macy 		do {
697eda14cbcSMatt Macy 			U32 h = forwardH;
698eda14cbcSMatt Macy 			int step = findMatchAttempts++ >> skipStrength;
699eda14cbcSMatt Macy 			ip = forwardIp;
700eda14cbcSMatt Macy 			forwardIp = ip + step;
701eda14cbcSMatt Macy 
702eda14cbcSMatt Macy 			if (forwardIp > mflimit) {
703eda14cbcSMatt Macy 				goto _last_literals;
704eda14cbcSMatt Macy 			}
705eda14cbcSMatt Macy 
706eda14cbcSMatt Macy 			forwardH = LZ4_HASH64K_VALUE(forwardIp);
707eda14cbcSMatt Macy 			ref = base + HashTable[h];
708eda14cbcSMatt Macy 			HashTable[h] = ip - base;
709eda14cbcSMatt Macy 
710eda14cbcSMatt Macy 		} while (A32(ref) != A32(ip));
711eda14cbcSMatt Macy 
712eda14cbcSMatt Macy 		/* Catch up */
713eda14cbcSMatt Macy 		while ((ip > anchor) && (ref > (BYTE *) source) &&
714eda14cbcSMatt Macy 		    (ip[-1] == ref[-1])) {
715eda14cbcSMatt Macy 			ip--;
716eda14cbcSMatt Macy 			ref--;
717eda14cbcSMatt Macy 		}
718eda14cbcSMatt Macy 
719eda14cbcSMatt Macy 		/* Encode Literal length */
720eda14cbcSMatt Macy 		length = ip - anchor;
721eda14cbcSMatt Macy 		token = op++;
722eda14cbcSMatt Macy 
723eda14cbcSMatt Macy 		/* Check output limit */
724eda14cbcSMatt Macy 		if (unlikely(op + length + (2 + 1 + LASTLITERALS) +
725eda14cbcSMatt Macy 		    (length >> 8) > oend))
726eda14cbcSMatt Macy 			return (0);
727eda14cbcSMatt Macy 
728eda14cbcSMatt Macy 		if (length >= (int)RUN_MASK) {
729eda14cbcSMatt Macy 			*token = (RUN_MASK << ML_BITS);
730eda14cbcSMatt Macy 			len = length - RUN_MASK;
731eda14cbcSMatt Macy 			for (; len > 254; len -= 255)
732eda14cbcSMatt Macy 				*op++ = 255;
733eda14cbcSMatt Macy 			*op++ = (BYTE)len;
734eda14cbcSMatt Macy 		} else
735eda14cbcSMatt Macy 			*token = (length << ML_BITS);
736eda14cbcSMatt Macy 
737eda14cbcSMatt Macy 		/* Copy Literals */
738eda14cbcSMatt Macy 		LZ4_BLINDCOPY(anchor, op, length);
739eda14cbcSMatt Macy 
740eda14cbcSMatt Macy 		_next_match:
741eda14cbcSMatt Macy 		/* Encode Offset */
742eda14cbcSMatt Macy 		LZ4_WRITE_LITTLEENDIAN_16(op, ip - ref);
743eda14cbcSMatt Macy 
744eda14cbcSMatt Macy 		/* Start Counting */
745eda14cbcSMatt Macy 		ip += MINMATCH;
746eda14cbcSMatt Macy 		ref += MINMATCH;	/* MinMatch verified */
747eda14cbcSMatt Macy 		anchor = ip;
748eda14cbcSMatt Macy 		while (ip < matchlimit - (STEPSIZE - 1)) {
749eda14cbcSMatt Macy 			UARCH diff = AARCH(ref) ^ AARCH(ip);
750eda14cbcSMatt Macy 			if (!diff) {
751eda14cbcSMatt Macy 				ip += STEPSIZE;
752eda14cbcSMatt Macy 				ref += STEPSIZE;
753eda14cbcSMatt Macy 				continue;
754eda14cbcSMatt Macy 			}
755eda14cbcSMatt Macy 			ip += LZ4_NbCommonBytes(diff);
756eda14cbcSMatt Macy 			goto _endCount;
757eda14cbcSMatt Macy 		}
758eda14cbcSMatt Macy #if LZ4_ARCH64
759eda14cbcSMatt Macy 		if ((ip < (matchlimit - 3)) && (A32(ref) == A32(ip))) {
760eda14cbcSMatt Macy 			ip += 4;
761eda14cbcSMatt Macy 			ref += 4;
762eda14cbcSMatt Macy 		}
763eda14cbcSMatt Macy #endif
764eda14cbcSMatt Macy 		if ((ip < (matchlimit - 1)) && (A16(ref) == A16(ip))) {
765eda14cbcSMatt Macy 			ip += 2;
766eda14cbcSMatt Macy 			ref += 2;
767eda14cbcSMatt Macy 		}
768eda14cbcSMatt Macy 		if ((ip < matchlimit) && (*ref == *ip))
769eda14cbcSMatt Macy 			ip++;
770eda14cbcSMatt Macy 		_endCount:
771eda14cbcSMatt Macy 
772eda14cbcSMatt Macy 		/* Encode MatchLength */
773eda14cbcSMatt Macy 		len = (ip - anchor);
774eda14cbcSMatt Macy 		/* Check output limit */
775eda14cbcSMatt Macy 		if (unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend))
776eda14cbcSMatt Macy 			return (0);
777eda14cbcSMatt Macy 		if (len >= (int)ML_MASK) {
778eda14cbcSMatt Macy 			*token += ML_MASK;
779eda14cbcSMatt Macy 			len -= ML_MASK;
780eda14cbcSMatt Macy 			for (; len > 509; len -= 510) {
781eda14cbcSMatt Macy 				*op++ = 255;
782eda14cbcSMatt Macy 				*op++ = 255;
783eda14cbcSMatt Macy 			}
784eda14cbcSMatt Macy 			if (len > 254) {
785eda14cbcSMatt Macy 				len -= 255;
786eda14cbcSMatt Macy 				*op++ = 255;
787eda14cbcSMatt Macy 			}
788eda14cbcSMatt Macy 			*op++ = (BYTE)len;
789eda14cbcSMatt Macy 		} else
790eda14cbcSMatt Macy 			*token += len;
791eda14cbcSMatt Macy 
792eda14cbcSMatt Macy 		/* Test end of chunk */
793eda14cbcSMatt Macy 		if (ip > mflimit) {
794eda14cbcSMatt Macy 			anchor = ip;
795eda14cbcSMatt Macy 			break;
796eda14cbcSMatt Macy 		}
797eda14cbcSMatt Macy 		/* Fill table */
798eda14cbcSMatt Macy 		HashTable[LZ4_HASH64K_VALUE(ip - 2)] = ip - 2 - base;
799eda14cbcSMatt Macy 
800eda14cbcSMatt Macy 		/* Test next position */
801eda14cbcSMatt Macy 		ref = base + HashTable[LZ4_HASH64K_VALUE(ip)];
802eda14cbcSMatt Macy 		HashTable[LZ4_HASH64K_VALUE(ip)] = ip - base;
803eda14cbcSMatt Macy 		if (A32(ref) == A32(ip)) {
804eda14cbcSMatt Macy 			token = op++;
805eda14cbcSMatt Macy 			*token = 0;
806eda14cbcSMatt Macy 			goto _next_match;
807eda14cbcSMatt Macy 		}
808eda14cbcSMatt Macy 		/* Prepare next loop */
809eda14cbcSMatt Macy 		anchor = ip++;
810eda14cbcSMatt Macy 		forwardH = LZ4_HASH64K_VALUE(ip);
811eda14cbcSMatt Macy 	}
812eda14cbcSMatt Macy 
813eda14cbcSMatt Macy 	_last_literals:
814eda14cbcSMatt Macy 	/* Encode Last Literals */
815eda14cbcSMatt Macy 	{
816eda14cbcSMatt Macy 		int lastRun = iend - anchor;
817eda14cbcSMatt Macy 		if (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) >
818eda14cbcSMatt Macy 		    oend)
819eda14cbcSMatt Macy 			return (0);
820eda14cbcSMatt Macy 		if (lastRun >= (int)RUN_MASK) {
821eda14cbcSMatt Macy 			*op++ = (RUN_MASK << ML_BITS);
822eda14cbcSMatt Macy 			lastRun -= RUN_MASK;
823eda14cbcSMatt Macy 			for (; lastRun > 254; lastRun -= 255)
824eda14cbcSMatt Macy 				*op++ = 255;
825eda14cbcSMatt Macy 			*op++ = (BYTE)lastRun;
826eda14cbcSMatt Macy 		} else
827eda14cbcSMatt Macy 			*op++ = (lastRun << ML_BITS);
828eda14cbcSMatt Macy 		(void) memcpy(op, anchor, iend - anchor);
829eda14cbcSMatt Macy 		op += iend - anchor;
830eda14cbcSMatt Macy 	}
831eda14cbcSMatt Macy 
832eda14cbcSMatt Macy 	/* End */
833eda14cbcSMatt Macy 	return (int)(((char *)op) - dest);
834eda14cbcSMatt Macy }
835eda14cbcSMatt Macy 
836eda14cbcSMatt Macy static int
837eda14cbcSMatt Macy real_LZ4_compress(const char *source, char *dest, int isize, int osize)
838eda14cbcSMatt Macy {
839eda14cbcSMatt Macy 	void *ctx;
840eda14cbcSMatt Macy 	int result;
841eda14cbcSMatt Macy 
842*aebc9683SMateusz Guzik 	ctx = lz4_alloc(KM_SLEEP);
843eda14cbcSMatt Macy 
844eda14cbcSMatt Macy 	/*
845eda14cbcSMatt Macy 	 * out of kernel memory, gently fall through - this will disable
846eda14cbcSMatt Macy 	 * compression in zio_compress_data
847eda14cbcSMatt Macy 	 */
848eda14cbcSMatt Macy 	if (ctx == NULL)
849eda14cbcSMatt Macy 		return (0);
850eda14cbcSMatt Macy 
851eda14cbcSMatt Macy 	memset(ctx, 0, sizeof (struct refTables));
852eda14cbcSMatt Macy 
853eda14cbcSMatt Macy 	if (isize < LZ4_64KLIMIT)
854eda14cbcSMatt Macy 		result = LZ4_compress64kCtx(ctx, source, dest, isize, osize);
855eda14cbcSMatt Macy 	else
856eda14cbcSMatt Macy 		result = LZ4_compressCtx(ctx, source, dest, isize, osize);
857eda14cbcSMatt Macy 
858*aebc9683SMateusz Guzik 	lz4_free(ctx);
859eda14cbcSMatt Macy 	return (result);
860eda14cbcSMatt Macy }
861eda14cbcSMatt Macy 
862eda14cbcSMatt Macy /* Decompression functions */
863eda14cbcSMatt Macy 
864eda14cbcSMatt Macy /*
865eda14cbcSMatt Macy  * Note: The decoding functions real_LZ4_uncompress() and
866eda14cbcSMatt Macy  *	LZ4_uncompress_unknownOutputSize() are safe against "buffer overflow"
867eda14cbcSMatt Macy  *	attack type. They will never write nor read outside of the provided
868eda14cbcSMatt Macy  *	output buffers. LZ4_uncompress_unknownOutputSize() also insures that
869eda14cbcSMatt Macy  *	it will never read outside of the input buffer. A corrupted input
870eda14cbcSMatt Macy  *	will produce an error result, a negative int, indicating the position
871eda14cbcSMatt Macy  *	of the error within input stream.
872eda14cbcSMatt Macy  *
873eda14cbcSMatt Macy  * Note[2]: real_LZ4_uncompress(), referred to above, is not used in ZFS so
874eda14cbcSMatt Macy  *	its code is not present here.
875eda14cbcSMatt Macy  */
876eda14cbcSMatt Macy 
877eda14cbcSMatt Macy static const int dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0};
878eda14cbcSMatt Macy #if LZ4_ARCH64
879eda14cbcSMatt Macy static const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
880eda14cbcSMatt Macy #endif
881eda14cbcSMatt Macy 
882eda14cbcSMatt Macy static int
883eda14cbcSMatt Macy LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
884eda14cbcSMatt Macy     int maxOutputSize)
885eda14cbcSMatt Macy {
886eda14cbcSMatt Macy 	/* Local Variables */
887eda14cbcSMatt Macy 	const BYTE *restrict ip = (const BYTE *) source;
888eda14cbcSMatt Macy 	const BYTE *const iend = ip + isize;
889eda14cbcSMatt Macy 	const BYTE *ref;
890eda14cbcSMatt Macy 
891eda14cbcSMatt Macy 	BYTE *op = (BYTE *) dest;
892eda14cbcSMatt Macy 	BYTE *const oend = op + maxOutputSize;
893eda14cbcSMatt Macy 	BYTE *cpy;
894eda14cbcSMatt Macy 
895eda14cbcSMatt Macy 	/* Main Loop */
896eda14cbcSMatt Macy 	while (ip < iend) {
897eda14cbcSMatt Macy 		unsigned token;
898eda14cbcSMatt Macy 		size_t length;
899eda14cbcSMatt Macy 
900eda14cbcSMatt Macy 		/* get runlength */
901eda14cbcSMatt Macy 		token = *ip++;
902eda14cbcSMatt Macy 		if ((length = (token >> ML_BITS)) == RUN_MASK) {
903eda14cbcSMatt Macy 			int s = 255;
904eda14cbcSMatt Macy 			while ((ip < iend) && (s == 255)) {
905eda14cbcSMatt Macy 				s = *ip++;
906eda14cbcSMatt Macy 				if (unlikely(length > (size_t)(length + s)))
907eda14cbcSMatt Macy 					goto _output_error;
908eda14cbcSMatt Macy 				length += s;
909eda14cbcSMatt Macy 			}
910eda14cbcSMatt Macy 		}
911eda14cbcSMatt Macy 		/* copy literals */
912eda14cbcSMatt Macy 		cpy = op + length;
913eda14cbcSMatt Macy 		/* CORNER-CASE: cpy might overflow. */
914eda14cbcSMatt Macy 		if (cpy < op)
915eda14cbcSMatt Macy 			goto _output_error;	/* cpy was overflowed, bail! */
916eda14cbcSMatt Macy 		if ((cpy > oend - COPYLENGTH) ||
917eda14cbcSMatt Macy 		    (ip + length > iend - COPYLENGTH)) {
918eda14cbcSMatt Macy 			if (cpy > oend)
919eda14cbcSMatt Macy 				/* Error: writes beyond output buffer */
920eda14cbcSMatt Macy 				goto _output_error;
921eda14cbcSMatt Macy 			if (ip + length != iend)
922eda14cbcSMatt Macy 				/*
923eda14cbcSMatt Macy 				 * Error: LZ4 format requires to consume all
924eda14cbcSMatt Macy 				 * input at this stage
925eda14cbcSMatt Macy 				 */
926eda14cbcSMatt Macy 				goto _output_error;
927eda14cbcSMatt Macy 			(void) memcpy(op, ip, length);
928eda14cbcSMatt Macy 			op += length;
929eda14cbcSMatt Macy 			/* Necessarily EOF, due to parsing restrictions */
930eda14cbcSMatt Macy 			break;
931eda14cbcSMatt Macy 		}
932eda14cbcSMatt Macy 		LZ4_WILDCOPY(ip, op, cpy);
933eda14cbcSMatt Macy 		ip -= (op - cpy);
934eda14cbcSMatt Macy 		op = cpy;
935eda14cbcSMatt Macy 
936eda14cbcSMatt Macy 		/* get offset */
937eda14cbcSMatt Macy 		LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
938eda14cbcSMatt Macy 		ip += 2;
939eda14cbcSMatt Macy 		if (ref < (BYTE * const) dest)
940eda14cbcSMatt Macy 			/*
941eda14cbcSMatt Macy 			 * Error: offset creates reference outside of
942eda14cbcSMatt Macy 			 * destination buffer
943eda14cbcSMatt Macy 			 */
944eda14cbcSMatt Macy 			goto _output_error;
945eda14cbcSMatt Macy 
946eda14cbcSMatt Macy 		/* get matchlength */
947eda14cbcSMatt Macy 		if ((length = (token & ML_MASK)) == ML_MASK) {
948eda14cbcSMatt Macy 			while (ip < iend) {
949eda14cbcSMatt Macy 				int s = *ip++;
950eda14cbcSMatt Macy 				if (unlikely(length > (size_t)(length + s)))
951eda14cbcSMatt Macy 					goto _output_error;
952eda14cbcSMatt Macy 				length += s;
953eda14cbcSMatt Macy 				if (s == 255)
954eda14cbcSMatt Macy 					continue;
955eda14cbcSMatt Macy 				break;
956eda14cbcSMatt Macy 			}
957eda14cbcSMatt Macy 		}
958eda14cbcSMatt Macy 		/* copy repeated sequence */
959eda14cbcSMatt Macy 		if (unlikely(op - ref < STEPSIZE)) {
960eda14cbcSMatt Macy #if LZ4_ARCH64
961eda14cbcSMatt Macy 			int dec64 = dec64table[op - ref];
962eda14cbcSMatt Macy #else
963eda14cbcSMatt Macy 			const int dec64 = 0;
964eda14cbcSMatt Macy #endif
965eda14cbcSMatt Macy 			op[0] = ref[0];
966eda14cbcSMatt Macy 			op[1] = ref[1];
967eda14cbcSMatt Macy 			op[2] = ref[2];
968eda14cbcSMatt Macy 			op[3] = ref[3];
969eda14cbcSMatt Macy 			op += 4;
970eda14cbcSMatt Macy 			ref += 4;
971eda14cbcSMatt Macy 			ref -= dec32table[op - ref];
972eda14cbcSMatt Macy 			A32(op) = A32(ref);
973eda14cbcSMatt Macy 			op += STEPSIZE - 4;
974eda14cbcSMatt Macy 			ref -= dec64;
975eda14cbcSMatt Macy 		} else {
976eda14cbcSMatt Macy 			LZ4_COPYSTEP(ref, op);
977eda14cbcSMatt Macy 		}
978eda14cbcSMatt Macy 		cpy = op + length - (STEPSIZE - 4);
979eda14cbcSMatt Macy 		if (cpy > oend - COPYLENGTH) {
980eda14cbcSMatt Macy 			if (cpy > oend)
981eda14cbcSMatt Macy 				/*
982eda14cbcSMatt Macy 				 * Error: request to write outside of
983eda14cbcSMatt Macy 				 * destination buffer
984eda14cbcSMatt Macy 				 */
985eda14cbcSMatt Macy 				goto _output_error;
986eda14cbcSMatt Macy #if LZ4_ARCH64
987eda14cbcSMatt Macy 			if ((ref + COPYLENGTH) > oend)
988eda14cbcSMatt Macy #else
989eda14cbcSMatt Macy 			if ((ref + COPYLENGTH) > oend ||
990eda14cbcSMatt Macy 			    (op + COPYLENGTH) > oend)
991eda14cbcSMatt Macy #endif
992eda14cbcSMatt Macy 				goto _output_error;
993eda14cbcSMatt Macy 			LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
994eda14cbcSMatt Macy 			while (op < cpy)
995eda14cbcSMatt Macy 				*op++ = *ref++;
996eda14cbcSMatt Macy 			op = cpy;
997eda14cbcSMatt Macy 			if (op == oend)
998eda14cbcSMatt Macy 				/*
999eda14cbcSMatt Macy 				 * Check EOF (should never happen, since
1000eda14cbcSMatt Macy 				 * last 5 bytes are supposed to be literals)
1001eda14cbcSMatt Macy 				 */
1002eda14cbcSMatt Macy 				goto _output_error;
1003eda14cbcSMatt Macy 			continue;
1004eda14cbcSMatt Macy 		}
1005eda14cbcSMatt Macy 		LZ4_SECURECOPY(ref, op, cpy);
1006eda14cbcSMatt Macy 		op = cpy;	/* correction */
1007eda14cbcSMatt Macy 	}
1008eda14cbcSMatt Macy 
1009eda14cbcSMatt Macy 	/* end of decoding */
1010eda14cbcSMatt Macy 	return (int)(((char *)op) - dest);
1011eda14cbcSMatt Macy 
1012eda14cbcSMatt Macy 	/* write overflow error detected */
1013eda14cbcSMatt Macy 	_output_error:
1014eda14cbcSMatt Macy 	return (-1);
1015eda14cbcSMatt Macy }
1016eda14cbcSMatt Macy 
1017*aebc9683SMateusz Guzik #ifdef __FreeBSD__
1018*aebc9683SMateusz Guzik /*
1019*aebc9683SMateusz Guzik  * FreeBSD has 4, 8 and 16 KB malloc zones which can be used here.
1020*aebc9683SMateusz Guzik  * Should struct refTables get resized this may need to be revisited, hence
1021*aebc9683SMateusz Guzik  * compiler-time asserts.
1022*aebc9683SMateusz Guzik  */
1023*aebc9683SMateusz Guzik _Static_assert(sizeof(struct refTables) <= 16384,
1024*aebc9683SMateusz Guzik     "refTables too big for malloc");
1025*aebc9683SMateusz Guzik _Static_assert((sizeof(struct refTables) % 4096) == 0,
1026*aebc9683SMateusz Guzik     "refTables not a multiple of page size");
1027*aebc9683SMateusz Guzik #else
1028*aebc9683SMateusz Guzik #define ZFS_LZ4_USE_CACHE
1029*aebc9683SMateusz Guzik #endif
1030*aebc9683SMateusz Guzik 
1031*aebc9683SMateusz Guzik #ifdef ZFS_LZ4_USE_CACHE
1032*aebc9683SMateusz Guzik static kmem_cache_t *lz4_cache;
1033*aebc9683SMateusz Guzik 
1034eda14cbcSMatt Macy void
1035eda14cbcSMatt Macy lz4_init(void)
1036eda14cbcSMatt Macy {
1037eda14cbcSMatt Macy 	lz4_cache = kmem_cache_create("lz4_cache",
1038eda14cbcSMatt Macy 	    sizeof (struct refTables), 0, NULL, NULL, NULL, NULL, NULL, 0);
1039eda14cbcSMatt Macy }
1040eda14cbcSMatt Macy 
1041eda14cbcSMatt Macy void
1042eda14cbcSMatt Macy lz4_fini(void)
1043eda14cbcSMatt Macy {
1044eda14cbcSMatt Macy 	if (lz4_cache) {
1045eda14cbcSMatt Macy 		kmem_cache_destroy(lz4_cache);
1046eda14cbcSMatt Macy 		lz4_cache = NULL;
1047eda14cbcSMatt Macy 	}
1048eda14cbcSMatt Macy }
1049*aebc9683SMateusz Guzik 
1050*aebc9683SMateusz Guzik static void *
1051*aebc9683SMateusz Guzik lz4_alloc(int flags)
1052*aebc9683SMateusz Guzik {
1053*aebc9683SMateusz Guzik 	ASSERT(lz4_cache != NULL);
1054*aebc9683SMateusz Guzik 	return (kmem_cache_alloc(lz4_cache, flags));
1055*aebc9683SMateusz Guzik }
1056*aebc9683SMateusz Guzik 
1057*aebc9683SMateusz Guzik static void
1058*aebc9683SMateusz Guzik lz4_free(void *ctx)
1059*aebc9683SMateusz Guzik {
1060*aebc9683SMateusz Guzik 	kmem_cache_free(lz4_cache, ctx);
1061*aebc9683SMateusz Guzik }
1062*aebc9683SMateusz Guzik #else
1063*aebc9683SMateusz Guzik void
1064*aebc9683SMateusz Guzik lz4_init(void)
1065*aebc9683SMateusz Guzik {
1066*aebc9683SMateusz Guzik }
1067*aebc9683SMateusz Guzik 
1068*aebc9683SMateusz Guzik void
1069*aebc9683SMateusz Guzik lz4_fini(void)
1070*aebc9683SMateusz Guzik {
1071*aebc9683SMateusz Guzik }
1072*aebc9683SMateusz Guzik 
1073*aebc9683SMateusz Guzik static void *
1074*aebc9683SMateusz Guzik lz4_alloc(int flags)
1075*aebc9683SMateusz Guzik {
1076*aebc9683SMateusz Guzik 	return (kmem_alloc(sizeof (struct refTables), flags));
1077*aebc9683SMateusz Guzik }
1078*aebc9683SMateusz Guzik 
1079*aebc9683SMateusz Guzik static void
1080*aebc9683SMateusz Guzik lz4_free(void *ctx)
1081*aebc9683SMateusz Guzik {
1082*aebc9683SMateusz Guzik 	kmem_free(ctx, sizeof (struct refTables));
1083*aebc9683SMateusz Guzik }
1084*aebc9683SMateusz Guzik #endif
1085