| /** |
| * \file zstd.c |
| * Single-file Zstandard library. |
| * |
| * Generate using: |
| * \code |
| * combine.sh -r ../../lib -o zstd.c zstd-in.c |
| * \endcode |
| */ |
| /* |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| /* |
| * Settings to bake for the single library file. |
| * |
| * Note: It's important that none of these affects 'zstd.h' (only the |
| * implementation files we're amalgamating). |
| * |
| * Note: MEM_MODULE stops xxhash redefining BYTE, U16, etc., which are also |
| * defined in mem.h (breaking C99 compatibility). |
| * |
| * Note: the undefs for xxHash allow Zstd's implementation to coinside with with |
| * standalone xxHash usage (with global defines). |
| * |
| * Note: multithreading is enabled for all platforms apart from Emscripten. |
| */ |
| #define DEBUGLEVEL 0 |
| #define MEM_MODULE |
| #undef XXH_NAMESPACE |
| #define XXH_NAMESPACE ZSTD_ |
| #undef XXH_PRIVATE_API |
| #define XXH_PRIVATE_API |
| #undef XXH_INLINE_ALL |
| #define XXH_INLINE_ALL |
| #define ZSTD_LEGACY_SUPPORT 0 |
| #ifndef __EMSCRIPTEN__ |
| #define ZSTD_MULTITHREAD |
| #endif |
| #define ZSTD_TRACE 0 |
| |
| /* Include zstd_deps.h first with all the options we need enabled. */ |
| #define ZSTD_DEPS_NEED_MALLOC |
| #define ZSTD_DEPS_NEED_MATH64 |
| /**** start inlining common/zstd_deps.h ****/ |
| /* |
| * Copyright (c) 2016-2021, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| |
| /* This file provides common libc dependencies that zstd requires. |
| * The purpose is to allow replacing this file with a custom implementation |
| * to compile zstd without libc support. |
| */ |
| |
| /* Need: |
| * NULL |
| * INT_MAX |
| * UINT_MAX |
| * ZSTD_memcpy() |
| * ZSTD_memset() |
| * ZSTD_memmove() |
| */ |
| #ifndef ZSTD_DEPS_COMMON |
| #define ZSTD_DEPS_COMMON |
| |
| #include <limits.h> |
| #include <stddef.h> |
| #include <string.h> |
| |
| #if defined(__GNUC__) && __GNUC__ >= 4 |
| # define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l)) |
| # define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l)) |
| # define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l)) |
| #else |
| # define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l)) |
| # define ZSTD_memmove(d,s,l) memmove((d),(s),(l)) |
| # define ZSTD_memset(p,v,l) memset((p),(v),(l)) |
| #endif |
| |
| #endif /* ZSTD_DEPS_COMMON */ |
| |
| /* Need: |
| * ZSTD_malloc() |
| * ZSTD_free() |
| * ZSTD_calloc() |
| */ |
| #ifdef ZSTD_DEPS_NEED_MALLOC |
| #ifndef ZSTD_DEPS_MALLOC |
| #define ZSTD_DEPS_MALLOC |
| |
| #include <stdlib.h> |
| |
| #define ZSTD_malloc(s) malloc(s) |
| #define ZSTD_calloc(n,s) calloc((n), (s)) |
| #define ZSTD_free(p) free((p)) |
| |
| #endif /* ZSTD_DEPS_MALLOC */ |
| #endif /* ZSTD_DEPS_NEED_MALLOC */ |
| |
| /* |
| * Provides 64-bit math support. |
| * Need: |
| * U64 ZSTD_div64(U64 dividend, U32 divisor) |
| */ |
| #ifdef ZSTD_DEPS_NEED_MATH64 |
| #ifndef ZSTD_DEPS_MATH64 |
| #define ZSTD_DEPS_MATH64 |
| |
| #define ZSTD_div64(dividend, divisor) ((dividend) / (divisor)) |
| |
| #endif /* ZSTD_DEPS_MATH64 */ |
| #endif /* ZSTD_DEPS_NEED_MATH64 */ |
| |
| /* Need: |
| * assert() |
| */ |
| #ifdef ZSTD_DEPS_NEED_ASSERT |
| #ifndef ZSTD_DEPS_ASSERT |
| #define ZSTD_DEPS_ASSERT |
| |
| #include <assert.h> |
| |
| #endif /* ZSTD_DEPS_ASSERT */ |
| #endif /* ZSTD_DEPS_NEED_ASSERT */ |
| |
| /* Need: |
| * ZSTD_DEBUG_PRINT() |
| */ |
| #ifdef ZSTD_DEPS_NEED_IO |
| #ifndef ZSTD_DEPS_IO |
| #define ZSTD_DEPS_IO |
| |
| #include <stdio.h> |
| #define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) |
| |
| #endif /* ZSTD_DEPS_IO */ |
| #endif /* ZSTD_DEPS_NEED_IO */ |
| |
| /* Only requested when <stdint.h> is known to be present. |
| * Need: |
| * intptr_t |
| */ |
| #ifdef ZSTD_DEPS_NEED_STDINT |
| #ifndef ZSTD_DEPS_STDINT |
| #define ZSTD_DEPS_STDINT |
| |
| #include <stdint.h> |
| |
| #endif /* ZSTD_DEPS_STDINT */ |
| #endif /* ZSTD_DEPS_NEED_STDINT */ |
| /**** ended inlining common/zstd_deps.h ****/ |
| |
| /**** start inlining common/debug.c ****/ |
| /* ****************************************************************** |
| * debug |
| * Part of FSE library |
| * Copyright (c) 2013-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| |
| |
| /* |
| * This module only hosts one global variable |
| * which can be used to dynamically influence the verbosity of traces, |
| * such as DEBUGLOG and RAWLOG |
| */ |
| |
| /**** start inlining debug.h ****/ |
| /* ****************************************************************** |
| * debug |
| * Part of FSE library |
| * Copyright (c) 2013-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| |
| |
| /* |
| * The purpose of this header is to enable debug functions. |
| * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time, |
| * and DEBUG_STATIC_ASSERT() for compile-time. |
| * |
| * By default, DEBUGLEVEL==0, which means run-time debug is disabled. |
| * |
| * Level 1 enables assert() only. |
| * Starting level 2, traces can be generated and pushed to stderr. |
| * The higher the level, the more verbose the traces. |
| * |
| * It's possible to dynamically adjust level using variable g_debug_level, |
| * which is only declared if DEBUGLEVEL>=2, |
| * and is a global variable, not multi-thread protected (use with care) |
| */ |
| |
| #ifndef DEBUG_H_12987983217 |
| #define DEBUG_H_12987983217 |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| |
| /* static assert is triggered at compile time, leaving no runtime artefact. |
| * static assert only works with compile-time constants. |
| * Also, this variant can only be used inside a function. */ |
| #define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1]) |
| |
| |
| /* DEBUGLEVEL is expected to be defined externally, |
| * typically through compiler command line. |
| * Value must be a number. */ |
| #ifndef DEBUGLEVEL |
| # define DEBUGLEVEL 0 |
| #endif |
| |
| |
| /* recommended values for DEBUGLEVEL : |
| * 0 : release mode, no debug, all run-time checks disabled |
| * 1 : enables assert() only, no display |
| * 2 : reserved, for currently active debug path |
| * 3 : events once per object lifetime (CCtx, CDict, etc.) |
| * 4 : events once per frame |
| * 5 : events once per block |
| * 6 : events once per sequence (verbose) |
| * 7+: events at every position (*very* verbose) |
| * |
| * It's generally inconvenient to output traces > 5. |
| * In which case, it's possible to selectively trigger high verbosity levels |
| * by modifying g_debug_level. |
| */ |
| |
| #if (DEBUGLEVEL>=1) |
| # define ZSTD_DEPS_NEED_ASSERT |
| /**** skipping file: zstd_deps.h ****/ |
| #else |
| # ifndef assert /* assert may be already defined, due to prior #include <assert.h> */ |
| # define assert(condition) ((void)0) /* disable assert (default) */ |
| # endif |
| #endif |
| |
| #if (DEBUGLEVEL>=2) |
| # define ZSTD_DEPS_NEED_IO |
| /**** skipping file: zstd_deps.h ****/ |
| extern int g_debuglevel; /* the variable is only declared, |
| it actually lives in debug.c, |
| and is shared by the whole process. |
| It's not thread-safe. |
| It's useful when enabling very verbose levels |
| on selective conditions (such as position in src) */ |
| |
| # define RAWLOG(l, ...) { \ |
| if (l<=g_debuglevel) { \ |
| ZSTD_DEBUG_PRINT(__VA_ARGS__); \ |
| } } |
| # define DEBUGLOG(l, ...) { \ |
| if (l<=g_debuglevel) { \ |
| ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \ |
| ZSTD_DEBUG_PRINT(" \n"); \ |
| } } |
| #else |
| # define RAWLOG(l, ...) {} /* disabled */ |
| # define DEBUGLOG(l, ...) {} /* disabled */ |
| #endif |
| |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| |
| #endif /* DEBUG_H_12987983217 */ |
| /**** ended inlining debug.h ****/ |
| |
| int g_debuglevel = DEBUGLEVEL; |
| /**** ended inlining common/debug.c ****/ |
| /**** start inlining common/entropy_common.c ****/ |
| /* ****************************************************************** |
| * Common functions of New Generation Entropy library |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * - Public forum : https://groups.google.com/forum/#!forum/lz4c |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| |
| /* ************************************* |
| * Dependencies |
| ***************************************/ |
| /**** start inlining mem.h ****/ |
| /* |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| |
| #ifndef MEM_H_MODULE |
| #define MEM_H_MODULE |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| /*-**************************************** |
| * Dependencies |
| ******************************************/ |
| #include <stddef.h> /* size_t, ptrdiff_t */ |
| /**** start inlining compiler.h ****/ |
| /* |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| |
| #ifndef ZSTD_COMPILER_H |
| #define ZSTD_COMPILER_H |
| |
| /*-******************************************************* |
| * Compiler specifics |
| *********************************************************/ |
| /* force inlining */ |
| |
| #if !defined(ZSTD_NO_INLINE) |
| #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ |
| # define INLINE_KEYWORD inline |
| #else |
| # define INLINE_KEYWORD |
| #endif |
| |
| #if defined(__GNUC__) || defined(__ICCARM__) |
| # define FORCE_INLINE_ATTR __attribute__((always_inline)) |
| #elif defined(_MSC_VER) |
| # define FORCE_INLINE_ATTR __forceinline |
| #else |
| # define FORCE_INLINE_ATTR |
| #endif |
| |
| #else |
| |
| #define INLINE_KEYWORD |
| #define FORCE_INLINE_ATTR |
| |
| #endif |
| |
| /** |
| On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). |
| This explictly marks such functions as __cdecl so that the code will still compile |
| if a CC other than __cdecl has been made the default. |
| */ |
| #if defined(_MSC_VER) |
| # define WIN_CDECL __cdecl |
| #else |
| # define WIN_CDECL |
| #endif |
| |
| /** |
| * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant |
| * parameters. They must be inlined for the compiler to eliminate the constant |
| * branches. |
| */ |
| #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR |
| /** |
| * HINT_INLINE is used to help the compiler generate better code. It is *not* |
| * used for "templates", so it can be tweaked based on the compilers |
| * performance. |
| * |
| * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the |
| * always_inline attribute. |
| * |
| * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline |
| * attribute. |
| */ |
| #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 |
| # define HINT_INLINE static INLINE_KEYWORD |
| #else |
| # define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR |
| #endif |
| |
| /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ |
| #if defined(__GNUC__) |
| # define UNUSED_ATTR __attribute__((unused)) |
| #else |
| # define UNUSED_ATTR |
| #endif |
| |
| /* force no inlining */ |
| #ifdef _MSC_VER |
| # define FORCE_NOINLINE static __declspec(noinline) |
| #else |
| # if defined(__GNUC__) || defined(__ICCARM__) |
| # define FORCE_NOINLINE static __attribute__((__noinline__)) |
| # else |
| # define FORCE_NOINLINE static |
| # endif |
| #endif |
| |
| |
| /* target attribute */ |
| #ifndef __has_attribute |
| #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ |
| #endif |
| #if defined(__GNUC__) || defined(__ICCARM__) |
| # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) |
| #else |
| # define TARGET_ATTRIBUTE(target) |
| #endif |
| |
| /* Enable runtime BMI2 dispatch based on the CPU. |
| * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default. |
| */ |
| #ifndef DYNAMIC_BMI2 |
| #if ((defined(__clang__) && __has_attribute(__target__)) \ |
| || (defined(__GNUC__) \ |
| && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \ |
| && (defined(__x86_64__) || defined(_M_X86)) \ |
| && !defined(__BMI2__) |
| # define DYNAMIC_BMI2 1 |
| #else |
| # define DYNAMIC_BMI2 0 |
| #endif |
| #endif |
| |
| /* prefetch |
| * can be disabled, by declaring NO_PREFETCH build macro */ |
| #if defined(NO_PREFETCH) |
| # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ |
| # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ |
| #else |
| # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ |
| # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ |
| # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) |
| # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) |
| # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) |
| # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) |
| # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) |
| # elif defined(__aarch64__) |
| # define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) |
| # define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) |
| # else |
| # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ |
| # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ |
| # endif |
| #endif /* NO_PREFETCH */ |
| |
| #define CACHELINE_SIZE 64 |
| |
| #define PREFETCH_AREA(p, s) { \ |
| const char* const _ptr = (const char*)(p); \ |
| size_t const _size = (size_t)(s); \ |
| size_t _pos; \ |
| for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ |
| PREFETCH_L2(_ptr + _pos); \ |
| } \ |
| } |
| |
| /* vectorization |
| * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */ |
| #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) |
| # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) |
| # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) |
| # else |
| # define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")") |
| # endif |
| #else |
| # define DONT_VECTORIZE |
| #endif |
| |
| /* Tell the compiler that a branch is likely or unlikely. |
| * Only use these macros if it causes the compiler to generate better code. |
| * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc |
| * and clang, please do. |
| */ |
| #if defined(__GNUC__) |
| #define LIKELY(x) (__builtin_expect((x), 1)) |
| #define UNLIKELY(x) (__builtin_expect((x), 0)) |
| #else |
| #define LIKELY(x) (x) |
| #define UNLIKELY(x) (x) |
| #endif |
| |
| /* disable warnings */ |
| #ifdef _MSC_VER /* Visual Studio */ |
| # include <intrin.h> /* For Visual 2005 */ |
| # pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ |
| # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ |
| # pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ |
| # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ |
| # pragma warning(disable : 4324) /* disable: C4324: padded structure */ |
| #endif |
| |
| /*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ |
| #ifndef STATIC_BMI2 |
| # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) |
| # ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 |
| # define STATIC_BMI2 1 |
| # endif |
| # endif |
| #endif |
| |
| #ifndef STATIC_BMI2 |
| #define STATIC_BMI2 0 |
| #endif |
| |
| /* compat. with non-clang compilers */ |
| #ifndef __has_builtin |
| # define __has_builtin(x) 0 |
| #endif |
| |
| /* compat. with non-clang compilers */ |
| #ifndef __has_feature |
| # define __has_feature(x) 0 |
| #endif |
| |
| /* detects whether we are being compiled under msan */ |
| #ifndef ZSTD_MEMORY_SANITIZER |
| # if __has_feature(memory_sanitizer) |
| # define ZSTD_MEMORY_SANITIZER 1 |
| # else |
| # define ZSTD_MEMORY_SANITIZER 0 |
| # endif |
| #endif |
| |
| #if ZSTD_MEMORY_SANITIZER |
| /* Not all platforms that support msan provide sanitizers/msan_interface.h. |
| * We therefore declare the functions we need ourselves, rather than trying to |
| * include the header file... */ |
| #include <stddef.h> /* size_t */ |
| #define ZSTD_DEPS_NEED_STDINT |
| /**** skipping file: zstd_deps.h ****/ |
| |
| /* Make memory region fully initialized (without changing its contents). */ |
| void __msan_unpoison(const volatile void *a, size_t size); |
| |
| /* Make memory region fully uninitialized (without changing its contents). |
| This is a legacy interface that does not update origin information. Use |
| __msan_allocated_memory() instead. */ |
| void __msan_poison(const volatile void *a, size_t size); |
| |
| /* Returns the offset of the first (at least partially) poisoned byte in the |
| memory range, or -1 if the whole range is good. */ |
| intptr_t __msan_test_shadow(const volatile void *x, size_t size); |
| #endif |
| |
| /* detects whether we are being compiled under asan */ |
| #ifndef ZSTD_ADDRESS_SANITIZER |
| # if __has_feature(address_sanitizer) |
| # define ZSTD_ADDRESS_SANITIZER 1 |
| # elif defined(__SANITIZE_ADDRESS__) |
| # define ZSTD_ADDRESS_SANITIZER 1 |
| # else |
| # define ZSTD_ADDRESS_SANITIZER 0 |
| # endif |
| #endif |
| |
| #if ZSTD_ADDRESS_SANITIZER |
| /* Not all platforms that support asan provide sanitizers/asan_interface.h. |
| * We therefore declare the functions we need ourselves, rather than trying to |
| * include the header file... */ |
| #include <stddef.h> /* size_t */ |
| |
| /** |
| * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. |
| * |
| * This memory must be previously allocated by your program. Instrumented |
| * code is forbidden from accessing addresses in this region until it is |
| * unpoisoned. This function is not guaranteed to poison the entire region - |
| * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan |
| * alignment restrictions. |
| * |
| * \note This function is not thread-safe because no two threads can poison or |
| * unpoison memory in the same memory region simultaneously. |
| * |
| * \param addr Start of memory region. |
| * \param size Size of memory region. */ |
| void __asan_poison_memory_region(void const volatile *addr, size_t size); |
| |
| /** |
| * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. |
| * |
| * This memory must be previously allocated by your program. Accessing |
| * addresses in this region is allowed until this region is poisoned again. |
| * This function could unpoison a super-region of <c>[addr, addr+size)</c> due |
| * to ASan alignment restrictions. |
| * |
| * \note This function is not thread-safe because no two threads can |
| * poison or unpoison memory in the same memory region simultaneously. |
| * |
| * \param addr Start of memory region. |
| * \param size Size of memory region. */ |
| void __asan_unpoison_memory_region(void const volatile *addr, size_t size); |
| #endif |
| |
| #endif /* ZSTD_COMPILER_H */ |
| /**** ended inlining compiler.h ****/ |
| /**** skipping file: debug.h ****/ |
| /**** skipping file: zstd_deps.h ****/ |
| |
| |
| /*-**************************************** |
| * Compiler specifics |
| ******************************************/ |
| #if defined(_MSC_VER) /* Visual Studio */ |
| # include <stdlib.h> /* _byteswap_ulong */ |
| # include <intrin.h> /* _byteswap_* */ |
| #endif |
| #if defined(__GNUC__) |
| # define MEM_STATIC static __inline __attribute__((unused)) |
| #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) |
| # define MEM_STATIC static inline |
| #elif defined(_MSC_VER) |
| # define MEM_STATIC static __inline |
| #else |
| # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ |
| #endif |
| |
| /*-************************************************************** |
| * Basic Types |
| *****************************************************************/ |
| #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) |
| # if defined(_AIX) |
| # include <inttypes.h> |
| # else |
| # include <stdint.h> /* intptr_t */ |
| # endif |
| typedef uint8_t BYTE; |
| typedef uint16_t U16; |
| typedef int16_t S16; |
| typedef uint32_t U32; |
| typedef int32_t S32; |
| typedef uint64_t U64; |
| typedef int64_t S64; |
| #else |
| # include <limits.h> |
| #if CHAR_BIT != 8 |
| # error "this implementation requires char to be exactly 8-bit type" |
| #endif |
| typedef unsigned char BYTE; |
| #if USHRT_MAX != 65535 |
| # error "this implementation requires short to be exactly 16-bit type" |
| #endif |
| typedef unsigned short U16; |
| typedef signed short S16; |
| #if UINT_MAX != 4294967295 |
| # error "this implementation requires int to be exactly 32-bit type" |
| #endif |
| typedef unsigned int U32; |
| typedef signed int S32; |
| /* note : there are no limits defined for long long type in C90. |
| * limits exist in C99, however, in such case, <stdint.h> is preferred */ |
| typedef unsigned long long U64; |
| typedef signed long long S64; |
| #endif |
| |
| |
| /*-************************************************************** |
| * Memory I/O API |
| *****************************************************************/ |
| /*=== Static platform detection ===*/ |
| MEM_STATIC unsigned MEM_32bits(void); |
| MEM_STATIC unsigned MEM_64bits(void); |
| MEM_STATIC unsigned MEM_isLittleEndian(void); |
| |
| /*=== Native unaligned read/write ===*/ |
| MEM_STATIC U16 MEM_read16(const void* memPtr); |
| MEM_STATIC U32 MEM_read32(const void* memPtr); |
| MEM_STATIC U64 MEM_read64(const void* memPtr); |
| MEM_STATIC size_t MEM_readST(const void* memPtr); |
| |
| MEM_STATIC void MEM_write16(void* memPtr, U16 value); |
| MEM_STATIC void MEM_write32(void* memPtr, U32 value); |
| MEM_STATIC void MEM_write64(void* memPtr, U64 value); |
| |
| /*=== Little endian unaligned read/write ===*/ |
| MEM_STATIC U16 MEM_readLE16(const void* memPtr); |
| MEM_STATIC U32 MEM_readLE24(const void* memPtr); |
| MEM_STATIC U32 MEM_readLE32(const void* memPtr); |
| MEM_STATIC U64 MEM_readLE64(const void* memPtr); |
| MEM_STATIC size_t MEM_readLEST(const void* memPtr); |
| |
| MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); |
| MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); |
| MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); |
| MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); |
| MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); |
| |
| /*=== Big endian unaligned read/write ===*/ |
| MEM_STATIC U32 MEM_readBE32(const void* memPtr); |
| MEM_STATIC U64 MEM_readBE64(const void* memPtr); |
| MEM_STATIC size_t MEM_readBEST(const void* memPtr); |
| |
| MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); |
| MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); |
| MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); |
| |
| /*=== Byteswap ===*/ |
| MEM_STATIC U32 MEM_swap32(U32 in); |
| MEM_STATIC U64 MEM_swap64(U64 in); |
| MEM_STATIC size_t MEM_swapST(size_t in); |
| |
| |
| /*-************************************************************** |
| * Memory I/O Implementation |
| *****************************************************************/ |
| /* MEM_FORCE_MEMORY_ACCESS : |
| * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. |
| * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. |
| * The below switch allow to select different access method for improved performance. |
| * Method 0 (default) : use `memcpy()`. Safe and portable. |
| * Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable). |
| * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. |
| * Method 2 : direct access. This method is portable but violate C standard. |
| * It can generate buggy code on targets depending on alignment. |
| * In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6) |
| * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. |
| * Prefer these methods in priority order (0 > 1 > 2) |
| */ |
| #ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ |
| # if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) |
| # define MEM_FORCE_MEMORY_ACCESS 2 |
| # elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__) |
| # define MEM_FORCE_MEMORY_ACCESS 1 |
| # endif |
| #endif |
| |
| MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; } |
| MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; } |
| |
| MEM_STATIC unsigned MEM_isLittleEndian(void) |
| { |
| const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ |
| return one.c[0]; |
| } |
| |
| #if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2) |
| |
| /* violates C standard, by lying on structure alignment. |
| Only use if no other choice to achieve best performance on target platform */ |
| MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; } |
| MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; } |
| MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; } |
| MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; } |
| |
| MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } |
| MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } |
| MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; } |
| |
| #elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1) |
| |
| /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ |
| /* currently only defined for gcc and icc */ |
| #if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32)) |
| __pragma( pack(push, 1) ) |
| typedef struct { U16 v; } unalign16; |
| typedef struct { U32 v; } unalign32; |
| typedef struct { U64 v; } unalign64; |
| typedef struct { size_t v; } unalignArch; |
| __pragma( pack(pop) ) |
| #else |
| typedef struct { U16 v; } __attribute__((packed)) unalign16; |
| typedef struct { U32 v; } __attribute__((packed)) unalign32; |
| typedef struct { U64 v; } __attribute__((packed)) unalign64; |
| typedef struct { size_t v; } __attribute__((packed)) unalignArch; |
| #endif |
| |
| MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; } |
| MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; } |
| MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; } |
| MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; } |
| |
| MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; } |
| MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; } |
| MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; } |
| |
| #else |
| |
| /* default method, safe and standard. |
| can sometimes prove slower */ |
| |
| MEM_STATIC U16 MEM_read16(const void* memPtr) |
| { |
| U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; |
| } |
| |
| MEM_STATIC U32 MEM_read32(const void* memPtr) |
| { |
| U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; |
| } |
| |
| MEM_STATIC U64 MEM_read64(const void* memPtr) |
| { |
| U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; |
| } |
| |
| MEM_STATIC size_t MEM_readST(const void* memPtr) |
| { |
| size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; |
| } |
| |
| MEM_STATIC void MEM_write16(void* memPtr, U16 value) |
| { |
| ZSTD_memcpy(memPtr, &value, sizeof(value)); |
| } |
| |
| MEM_STATIC void MEM_write32(void* memPtr, U32 value) |
| { |
| ZSTD_memcpy(memPtr, &value, sizeof(value)); |
| } |
| |
| MEM_STATIC void MEM_write64(void* memPtr, U64 value) |
| { |
| ZSTD_memcpy(memPtr, &value, sizeof(value)); |
| } |
| |
| #endif /* MEM_FORCE_MEMORY_ACCESS */ |
| |
| MEM_STATIC U32 MEM_swap32(U32 in) |
| { |
| #if defined(_MSC_VER) /* Visual Studio */ |
| return _byteswap_ulong(in); |
| #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \ |
| || (defined(__clang__) && __has_builtin(__builtin_bswap32)) |
| return __builtin_bswap32(in); |
| #else |
| return ((in << 24) & 0xff000000 ) | |
| ((in << 8) & 0x00ff0000 ) | |
| ((in >> 8) & 0x0000ff00 ) | |
| ((in >> 24) & 0x000000ff ); |
| #endif |
| } |
| |
| MEM_STATIC U64 MEM_swap64(U64 in) |
| { |
| #if defined(_MSC_VER) /* Visual Studio */ |
| return _byteswap_uint64(in); |
| #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \ |
| || (defined(__clang__) && __has_builtin(__builtin_bswap64)) |
| return __builtin_bswap64(in); |
| #else |
| return ((in << 56) & 0xff00000000000000ULL) | |
| ((in << 40) & 0x00ff000000000000ULL) | |
| ((in << 24) & 0x0000ff0000000000ULL) | |
| ((in << 8) & 0x000000ff00000000ULL) | |
| ((in >> 8) & 0x00000000ff000000ULL) | |
| ((in >> 24) & 0x0000000000ff0000ULL) | |
| ((in >> 40) & 0x000000000000ff00ULL) | |
| ((in >> 56) & 0x00000000000000ffULL); |
| #endif |
| } |
| |
| MEM_STATIC size_t MEM_swapST(size_t in) |
| { |
| if (MEM_32bits()) |
| return (size_t)MEM_swap32((U32)in); |
| else |
| return (size_t)MEM_swap64((U64)in); |
| } |
| |
| /*=== Little endian r/w ===*/ |
| |
| MEM_STATIC U16 MEM_readLE16(const void* memPtr) |
| { |
| if (MEM_isLittleEndian()) |
| return MEM_read16(memPtr); |
| else { |
| const BYTE* p = (const BYTE*)memPtr; |
| return (U16)(p[0] + (p[1]<<8)); |
| } |
| } |
| |
| MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val) |
| { |
| if (MEM_isLittleEndian()) { |
| MEM_write16(memPtr, val); |
| } else { |
| BYTE* p = (BYTE*)memPtr; |
| p[0] = (BYTE)val; |
| p[1] = (BYTE)(val>>8); |
| } |
| } |
| |
| MEM_STATIC U32 MEM_readLE24(const void* memPtr) |
| { |
| return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16); |
| } |
| |
| MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val) |
| { |
| MEM_writeLE16(memPtr, (U16)val); |
| ((BYTE*)memPtr)[2] = (BYTE)(val>>16); |
| } |
| |
| MEM_STATIC U32 MEM_readLE32(const void* memPtr) |
| { |
| if (MEM_isLittleEndian()) |
| return MEM_read32(memPtr); |
| else |
| return MEM_swap32(MEM_read32(memPtr)); |
| } |
| |
| MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32) |
| { |
| if (MEM_isLittleEndian()) |
| MEM_write32(memPtr, val32); |
| else |
| MEM_write32(memPtr, MEM_swap32(val32)); |
| } |
| |
| MEM_STATIC U64 MEM_readLE64(const void* memPtr) |
| { |
| if (MEM_isLittleEndian()) |
| return MEM_read64(memPtr); |
| else |
| return MEM_swap64(MEM_read64(memPtr)); |
| } |
| |
| MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64) |
| { |
| if (MEM_isLittleEndian()) |
| MEM_write64(memPtr, val64); |
| else |
| MEM_write64(memPtr, MEM_swap64(val64)); |
| } |
| |
| MEM_STATIC size_t MEM_readLEST(const void* memPtr) |
| { |
| if (MEM_32bits()) |
| return (size_t)MEM_readLE32(memPtr); |
| else |
| return (size_t)MEM_readLE64(memPtr); |
| } |
| |
| MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val) |
| { |
| if (MEM_32bits()) |
| MEM_writeLE32(memPtr, (U32)val); |
| else |
| MEM_writeLE64(memPtr, (U64)val); |
| } |
| |
| /*=== Big endian r/w ===*/ |
| |
| MEM_STATIC U32 MEM_readBE32(const void* memPtr) |
| { |
| if (MEM_isLittleEndian()) |
| return MEM_swap32(MEM_read32(memPtr)); |
| else |
| return MEM_read32(memPtr); |
| } |
| |
| MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32) |
| { |
| if (MEM_isLittleEndian()) |
| MEM_write32(memPtr, MEM_swap32(val32)); |
| else |
| MEM_write32(memPtr, val32); |
| } |
| |
| MEM_STATIC U64 MEM_readBE64(const void* memPtr) |
| { |
| if (MEM_isLittleEndian()) |
| return MEM_swap64(MEM_read64(memPtr)); |
| else |
| return MEM_read64(memPtr); |
| } |
| |
| MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64) |
| { |
| if (MEM_isLittleEndian()) |
| MEM_write64(memPtr, MEM_swap64(val64)); |
| else |
| MEM_write64(memPtr, val64); |
| } |
| |
| MEM_STATIC size_t MEM_readBEST(const void* memPtr) |
| { |
| if (MEM_32bits()) |
| return (size_t)MEM_readBE32(memPtr); |
| else |
| return (size_t)MEM_readBE64(memPtr); |
| } |
| |
| MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val) |
| { |
| if (MEM_32bits()) |
| MEM_writeBE32(memPtr, (U32)val); |
| else |
| MEM_writeBE64(memPtr, (U64)val); |
| } |
| |
| /* code only tested on 32 and 64 bits systems */ |
| MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } |
| |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| |
| #endif /* MEM_H_MODULE */ |
| /**** ended inlining mem.h ****/ |
| /**** start inlining error_private.h ****/ |
| /* |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| |
| /* Note : this module is expected to remain private, do not expose it */ |
| |
| #ifndef ERROR_H_MODULE |
| #define ERROR_H_MODULE |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| |
| /* **************************************** |
| * Dependencies |
| ******************************************/ |
| /**** skipping file: zstd_deps.h ****/ |
| /**** start inlining zstd_errors.h ****/ |
| /* |
| * Copyright (c) 2016-2021, Yann Collet, Facebook, Inc. |
| * All rights reserved. |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| */ |
| |
| #ifndef ZSTD_ERRORS_H_398273423 |
| #define ZSTD_ERRORS_H_398273423 |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| /*===== dependency =====*/ |
| #include <stddef.h> /* size_t */ |
| |
| |
| /* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ |
| #ifndef ZSTDERRORLIB_VISIBILITY |
| # if defined(__GNUC__) && (__GNUC__ >= 4) |
| # define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default"))) |
| # else |
| # define ZSTDERRORLIB_VISIBILITY |
| # endif |
| #endif |
| #if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1) |
| # define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY |
| #elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1) |
| # define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ |
| #else |
| # define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY |
| #endif |
| |
| /*-********************************************* |
| * Error codes list |
| *-********************************************* |
| * Error codes _values_ are pinned down since v1.3.1 only. |
| * Therefore, don't rely on values if you may link to any version < v1.3.1. |
| * |
| * Only values < 100 are considered stable. |
| * |
| * note 1 : this API shall be used with static linking only. |
| * dynamic linking is not yet officially supported. |
| * note 2 : Prefer relying on the enum than on its value whenever possible |
| * This is the only supported way to use the error list < v1.3.1 |
| * note 3 : ZSTD_isError() is always correct, whatever the library version. |
| **********************************************/ |
| typedef enum { |
| ZSTD_error_no_error = 0, |
| ZSTD_error_GENERIC = 1, |
| ZSTD_error_prefix_unknown = 10, |
| ZSTD_error_version_unsupported = 12, |
| ZSTD_error_frameParameter_unsupported = 14, |
| ZSTD_error_frameParameter_windowTooLarge = 16, |
| ZSTD_error_corruption_detected = 20, |
| ZSTD_error_checksum_wrong = 22, |
| ZSTD_error_dictionary_corrupted = 30, |
| ZSTD_error_dictionary_wrong = 32, |
| ZSTD_error_dictionaryCreation_failed = 34, |
| ZSTD_error_parameter_unsupported = 40, |
| ZSTD_error_parameter_outOfBound = 42, |
| ZSTD_error_tableLog_tooLarge = 44, |
| ZSTD_error_maxSymbolValue_tooLarge = 46, |
| ZSTD_error_maxSymbolValue_tooSmall = 48, |
| ZSTD_error_stage_wrong = 60, |
| ZSTD_error_init_missing = 62, |
| ZSTD_error_memory_allocation = 64, |
| ZSTD_error_workSpace_tooSmall= 66, |
| ZSTD_error_dstSize_tooSmall = 70, |
| ZSTD_error_srcSize_wrong = 72, |
| ZSTD_error_dstBuffer_null = 74, |
| /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */ |
| ZSTD_error_frameIndex_tooLarge = 100, |
| ZSTD_error_seekableIO = 102, |
| ZSTD_error_dstBuffer_wrong = 104, |
| ZSTD_error_srcBuffer_wrong = 105, |
| ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ |
| } ZSTD_ErrorCode; |
| |
| /*! ZSTD_getErrorCode() : |
| convert a `size_t` function result into a `ZSTD_ErrorCode` enum type, |
| which can be used to compare with enum list published above */ |
| ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); |
| ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */ |
| |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| |
| #endif /* ZSTD_ERRORS_H_398273423 */ |
| /**** ended inlining zstd_errors.h ****/ |
| |
| |
| /* **************************************** |
| * Compiler-specific |
| ******************************************/ |
| #if defined(__GNUC__) |
| # define ERR_STATIC static __attribute__((unused)) |
| #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) |
| # define ERR_STATIC static inline |
| #elif defined(_MSC_VER) |
| # define ERR_STATIC static __inline |
| #else |
| # define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ |
| #endif |
| |
| |
| /*-**************************************** |
| * Customization (error_public.h) |
| ******************************************/ |
| typedef ZSTD_ErrorCode ERR_enum; |
| #define PREFIX(name) ZSTD_error_##name |
| |
| |
| /*-**************************************** |
| * Error codes handling |
| ******************************************/ |
| #undef ERROR /* already defined on Visual Studio */ |
| #define ERROR(name) ZSTD_ERROR(name) |
| #define ZSTD_ERROR(name) ((size_t)-PREFIX(name)) |
| |
| ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } |
| |
| ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } |
| |
| /* check and forward error code */ |
| #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e |
| #define CHECK_F(f) { CHECK_V_F(_var_err__, f); } |
| |
| |
| /*-**************************************** |
| * Error Strings |
| ******************************************/ |
| |
| const char* ERR_getErrorString(ERR_enum code); /* error_private.c */ |
| |
| ERR_STATIC const char* ERR_getErrorName(size_t code) |
| { |
| return ERR_getErrorString(ERR_getErrorCode(code)); |
| } |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| |
| #endif /* ERROR_H_MODULE */ |
| /**** ended inlining error_private.h ****/ |
| #define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ |
| /**** start inlining fse.h ****/ |
| /* ****************************************************************** |
| * FSE : Finite State Entropy codec |
| * Public Prototypes declaration |
| * Copyright (c) 2013-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| #ifndef FSE_H |
| #define FSE_H |
| |
| |
| /*-***************************************** |
| * Dependencies |
| ******************************************/ |
| /**** skipping file: zstd_deps.h ****/ |
| |
| |
| /*-***************************************** |
| * FSE_PUBLIC_API : control library symbols visibility |
| ******************************************/ |
| #if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) |
| # define FSE_PUBLIC_API __attribute__ ((visibility ("default"))) |
| #elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ |
| # define FSE_PUBLIC_API __declspec(dllexport) |
| #elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) |
| # define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ |
| #else |
| # define FSE_PUBLIC_API |
| #endif |
| |
| /*------ Version ------*/ |
| #define FSE_VERSION_MAJOR 0 |
| #define FSE_VERSION_MINOR 9 |
| #define FSE_VERSION_RELEASE 0 |
| |
| #define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE |
| #define FSE_QUOTE(str) #str |
| #define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str) |
| #define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION) |
| |
| #define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE) |
| FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */ |
| |
| |
| /*-**************************************** |
| * FSE simple functions |
| ******************************************/ |
| /*! FSE_compress() : |
| Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'. |
| 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize). |
| @return : size of compressed data (<= dstCapacity). |
| Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! |
| if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead. |
| if FSE_isError(return), compression failed (more details using FSE_getErrorName()) |
| */ |
| FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity, |
| const void* src, size_t srcSize); |
| |
| /*! FSE_decompress(): |
| Decompress FSE data from buffer 'cSrc', of size 'cSrcSize', |
| into already allocated destination buffer 'dst', of size 'dstCapacity'. |
| @return : size of regenerated data (<= maxDstSize), |
| or an error code, which can be tested using FSE_isError() . |
| |
| ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!! |
| Why ? : making this distinction requires a header. |
| Header management is intentionally delegated to the user layer, which can better manage special cases. |
| */ |
| FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity, |
| const void* cSrc, size_t cSrcSize); |
| |
| |
| /*-***************************************** |
| * Tool functions |
| ******************************************/ |
| FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */ |
| |
| /* Error Management */ |
| FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ |
| FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */ |
| |
| |
| /*-***************************************** |
| * FSE advanced functions |
| ******************************************/ |
| /*! FSE_compress2() : |
| Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog' |
| Both parameters can be defined as '0' to mean : use default value |
| @return : size of compressed data |
| Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!! |
| if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression. |
| if FSE_isError(return), it's an error code. |
| */ |
| FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); |
| |
| |
| /*-***************************************** |
| * FSE detailed API |
| ******************************************/ |
| /*! |
| FSE_compress() does the following: |
| 1. count symbol occurrence from source[] into table count[] (see hist.h) |
| 2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog) |
| 3. save normalized counters to memory buffer using writeNCount() |
| 4. build encoding table 'CTable' from normalized counters |
| 5. encode the data stream using encoding table 'CTable' |
| |
| FSE_decompress() does the following: |
| 1. read normalized counters with readNCount() |
| 2. build decoding table 'DTable' from normalized counters |
| 3. decode the data stream using decoding table 'DTable' |
| |
| The following API allows targeting specific sub-functions for advanced tasks. |
| For example, it's possible to compress several blocks using the same 'CTable', |
| or to save and provide normalized distribution using external method. |
| */ |
| |
| /* *** COMPRESSION *** */ |
| |
| /*! FSE_optimalTableLog(): |
| dynamically downsize 'tableLog' when conditions are met. |
| It saves CPU time, by using smaller tables, while preserving or even improving compression ratio. |
| @return : recommended tableLog (necessarily <= 'maxTableLog') */ |
| FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); |
| |
| /*! FSE_normalizeCount(): |
| normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) |
| 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). |
| useLowProbCount is a boolean parameter which trades off compressed size for |
| faster header decoding. When it is set to 1, the compressed data will be slightly |
| smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be |
| faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0 |
| is a good default, since header deserialization makes a big speed difference. |
| Otherwise, useLowProbCount=1 is a good default, since the speed difference is small. |
| @return : tableLog, |
| or an errorCode, which can be tested using FSE_isError() */ |
| FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, |
| const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount); |
| |
| /*! FSE_NCountWriteBound(): |
| Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. |
| Typically useful for allocation purpose. */ |
| FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog); |
| |
| /*! FSE_writeNCount(): |
| Compactly save 'normalizedCounter' into 'buffer'. |
| @return : size of the compressed table, |
| or an errorCode, which can be tested using FSE_isError(). */ |
| FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, |
| const short* normalizedCounter, |
| unsigned maxSymbolValue, unsigned tableLog); |
| |
| /*! Constructor and Destructor of FSE_CTable. |
| Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */ |
| typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ |
| FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog); |
| FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct); |
| |
| /*! FSE_buildCTable(): |
| Builds `ct`, which must be already allocated, using FSE_createCTable(). |
| @return : 0, or an errorCode, which can be tested using FSE_isError() */ |
| FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); |
| |
| /*! FSE_compress_usingCTable(): |
| Compress `src` using `ct` into `dst` which must be already allocated. |
| @return : size of compressed data (<= `dstCapacity`), |
| or 0 if compressed data could not fit into `dst`, |
| or an errorCode, which can be tested using FSE_isError() */ |
| FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct); |
| |
| /*! |
| Tutorial : |
| ---------- |
| The first step is to count all symbols. FSE_count() does this job very fast. |
| Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells. |
| 'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0] |
| maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value) |
| FSE_count() will return the number of occurrence of the most frequent symbol. |
| This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility. |
| If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). |
| |
| The next step is to normalize the frequencies. |
| FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'. |
| It also guarantees a minimum of 1 to any Symbol with frequency >= 1. |
| You can use 'tableLog'==0 to mean "use default tableLog value". |
| If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(), |
| which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default"). |
| |
| The result of FSE_normalizeCount() will be saved into a table, |
| called 'normalizedCounter', which is a table of signed short. |
| 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells. |
| The return value is tableLog if everything proceeded as expected. |
| It is 0 if there is a single symbol within distribution. |
| If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()). |
| |
| 'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount(). |
| 'buffer' must be already allocated. |
| For guaranteed success, buffer size must be at least FSE_headerBound(). |
| The result of the function is the number of bytes written into 'buffer'. |
| If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small). |
| |
| 'normalizedCounter' can then be used to create the compression table 'CTable'. |
| The space required by 'CTable' must be already allocated, using FSE_createCTable(). |
| You can then use FSE_buildCTable() to fill 'CTable'. |
| If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()). |
| |
| 'CTable' can then be used to compress 'src', with FSE_compress_usingCTable(). |
| Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize' |
| The function returns the size of compressed data (without header), necessarily <= `dstCapacity`. |
| If it returns '0', compressed data could not fit into 'dst'. |
| If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). |
| */ |
| |
| |
| /* *** DECOMPRESSION *** */ |
| |
| /*! FSE_readNCount(): |
| Read compactly saved 'normalizedCounter' from 'rBuffer'. |
| @return : size read from 'rBuffer', |
| or an errorCode, which can be tested using FSE_isError(). |
| maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ |
| FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, |
| unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, |
| const void* rBuffer, size_t rBuffSize); |
| |
| /*! FSE_readNCount_bmi2(): |
| * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise. |
| */ |
| FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter, |
| unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, |
| const void* rBuffer, size_t rBuffSize, int bmi2); |
| |
| /*! Constructor and Destructor of FSE_DTable. |
| Note that its size depends on 'tableLog' */ |
| typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ |
| FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog); |
| FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt); |
| |
| /*! FSE_buildDTable(): |
| Builds 'dt', which must be already allocated, using FSE_createDTable(). |
| return : 0, or an errorCode, which can be tested using FSE_isError() */ |
| FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); |
| |
| /*! FSE_decompress_usingDTable(): |
| Decompress compressed source `cSrc` of size `cSrcSize` using `dt` |
| into `dst` which must be already allocated. |
| @return : size of regenerated data (necessarily <= `dstCapacity`), |
| or an errorCode, which can be tested using FSE_isError() */ |
| FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); |
| |
| /*! |
| Tutorial : |
| ---------- |
| (Note : these functions only decompress FSE-compressed blocks. |
| If block is uncompressed, use memcpy() instead |
| If block is a single repeated byte, use memset() instead ) |
| |
| The first step is to obtain the normalized frequencies of symbols. |
| This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount(). |
| 'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short. |
| In practice, that means it's necessary to know 'maxSymbolValue' beforehand, |
| or size the table to handle worst case situations (typically 256). |
| FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'. |
| The result of FSE_readNCount() is the number of bytes read from 'rBuffer'. |
| Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that. |
| If there is an error, the function will return an error code, which can be tested using FSE_isError(). |
| |
| The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'. |
| This is performed by the function FSE_buildDTable(). |
| The space required by 'FSE_DTable' must be already allocated using FSE_createDTable(). |
| If there is an error, the function will return an error code, which can be tested using FSE_isError(). |
| |
| `FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable(). |
| `cSrcSize` must be strictly correct, otherwise decompression will fail. |
| FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`). |
| If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) |
| */ |
| |
| #endif /* FSE_H */ |
| |
| #if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY) |
| #define FSE_H_FSE_STATIC_LINKING_ONLY |
| |
| /* *** Dependency *** */ |
| /**** start inlining bitstream.h ****/ |
| /* ****************************************************************** |
| * bitstream |
| * Part of FSE library |
| * Copyright (c) 2013-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| #ifndef BITSTREAM_H_MODULE |
| #define BITSTREAM_H_MODULE |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| /* |
| * This API consists of small unitary functions, which must be inlined for best performance. |
| * Since link-time-optimization is not available for all compilers, |
| * these functions are defined into a .h to be included. |
| */ |
| |
| /*-**************************************** |
| * Dependencies |
| ******************************************/ |
| /**** skipping file: mem.h ****/ |
| /**** skipping file: compiler.h ****/ |
| /**** skipping file: debug.h ****/ |
| /**** skipping file: error_private.h ****/ |
| |
| |
| /*========================================= |
| * Target specific |
| =========================================*/ |
| #ifndef ZSTD_NO_INTRINSICS |
| # if defined(__BMI__) && defined(__GNUC__) |
| # include <immintrin.h> /* support for bextr (experimental) */ |
| # elif defined(__ICCARM__) |
| # include <intrinsics.h> |
| # endif |
| #endif |
| |
| #define STREAM_ACCUMULATOR_MIN_32 25 |
| #define STREAM_ACCUMULATOR_MIN_64 57 |
| #define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64)) |
| |
| |
| /*-****************************************** |
| * bitStream encoding API (write forward) |
| ********************************************/ |
| /* bitStream can mix input from multiple sources. |
| * A critical property of these streams is that they encode and decode in **reverse** direction. |
| * So the first bit sequence you add will be the last to be read, like a LIFO stack. |
| */ |
| typedef struct { |
| size_t bitContainer; |
| unsigned bitPos; |
| char* startPtr; |
| char* ptr; |
| char* endPtr; |
| } BIT_CStream_t; |
| |
| MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity); |
| MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits); |
| MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC); |
| MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); |
| |
| /* Start with initCStream, providing the size of buffer to write into. |
| * bitStream will never write outside of this buffer. |
| * `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code. |
| * |
| * bits are first added to a local register. |
| * Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems. |
| * Writing data into memory is an explicit operation, performed by the flushBits function. |
| * Hence keep track how many bits are potentially stored into local register to avoid register overflow. |
| * After a flushBits, a maximum of 7 bits might still be stored into local register. |
| * |
| * Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers. |
| * |
| * Last operation is to close the bitStream. |
| * The function returns the final size of CStream in bytes. |
| * If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable) |
| */ |
| |
| |
| /*-******************************************** |
| * bitStream decoding API (read backward) |
| **********************************************/ |
| typedef struct { |
| size_t bitContainer; |
| unsigned bitsConsumed; |
| const char* ptr; |
| const char* start; |
| const char* limitPtr; |
| } BIT_DStream_t; |
| |
| typedef enum { BIT_DStream_unfinished = 0, |
| BIT_DStream_endOfBuffer = 1, |
| BIT_DStream_completed = 2, |
| BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ |
| /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ |
| |
| MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); |
| MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits); |
| MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD); |
| MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD); |
| |
| |
| /* Start by invoking BIT_initDStream(). |
| * A chunk of the bitStream is then stored into a local register. |
| * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). |
| * You can then retrieve bitFields stored into the local register, **in reverse order**. |
| * Local register is explicitly reloaded from memory by the BIT_reloadDStream() method. |
| * A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished. |
| * Otherwise, it can be less than that, so proceed accordingly. |
| * Checking if DStream has reached its end can be performed with BIT_endOfDStream(). |
| */ |
| |
| |
| /*-**************************************** |
| * unsafe API |
| ******************************************/ |
| MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits); |
| /* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */ |
| |
| MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); |
| /* unsafe version; does not check buffer overflow */ |
| |
| MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); |
| /* faster, but works only if nbBits >= 1 */ |
| |
| |
| |
| /*-************************************************************** |
| * Internal functions |
| ****************************************************************/ |
| MEM_STATIC unsigned BIT_highbit32 (U32 val) |
| { |
| assert(val != 0); |
| { |
| # if defined(_MSC_VER) /* Visual */ |
| # if STATIC_BMI2 == 1 |
| return _lzcnt_u32(val) ^ 31; |
| # else |
| unsigned long r = 0; |
| return _BitScanReverse(&r, val) ? (unsigned)r : 0; |
| # endif |
| # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ |
| return __builtin_clz (val) ^ 31; |
| # elif defined(__ICCARM__) /* IAR Intrinsic */ |
| return 31 - __CLZ(val); |
| # else /* Software version */ |
| static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, |
| 11, 14, 16, 18, 22, 25, 3, 30, |
| 8, 12, 20, 28, 15, 17, 24, 7, |
| 19, 27, 23, 6, 26, 5, 4, 31 }; |
| U32 v = val; |
| v |= v >> 1; |
| v |= v >> 2; |
| v |= v >> 4; |
| v |= v >> 8; |
| v |= v >> 16; |
| return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27]; |
| # endif |
| } |
| } |
| |
| /*===== Local Constants =====*/ |
| static const unsigned BIT_mask[] = { |
| 0, 1, 3, 7, 0xF, 0x1F, |
| 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, |
| 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, |
| 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, |
| 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF, |
| 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */ |
| #define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0])) |
| |
| /*-************************************************************** |
| * bitStream encoding |
| ****************************************************************/ |
| /*! BIT_initCStream() : |
| * `dstCapacity` must be > sizeof(size_t) |
| * @return : 0 if success, |
| * otherwise an error code (can be tested using ERR_isError()) */ |
| MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, |
| void* startPtr, size_t dstCapacity) |
| { |
| bitC->bitContainer = 0; |
| bitC->bitPos = 0; |
| bitC->startPtr = (char*)startPtr; |
| bitC->ptr = bitC->startPtr; |
| bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer); |
| if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall); |
| return 0; |
| } |
| |
| /*! BIT_addBits() : |
| * can add up to 31 bits into `bitC`. |
| * Note : does not check for register overflow ! */ |
| MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, |
| size_t value, unsigned nbBits) |
| { |
| DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32); |
| assert(nbBits < BIT_MASK_SIZE); |
| assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); |
| bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; |
| bitC->bitPos += nbBits; |
| } |
| |
| /*! BIT_addBitsFast() : |
| * works only if `value` is _clean_, |
| * meaning all high bits above nbBits are 0 */ |
| MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, |
| size_t value, unsigned nbBits) |
| { |
| assert((value>>nbBits) == 0); |
| assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); |
| bitC->bitContainer |= value << bitC->bitPos; |
| bitC->bitPos += nbBits; |
| } |
| |
| /*! BIT_flushBitsFast() : |
| * assumption : bitContainer has not overflowed |
| * unsafe version; does not check buffer overflow */ |
| MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC) |
| { |
| size_t const nbBytes = bitC->bitPos >> 3; |
| assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); |
| assert(bitC->ptr <= bitC->endPtr); |
| MEM_writeLEST(bitC->ptr, bitC->bitContainer); |
| bitC->ptr += nbBytes; |
| bitC->bitPos &= 7; |
| bitC->bitContainer >>= nbBytes*8; |
| } |
| |
| /*! BIT_flushBits() : |
| * assumption : bitContainer has not overflowed |
| * safe version; check for buffer overflow, and prevents it. |
| * note : does not signal buffer overflow. |
| * overflow will be revealed later on using BIT_closeCStream() */ |
| MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC) |
| { |
| size_t const nbBytes = bitC->bitPos >> 3; |
| assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8); |
| assert(bitC->ptr <= bitC->endPtr); |
| MEM_writeLEST(bitC->ptr, bitC->bitContainer); |
| bitC->ptr += nbBytes; |
| if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; |
| bitC->bitPos &= 7; |
| bitC->bitContainer >>= nbBytes*8; |
| } |
| |
| /*! BIT_closeCStream() : |
| * @return : size of CStream, in bytes, |
| * or 0 if it could not fit into dstBuffer */ |
| MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) |
| { |
| BIT_addBitsFast(bitC, 1, 1); /* endMark */ |
| BIT_flushBits(bitC); |
| if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */ |
| return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0); |
| } |
| |
| |
| /*-******************************************************** |
| * bitStream decoding |
| **********************************************************/ |
| /*! BIT_initDStream() : |
| * Initialize a BIT_DStream_t. |
| * `bitD` : a pointer to an already allocated BIT_DStream_t structure. |
| * `srcSize` must be the *exact* size of the bitStream, in bytes. |
| * @return : size of stream (== srcSize), or an errorCode if a problem is detected |
| */ |
| MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) |
| { |
| if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } |
| |
| bitD->start = (const char*)srcBuffer; |
| bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer); |
| |
| if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */ |
| bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer); |
| bitD->bitContainer = MEM_readLEST(bitD->ptr); |
| { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; |
| bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */ |
| if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ } |
| } else { |
| bitD->ptr = bitD->start; |
| bitD->bitContainer = *(const BYTE*)(bitD->start); |
| switch(srcSize) |
| { |
| case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16); |
| /* fall-through */ |
| |
| case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24); |
| /* fall-through */ |
| |
| case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32); |
| /* fall-through */ |
| |
| case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; |
| /* fall-through */ |
| |
| case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; |
| /* fall-through */ |
| |
| case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8; |
| /* fall-through */ |
| |
| default: break; |
| } |
| { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; |
| bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; |
| if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */ |
| } |
| bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8; |
| } |
| |
| return srcSize; |
| } |
| |
| MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start) |
| { |
| return bitContainer >> start; |
| } |
| |
| MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) |
| { |
| U32 const regMask = sizeof(bitContainer)*8 - 1; |
| /* if start > regMask, bitstream is corrupted, and result is undefined */ |
| assert(nbBits < BIT_MASK_SIZE); |
| return (bitContainer >> (start & regMask)) & BIT_mask[nbBits]; |
| } |
| |
| MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) |
| { |
| #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 |
| return _bzhi_u64(bitContainer, nbBits); |
| #else |
| assert(nbBits < BIT_MASK_SIZE); |
| return bitContainer & BIT_mask[nbBits]; |
| #endif |
| } |
| |
| /*! BIT_lookBits() : |
| * Provides next n bits from local register. |
| * local register is not modified. |
| * On 32-bits, maxNbBits==24. |
| * On 64-bits, maxNbBits==56. |
| * @return : value extracted */ |
| MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) |
| { |
| /* arbitrate between double-shift and shift+mask */ |
| #if 1 |
| /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8, |
| * bitstream is likely corrupted, and result is undefined */ |
| return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits); |
| #else |
| /* this code path is slower on my os-x laptop */ |
| U32 const regMask = sizeof(bitD->bitContainer)*8 - 1; |
| return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask); |
| #endif |
| } |
| |
| /*! BIT_lookBitsFast() : |
| * unsafe version; only works if nbBits >= 1 */ |
| MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) |
| { |
| U32 const regMask = sizeof(bitD->bitContainer)*8 - 1; |
| assert(nbBits >= 1); |
| return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask); |
| } |
| |
| MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) |
| { |
| bitD->bitsConsumed += nbBits; |
| } |
| |
| /*! BIT_readBits() : |
| * Read (consume) next n bits from local register and update. |
| * Pay attention to not read more than nbBits contained into local register. |
| * @return : extracted value. */ |
| MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) |
| { |
| size_t const value = BIT_lookBits(bitD, nbBits); |
| BIT_skipBits(bitD, nbBits); |
| return value; |
| } |
| |
| /*! BIT_readBitsFast() : |
| * unsafe version; only works only if nbBits >= 1 */ |
| MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits) |
| { |
| size_t const value = BIT_lookBitsFast(bitD, nbBits); |
| assert(nbBits >= 1); |
| BIT_skipBits(bitD, nbBits); |
| return value; |
| } |
| |
| /*! BIT_reloadDStreamFast() : |
| * Similar to BIT_reloadDStream(), but with two differences: |
| * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold! |
| * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this |
| * point you must use BIT_reloadDStream() to reload. |
| */ |
| MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD) |
| { |
| if (UNLIKELY(bitD->ptr < bitD->limitPtr)) |
| return BIT_DStream_overflow; |
| assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8); |
| bitD->ptr -= bitD->bitsConsumed >> 3; |
| bitD->bitsConsumed &= 7; |
| bitD->bitContainer = MEM_readLEST(bitD->ptr); |
| return BIT_DStream_unfinished; |
| } |
| |
| /*! BIT_reloadDStream() : |
| * Refill `bitD` from buffer previously set in BIT_initDStream() . |
| * This function is safe, it guarantees it will not read beyond src buffer. |
| * @return : status of `BIT_DStream_t` internal register. |
| * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */ |
| MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) |
| { |
| if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */ |
| return BIT_DStream_overflow; |
| |
| if (bitD->ptr >= bitD->limitPtr) { |
| return BIT_reloadDStreamFast(bitD); |
| } |
| if (bitD->ptr == bitD->start) { |
| if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; |
| return BIT_DStream_completed; |
| } |
| /* start < ptr < limitPtr */ |
| { U32 nbBytes = bitD->bitsConsumed >> 3; |
| BIT_DStream_status result = BIT_DStream_unfinished; |
| if (bitD->ptr - nbBytes < bitD->start) { |
| nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ |
| result = BIT_DStream_endOfBuffer; |
| } |
| bitD->ptr -= nbBytes; |
| bitD->bitsConsumed -= nbBytes*8; |
| bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */ |
| return result; |
| } |
| } |
| |
| /*! BIT_endOfDStream() : |
| * @return : 1 if DStream has _exactly_ reached its end (all bits consumed). |
| */ |
| MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) |
| { |
| return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); |
| } |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| |
| #endif /* BITSTREAM_H_MODULE */ |
| /**** ended inlining bitstream.h ****/ |
| |
| |
| /* ***************************************** |
| * Static allocation |
| *******************************************/ |
| /* FSE buffer bounds */ |
| #define FSE_NCOUNTBOUND 512 |
| #define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) |
| #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ |
| |
| /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ |
| #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2)) |
| #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog))) |
| |
| /* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ |
| #define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) |
| #define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable)) |
| |
| |
| /* ***************************************** |
| * FSE advanced API |
| ***************************************** */ |
| |
| unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus); |
| /**< same as FSE_optimalTableLog(), which used `minus==2` */ |
| |
| /* FSE_compress_wksp() : |
| * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). |
| * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. |
| */ |
| #define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) |
| size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); |
| |
| size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); |
| /**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */ |
| |
| size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); |
| /**< build a fake FSE_CTable, designed to compress always the same symbolValue */ |
| |
| /* FSE_buildCTable_wksp() : |
| * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). |
| * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`. |
| */ |
| #define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2))) |
| #define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)) |
| size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); |
| |
| #define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8) |
| #define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned)) |
| FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); |
| /**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */ |
| |
| size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); |
| /**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ |
| |
| size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); |
| /**< build a fake FSE_DTable, designed to always generate the same symbolValue */ |
| |
| #define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue)) |
| #define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned)) |
| size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize); |
| /**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */ |
| |
| size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2); |
| /**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */ |
| |
| typedef enum { |
| FSE_repeat_none, /**< Cannot use the previous table */ |
| FSE_repeat_check, /**< Can use the previous table but it must be checked */ |
| FSE_repeat_valid /**< Can use the previous table and it is assumed to be valid */ |
| } FSE_repeat; |
| |
| /* ***************************************** |
| * FSE symbol compression API |
| *******************************************/ |
| /*! |
| This API consists of small unitary functions, which highly benefit from being inlined. |
| Hence their body are included in next section. |
| */ |
| typedef struct { |
| ptrdiff_t value; |
| const void* stateTable; |
| const void* symbolTT; |
| unsigned stateLog; |
| } FSE_CState_t; |
| |
| static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); |
| |
| static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); |
| |
| static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); |
| |
| /**< |
| These functions are inner components of FSE_compress_usingCTable(). |
| They allow the creation of custom streams, mixing multiple tables and bit sources. |
| |
| A key property to keep in mind is that encoding and decoding are done **in reverse direction**. |
| So the first symbol you will encode is the last you will decode, like a LIFO stack. |
| |
| You will need a few variables to track your CStream. They are : |
| |
| FSE_CTable ct; // Provided by FSE_buildCTable() |
| BIT_CStream_t bitStream; // bitStream tracking structure |
| FSE_CState_t state; // State tracking structure (can have several) |
| |
| |
| The first thing to do is to init bitStream and state. |
| size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize); |
| FSE_initCState(&state, ct); |
| |
| Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError(); |
| You can then encode your input data, byte after byte. |
| FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time. |
| Remember decoding will be done in reverse direction. |
| FSE_encodeByte(&bitStream, &state, symbol); |
| |
| At any time, you can also add any bit sequence. |
| Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders |
| BIT_addBits(&bitStream, bitField, nbBits); |
| |
| The above methods don't commit data to memory, they just store it into local register, for speed. |
| Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t). |
| Writing data to memory is a manual operation, performed by the flushBits function. |
| BIT_flushBits(&bitStream); |
| |
| Your last FSE encoding operation shall be to flush your last state value(s). |
| FSE_flushState(&bitStream, &state); |
| |
| Finally, you must close the bitStream. |
| The function returns the size of CStream in bytes. |
| If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible) |
| If there is an error, it returns an errorCode (which can be tested using FSE_isError()). |
| size_t size = BIT_closeCStream(&bitStream); |
| */ |
| |
| |
| /* ***************************************** |
| * FSE symbol decompression API |
| *******************************************/ |
| typedef struct { |
| size_t state; |
| const void* table; /* precise table may vary, depending on U16 */ |
| } FSE_DState_t; |
| |
| |
| static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); |
| |
| static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); |
| |
| static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr); |
| |
| /**< |
| Let's now decompose FSE_decompress_usingDTable() into its unitary components. |
| You will decode FSE-encoded symbols from the bitStream, |
| and also any other bitFields you put in, **in reverse order**. |
| |
| You will need a few variables to track your bitStream. They are : |
| |
| BIT_DStream_t DStream; // Stream context |
| FSE_DState_t DState; // State context. Multiple ones are possible |
| FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable() |
| |
| The first thing to do is to init the bitStream. |
| errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize); |
| |
| You should then retrieve your initial state(s) |
| (in reverse flushing order if you have several ones) : |
| errorCode = FSE_initDState(&DState, &DStream, DTablePtr); |
| |
| You can then decode your data, symbol after symbol. |
| For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'. |
| Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out). |
| unsigned char symbol = FSE_decodeSymbol(&DState, &DStream); |
| |
| You can retrieve any bitfield you eventually stored into the bitStream (in reverse order) |
| Note : maximum allowed nbBits is 25, for 32-bits compatibility |
| size_t bitField = BIT_readBits(&DStream, nbBits); |
| |
| All above operations only read from local register (which size depends on size_t). |
| Refueling the register from memory is manually performed by the reload method. |
| endSignal = FSE_reloadDStream(&DStream); |
| |
| BIT_reloadDStream() result tells if there is still some more data to read from DStream. |
| BIT_DStream_unfinished : there is still some data left into the DStream. |
| BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled. |
| BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed. |
| BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted. |
| |
| When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop, |
| to properly detect the exact end of stream. |
| After each decoded symbol, check if DStream is fully consumed using this simple test : |
| BIT_reloadDStream(&DStream) >= BIT_DStream_completed |
| |
| When it's done, verify decompression is fully completed, by checking both DStream and the relevant states. |
| Checking if DStream has reached its end is performed by : |
| BIT_endOfDStream(&DStream); |
| Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible. |
| FSE_endOfDState(&DState); |
| */ |
| |
| |
| /* ***************************************** |
| * FSE unsafe API |
| *******************************************/ |
| static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); |
| /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ |
| |
| |
| /* ***************************************** |
| * Implementation of inlined functions |
| *******************************************/ |
| typedef struct { |
| int deltaFindState; |
| U32 deltaNbBits; |
| } FSE_symbolCompressionTransform; /* total 8 bytes */ |
| |
| MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) |
| { |
| const void* ptr = ct; |
| const U16* u16ptr = (const U16*) ptr; |
| const U32 tableLog = MEM_read16(ptr); |
| statePtr->value = (ptrdiff_t)1<<tableLog; |
| statePtr->stateTable = u16ptr+2; |
| statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1); |
| statePtr->stateLog = tableLog; |
| } |
| |
| |
| /*! FSE_initCState2() : |
| * Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) |
| * uses the smallest state value possible, saving the cost of this symbol */ |
| MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) |
| { |
| FSE_initCState(statePtr, ct); |
| { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; |
| const U16* stateTable = (const U16*)(statePtr->stateTable); |
| U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); |
| statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; |
| statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; |
| } |
| } |
| |
| MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol) |
| { |
| FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; |
| const U16* const stateTable = (const U16*)(statePtr->stateTable); |
| U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); |
| BIT_addBits(bitC, statePtr->value, nbBitsOut); |
| statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; |
| } |
| |
| MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) |
| { |
| BIT_addBits(bitC, statePtr->value, statePtr->stateLog); |
| BIT_flushBits(bitC); |
| } |
| |
| |
| /* FSE_getMaxNbBits() : |
| * Approximate maximum cost of a symbol, in bits. |
| * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2) |
| * note 1 : assume symbolValue is valid (<= maxSymbolValue) |
| * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ |
| MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue) |
| { |
| const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; |
| return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16; |
| } |
| |
| /* FSE_bitCost() : |
| * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) |
| * note 1 : assume symbolValue is valid (<= maxSymbolValue) |
| * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */ |
| MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog) |
| { |
| const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr; |
| U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16; |
| U32 const threshold = (minNbBits+1) << 16; |
| assert(tableLog < 16); |
| assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */ |
| { U32 const tableSize = 1 << tableLog; |
| U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize); |
| U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */ |
| U32 const bitMultiplier = 1 << accuracyLog; |
| assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold); |
| assert(normalizedDeltaFromThreshold <= bitMultiplier); |
| return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold; |
| } |
| } |
| |
| |
| /* ====== Decompression ====== */ |
| |
| typedef struct { |
| U16 tableLog; |
| U16 fastMode; |
| } FSE_DTableHeader; /* sizeof U32 */ |
| |
| typedef struct |
| { |
| unsigned short newState; |
| unsigned char symbol; |
| unsigned char nbBits; |
| } FSE_decode_t; /* size == U32 */ |
| |
| MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) |
| { |
| const void* ptr = dt; |
| const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; |
| DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); |
| BIT_reloadDStream(bitD); |
| DStatePtr->table = dt + 1; |
| } |
| |
| MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) |
| { |
| FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| return DInfo.symbol; |
| } |
| |
| MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) |
| { |
| FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| U32 const nbBits = DInfo.nbBits; |
| size_t const lowBits = BIT_readBits(bitD, nbBits); |
| DStatePtr->state = DInfo.newState + lowBits; |
| } |
| |
| MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) |
| { |
| FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| U32 const nbBits = DInfo.nbBits; |
| BYTE const symbol = DInfo.symbol; |
| size_t const lowBits = BIT_readBits(bitD, nbBits); |
| |
| DStatePtr->state = DInfo.newState + lowBits; |
| return symbol; |
| } |
| |
| /*! FSE_decodeSymbolFast() : |
| unsafe, only works if no symbol has a probability > 50% */ |
| MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) |
| { |
| FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; |
| U32 const nbBits = DInfo.nbBits; |
| BYTE const symbol = DInfo.symbol; |
| size_t const lowBits = BIT_readBitsFast(bitD, nbBits); |
| |
| DStatePtr->state = DInfo.newState + lowBits; |
| return symbol; |
| } |
| |
| MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) |
| { |
| return DStatePtr->state == 0; |
| } |
| |
| |
| |
| #ifndef FSE_COMMONDEFS_ONLY |
| |
| /* ************************************************************** |
| * Tuning parameters |
| ****************************************************************/ |
| /*!MEMORY_USAGE : |
| * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) |
| * Increasing memory usage improves compression ratio |
| * Reduced memory usage can improve speed, due to cache effect |
| * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ |
| #ifndef FSE_MAX_MEMORY_USAGE |
| # define FSE_MAX_MEMORY_USAGE 14 |
| #endif |
| #ifndef FSE_DEFAULT_MEMORY_USAGE |
| # define FSE_DEFAULT_MEMORY_USAGE 13 |
| #endif |
| #if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE) |
| # error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE" |
| #endif |
| |
| /*!FSE_MAX_SYMBOL_VALUE : |
| * Maximum symbol value authorized. |
| * Required for proper stack allocation */ |
| #ifndef FSE_MAX_SYMBOL_VALUE |
| # define FSE_MAX_SYMBOL_VALUE 255 |
| #endif |
| |
| /* ************************************************************** |
| * template functions type & suffix |
| ****************************************************************/ |
| #define FSE_FUNCTION_TYPE BYTE |
| #define FSE_FUNCTION_EXTENSION |
| #define FSE_DECODE_TYPE FSE_decode_t |
| |
| |
| #endif /* !FSE_COMMONDEFS_ONLY */ |
| |
| |
| /* *************************************************************** |
| * Constants |
| *****************************************************************/ |
| #define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) |
| #define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG) |
| #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1) |
| #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2) |
| #define FSE_MIN_TABLELOG 5 |
| |
| #define FSE_TABLELOG_ABSOLUTE_MAX 15 |
| #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX |
| # error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" |
| #endif |
| |
| #define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3) |
| |
| |
| #endif /* FSE_STATIC_LINKING_ONLY */ |
| |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| /**** ended inlining fse.h ****/ |
| #define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ |
| /**** start inlining huf.h ****/ |
| /* ****************************************************************** |
| * huff0 huffman codec, |
| * part of Finite State Entropy library |
| * Copyright (c) 2013-2021, Yann Collet, Facebook, Inc. |
| * |
| * You can contact the author at : |
| * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy |
| * |
| * This source code is licensed under both the BSD-style license (found in the |
| * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| * in the COPYING file in the root directory of this source tree). |
| * You may select, at your option, one of the above-listed licenses. |
| ****************************************************************** */ |
| |
| #if defined (__cplusplus) |
| extern "C" { |
| #endif |
| |
| #ifndef HUF_H_298734234 |
| #define HUF_H_298734234 |
| |
| /* *** Dependencies *** */ |
| /**** skipping file: zstd_deps.h ****/ |
| |
| |
| /* *** library symbols visibility *** */ |
| /* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual, |
| * HUF symbols remain "private" (internal symbols for library only). |
| * Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */ |
| #if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4) |
| # define HUF_PUBLIC_API __attribute__ ((visibility ("default"))) |
| #elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */ |
| # define HUF_PUBLIC_API __declspec(dllexport) |
| #elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1) |
| # define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */ |
| #else |
| # define HUF_PUBLIC_API |
| #endif |
| |
| |
| /* ========================== */ |
| /* *** simple functions *** */ |
| /* ========================== */ |
| |
| /** HUF_compress() : |
| * Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'. |
| * 'dst' buffer must be already allocated. |
| * Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize). |
| * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB. |
| * @return : size of compressed data (<= `dstCapacity`). |
| * Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!! |
| * if HUF_isError(return), compression failed (more details using HUF_getErrorName()) |
| */ |
| HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity, |
| const void* src, size_t srcSize); |
| |
| /** HUF_decompress() : |
| * Decompress HUF data from buffer 'cSrc', of size 'cSrcSize', |
| * into already allocated buffer 'dst', of minimum size 'dstSize'. |
| * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data. |
| * Note : in contrast with FSE, HUF_decompress can regenerate |
| * RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, |
| * because it knows size to regenerate (originalSize). |
| * @return : size of regenerated data (== originalSize), |
| * or an error code, which can be tested using HUF_isError() |
| */ |
| HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize, |
| const void* cSrc, size_t cSrcSize); |
| |
| |
| /* *** Tool functions *** */ |
| #define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */ |
| HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ |
| |
| /* Error Management */ |
| HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ |
| HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */ |
| |
| |
| /* *** Advanced function *** */ |
| |
| /** HUF_compress2() : |
| * Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`. |
| * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX . |
| * `tableLog` must be `<= HUF_TABLELOG_MAX` . */ |
| HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, |
| const void* src, size_t srcSize, |
| unsigned maxSymbolValue, unsigned tableLog); |
| |
| /** HUF_compress4X_wksp() : |
| * Same as HUF_compress2(), but uses externally allocated `workSpace`. |
| * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */ |
| #define HUF_WORKSPACE_SIZE ((6 << 10) + 256) |
| #define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) |
| HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, |
| const void* src, size_t srcSize, |
| unsigned maxSymbolValue, unsigned tableLog, |
| void* workSpace, size_t wkspSize); |
| |
| #endif /* HUF_H_298734234 */ |
| |
| /* ****************************************************************** |
| * WARNING !! |
| * The following section contains advanced and experimental definitions |
| * which shall never be used in the context of a dynamic library, |
| * because they are not guaranteed to remain stable in the future. |
| * Only consider them in association with static linking. |
| * *****************************************************************/ |
| #if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY) |
| #define HUF_H_HUF_STATIC_LINKING_ONLY |
| |
| /* *** Dependencies *** */ |
| /**** skipping file: mem.h ****/ |
| #define FSE_STATIC_LINKING_ONLY |
| /**** skipping file: fse.h ****/ |
| |
| |
| /* *** Constants *** */ |
| #define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ |
| #define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */ |
| #define HUF_SYMBOLVALUE_MAX 255 |
| |
| #define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ |
| #if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) |
| # error "HUF_TABLELOG_MAX is too large !" |
| #endif |
| |
| |
| /* **************************************** |
| * Static allocation |
| ******************************************/ |
| /* HUF buffer bounds */ |
| #define HUF_CTABLEBOUND 129 |
| #define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */ |
| #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ |
| |
| /* static allocation of HUF's Compression Table */ |
| /* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */ |
| struct HUF_CElt_s { |
| U16 val; |
| BYTE nbBits; |
| }; /* typedef'd to HUF_CElt */ |
| typedef struct HUF_CElt_s HUF_CElt; /* consider it an incomplete type */ |
| #define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */ |
| #define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32)) |
| #define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ |
| HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */ |
| |
| /* static allocation of HUF's DTable */ |
| typedef U32 HUF_DTable; |
| #define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) |
| #define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \ |
| HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } |
| #define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ |
| HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) } |
| |
| |
| /* **************************************** |
| * Advanced decompression functions |
| ******************************************/ |
| size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ |
| #endif |
| |
| size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */ |
| size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */ |
| size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */ |
| size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ |
| size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ |
| size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ |
| #endif |
| |
| |
| /* **************************************** |
| * HUF detailed API |
| * ****************************************/ |
| |
| /*! HUF_compress() does the following: |
| * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h") |
| * 2. (optional) refine tableLog using HUF_optimalTableLog() |
| * 3. build Huffman table from count using HUF_buildCTable() |
| * 4. save Huffman table to memory buffer using HUF_writeCTable() |
| * 5. encode the data stream using HUF_compress4X_usingCTable() |
| * |
| * The following API allows targeting specific sub-functions for advanced tasks. |
| * For example, it's possible to compress several blocks using the same 'CTable', |
| * or to save and regenerate 'CTable' using external methods. |
| */ |
| unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); |
| size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ |
| size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); |
| size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); |
| size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); |
| int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue); |
| |
| typedef enum { |
| HUF_repeat_none, /**< Cannot use the previous table */ |
| HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */ |
| HUF_repeat_valid /**< Can use the previous table and it is assumed to be valid */ |
| } HUF_repeat; |
| /** HUF_compress4X_repeat() : |
| * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. |
| * If it uses hufTable it does not modify hufTable or repeat. |
| * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. |
| * If preferRepeat then the old table will always be used if valid. */ |
| size_t HUF_compress4X_repeat(void* dst, size_t dstSize, |
| const void* src, size_t srcSize, |
| unsigned maxSymbolValue, unsigned tableLog, |
| void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ |
| HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); |
| |
| /** HUF_buildCTable_wksp() : |
| * Same as HUF_buildCTable(), but using externally allocated scratch buffer. |
| * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE. |
| */ |
| #define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1) |
| #define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned)) |
| size_t HUF_buildCTable_wksp (HUF_CElt* tree, |
| const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, |
| void* workSpace, size_t wkspSize); |
| |
| /*! HUF_readStats() : |
| * Read compact Huffman tree, saved by HUF_writeCTable(). |
| * `huffWeight` is destination buffer. |
| * @return : size read from `src` , or an error Code . |
| * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */ |
| size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, |
| U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize); |
| |
| /*! HUF_readStats_wksp() : |
| * Same as HUF_readStats() but takes an external workspace which must be |
| * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE. |
| * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. |
| */ |
| #define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1) |
| #define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned)) |
| size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, |
| U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize, |
| void* workspace, size_t wkspSize, |
| int bmi2); |
| |
| /** HUF_readCTable() : |
| * Loading a CTable saved with HUF_writeCTable() */ |
| size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); |
| |
| /** HUF_getNbBits() : |
| * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX |
| * Note 1 : is not inlined, as HUF_CElt definition is private |
| * Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */ |
| U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue); |
| |
| /* |
| * HUF_decompress() does the following: |
| * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics |
| * 2. build Huffman table from save, using HUF_readDTableX?() |
| * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable() |
| */ |
| |
| /** HUF_selectDecoder() : |
| * Tells which decoder is likely to decode faster, |
| * based on a set of pre-computed metrics. |
| * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 . |
| * Assumption : 0 < dstSize <= 128 KB */ |
| U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); |
| |
| /** |
| * The minimum workspace size for the `workSpace` used in |
| * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp(). |
| * |
| * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when |
| * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15. |
| * Buffer overflow errors may potentially occur if code modifications result in |
| * a required workspace size greater than that specified in the following |
| * macro. |
| */ |
| #define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10) |
| #define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32)) |
| |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize); |
| size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); |
| #endif |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize); |
| size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize); |
| #endif |
| |
| size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); |
| #endif |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); |
| #endif |
| |
| |
| /* ====================== */ |
| /* single stream variants */ |
| /* ====================== */ |
| |
| size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); |
| size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ |
| size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); |
| /** HUF_compress1X_repeat() : |
| * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. |
| * If it uses hufTable it does not modify hufTable or repeat. |
| * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. |
| * If preferRepeat then the old table will always be used if valid. */ |
| size_t HUF_compress1X_repeat(void* dst, size_t dstSize, |
| const void* src, size_t srcSize, |
| unsigned maxSymbolValue, unsigned tableLog, |
| void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */ |
| HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2); |
| |
| size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */ |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */ |
| #endif |
| |
| size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); |
| size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ |
| size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */ |
| #endif |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ |
| size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */ |
| #endif |
| |
| size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */ |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); |
| #endif |
| #ifndef HUF_FORCE_DECOMPRESS_X1 |
| size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); |
| #endif |
| |
| /* BMI2 variants. |
| * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. |
| */ |
| size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); |
| #endif |
| size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); |
| size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); |
| #ifndef HUF_FORCE_DECOMPRESS_X2 |
| size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2); |
| #endif |
| |
| #endif /* HUF_STATIC_LINKING_ONLY */ |
| |
| #if defined (__cplusplus) |
| } |
| #endif |
| /**** ended inlining huf.h ****/ |
| |
| |
| /*=== Version ===*/ |
| unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } |
| |
| |
| /*=== Error Management ===*/ |
| unsigned FSE_isError(size_t code) { return ERR_isError(code); } |
| const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); } |
| |
| unsigned HUF_isError(size_t code) { return ERR_isError(code); } |
| const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } |
| |
| |
| /*-************************************************************** |
| * FSE NCount encoding-decoding |
| ****************************************************************/ |
| static U32 FSE_ctz(U32 val) |
| { |
| assert(val != 0); |
| { |
| # if defined(_MSC_VER) /* Visual */ |
| unsigned long r=0; |
| return _BitScanForward(&r, val) ? (unsigned)r : 0; |
| # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ |
| return __builtin_ctz(val); |
| # elif defined(__ICCARM__) /* IAR Intrinsic */ |
| return __CTZ(val); |
| # else /* Software version */ |
| U32 count = 0; |
| while ((val & 1) == 0) { |
| val >>= 1; |
| ++count; |
| } |
| return count; |
| # endif |
| } |
| } |
| |
| FORCE_INLINE_TEMPLATE |
| size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, |
| const void* headerBuffer, size_t hbSize) |
| { |
| const BYTE* const istart = (const BYTE*) headerBuffer; |
| const BYTE* const iend = istart + hbSize; |
| const BYTE* ip = istart; |
| int nbBits; |
| int remaining; |
| int threshold; |
| U32 bitStream; |
| int bitCount; |
| unsigned charnum = 0; |
| unsigned const maxSV1 = *maxSVPtr + 1; |
| int previous0 = 0; |
| |
| if (hbSize < 8) { |
| /* This function only works when hbSize >= 8 */ |
| char buffer[8] = {0}; |
| ZSTD_memcpy(buffer, headerBuffer, hbSize); |
| { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, |
| buffer, sizeof(buffer)); |
| if (FSE_isError(countSize)) return countSize; |
| if (countSize > hbSize) return ERROR(corruption_detected); |
| return countSize; |
| } } |
| assert(hbSize >= 8); |
| |
| /* init */ |
| ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ |
| bitStream = MEM_readLE32(ip); |
| nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ |
| if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); |
| bitStream >>= 4; |
| bitCount = 4; |
| *tableLogPtr = nbBits; |
| remaining = (1<<nbBits)+1; |
| threshold = 1<<nbBits; |
| nbBits++; |
| |
| for (;;) { |
| if (previous0) { |
| /* Count the number of repeats. Each time the |
| * 2-bit repeat code is 0b11 there is another |
| * repeat. |
| * Avoid UB by setting the high bit to 1. |
| */ |
| int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; |
| while (repeats >= 12) { |
| charnum += 3 * 12; |
| if (LIKELY(ip <= iend-7)) { |
| ip += 3; |
| } else { |
| bitCount -= (int)(8 * (iend - 7 - ip)); |
| bitCount &= 31; |
| ip = iend - 4; |
| } |
| bitStream = MEM_readLE32(ip) >> bitCount; |
| repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; |
| } |
| charnum += 3 * repeats; |
| bitStream >>= 2 * repeats; |
| bitCount += 2 * repeats; |
| |
| /* Add the final repeat which isn't 0b11. */ |
| assert((bitStream & 3) < 3); |
| charnum += bitStream & 3; |
| bitCount += 2; |
| |
| /* This is an error, but break and return an error |
| * at the end, because returning out of a loop makes |
| * it harder for the compiler to optimize. |
| */ |
| if (charnum >= maxSV1) break; |
| |
| /* We don't need to set the normalized count to 0 |
| * because we already memset the whole buffer to 0. |
| */ |
| |
| if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { |
| assert((bitCount >> 3) <= 3); /* For first condition to work */ |
| ip += bitCount>>3; |
| bitCount &= 7; |
| } else { |
| bitCount -= (int)(8 * (iend - 4 - ip)); |
| bitCount &= 31; |
| ip = iend - 4; |
| } |
| bitStream = MEM_readLE32(ip) >> bitCount; |
| } |
| { |
| int const max = (2*threshold-1) - remaining; |
| int count; |
| |
| if ((bitStream & (threshold-1)) < (U32)max) { |
| count = bitStream & (threshold-1); |
| bitCount += nbBits-1; |
| } else { |
| count = bitStream & (2*threshold-1); |
| if (count >= threshold) count -= max; |
| bitCount += nbBits; |
| } |
| |
| count--; /* extra accuracy */ |
| /* When it matters (small blocks), this is a |
| * predictable branch, because we don't use -1. |
| */ |
| if (count >= 0) { |
| remaining -= count; |
| } else { |
| assert(count == -1); |
| remaining += count; |
| } |
| normalizedCounter[charnum++] = (short)count; |
| previous0 = !count; |
| |
| assert(threshold > 1); |
| if (remaining < threshold) { |
| /* This branch can be folded into the |
| * threshold update condition because we |
| * know that threshold > 1. |
| */ |
| if (remaining <= 1) break; |
| nbBits = BIT_highbit32(remaining) + 1; |
| threshold = 1 << (nbBits - 1); |
| } |
| if (charnum >= maxSV1) break; |
| |
| if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { |
| ip += bitCount>>3; |
| bitCount &= 7; |
| } else { |
| bitCount -= (int)(8 * (iend - 4 - ip)); |
| bitCount &= 31; |
| ip = iend - 4; |
| } |
| bitStream = MEM_readLE32(ip) >> bitCount; |
| } } |
| if (remaining != 1) return ERROR(corruption_detected); |
| /* Only possible when there are too many zeros. */ |
| if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall); |
| if (bitCount > 32) return ERROR(corruption_detected); |
| *maxSVPtr = charnum-1; |
| |
| ip += (bitCount+7)>>3; |
| return ip-istart; |
| } |
| |
| /* Avoids the FORCE_INLINE of the _body() function. */ |
| static size_t FSE_readNCount_body_default( |
| short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, |
| const void* headerBuffer, size_t hbSize) |
| { |
| return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); |
| } |
| |
| #if DYNAMIC_BMI2 |
| TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2( |
| short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, |
| const void* headerBuffer, size_t hbSize) |
| { |
| return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); |
| } |
| #endif |
| |
| size_t FSE_readNCount_bmi2( |
| short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, |
| const void* headerBuffer, size_t hbSize, int bmi2) |
| { |
| #if DYNAMIC_BMI2 |
| if (bmi2) { |
| return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); |
| } |
| #endif |
| (void)bmi2; |
| return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); |
| } |
| |
| size_t FSE_readNCount( |
| short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, |
| const void* headerBuffer, size_t hbSize) |
| { |
| return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0); |
| } |
| |
| |
| /*! HUF_readStats() : |
| Read compact Huffman tree, saved by HUF_writeCTable(). |
| `huffWeight` is destination buffer. |
| `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32. |
| @return : size read from `src` , or an error Code . |
| Note : Needed by HUF_readCTable() and HUF_readDTableX?() . |
| */ |
| size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, |
| U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize) |
| { |
| U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; |
| return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0); |
| } |
| |
| FORCE_INLINE_TEMPLATE size_t |
| HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats, |
| U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize, |
| void* workSpace, size_t wkspSize, |
| int bmi2) |
| { |
| U32 weightTotal; |
| const BYTE* ip = (const BYTE*) src; |
| size_t iSize; |
| size_t oSize; |
| |
| if (!srcSize) return ERROR(srcSize_wrong); |
| iSize = ip[0]; |
| /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ |
| |
| if (iSize >= 128) { /* special header */ |
| oSize = iSize - 127; |
| iSize = ((oSize+1)/2); |
| if (iSize+1 > srcSize) return ERROR(srcSize_wrong); |
| if (oSize >= hwSize) return ERROR(corruption_detected); |
| ip += 1; |
| { U32 n; |
| for (n=0; n<oSize; n+=2) { |
| huffWeight[n] = ip[n/2] >> 4; |
| huffWeight[n+1] = ip[n/2] & 15; |
| } } } |
| else { /* header compressed with FSE (normal case) */ |
| if (iSize+1 > srcSize) return ERROR(srcSize_wrong); |
| /* max (hwSize-1) values decoded, as last one is implied */ |
| oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2); |
| if (FSE_isError(oSize)) return oSize; |
| } |
| |
| /* collect weight stats */ |
| ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); |
| weightTotal = 0; |
| { U32 n; for (n=0; n<oSize; n++) { |
| if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); |
| rankStats[huffWeight[n]]++; |
| weightTotal += (1 << huffWeight[n]) >> 1; |
| } } |
| if (weightTotal == 0) return ERROR(corruption_detected); |
| |
| /* get last non-null symbol weight (implied, total must be 2^n) */ |
| { U32 const tableLog = BIT_highbit32(weightTotal) + 1; |
| if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); |
| *tableLogPtr = tableLog; |
| /* determine last weight */ |
| { U32 const total = 1 << tableLog; |
| U32 const rest = total - weightTotal; |
| U32 const verif = 1 << BIT_highbit32(rest); |
| U32 const lastWeight = BIT_highbit32(rest) + 1; |
| if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ |
| huffWeight[oSize] = (BYTE)lastWeight; |
| rankStats[lastWeight]++; |
| } } |
| |
| /* check tree construction validity */ |
| if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ |
| |
| /* results */ |
| *nbSymbolsPtr = (U32)(oSize+1); |
| return iSize+1; |
| } |
| |
| /* Avoids the FORCE_INLINE of the _body() function. */ |
| static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats, |
| U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize, |
| void* workSpace, size_t wkspSize) |
| { |
| return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0); |
| } |
| |
| #if DYNAMIC_BMI2 |
| static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats, |
| U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize, |
| void* workSpace, size_t wkspSize) |
| { |
| return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1); |
| } |
| #endif |
| |
| size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats, |
| U32* nbSymbolsPtr, U32* tableLogPtr, |
| const void* src, size_t srcSize, |
| void* workSpace, size_t wkspSize, |
| int bmi2) |
| { |
| #if DYNAMIC_BMI2 |
| if (bmi2) { |
| return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); |
| } |
| #endif |
| (void)bmi2; |
| return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, |