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