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