diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 6b2c22c7..05b8d2ef 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -84,10 +84,6 @@ SET(MINIZIP_SRC ) ENDIF() -SET(ZSTD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zstd PARENT_SCOPE) - -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/zstd) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/blosc) SET(BLOSC_SRC ${BLOSC_SRC} PARENT_SCOPE) @@ -103,12 +99,3 @@ SET(CHARLS_SRC ${CHARLS_SRC} PARENT_SCOPE) SET(EXTRAS_INCLUDE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) - -SET(ZSTD_INCLUDE_DIR - ${ZSTD_INCLUDE_DIR} - PARENT_SCOPE -) -SET(ZSTD_SRC - ${ZSTD_SRC} - PARENT_SCOPE -) \ No newline at end of file diff --git a/extra/zstd/CMakeLists.txt b/extra/zstd/CMakeLists.txt deleted file mode 100644 index 8a8a4709..00000000 --- a/extra/zstd/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ - -SET(ZSTD_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/fse_decompress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v01.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v06.c - ${CMAKE_CURRENT_SOURCE_DIR}/entropy_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/zdict.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_compress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v04.c - ${CMAKE_CURRENT_SOURCE_DIR}/error_private.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash.c - ${CMAKE_CURRENT_SOURCE_DIR}/pool.c - ${CMAKE_CURRENT_SOURCE_DIR}/zbuff_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_decompress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstdmt_compress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v02.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v07.c - ${CMAKE_CURRENT_SOURCE_DIR}/cover.c - ${CMAKE_CURRENT_SOURCE_DIR}/huf_compress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zbuff_compress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v05.c - ${CMAKE_CURRENT_SOURCE_DIR}/divsufsort.c - ${CMAKE_CURRENT_SOURCE_DIR}/fse_compress.c - ${CMAKE_CURRENT_SOURCE_DIR}/huf_decompress.c - ${CMAKE_CURRENT_SOURCE_DIR}/threading.c - ${CMAKE_CURRENT_SOURCE_DIR}/zbuff_decompress.c - ${CMAKE_CURRENT_SOURCE_DIR}/zstd_v03.c -) - -SET(ZSTD_SRC - ${ZSTD_SRC} - PARENT_SCOPE -) - -SET(ZSTD_INCLUDE_DIR - ${CMAKE_CURRENT_SOURCE_DIR} - -) - -SET(ZSTD_INCLUDE_DIR - ${ZSTD_INCLUDE_DIR} - PARENT_SCOPE -) - - -add_library(libzstd ${ZSTD_SRC}) \ No newline at end of file diff --git a/extra/zstd/bitstream.h b/extra/zstd/bitstream.h deleted file mode 100644 index c2fc0928..00000000 --- a/extra/zstd/bitstream.h +++ /dev/null @@ -1,439 +0,0 @@ -/* ****************************************************************** - bitstream - Part of FSE library - header file (to include) - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy -****************************************************************** */ -#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 - ******************************************/ -#include "mem.h" /* unaligned access routines */ -#include "error_private.h" /* error codes and messages */ - -/*========================================= -* Target specific -=========================================*/ -#if defined(__BMI__) && defined(__GNUC__) -#include /* support for bextr (experimental) */ -#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; - int 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; - } 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(register U32 val) - { -#if defined(_MSC_VER) /* Visual */ - unsigned long r = 0; - _BitScanReverse(&r, val); - return (unsigned)r; -#elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ - return 31 - __builtin_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}; /* up to 26 bits */ - - /*-************************************************************** - * bitStream encoding - ****************************************************************/ - /*! BIT_initCStream() : - * `dstCapacity` must be > sizeof(void*) - * @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->ptr); - if (dstCapacity <= sizeof(bitC->ptr)) - return ERROR(dstSize_tooSmall); - return 0; - } - - /*! BIT_addBits() : - can add up to 26 bits into `bitC`. - Does not check for register overflow ! */ - MEM_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits) - { - 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) - { - bitC->bitContainer |= value << bitC->bitPos; - bitC->bitPos += nbBits; - } - - /*! BIT_flushBitsFast() : - * unsafe version; does not check buffer overflow */ - MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC) - { - size_t const nbBytes = bitC->bitPos >> 3; - MEM_writeLEST(bitC->ptr, bitC->bitContainer); - bitC->ptr += nbBytes; - bitC->bitPos &= 7; - bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ - } - - /*! BIT_flushBits() : - * safe version; check for buffer overflow, and prevents it. - * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */ - MEM_STATIC void BIT_flushBits(BIT_CStream_t *bitC) - { - size_t const nbBytes = bitC->bitPos >> 3; - 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; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ - } - - /*! 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; /* doesn't fit within authorized budget : cancel */ - - 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) - { - memset(bitD, 0, sizeof(*bitD)); - return ERROR(srcSize_wrong); - } - - if (srcSize >= sizeof(bitD->bitContainer)) - { /* normal case */ - bitD->start = (const char *)srcBuffer; - 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->start = (const char *)srcBuffer; - 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:; - } - { - BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1]; - bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; - if (lastByte == 0) - return ERROR(GENERIC); /* endMark not present */ - } - bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize) * 8; - } - - return srcSize; - } - - MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) - { - return bitContainer >> start; - } - - MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) - { -#if defined(__BMI__) && defined(__GNUC__) && __GNUC__ * 1000 + __GNUC_MINOR__ >= 4008 /* experimental */ -#if defined(__x86_64__) - if (sizeof(bitContainer) == 8) - return _bextr_u64(bitContainer, start, nbBits); - else -#endif - return _bextr_u32(bitContainer, start, nbBits); -#else - return (bitContainer >> start) & BIT_mask[nbBits]; -#endif - } - - MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) - { - return bitContainer & BIT_mask[nbBits]; - } - - /*! 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 size_t BIT_lookBits(const BIT_DStream_t *bitD, U32 nbBits) - { -#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */ - return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer) * 8) - bitD->bitsConsumed - nbBits, nbBits); -#else - U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask); -#endif - } - - /*! BIT_lookBitsFast() : - * unsafe version; only works only if nbBits >= 1 */ - MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t *bitD, U32 nbBits) - { - U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask); - } - - MEM_STATIC 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 size_t BIT_readBits(BIT_DStream_t *bitD, U32 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, U32 nbBits) - { - size_t const value = BIT_lookBitsFast(bitD, nbBits); - BIT_skipBits(bitD, nbBits); - return value; - } - - /*! 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. - if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */ - MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD) - { - if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should not happen => corruption detected */ - return BIT_DStream_overflow; - - if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) - { - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = MEM_readLEST(bitD->ptr); - return BIT_DStream_unfinished; - } - if (bitD->ptr == bitD->start) - { - if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8) - return BIT_DStream_endOfBuffer; - return BIT_DStream_completed; - } - { - 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) */ - return result; - } - } - - /*! BIT_endOfDStream() : - * @return Tells 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 */ diff --git a/extra/zstd/cover.c b/extra/zstd/cover.c deleted file mode 100644 index 22ee8158..00000000 --- a/extra/zstd/cover.c +++ /dev/null @@ -1,1151 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* ***************************************************************************** - * Constructs a dictionary using a heuristic based on the following paper: - * - * Liao, Petri, Moffat, Wirth - * Effective Construction of Relative Lempel-Ziv Dictionaries - * Published in WWW 2016. - * - * Adapted from code originally written by @ot (Giuseppe Ottaviano). - ******************************************************************************/ - -/*-************************************* - * Dependencies - ***************************************/ -#include /* fprintf */ -#include /* malloc, free, qsort */ -#include /* memset */ -#include /* clock */ - -#include "mem.h" /* read */ -#include "pool.h" -#include "threading.h" -#include "zstd_internal.h" /* includes zstd.h */ -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" - -/*-************************************* - * Constants - ***************************************/ -#define COVER_MAX_SAMPLES_SIZE (sizeof(size_t) == 8 ? ((U32)-1) : ((U32)1 GB)) - -/*-************************************* - * Console display - ***************************************/ -static int g_displayLevel = 2; -#define DISPLAY(...) \ - { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } -#define LOCALDISPLAYLEVEL(displayLevel, l, ...) \ - if (displayLevel >= l) \ - { \ - DISPLAY(__VA_ARGS__); \ - } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ -#define DISPLAYLEVEL(l, ...) LOCALDISPLAYLEVEL(g_displayLevel, l, __VA_ARGS__) - -#define LOCALDISPLAYUPDATE(displayLevel, l, ...) \ - if (displayLevel >= l) \ - { \ - if ((clock() - g_time > refreshRate) || (displayLevel >= 4)) \ - { \ - g_time = clock(); \ - DISPLAY(__VA_ARGS__); \ - if (displayLevel >= 4) \ - fflush(stdout); \ - } \ - } -#define DISPLAYUPDATE(l, ...) LOCALDISPLAYUPDATE(g_displayLevel, l, __VA_ARGS__) -static const clock_t refreshRate = CLOCKS_PER_SEC * 15 / 100; -static clock_t g_time = 0; - -/*-************************************* - * Hash table - *************************************** - * A small specialized hash map for storing activeDmers. - * The map does not resize, so if it becomes full it will loop forever. - * Thus, the map must be large enough to store every value. - * The map implements linear probing and keeps its load less than 0.5. - */ - -#define MAP_EMPTY_VALUE ((U32)-1) -typedef struct COVER_map_pair_t_s -{ - U32 key; - U32 value; -} COVER_map_pair_t; - -typedef struct COVER_map_s -{ - COVER_map_pair_t *data; - U32 sizeLog; - U32 size; - U32 sizeMask; -} COVER_map_t; - -/** - * Clear the map. - */ -static void COVER_map_clear(COVER_map_t *map) -{ - memset(map->data, MAP_EMPTY_VALUE, map->size * sizeof(COVER_map_pair_t)); -} - -/** - * Initializes a map of the given size. - * Returns 1 on success and 0 on failure. - * The map must be destroyed with COVER_map_destroy(). - * The map is only guaranteed to be large enough to hold size elements. - */ -static int COVER_map_init(COVER_map_t *map, U32 size) -{ - map->sizeLog = ZSTD_highbit32(size) + 2; - map->size = (U32)1 << map->sizeLog; - map->sizeMask = map->size - 1; - map->data = (COVER_map_pair_t *)malloc(map->size * sizeof(COVER_map_pair_t)); - if (!map->data) - { - map->sizeLog = 0; - map->size = 0; - return 0; - } - COVER_map_clear(map); - return 1; -} - -/** - * Internal hash function - */ -static const U32 prime4bytes = 2654435761U; -static U32 COVER_map_hash(COVER_map_t *map, U32 key) -{ - return (key * prime4bytes) >> (32 - map->sizeLog); -} - -/** - * Helper function that returns the index that a key should be placed into. - */ -static U32 COVER_map_index(COVER_map_t *map, U32 key) -{ - const U32 hash = COVER_map_hash(map, key); - U32 i; - for (i = hash;; i = (i + 1) & map->sizeMask) - { - COVER_map_pair_t *pos = &map->data[i]; - if (pos->value == MAP_EMPTY_VALUE) - { - return i; - } - if (pos->key == key) - { - return i; - } - } -} - -/** - * Returns the pointer to the value for key. - * If key is not in the map, it is inserted and the value is set to 0. - * The map must not be full. - */ -static U32 *COVER_map_at(COVER_map_t *map, U32 key) -{ - COVER_map_pair_t *pos = &map->data[COVER_map_index(map, key)]; - if (pos->value == MAP_EMPTY_VALUE) - { - pos->key = key; - pos->value = 0; - } - return &pos->value; -} - -/** - * Deletes key from the map if present. - */ -static void COVER_map_remove(COVER_map_t *map, U32 key) -{ - U32 i = COVER_map_index(map, key); - COVER_map_pair_t *del = &map->data[i]; - U32 shift = 1; - if (del->value == MAP_EMPTY_VALUE) - { - return; - } - for (i = (i + 1) & map->sizeMask;; i = (i + 1) & map->sizeMask) - { - COVER_map_pair_t *const pos = &map->data[i]; - /* If the position is empty we are done */ - if (pos->value == MAP_EMPTY_VALUE) - { - del->value = MAP_EMPTY_VALUE; - return; - } - /* If pos can be moved to del do so */ - if (((i - COVER_map_hash(map, pos->key)) & map->sizeMask) >= shift) - { - del->key = pos->key; - del->value = pos->value; - del = pos; - shift = 1; - } - else - { - ++shift; - } - } -} - -/** - * Destroyes a map that is inited with COVER_map_init(). - */ -static void COVER_map_destroy(COVER_map_t *map) -{ - if (map->data) - { - free(map->data); - } - map->data = NULL; - map->size = 0; -} - -/*-************************************* - * Context - ***************************************/ - -typedef struct -{ - const BYTE *samples; - size_t *offsets; - const size_t *samplesSizes; - size_t nbSamples; - U32 *suffix; - size_t suffixSize; - U32 *freqs; - U32 *dmerAt; - unsigned d; -} COVER_ctx_t; - -/* We need a global context for qsort... */ -static COVER_ctx_t *g_ctx = NULL; - -/*-************************************* - * Helper functions - ***************************************/ - -/** - * Returns the sum of the sample sizes. - */ -static size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) -{ - size_t sum = 0; - size_t i; - for (i = 0; i < nbSamples; ++i) - { - sum += samplesSizes[i]; - } - return sum; -} - -/** - * Returns -1 if the dmer at lp is less than the dmer at rp. - * Return 0 if the dmers at lp and rp are equal. - * Returns 1 if the dmer at lp is greater than the dmer at rp. - */ -static int COVER_cmp(COVER_ctx_t *ctx, const void *lp, const void *rp) -{ - const U32 lhs = *(const U32 *)lp; - const U32 rhs = *(const U32 *)rp; - return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d); -} - -/** - * Same as COVER_cmp() except ties are broken by pointer value - * NOTE: g_ctx must be set to call this function. A global is required because - * qsort doesn't take an opaque pointer. - */ -static int COVER_strict_cmp(const void *lp, const void *rp) -{ - int result = COVER_cmp(g_ctx, lp, rp); - if (result == 0) - { - result = lp < rp ? -1 : 1; - } - return result; -} - -/** - * Returns the first pointer in [first, last) whose element does not compare - * less than value. If no such element exists it returns last. - */ -static const size_t *COVER_lower_bound(const size_t *first, const size_t *last, - size_t value) -{ - size_t count = last - first; - while (count != 0) - { - size_t step = count / 2; - const size_t *ptr = first; - ptr += step; - if (*ptr < value) - { - first = ++ptr; - count -= step + 1; - } - else - { - count = step; - } - } - return first; -} - -/** - * Generic groupBy function. - * Groups an array sorted by cmp into groups with equivalent values. - * Calls grp for each group. - */ -static void -COVER_groupBy(const void *data, size_t count, size_t size, COVER_ctx_t *ctx, - int (*cmp)(COVER_ctx_t *, const void *, const void *), - void (*grp)(COVER_ctx_t *, const void *, const void *)) -{ - const BYTE *ptr = (const BYTE *)data; - size_t num = 0; - while (num < count) - { - const BYTE *grpEnd = ptr + size; - ++num; - while (num < count && cmp(ctx, ptr, grpEnd) == 0) - { - grpEnd += size; - ++num; - } - grp(ctx, ptr, grpEnd); - ptr = grpEnd; - } -} - -/*-************************************* - * Cover functions - ***************************************/ - -/** - * Called on each group of positions with the same dmer. - * Counts the frequency of each dmer and saves it in the suffix array. - * Fills `ctx->dmerAt`. - */ -static void COVER_group(COVER_ctx_t *ctx, const void *group, - const void *groupEnd) -{ - /* The group consists of all the positions with the same first d bytes. */ - const U32 *grpPtr = (const U32 *)group; - const U32 *grpEnd = (const U32 *)groupEnd; - /* The dmerId is how we will reference this dmer. - * This allows us to map the whole dmer space to a much smaller space, the - * size of the suffix array. - */ - const U32 dmerId = (U32)(grpPtr - ctx->suffix); - /* Count the number of samples this dmer shows up in */ - U32 freq = 0; - /* Details */ - const size_t *curOffsetPtr = ctx->offsets; - const size_t *offsetsEnd = ctx->offsets + ctx->nbSamples; - /* Once *grpPtr >= curSampleEnd this occurrence of the dmer is in a - * different sample than the last. - */ - size_t curSampleEnd = ctx->offsets[0]; - for (; grpPtr != grpEnd; ++grpPtr) - { - /* Save the dmerId for this position so we can get back to it. */ - ctx->dmerAt[*grpPtr] = dmerId; - /* Dictionaries only help for the first reference to the dmer. - * After that zstd can reference the match from the previous reference. - * So only count each dmer once for each sample it is in. - */ - if (*grpPtr < curSampleEnd) - { - continue; - } - freq += 1; - /* Binary search to find the end of the sample *grpPtr is in. - * In the common case that grpPtr + 1 == grpEnd we can skip the binary - * search because the loop is over. - */ - if (grpPtr + 1 != grpEnd) - { - const size_t *sampleEndPtr = - COVER_lower_bound(curOffsetPtr, offsetsEnd, *grpPtr); - curSampleEnd = *sampleEndPtr; - curOffsetPtr = sampleEndPtr + 1; - } - } - /* At this point we are never going to look at this segment of the suffix - * array again. We take advantage of this fact to save memory. - * We store the frequency of the dmer in the first position of the group, - * which is dmerId. - */ - ctx->suffix[dmerId] = freq; -} - -/** - * A segment is a range in the source as well as the score of the segment. - */ -typedef struct -{ - U32 begin; - U32 end; - double score; -} COVER_segment_t; - -/** - * Selects the best segment in an epoch. - * Segments of are scored according to the function: - * - * Let F(d) be the frequency of dmer d. - * Let S_i be the dmer at position i of segment S which has length k. - * - * Score(S) = F(S_1) + F(S_2) + ... + F(S_{k-d+1}) - * - * Once the dmer d is in the dictionay we set F(d) = 0. - */ -static COVER_segment_t COVER_selectSegment(const COVER_ctx_t *ctx, U32 *freqs, - COVER_map_t *activeDmers, U32 begin, - U32 end, COVER_params_t parameters) -{ - /* Constants */ - const U32 k = parameters.k; - const U32 d = parameters.d; - const U32 dmersInK = k - d + 1; - /* Try each segment (activeSegment) and save the best (bestSegment) */ - COVER_segment_t bestSegment = {0, 0, 0}; - COVER_segment_t activeSegment; - /* Reset the activeDmers in the segment */ - COVER_map_clear(activeDmers); - /* The activeSegment starts at the beginning of the epoch. */ - activeSegment.begin = begin; - activeSegment.end = begin; - activeSegment.score = 0; - /* Slide the activeSegment through the whole epoch. - * Save the best segment in bestSegment. - */ - while (activeSegment.end < end) - { - /* The dmerId for the dmer at the next position */ - U32 newDmer = ctx->dmerAt[activeSegment.end]; - /* The entry in activeDmers for this dmerId */ - U32 *newDmerOcc = COVER_map_at(activeDmers, newDmer); - /* If the dmer isn't already present in the segment add its score. */ - if (*newDmerOcc == 0) - { - /* The paper suggest using the L-0.5 norm, but experiments show that it - * doesn't help. - */ - activeSegment.score += freqs[newDmer]; - } - /* Add the dmer to the segment */ - activeSegment.end += 1; - *newDmerOcc += 1; - - /* If the window is now too large, drop the first position */ - if (activeSegment.end - activeSegment.begin == dmersInK + 1) - { - U32 delDmer = ctx->dmerAt[activeSegment.begin]; - U32 *delDmerOcc = COVER_map_at(activeDmers, delDmer); - activeSegment.begin += 1; - *delDmerOcc -= 1; - /* If this is the last occurence of the dmer, subtract its score */ - if (*delDmerOcc == 0) - { - COVER_map_remove(activeDmers, delDmer); - activeSegment.score -= freqs[delDmer]; - } - } - - /* If this segment is the best so far save it */ - if (activeSegment.score > bestSegment.score) - { - bestSegment = activeSegment; - } - } - { - /* Trim off the zero frequency head and tail from the segment. */ - U32 newBegin = bestSegment.end; - U32 newEnd = bestSegment.begin; - U32 pos; - for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) - { - U32 freq = freqs[ctx->dmerAt[pos]]; - if (freq != 0) - { - newBegin = MIN(newBegin, pos); - newEnd = pos + 1; - } - } - bestSegment.begin = newBegin; - bestSegment.end = newEnd; - } - { - /* Zero out the frequency of each dmer covered by the chosen segment. */ - U32 pos; - for (pos = bestSegment.begin; pos != bestSegment.end; ++pos) - { - freqs[ctx->dmerAt[pos]] = 0; - } - } - return bestSegment; -} - -/** - * Check the validity of the parameters. - * Returns non-zero if the parameters are valid and 0 otherwise. - */ -static int COVER_checkParameters(COVER_params_t parameters) -{ - /* k and d are required parameters */ - if (parameters.d == 0 || parameters.k == 0) - { - return 0; - } - /* d <= k */ - if (parameters.d > parameters.k) - { - return 0; - } - return 1; -} - -/** - * Clean up a context initialized with `COVER_ctx_init()`. - */ -static void COVER_ctx_destroy(COVER_ctx_t *ctx) -{ - if (!ctx) - { - return; - } - if (ctx->suffix) - { - free(ctx->suffix); - ctx->suffix = NULL; - } - if (ctx->freqs) - { - free(ctx->freqs); - ctx->freqs = NULL; - } - if (ctx->dmerAt) - { - free(ctx->dmerAt); - ctx->dmerAt = NULL; - } - if (ctx->offsets) - { - free(ctx->offsets); - ctx->offsets = NULL; - } -} - -/** - * Prepare a context for dictionary building. - * The context is only dependent on the parameter `d` and can used multiple - * times. - * Returns 1 on success or zero on error. - * The context must be destroyed with `COVER_ctx_destroy()`. - */ -static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, - unsigned d) -{ - const BYTE *const samples = (const BYTE *)samplesBuffer; - const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples); - /* Checks */ - if (totalSamplesSize < d || - totalSamplesSize >= (size_t)COVER_MAX_SAMPLES_SIZE) - { - DISPLAYLEVEL(1, "Total samples size is too large, maximum size is %u MB\n", - (COVER_MAX_SAMPLES_SIZE >> 20)); - return 0; - } - /* Zero the context */ - memset(ctx, 0, sizeof(*ctx)); - DISPLAYLEVEL(2, "Training on %u samples of total size %u\n", nbSamples, - (U32)totalSamplesSize); - ctx->samples = samples; - ctx->samplesSizes = samplesSizes; - ctx->nbSamples = nbSamples; - /* Partial suffix array */ - ctx->suffixSize = totalSamplesSize - d + 1; - ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); - /* Maps index to the dmerID */ - ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); - /* The offsets of each file */ - ctx->offsets = (size_t *)malloc((nbSamples + 1) * sizeof(size_t)); - if (!ctx->suffix || !ctx->dmerAt || !ctx->offsets) - { - DISPLAYLEVEL(1, "Failed to allocate scratch buffers\n"); - COVER_ctx_destroy(ctx); - return 0; - } - ctx->freqs = NULL; - ctx->d = d; - - /* Fill offsets from the samlesSizes */ - { - U32 i; - ctx->offsets[0] = 0; - for (i = 1; i <= nbSamples; ++i) - { - ctx->offsets[i] = ctx->offsets[i - 1] + samplesSizes[i - 1]; - } - } - DISPLAYLEVEL(2, "Constructing partial suffix array\n"); - { - /* suffix is a partial suffix array. - * It only sorts suffixes by their first parameters.d bytes. - * The sort is stable, so each dmer group is sorted by position in input. - */ - U32 i; - for (i = 0; i < ctx->suffixSize; ++i) - { - ctx->suffix[i] = i; - } - /* qsort doesn't take an opaque pointer, so pass as a global */ - g_ctx = ctx; - qsort(ctx->suffix, ctx->suffixSize, sizeof(U32), &COVER_strict_cmp); - } - DISPLAYLEVEL(2, "Computing frequencies\n"); - /* For each dmer group (group of positions with the same first d bytes): - * 1. For each position we set dmerAt[position] = dmerID. The dmerID is - * (groupBeginPtr - suffix). This allows us to go from position to - * dmerID so we can look up values in freq. - * 2. We calculate how many samples the dmer occurs in and save it in - * freqs[dmerId]. - */ - COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx, &COVER_cmp, - &COVER_group); - ctx->freqs = ctx->suffix; - ctx->suffix = NULL; - return 1; -} - -/** - * Given the prepared context build the dictionary. - */ -static size_t COVER_buildDictionary(const COVER_ctx_t *ctx, U32 *freqs, - COVER_map_t *activeDmers, void *dictBuffer, - size_t dictBufferCapacity, - COVER_params_t parameters) -{ - BYTE *const dict = (BYTE *)dictBuffer; - size_t tail = dictBufferCapacity; - /* Divide the data up into epochs of equal size. - * We will select at least one segment from each epoch. - */ - const U32 epochs = (U32)(dictBufferCapacity / parameters.k); - const U32 epochSize = (U32)(ctx->suffixSize / epochs); - size_t epoch; - DISPLAYLEVEL(2, "Breaking content into %u epochs of size %u\n", epochs, - epochSize); - /* Loop through the epochs until there are no more segments or the dictionary - * is full. - */ - for (epoch = 0; tail > 0; epoch = (epoch + 1) % epochs) - { - const U32 epochBegin = (U32)(epoch * epochSize); - const U32 epochEnd = epochBegin + epochSize; - size_t segmentSize; - /* Select a segment */ - COVER_segment_t segment = COVER_selectSegment( - ctx, freqs, activeDmers, epochBegin, epochEnd, parameters); - /* Trim the segment if necessary and if it is empty then we are done */ - segmentSize = MIN(segment.end - segment.begin + parameters.d - 1, tail); - if (segmentSize == 0) - { - break; - } - /* We fill the dictionary from the back to allow the best segments to be - * referenced with the smallest offsets. - */ - tail -= segmentSize; - memcpy(dict + tail, ctx->samples + segment.begin, segmentSize); - DISPLAYUPDATE( - 2, "\r%u%% ", - (U32)(((dictBufferCapacity - tail) * 100) / dictBufferCapacity)); - } - DISPLAYLEVEL(2, "\r%79s\r", ""); - return tail; -} - -/** - * Translate from COVER_params_t to ZDICT_params_t required for finalizing the - * dictionary. - */ -static ZDICT_params_t COVER_translateParams(COVER_params_t parameters) -{ - ZDICT_params_t zdictParams; - memset(&zdictParams, 0, sizeof(zdictParams)); - zdictParams.notificationLevel = 1; - zdictParams.dictID = parameters.dictID; - zdictParams.compressionLevel = parameters.compressionLevel; - return zdictParams; -} - -ZDICTLIB_API size_t COVER_trainFromBuffer( - void *dictBuffer, size_t dictBufferCapacity, const void *samplesBuffer, - const size_t *samplesSizes, unsigned nbSamples, COVER_params_t parameters) -{ - BYTE *const dict = (BYTE *)dictBuffer; - COVER_ctx_t ctx; - COVER_map_t activeDmers; - /* Checks */ - if (!COVER_checkParameters(parameters)) - { - DISPLAYLEVEL(1, "Cover parameters incorrect\n"); - return ERROR(GENERIC); - } - if (nbSamples == 0) - { - DISPLAYLEVEL(1, "Cover must have at least one input file\n"); - return ERROR(GENERIC); - } - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) - { - DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", - ZDICT_DICTSIZE_MIN); - return ERROR(dstSize_tooSmall); - } - /* Initialize global data */ - g_displayLevel = parameters.notificationLevel; - /* Initialize context and activeDmers */ - if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, - parameters.d)) - { - return ERROR(GENERIC); - } - if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) - { - DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); - COVER_ctx_destroy(&ctx); - return ERROR(GENERIC); - } - - DISPLAYLEVEL(2, "Building dictionary\n"); - { - const size_t tail = - COVER_buildDictionary(&ctx, ctx.freqs, &activeDmers, dictBuffer, - dictBufferCapacity, parameters); - ZDICT_params_t zdictParams = COVER_translateParams(parameters); - const size_t dictionarySize = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - samplesBuffer, samplesSizes, nbSamples, zdictParams); - if (!ZSTD_isError(dictionarySize)) - { - DISPLAYLEVEL(2, "Constructed dictionary of size %u\n", - (U32)dictionarySize); - } - COVER_ctx_destroy(&ctx); - COVER_map_destroy(&activeDmers); - return dictionarySize; - } -} - -/** - * COVER_best_t is used for two purposes: - * 1. Synchronizing threads. - * 2. Saving the best parameters and dictionary. - * - * All of the methods except COVER_best_init() are thread safe if zstd is - * compiled with multithreaded support. - */ -typedef struct COVER_best_s -{ - pthread_mutex_t mutex; - pthread_cond_t cond; - size_t liveJobs; - void *dict; - size_t dictSize; - COVER_params_t parameters; - size_t compressedSize; -} COVER_best_t; - -/** - * Initialize the `COVER_best_t`. - */ -static void COVER_best_init(COVER_best_t *best) -{ - if (!best) - { - return; - } - pthread_mutex_init(&best->mutex, NULL); - pthread_cond_init(&best->cond, NULL); - best->liveJobs = 0; - best->dict = NULL; - best->dictSize = 0; - best->compressedSize = (size_t)-1; - memset(&best->parameters, 0, sizeof(best->parameters)); -} - -/** - * Wait until liveJobs == 0. - */ -static void COVER_best_wait(COVER_best_t *best) -{ - if (!best) - { - return; - } - pthread_mutex_lock(&best->mutex); - while (best->liveJobs != 0) - { - pthread_cond_wait(&best->cond, &best->mutex); - } - pthread_mutex_unlock(&best->mutex); -} - -/** - * Call COVER_best_wait() and then destroy the COVER_best_t. - */ -static void COVER_best_destroy(COVER_best_t *best) -{ - if (!best) - { - return; - } - COVER_best_wait(best); - if (best->dict) - { - free(best->dict); - } - pthread_mutex_destroy(&best->mutex); - pthread_cond_destroy(&best->cond); -} - -/** - * Called when a thread is about to be launched. - * Increments liveJobs. - */ -static void COVER_best_start(COVER_best_t *best) -{ - if (!best) - { - return; - } - pthread_mutex_lock(&best->mutex); - ++best->liveJobs; - pthread_mutex_unlock(&best->mutex); -} - -/** - * Called when a thread finishes executing, both on error or success. - * Decrements liveJobs and signals any waiting threads if liveJobs == 0. - * If this dictionary is the best so far save it and its parameters. - */ -static void COVER_best_finish(COVER_best_t *best, size_t compressedSize, - COVER_params_t parameters, void *dict, - size_t dictSize) -{ - if (!best) - { - return; - } - { - size_t liveJobs; - pthread_mutex_lock(&best->mutex); - --best->liveJobs; - liveJobs = best->liveJobs; - /* If the new dictionary is better */ - if (compressedSize < best->compressedSize) - { - /* Allocate space if necessary */ - if (!best->dict || best->dictSize < dictSize) - { - if (best->dict) - { - free(best->dict); - } - best->dict = malloc(dictSize); - if (!best->dict) - { - best->compressedSize = ERROR(GENERIC); - best->dictSize = 0; - return; - } - } - /* Save the dictionary, parameters, and size */ - memcpy(best->dict, dict, dictSize); - best->dictSize = dictSize; - best->parameters = parameters; - best->compressedSize = compressedSize; - } - pthread_mutex_unlock(&best->mutex); - if (liveJobs == 0) - { - pthread_cond_broadcast(&best->cond); - } - } -} - -/** - * Parameters for COVER_tryParameters(). - */ -typedef struct COVER_tryParameters_data_s -{ - const COVER_ctx_t *ctx; - COVER_best_t *best; - size_t dictBufferCapacity; - COVER_params_t parameters; -} COVER_tryParameters_data_t; - -/** - * Tries a set of parameters and upates the COVER_best_t with the results. - * This function is thread safe if zstd is compiled with multithreaded support. - * It takes its parameters as an *OWNING* opaque pointer to support threading. - */ -static void COVER_tryParameters(void *opaque) -{ - /* Save parameters as local variables */ - COVER_tryParameters_data_t *const data = (COVER_tryParameters_data_t *)opaque; - const COVER_ctx_t *const ctx = data->ctx; - const COVER_params_t parameters = data->parameters; - size_t dictBufferCapacity = data->dictBufferCapacity; - size_t totalCompressedSize = ERROR(GENERIC); - /* Allocate space for hash table, dict, and freqs */ - COVER_map_t activeDmers; - BYTE *const dict = (BYTE *const)malloc(dictBufferCapacity); - U32 *freqs = (U32 *)malloc(ctx->suffixSize * sizeof(U32)); - if (!COVER_map_init(&activeDmers, parameters.k - parameters.d + 1)) - { - DISPLAYLEVEL(1, "Failed to allocate dmer map: out of memory\n"); - goto _cleanup; - } - if (!dict || !freqs) - { - DISPLAYLEVEL(1, "Failed to allocate buffers: out of memory\n"); - goto _cleanup; - } - /* Copy the frequencies because we need to modify them */ - memcpy(freqs, ctx->freqs, ctx->suffixSize * sizeof(U32)); - /* Build the dictionary */ - { - const size_t tail = COVER_buildDictionary(ctx, freqs, &activeDmers, dict, - dictBufferCapacity, parameters); - const ZDICT_params_t zdictParams = COVER_translateParams(parameters); - dictBufferCapacity = ZDICT_finalizeDictionary( - dict, dictBufferCapacity, dict + tail, dictBufferCapacity - tail, - ctx->samples, ctx->samplesSizes, (unsigned)ctx->nbSamples, zdictParams); - if (ZDICT_isError(dictBufferCapacity)) - { - DISPLAYLEVEL(1, "Failed to finalize dictionary\n"); - goto _cleanup; - } - } - /* Check total compressed size */ - { - /* Pointers */ - ZSTD_CCtx *cctx; - ZSTD_CDict *cdict; - void *dst; - /* Local variables */ - size_t dstCapacity; - size_t i; - /* Allocate dst with enough space to compress the maximum sized sample */ - { - size_t maxSampleSize = 0; - for (i = 0; i < ctx->nbSamples; ++i) - { - maxSampleSize = MAX(ctx->samplesSizes[i], maxSampleSize); - } - dstCapacity = ZSTD_compressBound(maxSampleSize); - dst = malloc(dstCapacity); - } - /* Create the cctx and cdict */ - cctx = ZSTD_createCCtx(); - cdict = - ZSTD_createCDict(dict, dictBufferCapacity, parameters.compressionLevel); - if (!dst || !cctx || !cdict) - { - goto _compressCleanup; - } - /* Compress each sample and sum their sizes (or error) */ - totalCompressedSize = 0; - for (i = 0; i < ctx->nbSamples; ++i) - { - const size_t size = ZSTD_compress_usingCDict( - cctx, dst, dstCapacity, ctx->samples + ctx->offsets[i], - ctx->samplesSizes[i], cdict); - if (ZSTD_isError(size)) - { - totalCompressedSize = ERROR(GENERIC); - goto _compressCleanup; - } - totalCompressedSize += size; - } - _compressCleanup: - ZSTD_freeCCtx(cctx); - ZSTD_freeCDict(cdict); - if (dst) - { - free(dst); - } - } - -_cleanup: - COVER_best_finish(data->best, totalCompressedSize, parameters, dict, - dictBufferCapacity); - free(data); - COVER_map_destroy(&activeDmers); - if (dict) - { - free(dict); - } - if (freqs) - { - free(freqs); - } -} - -ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, - size_t dictBufferCapacity, - const void *samplesBuffer, - const size_t *samplesSizes, - unsigned nbSamples, - COVER_params_t *parameters) -{ - /* constants */ - const unsigned nbThreads = parameters->nbThreads; - const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; - const unsigned kMaxD = parameters->d == 0 ? 16 : parameters->d; - const unsigned kMinK = parameters->k == 0 ? kMaxD : parameters->k; - const unsigned kMaxK = parameters->k == 0 ? 2048 : parameters->k; - const unsigned kSteps = parameters->steps == 0 ? 32 : parameters->steps; - const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); - const unsigned kIterations = - (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); - /* Local variables */ - const int displayLevel = parameters->notificationLevel; - unsigned iteration = 1; - unsigned d; - unsigned k; - COVER_best_t best; - POOL_ctx *pool = NULL; - /* Checks */ - if (kMinK < kMaxD || kMaxK < kMinK) - { - LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n"); - return ERROR(GENERIC); - } - if (nbSamples == 0) - { - DISPLAYLEVEL(1, "Cover must have at least one input file\n"); - return ERROR(GENERIC); - } - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) - { - DISPLAYLEVEL(1, "dictBufferCapacity must be at least %u\n", - ZDICT_DICTSIZE_MIN); - return ERROR(dstSize_tooSmall); - } - if (nbThreads > 1) - { - pool = POOL_create(nbThreads, 1); - if (!pool) - { - return ERROR(memory_allocation); - } - } - /* Initialization */ - COVER_best_init(&best); - /* Turn down global display level to clean up display at level 2 and below */ - g_displayLevel = parameters->notificationLevel - 1; - /* Loop through d first because each new value needs a new context */ - LOCALDISPLAYLEVEL(displayLevel, 2, "Trying %u different sets of parameters\n", - kIterations); - for (d = kMinD; d <= kMaxD; d += 2) - { - /* Initialize the context for this value of d */ - COVER_ctx_t ctx; - LOCALDISPLAYLEVEL(displayLevel, 3, "d=%u\n", d); - if (!COVER_ctx_init(&ctx, samplesBuffer, samplesSizes, nbSamples, d)) - { - LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to initialize context\n"); - COVER_best_destroy(&best); - POOL_free(pool); - return ERROR(GENERIC); - } - /* Loop through k reusing the same context */ - for (k = kMinK; k <= kMaxK; k += kStepSize) - { - /* Prepare the arguments */ - COVER_tryParameters_data_t *data = (COVER_tryParameters_data_t *)malloc( - sizeof(COVER_tryParameters_data_t)); - LOCALDISPLAYLEVEL(displayLevel, 3, "k=%u\n", k); - if (!data) - { - LOCALDISPLAYLEVEL(displayLevel, 1, "Failed to allocate parameters\n"); - COVER_best_destroy(&best); - COVER_ctx_destroy(&ctx); - POOL_free(pool); - return ERROR(GENERIC); - } - data->ctx = &ctx; - data->best = &best; - data->dictBufferCapacity = dictBufferCapacity; - data->parameters = *parameters; - data->parameters.k = k; - data->parameters.d = d; - data->parameters.steps = kSteps; - /* Check the parameters */ - if (!COVER_checkParameters(data->parameters)) - { - DISPLAYLEVEL(1, "Cover parameters incorrect\n"); - free(data); - continue; - } - /* Call the function and pass ownership of data to it */ - COVER_best_start(&best); - if (pool) - { - POOL_add(pool, &COVER_tryParameters, data); - } - else - { - COVER_tryParameters(data); - } - /* Print status */ - LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ", - (U32)((iteration * 100) / kIterations)); - ++iteration; - } - COVER_best_wait(&best); - COVER_ctx_destroy(&ctx); - } - LOCALDISPLAYLEVEL(displayLevel, 2, "\r%79s\r", ""); - /* Fill the output buffer and parameters with output of the best parameters */ - { - const size_t dictSize = best.dictSize; - if (ZSTD_isError(best.compressedSize)) - { - const size_t compressedSize = best.compressedSize; - COVER_best_destroy(&best); - POOL_free(pool); - return compressedSize; - } - *parameters = best.parameters; - memcpy(dictBuffer, best.dict, dictSize); - COVER_best_destroy(&best); - POOL_free(pool); - return dictSize; - } -} diff --git a/extra/zstd/divsufsort.c b/extra/zstd/divsufsort.c deleted file mode 100644 index 0c614450..00000000 --- a/extra/zstd/divsufsort.c +++ /dev/null @@ -1,2765 +0,0 @@ -/* - * divsufsort.c for libdivsufsort-lite - * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/*- Compiler specifics -*/ -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wshorten-64-to-32" -#endif - -#if defined(_MSC_VER) -#pragma warning(disable : 4244) -#pragma warning(disable : 4127) /* C4127 : Condition expression is constant */ -#endif - -/*- Dependencies -*/ -#include -#include -#include - -#include "divsufsort.h" - -/*- Constants -*/ -#if defined(INLINE) -#undef INLINE -#endif -#if !defined(INLINE) -#define INLINE __inline -#endif -#if defined(ALPHABET_SIZE) && (ALPHABET_SIZE < 1) -#undef ALPHABET_SIZE -#endif -#if !defined(ALPHABET_SIZE) -#define ALPHABET_SIZE (256) -#endif -#define BUCKET_A_SIZE (ALPHABET_SIZE) -#define BUCKET_B_SIZE (ALPHABET_SIZE * ALPHABET_SIZE) -#if defined(SS_INSERTIONSORT_THRESHOLD) -#if SS_INSERTIONSORT_THRESHOLD < 1 -#undef SS_INSERTIONSORT_THRESHOLD -#define SS_INSERTIONSORT_THRESHOLD (1) -#endif -#else -#define SS_INSERTIONSORT_THRESHOLD (8) -#endif -#if defined(SS_BLOCKSIZE) -#if SS_BLOCKSIZE < 0 -#undef SS_BLOCKSIZE -#define SS_BLOCKSIZE (0) -#elif 32768 <= SS_BLOCKSIZE -#undef SS_BLOCKSIZE -#define SS_BLOCKSIZE (32767) -#endif -#else -#define SS_BLOCKSIZE (1024) -#endif -/* minstacksize = log(SS_BLOCKSIZE) / log(3) * 2 */ -#if SS_BLOCKSIZE == 0 -#define SS_MISORT_STACKSIZE (96) -#elif SS_BLOCKSIZE <= 4096 -#define SS_MISORT_STACKSIZE (16) -#else -#define SS_MISORT_STACKSIZE (24) -#endif -#define SS_SMERGE_STACKSIZE (32) -#define TR_INSERTIONSORT_THRESHOLD (8) -#define TR_STACKSIZE (64) - -/*- Macros -*/ -#ifndef SWAP -#define SWAP(_a, _b) \ - do \ - { \ - t = (_a); \ - (_a) = (_b); \ - (_b) = t; \ - } while (0) -#endif /* SWAP */ -#ifndef MIN -#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) -#endif /* MIN */ -#ifndef MAX -#define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) -#endif /* MAX */ -#define STACK_PUSH(_a, _b, _c, _d) \ - do \ - { \ - assert(ssize < STACK_SIZE); \ - stack[ssize].a = (_a), stack[ssize].b = (_b), \ - stack[ssize].c = (_c), stack[ssize++].d = (_d); \ - } while (0) -#define STACK_PUSH5(_a, _b, _c, _d, _e) \ - do \ - { \ - assert(ssize < STACK_SIZE); \ - stack[ssize].a = (_a), stack[ssize].b = (_b), \ - stack[ssize].c = (_c), stack[ssize].d = (_d), stack[ssize++].e = (_e); \ - } while (0) -#define STACK_POP(_a, _b, _c, _d) \ - do \ - { \ - assert(0 <= ssize); \ - if (ssize == 0) \ - { \ - return; \ - } \ - (_a) = stack[--ssize].a, (_b) = stack[ssize].b, \ - (_c) = stack[ssize].c, (_d) = stack[ssize].d; \ - } while (0) -#define STACK_POP5(_a, _b, _c, _d, _e) \ - do \ - { \ - assert(0 <= ssize); \ - if (ssize == 0) \ - { \ - return; \ - } \ - (_a) = stack[--ssize].a, (_b) = stack[ssize].b, \ - (_c) = stack[ssize].c, (_d) = stack[ssize].d, (_e) = stack[ssize].e; \ - } while (0) -#define BUCKET_A(_c0) bucket_A[(_c0)] -#if ALPHABET_SIZE == 256 -#define BUCKET_B(_c0, _c1) (bucket_B[((_c1) << 8) | (_c0)]) -#define BUCKET_BSTAR(_c0, _c1) (bucket_B[((_c0) << 8) | (_c1)]) -#else -#define BUCKET_B(_c0, _c1) (bucket_B[(_c1) * ALPHABET_SIZE + (_c0)]) -#define BUCKET_BSTAR(_c0, _c1) (bucket_B[(_c0) * ALPHABET_SIZE + (_c1)]) -#endif - -/*- Private Functions -*/ - -static const int lg_table[256] = { - -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; - -#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) - -static INLINE int -ss_ilg(int n) -{ -#if SS_BLOCKSIZE == 0 - return (n & 0xffff0000) ? ((n & 0xff000000) ? 24 + lg_table[(n >> 24) & 0xff] : 16 + lg_table[(n >> 16) & 0xff]) : ((n & 0x0000ff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]); -#elif SS_BLOCKSIZE < 256 - return lg_table[n]; -#else - return (n & 0xff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]; -#endif -} - -#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ - -#if SS_BLOCKSIZE != 0 - -static const int sqq_table[256] = { - 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, - 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, - 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, - 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 128, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, - 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, - 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, 179, 180, - 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, - 192, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, - 202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, - 212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, - 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, - 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, - 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, - 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255}; - -static INLINE int -ss_isqrt(int x) -{ - int y, e; - - if (x >= (SS_BLOCKSIZE * SS_BLOCKSIZE)) - { - return SS_BLOCKSIZE; - } - e = (x & 0xffff0000) ? ((x & 0xff000000) ? 24 + lg_table[(x >> 24) & 0xff] : 16 + lg_table[(x >> 16) & 0xff]) : ((x & 0x0000ff00) ? 8 + lg_table[(x >> 8) & 0xff] : 0 + lg_table[(x >> 0) & 0xff]); - - if (e >= 16) - { - y = sqq_table[x >> ((e - 6) - (e & 1))] << ((e >> 1) - 7); - if (e >= 24) - { - y = (y + 1 + x / y) >> 1; - } - y = (y + 1 + x / y) >> 1; - } - else if (e >= 8) - { - y = (sqq_table[x >> ((e - 6) - (e & 1))] >> (7 - (e >> 1))) + 1; - } - else - { - return sqq_table[x] >> 4; - } - - return (x < (y * y)) ? y - 1 : y; -} - -#endif /* SS_BLOCKSIZE != 0 */ - -/*---------------------------------------------------------------------------*/ - -/* Compares two suffixes. */ -static INLINE int -ss_compare(const unsigned char *T, - const int *p1, const int *p2, - int depth) -{ - const unsigned char *U1, *U2, *U1n, *U2n; - - for (U1 = T + depth + *p1, - U2 = T + depth + *p2, - U1n = T + *(p1 + 1) + 2, - U2n = T + *(p2 + 1) + 2; - (U1 < U1n) && (U2 < U2n) && (*U1 == *U2); - ++U1, ++U2) - { - } - - return U1 < U1n ? (U2 < U2n ? *U1 - *U2 : 1) : (U2 < U2n ? -1 : 0); -} - -/*---------------------------------------------------------------------------*/ - -#if (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) - -/* Insertionsort for small size groups */ -static void -ss_insertionsort(const unsigned char *T, const int *PA, - int *first, int *last, int depth) -{ - int *i, *j; - int t; - int r; - - for (i = last - 2; first <= i; --i) - { - for (t = *i, j = i + 1; 0 < (r = ss_compare(T, PA + t, PA + *j, depth));) - { - do - { - *(j - 1) = *j; - } while ((++j < last) && (*j < 0)); - if (last <= j) - { - break; - } - } - if (r == 0) - { - *j = ~*j; - } - *(j - 1) = t; - } -} - -#endif /* (SS_BLOCKSIZE != 1) && (SS_INSERTIONSORT_THRESHOLD != 1) */ - -/*---------------------------------------------------------------------------*/ - -#if (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) - -static INLINE void -ss_fixdown(const unsigned char *Td, const int *PA, - int *SA, int i, int size) -{ - int j, k; - int v; - int c, d, e; - - for (v = SA[i], c = Td[PA[v]]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) - { - d = Td[PA[SA[k = j++]]]; - if (d < (e = Td[PA[SA[j]]])) - { - k = j; - d = e; - } - if (d <= c) - { - break; - } - } - SA[i] = v; -} - -/* Simple top-down heapsort. */ -static void -ss_heapsort(const unsigned char *Td, const int *PA, int *SA, int size) -{ - int i, m; - int t; - - m = size; - if ((size % 2) == 0) - { - m--; - if (Td[PA[SA[m / 2]]] < Td[PA[SA[m]]]) - { - SWAP(SA[m], SA[m / 2]); - } - } - - for (i = m / 2 - 1; 0 <= i; --i) - { - ss_fixdown(Td, PA, SA, i, m); - } - if ((size % 2) == 0) - { - SWAP(SA[0], SA[m]); - ss_fixdown(Td, PA, SA, 0, m); - } - for (i = m - 1; 0 < i; --i) - { - t = SA[0], SA[0] = SA[i]; - ss_fixdown(Td, PA, SA, 0, i); - SA[i] = t; - } -} - -/*---------------------------------------------------------------------------*/ - -/* Returns the median of three elements. */ -static INLINE int * -ss_median3(const unsigned char *Td, const int *PA, - int *v1, int *v2, int *v3) -{ - int *t; - if (Td[PA[*v1]] > Td[PA[*v2]]) - { - SWAP(v1, v2); - } - if (Td[PA[*v2]] > Td[PA[*v3]]) - { - if (Td[PA[*v1]] > Td[PA[*v3]]) - { - return v1; - } - else - { - return v3; - } - } - return v2; -} - -/* Returns the median of five elements. */ -static INLINE int * -ss_median5(const unsigned char *Td, const int *PA, - int *v1, int *v2, int *v3, int *v4, int *v5) -{ - int *t; - if (Td[PA[*v2]] > Td[PA[*v3]]) - { - SWAP(v2, v3); - } - if (Td[PA[*v4]] > Td[PA[*v5]]) - { - SWAP(v4, v5); - } - if (Td[PA[*v2]] > Td[PA[*v4]]) - { - SWAP(v2, v4); - SWAP(v3, v5); - } - if (Td[PA[*v1]] > Td[PA[*v3]]) - { - SWAP(v1, v3); - } - if (Td[PA[*v1]] > Td[PA[*v4]]) - { - SWAP(v1, v4); - SWAP(v3, v5); - } - if (Td[PA[*v3]] > Td[PA[*v4]]) - { - return v4; - } - return v3; -} - -/* Returns the pivot element. */ -static INLINE int * -ss_pivot(const unsigned char *Td, const int *PA, int *first, int *last) -{ - int *middle; - int t; - - t = last - first; - middle = first + t / 2; - - if (t <= 512) - { - if (t <= 32) - { - return ss_median3(Td, PA, first, middle, last - 1); - } - else - { - t >>= 2; - return ss_median5(Td, PA, first, first + t, middle, last - 1 - t, last - 1); - } - } - t >>= 3; - first = ss_median3(Td, PA, first, first + t, first + (t << 1)); - middle = ss_median3(Td, PA, middle - t, middle, middle + t); - last = ss_median3(Td, PA, last - 1 - (t << 1), last - 1 - t, last - 1); - return ss_median3(Td, PA, first, middle, last); -} - -/*---------------------------------------------------------------------------*/ - -/* Binary partition for substrings. */ -static INLINE int * -ss_partition(const int *PA, - int *first, int *last, int depth) -{ - int *a, *b; - int t; - for (a = first - 1, b = last;;) - { - for (; (++a < b) && ((PA[*a] + depth) >= (PA[*a + 1] + 1));) - { - *a = ~*a; - } - for (; (a < --b) && ((PA[*b] + depth) < (PA[*b + 1] + 1));) - { - } - if (b <= a) - { - break; - } - t = ~*b; - *b = *a; - *a = t; - } - if (first < a) - { - *first = ~*first; - } - return a; -} - -/* Multikey introsort for medium size groups. */ -static void -ss_mintrosort(const unsigned char *T, const int *PA, - int *first, int *last, - int depth) -{ -#define STACK_SIZE SS_MISORT_STACKSIZE - struct - { - int *a, *b, c; - int d; - } stack[STACK_SIZE]; - const unsigned char *Td; - int *a, *b, *c, *d, *e, *f; - int s, t; - int ssize; - int limit; - int v, x = 0; - - for (ssize = 0, limit = ss_ilg(last - first);;) - { - - if ((last - first) <= SS_INSERTIONSORT_THRESHOLD) - { -#if 1 < SS_INSERTIONSORT_THRESHOLD - if (1 < (last - first)) - { - ss_insertionsort(T, PA, first, last, depth); - } -#endif - STACK_POP(first, last, depth, limit); - continue; - } - - Td = T + depth; - if (limit-- == 0) - { - ss_heapsort(Td, PA, first, last - first); - } - if (limit < 0) - { - for (a = first + 1, v = Td[PA[*first]]; a < last; ++a) - { - if ((x = Td[PA[*a]]) != v) - { - if (1 < (a - first)) - { - break; - } - v = x; - first = a; - } - } - if (Td[PA[*first] - 1] < v) - { - first = ss_partition(PA, first, a, depth); - } - if ((a - first) <= (last - a)) - { - if (1 < (a - first)) - { - STACK_PUSH(a, last, depth, -1); - last = a, depth += 1, limit = ss_ilg(a - first); - } - else - { - first = a, limit = -1; - } - } - else - { - if (1 < (last - a)) - { - STACK_PUSH(first, a, depth + 1, ss_ilg(a - first)); - first = a, limit = -1; - } - else - { - last = a, depth += 1, limit = ss_ilg(a - first); - } - } - continue; - } - - /* choose pivot */ - a = ss_pivot(Td, PA, first, last); - v = Td[PA[*a]]; - SWAP(*first, *a); - - /* partition */ - for (b = first; (++b < last) && ((x = Td[PA[*b]]) == v);) - { - } - if (((a = b) < last) && (x < v)) - { - for (; (++b < last) && ((x = Td[PA[*b]]) <= v);) - { - if (x == v) - { - SWAP(*b, *a); - ++a; - } - } - } - for (c = last; (b < --c) && ((x = Td[PA[*c]]) == v);) - { - } - if ((b < (d = c)) && (x > v)) - { - for (; (b < --c) && ((x = Td[PA[*c]]) >= v);) - { - if (x == v) - { - SWAP(*c, *d); - --d; - } - } - } - for (; b < c;) - { - SWAP(*b, *c); - for (; (++b < c) && ((x = Td[PA[*b]]) <= v);) - { - if (x == v) - { - SWAP(*b, *a); - ++a; - } - } - for (; (b < --c) && ((x = Td[PA[*c]]) >= v);) - { - if (x == v) - { - SWAP(*c, *d); - --d; - } - } - } - - if (a <= d) - { - c = b - 1; - - if ((s = a - first) > (t = b - a)) - { - s = t; - } - for (e = first, f = b - s; 0 < s; --s, ++e, ++f) - { - SWAP(*e, *f); - } - if ((s = d - c) > (t = last - d - 1)) - { - s = t; - } - for (e = b, f = last - s; 0 < s; --s, ++e, ++f) - { - SWAP(*e, *f); - } - - a = first + (b - a), c = last - (d - c); - b = (v <= Td[PA[*a] - 1]) ? a : ss_partition(PA, a, c, depth); - - if ((a - first) <= (last - c)) - { - if ((last - c) <= (c - b)) - { - STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); - STACK_PUSH(c, last, depth, limit); - last = a; - } - else if ((a - first) <= (c - b)) - { - STACK_PUSH(c, last, depth, limit); - STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); - last = a; - } - else - { - STACK_PUSH(c, last, depth, limit); - STACK_PUSH(first, a, depth, limit); - first = b, last = c, depth += 1, limit = ss_ilg(c - b); - } - } - else - { - if ((a - first) <= (c - b)) - { - STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); - STACK_PUSH(first, a, depth, limit); - first = c; - } - else if ((last - c) <= (c - b)) - { - STACK_PUSH(first, a, depth, limit); - STACK_PUSH(b, c, depth + 1, ss_ilg(c - b)); - first = c; - } - else - { - STACK_PUSH(first, a, depth, limit); - STACK_PUSH(c, last, depth, limit); - first = b, last = c, depth += 1, limit = ss_ilg(c - b); - } - } - } - else - { - limit += 1; - if (Td[PA[*first] - 1] < v) - { - first = ss_partition(PA, first, last, depth); - limit = ss_ilg(last - first); - } - depth += 1; - } - } -#undef STACK_SIZE -} - -#endif /* (SS_BLOCKSIZE == 0) || (SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE) */ - -/*---------------------------------------------------------------------------*/ - -#if SS_BLOCKSIZE != 0 - -static INLINE void -ss_blockswap(int *a, int *b, int n) -{ - int t; - for (; 0 < n; --n, ++a, ++b) - { - t = *a, *a = *b, *b = t; - } -} - -static INLINE void -ss_rotate(int *first, int *middle, int *last) -{ - int *a, *b, t; - int l, r; - l = middle - first, r = last - middle; - for (; (0 < l) && (0 < r);) - { - if (l == r) - { - ss_blockswap(first, middle, l); - break; - } - if (l < r) - { - a = last - 1, b = middle - 1; - t = *a; - do - { - *a-- = *b, *b-- = *a; - if (b < first) - { - *a = t; - last = a; - if ((r -= l + 1) <= l) - { - break; - } - a -= 1, b = middle - 1; - t = *a; - } - } while (1); - } - else - { - a = first, b = middle; - t = *a; - do - { - *a++ = *b, *b++ = *a; - if (last <= b) - { - *a = t; - first = a + 1; - if ((l -= r + 1) <= r) - { - break; - } - a += 1, b = middle; - t = *a; - } - } while (1); - } - } -} - -/*---------------------------------------------------------------------------*/ - -static void -ss_inplacemerge(const unsigned char *T, const int *PA, - int *first, int *middle, int *last, - int depth) -{ - const int *p; - int *a, *b; - int len, half; - int q, r; - int x; - - for (;;) - { - if (*(last - 1) < 0) - { - x = 1; - p = PA + ~*(last - 1); - } - else - { - x = 0; - p = PA + *(last - 1); - } - for (a = first, len = middle - first, half = len >> 1, r = -1; - 0 < len; - len = half, half >>= 1) - { - b = a + half; - q = ss_compare(T, PA + ((0 <= *b) ? *b : ~*b), p, depth); - if (q < 0) - { - a = b + 1; - half -= (len & 1) ^ 1; - } - else - { - r = q; - } - } - if (a < middle) - { - if (r == 0) - { - *a = ~*a; - } - ss_rotate(a, middle, last); - last -= middle - a; - middle = a; - if (first == middle) - { - break; - } - } - --last; - if (x != 0) - { - while (*--last < 0) - { - } - } - if (middle == last) - { - break; - } - } -} - -/*---------------------------------------------------------------------------*/ - -/* Merge-forward with internal buffer. */ -static void -ss_mergeforward(const unsigned char *T, const int *PA, - int *first, int *middle, int *last, - int *buf, int depth) -{ - int *a, *b, *c, *bufend; - int t; - int r; - - bufend = buf + (middle - first) - 1; - ss_blockswap(buf, first, middle - first); - - for (t = *(a = first), b = buf, c = middle;;) - { - r = ss_compare(T, PA + *b, PA + *c, depth); - if (r < 0) - { - do - { - *a++ = *b; - if (bufend <= b) - { - *bufend = t; - return; - } - *b++ = *a; - } while (*b < 0); - } - else if (r > 0) - { - do - { - *a++ = *c, *c++ = *a; - if (last <= c) - { - while (b < bufend) - { - *a++ = *b, *b++ = *a; - } - *a = *b, *b = t; - return; - } - } while (*c < 0); - } - else - { - *c = ~*c; - do - { - *a++ = *b; - if (bufend <= b) - { - *bufend = t; - return; - } - *b++ = *a; - } while (*b < 0); - - do - { - *a++ = *c, *c++ = *a; - if (last <= c) - { - while (b < bufend) - { - *a++ = *b, *b++ = *a; - } - *a = *b, *b = t; - return; - } - } while (*c < 0); - } - } -} - -/* Merge-backward with internal buffer. */ -static void -ss_mergebackward(const unsigned char *T, const int *PA, - int *first, int *middle, int *last, - int *buf, int depth) -{ - const int *p1, *p2; - int *a, *b, *c, *bufend; - int t; - int r; - int x; - - bufend = buf + (last - middle) - 1; - ss_blockswap(buf, middle, last - middle); - - x = 0; - if (*bufend < 0) - { - p1 = PA + ~*bufend; - x |= 1; - } - else - { - p1 = PA + *bufend; - } - if (*(middle - 1) < 0) - { - p2 = PA + ~*(middle - 1); - x |= 2; - } - else - { - p2 = PA + *(middle - 1); - } - for (t = *(a = last - 1), b = bufend, c = middle - 1;;) - { - r = ss_compare(T, p1, p2, depth); - if (0 < r) - { - if (x & 1) - { - do - { - *a-- = *b, *b-- = *a; - } while (*b < 0); - x ^= 1; - } - *a-- = *b; - if (b <= buf) - { - *buf = t; - break; - } - *b-- = *a; - if (*b < 0) - { - p1 = PA + ~*b; - x |= 1; - } - else - { - p1 = PA + *b; - } - } - else if (r < 0) - { - if (x & 2) - { - do - { - *a-- = *c, *c-- = *a; - } while (*c < 0); - x ^= 2; - } - *a-- = *c, *c-- = *a; - if (c < first) - { - while (buf < b) - { - *a-- = *b, *b-- = *a; - } - *a = *b, *b = t; - break; - } - if (*c < 0) - { - p2 = PA + ~*c; - x |= 2; - } - else - { - p2 = PA + *c; - } - } - else - { - if (x & 1) - { - do - { - *a-- = *b, *b-- = *a; - } while (*b < 0); - x ^= 1; - } - *a-- = ~*b; - if (b <= buf) - { - *buf = t; - break; - } - *b-- = *a; - if (x & 2) - { - do - { - *a-- = *c, *c-- = *a; - } while (*c < 0); - x ^= 2; - } - *a-- = *c, *c-- = *a; - if (c < first) - { - while (buf < b) - { - *a-- = *b, *b-- = *a; - } - *a = *b, *b = t; - break; - } - if (*b < 0) - { - p1 = PA + ~*b; - x |= 1; - } - else - { - p1 = PA + *b; - } - if (*c < 0) - { - p2 = PA + ~*c; - x |= 2; - } - else - { - p2 = PA + *c; - } - } - } -} - -/* D&C based merge. */ -static void -ss_swapmerge(const unsigned char *T, const int *PA, - int *first, int *middle, int *last, - int *buf, int bufsize, int depth) -{ -#define STACK_SIZE SS_SMERGE_STACKSIZE -#define GETIDX(a) ((0 <= (a)) ? (a) : (~(a))) -#define MERGE_CHECK(a, b, c) \ - do \ - { \ - if (((c) & 1) || \ - (((c) & 2) && (ss_compare(T, PA + GETIDX(*((a)-1)), PA + *(a), depth) == 0))) \ - { \ - *(a) = ~*(a); \ - } \ - if (((c) & 4) && ((ss_compare(T, PA + GETIDX(*((b)-1)), PA + *(b), depth) == 0))) \ - { \ - *(b) = ~*(b); \ - } \ - } while (0) - struct - { - int *a, *b, *c; - int d; - } stack[STACK_SIZE]; - int *l, *r, *lm, *rm; - int m, len, half; - int ssize; - int check, next; - - for (check = 0, ssize = 0;;) - { - if ((last - middle) <= bufsize) - { - if ((first < middle) && (middle < last)) - { - ss_mergebackward(T, PA, first, middle, last, buf, depth); - } - MERGE_CHECK(first, last, check); - STACK_POP(first, middle, last, check); - continue; - } - - if ((middle - first) <= bufsize) - { - if (first < middle) - { - ss_mergeforward(T, PA, first, middle, last, buf, depth); - } - MERGE_CHECK(first, last, check); - STACK_POP(first, middle, last, check); - continue; - } - - for (m = 0, len = MIN(middle - first, last - middle), half = len >> 1; - 0 < len; - len = half, half >>= 1) - { - if (ss_compare(T, PA + GETIDX(*(middle + m + half)), - PA + GETIDX(*(middle - m - half - 1)), depth) < 0) - { - m += half + 1; - half -= (len & 1) ^ 1; - } - } - - if (0 < m) - { - lm = middle - m, rm = middle + m; - ss_blockswap(lm, middle, m); - l = r = middle, next = 0; - if (rm < last) - { - if (*rm < 0) - { - *rm = ~*rm; - if (first < lm) - { - for (; *--l < 0;) - { - } - next |= 4; - } - next |= 1; - } - else if (first < lm) - { - for (; *r < 0; ++r) - { - } - next |= 2; - } - } - - if ((l - first) <= (last - r)) - { - STACK_PUSH(r, rm, last, (next & 3) | (check & 4)); - middle = lm, last = l, check = (check & 3) | (next & 4); - } - else - { - if ((next & 2) && (r == middle)) - { - next ^= 6; - } - STACK_PUSH(first, lm, l, (check & 3) | (next & 4)); - first = r, middle = rm, check = (next & 3) | (check & 4); - } - } - else - { - if (ss_compare(T, PA + GETIDX(*(middle - 1)), PA + *middle, depth) == 0) - { - *middle = ~*middle; - } - MERGE_CHECK(first, last, check); - STACK_POP(first, middle, last, check); - } - } -#undef STACK_SIZE -} - -#endif /* SS_BLOCKSIZE != 0 */ - -/*---------------------------------------------------------------------------*/ - -/* Substring sort */ -static void -sssort(const unsigned char *T, const int *PA, - int *first, int *last, - int *buf, int bufsize, - int depth, int n, int lastsuffix) -{ - int *a; -#if SS_BLOCKSIZE != 0 - int *b, *middle, *curbuf; - int j, k, curbufsize, limit; -#endif - int i; - - if (lastsuffix != 0) - { - ++first; - } - -#if SS_BLOCKSIZE == 0 - ss_mintrosort(T, PA, first, last, depth); -#else - if ((bufsize < SS_BLOCKSIZE) && - (bufsize < (last - first)) && - (bufsize < (limit = ss_isqrt(last - first)))) - { - if (SS_BLOCKSIZE < limit) - { - limit = SS_BLOCKSIZE; - } - buf = middle = last - limit, bufsize = limit; - } - else - { - middle = last, limit = 0; - } - for (a = first, i = 0; SS_BLOCKSIZE < (middle - a); a += SS_BLOCKSIZE, ++i) - { -#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE - ss_mintrosort(T, PA, a, a + SS_BLOCKSIZE, depth); -#elif 1 < SS_BLOCKSIZE - ss_insertionsort(T, PA, a, a + SS_BLOCKSIZE, depth); -#endif - curbufsize = last - (a + SS_BLOCKSIZE); - curbuf = a + SS_BLOCKSIZE; - if (curbufsize <= bufsize) - { - curbufsize = bufsize, curbuf = buf; - } - for (b = a, k = SS_BLOCKSIZE, j = i; j & 1; b -= k, k <<= 1, j >>= 1) - { - ss_swapmerge(T, PA, b - k, b, b + k, curbuf, curbufsize, depth); - } - } -#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE - ss_mintrosort(T, PA, a, middle, depth); -#elif 1 < SS_BLOCKSIZE - ss_insertionsort(T, PA, a, middle, depth); -#endif - for (k = SS_BLOCKSIZE; i != 0; k <<= 1, i >>= 1) - { - if (i & 1) - { - ss_swapmerge(T, PA, a - k, a, middle, buf, bufsize, depth); - a -= k; - } - } - if (limit != 0) - { -#if SS_INSERTIONSORT_THRESHOLD < SS_BLOCKSIZE - ss_mintrosort(T, PA, middle, last, depth); -#elif 1 < SS_BLOCKSIZE - ss_insertionsort(T, PA, middle, last, depth); -#endif - ss_inplacemerge(T, PA, first, middle, last, depth); - } -#endif - - if (lastsuffix != 0) - { - /* Insert last type B* suffix. */ - int PAi[2]; - PAi[0] = PA[*(first - 1)], PAi[1] = n - 2; - for (a = first, i = *(first - 1); - (a < last) && ((*a < 0) || (0 < ss_compare(T, &(PAi[0]), PA + *a, depth))); - ++a) - { - *(a - 1) = *a; - } - *(a - 1) = i; - } -} - -/*---------------------------------------------------------------------------*/ - -static INLINE int -tr_ilg(int n) -{ - return (n & 0xffff0000) ? ((n & 0xff000000) ? 24 + lg_table[(n >> 24) & 0xff] : 16 + lg_table[(n >> 16) & 0xff]) : ((n & 0x0000ff00) ? 8 + lg_table[(n >> 8) & 0xff] : 0 + lg_table[(n >> 0) & 0xff]); -} - -/*---------------------------------------------------------------------------*/ - -/* Simple insertionsort for small size groups. */ -static void -tr_insertionsort(const int *ISAd, int *first, int *last) -{ - int *a, *b; - int t, r; - - for (a = first + 1; a < last; ++a) - { - for (t = *a, b = a - 1; 0 > (r = ISAd[t] - ISAd[*b]);) - { - do - { - *(b + 1) = *b; - } while ((first <= --b) && (*b < 0)); - if (b < first) - { - break; - } - } - if (r == 0) - { - *b = ~*b; - } - *(b + 1) = t; - } -} - -/*---------------------------------------------------------------------------*/ - -static INLINE void -tr_fixdown(const int *ISAd, int *SA, int i, int size) -{ - int j, k; - int v; - int c, d, e; - - for (v = SA[i], c = ISAd[v]; (j = 2 * i + 1) < size; SA[i] = SA[k], i = k) - { - d = ISAd[SA[k = j++]]; - if (d < (e = ISAd[SA[j]])) - { - k = j; - d = e; - } - if (d <= c) - { - break; - } - } - SA[i] = v; -} - -/* Simple top-down heapsort. */ -static void -tr_heapsort(const int *ISAd, int *SA, int size) -{ - int i, m; - int t; - - m = size; - if ((size % 2) == 0) - { - m--; - if (ISAd[SA[m / 2]] < ISAd[SA[m]]) - { - SWAP(SA[m], SA[m / 2]); - } - } - - for (i = m / 2 - 1; 0 <= i; --i) - { - tr_fixdown(ISAd, SA, i, m); - } - if ((size % 2) == 0) - { - SWAP(SA[0], SA[m]); - tr_fixdown(ISAd, SA, 0, m); - } - for (i = m - 1; 0 < i; --i) - { - t = SA[0], SA[0] = SA[i]; - tr_fixdown(ISAd, SA, 0, i); - SA[i] = t; - } -} - -/*---------------------------------------------------------------------------*/ - -/* Returns the median of three elements. */ -static INLINE int * -tr_median3(const int *ISAd, int *v1, int *v2, int *v3) -{ - int *t; - if (ISAd[*v1] > ISAd[*v2]) - { - SWAP(v1, v2); - } - if (ISAd[*v2] > ISAd[*v3]) - { - if (ISAd[*v1] > ISAd[*v3]) - { - return v1; - } - else - { - return v3; - } - } - return v2; -} - -/* Returns the median of five elements. */ -static INLINE int * -tr_median5(const int *ISAd, - int *v1, int *v2, int *v3, int *v4, int *v5) -{ - int *t; - if (ISAd[*v2] > ISAd[*v3]) - { - SWAP(v2, v3); - } - if (ISAd[*v4] > ISAd[*v5]) - { - SWAP(v4, v5); - } - if (ISAd[*v2] > ISAd[*v4]) - { - SWAP(v2, v4); - SWAP(v3, v5); - } - if (ISAd[*v1] > ISAd[*v3]) - { - SWAP(v1, v3); - } - if (ISAd[*v1] > ISAd[*v4]) - { - SWAP(v1, v4); - SWAP(v3, v5); - } - if (ISAd[*v3] > ISAd[*v4]) - { - return v4; - } - return v3; -} - -/* Returns the pivot element. */ -static INLINE int * -tr_pivot(const int *ISAd, int *first, int *last) -{ - int *middle; - int t; - - t = last - first; - middle = first + t / 2; - - if (t <= 512) - { - if (t <= 32) - { - return tr_median3(ISAd, first, middle, last - 1); - } - else - { - t >>= 2; - return tr_median5(ISAd, first, first + t, middle, last - 1 - t, last - 1); - } - } - t >>= 3; - first = tr_median3(ISAd, first, first + t, first + (t << 1)); - middle = tr_median3(ISAd, middle - t, middle, middle + t); - last = tr_median3(ISAd, last - 1 - (t << 1), last - 1 - t, last - 1); - return tr_median3(ISAd, first, middle, last); -} - -/*---------------------------------------------------------------------------*/ - -typedef struct _trbudget_t trbudget_t; -struct _trbudget_t -{ - int chance; - int remain; - int incval; - int count; -}; - -static INLINE void -trbudget_init(trbudget_t *budget, int chance, int incval) -{ - budget->chance = chance; - budget->remain = budget->incval = incval; -} - -static INLINE int -trbudget_check(trbudget_t *budget, int size) -{ - if (size <= budget->remain) - { - budget->remain -= size; - return 1; - } - if (budget->chance == 0) - { - budget->count += size; - return 0; - } - budget->remain += budget->incval - size; - budget->chance -= 1; - return 1; -} - -/*---------------------------------------------------------------------------*/ - -static INLINE void -tr_partition(const int *ISAd, - int *first, int *middle, int *last, - int **pa, int **pb, int v) -{ - int *a, *b, *c, *d, *e, *f; - int t, s; - int x = 0; - - for (b = middle - 1; (++b < last) && ((x = ISAd[*b]) == v);) - { - } - if (((a = b) < last) && (x < v)) - { - for (; (++b < last) && ((x = ISAd[*b]) <= v);) - { - if (x == v) - { - SWAP(*b, *a); - ++a; - } - } - } - for (c = last; (b < --c) && ((x = ISAd[*c]) == v);) - { - } - if ((b < (d = c)) && (x > v)) - { - for (; (b < --c) && ((x = ISAd[*c]) >= v);) - { - if (x == v) - { - SWAP(*c, *d); - --d; - } - } - } - for (; b < c;) - { - SWAP(*b, *c); - for (; (++b < c) && ((x = ISAd[*b]) <= v);) - { - if (x == v) - { - SWAP(*b, *a); - ++a; - } - } - for (; (b < --c) && ((x = ISAd[*c]) >= v);) - { - if (x == v) - { - SWAP(*c, *d); - --d; - } - } - } - - if (a <= d) - { - c = b - 1; - if ((s = a - first) > (t = b - a)) - { - s = t; - } - for (e = first, f = b - s; 0 < s; --s, ++e, ++f) - { - SWAP(*e, *f); - } - if ((s = d - c) > (t = last - d - 1)) - { - s = t; - } - for (e = b, f = last - s; 0 < s; --s, ++e, ++f) - { - SWAP(*e, *f); - } - first += (b - a), last -= (d - c); - } - *pa = first, *pb = last; -} - -static void -tr_copy(int *ISA, const int *SA, - int *first, int *a, int *b, int *last, - int depth) -{ - /* sort suffixes of middle partition - by using sorted order of suffixes of left and right partition. */ - int *c, *d, *e; - int s, v; - - v = b - SA - 1; - for (c = first, d = a - 1; c <= d; ++c) - { - if ((0 <= (s = *c - depth)) && (ISA[s] == v)) - { - *++d = s; - ISA[s] = d - SA; - } - } - for (c = last - 1, e = d + 1, d = b; e < d; --c) - { - if ((0 <= (s = *c - depth)) && (ISA[s] == v)) - { - *--d = s; - ISA[s] = d - SA; - } - } -} - -static void -tr_partialcopy(int *ISA, const int *SA, - int *first, int *a, int *b, int *last, - int depth) -{ - int *c, *d, *e; - int s, v; - int rank, lastrank, newrank = -1; - - v = b - SA - 1; - lastrank = -1; - for (c = first, d = a - 1; c <= d; ++c) - { - if ((0 <= (s = *c - depth)) && (ISA[s] == v)) - { - *++d = s; - rank = ISA[s + depth]; - if (lastrank != rank) - { - lastrank = rank; - newrank = d - SA; - } - ISA[s] = newrank; - } - } - - lastrank = -1; - for (e = d; first <= e; --e) - { - rank = ISA[*e]; - if (lastrank != rank) - { - lastrank = rank; - newrank = e - SA; - } - if (newrank != rank) - { - ISA[*e] = newrank; - } - } - - lastrank = -1; - for (c = last - 1, e = d + 1, d = b; e < d; --c) - { - if ((0 <= (s = *c - depth)) && (ISA[s] == v)) - { - *--d = s; - rank = ISA[s + depth]; - if (lastrank != rank) - { - lastrank = rank; - newrank = d - SA; - } - ISA[s] = newrank; - } - } -} - -static void -tr_introsort(int *ISA, const int *ISAd, - int *SA, int *first, int *last, - trbudget_t *budget) -{ -#define STACK_SIZE TR_STACKSIZE - struct - { - const int *a; - int *b, *c; - int d, e; - } stack[STACK_SIZE]; - int *a, *b, *c; - int t; - int v, x = 0; - int incr = ISAd - ISA; - int limit, next; - int ssize, trlink = -1; - - for (ssize = 0, limit = tr_ilg(last - first);;) - { - - if (limit < 0) - { - if (limit == -1) - { - /* tandem repeat partition */ - tr_partition(ISAd - incr, first, first, last, &a, &b, last - SA - 1); - - /* update ranks */ - if (a < last) - { - for (c = first, v = a - SA - 1; c < a; ++c) - { - ISA[*c] = v; - } - } - if (b < last) - { - for (c = a, v = b - SA - 1; c < b; ++c) - { - ISA[*c] = v; - } - } - - /* push */ - if (1 < (b - a)) - { - STACK_PUSH5(NULL, a, b, 0, 0); - STACK_PUSH5(ISAd - incr, first, last, -2, trlink); - trlink = ssize - 2; - } - if ((a - first) <= (last - b)) - { - if (1 < (a - first)) - { - STACK_PUSH5(ISAd, b, last, tr_ilg(last - b), trlink); - last = a, limit = tr_ilg(a - first); - } - else if (1 < (last - b)) - { - first = b, limit = tr_ilg(last - b); - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - else - { - if (1 < (last - b)) - { - STACK_PUSH5(ISAd, first, a, tr_ilg(a - first), trlink); - first = b, limit = tr_ilg(last - b); - } - else if (1 < (a - first)) - { - last = a, limit = tr_ilg(a - first); - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - } - else if (limit == -2) - { - /* tandem repeat copy */ - a = stack[--ssize].b, b = stack[ssize].c; - if (stack[ssize].d == 0) - { - tr_copy(ISA, SA, first, a, b, last, ISAd - ISA); - } - else - { - if (0 <= trlink) - { - stack[trlink].d = -1; - } - tr_partialcopy(ISA, SA, first, a, b, last, ISAd - ISA); - } - STACK_POP5(ISAd, first, last, limit, trlink); - } - else - { - /* sorted partition */ - if (0 <= *first) - { - a = first; - do - { - ISA[*a] = a - SA; - } while ((++a < last) && (0 <= *a)); - first = a; - } - if (first < last) - { - a = first; - do - { - *a = ~*a; - } while (*++a < 0); - next = (ISA[*a] != ISAd[*a]) ? tr_ilg(a - first + 1) : -1; - if (++a < last) - { - for (b = first, v = a - SA - 1; b < a; ++b) - { - ISA[*b] = v; - } - } - - /* push */ - if (trbudget_check(budget, a - first)) - { - if ((a - first) <= (last - a)) - { - STACK_PUSH5(ISAd, a, last, -3, trlink); - ISAd += incr, last = a, limit = next; - } - else - { - if (1 < (last - a)) - { - STACK_PUSH5(ISAd + incr, first, a, next, trlink); - first = a, limit = -3; - } - else - { - ISAd += incr, last = a, limit = next; - } - } - } - else - { - if (0 <= trlink) - { - stack[trlink].d = -1; - } - if (1 < (last - a)) - { - first = a, limit = -3; - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - continue; - } - - if ((last - first) <= TR_INSERTIONSORT_THRESHOLD) - { - tr_insertionsort(ISAd, first, last); - limit = -3; - continue; - } - - if (limit-- == 0) - { - tr_heapsort(ISAd, first, last - first); - for (a = last - 1; first < a; a = b) - { - for (x = ISAd[*a], b = a - 1; (first <= b) && (ISAd[*b] == x); --b) - { - *b = ~*b; - } - } - limit = -3; - continue; - } - - /* choose pivot */ - a = tr_pivot(ISAd, first, last); - SWAP(*first, *a); - v = ISAd[*first]; - - /* partition */ - tr_partition(ISAd, first, first + 1, last, &a, &b, v); - if ((last - first) != (b - a)) - { - next = (ISA[*a] != v) ? tr_ilg(b - a) : -1; - - /* update ranks */ - for (c = first, v = a - SA - 1; c < a; ++c) - { - ISA[*c] = v; - } - if (b < last) - { - for (c = a, v = b - SA - 1; c < b; ++c) - { - ISA[*c] = v; - } - } - - /* push */ - if ((1 < (b - a)) && (trbudget_check(budget, b - a))) - { - if ((a - first) <= (last - b)) - { - if ((last - b) <= (b - a)) - { - if (1 < (a - first)) - { - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - STACK_PUSH5(ISAd, b, last, limit, trlink); - last = a; - } - else if (1 < (last - b)) - { - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - first = b; - } - else - { - ISAd += incr, first = a, last = b, limit = next; - } - } - else if ((a - first) <= (b - a)) - { - if (1 < (a - first)) - { - STACK_PUSH5(ISAd, b, last, limit, trlink); - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - last = a; - } - else - { - STACK_PUSH5(ISAd, b, last, limit, trlink); - ISAd += incr, first = a, last = b, limit = next; - } - } - else - { - STACK_PUSH5(ISAd, b, last, limit, trlink); - STACK_PUSH5(ISAd, first, a, limit, trlink); - ISAd += incr, first = a, last = b, limit = next; - } - } - else - { - if ((a - first) <= (b - a)) - { - if (1 < (last - b)) - { - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - STACK_PUSH5(ISAd, first, a, limit, trlink); - first = b; - } - else if (1 < (a - first)) - { - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - last = a; - } - else - { - ISAd += incr, first = a, last = b, limit = next; - } - } - else if ((last - b) <= (b - a)) - { - if (1 < (last - b)) - { - STACK_PUSH5(ISAd, first, a, limit, trlink); - STACK_PUSH5(ISAd + incr, a, b, next, trlink); - first = b; - } - else - { - STACK_PUSH5(ISAd, first, a, limit, trlink); - ISAd += incr, first = a, last = b, limit = next; - } - } - else - { - STACK_PUSH5(ISAd, first, a, limit, trlink); - STACK_PUSH5(ISAd, b, last, limit, trlink); - ISAd += incr, first = a, last = b, limit = next; - } - } - } - else - { - if ((1 < (b - a)) && (0 <= trlink)) - { - stack[trlink].d = -1; - } - if ((a - first) <= (last - b)) - { - if (1 < (a - first)) - { - STACK_PUSH5(ISAd, b, last, limit, trlink); - last = a; - } - else if (1 < (last - b)) - { - first = b; - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - else - { - if (1 < (last - b)) - { - STACK_PUSH5(ISAd, first, a, limit, trlink); - first = b; - } - else if (1 < (a - first)) - { - last = a; - } - else - { - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - } - } - else - { - if (trbudget_check(budget, last - first)) - { - limit = tr_ilg(last - first), ISAd += incr; - } - else - { - if (0 <= trlink) - { - stack[trlink].d = -1; - } - STACK_POP5(ISAd, first, last, limit, trlink); - } - } - } -#undef STACK_SIZE -} - -/*---------------------------------------------------------------------------*/ - -/* Tandem repeat sort */ -static void -trsort(int *ISA, int *SA, int n, int depth) -{ - int *ISAd; - int *first, *last; - trbudget_t budget; - int t, skip, unsorted; - - trbudget_init(&budget, tr_ilg(n) * 2 / 3, n); - /* trbudget_init(&budget, tr_ilg(n) * 3 / 4, n); */ - for (ISAd = ISA + depth; -n < *SA; ISAd += ISAd - ISA) - { - first = SA; - skip = 0; - unsorted = 0; - do - { - if ((t = *first) < 0) - { - first -= t; - skip += t; - } - else - { - if (skip != 0) - { - *(first + skip) = skip; - skip = 0; - } - last = SA + ISA[t] + 1; - if (1 < (last - first)) - { - budget.count = 0; - tr_introsort(ISA, ISAd, SA, first, last, &budget); - if (budget.count != 0) - { - unsorted += budget.count; - } - else - { - skip = first - last; - } - } - else if ((last - first) == 1) - { - skip = -1; - } - first = last; - } - } while (first < (SA + n)); - if (skip != 0) - { - *(first + skip) = skip; - } - if (unsorted == 0) - { - break; - } - } -} - -/*---------------------------------------------------------------------------*/ - -/* Sorts suffixes of type B*. */ -static int -sort_typeBstar(const unsigned char *T, int *SA, - int *bucket_A, int *bucket_B, - int n, int openMP) -{ - int *PAb, *ISAb, *buf; -#ifdef LIBBSC_OPENMP - int *curbuf; - int l; -#endif - int i, j, k, t, m, bufsize; - int c0, c1; -#ifdef LIBBSC_OPENMP - int d0, d1; -#endif - (void)openMP; - - /* Initialize bucket arrays. */ - for (i = 0; i < BUCKET_A_SIZE; ++i) - { - bucket_A[i] = 0; - } - for (i = 0; i < BUCKET_B_SIZE; ++i) - { - bucket_B[i] = 0; - } - - /* Count the number of occurrences of the first one or two characters of each - type A, B and B* suffix. Moreover, store the beginning position of all - type B* suffixes into the array SA. */ - for (i = n - 1, m = n, c0 = T[n - 1]; 0 <= i;) - { - /* type A suffix. */ - do - { - ++BUCKET_A(c1 = c0); - } while ((0 <= --i) && ((c0 = T[i]) >= c1)); - if (0 <= i) - { - /* type B* suffix. */ - ++BUCKET_BSTAR(c0, c1); - SA[--m] = i; - /* type B suffix. */ - for (--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) - { - ++BUCKET_B(c0, c1); - } - } - } - m = n - m; - /* - note: - A type B* suffix is lexicographically smaller than a type B suffix that - begins with the same first two characters. - */ - - /* Calculate the index of start/end point of each bucket. */ - for (c0 = 0, i = 0, j = 0; c0 < ALPHABET_SIZE; ++c0) - { - t = i + BUCKET_A(c0); - BUCKET_A(c0) = i + j; /* start point */ - i = t + BUCKET_B(c0, c0); - for (c1 = c0 + 1; c1 < ALPHABET_SIZE; ++c1) - { - j += BUCKET_BSTAR(c0, c1); - BUCKET_BSTAR(c0, c1) = j; /* end point */ - i += BUCKET_B(c0, c1); - } - } - - if (0 < m) - { - /* Sort the type B* suffixes by their first two characters. */ - PAb = SA + n - m; - ISAb = SA + m; - for (i = m - 2; 0 <= i; --i) - { - t = PAb[i], c0 = T[t], c1 = T[t + 1]; - SA[--BUCKET_BSTAR(c0, c1)] = i; - } - t = PAb[m - 1], c0 = T[t], c1 = T[t + 1]; - SA[--BUCKET_BSTAR(c0, c1)] = m - 1; - - /* Sort the type B* substrings using sssort. */ -#ifdef LIBBSC_OPENMP - if (openMP) - { - buf = SA + m; - c0 = ALPHABET_SIZE - 2, c1 = ALPHABET_SIZE - 1, j = m; -#pragma omp parallel default(shared) private(bufsize, curbuf, k, l, d0, d1) - { - bufsize = (n - (2 * m)) / omp_get_num_threads(); - curbuf = buf + omp_get_thread_num() * bufsize; - k = 0; - for (;;) - { -#pragma omp critical(sssort_lock) - { - if (0 < (l = j)) - { - d0 = c0, d1 = c1; - do - { - k = BUCKET_BSTAR(d0, d1); - if (--d1 <= d0) - { - d1 = ALPHABET_SIZE - 1; - if (--d0 < 0) - { - break; - } - } - } while (((l - k) <= 1) && (0 < (l = k))); - c0 = d0, c1 = d1, j = k; - } - } - if (l == 0) - { - break; - } - sssort(T, PAb, SA + k, SA + l, - curbuf, bufsize, 2, n, *(SA + k) == (m - 1)); - } - } - } - else - { - buf = SA + m, bufsize = n - (2 * m); - for (c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) - { - for (c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) - { - i = BUCKET_BSTAR(c0, c1); - if (1 < (j - i)) - { - sssort(T, PAb, SA + i, SA + j, - buf, bufsize, 2, n, *(SA + i) == (m - 1)); - } - } - } - } -#else - buf = SA + m, bufsize = n - (2 * m); - for (c0 = ALPHABET_SIZE - 2, j = m; 0 < j; --c0) - { - for (c1 = ALPHABET_SIZE - 1; c0 < c1; j = i, --c1) - { - i = BUCKET_BSTAR(c0, c1); - if (1 < (j - i)) - { - sssort(T, PAb, SA + i, SA + j, - buf, bufsize, 2, n, *(SA + i) == (m - 1)); - } - } - } -#endif - - /* Compute ranks of type B* substrings. */ - for (i = m - 1; 0 <= i; --i) - { - if (0 <= SA[i]) - { - j = i; - do - { - ISAb[SA[i]] = i; - } while ((0 <= --i) && (0 <= SA[i])); - SA[i + 1] = i - j; - if (i <= 0) - { - break; - } - } - j = i; - do - { - ISAb[SA[i] = ~SA[i]] = j; - } while (SA[--i] < 0); - ISAb[SA[i]] = j; - } - - /* Construct the inverse suffix array of type B* suffixes using trsort. */ - trsort(ISAb, SA, m, 1); - - /* Set the sorted order of tyoe B* suffixes. */ - for (i = n - 1, j = m, c0 = T[n - 1]; 0 <= i;) - { - for (--i, c1 = c0; (0 <= i) && ((c0 = T[i]) >= c1); --i, c1 = c0) - { - } - if (0 <= i) - { - t = i; - for (--i, c1 = c0; (0 <= i) && ((c0 = T[i]) <= c1); --i, c1 = c0) - { - } - SA[ISAb[--j]] = ((t == 0) || (1 < (t - i))) ? t : ~t; - } - } - - /* Calculate the index of start/end point of each bucket. */ - BUCKET_B(ALPHABET_SIZE - 1, ALPHABET_SIZE - 1) = n; /* end point */ - for (c0 = ALPHABET_SIZE - 2, k = m - 1; 0 <= c0; --c0) - { - i = BUCKET_A(c0 + 1) - 1; - for (c1 = ALPHABET_SIZE - 1; c0 < c1; --c1) - { - t = i - BUCKET_B(c0, c1); - BUCKET_B(c0, c1) = i; /* end point */ - - /* Move all type B* suffixes to the correct position. */ - for (i = t, j = BUCKET_BSTAR(c0, c1); - j <= k; - --i, --k) - { - SA[i] = SA[k]; - } - } - BUCKET_BSTAR(c0, c0 + 1) = i - BUCKET_B(c0, c0) + 1; /* start point */ - BUCKET_B(c0, c0) = i; /* end point */ - } - } - - return m; -} - -/* Constructs the suffix array by using the sorted order of type B* suffixes. */ -static void -construct_SA(const unsigned char *T, int *SA, - int *bucket_A, int *bucket_B, - int n, int m) -{ - int *i, *j, *k; - int s; - int c0, c1, c2; - - if (0 < m) - { - /* Construct the sorted order of type B suffixes by using - the sorted order of type B* suffixes. */ - for (c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) - { - /* Scan the suffix array from right to left. */ - for (i = SA + BUCKET_BSTAR(c1, c1 + 1), - j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; - i <= j; - --j) - { - if (0 < (s = *j)) - { - assert(T[s] == c1); - assert(((s + 1) < n) && (T[s] <= T[s + 1])); - assert(T[s - 1] <= T[s]); - *j = ~s; - c0 = T[--s]; - if ((0 < s) && (T[s - 1] > c0)) - { - s = ~s; - } - if (c0 != c2) - { - if (0 <= c2) - { - BUCKET_B(c2, c1) = k - SA; - } - k = SA + BUCKET_B(c2 = c0, c1); - } - assert(k < j); - *k-- = s; - } - else - { - assert(((s == 0) && (T[s] == c1)) || (s < 0)); - *j = ~s; - } - } - } - } - - /* Construct the suffix array by using - the sorted order of type B suffixes. */ - k = SA + BUCKET_A(c2 = T[n - 1]); - *k++ = (T[n - 2] < c2) ? ~(n - 1) : (n - 1); - /* Scan the suffix array from left to right. */ - for (i = SA, j = SA + n; i < j; ++i) - { - if (0 < (s = *i)) - { - assert(T[s - 1] >= T[s]); - c0 = T[--s]; - if ((s == 0) || (T[s - 1] < c0)) - { - s = ~s; - } - if (c0 != c2) - { - BUCKET_A(c2) = k - SA; - k = SA + BUCKET_A(c2 = c0); - } - assert(i < k); - *k++ = s; - } - else - { - assert(s < 0); - *i = ~s; - } - } -} - -/* Constructs the burrows-wheeler transformed string directly - by using the sorted order of type B* suffixes. */ -static int -construct_BWT(const unsigned char *T, int *SA, - int *bucket_A, int *bucket_B, - int n, int m) -{ - int *i, *j, *k, *orig; - int s; - int c0, c1, c2; - - if (0 < m) - { - /* Construct the sorted order of type B suffixes by using - the sorted order of type B* suffixes. */ - for (c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) - { - /* Scan the suffix array from right to left. */ - for (i = SA + BUCKET_BSTAR(c1, c1 + 1), - j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; - i <= j; - --j) - { - if (0 < (s = *j)) - { - assert(T[s] == c1); - assert(((s + 1) < n) && (T[s] <= T[s + 1])); - assert(T[s - 1] <= T[s]); - c0 = T[--s]; - *j = ~((int)c0); - if ((0 < s) && (T[s - 1] > c0)) - { - s = ~s; - } - if (c0 != c2) - { - if (0 <= c2) - { - BUCKET_B(c2, c1) = k - SA; - } - k = SA + BUCKET_B(c2 = c0, c1); - } - assert(k < j); - *k-- = s; - } - else if (s != 0) - { - *j = ~s; -#ifndef NDEBUG - } - else - { - assert(T[s] == c1); -#endif - } - } - } - } - - /* Construct the BWTed string by using - the sorted order of type B suffixes. */ - k = SA + BUCKET_A(c2 = T[n - 1]); - *k++ = (T[n - 2] < c2) ? ~((int)T[n - 2]) : (n - 1); - /* Scan the suffix array from left to right. */ - for (i = SA, j = SA + n, orig = SA; i < j; ++i) - { - if (0 < (s = *i)) - { - assert(T[s - 1] >= T[s]); - c0 = T[--s]; - *i = c0; - if ((0 < s) && (T[s - 1] < c0)) - { - s = ~((int)T[s - 1]); - } - if (c0 != c2) - { - BUCKET_A(c2) = k - SA; - k = SA + BUCKET_A(c2 = c0); - } - assert(i < k); - *k++ = s; - } - else if (s != 0) - { - *i = ~s; - } - else - { - orig = i; - } - } - - return orig - SA; -} - -/* Constructs the burrows-wheeler transformed string directly - by using the sorted order of type B* suffixes. */ -static int -construct_BWT_indexes(const unsigned char *T, int *SA, - int *bucket_A, int *bucket_B, - int n, int m, - unsigned char *num_indexes, int *indexes) -{ - int *i, *j, *k, *orig; - int s; - int c0, c1, c2; - - int mod = n / 8; - { - mod |= mod >> 1; - mod |= mod >> 2; - mod |= mod >> 4; - mod |= mod >> 8; - mod |= mod >> 16; - mod >>= 1; - - *num_indexes = (unsigned char)((n - 1) / (mod + 1)); - } - - if (0 < m) - { - /* Construct the sorted order of type B suffixes by using - the sorted order of type B* suffixes. */ - for (c1 = ALPHABET_SIZE - 2; 0 <= c1; --c1) - { - /* Scan the suffix array from right to left. */ - for (i = SA + BUCKET_BSTAR(c1, c1 + 1), - j = SA + BUCKET_A(c1 + 1) - 1, k = NULL, c2 = -1; - i <= j; - --j) - { - if (0 < (s = *j)) - { - assert(T[s] == c1); - assert(((s + 1) < n) && (T[s] <= T[s + 1])); - assert(T[s - 1] <= T[s]); - - if ((s & mod) == 0) - indexes[s / (mod + 1) - 1] = j - SA; - - c0 = T[--s]; - *j = ~((int)c0); - if ((0 < s) && (T[s - 1] > c0)) - { - s = ~s; - } - if (c0 != c2) - { - if (0 <= c2) - { - BUCKET_B(c2, c1) = k - SA; - } - k = SA + BUCKET_B(c2 = c0, c1); - } - assert(k < j); - *k-- = s; - } - else if (s != 0) - { - *j = ~s; -#ifndef NDEBUG - } - else - { - assert(T[s] == c1); -#endif - } - } - } - } - - /* Construct the BWTed string by using - the sorted order of type B suffixes. */ - k = SA + BUCKET_A(c2 = T[n - 1]); - if (T[n - 2] < c2) - { - if (((n - 1) & mod) == 0) - indexes[(n - 1) / (mod + 1) - 1] = k - SA; - *k++ = ~((int)T[n - 2]); - } - else - { - *k++ = n - 1; - } - - /* Scan the suffix array from left to right. */ - for (i = SA, j = SA + n, orig = SA; i < j; ++i) - { - if (0 < (s = *i)) - { - assert(T[s - 1] >= T[s]); - - if ((s & mod) == 0) - indexes[s / (mod + 1) - 1] = i - SA; - - c0 = T[--s]; - *i = c0; - if (c0 != c2) - { - BUCKET_A(c2) = k - SA; - k = SA + BUCKET_A(c2 = c0); - } - assert(i < k); - if ((0 < s) && (T[s - 1] < c0)) - { - if ((s & mod) == 0) - indexes[s / (mod + 1) - 1] = k - SA; - *k++ = ~((int)T[s - 1]); - } - else - *k++ = s; - } - else if (s != 0) - { - *i = ~s; - } - else - { - orig = i; - } - } - - return orig - SA; -} - -/*---------------------------------------------------------------------------*/ - -/*- Function -*/ - -int divsufsort(const unsigned char *T, int *SA, int n, int openMP) -{ - int *bucket_A, *bucket_B; - int m; - int err = 0; - - /* Check arguments. */ - if ((T == NULL) || (SA == NULL) || (n < 0)) - { - return -1; - } - else if (n == 0) - { - return 0; - } - else if (n == 1) - { - SA[0] = 0; - return 0; - } - else if (n == 2) - { - m = (T[0] < T[1]); - SA[m ^ 1] = 0, SA[m] = 1; - return 0; - } - - bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); - bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); - - /* Suffixsort. */ - if ((bucket_A != NULL) && (bucket_B != NULL)) - { - m = sort_typeBstar(T, SA, bucket_A, bucket_B, n, openMP); - construct_SA(T, SA, bucket_A, bucket_B, n, m); - } - else - { - err = -2; - } - - free(bucket_B); - free(bucket_A); - - return err; -} - -int divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char *num_indexes, int *indexes, int openMP) -{ - int *B; - int *bucket_A, *bucket_B; - int m, pidx, i; - - /* Check arguments. */ - if ((T == NULL) || (U == NULL) || (n < 0)) - { - return -1; - } - else if (n <= 1) - { - if (n == 1) - { - U[0] = T[0]; - } - return n; - } - - if ((B = A) == NULL) - { - B = (int *)malloc((size_t)(n + 1) * sizeof(int)); - } - bucket_A = (int *)malloc(BUCKET_A_SIZE * sizeof(int)); - bucket_B = (int *)malloc(BUCKET_B_SIZE * sizeof(int)); - - /* Burrows-Wheeler Transform. */ - if ((B != NULL) && (bucket_A != NULL) && (bucket_B != NULL)) - { - m = sort_typeBstar(T, B, bucket_A, bucket_B, n, openMP); - - if (num_indexes == NULL || indexes == NULL) - { - pidx = construct_BWT(T, B, bucket_A, bucket_B, n, m); - } - else - { - pidx = construct_BWT_indexes(T, B, bucket_A, bucket_B, n, m, num_indexes, indexes); - } - - /* Copy to output string. */ - U[0] = T[n - 1]; - for (i = 0; i < pidx; ++i) - { - U[i + 1] = (unsigned char)B[i]; - } - for (i += 1; i < n; ++i) - { - U[i] = (unsigned char)B[i]; - } - pidx += 1; - } - else - { - pidx = -2; - } - - free(bucket_B); - free(bucket_A); - if (A == NULL) - { - free(B); - } - - return pidx; -} diff --git a/extra/zstd/divsufsort.h b/extra/zstd/divsufsort.h deleted file mode 100644 index f6bd7517..00000000 --- a/extra/zstd/divsufsort.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * divsufsort.h for libdivsufsort-lite - * Copyright (c) 2003-2008 Yuta Mori All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _DIVSUFSORT_H -#define _DIVSUFSORT_H 1 - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - - /*- Prototypes -*/ - - /** - * Constructs the suffix array of a given string. - * @param T [0..n-1] The input string. - * @param SA [0..n-1] The output array of suffixes. - * @param n The length of the given string. - * @param openMP enables OpenMP optimization. - * @return 0 if no error occurred, -1 or -2 otherwise. - */ - int - divsufsort(const unsigned char *T, int *SA, int n, int openMP); - - /** - * Constructs the burrows-wheeler transformed string of a given string. - * @param T [0..n-1] The input string. - * @param U [0..n-1] The output string. (can be T) - * @param A [0..n-1] The temporary array. (can be NULL) - * @param n The length of the given string. - * @param num_indexes The length of secondary indexes array. (can be NULL) - * @param indexes The secondary indexes array. (can be NULL) - * @param openMP enables OpenMP optimization. - * @return The primary index if no error occurred, -1 or -2 otherwise. - */ - int - divbwt(const unsigned char *T, unsigned char *U, int *A, int n, unsigned char *num_indexes, int *indexes, int openMP); - -#ifdef __cplusplus -} /* extern "C" */ -#endif /* __cplusplus */ - -#endif /* _DIVSUFSORT_H */ diff --git a/extra/zstd/entropy_common.c b/extra/zstd/entropy_common.c deleted file mode 100644 index 6a905fd4..00000000 --- a/extra/zstd/entropy_common.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - Common functions of New Generation Entropy library - Copyright (C) 2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -*************************************************************************** */ - -/* ************************************* - * Dependencies - ***************************************/ -#include "mem.h" -#include "error_private.h" /* ERR_*, ERROR */ -#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */ -#include "fse.h" -#define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */ -#include "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 - ****************************************************************/ -size_t FSE_readNCount(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; - int previous0 = 0; - - if (hbSize < 4) - return ERROR(srcSize_wrong); - 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++; - - while ((remaining > 1) & (charnum <= *maxSVPtr)) - { - if (previous0) - { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) - { - n0 += 24; - if (ip < iend - 5) - { - ip += 2; - bitStream = MEM_readLE32(ip) >> bitCount; - } - else - { - bitStream >>= 16; - bitCount += 16; - } - } - while ((bitStream & 3) == 3) - { - n0 += 3; - bitStream >>= 2; - bitCount += 2; - } - n0 += bitStream & 3; - bitCount += 2; - if (n0 > *maxSVPtr) - return ERROR(maxSymbolValue_tooSmall); - while (charnum < n0) - normalizedCounter[charnum++] = 0; - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - bitStream = MEM_readLE32(ip) >> bitCount; - } - else - { - bitStream >>= 2; - } - } - { - 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 */ - remaining -= count < 0 ? -count : count; /* -1 means +1 */ - normalizedCounter[charnum++] = (short)count; - previous0 = !count; - while (remaining < threshold) - { - nbBits--; - threshold >>= 1; - } - - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - } - else - { - bitCount -= (int)(8 * (iend - 4 - ip)); - ip = iend - 4; - } - bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } - } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ - if (remaining != 1) - return ERROR(corruption_detected); - if (bitCount > 32) - return ERROR(corruption_detected); - *maxSVPtr = charnum - 1; - - ip += (bitCount + 7) >> 3; - return ip - istart; -} - -/*! 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 weightTotal; - const BYTE *ip = (const BYTE *)src; - size_t iSize; - size_t oSize; - - if (!srcSize) - return ERROR(srcSize_wrong); - iSize = ip[0]; - /* 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) */ - FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ - if (iSize + 1 > srcSize) - return ERROR(srcSize_wrong); - oSize = FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ - if (FSE_isError(oSize)) - return oSize; - } - - /* collect weight stats */ - 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; -} diff --git a/extra/zstd/error_private.c b/extra/zstd/error_private.c deleted file mode 100644 index 7f49edff..00000000 --- a/extra/zstd/error_private.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* The purpose of this file is to have a single list of error strings embedded in binary */ - -#include "error_private.h" - -const char *ERR_getErrorString(ERR_enum code) -{ - static const char *const notErrorCode = "Unspecified error code"; - switch (code) - { - case PREFIX(no_error): - return "No error detected"; - case PREFIX(GENERIC): - return "Error (generic)"; - case PREFIX(prefix_unknown): - return "Unknown frame descriptor"; - case PREFIX(version_unsupported): - return "Version not supported"; - case PREFIX(parameter_unknown): - return "Unknown parameter type"; - case PREFIX(frameParameter_unsupported): - return "Unsupported frame parameter"; - case PREFIX(frameParameter_unsupportedBy32bits): - return "Frame parameter unsupported in 32-bits mode"; - case PREFIX(frameParameter_windowTooLarge): - return "Frame requires too much memory for decoding"; - case PREFIX(compressionParameter_unsupported): - return "Compression parameter is out of bound"; - case PREFIX(init_missing): - return "Context should be init first"; - case PREFIX(memory_allocation): - return "Allocation error : not enough memory"; - case PREFIX(stage_wrong): - return "Operation not authorized at current processing stage"; - case PREFIX(dstSize_tooSmall): - return "Destination buffer is too small"; - case PREFIX(srcSize_wrong): - return "Src size incorrect"; - case PREFIX(corruption_detected): - return "Corrupted block detected"; - case PREFIX(checksum_wrong): - return "Restored data doesn't match checksum"; - case PREFIX(tableLog_tooLarge): - return "tableLog requires too much memory : unsupported"; - case PREFIX(maxSymbolValue_tooLarge): - return "Unsupported max Symbol Value : too large"; - case PREFIX(maxSymbolValue_tooSmall): - return "Specified maxSymbolValue is too small"; - case PREFIX(dictionary_corrupted): - return "Dictionary is corrupted"; - case PREFIX(dictionary_wrong): - return "Dictionary mismatch"; - case PREFIX(maxCode): - default: - return notErrorCode; - } -} diff --git a/extra/zstd/error_private.h b/extra/zstd/error_private.h deleted file mode 100644 index e730cd1c..00000000 --- a/extra/zstd/error_private.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* 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 - ******************************************/ -#include /* size_t */ -#include "zstd_errors.h" /* enum list */ - -/* **************************************** - * 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 - ******************************************/ -#ifdef ERROR -#undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */ -#endif -#define 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); - } - - /*-**************************************** - * 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 */ diff --git a/extra/zstd/fse.h b/extra/zstd/fse.h deleted file mode 100644 index 9b9ed40b..00000000 --- a/extra/zstd/fse.h +++ /dev/null @@ -1,675 +0,0 @@ -/* ****************************************************************** - FSE : Finite State Entropy codec - Public Prototypes declaration - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy -****************************************************************** */ -#ifndef FSE_H -#define FSE_H - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*-***************************************** - * Dependencies - ******************************************/ -#include /* size_t, ptrdiff_t */ - -/*-***************************************** - * 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[] - 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_count(): - Provides the precise count of each byte within a table 'count'. - 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1). - *maxSymbolValuePtr will be updated if detected smaller than initial value. - @return : the count of the most frequent symbol (which is not identified). - if return == srcSize, there is only one symbol. - Can also return an error code, which can be tested with FSE_isError(). */ - FSE_PUBLIC_API size_t FSE_count(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize); - - /*! 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). - @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); - - /*! 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 tableLog, unsigned maxSymbolValue); - 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); - - /*! 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) - */ - -#ifdef FSE_STATIC_LINKING_ONLY - -/* *** Dependency *** */ -#include "bitstream.h" - -/* ***************************************** - * Static allocation - *******************************************/ -/* FSE buffer bounds */ -#define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size >> 7)) -#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)) - - /* ***************************************** - * FSE advanced API - *******************************************/ - /* FSE_count_wksp() : - * Same as FSE_count(), but using an externally provided scratch buffer. - * `workSpace` size must be table of >= `1024` unsigned - */ - size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, - const void *source, size_t sourceSize, unsigned *workSpace); - - /** FSE_countFast() : - * same as FSE_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr - */ - size_t FSE_countFast(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize); - - /* FSE_countFast_wksp() : - * Same as FSE_countFast(), but using an externally provided scratch buffer. - * `workSpace` must be a table of minimum `1024` unsigned - */ - size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize, unsigned *workSpace); - - /*! FSE_count_simple - * Same as FSE_countFast(), but does not use any additional memory (not even on stack). - * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`). - */ - size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize); - - 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_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. - */ -#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + (1 << ((maxTableLog > 2) ? (maxTableLog - 2) : 0))) - 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 >= `(1<= 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 = ((const U32 *)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, U32 symbol) - { - const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol]; - const U16 *const stateTable = (const U16 *)(statePtr->stateTable); - U32 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); - } - - /* ====== 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 - -/*!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 - -#endif /* FSE_H */ diff --git a/extra/zstd/fse_compress.c b/extra/zstd/fse_compress.c deleted file mode 100644 index 71b4d316..00000000 --- a/extra/zstd/fse_compress.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* ****************************************************************** - FSE : Finite State Entropy encoder - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -/* ************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/* ************************************************************** - * Includes - ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include /* printf (debug) */ -#include "bitstream.h" -#define FSE_STATIC_LINKING_ONLY -#include "fse.h" - -/* ************************************************************** - * Error Management - ****************************************************************/ -#define FSE_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - FSE_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/* ************************************************************** - * Templates - ****************************************************************/ -/* - designed to be included - for type-specific functions (template emulation in C) - Objective is to write these functions only once, for improved maintenance -*/ - -/* safety checks */ -#ifndef FSE_FUNCTION_EXTENSION -#error "FSE_FUNCTION_EXTENSION must be defined" -#endif -#ifndef FSE_FUNCTION_TYPE -#error "FSE_FUNCTION_TYPE must be defined" -#endif - -/* Function names */ -#define FSE_CAT(X, Y) X##Y -#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y) -#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y) - -/* Function templates */ - -/* FSE_buildCTable_wksp() : - * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). - * wkspSize should be sized to handle worst case situation, which is `1<> 1 : 1); - FSE_symbolCompressionTransform *const symbolTT = (FSE_symbolCompressionTransform *)(FSCT); - U32 const step = FSE_TABLESTEP(tableSize); - U32 cumul[FSE_MAX_SYMBOL_VALUE + 2]; - - FSE_FUNCTION_TYPE *const tableSymbol = (FSE_FUNCTION_TYPE *)workSpace; - U32 highThreshold = tableSize - 1; - - /* CTable header */ - if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) - return ERROR(tableLog_tooLarge); - tableU16[-2] = (U16)tableLog; - tableU16[-1] = (U16)maxSymbolValue; - - /* For explanations on how to distribute symbol values over the table : - * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ - - /* symbol start positions */ - { - U32 u; - cumul[0] = 0; - for (u = 1; u <= maxSymbolValue + 1; u++) - { - if (normalizedCounter[u - 1] == -1) - { /* Low proba symbol */ - cumul[u] = cumul[u - 1] + 1; - tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u - 1); - } - else - { - cumul[u] = cumul[u - 1] + normalizedCounter[u - 1]; - } - } - cumul[maxSymbolValue + 1] = tableSize + 1; - } - - /* Spread symbols */ - { - U32 position = 0; - U32 symbol; - for (symbol = 0; symbol <= maxSymbolValue; symbol++) - { - int nbOccurences; - for (nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++) - { - tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol; - position = (position + step) & tableMask; - while (position > highThreshold) - position = (position + step) & tableMask; /* Low proba area */ - } - } - - if (position != 0) - return ERROR(GENERIC); /* Must have gone through all positions */ - } - - /* Build table */ - { - U32 u; - for (u = 0; u < tableSize; u++) - { - FSE_FUNCTION_TYPE s = tableSymbol[u]; /* note : static analyzer may not understand tableSymbol is properly initialized */ - tableU16[cumul[s]++] = (U16)(tableSize + u); /* TableU16 : sorted by symbol order; gives next state value */ - } - } - - /* Build Symbol Transformation Table */ - { - unsigned total = 0; - unsigned s; - for (s = 0; s <= maxSymbolValue; s++) - { - switch (normalizedCounter[s]) - { - case 0: - break; - - case -1: - case 1: - symbolTT[s].deltaNbBits = (tableLog << 16) - (1 << tableLog); - symbolTT[s].deltaFindState = total - 1; - total++; - break; - default: - { - U32 const maxBitsOut = tableLog - BIT_highbit32(normalizedCounter[s] - 1); - U32 const minStatePlus = normalizedCounter[s] << maxBitsOut; - symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus; - symbolTT[s].deltaFindState = total - normalizedCounter[s]; - total += normalizedCounter[s]; - } - } - } - } - - return 0; -} - -size_t FSE_buildCTable(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ - return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol)); -} - -#ifndef FSE_COMMONDEFS_ONLY - -/*-************************************************************** - * FSE NCount encoding-decoding - ****************************************************************/ -size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog) -{ - size_t const maxHeaderSize = (((maxSymbolValue + 1) * tableLog) >> 3) + 3; - return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */ -} - -static size_t FSE_writeNCount_generic(void *header, size_t headerBufferSize, - const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, - unsigned writeIsSafe) -{ - BYTE *const ostart = (BYTE *)header; - BYTE *out = ostart; - BYTE *const oend = ostart + headerBufferSize; - int nbBits; - const int tableSize = 1 << tableLog; - int remaining; - int threshold; - U32 bitStream; - int bitCount; - unsigned charnum = 0; - int previous0 = 0; - - bitStream = 0; - bitCount = 0; - /* Table Size */ - bitStream += (tableLog - FSE_MIN_TABLELOG) << bitCount; - bitCount += 4; - - /* Init */ - remaining = tableSize + 1; /* +1 for extra accuracy */ - threshold = tableSize; - nbBits = tableLog + 1; - - while (remaining > 1) - { /* stops at 1 */ - if (previous0) - { - unsigned start = charnum; - while (!normalizedCounter[charnum]) - charnum++; - while (charnum >= start + 24) - { - start += 24; - bitStream += 0xFFFFU << bitCount; - if ((!writeIsSafe) && (out > oend - 2)) - return ERROR(dstSize_tooSmall); /* Buffer overflow */ - out[0] = (BYTE)bitStream; - out[1] = (BYTE)(bitStream >> 8); - out += 2; - bitStream >>= 16; - } - while (charnum >= start + 3) - { - start += 3; - bitStream += 3 << bitCount; - bitCount += 2; - } - bitStream += (charnum - start) << bitCount; - bitCount += 2; - if (bitCount > 16) - { - if ((!writeIsSafe) && (out > oend - 2)) - return ERROR(dstSize_tooSmall); /* Buffer overflow */ - out[0] = (BYTE)bitStream; - out[1] = (BYTE)(bitStream >> 8); - out += 2; - bitStream >>= 16; - bitCount -= 16; - } - } - { - int count = normalizedCounter[charnum++]; - int const max = (2 * threshold - 1) - remaining; - remaining -= count < 0 ? -count : count; - count++; /* +1 for extra accuracy */ - if (count >= threshold) - count += max; /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */ - bitStream += count << bitCount; - bitCount += nbBits; - bitCount -= (count < max); - previous0 = (count == 1); - if (remaining < 1) - return ERROR(GENERIC); - while (remaining < threshold) - nbBits--, threshold >>= 1; - } - if (bitCount > 16) - { - if ((!writeIsSafe) && (out > oend - 2)) - return ERROR(dstSize_tooSmall); /* Buffer overflow */ - out[0] = (BYTE)bitStream; - out[1] = (BYTE)(bitStream >> 8); - out += 2; - bitStream >>= 16; - bitCount -= 16; - } - } - - /* flush remaining bitStream */ - if ((!writeIsSafe) && (out > oend - 2)) - return ERROR(dstSize_tooSmall); /* Buffer overflow */ - out[0] = (BYTE)bitStream; - out[1] = (BYTE)(bitStream >> 8); - out += (bitCount + 7) / 8; - - if (charnum > maxSymbolValue + 1) - return ERROR(GENERIC); - - return (out - ostart); -} - -size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(GENERIC); /* Unsupported */ - if (tableLog < FSE_MIN_TABLELOG) - return ERROR(GENERIC); /* Unsupported */ - - if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog)) - return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0); - - return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1); -} - -/*-************************************************************** - * Counting histogram - ****************************************************************/ -/*! FSE_count_simple - This function counts byte values within `src`, and store the histogram into table `count`. - It doesn't use any additional memory. - But this function is unsafe : it doesn't check that all values within `src` can fit into `count`. - For this reason, prefer using a table `count` with 256 elements. - @return : count of most numerous element -*/ -size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, - const void *src, size_t srcSize) -{ - const BYTE *ip = (const BYTE *)src; - const BYTE *const end = ip + srcSize; - unsigned maxSymbolValue = *maxSymbolValuePtr; - unsigned max = 0; - - memset(count, 0, (maxSymbolValue + 1) * sizeof(*count)); - if (srcSize == 0) - { - *maxSymbolValuePtr = 0; - return 0; - } - - while (ip < end) - count[*ip++]++; - - while (!count[maxSymbolValue]) - maxSymbolValue--; - *maxSymbolValuePtr = maxSymbolValue; - - { - U32 s; - for (s = 0; s <= maxSymbolValue; s++) - if (count[s] > max) - max = count[s]; - } - - return (size_t)max; -} - -/* FSE_count_parallel_wksp() : - * Same as FSE_count_parallel(), but using an externally provided scratch buffer. - * `workSpace` size must be a minimum of `1024 * sizeof(unsigned)`` */ -static size_t FSE_count_parallel_wksp( - unsigned *count, unsigned *maxSymbolValuePtr, - const void *source, size_t sourceSize, - unsigned checkMax, unsigned *const workSpace) -{ - const BYTE *ip = (const BYTE *)source; - const BYTE *const iend = ip + sourceSize; - unsigned maxSymbolValue = *maxSymbolValuePtr; - unsigned max = 0; - U32 *const Counting1 = workSpace; - U32 *const Counting2 = Counting1 + 256; - U32 *const Counting3 = Counting2 + 256; - U32 *const Counting4 = Counting3 + 256; - - memset(Counting1, 0, 4 * 256 * sizeof(unsigned)); - - /* safety checks */ - if (!sourceSize) - { - memset(count, 0, maxSymbolValue + 1); - *maxSymbolValuePtr = 0; - return 0; - } - if (!maxSymbolValue) - maxSymbolValue = 255; /* 0 == default */ - - /* by stripes of 16 bytes */ - { - U32 cached = MEM_read32(ip); - ip += 4; - while (ip < iend - 15) - { - U32 c = cached; - cached = MEM_read32(ip); - ip += 4; - Counting1[(BYTE)c]++; - Counting2[(BYTE)(c >> 8)]++; - Counting3[(BYTE)(c >> 16)]++; - Counting4[c >> 24]++; - c = cached; - cached = MEM_read32(ip); - ip += 4; - Counting1[(BYTE)c]++; - Counting2[(BYTE)(c >> 8)]++; - Counting3[(BYTE)(c >> 16)]++; - Counting4[c >> 24]++; - c = cached; - cached = MEM_read32(ip); - ip += 4; - Counting1[(BYTE)c]++; - Counting2[(BYTE)(c >> 8)]++; - Counting3[(BYTE)(c >> 16)]++; - Counting4[c >> 24]++; - c = cached; - cached = MEM_read32(ip); - ip += 4; - Counting1[(BYTE)c]++; - Counting2[(BYTE)(c >> 8)]++; - Counting3[(BYTE)(c >> 16)]++; - Counting4[c >> 24]++; - } - ip -= 4; - } - - /* finish last symbols */ - while (ip < iend) - Counting1[*ip++]++; - - if (checkMax) - { /* verify stats will fit into destination table */ - U32 s; - for (s = 255; s > maxSymbolValue; s--) - { - Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; - if (Counting1[s]) - return ERROR(maxSymbolValue_tooSmall); - } - } - - { - U32 s; - for (s = 0; s <= maxSymbolValue; s++) - { - count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; - if (count[s] > max) - max = count[s]; - } - } - - while (!count[maxSymbolValue]) - maxSymbolValue--; - *maxSymbolValuePtr = maxSymbolValue; - return (size_t)max; -} - -/* FSE_countFast_wksp() : - * Same as FSE_countFast(), but using an externally provided scratch buffer. - * `workSpace` size must be table of >= `1024` unsigned */ -size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, - const void *source, size_t sourceSize, unsigned *workSpace) -{ - if (sourceSize < 1500) - return FSE_count_simple(count, maxSymbolValuePtr, source, sourceSize); - return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 0, workSpace); -} - -/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ -size_t FSE_countFast(unsigned *count, unsigned *maxSymbolValuePtr, - const void *source, size_t sourceSize) -{ - unsigned tmpCounters[1024]; - return FSE_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters); -} - -/* FSE_count_wksp() : - * Same as FSE_count(), but using an externally provided scratch buffer. - * `workSpace` size must be table of >= `1024` unsigned */ -size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, - const void *source, size_t sourceSize, unsigned *workSpace) -{ - if (*maxSymbolValuePtr < 255) - return FSE_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, 1, workSpace); - *maxSymbolValuePtr = 255; - return FSE_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace); -} - -size_t FSE_count(unsigned *count, unsigned *maxSymbolValuePtr, - const void *src, size_t srcSize) -{ - unsigned tmpCounters[1024]; - return FSE_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters); -} - -/*-************************************************************** - * FSE Compression Code - ****************************************************************/ -/*! FSE_sizeof_CTable() : - FSE_CTable is a variable size structure which contains : - `U16 tableLog;` - `U16 maxSymbolValue;` - `U16 nextStateNumber[1 << tableLog];` // This size is variable - `FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable -Allocation is manual (C standard does not support variable-size structures). -*/ -size_t FSE_sizeof_CTable(unsigned maxSymbolValue, unsigned tableLog) -{ - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); - return FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue) * sizeof(U32); -} - -FSE_CTable *FSE_createCTable(unsigned maxSymbolValue, unsigned tableLog) -{ - size_t size; - if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) - tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - size = FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue) * sizeof(U32); - return (FSE_CTable *)malloc(size); -} - -void FSE_freeCTable(FSE_CTable *ct) { free(ct); } - -/* provides the minimum logSize to safely represent a distribution */ -static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) -{ - U32 minBitsSrc = BIT_highbit32((U32)(srcSize - 1)) + 1; - U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2; - U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols; - return minBits; -} - -unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus) -{ - U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus; - U32 tableLog = maxTableLog; - U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue); - if (tableLog == 0) - tableLog = FSE_DEFAULT_TABLELOG; - if (maxBitsSrc < tableLog) - tableLog = maxBitsSrc; /* Accuracy can be reduced */ - if (minBits > tableLog) - tableLog = minBits; /* Need a minimum to safely represent all symbol values */ - if (tableLog < FSE_MIN_TABLELOG) - tableLog = FSE_MIN_TABLELOG; - if (tableLog > FSE_MAX_TABLELOG) - tableLog = FSE_MAX_TABLELOG; - return tableLog; -} - -unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue) -{ - return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2); -} - -/* Secondary normalization method. - To be used when primary method fails. */ - -static size_t FSE_normalizeM2(short *norm, U32 tableLog, const unsigned *count, size_t total, U32 maxSymbolValue) -{ - short const NOT_YET_ASSIGNED = -2; - U32 s; - U32 distributed = 0; - U32 ToDistribute; - - /* Init */ - U32 const lowThreshold = (U32)(total >> tableLog); - U32 lowOne = (U32)((total * 3) >> (tableLog + 1)); - - for (s = 0; s <= maxSymbolValue; s++) - { - if (count[s] == 0) - { - norm[s] = 0; - continue; - } - if (count[s] <= lowThreshold) - { - norm[s] = -1; - distributed++; - total -= count[s]; - continue; - } - if (count[s] <= lowOne) - { - norm[s] = 1; - distributed++; - total -= count[s]; - continue; - } - - norm[s] = NOT_YET_ASSIGNED; - } - ToDistribute = (1 << tableLog) - distributed; - - if ((total / ToDistribute) > lowOne) - { - /* risk of rounding to zero */ - lowOne = (U32)((total * 3) / (ToDistribute * 2)); - for (s = 0; s <= maxSymbolValue; s++) - { - if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) - { - norm[s] = 1; - distributed++; - total -= count[s]; - continue; - } - } - ToDistribute = (1 << tableLog) - distributed; - } - - if (distributed == maxSymbolValue + 1) - { - /* all values are pretty poor; - probably incompressible data (should have already been detected); - find max, then give all remaining points to max */ - U32 maxV = 0, maxC = 0; - for (s = 0; s <= maxSymbolValue; s++) - if (count[s] > maxC) - maxV = s, maxC = count[s]; - norm[maxV] += (short)ToDistribute; - return 0; - } - - if (total == 0) - { - /* all of the symbols were low enough for the lowOne or lowThreshold */ - for (s = 0; ToDistribute > 0; s = (s + 1) % (maxSymbolValue + 1)) - if (norm[s] > 0) - ToDistribute--, norm[s]++; - return 0; - } - - { - U64 const vStepLog = 62 - tableLog; - U64 const mid = (1ULL << (vStepLog - 1)) - 1; - U64 const rStep = ((((U64)1 << vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ - U64 tmpTotal = mid; - for (s = 0; s <= maxSymbolValue; s++) - { - if (norm[s] == NOT_YET_ASSIGNED) - { - U64 const end = tmpTotal + (count[s] * rStep); - U32 const sStart = (U32)(tmpTotal >> vStepLog); - U32 const sEnd = (U32)(end >> vStepLog); - U32 const weight = sEnd - sStart; - if (weight < 1) - return ERROR(GENERIC); - norm[s] = (short)weight; - tmpTotal = end; - } - } - } - - return 0; -} - -size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, - const unsigned *count, size_t total, - unsigned maxSymbolValue) -{ - /* Sanity checks */ - if (tableLog == 0) - tableLog = FSE_DEFAULT_TABLELOG; - if (tableLog < FSE_MIN_TABLELOG) - return ERROR(GENERIC); /* Unsupported size */ - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); /* Unsupported size */ - if (tableLog < FSE_minTableLog(total, maxSymbolValue)) - return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ - - { - U32 const rtbTable[] = {0, 473195, 504333, 520860, 550000, 700000, 750000, 830000}; - U64 const scale = 62 - tableLog; - U64 const step = ((U64)1 << 62) / total; /* <== here, one division ! */ - U64 const vStep = 1ULL << (scale - 20); - int stillToDistribute = 1 << tableLog; - unsigned s; - unsigned largest = 0; - short largestP = 0; - U32 lowThreshold = (U32)(total >> tableLog); - - for (s = 0; s <= maxSymbolValue; s++) - { - if (count[s] == total) - return 0; /* rle special case */ - if (count[s] == 0) - { - normalizedCounter[s] = 0; - continue; - } - if (count[s] <= lowThreshold) - { - normalizedCounter[s] = -1; - stillToDistribute--; - } - else - { - short proba = (short)((count[s] * step) >> scale); - if (proba < 8) - { - U64 restToBeat = vStep * rtbTable[proba]; - proba += (count[s] * step) - ((U64)proba << scale) > restToBeat; - } - if (proba > largestP) - largestP = proba, largest = s; - normalizedCounter[s] = proba; - stillToDistribute -= proba; - } - } - if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) - { - /* corner case, need another normalization method */ - size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); - if (FSE_isError(errorCode)) - return errorCode; - } - else - normalizedCounter[largest] += (short)stillToDistribute; - } - -#if 0 - { /* Print Table (debug) */ - U32 s; - U32 nTotal = 0; - for (s=0; s<=maxSymbolValue; s++) - printf("%3i: %4i \n", s, normalizedCounter[s]); - for (s=0; s<=maxSymbolValue; s++) - nTotal += abs(normalizedCounter[s]); - if (nTotal != (1U<> 1); /* assumption : tableLog >= 1 */ - FSE_symbolCompressionTransform *const symbolTT = (FSE_symbolCompressionTransform *)(FSCT); - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) - return ERROR(GENERIC); /* min size */ - - /* header */ - tableU16[-2] = (U16)nbBits; - tableU16[-1] = (U16)maxSymbolValue; - - /* Build table */ - for (s = 0; s < tableSize; s++) - tableU16[s] = (U16)(tableSize + s); - - /* Build Symbol Transformation Table */ - { - const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits); - for (s = 0; s <= maxSymbolValue; s++) - { - symbolTT[s].deltaNbBits = deltaNbBits; - symbolTT[s].deltaFindState = s - 1; - } - } - - return 0; -} - -/* fake FSE_CTable, for rle input (always same symbol) */ -size_t FSE_buildCTable_rle(FSE_CTable *ct, BYTE symbolValue) -{ - void *ptr = ct; - U16 *tableU16 = ((U16 *)ptr) + 2; - void *FSCTptr = (U32 *)ptr + 2; - FSE_symbolCompressionTransform *symbolTT = (FSE_symbolCompressionTransform *)FSCTptr; - - /* header */ - tableU16[-2] = (U16)0; - tableU16[-1] = (U16)symbolValue; - - /* Build table */ - tableU16[0] = 0; - tableU16[1] = 0; /* just in case */ - - /* Build Symbol Transformation Table */ - symbolTT[symbolValue].deltaNbBits = 0; - symbolTT[symbolValue].deltaFindState = 0; - - return 0; -} - -static size_t FSE_compress_usingCTable_generic(void *dst, size_t dstSize, - const void *src, size_t srcSize, - const FSE_CTable *ct, const unsigned fast) -{ - const BYTE *const istart = (const BYTE *)src; - const BYTE *const iend = istart + srcSize; - const BYTE *ip = iend; - - BIT_CStream_t bitC; - FSE_CState_t CState1, CState2; - - /* init */ - if (srcSize <= 2) - return 0; - { - size_t const initError = BIT_initCStream(&bitC, dst, dstSize); - if (FSE_isError(initError)) - return 0; /* not enough space available to write a bitstream */ - } - -#define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s)) - - if (srcSize & 1) - { - FSE_initCState2(&CState1, ct, *--ip); - FSE_initCState2(&CState2, ct, *--ip); - FSE_encodeSymbol(&bitC, &CState1, *--ip); - FSE_FLUSHBITS(&bitC); - } - else - { - FSE_initCState2(&CState2, ct, *--ip); - FSE_initCState2(&CState1, ct, *--ip); - } - - /* join to mod 4 */ - srcSize -= 2; - if ((sizeof(bitC.bitContainer) * 8 > FSE_MAX_TABLELOG * 4 + 7) && (srcSize & 2)) - { /* test bit 2 */ - FSE_encodeSymbol(&bitC, &CState2, *--ip); - FSE_encodeSymbol(&bitC, &CState1, *--ip); - FSE_FLUSHBITS(&bitC); - } - - /* 2 or 4 encoding per loop */ - while (ip > istart) - { - - FSE_encodeSymbol(&bitC, &CState2, *--ip); - - if (sizeof(bitC.bitContainer) * 8 < FSE_MAX_TABLELOG * 2 + 7) /* this test must be static */ - FSE_FLUSHBITS(&bitC); - - FSE_encodeSymbol(&bitC, &CState1, *--ip); - - if (sizeof(bitC.bitContainer) * 8 > FSE_MAX_TABLELOG * 4 + 7) - { /* this test must be static */ - FSE_encodeSymbol(&bitC, &CState2, *--ip); - FSE_encodeSymbol(&bitC, &CState1, *--ip); - } - - FSE_FLUSHBITS(&bitC); - } - - FSE_flushCState(&bitC, &CState2); - FSE_flushCState(&bitC, &CState1); - return BIT_closeCStream(&bitC); -} - -size_t FSE_compress_usingCTable(void *dst, size_t dstSize, - const void *src, size_t srcSize, - const FSE_CTable *ct) -{ - unsigned const fast = (dstSize >= FSE_BLOCKBOUND(srcSize)); - - if (fast) - return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1); - else - return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0); -} - -size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } - -#define CHECK_V_F(e, f) \ - size_t const e = f; \ - if (ERR_isError(e)) \ - return f -#define CHECK_F(f) \ - { \ - CHECK_V_F(_var_err__, f); \ - } - -/* FSE_compress_wksp() : - * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). - * `wkspSize` size must be `(1< not compressible */ - if (maxCount < (srcSize >> 7)) - return 0; /* Heuristic : not compressible enough */ - } - - tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); - CHECK_F(FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue)); - - /* Write table description header */ - { - CHECK_V_F(nc_err, FSE_writeNCount(op, oend - op, norm, maxSymbolValue, tableLog)); - op += nc_err; - } - - /* Compress */ - CHECK_F(FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize)); - { - CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, src, srcSize, CTable)); - if (cSize == 0) - return 0; /* not enough space for compressed data */ - op += cSize; - } - - /* check compressibility */ - if ((size_t)(op - ostart) >= srcSize - 1) - return 0; - - return op - ostart; -} - -typedef struct -{ - FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; - BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; -} fseWkspMax_t; - -size_t FSE_compress2(void *dst, size_t dstCapacity, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) -{ - fseWkspMax_t scratchBuffer; - FSE_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); - return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer)); -} - -size_t FSE_compress(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG); -} - -#endif /* FSE_COMMONDEFS_ONLY */ diff --git a/extra/zstd/fse_decompress.c b/extra/zstd/fse_decompress.c deleted file mode 100644 index cf5c6226..00000000 --- a/extra/zstd/fse_decompress.c +++ /dev/null @@ -1,366 +0,0 @@ -/* ****************************************************************** - FSE : Finite State Entropy decoder - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -/* ************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/* ************************************************************** - * Includes - ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include "bitstream.h" -#define FSE_STATIC_LINKING_ONLY -#include "fse.h" - -/* ************************************************************** - * Error Management - ****************************************************************/ -#define FSE_isError ERR_isError -#define FSE_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - FSE_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/* check and forward error code */ -#define CHECK_F(f) \ - { \ - size_t const e = f; \ - if (FSE_isError(e)) \ - return e; \ - } - -/* ************************************************************** - * Templates - ****************************************************************/ -/* - designed to be included - for type-specific functions (template emulation in C) - Objective is to write these functions only once, for improved maintenance -*/ - -/* safety checks */ -#ifndef FSE_FUNCTION_EXTENSION -#error "FSE_FUNCTION_EXTENSION must be defined" -#endif -#ifndef FSE_FUNCTION_TYPE -#error "FSE_FUNCTION_TYPE must be defined" -#endif - -/* Function names */ -#define FSE_CAT(X, Y) X##Y -#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y) -#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y) - -/* Function templates */ -FSE_DTable *FSE_createDTable(unsigned tableLog) -{ - if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) - tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - return (FSE_DTable *)malloc(FSE_DTABLE_SIZE_U32(tableLog) * sizeof(U32)); -} - -void FSE_freeDTable(FSE_DTable *dt) -{ - free(dt); -} - -size_t FSE_buildDTable(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ - FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE + 1]; - - U32 const maxSV1 = maxSymbolValue + 1; - U32 const tableSize = 1 << tableLog; - U32 highThreshold = tableSize - 1; - - /* Sanity Checks */ - if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) - return ERROR(maxSymbolValue_tooLarge); - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); - - /* Init, lay down lowprob symbols */ - { - FSE_DTableHeader DTableH; - DTableH.tableLog = (U16)tableLog; - DTableH.fastMode = 1; - { - S16 const largeLimit = (S16)(1 << (tableLog - 1)); - U32 s; - for (s = 0; s < maxSV1; s++) - { - if (normalizedCounter[s] == -1) - { - tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; - symbolNext[s] = 1; - } - else - { - if (normalizedCounter[s] >= largeLimit) - DTableH.fastMode = 0; - symbolNext[s] = normalizedCounter[s]; - } - } - } - memcpy(dt, &DTableH, sizeof(DTableH)); - } - - /* Spread symbols */ - { - U32 const tableMask = tableSize - 1; - U32 const step = FSE_TABLESTEP(tableSize); - U32 s, position = 0; - for (s = 0; s < maxSV1; s++) - { - int i; - for (i = 0; i < normalizedCounter[s]; i++) - { - tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; - position = (position + step) & tableMask; - while (position > highThreshold) - position = (position + step) & tableMask; /* lowprob area */ - } - } - if (position != 0) - return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ - } - - /* Build Decoding table */ - { - U32 u; - for (u = 0; u < tableSize; u++) - { - FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol); - U16 nextState = symbolNext[symbol]++; - tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState)); - tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize); - } - } - - return 0; -} - -#ifndef FSE_COMMONDEFS_ONLY - -/*-******************************************************* - * Decompression (Byte symbols) - *********************************************************/ -size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - void *dPtr = dt + 1; - FSE_decode_t *const cell = (FSE_decode_t *)dPtr; - - DTableH->tableLog = 0; - DTableH->fastMode = 0; - - cell->newState = 0; - cell->symbol = symbolValue; - cell->nbBits = 0; - - return 0; -} - -size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - void *dPtr = dt + 1; - FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr; - const unsigned tableSize = 1 << nbBits; - const unsigned tableMask = tableSize - 1; - const unsigned maxSV1 = tableMask + 1; - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) - return ERROR(GENERIC); /* min size */ - - /* Build Decoding Table */ - DTableH->tableLog = (U16)nbBits; - DTableH->fastMode = 1; - for (s = 0; s < maxSV1; s++) - { - dinfo[s].newState = 0; - dinfo[s].symbol = (BYTE)s; - dinfo[s].nbBits = (BYTE)nbBits; - } - - return 0; -} - -FORCE_INLINE size_t FSE_decompress_usingDTable_generic( - void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt, const unsigned fast) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - BYTE *const omax = op + maxDstSize; - BYTE *const olimit = omax - 3; - - BIT_DStream_t bitD; - FSE_DState_t state1; - FSE_DState_t state2; - - /* Init */ - CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize)); - - FSE_initDState(&state1, &bitD, dt); - FSE_initDState(&state2, &bitD, dt); - -#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) - - /* 4 symbols per loop */ - for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) - { - op[0] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[1] = FSE_GETSYMBOL(&state2); - - if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - { - if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) - { - op += 2; - break; - } - } - - op[2] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[3] = FSE_GETSYMBOL(&state2); - } - - /* tail */ - /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ - while (1) - { - if (op > (omax - 2)) - return ERROR(dstSize_tooSmall); - *op++ = FSE_GETSYMBOL(&state1); - if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) - { - *op++ = FSE_GETSYMBOL(&state2); - break; - } - - if (op > (omax - 2)) - return ERROR(dstSize_tooSmall); - *op++ = FSE_GETSYMBOL(&state2); - if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) - { - *op++ = FSE_GETSYMBOL(&state1); - break; - } - } - - return op - ostart; -} - -size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt) -{ - const void *ptr = dt; - const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr; - const U32 fastMode = DTableH->fastMode; - - /* select fast mode (static) */ - if (fastMode) - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); -} - -size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, FSE_DTable *workSpace, unsigned maxLog) -{ - const BYTE *const istart = (const BYTE *)cSrc; - const BYTE *ip = istart; - short counting[FSE_MAX_SYMBOL_VALUE + 1]; - unsigned tableLog; - unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; - - /* normal FSE decoding mode */ - size_t const NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize); - if (FSE_isError(NCountLength)) - return NCountLength; - // if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ - if (tableLog > maxLog) - return ERROR(tableLog_tooLarge); - ip += NCountLength; - cSrcSize -= NCountLength; - - CHECK_F(FSE_buildDTable(workSpace, counting, maxSymbolValue, tableLog)); - - return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ -} - -typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; - -size_t FSE_decompress(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize) -{ - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG); -} - -#endif /* FSE_COMMONDEFS_ONLY */ diff --git a/extra/zstd/hash.c b/extra/zstd/hash.c deleted file mode 100644 index 652cb21a..00000000 --- a/extra/zstd/hash.c +++ /dev/null @@ -1,925 +0,0 @@ -/* - * xxHash - Fast Hash algorithm - * Copyright (C) 2012-2016, Yann Collet - * - * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You can contact the author at : - * - xxHash homepage: http://www.xxhash.com - * - xxHash source repository : https://github.com/Cyan4973/xxHash - */ - -/* ************************************* - * Tuning parameters - ***************************************/ -/*!XXH_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 (ie, 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 doesn't depend on compiler but violate C standard. - * It can generate buggy code on targets which do not support unaligned memory accesses. - * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) - * See http://stackoverflow.com/a/32095106/646947 for details. - * Prefer these methods in priority order (0 > 1 > 2) - */ -#ifndef XXH_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 XXH_FORCE_MEMORY_ACCESS 2 -#elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ - (defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__))) -#define XXH_FORCE_MEMORY_ACCESS 1 -#endif -#endif - -/*!XXH_ACCEPT_NULL_INPUT_POINTER : - * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. - * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. - * By default, this option is disabled. To enable it, uncomment below define : - */ -/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */ - -/*!XXH_FORCE_NATIVE_FORMAT : - * By default, xxHash library provides endian-independant Hash values, based on little-endian convention. - * Results are therefore identical for little-endian and big-endian CPU. - * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. - * Should endian-independance be of no importance for your application, you may set the #define below to 1, - * to improve speed for Big-endian CPU. - * This option has no impact on Little_Endian CPU. - */ -#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ -#define XXH_FORCE_NATIVE_FORMAT 0 -#endif - -/*!XXH_FORCE_ALIGN_CHECK : - * This is a minor performance trick, only useful with lots of very small keys. - * It means : check for aligned/unaligned input. - * The check costs one initial branch per hash; set to 0 when the input data - * is guaranteed to be aligned. - */ -#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ -#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) -#define XXH_FORCE_ALIGN_CHECK 0 -#else -#define XXH_FORCE_ALIGN_CHECK 1 -#endif -#endif - -/* ************************************* - * Includes & Memory related functions - ***************************************/ -/* Modify the local functions below should you wish to use some other memory routines */ -/* for malloc(), free() */ -#include -static void *XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free(void *p) { free(p); } -/* for memcpy() */ -#include -static void *XXH_memcpy(void *dest, const void *src, size_t size) { return memcpy(dest, src, size); } - -#ifndef XXH_STATIC_LINKING_ONLY -#define XXH_STATIC_LINKING_ONLY -#endif -#include "xxhash.h" - -/* ************************************* - * Compiler Specific Options - ***************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#define FORCE_INLINE static __forceinline -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/* ************************************* - * Basic Types - ***************************************/ -#ifndef MEM_MODULE -#define MEM_MODULE -#if !defined(__VMS) && (defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)) -#include -typedef uint8_t BYTE; -typedef uint16_t U16; -typedef uint32_t U32; -typedef int32_t S32; -typedef uint64_t U64; -#else -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */ -#endif -#endif - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS == 2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U32 XXH_read32(const void *memPtr) { return *(const U32 *)memPtr; } -static U64 XXH_read64(const void *memPtr) { return *(const U64 *)memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS == 1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union -{ - U32 u32; - U64 u64; -} __attribute__((packed)) unalign; - -static U32 XXH_read32(const void *ptr) { return ((const unalign *)ptr)->u32; } -static U64 XXH_read64(const void *ptr) { return ((const unalign *)ptr)->u64; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ - -static U32 XXH_read32(const void *memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -static U64 XXH_read64(const void *memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - -/* **************************************** - * Compiler-specific Functions and Macros - ******************************************/ -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ -#if defined(_MSC_VER) -#define XXH_rotl32(x, r) _rotl(x, r) -#define XXH_rotl64(x, r) _rotl64(x, r) -#else -#define XXH_rotl32(x, r) ((x << r) | (x >> (32 - r))) -#define XXH_rotl64(x, r) ((x << r) | (x >> (64 - r))) -#endif - -#if defined(_MSC_VER) /* Visual Studio */ -#define XXH_swap32 _byteswap_ulong -#define XXH_swap64 _byteswap_uint64 -#elif GCC_VERSION >= 403 -#define XXH_swap32 __builtin_bswap32 -#define XXH_swap64 __builtin_bswap64 -#else -static U32 XXH_swap32(U32 x) -{ - return ((x << 24) & 0xff000000) | - ((x << 8) & 0x00ff0000) | - ((x >> 8) & 0x0000ff00) | - ((x >> 24) & 0x000000ff); -} -static U64 XXH_swap64(U64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - -/* ************************************* - * Architecture Macros - ***************************************/ -typedef enum -{ - XXH_bigEndian = 0, - XXH_littleEndian = 1 -} XXH_endianess; - -/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ -#ifndef XXH_CPU_LITTLE_ENDIAN -static const int g_one = 1; -#define XXH_CPU_LITTLE_ENDIAN (*(const char *)(&g_one)) -#endif - -/* *************************** - * Memory reads - *****************************/ -typedef enum -{ - XXH_aligned, - XXH_unaligned -} XXH_alignment; - -FORCE_INLINE U32 XXH_readLE32_align(const void *ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align == XXH_unaligned) - return endian == XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); - else - return endian == XXH_littleEndian ? *(const U32 *)ptr : XXH_swap32(*(const U32 *)ptr); -} - -FORCE_INLINE U32 XXH_readLE32(const void *ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -static U32 XXH_readBE32(const void *ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); -} - -FORCE_INLINE U64 XXH_readLE64_align(const void *ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align == XXH_unaligned) - return endian == XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); - else - return endian == XXH_littleEndian ? *(const U64 *)ptr : XXH_swap64(*(const U64 *)ptr); -} - -FORCE_INLINE U64 XXH_readLE64(const void *ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -static U64 XXH_readBE64(const void *ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); -} - -/* ************************************* - * Macros - ***************************************/ -#define XXH_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - XXH_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/* ************************************* - * Constants - ***************************************/ -static const U32 PRIME32_1 = 2654435761U; -static const U32 PRIME32_2 = 2246822519U; -static const U32 PRIME32_3 = 3266489917U; -static const U32 PRIME32_4 = 668265263U; -static const U32 PRIME32_5 = 374761393U; - -static const U64 PRIME64_1 = 11400714785074694791ULL; -static const U64 PRIME64_2 = 14029467366897019727ULL; -static const U64 PRIME64_3 = 1609587929392839161ULL; -static const U64 PRIME64_4 = 9650029242287828579ULL; -static const U64 PRIME64_5 = 2870177450012600261ULL; - -XXH_PUBLIC_API unsigned XXH_versionNumber(void) { return XXH_VERSION_NUMBER; } - -/* ************************** - * Utils - ****************************/ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t *restrict dstState, const XXH32_state_t *restrict srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t *restrict dstState, const XXH64_state_t *restrict srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -/* *************************** - * Simple Hash Functions - *****************************/ - -static U32 XXH32_round(U32 seed, U32 input) -{ - seed += input * PRIME32_2; - seed = XXH_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -FORCE_INLINE U32 XXH32_endian_align(const void *input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE *p = (const BYTE *)input; - const BYTE *bEnd = p + len; - U32 h32; -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p == NULL) - { - len = 0; - bEnd = p = (const BYTE *)(size_t)16; - } -#endif - - if (len >= 16) - { - const BYTE *const limit = bEnd - 16; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do - { - v1 = XXH32_round(v1, XXH_get32bits(p)); - p += 4; - v2 = XXH32_round(v2, XXH_get32bits(p)); - p += 4; - v3 = XXH32_round(v3, XXH_get32bits(p)); - p += 4; - v4 = XXH32_round(v4, XXH_get32bits(p)); - p += 4; - } while (p <= limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } - else - { - h32 = seed + PRIME32_5; - } - - h32 += (U32)len; - - while (p + 4 <= bEnd) - { - h32 += XXH_get32bits(p) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p += 4; - } - - while (p < bEnd) - { - h32 += (*p) * PRIME32_5; - h32 = XXH_rotl32(h32, 11) * PRIME32_1; - p++; - } - - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - -XXH_PUBLIC_API unsigned int XXH32(const void *input, size_t len, unsigned int seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_CREATESTATE_STATIC(state); - XXH32_reset(state, seed); - XXH32_update(state, input, len); - return XXH32_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) - { - if ((((size_t)input) & 3) == 0) - { /* Input is 4-bytes aligned, leverage the speed benefit */ - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } - } - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -static U64 XXH64_round(U64 acc, U64 input) -{ - acc += input * PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= PRIME64_1; - return acc; -} - -static U64 XXH64_mergeRound(U64 acc, U64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * PRIME64_1 + PRIME64_4; - return acc; -} - -FORCE_INLINE U64 XXH64_endian_align(const void *input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE *p = (const BYTE *)input; - const BYTE *const bEnd = p + len; - U64 h64; -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p == NULL) - { - len = 0; - bEnd = p = (const BYTE *)(size_t)32; - } -#endif - - if (len >= 32) - { - const BYTE *const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do - { - v1 = XXH64_round(v1, XXH_get64bits(p)); - p += 8; - v2 = XXH64_round(v2, XXH_get64bits(p)); - p += 8; - v3 = XXH64_round(v3, XXH_get64bits(p)); - p += 8; - v4 = XXH64_round(v4, XXH_get64bits(p)); - p += 8; - } while (p <= limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } - else - { - h64 = seed + PRIME64_5; - } - - h64 += (U64)len; - - while (p + 8 <= bEnd) - { - U64 const k1 = XXH64_round(0, XXH_get64bits(p)); - h64 ^= k1; - h64 = XXH_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; - p += 8; - } - - if (p + 4 <= bEnd) - { - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p += 4; - } - - while (p < bEnd) - { - h64 ^= (*p) * PRIME64_5; - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - p++; - } - - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - -XXH_PUBLIC_API unsigned long long XXH64(const void *input, size_t len, unsigned long long seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_CREATESTATE_STATIC(state); - XXH64_reset(state, seed); - XXH64_update(state, input, len); - return XXH64_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) - { - if ((((size_t)input) & 7) == 0) - { /* Input is aligned, let's leverage the speed advantage */ - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } - } - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -/* ************************************************** - * Advanced Hash Functions - ****************************************************/ - -XXH_PUBLIC_API XXH32_state_t *XXH32_createState(void) -{ - return (XXH32_state_t *)XXH_malloc(sizeof(XXH32_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t *statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API XXH64_state_t *XXH64_createState(void) -{ - return (XXH64_state_t *)XXH_malloc(sizeof(XXH64_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t *statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -/*** Hash feed ***/ - -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, unsigned int seed) -{ - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state) - 4); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME32_1 + PRIME32_2; - state.v2 = seed + PRIME32_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME32_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t *statePtr, unsigned long long seed) -{ - XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state) - 8); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME64_1 + PRIME64_2; - state.v2 = seed + PRIME64_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME64_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - -FORCE_INLINE XXH_errorcode XXH32_update_endian(XXH32_state_t *state, const void *input, size_t len, XXH_endianess endian) -{ - const BYTE *p = (const BYTE *)input; - const BYTE *const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input == NULL) - return XXH_ERROR; -#endif - - state->total_len_32 += (unsigned)len; - state->large_len |= (len >= 16) | (state->total_len_32 >= 16); - - if (state->memsize + len < 16) - { /* fill in tmp buffer */ - XXH_memcpy((BYTE *)(state->mem32) + state->memsize, input, len); - state->memsize += (unsigned)len; - return XXH_OK; - } - - if (state->memsize) - { /* some data left from previous update */ - XXH_memcpy((BYTE *)(state->mem32) + state->memsize, input, 16 - state->memsize); - { - const U32 *p32 = state->mem32; - state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); - p32++; - state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); - p32++; - state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); - p32++; - state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); - p32++; - } - p += 16 - state->memsize; - state->memsize = 0; - } - - if (p <= bEnd - 16) - { - const BYTE *const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do - { - v1 = XXH32_round(v1, XXH_readLE32(p, endian)); - p += 4; - v2 = XXH32_round(v2, XXH_readLE32(p, endian)); - p += 4; - v3 = XXH32_round(v3, XXH_readLE32(p, endian)); - p += 4; - v4 = XXH32_round(v4, XXH_readLE32(p, endian)); - p += 4; - } while (p <= limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) - { - XXH_memcpy(state->mem32, p, (size_t)(bEnd - p)); - state->memsize = (unsigned)(bEnd - p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *state_in, const void *input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U32 XXH32_digest_endian(const XXH32_state_t *state, XXH_endianess endian) -{ - const BYTE *p = (const BYTE *)state->mem32; - const BYTE *const bEnd = (const BYTE *)(state->mem32) + state->memsize; - U32 h32; - - if (state->large_len) - { - h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); - } - else - { - h32 = state->v3 /* == seed */ + PRIME32_5; - } - - h32 += state->total_len_32; - - while (p + 4 <= bEnd) - { - h32 += XXH_readLE32(p, endian) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p += 4; - } - - while (p < bEnd) - { - h32 += (*p) * PRIME32_5; - h32 = XXH_rotl32(h32, 11) * PRIME32_1; - p++; - } - - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - -XXH_PUBLIC_API unsigned int XXH32_digest(const XXH32_state_t *state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - -/* **** XXH64 **** */ - -FORCE_INLINE XXH_errorcode XXH64_update_endian(XXH64_state_t *state, const void *input, size_t len, XXH_endianess endian) -{ - const BYTE *p = (const BYTE *)input; - const BYTE *const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input == NULL) - return XXH_ERROR; -#endif - - state->total_len += len; - - if (state->memsize + len < 32) - { /* fill in tmp buffer */ - XXH_memcpy(((BYTE *)state->mem64) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) - { /* tmp buffer is full */ - XXH_memcpy(((BYTE *)state->mem64) + state->memsize, input, 32 - state->memsize); - state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64 + 0, endian)); - state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64 + 1, endian)); - state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64 + 2, endian)); - state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64 + 3, endian)); - p += 32 - state->memsize; - state->memsize = 0; - } - - if (p + 32 <= bEnd) - { - const BYTE *const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do - { - v1 = XXH64_round(v1, XXH_readLE64(p, endian)); - p += 8; - v2 = XXH64_round(v2, XXH_readLE64(p, endian)); - p += 8; - v3 = XXH64_round(v3, XXH_readLE64(p, endian)); - p += 8; - v4 = XXH64_round(v4, XXH_readLE64(p, endian)); - p += 8; - } while (p <= limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) - { - XXH_memcpy(state->mem64, p, (size_t)(bEnd - p)); - state->memsize = (unsigned)(bEnd - p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH64_state_t *state_in, const void *input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U64 XXH64_digest_endian(const XXH64_state_t *state, XXH_endianess endian) -{ - const BYTE *p = (const BYTE *)state->mem64; - const BYTE *const bEnd = (const BYTE *)state->mem64 + state->memsize; - U64 h64; - - if (state->total_len >= 32) - { - U64 const v1 = state->v1; - U64 const v2 = state->v2; - U64 const v3 = state->v3; - U64 const v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } - else - { - h64 = state->v3 + PRIME64_5; - } - - h64 += (U64)state->total_len; - - while (p + 8 <= bEnd) - { - U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); - h64 ^= k1; - h64 = XXH_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; - p += 8; - } - - if (p + 4 <= bEnd) - { - h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p += 4; - } - - while (p < bEnd) - { - h64 ^= (*p) * PRIME64_5; - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - p++; - } - - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - -XXH_PUBLIC_API unsigned long long XXH64_digest(const XXH64_state_t *state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected == XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - -/* ************************** - * Canonical representation - ****************************/ - -/*! Default XXH result types are basic unsigned 32 and 64 bits. - * The canonical representation follows human-readable write convention, aka big-endian (large digits first). - * These functions allow transformation of hash result into and from its canonical format. - * This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs. - */ - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t *dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) - hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t *dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) - hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t *src) -{ - return XXH_readBE32(src); -} - -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t *src) -{ - return XXH_readBE64(src); -} diff --git a/extra/zstd/huf.h b/extra/zstd/huf.h deleted file mode 100644 index 32a1c1f8..00000000 --- a/extra/zstd/huf.h +++ /dev/null @@ -1,249 +0,0 @@ -/* ****************************************************************** - Huffman coder, part of New Generation Entropy library - header file - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy -****************************************************************** */ -#ifndef HUF_H_298734234 -#define HUF_H_298734234 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* *** Dependencies *** */ -#include /* size_t */ - - /* *** 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 return == 1, srcData is a single repeated byte symbol (RLE compression). - if HUF_isError(return), compression failed (more details using HUF_getErrorName()) - */ - 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. - @return : size of regenerated data (== originalSize), - or an error code, which can be tested using HUF_isError() - */ - 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 */ - size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ - - /* Error Management */ - unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ - const char *HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */ - - /* *** Advanced function *** */ - - /** HUF_compress2() : - * Same as HUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog` . - * `tableLog` must be `<= HUF_TABLELOG_MAX` . */ - size_t HUF_compress2(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog); - - /** HUF_compress4X_wksp() : - * Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */ - size_t HUF_compress4X_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 */ - -#ifdef HUF_STATIC_LINKING_ONLY - -/* *** Dependencies *** */ -#include "mem.h" /* U32 */ - -/* *** Constants *** */ -#define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ -#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not 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 if incompressible 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 */ -#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ - U32 name##hb[maxSymbolValue + 1]; \ - void *name##hv = &(name##hb); \ - HUF_CElt *name = (HUF_CElt *)(name##hv) /* no final ; */ - - /* static allocation of HUF's DTable */ - typedef U32 HUF_DTable; -#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << (maxTableLog))) -#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ - HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = {((U32)((maxTableLog)-1) * 0x01000001)} -#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \ - HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = {((U32)(maxTableLog) * 0x01000001)} - -/* The workspace must have alignment at least 4 and be at least this large */ -#define HUF_WORKSPACE_SIZE (6 << 10) -#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) - - /* **************************************** - * Advanced decompression functions - ******************************************/ - size_t HUF_decompress4X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< single-symbol decoder */ - size_t HUF_decompress4X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< double-symbols decoder */ - - 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_decompress4X2_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< single-symbol decoder */ - size_t HUF_decompress4X4_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< double-symbols decoder */ - - /* **************************************** - * HUF detailed API - ******************************************/ - /*! - HUF_compress() does the following: - 1. count symbol occurrence from source[] into table count[] using FSE_count() - 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. - */ - /* FSE_count() : find it within "fse.h" */ - unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); - typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ - size_t HUF_buildCTable(HUF_CElt *CTable, const unsigned *count, unsigned maxSymbolValue, unsigned maxNbBits); - 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); - - 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 asumed 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, HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ - - /** HUF_buildCTable_wksp() : - * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned. - */ - size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *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_readCTable() : - * Loading a CTable saved with HUF_writeCTable() */ - size_t HUF_readCTable(HUF_CElt *CTable, unsigned maxSymbolValue, const void *src, size_t srcSize); - - /* - HUF_decompress() does the following: - 1. select the decompression algorithm (X2, X4) based on pre-computed heuristics - 2. build Huffman table from save, using HUF_readDTableXn() - 3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable - */ - - /** HUF_selectDecoder() : - * Tells which decoder is likely to decode faster, - * based on a set of pre-determined metrics. - * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 . - * Assumption : 0 < cSrcSize < dstSize <= 128 KB */ - U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize); - - size_t HUF_readDTableX2(HUF_DTable *DTable, const void *src, size_t srcSize); - size_t HUF_readDTableX4(HUF_DTable *DTable, const void *src, size_t srcSize); - - size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable); - size_t HUF_decompress4X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable); - size_t HUF_decompress4X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable); - - /* 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, HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ - - size_t HUF_decompress1X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /* single-symbol decoder */ - size_t HUF_decompress1X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /* double-symbol decoder */ - - size_t HUF_decompress1X_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); - size_t HUF_decompress1X2_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< single-symbol decoder */ - size_t HUF_decompress1X4_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< double-symbols decoder */ - - 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 */ - size_t HUF_decompress1X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable); - size_t HUF_decompress1X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable); - -#endif /* HUF_STATIC_LINKING_ONLY */ - -#if defined(__cplusplus) -} -#endif - -#endif /* HUF_H_298734234 */ diff --git a/extra/zstd/huf_compress.c b/extra/zstd/huf_compress.c deleted file mode 100644 index aa696f12..00000000 --- a/extra/zstd/huf_compress.c +++ /dev/null @@ -1,822 +0,0 @@ -/* ****************************************************************** - Huffman encoder, part of New Generation Entropy library - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -/* ************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - -/* ************************************************************** - * Includes - ****************************************************************/ -#include /* memcpy, memset */ -#include /* printf (debug) */ -#include "bitstream.h" -#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */ -#include "fse.h" /* header compression */ -#define HUF_STATIC_LINKING_ONLY -#include "huf.h" - -/* ************************************************************** - * Error Management - ****************************************************************/ -#define HUF_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - HUF_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ -#define CHECK_V_F(e, f) \ - size_t const e = f; \ - if (ERR_isError(e)) \ - return f -#define CHECK_F(f) \ - { \ - CHECK_V_F(_var_err__, f); \ - } - -/* ************************************************************** - * Utils - ****************************************************************/ -unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue) -{ - return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1); -} - -/* ******************************************************* - * HUF : Huffman block compression - *********************************************************/ -/* HUF_compressWeights() : - * Same as FSE_compress(), but dedicated to huff0's weights compression. - * The use case needs much less stack memory. - * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX. - */ -#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6 -size_t HUF_compressWeights(void *dst, size_t dstSize, const void *weightTable, size_t wtSize) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - BYTE *const oend = ostart + dstSize; - - U32 maxSymbolValue = HUF_TABLELOG_MAX; - U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; - - FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; - BYTE scratchBuffer[1 << MAX_FSE_TABLELOG_FOR_HUFF_HEADER]; - - U32 count[HUF_TABLELOG_MAX + 1]; - S16 norm[HUF_TABLELOG_MAX + 1]; - - /* init conditions */ - if (wtSize <= 1) - return 0; /* Not compressible */ - - /* Scan input and build symbol stats */ - { - CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize)); - if (maxCount == wtSize) - return 1; /* only a single symbol in src : rle */ - if (maxCount == 1) - return 0; /* each symbol present maximum once => not compressible */ - } - - tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); - CHECK_F(FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue)); - - /* Write table description header */ - { - CHECK_V_F(hSize, FSE_writeNCount(op, oend - op, norm, maxSymbolValue, tableLog)); - op += hSize; - } - - /* Compress */ - CHECK_F(FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer))); - { - CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable)); - if (cSize == 0) - return 0; /* not enough space for compressed data */ - op += cSize; - } - - return op - ostart; -} - -struct HUF_CElt_s -{ - U16 val; - BYTE nbBits; -}; /* typedef'd to HUF_CElt within "huf.h" */ - -/*! HUF_writeCTable() : - `CTable` : Huffman tree to save, using huf representation. - @return : size of saved CTable */ -size_t HUF_writeCTable(void *dst, size_t maxDstSize, - const HUF_CElt *CTable, U32 maxSymbolValue, U32 huffLog) -{ - BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ - BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; - BYTE *op = (BYTE *)dst; - U32 n; - - /* check conditions */ - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) - return ERROR(maxSymbolValue_tooLarge); - - /* convert to weight */ - bitsToWeight[0] = 0; - for (n = 1; n < huffLog + 1; n++) - bitsToWeight[n] = (BYTE)(huffLog + 1 - n); - for (n = 0; n < maxSymbolValue; n++) - huffWeight[n] = bitsToWeight[CTable[n].nbBits]; - - /* attempt weights compression by FSE */ - { - CHECK_V_F(hSize, HUF_compressWeights(op + 1, maxDstSize - 1, huffWeight, maxSymbolValue)); - if ((hSize > 1) & (hSize < maxSymbolValue / 2)) - { /* FSE compressed */ - op[0] = (BYTE)hSize; - return hSize + 1; - } - } - - /* write raw values as 4-bits (max : 15) */ - if (maxSymbolValue > (256 - 128)) - return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */ - if (((maxSymbolValue + 1) / 2) + 1 > maxDstSize) - return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ - op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue - 1)); - huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ - for (n = 0; n < maxSymbolValue; n += 2) - op[(n / 2) + 1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n + 1]); - return ((maxSymbolValue + 1) / 2) + 1; -} - -size_t HUF_readCTable(HUF_CElt *CTable, U32 maxSymbolValue, const void *src, size_t srcSize) -{ - BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */ - U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ - U32 tableLog = 0; - U32 nbSymbols = 0; - - /* get symbol weights */ - CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize)); - - /* check result */ - if (tableLog > HUF_TABLELOG_MAX) - return ERROR(tableLog_tooLarge); - if (nbSymbols > maxSymbolValue + 1) - return ERROR(maxSymbolValue_tooSmall); - - /* Prepare base value per rank */ - { - U32 n, nextRankStart = 0; - for (n = 1; n <= tableLog; n++) - { - U32 current = nextRankStart; - nextRankStart += (rankVal[n] << (n - 1)); - rankVal[n] = current; - } - } - - /* fill nbBits */ - { - U32 n; - for (n = 0; n < nbSymbols; n++) - { - const U32 w = huffWeight[n]; - CTable[n].nbBits = (BYTE)(tableLog + 1 - w); - } - } - - /* fill val */ - { - U16 nbPerRank[HUF_TABLELOG_MAX + 2] = {0}; /* support w=0=>n=tableLog+1 */ - U16 valPerRank[HUF_TABLELOG_MAX + 2] = {0}; - { - U32 n; - for (n = 0; n < nbSymbols; n++) - nbPerRank[CTable[n].nbBits]++; - } - /* determine stating value per rank */ - valPerRank[tableLog + 1] = 0; /* for w==0 */ - { - U16 min = 0; - U32 n; - for (n = tableLog; n > 0; n--) - { /* start at n=tablelog <-> w=1 */ - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } - } - /* assign value within rank, symbol order */ - { - U32 n; - for (n = 0; n <= maxSymbolValue; n++) - CTable[n].val = valPerRank[CTable[n].nbBits]++; - } - } - - return readSize; -} - -typedef struct nodeElt_s -{ - U32 count; - U16 parent; - BYTE byte; - BYTE nbBits; -} nodeElt; - -static U32 HUF_setMaxHeight(nodeElt *huffNode, U32 lastNonNull, U32 maxNbBits) -{ - const U32 largestBits = huffNode[lastNonNull].nbBits; - if (largestBits <= maxNbBits) - return largestBits; /* early exit : no elt > maxNbBits */ - - /* there are several too large elements (at least >= 2) */ - { - int totalCost = 0; - const U32 baseCost = 1 << (largestBits - maxNbBits); - U32 n = lastNonNull; - - while (huffNode[n].nbBits > maxNbBits) - { - totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); - huffNode[n].nbBits = (BYTE)maxNbBits; - n--; - } /* n stops at huffNode[n].nbBits <= maxNbBits */ - while (huffNode[n].nbBits == maxNbBits) - n--; /* n end at index of smallest symbol using < maxNbBits */ - - /* renorm totalCost */ - totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ - - /* repay normalized cost */ - { - U32 const noSymbol = 0xF0F0F0F0; - U32 rankLast[HUF_TABLELOG_MAX + 2]; - int pos; - - /* Get pos of last (smallest) symbol per rank */ - memset(rankLast, 0xF0, sizeof(rankLast)); - { - U32 currentNbBits = maxNbBits; - for (pos = n; pos >= 0; pos--) - { - if (huffNode[pos].nbBits >= currentNbBits) - continue; - currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */ - rankLast[maxNbBits - currentNbBits] = pos; - } - } - - while (totalCost > 0) - { - U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; - for (; nBitsToDecrease > 1; nBitsToDecrease--) - { - U32 highPos = rankLast[nBitsToDecrease]; - U32 lowPos = rankLast[nBitsToDecrease - 1]; - if (highPos == noSymbol) - continue; - if (lowPos == noSymbol) - break; - { - U32 const highTotal = huffNode[highPos].count; - U32 const lowTotal = 2 * huffNode[lowPos].count; - if (highTotal <= lowTotal) - break; - } - } - /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ - while ((nBitsToDecrease <= HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ - nBitsToDecrease++; - totalCost -= 1 << (nBitsToDecrease - 1); - if (rankLast[nBitsToDecrease - 1] == noSymbol) - rankLast[nBitsToDecrease - 1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ - huffNode[rankLast[nBitsToDecrease]].nbBits++; - if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ - rankLast[nBitsToDecrease] = noSymbol; - else - { - rankLast[nBitsToDecrease]--; - if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits - nBitsToDecrease) - rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ - } - } /* while (totalCost > 0) */ - - while (totalCost < 0) - { /* Sometimes, cost correction overshoot */ - if (rankLast[1] == noSymbol) - { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ - while (huffNode[n].nbBits == maxNbBits) - n--; - huffNode[n + 1].nbBits--; - rankLast[1] = n + 1; - totalCost++; - continue; - } - huffNode[rankLast[1] + 1].nbBits--; - rankLast[1]++; - totalCost++; - } - } - } /* there are several too large elements (at least >= 2) */ - - return maxNbBits; -} - -typedef struct -{ - U32 base; - U32 current; -} rankPos; - -static void HUF_sort(nodeElt *huffNode, const U32 *count, U32 maxSymbolValue) -{ - rankPos rank[32]; - U32 n; - - memset(rank, 0, sizeof(rank)); - for (n = 0; n <= maxSymbolValue; n++) - { - U32 r = BIT_highbit32(count[n] + 1); - rank[r].base++; - } - for (n = 30; n > 0; n--) - rank[n - 1].base += rank[n].base; - for (n = 0; n < 32; n++) - rank[n].current = rank[n].base; - for (n = 0; n <= maxSymbolValue; n++) - { - U32 const c = count[n]; - U32 const r = BIT_highbit32(c + 1) + 1; - U32 pos = rank[r].current++; - while ((pos > rank[r].base) && (c > huffNode[pos - 1].count)) - huffNode[pos] = huffNode[pos - 1], pos--; - huffNode[pos].count = c; - huffNode[pos].byte = (BYTE)n; - } -} - -/** HUF_buildCTable_wksp() : - * Same as HUF_buildCTable(), but using externally allocated scratch buffer. - * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned. - */ -#define STARTNODE (HUF_SYMBOLVALUE_MAX + 1) -typedef nodeElt huffNodeTable[2 * HUF_SYMBOLVALUE_MAX + 1 + 1]; -size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize) -{ - nodeElt *const huffNode0 = (nodeElt *)workSpace; - nodeElt *const huffNode = huffNode0 + 1; - U32 n, nonNullRank; - int lowS, lowN; - U16 nodeNb = STARTNODE; - U32 nodeRoot; - - /* safety checks */ - if (wkspSize < sizeof(huffNodeTable)) - return ERROR(GENERIC); /* workSpace is not large enough */ - if (maxNbBits == 0) - maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) - return ERROR(GENERIC); - memset(huffNode0, 0, sizeof(huffNodeTable)); - - /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue); - - /* init for parents */ - nonNullRank = maxSymbolValue; - while (huffNode[nonNullRank].count == 0) - nonNullRank--; - lowS = nonNullRank; - nodeRoot = nodeNb + lowS - 1; - lowN = nodeNb; - huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS - 1].count; - huffNode[lowS].parent = huffNode[lowS - 1].parent = nodeNb; - nodeNb++; - lowS -= 2; - for (n = nodeNb; n <= nodeRoot; n++) - huffNode[n].count = (U32)(1U << 30); - huffNode0[0].count = (U32)(1U << 31); /* fake entry, strong barrier */ - - /* create parents */ - while (nodeNb <= nodeRoot) - { - U32 n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - U32 n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++; - huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count; - huffNode[n1].parent = huffNode[n2].parent = nodeNb; - nodeNb++; - } - - /* distribute weights (unlimited tree height) */ - huffNode[nodeRoot].nbBits = 0; - for (n = nodeRoot - 1; n >= STARTNODE; n--) - huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1; - for (n = 0; n <= nonNullRank; n++) - huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1; - - /* enforce maxTableLog */ - maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); - - /* fill result into tree (val, nbBits) */ - { - U16 nbPerRank[HUF_TABLELOG_MAX + 1] = {0}; - U16 valPerRank[HUF_TABLELOG_MAX + 1] = {0}; - if (maxNbBits > HUF_TABLELOG_MAX) - return ERROR(GENERIC); /* check fit into table */ - for (n = 0; n <= nonNullRank; n++) - nbPerRank[huffNode[n].nbBits]++; - /* determine stating value per rank */ - { - U16 min = 0; - for (n = maxNbBits; n > 0; n--) - { - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } - } - for (n = 0; n <= maxSymbolValue; n++) - tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ - for (n = 0; n <= maxSymbolValue; n++) - tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ - } - - return maxNbBits; -} - -/** HUF_buildCTable() : - * Note : count is used before tree is written, so they can safely overlap - */ -size_t HUF_buildCTable(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits) -{ - huffNodeTable nodeTable; - return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, nodeTable, sizeof(nodeTable)); -} - -static size_t HUF_estimateCompressedSize(HUF_CElt *CTable, const unsigned *count, unsigned maxSymbolValue) -{ - size_t nbBits = 0; - int s; - for (s = 0; s <= (int)maxSymbolValue; ++s) - { - nbBits += CTable[s].nbBits * count[s]; - } - return nbBits >> 3; -} - -static int HUF_validateCTable(const HUF_CElt *CTable, const unsigned *count, unsigned maxSymbolValue) -{ - int bad = 0; - int s; - for (s = 0; s <= (int)maxSymbolValue; ++s) - { - bad |= (count[s] != 0) & (CTable[s].nbBits == 0); - } - return !bad; -} - -static void HUF_encodeSymbol(BIT_CStream_t *bitCPtr, U32 symbol, const HUF_CElt *CTable) -{ - BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits); -} - -size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); } - -#define HUF_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s)) - -#define HUF_FLUSHBITS_1(stream) \ - if (sizeof((stream)->bitContainer) * 8 < HUF_TABLELOG_MAX * 2 + 7) \ - HUF_FLUSHBITS(stream) - -#define HUF_FLUSHBITS_2(stream) \ - if (sizeof((stream)->bitContainer) * 8 < HUF_TABLELOG_MAX * 4 + 7) \ - HUF_FLUSHBITS(stream) - -size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable) -{ - const BYTE *ip = (const BYTE *)src; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - BYTE *op = ostart; - size_t n; - const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize)); - BIT_CStream_t bitC; - - /* init */ - if (dstSize < 8) - return 0; /* not enough space to compress */ - { - size_t const initErr = BIT_initCStream(&bitC, op, oend - op); - if (HUF_isError(initErr)) - return 0; - } - - n = srcSize & ~3; /* join to mod 4 */ - switch (srcSize & 3) - { - case 3: - HUF_encodeSymbol(&bitC, ip[n + 2], CTable); - HUF_FLUSHBITS_2(&bitC); - case 2: - HUF_encodeSymbol(&bitC, ip[n + 1], CTable); - HUF_FLUSHBITS_1(&bitC); - case 1: - HUF_encodeSymbol(&bitC, ip[n + 0], CTable); - HUF_FLUSHBITS(&bitC); - case 0: - default:; - } - - for (; n > 0; n -= 4) - { /* note : n&3==0 at this stage */ - HUF_encodeSymbol(&bitC, ip[n - 1], CTable); - HUF_FLUSHBITS_1(&bitC); - HUF_encodeSymbol(&bitC, ip[n - 2], CTable); - HUF_FLUSHBITS_2(&bitC); - HUF_encodeSymbol(&bitC, ip[n - 3], CTable); - HUF_FLUSHBITS_1(&bitC); - HUF_encodeSymbol(&bitC, ip[n - 4], CTable); - HUF_FLUSHBITS(&bitC); - } - - return BIT_closeCStream(&bitC); -} - -size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable) -{ - size_t const segmentSize = (srcSize + 3) / 4; /* first 3 segments */ - const BYTE *ip = (const BYTE *)src; - const BYTE *const iend = ip + srcSize; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - BYTE *op = ostart; - - if (dstSize < 6 + 1 + 1 + 1 + 8) - return 0; /* minimum space to compress successfully */ - if (srcSize < 12) - return 0; /* no saving possible : too small input */ - op += 6; /* jumpTable */ - - { - CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable)); - if (cSize == 0) - return 0; - MEM_writeLE16(ostart, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - { - CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable)); - if (cSize == 0) - return 0; - MEM_writeLE16(ostart + 2, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - { - CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable)); - if (cSize == 0) - return 0; - MEM_writeLE16(ostart + 4, (U16)cSize); - op += cSize; - } - - ip += segmentSize; - { - CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, iend - ip, CTable)); - if (cSize == 0) - return 0; - op += cSize; - } - - return op - ostart; -} - -static size_t HUF_compressCTable_internal( - BYTE *const ostart, BYTE *op, BYTE *const oend, - const void *src, size_t srcSize, - unsigned singleStream, const HUF_CElt *CTable) -{ - size_t const cSize = singleStream ? HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) : HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable); - if (HUF_isError(cSize)) - { - return cSize; - } - if (cSize == 0) - { - return 0; - } /* uncompressible */ - op += cSize; - /* check compressibility */ - if ((size_t)(op - ostart) >= srcSize - 1) - { - return 0; - } - return op - ostart; -} - -/* `workSpace` must a table of at least 1024 unsigned */ -static size_t HUF_compress_internal( - void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - unsigned singleStream, - void *workSpace, size_t wkspSize, - HUF_CElt *oldHufTable, HUF_repeat *repeat, int preferRepeat) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - BYTE *op = ostart; - - U32 *count; - size_t const countSize = sizeof(U32) * (HUF_SYMBOLVALUE_MAX + 1); - HUF_CElt *CTable; - size_t const CTableSize = sizeof(HUF_CElt) * (HUF_SYMBOLVALUE_MAX + 1); - - /* checks & inits */ - if (wkspSize < sizeof(huffNodeTable) + countSize + CTableSize) - return ERROR(GENERIC); - if (!srcSize) - return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */ - if (!dstSize) - return 0; /* cannot fit within dst budget */ - if (srcSize > HUF_BLOCKSIZE_MAX) - return ERROR(srcSize_wrong); /* current block size limit */ - if (huffLog > HUF_TABLELOG_MAX) - return ERROR(tableLog_tooLarge); - if (!maxSymbolValue) - maxSymbolValue = HUF_SYMBOLVALUE_MAX; - if (!huffLog) - huffLog = HUF_TABLELOG_DEFAULT; - - count = (U32 *)workSpace; - workSpace = (BYTE *)workSpace + countSize; - wkspSize -= countSize; - CTable = (HUF_CElt *)workSpace; - workSpace = (BYTE *)workSpace + CTableSize; - wkspSize -= CTableSize; - - /* Heuristic : If we don't need to check the validity of the old table use the old table for small inputs */ - if (preferRepeat && repeat && *repeat == HUF_repeat_valid) - { - return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable); - } - - /* Scan input and build symbol stats */ - { - CHECK_V_F(largest, FSE_count_wksp(count, &maxSymbolValue, (const BYTE *)src, srcSize, (U32 *)workSpace)); - if (largest == srcSize) - { - *ostart = ((const BYTE *)src)[0]; - return 1; - } /* single symbol, rle */ - if (largest <= (srcSize >> 7) + 1) - return 0; /* Fast heuristic : not compressible enough */ - } - - /* Check validity of previous table */ - if (repeat && *repeat == HUF_repeat_check && !HUF_validateCTable(oldHufTable, count, maxSymbolValue)) - { - *repeat = HUF_repeat_none; - } - /* Heuristic : use existing table for small inputs */ - if (preferRepeat && repeat && *repeat != HUF_repeat_none) - { - return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable); - } - - /* Build Huffman Tree */ - huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); - { - CHECK_V_F(maxBits, HUF_buildCTable_wksp(CTable, count, maxSymbolValue, huffLog, workSpace, wkspSize)); - huffLog = (U32)maxBits; - /* Zero the unused symbols so we can check it for validity */ - memset(CTable + maxSymbolValue + 1, 0, CTableSize - (maxSymbolValue + 1) * sizeof(HUF_CElt)); - } - - /* Write table description header */ - { - CHECK_V_F(hSize, HUF_writeCTable(op, dstSize, CTable, maxSymbolValue, huffLog)); - /* Check if using the previous table will be beneficial */ - if (repeat && *repeat != HUF_repeat_none) - { - size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, count, maxSymbolValue); - size_t const newSize = HUF_estimateCompressedSize(CTable, count, maxSymbolValue); - if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) - { - return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, oldHufTable); - } - } - /* Use the new table */ - if (hSize + 12ul >= srcSize) - { - return 0; - } - op += hSize; - if (repeat) - { - *repeat = HUF_repeat_none; - } - if (oldHufTable) - { - memcpy(oldHufTable, CTable, CTableSize); - } /* Save the new table */ - } - return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, CTable); -} - -size_t HUF_compress1X_wksp(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void *workSpace, size_t wkspSize) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, NULL, NULL, 0); -} - -size_t HUF_compress1X_repeat(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void *workSpace, size_t wkspSize, - HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, hufTable, repeat, preferRepeat); -} - -size_t HUF_compress1X(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[1024]; - return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - -size_t HUF_compress4X_wksp(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void *workSpace, size_t wkspSize) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, NULL, NULL, 0); -} - -size_t HUF_compress4X_repeat(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog, - void *workSpace, size_t wkspSize, - HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat) -{ - return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, hufTable, repeat, preferRepeat); -} - -size_t HUF_compress2(void *dst, size_t dstSize, - const void *src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[1024]; - return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - -size_t HUF_compress(void *dst, size_t maxDstSize, const void *src, size_t srcSize) -{ - return HUF_compress2(dst, maxDstSize, src, (U32)srcSize, 255, HUF_TABLELOG_DEFAULT); -} diff --git a/extra/zstd/huf_decompress.c b/extra/zstd/huf_decompress.c deleted file mode 100644 index 056287c1..00000000 --- a/extra/zstd/huf_decompress.c +++ /dev/null @@ -1,1048 +0,0 @@ -/* ****************************************************************** - Huffman decoder, part of New Generation Entropy library - Copyright (C) 2013-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -/* ************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/* ************************************************************** - * Dependencies - ****************************************************************/ -#include /* memcpy, memset */ -#include "bitstream.h" /* BIT_* */ -#include "fse.h" /* header compression */ -#define HUF_STATIC_LINKING_ONLY -#include "huf.h" - -/* ************************************************************** - * Error Management - ****************************************************************/ -#define HUF_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - HUF_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/*-***************************/ -/* generic DTableDesc */ -/*-***************************/ - -typedef struct -{ - BYTE maxTableLog; - BYTE tableType; - BYTE tableLog; - BYTE reserved; -} DTableDesc; - -static DTableDesc HUF_getDTableDesc(const HUF_DTable *table) -{ - DTableDesc dtd; - memcpy(&dtd, table, sizeof(dtd)); - return dtd; -} - -/*-***************************/ -/* single-symbol decoding */ -/*-***************************/ - -typedef struct -{ - BYTE byte; - BYTE nbBits; -} HUF_DEltX2; /* single-symbol decoding */ - -size_t HUF_readDTableX2(HUF_DTable *DTable, const void *src, size_t srcSize) -{ - BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; - U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ - U32 tableLog = 0; - U32 nbSymbols = 0; - size_t iSize; - void *const dtPtr = DTable + 1; - HUF_DEltX2 *const dt = (HUF_DEltX2 *)dtPtr; - - HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); - /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) - return iSize; - - /* Table header */ - { - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (tableLog > (U32)(dtd.maxTableLog + 1)) - return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ - dtd.tableType = 0; - dtd.tableLog = (BYTE)tableLog; - memcpy(DTable, &dtd, sizeof(dtd)); - } - - /* Calculate starting value for each rank */ - { - U32 n, nextRankStart = 0; - for (n = 1; n < tableLog + 1; n++) - { - U32 const current = nextRankStart; - nextRankStart += (rankVal[n] << (n - 1)); - rankVal[n] = current; - } - } - - /* fill DTable */ - { - U32 n; - for (n = 0; n < nbSymbols; n++) - { - U32 const w = huffWeight[n]; - U32 const length = (1 << w) >> 1; - U32 u; - HUF_DEltX2 D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(tableLog + 1 - w); - for (u = rankVal[w]; u < rankVal[w] + length; u++) - dt[u] = D; - rankVal[w] += length; - } - } - - return iSize; -} - -static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ - BYTE const c = dt[val].byte; - BIT_skipBits(Dstream, dt[val].nbBits); - return c; -} - -#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ - *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_TABLELOG_MAX <= 12)) \ - HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) - -#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) - -FORCE_INLINE size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog) -{ - BYTE *const pStart = p; - - /* up to 4 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) - { - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_1(p, bitDPtr); - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - } - - /* closer to the end */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd)) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - - /* no more data to retrieve from bitstream, hence no need to reload */ - while (p < pEnd) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - - return pEnd - pStart; -} - -static size_t HUF_decompress1X2_usingDTable_internal( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - BYTE *op = (BYTE *)dst; - BYTE *const oend = op + dstSize; - const void *dtPtr = DTable + 1; - const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr; - BIT_DStream_t bitD; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - - { - size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); - if (HUF_isError(errorCode)) - return errorCode; - } - - HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog); - - /* check */ - if (!BIT_endOfDStream(&bitD)) - return ERROR(corruption_detected); - - return dstSize; -} - -size_t HUF_decompress1X2_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 0) - return ERROR(GENERIC); - return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable); -} - -size_t HUF_decompress1X2_DCtx(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *ip = (const BYTE *)cSrc; - - size_t const hSize = HUF_readDTableX2(DCtx, cSrc, cSrcSize); - if (HUF_isError(hSize)) - return hSize; - if (hSize >= cSrcSize) - return ERROR(srcSize_wrong); - ip += hSize; - cSrcSize -= hSize; - - return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx); -} - -size_t HUF_decompress1X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -static size_t HUF_decompress4X2_usingDTable_internal( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - /* Check */ - if (cSrcSize < 10) - return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { - const BYTE *const istart = (const BYTE *)cSrc; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - const void *const dtPtr = DTable + 1; - const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - size_t const length1 = MEM_readLE16(istart); - size_t const length2 = MEM_readLE16(istart + 2); - size_t const length3 = MEM_readLE16(istart + 4); - size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); - const BYTE *const istart1 = istart + 6; /* jumpTable */ - const BYTE *const istart2 = istart1 + length1; - const BYTE *const istart3 = istart2 + length2; - const BYTE *const istart4 = istart3 + length3; - const size_t segmentSize = (dstSize + 3) / 4; - BYTE *const opStart2 = ostart + segmentSize; - BYTE *const opStart3 = opStart2 + segmentSize; - BYTE *const opStart4 = opStart3 + segmentSize; - BYTE *op1 = ostart; - BYTE *op2 = opStart2; - BYTE *op3 = opStart3; - BYTE *op4 = opStart4; - U32 endSignal; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - - if (length4 > cSrcSize) - return ERROR(corruption_detected); /* overflow */ - { - size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4); - if (HUF_isError(errorCode)) - return errorCode; - } - - /* 16-32 symbols per loop (4-8 symbols per stream) */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) - { - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_1(op1, &bitD1); - HUF_DECODE_SYMBOLX2_1(op2, &bitD2); - HUF_DECODE_SYMBOLX2_1(op3, &bitD3); - HUF_DECODE_SYMBOLX2_1(op4, &bitD4); - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_0(op1, &bitD1); - HUF_DECODE_SYMBOLX2_0(op2, &bitD2); - HUF_DECODE_SYMBOLX2_0(op3, &bitD3); - HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - } - - /* check corruption */ - if (op1 > opStart2) - return ERROR(corruption_detected); - if (op2 > opStart3) - return ERROR(corruption_detected); - if (op3 > opStart4) - return ERROR(corruption_detected); - /* note : op4 supposed already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); - - /* check */ - endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endSignal) - return ERROR(corruption_detected); - - /* decoded size */ - return dstSize; - } -} - -size_t HUF_decompress4X2_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 0) - return ERROR(GENERIC); - return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable); -} - -size_t HUF_decompress4X2_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *ip = (const BYTE *)cSrc; - - size_t const hSize = HUF_readDTableX2(dctx, cSrc, cSrcSize); - if (HUF_isError(hSize)) - return hSize; - if (hSize >= cSrcSize) - return ERROR(srcSize_wrong); - ip += hSize; - cSrcSize -= hSize; - - return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx); -} - -size_t HUF_decompress4X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -/* *************************/ -/* double-symbols decoding */ -/* *************************/ -typedef struct -{ - U16 sequence; - BYTE nbBits; - BYTE length; -} HUF_DEltX4; /* double-symbols decoding */ - -typedef struct -{ - BYTE symbol; - BYTE weight; -} sortedSymbol_t; - -/* HUF_fillDTableX4Level2() : - * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */ -static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, - const U32 *rankValOrigin, const int minWeight, - const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, - U32 nbBitsBaseline, U16 baseSeq) -{ - HUF_DEltX4 DElt; - U32 rankVal[HUF_TABLELOG_MAX + 1]; - - /* get pre-calculated rankVal */ - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill skipped values */ - if (minWeight > 1) - { - U32 i, skipSize = rankVal[minWeight]; - MEM_writeLE16(&(DElt.sequence), baseSeq); - DElt.nbBits = (BYTE)(consumed); - DElt.length = 1; - for (i = 0; i < skipSize; i++) - DTable[i] = DElt; - } - - /* fill DTable */ - { - U32 s; - for (s = 0; s < sortedListSize; s++) - { /* note : sortedSymbols already skipped */ - const U32 symbol = sortedSymbols[s].symbol; - const U32 weight = sortedSymbols[s].weight; - const U32 nbBits = nbBitsBaseline - weight; - const U32 length = 1 << (sizeLog - nbBits); - const U32 start = rankVal[weight]; - U32 i = start; - const U32 end = start + length; - - MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8))); - DElt.nbBits = (BYTE)(nbBits + consumed); - DElt.length = 2; - do - { - DTable[i++] = DElt; - } while (i < end); /* since length >= 1 */ - - rankVal[weight] += length; - } - } -} - -typedef U32 rankVal_t[HUF_TABLELOG_MAX][HUF_TABLELOG_MAX + 1]; - -static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, - const sortedSymbol_t *sortedList, const U32 sortedListSize, - const U32 *rankStart, rankVal_t rankValOrigin, const U32 maxWeight, - const U32 nbBitsBaseline) -{ - U32 rankVal[HUF_TABLELOG_MAX + 1]; - const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ - const U32 minBits = nbBitsBaseline - maxWeight; - U32 s; - - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill DTable */ - for (s = 0; s < sortedListSize; s++) - { - const U16 symbol = sortedList[s].symbol; - const U32 weight = sortedList[s].weight; - const U32 nbBits = nbBitsBaseline - weight; - const U32 start = rankVal[weight]; - const U32 length = 1 << (targetLog - nbBits); - - if (targetLog - nbBits >= minBits) - { /* enough room for a second symbol */ - U32 sortedRank; - int minWeight = nbBits + scaleLog; - if (minWeight < 1) - minWeight = 1; - sortedRank = rankStart[minWeight]; - HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, - rankValOrigin[nbBits], minWeight, - sortedList + sortedRank, sortedListSize - sortedRank, - nbBitsBaseline, symbol); - } - else - { - HUF_DEltX4 DElt; - MEM_writeLE16(&(DElt.sequence), symbol); - DElt.nbBits = (BYTE)(nbBits); - DElt.length = 1; - { - U32 const end = start + length; - U32 u; - for (u = start; u < end; u++) - DTable[u] = DElt; - } - } - rankVal[weight] += length; - } -} - -size_t HUF_readDTableX4(HUF_DTable *DTable, const void *src, size_t srcSize) -{ - BYTE weightList[HUF_SYMBOLVALUE_MAX + 1]; - sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1]; - U32 rankStats[HUF_TABLELOG_MAX + 1] = {0}; - U32 rankStart0[HUF_TABLELOG_MAX + 2] = {0}; - U32 *const rankStart = rankStart0 + 1; - rankVal_t rankVal; - U32 tableLog, maxW, sizeOfSort, nbSymbols; - DTableDesc dtd = HUF_getDTableDesc(DTable); - U32 const maxTableLog = dtd.maxTableLog; - size_t iSize; - void *dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */ - HUF_DEltX4 *const dt = (HUF_DEltX4 *)dtPtr; - - HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ - if (maxTableLog > HUF_TABLELOG_MAX) - return ERROR(tableLog_tooLarge); - /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) - return iSize; - - /* check result */ - if (tableLog > maxTableLog) - return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ - - /* find maxWeight */ - for (maxW = tableLog; rankStats[maxW] == 0; maxW--) - { - } /* necessarily finds a solution before 0 */ - - /* Get start index of each weight */ - { - U32 w, nextRankStart = 0; - for (w = 1; w < maxW + 1; w++) - { - U32 current = nextRankStart; - nextRankStart += rankStats[w]; - rankStart[w] = current; - } - rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ - sizeOfSort = nextRankStart; - } - - /* sort symbols by weight */ - { - U32 s; - for (s = 0; s < nbSymbols; s++) - { - U32 const w = weightList[s]; - U32 const r = rankStart[w]++; - sortedSymbol[r].symbol = (BYTE)s; - sortedSymbol[r].weight = (BYTE)w; - } - rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ - } - - /* Build rankVal */ - { - U32 *const rankVal0 = rankVal[0]; - { - int const rescale = (maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */ - U32 nextRankVal = 0; - U32 w; - for (w = 1; w < maxW + 1; w++) - { - U32 current = nextRankVal; - nextRankVal += rankStats[w] << (w + rescale); - rankVal0[w] = current; - } - } - { - U32 const minBits = tableLog + 1 - maxW; - U32 consumed; - for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) - { - U32 *const rankValPtr = rankVal[consumed]; - U32 w; - for (w = 1; w < maxW + 1; w++) - { - rankValPtr[w] = rankVal0[w] >> consumed; - } - } - } - } - - HUF_fillDTableX4(dt, maxTableLog, - sortedSymbol, sizeOfSort, - rankStart0, rankVal, maxW, - tableLog + 1); - - dtd.tableLog = (BYTE)maxTableLog; - dtd.tableType = 1; - memcpy(DTable, &dtd, sizeof(dtd)); - return iSize; -} - -static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt + val, 2); - BIT_skipBits(DStream, dt[val].nbBits); - return dt[val].length; -} - -static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog) -{ - size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt + val, 1); - if (dt[val].length == 1) - BIT_skipBits(DStream, dt[val].nbBits); - else - { - if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) - { - BIT_skipBits(DStream, dt[val].nbBits); - if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8)) - DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ - } - } - return 1; -} - -#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_TABLELOG_MAX <= 12)) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -FORCE_INLINE size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog) -{ - BYTE *const pStart = p; - - /* up to 8 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd - (sizeof(bitDPtr->bitContainer) - 1))) - { - HUF_DECODE_SYMBOLX4_2(p, bitDPtr); - HUF_DECODE_SYMBOLX4_1(p, bitDPtr); - HUF_DECODE_SYMBOLX4_2(p, bitDPtr); - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); - } - - /* closer to end : up to 2 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd - 2)) - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); - - while (p <= pEnd - 2) - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ - - if (p < pEnd) - p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog); - - return p - pStart; -} - -static size_t HUF_decompress1X4_usingDTable_internal( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - BIT_DStream_t bitD; - - /* Init */ - { - size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); - if (HUF_isError(errorCode)) - return errorCode; - } - - /* decode */ - { - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - const void *const dtPtr = DTable + 1; /* force compiler to not use strict-aliasing */ - const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog); - } - - /* check */ - if (!BIT_endOfDStream(&bitD)) - return ERROR(corruption_detected); - - /* decoded size */ - return dstSize; -} - -size_t HUF_decompress1X4_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 1) - return ERROR(GENERIC); - return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable); -} - -size_t HUF_decompress1X4_DCtx(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *ip = (const BYTE *)cSrc; - - size_t const hSize = HUF_readDTableX4(DCtx, cSrc, cSrcSize); - if (HUF_isError(hSize)) - return hSize; - if (hSize >= cSrcSize) - return ERROR(srcSize_wrong); - ip += hSize; - cSrcSize -= hSize; - - return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx); -} - -size_t HUF_decompress1X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -static size_t HUF_decompress4X4_usingDTable_internal( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - if (cSrcSize < 10) - return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { - const BYTE *const istart = (const BYTE *)cSrc; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - const void *const dtPtr = DTable + 1; - const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - size_t const length1 = MEM_readLE16(istart); - size_t const length2 = MEM_readLE16(istart + 2); - size_t const length3 = MEM_readLE16(istart + 4); - size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6); - const BYTE *const istart1 = istart + 6; /* jumpTable */ - const BYTE *const istart2 = istart1 + length1; - const BYTE *const istart3 = istart2 + length2; - const BYTE *const istart4 = istart3 + length3; - size_t const segmentSize = (dstSize + 3) / 4; - BYTE *const opStart2 = ostart + segmentSize; - BYTE *const opStart3 = opStart2 + segmentSize; - BYTE *const opStart4 = opStart3 + segmentSize; - BYTE *op1 = ostart; - BYTE *op2 = opStart2; - BYTE *op3 = opStart3; - BYTE *op4 = opStart4; - U32 endSignal; - DTableDesc const dtd = HUF_getDTableDesc(DTable); - U32 const dtLog = dtd.tableLog; - - if (length4 > cSrcSize) - return ERROR(corruption_detected); /* overflow */ - { - size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3); - if (HUF_isError(errorCode)) - return errorCode; - } - { - size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4); - if (HUF_isError(errorCode)) - return errorCode; - } - - /* 16-32 symbols per loop (4-8 symbols per stream) */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for (; (endSignal == BIT_DStream_unfinished) & (op4 < (oend - (sizeof(bitD4.bitContainer) - 1)));) - { - HUF_DECODE_SYMBOLX4_2(op1, &bitD1); - HUF_DECODE_SYMBOLX4_2(op2, &bitD2); - HUF_DECODE_SYMBOLX4_2(op3, &bitD3); - HUF_DECODE_SYMBOLX4_2(op4, &bitD4); - HUF_DECODE_SYMBOLX4_1(op1, &bitD1); - HUF_DECODE_SYMBOLX4_1(op2, &bitD2); - HUF_DECODE_SYMBOLX4_1(op3, &bitD3); - HUF_DECODE_SYMBOLX4_1(op4, &bitD4); - HUF_DECODE_SYMBOLX4_2(op1, &bitD1); - HUF_DECODE_SYMBOLX4_2(op2, &bitD2); - HUF_DECODE_SYMBOLX4_2(op3, &bitD3); - HUF_DECODE_SYMBOLX4_2(op4, &bitD4); - HUF_DECODE_SYMBOLX4_0(op1, &bitD1); - HUF_DECODE_SYMBOLX4_0(op2, &bitD2); - HUF_DECODE_SYMBOLX4_0(op3, &bitD3); - HUF_DECODE_SYMBOLX4_0(op4, &bitD4); - - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - } - - /* check corruption */ - if (op1 > opStart2) - return ERROR(corruption_detected); - if (op2 > opStart3) - return ERROR(corruption_detected); - if (op3 > opStart4) - return ERROR(corruption_detected); - /* note : op4 already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog); - - /* check */ - { - U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endCheck) - return ERROR(corruption_detected); - } - - /* decoded size */ - return dstSize; - } -} - -size_t HUF_decompress4X4_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc dtd = HUF_getDTableDesc(DTable); - if (dtd.tableType != 1) - return ERROR(GENERIC); - return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable); -} - -size_t HUF_decompress4X4_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *ip = (const BYTE *)cSrc; - - size_t hSize = HUF_readDTableX4(dctx, cSrc, cSrcSize); - if (HUF_isError(hSize)) - return hSize; - if (hSize >= cSrcSize) - return ERROR(srcSize_wrong); - ip += hSize; - cSrcSize -= hSize; - - return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx); -} - -size_t HUF_decompress4X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - -/* ********************************/ -/* Generic decompression selector */ -/* ********************************/ - -size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); - return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) : HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable); -} - -size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const HUF_DTable *DTable) -{ - DTableDesc const dtd = HUF_getDTableDesc(DTable); - return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) : HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable); -} - -typedef struct -{ - U32 tableTime; - U32 decode256Time; -} algo_time_t; -static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = - { - /* single, double, quad */ - {{0, 0}, {1, 1}, {2, 2}}, /* Q==0 : impossible */ - {{0, 0}, {1, 1}, {2, 2}}, /* Q==1 : impossible */ - {{38, 130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */ - {{448, 128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */ - {{556, 128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */ - {{714, 128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */ - {{883, 128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */ - {{897, 128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */ - {{926, 128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */ - {{947, 128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */ - {{1107, 128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */ - {{1177, 128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */ - {{1242, 128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */ - {{1349, 128}, {2644, 106}, {5260, 106}}, /* Q ==13 : 81-87% */ - {{1455, 128}, {2422, 124}, {4174, 124}}, /* Q ==14 : 87-93% */ - {{722, 128}, {1891, 145}, {1936, 146}}, /* Q ==15 : 93-99% */ -}; - -/** HUF_selectDecoder() : - * Tells which decoder is likely to decode faster, - * based on a set of pre-determined metrics. - * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 . - * Assumption : 0 < cSrcSize < dstSize <= 128 KB */ -U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize) -{ - /* decoder timing evaluation */ - U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */ - U32 const D256 = (U32)(dstSize >> 8); - U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256); - U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256); - DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */ - - return DTime1 < DTime0; -} - -typedef size_t (*decompressionAlgo)(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); - -size_t HUF_decompress(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - static const decompressionAlgo decompress[2] = {HUF_decompress4X2, HUF_decompress4X4}; - - /* validation checks */ - if (dstSize == 0) - return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) - return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) - { - memcpy(dst, cSrc, dstSize); - return dstSize; - } /* not compressed */ - if (cSrcSize == 1) - { - memset(dst, *(const BYTE *)cSrc, dstSize); - return dstSize; - } /* RLE */ - - { - U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); - return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); - } -} - -size_t HUF_decompress4X_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) - return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) - return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) - { - memcpy(dst, cSrc, dstSize); - return dstSize; - } /* not compressed */ - if (cSrcSize == 1) - { - memset(dst, *(const BYTE *)cSrc, dstSize); - return dstSize; - } /* RLE */ - - { - U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); - return algoNb ? HUF_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); - } -} - -size_t HUF_decompress4X_hufOnly(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) - return ERROR(dstSize_tooSmall); - if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) - return ERROR(corruption_detected); /* invalid */ - - { - U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); - return algoNb ? HUF_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); - } -} - -size_t HUF_decompress1X_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) - return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) - return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) - { - memcpy(dst, cSrc, dstSize); - return dstSize; - } /* not compressed */ - if (cSrcSize == 1) - { - memset(dst, *(const BYTE *)cSrc, dstSize); - return dstSize; - } /* RLE */ - - { - U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); - return algoNb ? HUF_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : HUF_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); - } -} diff --git a/extra/zstd/mem.h b/extra/zstd/mem.h deleted file mode 100644 index 2a56aea9..00000000 --- a/extra/zstd/mem.h +++ /dev/null @@ -1,409 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef MEM_H_MODULE -#define MEM_H_MODULE - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*-**************************************** - * Dependencies - ******************************************/ -#include /* size_t, ptrdiff_t */ -#include /* memcpy */ - -/*-**************************************** - * Compiler specifics - ******************************************/ -#if defined(_MSC_VER) /* Visual Studio */ -#include /* _byteswap_ulong */ -#include /* _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 - -/* code only tested on 32 and 64 bits systems */ -#define MEM_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - MEM_static_assert = 1 / (int)(!!(c)) \ - }; \ - } - MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t) == 4) || (sizeof(size_t) == 8)); } - -/*-************************************************************** - * Basic Types - *****************************************************************/ -#if !defined(__VMS) && (defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)) -#include - 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; - typedef intptr_t iPtrDiff; - typedef uintptr_t uPtrDiff; -#else -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef signed short S16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; -typedef signed long long S64; -typedef ptrdiff_t iPtrDiff; -typedef size_t uPtrDiff; -#endif - -/*-************************************************************** - * Memory I/O - *****************************************************************/ -/* 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(_MSC_VER)*/ || \ - (defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__))) -#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 U64 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 union -{ - U16 u16; - U32 u32; - U64 u64; - size_t st; -} unalign; -__pragma(pack(pop)) -#else -typedef union -{ - U16 u16; - U32 u32; - U64 u64; - size_t st; -} __attribute__((packed)) unalign; -#endif - - MEM_STATIC U16 MEM_read16(const void *ptr) -{ - return ((const unalign *)ptr)->u16; -} -MEM_STATIC U32 MEM_read32(const void *ptr) { return ((const unalign *)ptr)->u32; } -MEM_STATIC U64 MEM_read64(const void *ptr) { return ((const unalign *)ptr)->u64; } -MEM_STATIC U64 MEM_readST(const void *ptr) { return ((const unalign *)ptr)->st; } - -MEM_STATIC void MEM_write16(void *memPtr, U16 value) { ((unalign *)memPtr)->u16 = value; } -MEM_STATIC void MEM_write32(void *memPtr, U32 value) { ((unalign *)memPtr)->u32 = value; } -MEM_STATIC void MEM_write64(void *memPtr, U64 value) { ((unalign *)memPtr)->u64 = value; } - -#else - -/* default method, safe and standard. - can sometimes prove slower */ - -MEM_STATIC U16 MEM_read16(const void *memPtr) -{ - U16 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC U32 MEM_read32(const void *memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC U64 MEM_read64(const void *memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC size_t MEM_readST(const void *memPtr) -{ - size_t val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC void MEM_write16(void *memPtr, U16 value) -{ - memcpy(memPtr, &value, sizeof(value)); -} - -MEM_STATIC void MEM_write32(void *memPtr, U32 value) -{ - memcpy(memPtr, &value, sizeof(value)); -} - -MEM_STATIC void MEM_write64(void *memPtr, U64 value) -{ - 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) - 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) - 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); - } - - /* function safe only for comparisons */ - MEM_STATIC U32 MEM_readMINMATCH(const void *memPtr, U32 length) - { - switch (length) - { - default: - case 4: - return MEM_read32(memPtr); - case 3: - if (MEM_isLittleEndian()) - return MEM_read32(memPtr) << 8; - else - return MEM_read32(memPtr) >> 8; - } - } - -#if defined(__cplusplus) -} -#endif - -#endif /* MEM_H_MODULE */ diff --git a/extra/zstd/pool.c b/extra/zstd/pool.c deleted file mode 100644 index c6b9cad5..00000000 --- a/extra/zstd/pool.c +++ /dev/null @@ -1,239 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* ====== Dependencies ======= */ -#include /* size_t */ -#include /* malloc, calloc, free */ -#include "pool.h" - -/* ====== Compiler specifics ====== */ -#if defined(_MSC_VER) -#pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ -#endif - -#ifdef ZSTD_MULTITHREAD - -#include "threading.h" /* pthread adaptation */ - -/* A job is a function and an opaque argument */ -typedef struct POOL_job_s -{ - POOL_function function; - void *opaque; -} POOL_job; - -struct POOL_ctx_s -{ - /* Keep track of the threads */ - pthread_t *threads; - size_t numThreads; - - /* The queue is a circular buffer */ - POOL_job *queue; - size_t queueHead; - size_t queueTail; - size_t queueSize; - /* The mutex protects the queue */ - pthread_mutex_t queueMutex; - /* Condition variable for pushers to wait on when the queue is full */ - pthread_cond_t queuePushCond; - /* Condition variables for poppers to wait on when the queue is empty */ - pthread_cond_t queuePopCond; - /* Indicates if the queue is shutting down */ - int shutdown; -}; - -/* POOL_thread() : - Work thread for the thread pool. - Waits for jobs and executes them. - @returns : NULL on failure else non-null. -*/ -static void *POOL_thread(void *opaque) -{ - POOL_ctx *const ctx = (POOL_ctx *)opaque; - if (!ctx) - { - return NULL; - } - for (;;) - { - /* Lock the mutex and wait for a non-empty queue or until shutdown */ - pthread_mutex_lock(&ctx->queueMutex); - while (ctx->queueHead == ctx->queueTail && !ctx->shutdown) - { - pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex); - } - /* empty => shutting down: so stop */ - if (ctx->queueHead == ctx->queueTail) - { - pthread_mutex_unlock(&ctx->queueMutex); - return opaque; - } - /* Pop a job off the queue */ - { - POOL_job const job = ctx->queue[ctx->queueHead]; - ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize; - /* Unlock the mutex, signal a pusher, and run the job */ - pthread_mutex_unlock(&ctx->queueMutex); - pthread_cond_signal(&ctx->queuePushCond); - job.function(job.opaque); - } - } - /* Unreachable */ -} - -POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) -{ - POOL_ctx *ctx; - /* Check the parameters */ - if (!numThreads || !queueSize) - { - return NULL; - } - /* Allocate the context and zero initialize */ - ctx = (POOL_ctx *)calloc(1, sizeof(POOL_ctx)); - if (!ctx) - { - return NULL; - } - /* Initialize the job queue. - * It needs one extra space since one space is wasted to differentiate empty - * and full queues. - */ - ctx->queueSize = queueSize + 1; - ctx->queue = (POOL_job *)malloc(ctx->queueSize * sizeof(POOL_job)); - ctx->queueHead = 0; - ctx->queueTail = 0; - pthread_mutex_init(&ctx->queueMutex, NULL); - pthread_cond_init(&ctx->queuePushCond, NULL); - pthread_cond_init(&ctx->queuePopCond, NULL); - ctx->shutdown = 0; - /* Allocate space for the thread handles */ - ctx->threads = (pthread_t *)malloc(numThreads * sizeof(pthread_t)); - ctx->numThreads = 0; - /* Check for errors */ - if (!ctx->threads || !ctx->queue) - { - POOL_free(ctx); - return NULL; - } - /* Initialize the threads */ - { - size_t i; - for (i = 0; i < numThreads; ++i) - { - if (pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) - { - ctx->numThreads = i; - POOL_free(ctx); - return NULL; - } - } - ctx->numThreads = numThreads; - } - return ctx; -} - -/*! POOL_join() : - Shutdown the queue, wake any sleeping threads, and join all of the threads. -*/ -static void POOL_join(POOL_ctx *ctx) -{ - /* Shut down the queue */ - pthread_mutex_lock(&ctx->queueMutex); - ctx->shutdown = 1; - pthread_mutex_unlock(&ctx->queueMutex); - /* Wake up sleeping threads */ - pthread_cond_broadcast(&ctx->queuePushCond); - pthread_cond_broadcast(&ctx->queuePopCond); - /* Join all of the threads */ - { - size_t i; - for (i = 0; i < ctx->numThreads; ++i) - { - pthread_join(ctx->threads[i], NULL); - } - } -} - -void POOL_free(POOL_ctx *ctx) -{ - if (!ctx) - { - return; - } - POOL_join(ctx); - pthread_mutex_destroy(&ctx->queueMutex); - pthread_cond_destroy(&ctx->queuePushCond); - pthread_cond_destroy(&ctx->queuePopCond); - if (ctx->queue) - free(ctx->queue); - if (ctx->threads) - free(ctx->threads); - free(ctx); -} - -void POOL_add(void *ctxVoid, POOL_function function, void *opaque) -{ - POOL_ctx *ctx = (POOL_ctx *)ctxVoid; - if (!ctx) - { - return; - } - - pthread_mutex_lock(&ctx->queueMutex); - { - POOL_job const job = {function, opaque}; - /* Wait until there is space in the queue for the new job */ - size_t newTail = (ctx->queueTail + 1) % ctx->queueSize; - while (ctx->queueHead == newTail && !ctx->shutdown) - { - pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex); - newTail = (ctx->queueTail + 1) % ctx->queueSize; - } - /* The queue is still going => there is space */ - if (!ctx->shutdown) - { - ctx->queue[ctx->queueTail] = job; - ctx->queueTail = newTail; - } - } - pthread_mutex_unlock(&ctx->queueMutex); - pthread_cond_signal(&ctx->queuePopCond); -} - -#else /* ZSTD_MULTITHREAD not defined */ -/* No multi-threading support */ - -/* We don't need any data, but if it is empty malloc() might return NULL. */ -struct POOL_ctx_s -{ - int data; -}; - -POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) -{ - (void)numThreads; - (void)queueSize; - return (POOL_ctx *)malloc(sizeof(POOL_ctx)); -} - -void POOL_free(POOL_ctx *ctx) -{ - if (ctx) - free(ctx); -} - -void POOL_add(void *ctx, POOL_function function, void *opaque) -{ - (void)ctx; - function(opaque); -} - -#endif /* ZSTD_MULTITHREAD */ diff --git a/extra/zstd/pool.h b/extra/zstd/pool.h deleted file mode 100644 index 0c5e0da0..00000000 --- a/extra/zstd/pool.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2016-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -#ifndef POOL_H -#define POOL_H - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#include /* size_t */ - - typedef struct POOL_ctx_s POOL_ctx; - - /*! POOL_create() : - Create a thread pool with at most `numThreads` threads. - `numThreads` must be at least 1. - The maximum number of queued jobs before blocking is `queueSize`. - `queueSize` must be at least 1. - @return : The POOL_ctx pointer on success else NULL. - */ - POOL_ctx *POOL_create(size_t numThreads, size_t queueSize); - - /*! POOL_free() : - Free a thread pool returned by POOL_create(). - */ - void POOL_free(POOL_ctx *ctx); - - /*! POOL_function : - The function type that can be added to a thread pool. - */ - typedef void (*POOL_function)(void *); - /*! POOL_add_function : - The function type for a generic thread pool add function. - */ - typedef void (*POOL_add_function)(void *, POOL_function, void *); - - /*! POOL_add() : - Add the job `function(opaque)` to the thread pool. - Possibly blocks until there is room in the queue. - Note : The function may be executed asynchronously, so `opaque` must live until the function has been completed. - */ - void POOL_add(void *ctx, POOL_function function, void *opaque); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/extra/zstd/threading.c b/extra/zstd/threading.c deleted file mode 100644 index 368155fb..00000000 --- a/extra/zstd/threading.c +++ /dev/null @@ -1,80 +0,0 @@ - -/** - * Copyright (c) 2016 Tino Reichardt - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * You can contact the author at: - * - zstdmt source repository: https://github.com/mcmilk/zstdmt - */ - -/** - * This file will hold wrapper for systems, which do not support pthreads - */ - -/* When ZSTD_MULTITHREAD is not defined, this file would become an empty translation unit. - * Include some ISO C header code to prevent this and portably avoid related warnings. - * (Visual C++: C4206 / GCC: -Wpedantic / Clang: -Wempty-translation-unit) - */ -#include - -#if defined(ZSTD_MULTITHREAD) && defined(_WIN32) - -/** - * Windows minimalist Pthread Wrapper, based on : - * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html - */ - -/* === Dependencies === */ -#include -#include -#include "threading.h" - -/* === Implementation === */ - -static unsigned __stdcall worker(void *arg) -{ - pthread_t *const thread = (pthread_t *)arg; - thread->arg = thread->start_routine(thread->arg); - return 0; -} - -int pthread_create(pthread_t *thread, const void *unused, - void *(*start_routine)(void *), void *arg) -{ - (void)unused; - thread->arg = arg; - thread->start_routine = start_routine; - thread->handle = (HANDLE)_beginthreadex(NULL, 0, worker, thread, 0, NULL); - - if (!thread->handle) - return errno; - else - return 0; -} - -int _pthread_join(pthread_t *thread, void **value_ptr) -{ - DWORD result; - - if (!thread->handle) - return 0; - - result = WaitForSingleObject(thread->handle, INFINITE); - switch (result) - { - case WAIT_OBJECT_0: - if (value_ptr) - *value_ptr = thread->arg; - return 0; - case WAIT_ABANDONED: - return EINVAL; - default: - return GetLastError(); - } -} - -#endif /* ZSTD_MULTITHREAD */ diff --git a/extra/zstd/threading.h b/extra/zstd/threading.h deleted file mode 100644 index a2ba78ad..00000000 --- a/extra/zstd/threading.h +++ /dev/null @@ -1,105 +0,0 @@ - -/** - * Copyright (c) 2016 Tino Reichardt - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * You can contact the author at: - * - zstdmt source repository: https://github.com/mcmilk/zstdmt - */ - -#ifndef THREADING_H_938743 -#define THREADING_H_938743 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#if defined(ZSTD_MULTITHREAD) && defined(_WIN32) - -/** - * Windows minimalist Pthread Wrapper, based on : - * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html - */ -#ifdef WINVER -#undef WINVER -#endif -#define WINVER 0x0600 - -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif -#define _WIN32_WINNT 0x0600 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -/* mutex */ -#define pthread_mutex_t CRITICAL_SECTION -#define pthread_mutex_init(a, b) InitializeCriticalSection((a)) -#define pthread_mutex_destroy(a) DeleteCriticalSection((a)) -#define pthread_mutex_lock(a) EnterCriticalSection((a)) -#define pthread_mutex_unlock(a) LeaveCriticalSection((a)) - -/* condition variable */ -#define pthread_cond_t CONDITION_VARIABLE -#define pthread_cond_init(a, b) InitializeConditionVariable((a)) -#define pthread_cond_destroy(a) /* No delete */ -#define pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE) -#define pthread_cond_signal(a) WakeConditionVariable((a)) -#define pthread_cond_broadcast(a) WakeAllConditionVariable((a)) - - /* pthread_create() and pthread_join() */ - typedef struct - { - HANDLE handle; - void *(*start_routine)(void *); - void *arg; - } pthread_t; - - int pthread_create(pthread_t *thread, const void *unused, - void *(*start_routine)(void *), void *arg); - -#define pthread_join(a, b) _pthread_join(&(a), (b)) - int _pthread_join(pthread_t *thread, void **value_ptr); - - /** - * add here more wrappers as required - */ - -#elif defined(ZSTD_MULTITHREAD) /* posix assumed ; need a better detection method */ -/* === POSIX Systems === */ -#include - -#else /* ZSTD_MULTITHREAD not defined */ -/* No multithreading support */ - -#define pthread_mutex_t int /* #define rather than typedef, as sometimes pthread support is implicit, resulting in duplicated symbols */ -#define pthread_mutex_init(a, b) -#define pthread_mutex_destroy(a) -#define pthread_mutex_lock(a) -#define pthread_mutex_unlock(a) - -#define pthread_cond_t int -#define pthread_cond_init(a, b) -#define pthread_cond_destroy(a) -#define pthread_cond_wait(a, b) -#define pthread_cond_signal(a) -#define pthread_cond_broadcast(a) - -/* do not use pthread_t */ - -#endif /* ZSTD_MULTITHREAD */ - -#if defined(__cplusplus) -} -#endif - -#endif /* THREADING_H_938743 */ diff --git a/extra/zstd/xxhash.h b/extra/zstd/xxhash.h deleted file mode 100644 index 8277e675..00000000 --- a/extra/zstd/xxhash.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -A 64-bits version, named XXH64, is available since r35. -It offers much better speed, but for 64-bits applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 - -/* **************************** - * Definitions - ******************************/ -#include /* size_t */ - typedef enum - { - XXH_OK = 0, - XXH_ERROR - } XXH_errorcode; - -/* **************************** - * API modifier - ******************************/ -/** XXH_PRIVATE_API - * This is useful if you want to include xxhash functions in `static` mode - * in order to inline them, and remove their symbol from the public list. - * Methodology : - * #define XXH_PRIVATE_API - * #include "xxhash.h" - * `xxhash.c` is automatically included. - * It's not useful to compile and link it as a separate module anymore. - */ -#ifdef XXH_PRIVATE_API -#ifndef XXH_STATIC_LINKING_ONLY -#define XXH_STATIC_LINKING_ONLY -#endif -#if defined(__GNUC__) -#define XXH_PUBLIC_API static __inline __attribute__((unused)) -#elif defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -#define XXH_PUBLIC_API static inline -#elif defined(_MSC_VER) -#define XXH_PUBLIC_API static __inline -#else -#define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */ -#endif -#else -#define XXH_PUBLIC_API /* do nothing */ -#endif /* XXH_PRIVATE_API */ - -/*!XXH_NAMESPACE, aka Namespace Emulation : - -If you want to include _and expose_ xxHash functions from within your own library, -but also want to avoid symbol collisions with another library which also includes xxHash, - -you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library -with the value of XXH_NAMESPACE (so avoid to keep it NULL and avoid numeric values). - -Note that no change is required within the calling program as long as it includes `xxhash.h` : -regular symbol name will be automatically translated by this header. -*/ -#ifdef XXH_NAMESPACE -#define XXH_CAT(A, B) A##B -#define XXH_NAME2(A, B) XXH_CAT(A, B) -#define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) -#define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) -#define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) -#define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) -#define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) -#define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) -#define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) -#define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) -#define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) -#define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) -#define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) -#define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) -#define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) -#define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) -#define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) -#define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) -#define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) -#define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) -#define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) -#endif - -/* ************************************* - * Version - ***************************************/ -#define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 6 -#define XXH_VERSION_RELEASE 2 -#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR * 100 * 100 + XXH_VERSION_MINOR * 100 + XXH_VERSION_RELEASE) - XXH_PUBLIC_API unsigned XXH_versionNumber(void); - - /* **************************** - * Simple Hash Functions - ******************************/ - typedef unsigned int XXH32_hash_t; - typedef unsigned long long XXH64_hash_t; - - XXH_PUBLIC_API XXH32_hash_t XXH32(const void *input, size_t length, unsigned int seed); - XXH_PUBLIC_API XXH64_hash_t XXH64(const void *input, size_t length, unsigned long long seed); - - /*! - XXH32() : - Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". - The memory between input & input+length must be valid (allocated and read-accessible). - "seed" can be used to alter the result predictably. - Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s - XXH64() : - Calculate the 64-bits hash of sequence of length "len" stored at memory address "input". - "seed" can be used to alter the result predictably. - This function runs 2x faster on 64-bits systems, but slower on 32-bits systems (see benchmark). - */ - - /* **************************** - * Streaming Hash Functions - ******************************/ - typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ - typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ - - /*! State allocation, compatible with dynamic libraries */ - - XXH_PUBLIC_API XXH32_state_t *XXH32_createState(void); - XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t *statePtr); - - XXH_PUBLIC_API XXH64_state_t *XXH64_createState(void); - XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t *statePtr); - - /* hash streaming */ - - XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, unsigned int seed); - XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *statePtr, const void *input, size_t length); - XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t *statePtr); - - XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t *statePtr, unsigned long long seed); - XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH64_state_t *statePtr, const void *input, size_t length); - XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t *statePtr); - -/* -These functions generate the xxHash of an input provided in multiple segments. -Note that, for small input, they are slower than single-call functions, due to state management. -For small input, prefer `XXH32()` and `XXH64()` . - -XXH state must first be allocated, using XXH*_createState() . - -Start a new hash by initializing state with a seed, using XXH*_reset(). - -Then, feed the hash state by calling XXH*_update() as many times as necessary. -Obviously, input must be allocated and read accessible. -The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. - -Finally, a hash value can be produced anytime, by using XXH*_digest(). -This function returns the nn-bits hash as an int or long long. - -It's still possible to continue inserting input into the hash state after a digest, -and generate some new hashes later on, by calling again XXH*_digest(). - -When done, free XXH state space if it was allocated dynamically. -*/ - -/* ************************** - * Utils - ****************************/ -#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* ! C99 */ -#define restrict /* disable restrict */ -#endif - - XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t *restrict dst_state, const XXH32_state_t *restrict src_state); - XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t *restrict dst_state, const XXH64_state_t *restrict src_state); - - /* ************************** - * Canonical representation - ****************************/ - /* Default result type for XXH functions are primitive unsigned 32 and 64 bits. - * The canonical representation uses human-readable write convention, aka big-endian (large digits first). - * These functions allow transformation of hash result into and from its canonical format. - * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. - */ - typedef struct - { - unsigned char digest[4]; - } XXH32_canonical_t; - typedef struct - { - unsigned char digest[8]; - } XXH64_canonical_t; - - XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t *dst, XXH32_hash_t hash); - XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t *dst, XXH64_hash_t hash); - - XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t *src); - XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t *src); - -#endif /* XXHASH_H_5627135585666179 */ - -/* ================================================================================================ - This section contains definitions which are not guaranteed to remain stable. - They may change in future versions, becoming incompatible with a different version of the library. - They shall only be used with static linking. - Never use these definitions in association with dynamic linking ! -=================================================================================================== */ -#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXH_STATIC_H_3543687687345) -#define XXH_STATIC_H_3543687687345 - - /* These definitions are only meant to allow allocation of XXH state - statically, on stack, or in a struct for example. - Do not use members directly. */ - - struct XXH32_state_s - { - unsigned total_len_32; - unsigned large_len; - unsigned v1; - unsigned v2; - unsigned v3; - unsigned v4; - unsigned mem32[4]; /* buffer defined as U32 for alignment */ - unsigned memsize; - unsigned reserved; /* never read nor write, will be removed in a future version */ - }; /* typedef'd to XXH32_state_t */ - - struct XXH64_state_s - { - unsigned long long total_len; - unsigned long long v1; - unsigned long long v2; - unsigned long long v3; - unsigned long long v4; - unsigned long long mem64[4]; /* buffer defined as U64 for alignment */ - unsigned memsize; - unsigned reserved[2]; /* never read nor write, will be removed in a future version */ - }; /* typedef'd to XXH64_state_t */ - -#ifdef XXH_PRIVATE_API -#include "xxhash.c" /* include xxhash functions as `static`, for inlining */ -#endif - -#endif /* XXH_STATIC_LINKING_ONLY && XXH_STATIC_H_3543687687345 */ - -#if defined(__cplusplus) -} -#endif diff --git a/extra/zstd/zbuff.h b/extra/zstd/zbuff.h deleted file mode 100644 index 28579865..00000000 --- a/extra/zstd/zbuff.h +++ /dev/null @@ -1,224 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* *************************************************************** - * NOTES/WARNINGS - ******************************************************************/ -/* The streaming API defined here is deprecated. - * Consider migrating towards ZSTD_compressStream() API in `zstd.h` - * See 'lib/README.md'. - *****************************************************************/ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifndef ZSTD_BUFFERED_H_23987 -#define ZSTD_BUFFERED_H_23987 - -/* ************************************* - * Dependencies - ***************************************/ -#include /* size_t */ -#include "zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */ - -/* *************************************************************** - * Compiler specifics - *****************************************************************/ -/* Deprecation warnings */ -/* Should these warnings be a problem, - it is generally possible to disable them, - typically with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual. - Otherwise, it's also possible to define ZBUFF_DISABLE_DEPRECATE_WARNINGS */ -#ifdef ZBUFF_DISABLE_DEPRECATE_WARNINGS -#define ZBUFF_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */ -#else -#if defined(__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ -#define ZBUFF_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API -#elif (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) -#define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message))) -#elif defined(__GNUC__) && (__GNUC__ >= 3) -#define ZBUFF_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated)) -#elif defined(_MSC_VER) -#define ZBUFF_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message)) -#else -#pragma message("WARNING: You need to implement ZBUFF_DEPRECATED for this compiler") -#define ZBUFF_DEPRECATED(message) ZSTDLIB_API -#endif -#endif /* ZBUFF_DISABLE_DEPRECATE_WARNINGS */ - - /* ************************************* - * Streaming functions - ***************************************/ - /* This is the easier "buffered" streaming API, - * using an internal buffer to lift all restrictions on user-provided buffers - * which can be any size, any place, for both input and output. - * ZBUFF and ZSTD are 100% interoperable, - * frames created by one can be decoded by the other one */ - - typedef ZSTD_CStream ZBUFF_CCtx; - ZBUFF_DEPRECATED("use ZSTD_createCStream") - ZBUFF_CCtx *ZBUFF_createCCtx(void); - ZBUFF_DEPRECATED("use ZSTD_freeCStream") - size_t ZBUFF_freeCCtx(ZBUFF_CCtx *cctx); - - ZBUFF_DEPRECATED("use ZSTD_initCStream") - size_t ZBUFF_compressInit(ZBUFF_CCtx *cctx, int compressionLevel); - ZBUFF_DEPRECATED("use ZSTD_initCStream_usingDict") - size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx *cctx, const void *dict, size_t dictSize, int compressionLevel); - - ZBUFF_DEPRECATED("use ZSTD_compressStream") - size_t ZBUFF_compressContinue(ZBUFF_CCtx *cctx, void *dst, size_t *dstCapacityPtr, const void *src, size_t *srcSizePtr); - ZBUFF_DEPRECATED("use ZSTD_flushStream") - size_t ZBUFF_compressFlush(ZBUFF_CCtx *cctx, void *dst, size_t *dstCapacityPtr); - ZBUFF_DEPRECATED("use ZSTD_endStream") - size_t ZBUFF_compressEnd(ZBUFF_CCtx *cctx, void *dst, size_t *dstCapacityPtr); - - /*-************************************************* - * Streaming compression - howto - * - * A ZBUFF_CCtx object is required to track streaming operation. - * Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources. - * ZBUFF_CCtx objects can be reused multiple times. - * - * Start by initializing ZBUF_CCtx. - * Use ZBUFF_compressInit() to start a new compression operation. - * Use ZBUFF_compressInitDictionary() for a compression which requires a dictionary. - * - * Use ZBUFF_compressContinue() repetitively to consume input stream. - * *srcSizePtr and *dstCapacityPtr can be any size. - * The function will report how many bytes were read or written within *srcSizePtr and *dstCapacityPtr. - * Note that it may not consume the entire input, in which case it's up to the caller to present again remaining data. - * The content of `dst` will be overwritten (up to *dstCapacityPtr) at each call, so save its content if it matters or change @dst . - * @return : a hint to preferred nb of bytes to use as input for next function call (it's just a hint, to improve latency) - * or an error code, which can be tested using ZBUFF_isError(). - * - * At any moment, it's possible to flush whatever data remains within buffer, using ZBUFF_compressFlush(). - * The nb of bytes written into `dst` will be reported into *dstCapacityPtr. - * Note that the function cannot output more than *dstCapacityPtr, - * therefore, some content might still be left into internal buffer if *dstCapacityPtr is too small. - * @return : nb of bytes still present into internal buffer (0 if it's empty) - * or an error code, which can be tested using ZBUFF_isError(). - * - * ZBUFF_compressEnd() instructs to finish a frame. - * It will perform a flush and write frame epilogue. - * The epilogue is required for decoders to consider a frame completed. - * Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small. - * In which case, call again ZBUFF_compressFlush() to complete the flush. - * @return : nb of bytes still present into internal buffer (0 if it's empty) - * or an error code, which can be tested using ZBUFF_isError(). - * - * Hint : _recommended buffer_ sizes (not compulsory) : ZBUFF_recommendedCInSize() / ZBUFF_recommendedCOutSize() - * input : ZBUFF_recommendedCInSize==128 KB block size is the internal unit, use this value to reduce intermediate stages (better latency) - * output : ZBUFF_recommendedCOutSize==ZSTD_compressBound(128 KB) + 3 + 3 : ensures it's always possible to write/flush/end a full block. Skip some buffering. - * By using both, it ensures that input will be entirely consumed, and output will always contain the result, reducing intermediate buffering. - * **************************************************/ - - typedef ZSTD_DStream ZBUFF_DCtx; - ZBUFF_DEPRECATED("use ZSTD_createDStream") - ZBUFF_DCtx *ZBUFF_createDCtx(void); - ZBUFF_DEPRECATED("use ZSTD_freeDStream") - size_t ZBUFF_freeDCtx(ZBUFF_DCtx *dctx); - - ZBUFF_DEPRECATED("use ZSTD_initDStream") - size_t ZBUFF_decompressInit(ZBUFF_DCtx *dctx); - ZBUFF_DEPRECATED("use ZSTD_initDStream_usingDict") - size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx *dctx, const void *dict, size_t dictSize); - - ZBUFF_DEPRECATED("use ZSTD_decompressStream") - size_t ZBUFF_decompressContinue(ZBUFF_DCtx *dctx, - void *dst, size_t *dstCapacityPtr, - const void *src, size_t *srcSizePtr); - - /*-*************************************************************************** - * Streaming decompression howto - * - * A ZBUFF_DCtx object is required to track streaming operations. - * Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources. - * Use ZBUFF_decompressInit() to start a new decompression operation, - * or ZBUFF_decompressInitDictionary() if decompression requires a dictionary. - * Note that ZBUFF_DCtx objects can be re-init multiple times. - * - * Use ZBUFF_decompressContinue() repetitively to consume your input. - * *srcSizePtr and *dstCapacityPtr can be any size. - * The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. - * Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again. - * The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`. - * @return : 0 when a frame is completely decoded and fully flushed, - * 1 when there is still some data left within internal buffer to flush, - * >1 when more data is expected, with value being a suggested next input size (it's just a hint, which helps latency), - * or an error code, which can be tested using ZBUFF_isError(). - * - * Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize() and ZBUFF_recommendedDOutSize() - * output : ZBUFF_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded. - * input : ZBUFF_recommendedDInSize == 128KB + 3; - * just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 . - * *******************************************************************************/ - - /* ************************************* - * Tool functions - ***************************************/ - ZBUFF_DEPRECATED("use ZSTD_isError") - unsigned ZBUFF_isError(size_t errorCode); - ZBUFF_DEPRECATED("use ZSTD_getErrorName") - const char *ZBUFF_getErrorName(size_t errorCode); - - /** Functions below provide recommended buffer sizes for Compression or Decompression operations. - * These sizes are just hints, they tend to offer better latency */ - ZBUFF_DEPRECATED("use ZSTD_CStreamInSize") - size_t ZBUFF_recommendedCInSize(void); - ZBUFF_DEPRECATED("use ZSTD_CStreamOutSize") - size_t ZBUFF_recommendedCOutSize(void); - ZBUFF_DEPRECATED("use ZSTD_DStreamInSize") - size_t ZBUFF_recommendedDInSize(void); - ZBUFF_DEPRECATED("use ZSTD_DStreamOutSize") - size_t ZBUFF_recommendedDOutSize(void); - -#endif /* ZSTD_BUFFERED_H_23987 */ - -#ifdef ZBUFF_STATIC_LINKING_ONLY -#ifndef ZBUFF_STATIC_H_30298098432 -#define ZBUFF_STATIC_H_30298098432 - -/* ==================================================================================== - * The definitions in this section are considered experimental. - * They should never be used in association with a dynamic library, as they may change in the future. - * They are provided for advanced usages. - * Use them only in association with static linking. - * ==================================================================================== */ - -/*--- Dependency ---*/ -#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters, ZSTD_customMem */ -#include "zstd.h" - - /*--- Custom memory allocator ---*/ - /*! ZBUFF_createCCtx_advanced() : - * Create a ZBUFF compression context using external alloc and free functions */ - ZBUFF_DEPRECATED("use ZSTD_createCStream_advanced") - ZBUFF_CCtx *ZBUFF_createCCtx_advanced(ZSTD_customMem customMem); - - /*! ZBUFF_createDCtx_advanced() : - * Create a ZBUFF decompression context using external alloc and free functions */ - ZBUFF_DEPRECATED("use ZSTD_createDStream_advanced") - ZBUFF_DCtx *ZBUFF_createDCtx_advanced(ZSTD_customMem customMem); - - /*--- Advanced Streaming Initialization ---*/ - ZBUFF_DEPRECATED("use ZSTD_initDStream_usingDict") - size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx *zbc, - const void *dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize); - -#endif /* ZBUFF_STATIC_H_30298098432 */ -#endif /* ZBUFF_STATIC_LINKING_ONLY */ - -#if defined(__cplusplus) -} -#endif diff --git a/extra/zstd/zbuff_common.c b/extra/zstd/zbuff_common.c deleted file mode 100644 index 828c2fbe..00000000 --- a/extra/zstd/zbuff_common.c +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/*-************************************* - * Dependencies - ***************************************/ -#include "error_private.h" -#include "zbuff.h" - -/*-**************************************** - * ZBUFF Error Management (deprecated) - ******************************************/ - -/*! ZBUFF_isError() : - * tells if a return value is an error code */ -unsigned ZBUFF_isError(size_t errorCode) { return ERR_isError(errorCode); } -/*! ZBUFF_getErrorName() : - * provides error code string from function result (useful for debugging) */ -const char *ZBUFF_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } diff --git a/extra/zstd/zbuff_compress.c b/extra/zstd/zbuff_compress.c deleted file mode 100644 index 95803b87..00000000 --- a/extra/zstd/zbuff_compress.c +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* ************************************* - * Dependencies - ***************************************/ -#define ZBUFF_STATIC_LINKING_ONLY -#include "zbuff.h" - -/*-*********************************************************** - * Streaming compression - * - * A ZBUFF_CCtx object is required to track streaming operation. - * Use ZBUFF_createCCtx() and ZBUFF_freeCCtx() to create/release resources. - * Use ZBUFF_compressInit() to start a new compression operation. - * ZBUFF_CCtx objects can be reused multiple times. - * - * Use ZBUFF_compressContinue() repetitively to consume your input. - * *srcSizePtr and *dstCapacityPtr can be any size. - * The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr. - * Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input. - * The content of dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change dst . - * @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency) - * or an error code, which can be tested using ZBUFF_isError(). - * - * ZBUFF_compressFlush() can be used to instruct ZBUFF to compress and output whatever remains within its buffer. - * Note that it will not output more than *dstCapacityPtr. - * Therefore, some content might still be left into its internal buffer if dst buffer is too small. - * @return : nb of bytes still present into internal buffer (0 if it's empty) - * or an error code, which can be tested using ZBUFF_isError(). - * - * ZBUFF_compressEnd() instructs to finish a frame. - * It will perform a flush and write frame epilogue. - * Similar to ZBUFF_compressFlush(), it may not be able to output the entire internal buffer content if *dstCapacityPtr is too small. - * @return : nb of bytes still present into internal buffer (0 if it's empty) - * or an error code, which can be tested using ZBUFF_isError(). - * - * Hint : recommended buffer sizes (not compulsory) - * input : ZSTD_BLOCKSIZE_MAX (128 KB), internal unit size, it improves latency to use this value. - * output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed. - * ***********************************************************/ - -ZBUFF_CCtx *ZBUFF_createCCtx(void) -{ - return ZSTD_createCStream(); -} - -ZBUFF_CCtx *ZBUFF_createCCtx_advanced(ZSTD_customMem customMem) -{ - return ZSTD_createCStream_advanced(customMem); -} - -size_t ZBUFF_freeCCtx(ZBUFF_CCtx *zbc) -{ - return ZSTD_freeCStream(zbc); -} - -/* ====== Initialization ====== */ - -size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx *zbc, - const void *dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize) -{ - return ZSTD_initCStream_advanced(zbc, dict, dictSize, params, pledgedSrcSize); -} - -size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx *zbc, const void *dict, size_t dictSize, int compressionLevel) -{ - return ZSTD_initCStream_usingDict(zbc, dict, dictSize, compressionLevel); -} - -size_t ZBUFF_compressInit(ZBUFF_CCtx *zbc, int compressionLevel) -{ - return ZSTD_initCStream(zbc, compressionLevel); -} - -/* ====== Compression ====== */ - -size_t ZBUFF_compressContinue(ZBUFF_CCtx *zbc, - void *dst, size_t *dstCapacityPtr, - const void *src, size_t *srcSizePtr) -{ - size_t result; - ZSTD_outBuffer outBuff; - ZSTD_inBuffer inBuff; - outBuff.dst = dst; - outBuff.pos = 0; - outBuff.size = *dstCapacityPtr; - inBuff.src = src; - inBuff.pos = 0; - inBuff.size = *srcSizePtr; - result = ZSTD_compressStream(zbc, &outBuff, &inBuff); - *dstCapacityPtr = outBuff.pos; - *srcSizePtr = inBuff.pos; - return result; -} - -/* ====== Finalize ====== */ - -size_t ZBUFF_compressFlush(ZBUFF_CCtx *zbc, void *dst, size_t *dstCapacityPtr) -{ - size_t result; - ZSTD_outBuffer outBuff; - outBuff.dst = dst; - outBuff.pos = 0; - outBuff.size = *dstCapacityPtr; - result = ZSTD_flushStream(zbc, &outBuff); - *dstCapacityPtr = outBuff.pos; - return result; -} - -size_t ZBUFF_compressEnd(ZBUFF_CCtx *zbc, void *dst, size_t *dstCapacityPtr) -{ - size_t result; - ZSTD_outBuffer outBuff; - outBuff.dst = dst; - outBuff.pos = 0; - outBuff.size = *dstCapacityPtr; - result = ZSTD_endStream(zbc, &outBuff); - *dstCapacityPtr = outBuff.pos; - return result; -} - -/* ************************************* - * Tool functions - ***************************************/ -size_t ZBUFF_recommendedCInSize(void) { return ZSTD_CStreamInSize(); } -size_t ZBUFF_recommendedCOutSize(void) { return ZSTD_CStreamOutSize(); } diff --git a/extra/zstd/zbuff_decompress.c b/extra/zstd/zbuff_decompress.c deleted file mode 100644 index 4b606c72..00000000 --- a/extra/zstd/zbuff_decompress.c +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* ************************************* - * Dependencies - ***************************************/ -#define ZBUFF_STATIC_LINKING_ONLY -#include "zbuff.h" - -ZBUFF_DCtx *ZBUFF_createDCtx(void) -{ - return ZSTD_createDStream(); -} - -ZBUFF_DCtx *ZBUFF_createDCtx_advanced(ZSTD_customMem customMem) -{ - return ZSTD_createDStream_advanced(customMem); -} - -size_t ZBUFF_freeDCtx(ZBUFF_DCtx *zbd) -{ - return ZSTD_freeDStream(zbd); -} - -/* *** Initialization *** */ - -size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx *zbd, const void *dict, size_t dictSize) -{ - return ZSTD_initDStream_usingDict(zbd, dict, dictSize); -} - -size_t ZBUFF_decompressInit(ZBUFF_DCtx *zbd) -{ - return ZSTD_initDStream(zbd); -} - -/* *** Decompression *** */ - -size_t ZBUFF_decompressContinue(ZBUFF_DCtx *zbd, - void *dst, size_t *dstCapacityPtr, - const void *src, size_t *srcSizePtr) -{ - ZSTD_outBuffer outBuff; - ZSTD_inBuffer inBuff; - size_t result; - outBuff.dst = dst; - outBuff.pos = 0; - outBuff.size = *dstCapacityPtr; - inBuff.src = src; - inBuff.pos = 0; - inBuff.size = *srcSizePtr; - result = ZSTD_decompressStream(zbd, &outBuff, &inBuff); - *dstCapacityPtr = outBuff.pos; - *srcSizePtr = inBuff.pos; - return result; -} - -/* ************************************* - * Tool functions - ***************************************/ -size_t ZBUFF_recommendedDInSize(void) { return ZSTD_DStreamInSize(); } -size_t ZBUFF_recommendedDOutSize(void) { return ZSTD_DStreamOutSize(); } diff --git a/extra/zstd/zdict.c b/extra/zstd/zdict.c deleted file mode 100644 index 5b12b415..00000000 --- a/extra/zstd/zdict.c +++ /dev/null @@ -1,1270 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/*-************************************** - * Tuning parameters - ****************************************/ -#define ZDICT_MAX_SAMPLES_SIZE (2000U << 20) -#define ZDICT_MIN_SAMPLES_SIZE 512 - -/*-************************************** - * Compiler Options - ****************************************/ -/* Unix Large Files support (>4GB) */ -#define _FILE_OFFSET_BITS 64 -#if (defined(__sun__) && (!defined(__LP64__))) /* Sun Solaris 32-bits requires specific definitions */ -#define _LARGEFILE_SOURCE -#elif !defined(__LP64__) /* No point defining Large file for 64 bit */ -#define _LARGEFILE64_SOURCE -#endif - -/*-************************************* - * Dependencies - ***************************************/ -#include /* malloc, free */ -#include /* memset */ -#include /* fprintf, fopen, ftello64 */ -#include /* clock */ - -#include "mem.h" /* read */ -#include "fse.h" /* FSE_normalizeCount, FSE_writeNCount */ -#define HUF_STATIC_LINKING_ONLY -#include "huf.h" /* HUF_buildCTable, HUF_writeCTable */ -#include "zstd_internal.h" /* includes zstd.h */ -#include "xxhash.h" /* XXH64 */ -#include "divsufsort.h" -#ifndef ZDICT_STATIC_LINKING_ONLY -#define ZDICT_STATIC_LINKING_ONLY -#endif -#include "zdict.h" - -/*-************************************* - * Constants - ***************************************/ -#define KB *(1 << 10) -#define MB *(1 << 20) -#define GB *(1U << 30) - -#define DICTLISTSIZE_DEFAULT 10000 - -#define NOISELENGTH 32 - -#define MINRATIO 4 -static const int g_compressionLevel_default = 6; -static const U32 g_selectivity_default = 9; -static const size_t g_provision_entropySize = 200; -static const size_t g_min_fast_dictContent = 192; - -/*-************************************* - * Console display - ***************************************/ -#define DISPLAY(...) \ - { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } -#define DISPLAYLEVEL(l, ...) \ - if (notificationLevel >= l) \ - { \ - DISPLAY(__VA_ARGS__); \ - } /* 0 : no display; 1: errors; 2: default; 3: details; 4: debug */ - -static clock_t ZDICT_clockSpan(clock_t nPrevious) { return clock() - nPrevious; } - -static void ZDICT_printHex(const void *ptr, size_t length) -{ - const BYTE *const b = (const BYTE *)ptr; - size_t u; - for (u = 0; u < length; u++) - { - BYTE c = b[u]; - if (c < 32 || c > 126) - c = '.'; /* non-printable char */ - DISPLAY("%c", c); - } -} - -/*-******************************************************** - * Helper functions - **********************************************************/ -unsigned ZDICT_isError(size_t errorCode) { return ERR_isError(errorCode); } - -const char *ZDICT_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); } - -unsigned ZDICT_getDictID(const void *dictBuffer, size_t dictSize) -{ - if (dictSize < 8) - return 0; - if (MEM_readLE32(dictBuffer) != ZSTD_DICT_MAGIC) - return 0; - return MEM_readLE32((const char *)dictBuffer + 4); -} - -/*-******************************************************** - * Dictionary training functions - **********************************************************/ -static unsigned ZDICT_NbCommonBytes(register size_t val) -{ - if (MEM_isLittleEndian()) - { - if (MEM_64bits()) - { -#if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - _BitScanForward64(&r, (U64)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_ctzll((U64)val) >> 3); -#else - static const int DeBruijnBytePos[64] = {0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7}; - return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; -#endif - } - else - { /* 32 bits */ -#if defined(_MSC_VER) - unsigned long r = 0; - _BitScanForward(&r, (U32)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_ctz((U32)val) >> 3); -#else - static const int DeBruijnBytePos[32] = {0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1}; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; -#endif - } - } - else - { /* Big Endian CPU */ - if (MEM_64bits()) - { -#if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - _BitScanReverse64(&r, val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_clzll(val) >> 3); -#else - unsigned r; - const unsigned n32 = sizeof(size_t) * 4; /* calculate this way due to compiler complaining in 32-bits mode */ - if (!(val >> n32)) - { - r = 4; - } - else - { - r = 0; - val >>= n32; - } - if (!(val >> 16)) - { - r += 2; - val >>= 8; - } - else - { - val >>= 24; - } - r += (!val); - return r; -#endif - } - else - { /* 32 bits */ -#if defined(_MSC_VER) - unsigned long r = 0; - _BitScanReverse(&r, (unsigned long)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_clz((U32)val) >> 3); -#else - unsigned r; - if (!(val >> 16)) - { - r = 2; - val >>= 8; - } - else - { - r = 0; - val >>= 24; - } - r += (!val); - return r; -#endif - } - } -} - -/*! ZDICT_count() : - Count the nb of common bytes between 2 pointers. - Note : this function presumes end of buffer followed by noisy guard band. -*/ -static size_t ZDICT_count(const void *pIn, const void *pMatch) -{ - const char *const pStart = (const char *)pIn; - for (;;) - { - size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn); - if (!diff) - { - pIn = (const char *)pIn + sizeof(size_t); - pMatch = (const char *)pMatch + sizeof(size_t); - continue; - } - pIn = (const char *)pIn + ZDICT_NbCommonBytes(diff); - return (size_t)((const char *)pIn - pStart); - } -} - -typedef struct -{ - U32 pos; - U32 length; - U32 savings; -} dictItem; - -static void ZDICT_initDictItem(dictItem *d) -{ - d->pos = 1; - d->length = 0; - d->savings = (U32)(-1); -} - -#define LLIMIT 64 /* heuristic determined experimentally */ -#define MINMATCHLENGTH 7 /* heuristic determined experimentally */ -static dictItem ZDICT_analyzePos( - BYTE *doneMarks, - const int *suffix, U32 start, - const void *buffer, U32 minRatio, U32 notificationLevel) -{ - U32 lengthList[LLIMIT] = {0}; - U32 cumulLength[LLIMIT] = {0}; - U32 savings[LLIMIT] = {0}; - const BYTE *b = (const BYTE *)buffer; - size_t length; - size_t maxLength = LLIMIT; - size_t pos = suffix[start]; - U32 end = start; - dictItem solution; - - /* init */ - memset(&solution, 0, sizeof(solution)); - doneMarks[pos] = 1; - - /* trivial repetition cases */ - if ((MEM_read16(b + pos + 0) == MEM_read16(b + pos + 2)) || (MEM_read16(b + pos + 1) == MEM_read16(b + pos + 3)) || (MEM_read16(b + pos + 2) == MEM_read16(b + pos + 4))) - { - /* skip and mark segment */ - U16 u16 = MEM_read16(b + pos + 4); - U32 u, e = 6; - while (MEM_read16(b + pos + e) == u16) - e += 2; - if (b[pos + e] == b[pos + e - 1]) - e++; - for (u = 1; u < e; u++) - doneMarks[pos + u] = 1; - return solution; - } - - /* look forward */ - do - { - end++; - length = ZDICT_count(b + pos, b + suffix[end]); - } while (length >= MINMATCHLENGTH); - - /* look backward */ - do - { - length = ZDICT_count(b + pos, b + *(suffix + start - 1)); - if (length >= MINMATCHLENGTH) - start--; - } while (length >= MINMATCHLENGTH); - - /* exit if not found a minimum nb of repetitions */ - if (end - start < minRatio) - { - U32 idx; - for (idx = start; idx < end; idx++) - doneMarks[suffix[idx]] = 1; - return solution; - } - - { - int i; - U32 searchLength; - U32 refinedStart = start; - U32 refinedEnd = end; - - DISPLAYLEVEL(4, "\n"); - DISPLAYLEVEL(4, "found %3u matches of length >= %i at pos %7u ", (U32)(end - start), MINMATCHLENGTH, (U32)pos); - DISPLAYLEVEL(4, "\n"); - - for (searchLength = MINMATCHLENGTH;; searchLength++) - { - BYTE currentChar = 0; - U32 currentCount = 0; - U32 currentID = refinedStart; - U32 id; - U32 selectedCount = 0; - U32 selectedID = currentID; - for (id = refinedStart; id < refinedEnd; id++) - { - if (b[suffix[id] + searchLength] != currentChar) - { - if (currentCount > selectedCount) - { - selectedCount = currentCount; - selectedID = currentID; - } - currentID = id; - currentChar = b[suffix[id] + searchLength]; - currentCount = 0; - } - currentCount++; - } - if (currentCount > selectedCount) - { /* for last */ - selectedCount = currentCount; - selectedID = currentID; - } - - if (selectedCount < minRatio) - break; - refinedStart = selectedID; - refinedEnd = refinedStart + selectedCount; - } - - /* evaluate gain based on new ref */ - start = refinedStart; - pos = suffix[refinedStart]; - end = start; - memset(lengthList, 0, sizeof(lengthList)); - - /* look forward */ - do - { - end++; - length = ZDICT_count(b + pos, b + suffix[end]); - if (length >= LLIMIT) - length = LLIMIT - 1; - lengthList[length]++; - } while (length >= MINMATCHLENGTH); - - /* look backward */ - length = MINMATCHLENGTH; - while ((length >= MINMATCHLENGTH) & (start > 0)) - { - length = ZDICT_count(b + pos, b + suffix[start - 1]); - if (length >= LLIMIT) - length = LLIMIT - 1; - lengthList[length]++; - if (length >= MINMATCHLENGTH) - start--; - } - - /* largest useful length */ - memset(cumulLength, 0, sizeof(cumulLength)); - cumulLength[maxLength - 1] = lengthList[maxLength - 1]; - for (i = (int)(maxLength - 2); i >= 0; i--) - cumulLength[i] = cumulLength[i + 1] + lengthList[i]; - - for (i = LLIMIT - 1; i >= MINMATCHLENGTH; i--) - if (cumulLength[i] >= minRatio) - break; - maxLength = i; - - /* reduce maxLength in case of final into repetitive data */ - { - U32 l = (U32)maxLength; - BYTE const c = b[pos + maxLength - 1]; - while (b[pos + l - 2] == c) - l--; - maxLength = l; - } - if (maxLength < MINMATCHLENGTH) - return solution; /* skip : no long-enough solution */ - - /* calculate savings */ - savings[5] = 0; - for (i = MINMATCHLENGTH; i <= (int)maxLength; i++) - savings[i] = savings[i - 1] + (lengthList[i] * (i - 3)); - - DISPLAYLEVEL(4, "Selected ref at position %u, of length %u : saves %u (ratio: %.2f) \n", - (U32)pos, (U32)maxLength, savings[maxLength], (double)savings[maxLength] / maxLength); - - solution.pos = (U32)pos; - solution.length = (U32)maxLength; - solution.savings = savings[maxLength]; - - /* mark positions done */ - { - U32 id; - for (id = start; id < end; id++) - { - U32 p, pEnd; - U32 const testedPos = suffix[id]; - if (testedPos == pos) - length = solution.length; - else - { - length = ZDICT_count(b + pos, b + testedPos); - if (length > solution.length) - length = solution.length; - } - pEnd = (U32)(testedPos + length); - for (p = testedPos; p < pEnd; p++) - doneMarks[p] = 1; - } - } - } - - return solution; -} - -/*! ZDICT_checkMerge - check if dictItem can be merged, do it if possible - @return : id of destination elt, 0 if not merged -*/ -static U32 ZDICT_checkMerge(dictItem *table, dictItem elt, U32 eltNbToSkip) -{ - const U32 tableSize = table->pos; - const U32 eltEnd = elt.pos + elt.length; - - /* tail overlap */ - U32 u; - for (u = 1; u < tableSize; u++) - { - if (u == eltNbToSkip) - continue; - if ((table[u].pos > elt.pos) && (table[u].pos <= eltEnd)) - { /* overlap, existing > new */ - /* append */ - U32 addedLength = table[u].pos - elt.pos; - table[u].length += addedLength; - table[u].pos = elt.pos; - table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */ - table[u].savings += elt.length / 8; /* rough approx bonus */ - elt = table[u]; - /* sort : improve rank */ - while ((u > 1) && (table[u - 1].savings < elt.savings)) - table[u] = table[u - 1], u--; - table[u] = elt; - return u; - } - } - - /* front overlap */ - for (u = 1; u < tableSize; u++) - { - if (u == eltNbToSkip) - continue; - if ((table[u].pos + table[u].length >= elt.pos) && (table[u].pos < elt.pos)) - { /* overlap, existing < new */ - /* append */ - int addedLength = (int)eltEnd - (table[u].pos + table[u].length); - table[u].savings += elt.length / 8; /* rough approx bonus */ - if (addedLength > 0) - { /* otherwise, elt fully included into existing */ - table[u].length += addedLength; - table[u].savings += elt.savings * addedLength / elt.length; /* rough approx */ - } - /* sort : improve rank */ - elt = table[u]; - while ((u > 1) && (table[u - 1].savings < elt.savings)) - table[u] = table[u - 1], u--; - table[u] = elt; - return u; - } - } - - return 0; -} - -static void ZDICT_removeDictItem(dictItem *table, U32 id) -{ - /* convention : first element is nb of elts */ - U32 const max = table->pos; - U32 u; - if (!id) - return; /* protection, should never happen */ - for (u = id; u < max - 1; u++) - table[u] = table[u + 1]; - table->pos--; -} - -static void ZDICT_insertDictItem(dictItem *table, U32 maxSize, dictItem elt) -{ - /* merge if possible */ - U32 mergeId = ZDICT_checkMerge(table, elt, 0); - if (mergeId) - { - U32 newMerge = 1; - while (newMerge) - { - newMerge = ZDICT_checkMerge(table, table[mergeId], mergeId); - if (newMerge) - ZDICT_removeDictItem(table, mergeId); - mergeId = newMerge; - } - return; - } - - /* insert */ - { - U32 current; - U32 nextElt = table->pos; - if (nextElt >= maxSize) - nextElt = maxSize - 1; - current = nextElt - 1; - while (table[current].savings < elt.savings) - { - table[current + 1] = table[current]; - current--; - } - table[current + 1] = elt; - table->pos = nextElt + 1; - } -} - -static U32 ZDICT_dictSize(const dictItem *dictList) -{ - U32 u, dictSize = 0; - for (u = 1; u < dictList[0].pos; u++) - dictSize += dictList[u].length; - return dictSize; -} - -static size_t ZDICT_trainBuffer(dictItem *dictList, U32 dictListSize, - const void *const buffer, size_t bufferSize, /* buffer must end with noisy guard band */ - const size_t *fileSizes, unsigned nbFiles, - U32 minRatio, U32 notificationLevel) -{ - int *const suffix0 = (int *)malloc((bufferSize + 2) * sizeof(*suffix0)); - int *const suffix = suffix0 + 1; - U32 *reverseSuffix = (U32 *)malloc((bufferSize) * sizeof(*reverseSuffix)); - BYTE *doneMarks = (BYTE *)malloc((bufferSize + 16) * sizeof(*doneMarks)); /* +16 for overflow security */ - U32 *filePos = (U32 *)malloc(nbFiles * sizeof(*filePos)); - size_t result = 0; - clock_t displayClock = 0; - clock_t const refreshRate = CLOCKS_PER_SEC * 3 / 10; - -#define DISPLAYUPDATE(l, ...) \ - if (notificationLevel >= l) \ - { \ - if (ZDICT_clockSpan(displayClock) > refreshRate) \ - { \ - displayClock = clock(); \ - DISPLAY(__VA_ARGS__); \ - if (notificationLevel >= 4) \ - fflush(stdout); \ - } \ - } - - /* init */ - DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */ - if (!suffix0 || !reverseSuffix || !doneMarks || !filePos) - { - result = ERROR(memory_allocation); - goto _cleanup; - } - if (minRatio < MINRATIO) - minRatio = MINRATIO; - memset(doneMarks, 0, bufferSize + 16); - - /* limit sample set size (divsufsort limitation)*/ - if (bufferSize > ZDICT_MAX_SAMPLES_SIZE) - DISPLAYLEVEL(3, "sample set too large : reduced to %u MB ...\n", (U32)(ZDICT_MAX_SAMPLES_SIZE >> 20)); - while (bufferSize > ZDICT_MAX_SAMPLES_SIZE) - bufferSize -= fileSizes[--nbFiles]; - - /* sort */ - DISPLAYLEVEL(2, "sorting %u files of total size %u MB ...\n", nbFiles, (U32)(bufferSize >> 20)); - { - int const divSuftSortResult = divsufsort((const unsigned char *)buffer, suffix, (int)bufferSize, 0); - if (divSuftSortResult != 0) - { - result = ERROR(GENERIC); - goto _cleanup; - } - } - suffix[bufferSize] = (int)bufferSize; /* leads into noise */ - suffix0[0] = (int)bufferSize; /* leads into noise */ - /* build reverse suffix sort */ - { - size_t pos; - for (pos = 0; pos < bufferSize; pos++) - reverseSuffix[suffix[pos]] = (U32)pos; - /* note filePos tracks borders between samples. - It's not used at this stage, but planned to become useful in a later update */ - filePos[0] = 0; - for (pos = 1; pos < nbFiles; pos++) - filePos[pos] = (U32)(filePos[pos - 1] + fileSizes[pos - 1]); - } - - DISPLAYLEVEL(2, "finding patterns ... \n"); - DISPLAYLEVEL(3, "minimum ratio : %u \n", minRatio); - - { - U32 cursor; - for (cursor = 0; cursor < bufferSize;) - { - dictItem solution; - if (doneMarks[cursor]) - { - cursor++; - continue; - } - solution = ZDICT_analyzePos(doneMarks, suffix, reverseSuffix[cursor], buffer, minRatio, notificationLevel); - if (solution.length == 0) - { - cursor++; - continue; - } - ZDICT_insertDictItem(dictList, dictListSize, solution); - cursor += solution.length; - DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100); - } - } - -_cleanup: - free(suffix0); - free(reverseSuffix); - free(doneMarks); - free(filePos); - return result; -} - -static void ZDICT_fillNoise(void *buffer, size_t length) -{ - unsigned const prime1 = 2654435761U; - unsigned const prime2 = 2246822519U; - unsigned acc = prime1; - size_t p = 0; - ; - for (p = 0; p < length; p++) - { - acc *= prime2; - ((unsigned char *)buffer)[p] = (unsigned char)(acc >> 21); - } -} - -typedef struct -{ - ZSTD_CCtx *ref; - ZSTD_CCtx *zc; - void *workPlace; /* must be ZSTD_BLOCKSIZE_ABSOLUTEMAX allocated */ -} EStats_ress_t; - -#define MAXREPOFFSET 1024 - -static void ZDICT_countEStats(EStats_ress_t esr, ZSTD_parameters params, - U32 *countLit, U32 *offsetcodeCount, U32 *matchlengthCount, U32 *litlengthCount, U32 *repOffsets, - const void *src, size_t srcSize, U32 notificationLevel) -{ - size_t const blockSizeMax = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << params.cParams.windowLog); - size_t cSize; - - if (srcSize > blockSizeMax) - srcSize = blockSizeMax; /* protection vs large samples */ - { - size_t const errorCode = ZSTD_copyCCtx(esr.zc, esr.ref, 0); - if (ZSTD_isError(errorCode)) - { - DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); - return; - } - } - cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_ABSOLUTEMAX, src, srcSize); - if (ZSTD_isError(cSize)) - { - DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (U32)srcSize); - return; - } - - if (cSize) - { /* if == 0; block is not compressible */ - const seqStore_t *seqStorePtr = ZSTD_getSeqStore(esr.zc); - - /* literals stats */ - { - const BYTE *bytePtr; - for (bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++) - countLit[*bytePtr]++; - } - - /* seqStats */ - { - U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - ZSTD_seqToCodes(seqStorePtr); - - { - const BYTE *codePtr = seqStorePtr->ofCode; - U32 u; - for (u = 0; u < nbSeq; u++) - offsetcodeCount[codePtr[u]]++; - } - - { - const BYTE *codePtr = seqStorePtr->mlCode; - U32 u; - for (u = 0; u < nbSeq; u++) - matchlengthCount[codePtr[u]]++; - } - - { - const BYTE *codePtr = seqStorePtr->llCode; - U32 u; - for (u = 0; u < nbSeq; u++) - litlengthCount[codePtr[u]]++; - } - - if (nbSeq >= 2) - { /* rep offsets */ - const seqDef *const seq = seqStorePtr->sequencesStart; - U32 offset1 = seq[0].offset - 3; - U32 offset2 = seq[1].offset - 3; - if (offset1 >= MAXREPOFFSET) - offset1 = 0; - if (offset2 >= MAXREPOFFSET) - offset2 = 0; - repOffsets[offset1] += 3; - repOffsets[offset2] += 1; - } - } - } -} - -/* -static size_t ZDICT_maxSampleSize(const size_t* fileSizes, unsigned nbFiles) -{ - unsigned u; - size_t max=0; - for (u=0; u 0; u--) - { - offsetCount_t tmp; - if (table[u - 1].count >= table[u].count) - break; - tmp = table[u - 1]; - table[u - 1] = table[u]; - table[u] = tmp; - } -} - -#define OFFCODE_MAX 30 /* only applicable to first block */ -static size_t ZDICT_analyzeEntropy(void *dstBuffer, size_t maxDstSize, - unsigned compressionLevel, - const void *srcBuffer, const size_t *fileSizes, unsigned nbFiles, - const void *dictBuffer, size_t dictBufferSize, - unsigned notificationLevel) -{ - U32 countLit[256]; - HUF_CREATE_STATIC_CTABLE(hufTable, 255); - U32 offcodeCount[OFFCODE_MAX + 1]; - short offcodeNCount[OFFCODE_MAX + 1]; - U32 offcodeMax = ZSTD_highbit32((U32)(dictBufferSize + 128 KB)); - U32 matchLengthCount[MaxML + 1]; - short matchLengthNCount[MaxML + 1]; - U32 litLengthCount[MaxLL + 1]; - short litLengthNCount[MaxLL + 1]; - U32 repOffset[MAXREPOFFSET]; - offsetCount_t bestRepOffset[ZSTD_REP_NUM + 1]; - EStats_ress_t esr; - ZSTD_parameters params; - U32 u, huffLog = 11, Offlog = OffFSELog, mlLog = MLFSELog, llLog = LLFSELog, total; - size_t pos = 0, errorCode; - size_t eSize = 0; - size_t const totalSrcSize = ZDICT_totalSampleSize(fileSizes, nbFiles); - size_t const averageSampleSize = totalSrcSize / (nbFiles + !nbFiles); - BYTE *dstPtr = (BYTE *)dstBuffer; - - /* init */ - esr.ref = ZSTD_createCCtx(); - esr.zc = ZSTD_createCCtx(); - esr.workPlace = malloc(ZSTD_BLOCKSIZE_ABSOLUTEMAX); - if (!esr.ref || !esr.zc || !esr.workPlace) - { - eSize = ERROR(memory_allocation); - DISPLAYLEVEL(1, "Not enough memory \n"); - goto _cleanup; - } - if (offcodeMax > OFFCODE_MAX) - { - eSize = ERROR(dictionary_wrong); - goto _cleanup; - } /* too large dictionary */ - for (u = 0; u < 256; u++) - countLit[u] = 1; /* any character must be described */ - for (u = 0; u <= offcodeMax; u++) - offcodeCount[u] = 1; - for (u = 0; u <= MaxML; u++) - matchLengthCount[u] = 1; - for (u = 0; u <= MaxLL; u++) - litLengthCount[u] = 1; - memset(repOffset, 0, sizeof(repOffset)); - repOffset[1] = repOffset[4] = repOffset[8] = 1; - memset(bestRepOffset, 0, sizeof(bestRepOffset)); - if (compressionLevel == 0) - compressionLevel = g_compressionLevel_default; - params = ZSTD_getParams(compressionLevel, averageSampleSize, dictBufferSize); - { - size_t const beginResult = ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params, 0); - if (ZSTD_isError(beginResult)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced failed \n"); - goto _cleanup; - } - } - - /* collect stats on all files */ - for (u = 0; u < nbFiles; u++) - { - ZDICT_countEStats(esr, params, - countLit, offcodeCount, matchLengthCount, litLengthCount, repOffset, - (const char *)srcBuffer + pos, fileSizes[u], - notificationLevel); - pos += fileSizes[u]; - } - - /* analyze */ - errorCode = HUF_buildCTable(hufTable, countLit, 255, huffLog); - if (HUF_isError(errorCode)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "HUF_buildCTable error \n"); - goto _cleanup; - } - huffLog = (U32)errorCode; - - /* looking for most common first offsets */ - { - U32 offset; - for (offset = 1; offset < MAXREPOFFSET; offset++) - ZDICT_insertSortCount(bestRepOffset, offset, repOffset[offset]); - } - /* note : the result of this phase should be used to better appreciate the impact on statistics */ - - total = 0; - for (u = 0; u <= offcodeMax; u++) - total += offcodeCount[u]; - errorCode = FSE_normalizeCount(offcodeNCount, Offlog, offcodeCount, total, offcodeMax); - if (FSE_isError(errorCode)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_normalizeCount error with offcodeCount \n"); - goto _cleanup; - } - Offlog = (U32)errorCode; - - total = 0; - for (u = 0; u <= MaxML; u++) - total += matchLengthCount[u]; - errorCode = FSE_normalizeCount(matchLengthNCount, mlLog, matchLengthCount, total, MaxML); - if (FSE_isError(errorCode)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_normalizeCount error with matchLengthCount \n"); - goto _cleanup; - } - mlLog = (U32)errorCode; - - total = 0; - for (u = 0; u <= MaxLL; u++) - total += litLengthCount[u]; - errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL); - if (FSE_isError(errorCode)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_normalizeCount error with litLengthCount \n"); - goto _cleanup; - } - llLog = (U32)errorCode; - - /* write result to buffer */ - { - size_t const hhSize = HUF_writeCTable(dstPtr, maxDstSize, hufTable, 255, huffLog); - if (HUF_isError(hhSize)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "HUF_writeCTable error \n"); - goto _cleanup; - } - dstPtr += hhSize; - maxDstSize -= hhSize; - eSize += hhSize; - } - - { - size_t const ohSize = FSE_writeNCount(dstPtr, maxDstSize, offcodeNCount, OFFCODE_MAX, Offlog); - if (FSE_isError(ohSize)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_writeNCount error with offcodeNCount \n"); - goto _cleanup; - } - dstPtr += ohSize; - maxDstSize -= ohSize; - eSize += ohSize; - } - - { - size_t const mhSize = FSE_writeNCount(dstPtr, maxDstSize, matchLengthNCount, MaxML, mlLog); - if (FSE_isError(mhSize)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_writeNCount error with matchLengthNCount \n"); - goto _cleanup; - } - dstPtr += mhSize; - maxDstSize -= mhSize; - eSize += mhSize; - } - - { - size_t const lhSize = FSE_writeNCount(dstPtr, maxDstSize, litLengthNCount, MaxLL, llLog); - if (FSE_isError(lhSize)) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "FSE_writeNCount error with litlengthNCount \n"); - goto _cleanup; - } - dstPtr += lhSize; - maxDstSize -= lhSize; - eSize += lhSize; - } - - if (maxDstSize < 12) - { - eSize = ERROR(GENERIC); - DISPLAYLEVEL(1, "not enough space to write RepOffsets \n"); - goto _cleanup; - } -#if 0 - MEM_writeLE32(dstPtr+0, bestRepOffset[0].offset); - MEM_writeLE32(dstPtr+4, bestRepOffset[1].offset); - MEM_writeLE32(dstPtr+8, bestRepOffset[2].offset); -#else - /* at this stage, we don't use the result of "most common first offset", - as the impact of statistics is not properly evaluated */ - MEM_writeLE32(dstPtr + 0, repStartValue[0]); - MEM_writeLE32(dstPtr + 4, repStartValue[1]); - MEM_writeLE32(dstPtr + 8, repStartValue[2]); -#endif - // dstPtr += 12; - eSize += 12; - -_cleanup: - ZSTD_freeCCtx(esr.ref); - ZSTD_freeCCtx(esr.zc); - free(esr.workPlace); - - return eSize; -} - -size_t ZDICT_finalizeDictionary(void *dictBuffer, size_t dictBufferCapacity, - const void *customDictContent, size_t dictContentSize, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t params) -{ - size_t hSize; -#define HBUFFSIZE 256 - BYTE header[HBUFFSIZE]; - int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel; - U32 const notificationLevel = params.notificationLevel; - - /* check conditions */ - if (dictBufferCapacity < dictContentSize) - return ERROR(dstSize_tooSmall); - if (dictContentSize < ZDICT_CONTENTSIZE_MIN) - return ERROR(srcSize_wrong); - if (dictBufferCapacity < ZDICT_DICTSIZE_MIN) - return ERROR(dstSize_tooSmall); - - /* dictionary header */ - MEM_writeLE32(header, ZSTD_DICT_MAGIC); - { - U64 const randomID = XXH64(customDictContent, dictContentSize, 0); - U32 const compliantID = (randomID % ((1U << 31) - 32768)) + 32768; - U32 const dictID = params.dictID ? params.dictID : compliantID; - MEM_writeLE32(header + 4, dictID); - } - hSize = 8; - - /* entropy tables */ - DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */ - DISPLAYLEVEL(2, "statistics ... \n"); - { - size_t const eSize = ZDICT_analyzeEntropy(header + hSize, HBUFFSIZE - hSize, - compressionLevel, - samplesBuffer, samplesSizes, nbSamples, - customDictContent, dictContentSize, - notificationLevel); - if (ZDICT_isError(eSize)) - return eSize; - hSize += eSize; - } - - /* copy elements in final buffer ; note : src and dst buffer can overlap */ - if (hSize + dictContentSize > dictBufferCapacity) - dictContentSize = dictBufferCapacity - hSize; - { - size_t const dictSize = hSize + dictContentSize; - char *dictEnd = (char *)dictBuffer + dictSize; - memmove(dictEnd - dictContentSize, customDictContent, dictContentSize); - memcpy(dictBuffer, header, hSize); - return dictSize; - } -} - -size_t ZDICT_addEntropyTablesFromBuffer_advanced(void *dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t params) -{ - size_t hSize; - int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel; - U32 const notificationLevel = params.notificationLevel; - - /* dictionary header */ - MEM_writeLE32(dictBuffer, ZSTD_DICT_MAGIC); - { - U64 const randomID = XXH64((char *)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, 0); - U32 const compliantID = (randomID % ((1U << 31) - 32768)) + 32768; - U32 const dictID = params.dictID ? params.dictID : compliantID; - MEM_writeLE32((char *)dictBuffer + 4, dictID); - } - hSize = 8; - - /* entropy tables */ - DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */ - DISPLAYLEVEL(2, "statistics ... \n"); - { - size_t const eSize = ZDICT_analyzeEntropy((char *)dictBuffer + hSize, dictBufferCapacity - hSize, - compressionLevel, - samplesBuffer, samplesSizes, nbSamples, - (char *)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize, - notificationLevel); - if (ZDICT_isError(eSize)) - return eSize; - hSize += eSize; - } - - if (hSize + dictContentSize < dictBufferCapacity) - memmove((char *)dictBuffer + hSize, (char *)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize); - return MIN(dictBufferCapacity, hSize + dictContentSize); -} - -/*! ZDICT_trainFromBuffer_unsafe() : - * Warning : `samplesBuffer` must be followed by noisy guard band. - * @return : size of dictionary, or an error code which can be tested with ZDICT_isError() - */ -size_t ZDICT_trainFromBuffer_unsafe( - void *dictBuffer, size_t maxDictSize, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t params) -{ - U32 const dictListSize = MAX(MAX(DICTLISTSIZE_DEFAULT, nbSamples), (U32)(maxDictSize / 16)); - dictItem *const dictList = (dictItem *)malloc(dictListSize * sizeof(*dictList)); - unsigned const selectivity = params.selectivityLevel == 0 ? g_selectivity_default : params.selectivityLevel; - unsigned const minRep = (selectivity > 30) ? MINRATIO : nbSamples >> selectivity; - size_t const targetDictSize = maxDictSize; - size_t const samplesBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples); - size_t dictSize = 0; - U32 const notificationLevel = params.notificationLevel; - - /* checks */ - if (!dictList) - return ERROR(memory_allocation); - if (maxDictSize <= g_provision_entropySize + g_min_fast_dictContent) - { - free(dictList); - return ERROR(dstSize_tooSmall); - } - if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) - { - free(dictList); - return 0; - } /* not enough source to create dictionary */ - - /* init */ - ZDICT_initDictItem(dictList); - - /* build dictionary */ - ZDICT_trainBuffer(dictList, dictListSize, - samplesBuffer, samplesBuffSize, - samplesSizes, nbSamples, - minRep, notificationLevel); - - /* display best matches */ - if (params.notificationLevel >= 3) - { - U32 const nb = MIN(25, dictList[0].pos); - U32 const dictContentSize = ZDICT_dictSize(dictList); - U32 u; - DISPLAYLEVEL(3, "\n %u segments found, of total size %u \n", dictList[0].pos - 1, dictContentSize); - DISPLAYLEVEL(3, "list %u best segments \n", nb - 1); - for (u = 1; u < nb; u++) - { - U32 const pos = dictList[u].pos; - U32 const length = dictList[u].length; - U32 const printedLength = MIN(40, length); - if ((pos > samplesBuffSize) || ((pos + length) > samplesBuffSize)) - return ERROR(GENERIC); /* should never happen */ - DISPLAYLEVEL(3, "%3u:%3u bytes at pos %8u, savings %7u bytes |", - u, length, pos, dictList[u].savings); - ZDICT_printHex((const char *)samplesBuffer + pos, printedLength); - DISPLAYLEVEL(3, "| \n"); - } - } - - /* create dictionary */ - { - U32 dictContentSize = ZDICT_dictSize(dictList); - if (dictContentSize < targetDictSize / 3) - { - DISPLAYLEVEL(2, "! warning : selected content significantly smaller than requested (%u < %u) \n", dictContentSize, (U32)maxDictSize); - if (minRep > MINRATIO) - { - DISPLAYLEVEL(2, "! consider increasing selectivity to produce larger dictionary (-s%u) \n", selectivity + 1); - DISPLAYLEVEL(2, "! note : larger dictionaries are not necessarily better, test its efficiency on samples \n"); - } - if (samplesBuffSize < 10 * targetDictSize) - DISPLAYLEVEL(2, "! consider increasing the number of samples (total size : %u MB)\n", (U32)(samplesBuffSize >> 20)); - } - - if ((dictContentSize > targetDictSize * 3) && (nbSamples > 2 * MINRATIO) && (selectivity > 1)) - { - U32 proposedSelectivity = selectivity - 1; - while ((nbSamples >> proposedSelectivity) <= MINRATIO) - { - proposedSelectivity--; - } - DISPLAYLEVEL(2, "! note : calculated dictionary significantly larger than requested (%u > %u) \n", dictContentSize, (U32)maxDictSize); - DISPLAYLEVEL(2, "! consider increasing dictionary size, or produce denser dictionary (-s%u) \n", proposedSelectivity); - DISPLAYLEVEL(2, "! always test dictionary efficiency on samples \n"); - } - - /* limit dictionary size */ - { - U32 const max = dictList->pos; /* convention : nb of useful elts within dictList */ - U32 currentSize = 0; - U32 n; - for (n = 1; n < max; n++) - { - currentSize += dictList[n].length; - if (currentSize > targetDictSize) - { - currentSize -= dictList[n].length; - break; - } - } - dictList->pos = n; - dictContentSize = currentSize; - } - - /* build dict content */ - { - U32 u; - BYTE *ptr = (BYTE *)dictBuffer + maxDictSize; - for (u = 1; u < dictList->pos; u++) - { - U32 l = dictList[u].length; - ptr -= l; - if (ptr < (BYTE *)dictBuffer) - { - free(dictList); - return ERROR(GENERIC); - } /* should not happen */ - memcpy(ptr, (const char *)samplesBuffer + dictList[u].pos, l); - } - } - - dictSize = ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, maxDictSize, - samplesBuffer, samplesSizes, nbSamples, - params); - } - - /* clean up */ - free(dictList); - return dictSize; -} - -/* issue : samplesBuffer need to be followed by a noisy guard band. - * work around : duplicate the buffer, and add the noise */ -size_t ZDICT_trainFromBuffer_advanced(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t params) -{ - size_t result; - void *newBuff; - size_t const sBuffSize = ZDICT_totalSampleSize(samplesSizes, nbSamples); - if (sBuffSize < ZDICT_MIN_SAMPLES_SIZE) - return 0; /* not enough content => no dictionary */ - - newBuff = malloc(sBuffSize + NOISELENGTH); - if (!newBuff) - return ERROR(memory_allocation); - - memcpy(newBuff, samplesBuffer, sBuffSize); - ZDICT_fillNoise((char *)newBuff + sBuffSize, NOISELENGTH); /* guard band, for end of buffer condition */ - - result = ZDICT_trainFromBuffer_unsafe( - dictBuffer, dictBufferCapacity, - newBuff, samplesSizes, nbSamples, - params); - free(newBuff); - return result; -} - -size_t ZDICT_trainFromBuffer(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples) -{ - ZDICT_params_t params; - memset(¶ms, 0, sizeof(params)); - return ZDICT_trainFromBuffer_advanced(dictBuffer, dictBufferCapacity, - samplesBuffer, samplesSizes, nbSamples, - params); -} - -size_t ZDICT_addEntropyTablesFromBuffer(void *dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples) -{ - ZDICT_params_t params; - memset(¶ms, 0, sizeof(params)); - return ZDICT_addEntropyTablesFromBuffer_advanced(dictBuffer, dictContentSize, dictBufferCapacity, - samplesBuffer, samplesSizes, nbSamples, - params); -} diff --git a/extra/zstd/zdict.h b/extra/zstd/zdict.h deleted file mode 100644 index eafea424..00000000 --- a/extra/zstd/zdict.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef DICTBUILDER_H_001 -#define DICTBUILDER_H_001 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*====== Dependencies ======*/ -#include /* size_t */ - -/* ===== ZDICTLIB_API : control library symbols visibility ===== */ -#if defined(__GNUC__) && (__GNUC__ >= 4) -#define ZDICTLIB_VISIBILITY __attribute__((visibility("default"))) -#else -#define ZDICTLIB_VISIBILITY -#endif -#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT == 1) -#define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBILITY -#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT == 1) -#define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_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 ZDICTLIB_API ZDICTLIB_VISIBILITY -#endif - - /*! ZDICT_trainFromBuffer() : - Train a dictionary from an array of samples. - Samples must be stored concatenated in a single flat buffer `samplesBuffer`, - supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. - The resulting dictionary will be saved into `dictBuffer`. - @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - or an error code, which can be tested with ZDICT_isError(). - Tips : In general, a reasonable dictionary has a size of ~ 100 KB. - It's obviously possible to target smaller or larger ones, just by specifying different `dictBufferCapacity`. - In general, it's recommended to provide a few thousands samples, but this can vary a lot. - It's recommended that total size of all samples be about ~x100 times the target size of dictionary. - */ - ZDICTLIB_API size_t ZDICT_trainFromBuffer(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples); - - /*====== Helper functions ======*/ - ZDICTLIB_API unsigned ZDICT_getDictID(const void *dictBuffer, size_t dictSize); /**< extracts dictID; @return zero if error (not a valid dictionary) */ - ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode); - ZDICTLIB_API const char *ZDICT_getErrorName(size_t errorCode); - -#ifdef ZDICT_STATIC_LINKING_ONLY - - /* ==================================================================================== - * The definitions in this section are considered experimental. - * They should never be used with a dynamic library, as they may change in the future. - * They are provided for advanced usages. - * Use them only in association with static linking. - * ==================================================================================== */ - - typedef struct - { - unsigned selectivityLevel; /* 0 means default; larger => select more => larger dictionary */ - int compressionLevel; /* 0 means default; target a specific zstd compression level */ - unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ - unsigned dictID; /* 0 means auto mode (32-bits random value); other : force dictID value */ - unsigned reserved[2]; /* reserved space for future parameters */ - } ZDICT_params_t; - - /*! ZDICT_trainFromBuffer_advanced() : - Same as ZDICT_trainFromBuffer() with control over more parameters. - `parameters` is optional and can be provided with values set to 0 to mean "default". - @return : size of dictionary stored into `dictBuffer` (<= `dictBufferSize`), - or an error code, which can be tested by ZDICT_isError(). - note : ZDICT_trainFromBuffer_advanced() will send notifications into stderr if instructed to, using notificationLevel>0. - */ - ZDICTLIB_API size_t ZDICT_trainFromBuffer_advanced(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t parameters); - - /*! COVER_params_t : - For all values 0 means default. - kMin and d are the only required parameters. - */ - typedef struct - { - unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */ - unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */ - unsigned steps; /* Number of steps : Only used for optimization : 0 means default (32) : Higher means more parameters checked */ - - unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ - unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ - unsigned dictID; /* 0 means auto mode (32-bits random value); other : force dictID value */ - int compressionLevel; /* 0 means default; target a specific zstd compression level */ - } COVER_params_t; - - /*! COVER_trainFromBuffer() : - Train a dictionary from an array of samples using the COVER algorithm. - Samples must be stored concatenated in a single flat buffer `samplesBuffer`, - supplied with an array of sizes `samplesSizes`, providing the size of each sample, in order. - The resulting dictionary will be saved into `dictBuffer`. - @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - or an error code, which can be tested with ZDICT_isError(). - Note : COVER_trainFromBuffer() requires about 9 bytes of memory for each input byte. - Tips : In general, a reasonable dictionary has a size of ~ 100 KB. - It's obviously possible to target smaller or larger ones, just by specifying different `dictBufferCapacity`. - In general, it's recommended to provide a few thousands samples, but this can vary a lot. - It's recommended that total size of all samples be about ~x100 times the target size of dictionary. - */ - ZDICTLIB_API size_t COVER_trainFromBuffer(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - COVER_params_t parameters); - - /*! COVER_optimizeTrainFromBuffer() : - The same requirements as above hold for all the parameters except `parameters`. - This function tries many parameter combinations and picks the best parameters. - `*parameters` is filled with the best parameters found, and the dictionary - constructed with those parameters is stored in `dictBuffer`. - - All of the parameters d, k, steps are optional. - If d is non-zero then we don't check multiple values of d, otherwise we check d = {6, 8, 10, 12, 14, 16}. - if steps is zero it defaults to its default value. - If k is non-zero then we don't check multiple values of k, otherwise we check steps values in [16, 2048]. - - @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) - or an error code, which can be tested with ZDICT_isError(). - On success `*parameters` contains the parameters selected. - Note : COVER_optimizeTrainFromBuffer() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread. - */ - ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - COVER_params_t *parameters); - -/*! ZDICT_finalizeDictionary() : - - Given a custom content as a basis for dictionary, and a set of samples, - finalize dictionary by adding headers and statistics. - - Samples must be stored concatenated in a flat buffer `samplesBuffer`, - supplied with an array of sizes `samplesSizes`, providing the size of each sample in order. - - dictContentSize must be > ZDICT_CONTENTSIZE_MIN bytes. - maxDictSize must be >= dictContentSize, and must be > ZDICT_DICTSIZE_MIN bytes. - - @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`), - or an error code, which can be tested by ZDICT_isError(). - note : ZDICT_finalizeDictionary() will push notifications into stderr if instructed to, using notificationLevel>0. - note 2 : dictBuffer and customDictContent can overlap -*/ -#define ZDICT_CONTENTSIZE_MIN 256 -#define ZDICT_DICTSIZE_MIN 512 - ZDICTLIB_API size_t ZDICT_finalizeDictionary(void *dictBuffer, size_t dictBufferCapacity, - const void *customDictContent, size_t dictContentSize, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, - ZDICT_params_t parameters); - -/* Deprecation warnings */ -/* It is generally possible to disable deprecation warnings from compiler, - for example with -Wno-deprecated-declarations for gcc - or _CRT_SECURE_NO_WARNINGS in Visual. - Otherwise, it's also possible to manually define ZDICT_DISABLE_DEPRECATE_WARNINGS */ -#ifdef ZDICT_DISABLE_DEPRECATE_WARNINGS -#define ZDICT_DEPRECATED(message) ZDICTLIB_API /* disable deprecation warnings */ -#else -#define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -#if defined(__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ -#define ZDICT_DEPRECATED(message) [[deprecated(message)]] ZDICTLIB_API -#elif (ZDICT_GCC_VERSION >= 405) || defined(__clang__) -#define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated(message))) -#elif (ZDICT_GCC_VERSION >= 301) -#define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated)) -#elif defined(_MSC_VER) -#define ZDICT_DEPRECATED(message) ZDICTLIB_API __declspec(deprecated(message)) -#else -#pragma message("WARNING: You need to implement ZDICT_DEPRECATED for this compiler") -#define ZDICT_DEPRECATED(message) ZDICTLIB_API -#endif -#endif /* ZDICT_DISABLE_DEPRECATE_WARNINGS */ - - ZDICT_DEPRECATED("use ZDICT_finalizeDictionary() instead") - size_t ZDICT_addEntropyTablesFromBuffer(void *dictBuffer, size_t dictContentSize, size_t dictBufferCapacity, - const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples); - -#endif /* ZDICT_STATIC_LINKING_ONLY */ - -#if defined(__cplusplus) -} -#endif - -#endif /* DICTBUILDER_H_001 */ diff --git a/extra/zstd/zstd.h b/extra/zstd/zstd.h deleted file mode 100644 index b10c0957..00000000 --- a/extra/zstd/zstd.h +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#ifndef ZSTD_H_235446 -#define ZSTD_H_235446 - -/* ====== Dependency ======*/ -#include /* size_t */ - -/* ===== ZSTDLIB_API : control library symbols visibility ===== */ -#if defined(__GNUC__) && (__GNUC__ >= 4) -#define ZSTDLIB_VISIBILITY __attribute__((visibility("default"))) -#else -#define ZSTDLIB_VISIBILITY -#endif -#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT == 1) -#define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY -#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT == 1) -#define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_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 ZSTDLIB_API ZSTDLIB_VISIBILITY -#endif - -/******************************************************************************************************* - Introduction - - zstd, short for Zstandard, is a fast lossless compression algorithm, targeting real-time compression scenarios - at zlib-level and better compression ratios. The zstd compression library provides in-memory compression and - decompression functions. The library supports compression levels from 1 up to ZSTD_maxCLevel() which is 22. - Levels >= 20, labeled `--ultra`, should be used with caution, as they require more memory. - Compression can be done in: - - a single step (described as Simple API) - - a single step, reusing a context (described as Explicit memory management) - - unbounded multiple steps (described as Streaming compression) - The compression ratio achievable on small data can be highly improved using compression with a dictionary in: - - a single step (described as Simple dictionary API) - - a single step, reusing a dictionary (described as Fast dictionary API) - - Advanced experimental functions can be accessed using #define ZSTD_STATIC_LINKING_ONLY before including zstd.h. - These APIs shall never be used with a dynamic library. - They are not "stable", their definition may change in the future. Only static linking is allowed. -*********************************************************************************************************/ - -/*------ Version ------*/ -#define ZSTD_VERSION_MAJOR 1 -#define ZSTD_VERSION_MINOR 1 -#define ZSTD_VERSION_RELEASE 4 - -#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE -#define ZSTD_QUOTE(str) #str -#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) -#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) - -#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR * 100 * 100 + ZSTD_VERSION_MINOR * 100 + ZSTD_VERSION_RELEASE) - ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< library version number; to be used when checking dll version */ - - /*************************************** - * Simple API - ***************************************/ - /*! ZSTD_compress() : - Compresses `src` content as a single zstd compressed frame into already allocated `dst`. - Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`. - @return : compressed size written into `dst` (<= `dstCapacity), - or an error code if it fails (which can be tested using ZSTD_isError()). */ - ZSTDLIB_API size_t ZSTD_compress(void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - int compressionLevel); - - /*! ZSTD_decompress() : - `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames. - `dstCapacity` is an upper bound of originalSize. - If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data. - @return : the number of bytes decompressed into `dst` (<= `dstCapacity`), - or an errorCode if it fails (which can be tested using ZSTD_isError()). */ - ZSTDLIB_API size_t ZSTD_decompress(void *dst, size_t dstCapacity, - const void *src, size_t compressedSize); - - /*! ZSTD_getDecompressedSize() : - * NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize. - * ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single - * frame, but distinguishes empty frames from frames with an unknown size, or errors. - * - * Additionally, ZSTD_findDecompressedSize can be used instead. It can handle multiple - * concatenated frames in one buffer, and so is more general. - * As a result however, it requires more computation and entire frames to be passed to it, - * as opposed to ZSTD_getFrameContentSize which requires only a single frame's header. - * - * 'src' is the start of a zstd compressed frame. - * @return : content size to be decompressed, as a 64-bits value _if known_, 0 otherwise. - * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. - * When `return==0`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * Optionally, application can still use ZSTD_decompress() while relying on implied limits. - * (For example, data may be necessarily cut into blocks <= 16 KB). - * note 2 : decompressed size is always present when compression is done with ZSTD_compress() - * note 3 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure result fits within application's authorized limits. - * Each application can set its own limits. - * note 5 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */ - ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void *src, size_t srcSize); - - /*====== Helper functions ======*/ - ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */ - ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */ - ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ - ZSTDLIB_API const char *ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */ - - /*************************************** - * Explicit memory management - ***************************************/ - /*= Compression context - * When compressing many times, - * it is recommended to allocate a context just once, and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Use one context per thread for parallel execution in multi-threaded environments. */ - typedef struct ZSTD_CCtx_s ZSTD_CCtx; - ZSTDLIB_API ZSTD_CCtx *ZSTD_createCCtx(void); - ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx); - - /*! ZSTD_compressCCtx() : - Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */ - ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel); - - /*= Decompression context - * When decompressing many times, - * it is recommended to allocate a context just once, and re-use it for each successive compression operation. - * This will make workload friendlier for system's memory. - * Use one context per thread for parallel execution in multi-threaded environments. */ - typedef struct ZSTD_DCtx_s ZSTD_DCtx; - ZSTDLIB_API ZSTD_DCtx *ZSTD_createDCtx(void); - ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx); - - /*! ZSTD_decompressDCtx() : - * Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). */ - ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - - /************************** - * Simple dictionary API - ***************************/ - /*! ZSTD_compress_usingDict() : - * Compression using a predefined Dictionary (see dictBuilder/zdict.h). - * Note : This function loads the dictionary, resulting in significant startup delay. - * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ - ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx *ctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize, - int compressionLevel); - - /*! ZSTD_decompress_usingDict() : - * Decompression using a predefined Dictionary (see dictBuilder/zdict.h). - * Dictionary must be identical to the one used during compression. - * Note : This function loads the dictionary, resulting in significant startup delay. - * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */ - ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize); - - /**************************** - * Fast dictionary API - ****************************/ - typedef struct ZSTD_CDict_s ZSTD_CDict; - - /*! ZSTD_createCDict() : - * When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once. - * ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay. - * ZSTD_CDict can be created once and used by multiple threads concurrently, as its usage is read-only. - * `dictBuffer` can be released after ZSTD_CDict creation, as its content is copied within CDict */ - ZSTDLIB_API ZSTD_CDict *ZSTD_createCDict(const void *dictBuffer, size_t dictSize, int compressionLevel); - - /*! ZSTD_freeCDict() : - * Function frees memory allocated by ZSTD_createCDict(). */ - ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict *CDict); - - /*! ZSTD_compress_usingCDict() : - * Compression using a digested Dictionary. - * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. - * Note that compression level is decided during dictionary creation. */ - ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const ZSTD_CDict *cdict); - - typedef struct ZSTD_DDict_s ZSTD_DDict; - - /*! ZSTD_createDDict() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * dictBuffer can be released after DDict creation, as its content is copied inside DDict */ - ZSTDLIB_API ZSTD_DDict *ZSTD_createDDict(const void *dictBuffer, size_t dictSize); - - /*! ZSTD_freeDDict() : - * Function frees memory allocated with ZSTD_createDDict() */ - ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict *ddict); - - /*! ZSTD_decompress_usingDDict() : - * Decompression using a digested Dictionary. - * Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */ - ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const ZSTD_DDict *ddict); - - /**************************** - * Streaming - ****************************/ - - typedef struct ZSTD_inBuffer_s - { - const void *src; /**< start of input buffer */ - size_t size; /**< size of input buffer */ - size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */ - } ZSTD_inBuffer; - - typedef struct ZSTD_outBuffer_s - { - void *dst; /**< start of output buffer */ - size_t size; /**< size of output buffer */ - size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */ - } ZSTD_outBuffer; - - /*-*********************************************************************** - * Streaming compression - HowTo - * - * A ZSTD_CStream object is required to track streaming operation. - * Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources. - * ZSTD_CStream objects can be reused multiple times on consecutive compression operations. - * It is recommended to re-use ZSTD_CStream in situations where many streaming operations will be achieved consecutively, - * since it will play nicer with system's memory, by re-using already allocated memory. - * Use one separate ZSTD_CStream per thread for parallel execution. - * - * Start a new compression by initializing ZSTD_CStream. - * Use ZSTD_initCStream() to start a new compression operation. - * Use ZSTD_initCStream_usingDict() or ZSTD_initCStream_usingCDict() for a compression which requires a dictionary (experimental section) - * - * Use ZSTD_compressStream() repetitively to consume input stream. - * The function will automatically update both `pos` fields. - * Note that it may not consume the entire input, in which case `pos < size`, - * and it's up to the caller to present again remaining data. - * @return : a size hint, preferred nb of bytes to use as input for next function call - * or an error code, which can be tested using ZSTD_isError(). - * Note 1 : it's just a hint, to help latency a little, any other value will work fine. - * Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize() - * - * At any moment, it's possible to flush whatever data remains within internal buffer, using ZSTD_flushStream(). - * `output->pos` will be updated. - * Note that some content might still be left within internal buffer if `output->size` is too small. - * @return : nb of bytes still present within internal buffer (0 if it's empty) - * or an error code, which can be tested using ZSTD_isError(). - * - * ZSTD_endStream() instructs to finish a frame. - * It will perform a flush and write frame epilogue. - * The epilogue is required for decoders to consider a frame completed. - * Similar to ZSTD_flushStream(), it may not be able to flush the full content if `output->size` is too small. - * In which case, call again ZSTD_endStream() to complete the flush. - * @return : nb of bytes still present within internal buffer (0 if it's empty, hence compression completed) - * or an error code, which can be tested using ZSTD_isError(). - * - * *******************************************************************/ - - typedef struct ZSTD_CStream_s ZSTD_CStream; - /*===== ZSTD_CStream management functions =====*/ - ZSTDLIB_API ZSTD_CStream *ZSTD_createCStream(void); - ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream *zcs); - - /*===== Streaming compression functions =====*/ - ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream *zcs, int compressionLevel); - ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input); - ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output); - ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output); - - ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */ - ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */ - - /*-*************************************************************************** - * Streaming decompression - HowTo - * - * A ZSTD_DStream object is required to track streaming operations. - * Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources. - * ZSTD_DStream objects can be re-used multiple times. - * - * Use ZSTD_initDStream() to start a new decompression operation, - * or ZSTD_initDStream_usingDict() if decompression requires a dictionary. - * @return : recommended first input size - * - * Use ZSTD_decompressStream() repetitively to consume your input. - * The function will update both `pos` fields. - * If `input.pos < input.size`, some input has not been consumed. - * It's up to the caller to present again remaining data. - * If `output.pos < output.size`, decoder has flushed everything it could. - * @return : 0 when a frame is completely decoded and fully flushed, - * an error code, which can be tested using ZSTD_isError(), - * any other value > 0, which means there is still some decoding to do to complete current frame. - * The return value is a suggested next input size (a hint to improve latency) that will never load more than the current frame. - * *******************************************************************************/ - - typedef struct ZSTD_DStream_s ZSTD_DStream; - /*===== ZSTD_DStream management functions =====*/ - ZSTDLIB_API ZSTD_DStream *ZSTD_createDStream(void); - ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream *zds); - - /*===== Streaming decompression functions =====*/ - ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream *zds); - ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input); - - ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */ - ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */ - -#endif /* ZSTD_H_235446 */ - -#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY) -#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY - -/**************************************************************************************** - * START OF ADVANCED AND EXPERIMENTAL FUNCTIONS - * The definitions in this section are considered experimental. - * They should never be used with a dynamic library, as they may change in the future. - * They are provided for advanced usages. - * Use them only in association with static linking. - * ***************************************************************************************/ - -/* --- Constants ---*/ -#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */ -#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U - -#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) -#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) - -#define ZSTD_WINDOWLOG_MAX_32 27 -#define ZSTD_WINDOWLOG_MAX_64 27 -#define ZSTD_WINDOWLOG_MAX ((unsigned)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64)) -#define ZSTD_WINDOWLOG_MIN 10 -#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX -#define ZSTD_HASHLOG_MIN 6 -#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX + 1) -#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN -#define ZSTD_HASHLOG3_MAX 17 -#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX - 1) -#define ZSTD_SEARCHLOG_MIN 1 -#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */ -#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */ -#define ZSTD_TARGETLENGTH_MIN 4 -#define ZSTD_TARGETLENGTH_MAX 999 - -#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */ -#define ZSTD_FRAMEHEADERSIZE_MIN 6 - static const size_t ZSTD_frameHeaderSize_prefix = 5; - static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN; - static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX; - static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */ - - /*--- Advanced types ---*/ - typedef enum - { - ZSTD_fast, - ZSTD_dfast, - ZSTD_greedy, - ZSTD_lazy, - ZSTD_lazy2, - ZSTD_btlazy2, - ZSTD_btopt, - ZSTD_btopt2 - } ZSTD_strategy; /* from faster to stronger */ - - typedef struct - { - unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */ - unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */ - unsigned hashLog; /**< dispatch table : larger == faster, more memory */ - unsigned searchLog; /**< nb of searches : larger == more compression, slower */ - unsigned searchLength; /**< match length searched : larger == faster decompression, sometimes less compression */ - unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */ - ZSTD_strategy strategy; - } ZSTD_compressionParameters; - - typedef struct - { - unsigned contentSizeFlag; /**< 1: content size will be in frame header (when known) */ - unsigned checksumFlag; /**< 1: generate a 32-bits checksum at end of frame, for error detection */ - unsigned noDictIDFlag; /**< 1: no dictID will be saved into frame header (if dictionary compression) */ - } ZSTD_frameParameters; - - typedef struct - { - ZSTD_compressionParameters cParams; - ZSTD_frameParameters fParams; - } ZSTD_parameters; - - /*= Custom memory allocation functions */ - typedef void *(*ZSTD_allocFunction)(void *opaque, size_t size); - typedef void (*ZSTD_freeFunction)(void *opaque, void *address); - typedef struct - { - ZSTD_allocFunction customAlloc; - ZSTD_freeFunction customFree; - void *opaque; - } ZSTD_customMem; - - /*************************************** - * Compressed size functions - ***************************************/ - - /*! ZSTD_findFrameCompressedSize() : - * `src` should point to the start of a ZSTD encoded frame or skippable frame - * `srcSize` must be at least as large as the frame - * @return : the compressed size of the frame pointed to by `src`, suitable to pass to - * `ZSTD_decompress` or similar, or an error code if given invalid input. */ - ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize); - - /*************************************** - * Decompressed size functions - ***************************************/ - /*! ZSTD_getFrameContentSize() : - * `src` should point to the start of a ZSTD encoded frame - * `srcSize` must be at least as large as the frame header. A value greater than or equal - * to `ZSTD_frameHeaderSize_max` is guaranteed to be large enough in all cases. - * @return : decompressed size of the frame pointed to be `src` if known, otherwise - * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ - ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize); - - /*! ZSTD_findDecompressedSize() : - * `src` should point the start of a series of ZSTD encoded and/or skippable frames - * `srcSize` must be the _exact_ size of this series - * (i.e. there should be a frame boundary exactly `srcSize` bytes after `src`) - * @return : the decompressed size of all data in the contained frames, as a 64-bit value _if known_ - * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN - * - if an error occurred: ZSTD_CONTENTSIZE_ERROR - * - * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode. - * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size. - * In which case, it's necessary to use streaming mode to decompress data. - * Optionally, application can still use ZSTD_decompress() while relying on implied limits. - * (For example, data may be necessarily cut into blocks <= 16 KB). - * note 2 : decompressed size is always present when compression is done with ZSTD_compress() - * note 3 : decompressed size can be very large (64-bits value), - * potentially larger than what local system can handle as a single memory segment. - * In which case, it's necessary to use streaming mode to decompress data. - * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified. - * Always ensure result fits within application's authorized limits. - * Each application can set its own limits. - * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to - * read each contained frame header. This is efficient as most of the data is skipped, - * however it does mean that all frame data must be present and valid. */ - ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize); - - /*************************************** - * Advanced compression functions - ***************************************/ - /*! ZSTD_estimateCCtxSize() : - * Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters. - * `frameContentSize` is an optional parameter, provide `0` if unknown */ - ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams); - - /*! ZSTD_createCCtx_advanced() : - * Create a ZSTD compression context using external alloc and free functions */ - ZSTDLIB_API ZSTD_CCtx *ZSTD_createCCtx_advanced(ZSTD_customMem customMem); - - /*! ZSTD_sizeofCCtx() : - * Gives the amount of memory used by a given ZSTD_CCtx */ - ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx *cctx); - - typedef enum - { - ZSTD_p_forceWindow, /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0) */ - ZSTD_p_forceRawDict /* Force loading dictionary in "content-only" mode (no header analysis) */ - } ZSTD_CCtxParameter; - /*! ZSTD_setCCtxParameter() : - * Set advanced parameters, selected through enum ZSTD_CCtxParameter - * @result : 0, or an error code (which can be tested with ZSTD_isError()) */ - ZSTDLIB_API size_t ZSTD_setCCtxParameter(ZSTD_CCtx *cctx, ZSTD_CCtxParameter param, unsigned value); - - /*! ZSTD_createCDict_byReference() : - * Create a digested dictionary for compression - * Dictionary content is simply referenced, and therefore stays in dictBuffer. - * It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */ - ZSTDLIB_API ZSTD_CDict *ZSTD_createCDict_byReference(const void *dictBuffer, size_t dictSize, int compressionLevel); - - /*! ZSTD_createCDict_advanced() : - * Create a ZSTD_CDict using external alloc and free, and customized compression parameters */ - ZSTDLIB_API ZSTD_CDict *ZSTD_createCDict_advanced(const void *dict, size_t dictSize, unsigned byReference, - ZSTD_parameters params, ZSTD_customMem customMem); - - /*! ZSTD_sizeof_CDict() : - * Gives the amount of memory used by a given ZSTD_sizeof_CDict */ - ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict *cdict); - - /*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. - * `estimatedSrcSize` value is optional, select 0 if not known */ - ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - - /*! ZSTD_getParams() : - * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`. - * All fields of `ZSTD_frameParameters` are set to default (0) */ - ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize); - - /*! ZSTD_checkCParams() : - * Ensure param values remain within authorized range */ - ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params); - - /*! ZSTD_adjustCParams() : - * optimize params for a given `srcSize` and `dictSize`. - * both values are optional, select `0` if unknown. */ - ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize); - - /*! ZSTD_compress_advanced() : - * Same as ZSTD_compress_usingDict(), with fine-tune control of each compression parameter */ - ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx *ctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize, - ZSTD_parameters params); - - /*--- Advanced decompression functions ---*/ - - /*! ZSTD_isFrame() : - * Tells if the content of `buffer` starts with a valid Frame Identifier. - * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. - * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. - * Note 3 : Skippable Frame Identifiers are considered valid. */ - ZSTDLIB_API unsigned ZSTD_isFrame(const void *buffer, size_t size); - - /*! ZSTD_estimateDCtxSize() : - * Gives the potential amount of memory allocated to create a ZSTD_DCtx */ - ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void); - - /*! ZSTD_createDCtx_advanced() : - * Create a ZSTD decompression context using external alloc and free functions */ - ZSTDLIB_API ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem); - - /*! ZSTD_sizeof_DCtx() : - * Gives the amount of memory used by a given ZSTD_DCtx */ - ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx *dctx); - - /*! ZSTD_createDDict_byReference() : - * Create a digested dictionary, ready to start decompression operation without startup delay. - * Dictionary content is simply referenced, and therefore stays in dictBuffer. - * It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */ - ZSTDLIB_API ZSTD_DDict *ZSTD_createDDict_byReference(const void *dictBuffer, size_t dictSize); - - /*! ZSTD_createDDict_advanced() : - * Create a ZSTD_DDict using external alloc and free, optionally by reference */ - ZSTDLIB_API ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, - unsigned byReference, ZSTD_customMem customMem); - - /*! ZSTD_sizeof_DDict() : - * Gives the amount of memory used by a given ZSTD_DDict */ - ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict *ddict); - - /*! ZSTD_getDictID_fromDict() : - * Provides the dictID stored within dictionary. - * if @return == 0, the dictionary is not conformant with Zstandard specification. - * It can still be loaded, but as a content-only dictionary. */ - ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize); - - /*! ZSTD_getDictID_fromDDict() : - * Provides the dictID of the dictionary loaded into `ddict`. - * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. - * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ - ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict); - - /*! ZSTD_getDictID_fromFrame() : - * Provides the dictID required to decompressed the frame stored within `src`. - * If @return == 0, the dictID could not be decoded. - * This could for one of the following reasons : - * - The frame does not require a dictionary to be decoded (most common case). - * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. - * Note : this use case also happens when using a non-conformant dictionary. - * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). - * - This is not a Zstandard frame. - * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */ - ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize); - - /******************************************************************** - * Advanced streaming functions - ********************************************************************/ - - /*===== Advanced Streaming compression functions =====*/ - ZSTDLIB_API ZSTD_CStream *ZSTD_createCStream_advanced(ZSTD_customMem customMem); - ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream *zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ - ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream *zcs, const void *dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ - ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, const void *dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */ - ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream *zcs, const ZSTD_CDict *cdict); /**< note : cdict will just be referenced, and must outlive compression session */ - ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize); /**< re-use compression parameters from previous init; skip dictionary loading stage; zcs must be init at least once before. note: pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */ - ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream *zcs); - - /*===== Advanced Streaming decompression functions =====*/ - typedef enum - { - DStream_p_maxWindowSize - } ZSTD_DStreamParameter_e; - ZSTDLIB_API ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem); - ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream *zds, const void *dict, size_t dictSize); /**< note: a dict will not be used if dict == NULL or dictSize < 8 */ - ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream *zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue); - ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream *zds, const ZSTD_DDict *ddict); /**< note : ddict will just be referenced, and must outlive decompression session */ - ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream *zds); /**< re-use decompression parameters from previous init; saves dictionary loading */ - ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream *zds); - - /********************************************************************* - * Buffer-less and synchronous inner streaming functions - * - * This is an advanced API, giving full control over buffer management, for users which need direct control over memory. - * But it's also a complex one, with many restrictions (documented below). - * Prefer using normal streaming API for an easier experience - ********************************************************************* */ - - /** - Buffer-less streaming compression (synchronous mode) - - A ZSTD_CCtx object is required to track streaming operations. - Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource. - ZSTD_CCtx object can be re-used multiple times within successive compression operations. - - Start by initializing a context. - Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression, - or ZSTD_compressBegin_advanced(), for finer parameter control. - It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx() - - Then, consume your input using ZSTD_compressContinue(). - There are some important considerations to keep in mind when using this advanced function : - - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffer only. - - Interface is synchronous : input is consumed entirely and produce 1+ (or more) compressed blocks. - - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario. - Worst case evaluation is provided by ZSTD_compressBound(). - ZSTD_compressContinue() doesn't guarantee recover after a failed compression. - - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog). - It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks) - - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps. - In which case, it will "discard" the relevant memory section from its history. - - Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum. - It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame. - Without last block mark, frames will be considered unfinished (corrupted) by decoders. - - `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new frame. - */ - - /*===== Buffer-less streaming compression functions =====*/ - ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx *cctx, int compressionLevel); - ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, int compressionLevel); - ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */ - ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx *cctx, const ZSTD_CCtx *preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize can be 0, indicating unknown size. if it is non-zero, it must be accurate. for 0 size frames, use compressBegin_advanced */ - ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx *cctx, const ZSTD_CDict *cdict, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize can be 0, indicating unknown size. if it is non-zero, it must be accurate. for 0 size frames, use compressBegin_advanced */ - ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - - /*- - Buffer-less streaming decompression (synchronous mode) - - A ZSTD_DCtx object is required to track streaming operations. - Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it. - A ZSTD_DCtx object can be re-used multiple times. - - First typical operation is to retrieve frame parameters, using ZSTD_getFrameParams(). - It fills a ZSTD_frameParams structure which provide important information to correctly decode the frame, - such as the minimum rolling buffer size to allocate to decompress data (`windowSize`), - and the dictionary ID used. - (Note : content size is optional, it may not be present. 0 means : content size unknown). - Note that these values could be wrong, either because of data malformation, or because an attacker is spoofing deliberate false information. - As a consequence, check that values remain within valid application range, especially `windowSize`, before allocation. - Each application can set its own limit, depending on local restrictions. For extended interoperability, it is recommended to support at least 8 MB. - Frame parameters are extracted from the beginning of the compressed frame. - Data fragment must be large enough to ensure successful decoding, typically `ZSTD_frameHeaderSize_max` bytes. - @result : 0 : successful decoding, the `ZSTD_frameParams` structure is correctly filled. - >0 : `srcSize` is too small, please provide at least @result bytes on next attempt. - errorCode, which can be tested using ZSTD_isError(). - - Start decompression, with ZSTD_decompressBegin() or ZSTD_decompressBegin_usingDict(). - Alternatively, you can copy a prepared context, using ZSTD_copyDCtx(). - - Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. - ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail. - - @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity). - It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some metadata item. - It can also be an error code, which can be tested with ZSTD_isError(). - - ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize`. - They should preferably be located contiguously, prior to current block. - Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters. - ZSTD_decompressContinue() is very sensitive to contiguity, - if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place, - or that previous contiguous segment is large enough to properly handle maximum back-reference. - - A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. - Context can then be reset to start a new decompression. - - Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). - This information is not required to properly decode a frame. - - == Special case : skippable frames == - - Skippable frames allow integration of user-defined data into a flow of concatenated frames. - Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frames is as follows : - a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F - b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits - c) Frame Content - any content (User Data) of length equal to Frame Size - For skippable frames ZSTD_decompressContinue() always returns 0. - For skippable frames ZSTD_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable. - Note : If fparamsPtr->frameContentSize==0, it is ambiguous: the frame might actually be a Zstd encoded frame with no content. - For purposes of decompression, it is valid in both cases to skip the frame using - ZSTD_findFrameCompressedSize to find its size in bytes. - It also returns Frame Size as fparamsPtr->frameContentSize. - */ - - typedef struct - { - unsigned long long frameContentSize; - unsigned windowSize; - unsigned dictID; - unsigned checksumFlag; - } ZSTD_frameParams; - - /*===== Buffer-less streaming decompression functions =====*/ - ZSTDLIB_API size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize); /**< doesn't consume input, see details below */ - ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx); - ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize); - ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx *dctx, const ZSTD_DCtx *preparedDCtx); - ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx); - ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - typedef enum - { - ZSTDnit_frameHeader, - ZSTDnit_blockHeader, - ZSTDnit_block, - ZSTDnit_lastBlock, - ZSTDnit_checksum, - ZSTDnit_skippableFrame - } ZSTD_nextInputType_e; - ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx); - - /** - Block functions - - Block functions produce and decode raw zstd blocks, without frame metadata. - Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). - User will have to take in charge required information to regenerate data, such as compressed and content sizes. - - A few rules to respect : - - Compressing and decompressing require a context structure - + Use ZSTD_createCCtx() and ZSTD_createDCtx() - - It is necessary to init context before starting - + compression : ZSTD_compressBegin() - + decompression : ZSTD_decompressBegin() - + variants _usingDict() are also allowed - + copyCCtx() and copyDCtx() work too - - Block size is limited, it must be <= ZSTD_getBlockSizeMax() - + If you need to compress more, cut data into multiple blocks - + Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large. - - When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero. - In which case, nothing is produced into `dst`. - + User must test for such outcome and deal directly with uncompressed data - + ZSTD_decompressBlock() doesn't accept uncompressed data as input !!! - + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history. - Use ZSTD_insertBlock() in such a case. - */ - -#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */ - /*===== Raw zstd block functions =====*/ - ZSTDLIB_API size_t ZSTD_getBlockSizeMax(ZSTD_CCtx *cctx); - ZSTDLIB_API size_t ZSTD_compressBlock(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize); - ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */ - -#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */ - -#if defined(__cplusplus) -} -#endif diff --git a/extra/zstd/zstd_common.c b/extra/zstd/zstd_common.c deleted file mode 100644 index 306828b1..00000000 --- a/extra/zstd/zstd_common.c +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/*-************************************* - * Dependencies - ***************************************/ -#include /* malloc */ -#include "error_private.h" -#define ZSTD_STATIC_LINKING_ONLY -#include "zstd.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */ - -/*-**************************************** - * Version - ******************************************/ -unsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; } - -/*-**************************************** - * ZSTD Error Management - ******************************************/ -/*! ZSTD_isError() : - * tells if a return value is an error code */ -unsigned ZSTD_isError(size_t code) { return ERR_isError(code); } - -/*! ZSTD_getErrorName() : - * provides error code string from function result (useful for debugging) */ -const char *ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); } - -/*! ZSTD_getError() : - * convert a `size_t` function result into a proper ZSTD_errorCode enum */ -ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); } - -/*! ZSTD_getErrorString() : - * provides error code string from enum */ -const char *ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); } - -/*=************************************************************** - * Custom allocator - ****************************************************************/ -/* default uses stdlib */ -void *ZSTD_defaultAllocFunction(void *opaque, size_t size) -{ - void *address = malloc(size); - (void)opaque; - return address; -} - -void ZSTD_defaultFreeFunction(void *opaque, void *address) -{ - (void)opaque; - free(address); -} - -void *ZSTD_malloc(size_t size, ZSTD_customMem customMem) -{ - return customMem.customAlloc(customMem.opaque, size); -} - -void ZSTD_free(void *ptr, ZSTD_customMem customMem) -{ - if (ptr != NULL) - customMem.customFree(customMem.opaque, ptr); -} diff --git a/extra/zstd/zstd_compress.c b/extra/zstd/zstd_compress.c deleted file mode 100644 index af31e9e4..00000000 --- a/extra/zstd/zstd_compress.c +++ /dev/null @@ -1,4009 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/*-************************************* - * Dependencies - ***************************************/ -#include /* memset */ -#include "mem.h" -#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */ -#include "fse.h" -#define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "zstd_internal.h" /* includes zstd.h */ - -/*-************************************* - * Constants - ***************************************/ -static const U32 g_searchStrength = 8; /* control skip over incompressible data */ -#define HASH_READ_SIZE 8 -typedef enum -{ - ZSTDcs_created = 0, - ZSTDcs_init, - ZSTDcs_ongoing, - ZSTDcs_ending -} ZSTD_compressionStage_e; - -/*-************************************* - * Helper functions - ***************************************/ -#define ZSTD_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - ZSTD_static_assert = 1 / (int)(!!(c)) \ - }; \ - } -size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; } - -/*-************************************* - * Sequence storage - ***************************************/ -static void ZSTD_resetSeqStore(seqStore_t *ssPtr) -{ - ssPtr->lit = ssPtr->litStart; - ssPtr->sequences = ssPtr->sequencesStart; - ssPtr->longLengthID = 0; -} - -/*-************************************* - * Context memory management - ***************************************/ -struct ZSTD_CCtx_s -{ - const BYTE *nextSrc; /* next block here to continue on current prefix */ - const BYTE *base; /* All regular indexes relative to this position */ - const BYTE *dictBase; /* extDict indexes relative to this position */ - U32 dictLimit; /* below that point, need extDict */ - U32 lowLimit; /* below that point, no more data */ - U32 nextToUpdate; /* index from which to continue dictionary update */ - U32 nextToUpdate3; /* index from which to continue dictionary update */ - U32 hashLog3; /* dispatch table : larger == faster, more memory */ - U32 loadedDictEnd; /* index of end of dictionary */ - U32 forceWindow; /* force back-references to respect limit of 1<customMem = customMem; - return cctx; -} - -size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx) -{ - if (cctx == NULL) - return 0; /* support free on NULL */ - ZSTD_free(cctx->workSpace, cctx->customMem); - ZSTD_free(cctx, cctx->customMem); - return 0; /* reserved as a potential error code in the future */ -} - -size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx *cctx) -{ - if (cctx == NULL) - return 0; /* support sizeof on NULL */ - return sizeof(*cctx) + cctx->workSpaceSize; -} - -size_t ZSTD_setCCtxParameter(ZSTD_CCtx *cctx, ZSTD_CCtxParameter param, unsigned value) -{ - switch (param) - { - case ZSTD_p_forceWindow: - cctx->forceWindow = value > 0; - cctx->loadedDictEnd = 0; - return 0; - case ZSTD_p_forceRawDict: - cctx->forceRawDict = value > 0; - return 0; - default: - return ERROR(parameter_unknown); - } -} - -const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx) /* hidden interface */ -{ - return &(ctx->seqStore); -} - -static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx *cctx) -{ - return cctx->params; -} - -/** ZSTD_checkParams() : - ensure param values remain within authorized range. - @return : 0, or an error code if one value is beyond authorized range */ -size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams) -{ -#define CLAMPCHECK(val, min, max) \ - { \ - if ((val < min) | (val > max)) \ - return ERROR(compressionParameter_unsupported); \ - } - CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX); - CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX); - CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX); - CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX); - { - U32 const searchLengthMin = ((cParams.strategy == ZSTD_fast) | (cParams.strategy == ZSTD_greedy)) ? ZSTD_SEARCHLENGTH_MIN + 1 : ZSTD_SEARCHLENGTH_MIN; - U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX - 1; - CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); - } - CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX); - if ((U32)(cParams.strategy) > (U32)ZSTD_btopt2) - return ERROR(compressionParameter_unsupported); - return 0; -} - -/** ZSTD_cycleLog() : - * condition for correct operation : hashLog > 1 */ -static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) -{ - U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2); - return hashLog - btScale; -} - -/** ZSTD_adjustCParams() : - optimize `cPar` for a given input (`srcSize` and `dictSize`). - mostly downsizing to reduce memory consumption and initialization. - Both `srcSize` and `dictSize` are optional (use 0 if unknown), - but if both are 0, no optimization can be done. - Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */ -ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize) -{ - if (srcSize + dictSize == 0) - return cPar; /* no size information available : no adjustment */ - - /* resize params, to use less memory when necessary */ - { - U32 const minSrcSize = (srcSize == 0) ? 500 : 0; - U64 const rSize = srcSize + dictSize + minSrcSize; - if (rSize < ((U64)1 << ZSTD_WINDOWLOG_MAX)) - { - U32 const srcLog = MAX(ZSTD_HASHLOG_MIN, ZSTD_highbit32((U32)(rSize)-1) + 1); - if (cPar.windowLog > srcLog) - cPar.windowLog = srcLog; - } - } - if (cPar.hashLog > cPar.windowLog) - cPar.hashLog = cPar.windowLog; - { - U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); - if (cycleLog > cPar.windowLog) - cPar.chainLog -= (cycleLog - cPar.windowLog); - } - - if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) - cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */ - - return cPar; -} - -size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams) -{ - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog); - U32 const divider = (cParams.searchLength == 3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = blockSize + 11 * maxNbSeq; - - size_t const chainSize = (cParams.strategy == ZSTD_fast) ? 0 : (1 << cParams.chainLog); - size_t const hSize = ((size_t)1) << cParams.hashLog; - U32 const hashLog3 = (cParams.searchLength > 3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, cParams.windowLog); - size_t const h3Size = ((size_t)1) << hashLog3; - size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); - - size_t const optSpace = ((MaxML + 1) + (MaxLL + 1) + (MaxOff + 1) + (1 << Litbits)) * sizeof(U32) + (ZSTD_OPT_NUM + 1) * (sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t)); - size_t const neededSpace = tableSpace + (256 * sizeof(U32)) /* huffTable */ + tokenSpace + (((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btopt2)) ? optSpace : 0); - - return sizeof(ZSTD_CCtx) + neededSpace; -} - -static U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2) -{ - return (param1.cParams.hashLog == param2.cParams.hashLog) & (param1.cParams.chainLog == param2.cParams.chainLog) & (param1.cParams.strategy == param2.cParams.strategy) & ((param1.cParams.searchLength == 3) == (param2.cParams.searchLength == 3)); -} - -/*! ZSTD_continueCCtx() : - reuse CCtx without reset (note : requires no dictionary) */ -static size_t ZSTD_continueCCtx(ZSTD_CCtx *cctx, ZSTD_parameters params, U64 frameContentSize) -{ - U32 const end = (U32)(cctx->nextSrc - cctx->base); - cctx->params = params; - cctx->frameContentSize = frameContentSize; - cctx->lowLimit = end; - cctx->dictLimit = end; - cctx->nextToUpdate = end + 1; - cctx->stage = ZSTDcs_init; - cctx->dictID = 0; - cctx->loadedDictEnd = 0; - { - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - cctx->rep[i] = repStartValue[i]; - } - cctx->seqStore.litLengthSum = 0; /* force reset of btopt stats */ - XXH64_reset(&cctx->xxhState, 0); - return 0; -} - -typedef enum -{ - ZSTDcrp_continue, - ZSTDcrp_noMemset, - ZSTDcrp_fullReset -} ZSTD_compResetPolicy_e; - -/*! ZSTD_resetCCtx_advanced() : - note : `params` must be validated */ -static size_t ZSTD_resetCCtx_advanced(ZSTD_CCtx *zc, - ZSTD_parameters params, U64 frameContentSize, - ZSTD_compResetPolicy_e const crp) -{ - if (crp == ZSTDcrp_continue) - if (ZSTD_equivalentParams(params, zc->params)) - { - zc->flagStaticTables = 0; - zc->flagStaticHufTable = HUF_repeat_none; - return ZSTD_continueCCtx(zc, params, frameContentSize); - } - - { - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog); - U32 const divider = (params.cParams.searchLength == 3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = blockSize + 11 * maxNbSeq; - size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog); - size_t const hSize = ((size_t)1) << params.cParams.hashLog; - U32 const hashLog3 = (params.cParams.searchLength > 3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog); - size_t const h3Size = ((size_t)1) << hashLog3; - size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); - void *ptr; - - /* Check if workSpace is large enough, alloc a new one if needed */ - { - size_t const optSpace = ((MaxML + 1) + (MaxLL + 1) + (MaxOff + 1) + (1 << Litbits)) * sizeof(U32) + (ZSTD_OPT_NUM + 1) * (sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t)); - size_t const neededSpace = tableSpace + (256 * sizeof(U32)) /* huffTable */ + tokenSpace + (((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) ? optSpace : 0); - if (zc->workSpaceSize < neededSpace) - { - ZSTD_free(zc->workSpace, zc->customMem); - zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem); - if (zc->workSpace == NULL) - return ERROR(memory_allocation); - zc->workSpaceSize = neededSpace; - } - } - - if (crp != ZSTDcrp_noMemset) - memset(zc->workSpace, 0, tableSpace); /* reset tables only */ - XXH64_reset(&zc->xxhState, 0); - zc->hashLog3 = hashLog3; - zc->hashTable = (U32 *)(zc->workSpace); - zc->chainTable = zc->hashTable + hSize; - zc->hashTable3 = zc->chainTable + chainSize; - ptr = zc->hashTable3 + h3Size; - zc->hufTable = (HUF_CElt *)ptr; - zc->flagStaticTables = 0; - zc->flagStaticHufTable = HUF_repeat_none; - ptr = ((U32 *)ptr) + 256; /* note : HUF_CElt* is incomplete type, size is simulated using U32 */ - - zc->nextToUpdate = 1; - zc->nextSrc = NULL; - zc->base = NULL; - zc->dictBase = NULL; - zc->dictLimit = 0; - zc->lowLimit = 0; - zc->params = params; - zc->blockSize = blockSize; - zc->frameContentSize = frameContentSize; - { - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - zc->rep[i] = repStartValue[i]; - } - - if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btopt2)) - { - zc->seqStore.litFreq = (U32 *)ptr; - zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1 << Litbits); - zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL + 1); - zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML + 1); - ptr = zc->seqStore.offCodeFreq + (MaxOff + 1); - zc->seqStore.matchTable = (ZSTD_match_t *)ptr; - ptr = zc->seqStore.matchTable + ZSTD_OPT_NUM + 1; - zc->seqStore.priceTable = (ZSTD_optimal_t *)ptr; - ptr = zc->seqStore.priceTable + ZSTD_OPT_NUM + 1; - zc->seqStore.litLengthSum = 0; - } - zc->seqStore.sequencesStart = (seqDef *)ptr; - ptr = zc->seqStore.sequencesStart + maxNbSeq; - zc->seqStore.llCode = (BYTE *)ptr; - zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq; - zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq; - zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq; - - zc->stage = ZSTDcs_init; - zc->dictID = 0; - zc->loadedDictEnd = 0; - - return 0; - } -} - -/* ZSTD_invalidateRepCodes() : - * ensures next compression will not use repcodes from previous block. - * Note : only works with regular variant; - * do not use with extDict variant ! */ -void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx) -{ - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - cctx->rep[i] = 0; -} - -/*! ZSTD_copyCCtx() : - * Duplicate an existing context `srcCCtx` into another one `dstCCtx`. - * Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()). - * @return : 0, or an error code */ -size_t ZSTD_copyCCtx(ZSTD_CCtx *dstCCtx, const ZSTD_CCtx *srcCCtx, unsigned long long pledgedSrcSize) -{ - if (srcCCtx->stage != ZSTDcs_init) - return ERROR(stage_wrong); - - memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); - { - ZSTD_parameters params = srcCCtx->params; - params.fParams.contentSizeFlag = (pledgedSrcSize > 0); - ZSTD_resetCCtx_advanced(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset); - } - - /* copy tables */ - { - size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog); - size_t const hSize = ((size_t)1) << srcCCtx->params.cParams.hashLog; - size_t const h3Size = (size_t)1 << srcCCtx->hashLog3; - size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32); - memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace); - } - - /* copy dictionary offsets */ - dstCCtx->nextToUpdate = srcCCtx->nextToUpdate; - dstCCtx->nextToUpdate3 = srcCCtx->nextToUpdate3; - dstCCtx->nextSrc = srcCCtx->nextSrc; - dstCCtx->base = srcCCtx->base; - dstCCtx->dictBase = srcCCtx->dictBase; - dstCCtx->dictLimit = srcCCtx->dictLimit; - dstCCtx->lowLimit = srcCCtx->lowLimit; - dstCCtx->loadedDictEnd = srcCCtx->loadedDictEnd; - dstCCtx->dictID = srcCCtx->dictID; - - /* copy entropy tables */ - dstCCtx->flagStaticTables = srcCCtx->flagStaticTables; - dstCCtx->flagStaticHufTable = srcCCtx->flagStaticHufTable; - if (srcCCtx->flagStaticTables) - { - memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, sizeof(dstCCtx->litlengthCTable)); - memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, sizeof(dstCCtx->matchlengthCTable)); - memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, sizeof(dstCCtx->offcodeCTable)); - } - if (srcCCtx->flagStaticHufTable) - { - memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256 * 4); - } - - return 0; -} - -/*! ZSTD_reduceTable() : - * reduce table indexes by `reducerValue` */ -static void ZSTD_reduceTable(U32 *const table, U32 const size, U32 const reducerValue) -{ - U32 u; - for (u = 0; u < size; u++) - { - if (table[u] < reducerValue) - table[u] = 0; - else - table[u] -= reducerValue; - } -} - -/*! ZSTD_reduceIndex() : - * rescale all indexes to avoid future overflow (indexes are U32) */ -static void ZSTD_reduceIndex(ZSTD_CCtx *zc, const U32 reducerValue) -{ - { - U32 const hSize = 1 << zc->params.cParams.hashLog; - ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); - } - - { - U32 const chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog); - ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); - } - - { - U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0; - ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); - } -} - -/*-******************************************************* - * Block entropic compression - *********************************************************/ - -/* See doc/zstd_compression_format.md for detailed format description */ - -size_t ZSTD_noCompressBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - if (srcSize + ZSTD_blockHeaderSize > dstCapacity) - return ERROR(dstSize_tooSmall); - memcpy((BYTE *)dst + ZSTD_blockHeaderSize, src, srcSize); - MEM_writeLE24(dst, (U32)(srcSize << 2) + (U32)bt_raw); - return ZSTD_blockHeaderSize + srcSize; -} - -static size_t ZSTD_noCompressLiterals(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - BYTE *const ostart = (BYTE *const)dst; - U32 const flSize = 1 + (srcSize > 31) + (srcSize > 4095); - - if (srcSize + flSize > dstCapacity) - return ERROR(dstSize_tooSmall); - - switch (flSize) - { - case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((U32)set_basic + (srcSize << 3)); - break; - case 2: /* 2 - 2 - 12 */ - MEM_writeLE16(ostart, (U16)((U32)set_basic + (1 << 2) + (srcSize << 4))); - break; - default: /*note : should not be necessary : flSize is within {1,2,3} */ - case 3: /* 2 - 2 - 20 */ - MEM_writeLE32(ostart, (U32)((U32)set_basic + (3 << 2) + (srcSize << 4))); - break; - } - - memcpy(ostart + flSize, src, srcSize); - return srcSize + flSize; -} - -static size_t ZSTD_compressRleLiteralsBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - BYTE *const ostart = (BYTE *const)dst; - U32 const flSize = 1 + (srcSize > 31) + (srcSize > 4095); - - (void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */ - - switch (flSize) - { - case 1: /* 2 - 1 - 5 */ - ostart[0] = (BYTE)((U32)set_rle + (srcSize << 3)); - break; - case 2: /* 2 - 2 - 12 */ - MEM_writeLE16(ostart, (U16)((U32)set_rle + (1 << 2) + (srcSize << 4))); - break; - default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */ - case 3: /* 2 - 2 - 20 */ - MEM_writeLE32(ostart, (U32)((U32)set_rle + (3 << 2) + (srcSize << 4))); - break; - } - - ostart[flSize] = *(const BYTE *)src; - return flSize + 1; -} - -static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; } - -static size_t ZSTD_compressLiterals(ZSTD_CCtx *zc, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize) -{ - size_t const minGain = ZSTD_minGain(srcSize); - size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB); - BYTE *const ostart = (BYTE *)dst; - U32 singleStream = srcSize < 256; - symbolEncodingType_e hType = set_compressed; - size_t cLitSize; - - /* small ? don't even attempt compression (speed opt) */ -#define LITERAL_NOENTROPY 63 - { - size_t const minLitSize = zc->flagStaticHufTable == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY; - if (srcSize <= minLitSize) - return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); - } - - if (dstCapacity < lhSize + 1) - return ERROR(dstSize_tooSmall); /* not enough space for compression */ - { - HUF_repeat repeat = zc->flagStaticHufTable; - int const preferRepeat = zc->params.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0; - if (repeat == HUF_repeat_valid && lhSize == 3) - singleStream = 1; - cLitSize = singleStream ? HUF_compress1X_repeat(ostart + lhSize, dstCapacity - lhSize, src, srcSize, 255, 11, zc->tmpCounters, sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat) - : HUF_compress4X_repeat(ostart + lhSize, dstCapacity - lhSize, src, srcSize, 255, 11, zc->tmpCounters, sizeof(zc->tmpCounters), zc->hufTable, &repeat, preferRepeat); - if (repeat != HUF_repeat_none) - { - hType = set_repeat; - } /* reused the existing table */ - else - { - zc->flagStaticHufTable = HUF_repeat_check; - } /* now have a table to reuse */ - } - - if ((cLitSize == 0) | (cLitSize >= srcSize - minGain)) - { - zc->flagStaticHufTable = HUF_repeat_none; - return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); - } - if (cLitSize == 1) - { - zc->flagStaticHufTable = HUF_repeat_none; - return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); - } - - /* Build header */ - switch (lhSize) - { - case 3: /* 2 - 2 - 10 - 10 */ - { - U32 const lhc = hType + ((!singleStream) << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 14); - MEM_writeLE24(ostart, lhc); - break; - } - case 4: /* 2 - 2 - 14 - 14 */ - { - U32 const lhc = hType + (2 << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 18); - MEM_writeLE32(ostart, lhc); - break; - } - default: /* should not be necessary, lhSize is only {3,4,5} */ - case 5: /* 2 - 2 - 18 - 18 */ - { - U32 const lhc = hType + (3 << 2) + ((U32)srcSize << 4) + ((U32)cLitSize << 22); - MEM_writeLE32(ostart, lhc); - ostart[4] = (BYTE)(cLitSize >> 10); - break; - } - } - return lhSize + cLitSize; -} - -static const BYTE LL_Code[64] = {0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 16, 17, 17, 18, 18, 19, 19, - 20, 20, 20, 20, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24}; - -static const BYTE ML_Code[128] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, - 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, - 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, - 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}; - -void ZSTD_seqToCodes(const seqStore_t *seqStorePtr) -{ - BYTE const LL_deltaCode = 19; - BYTE const ML_deltaCode = 36; - const seqDef *const sequences = seqStorePtr->sequencesStart; - BYTE *const llCodeTable = seqStorePtr->llCode; - BYTE *const ofCodeTable = seqStorePtr->ofCode; - BYTE *const mlCodeTable = seqStorePtr->mlCode; - U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - U32 u; - for (u = 0; u < nbSeq; u++) - { - U32 const llv = sequences[u].litLength; - U32 const mlv = sequences[u].matchLength; - llCodeTable[u] = (llv > 63) ? (BYTE)ZSTD_highbit32(llv) + LL_deltaCode : LL_Code[llv]; - ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset); - mlCodeTable[u] = (mlv > 127) ? (BYTE)ZSTD_highbit32(mlv) + ML_deltaCode : ML_Code[mlv]; - } - if (seqStorePtr->longLengthID == 1) - llCodeTable[seqStorePtr->longLengthPos] = MaxLL; - if (seqStorePtr->longLengthID == 2) - mlCodeTable[seqStorePtr->longLengthPos] = MaxML; -} - -MEM_STATIC size_t ZSTD_compressSequences(ZSTD_CCtx *zc, - void *dst, size_t dstCapacity, - size_t srcSize) -{ - const int longOffsets = zc->params.cParams.windowLog > STREAM_ACCUMULATOR_MIN; - const seqStore_t *seqStorePtr = &(zc->seqStore); - U32 count[MaxSeq + 1]; - S16 norm[MaxSeq + 1]; - FSE_CTable *CTable_LitLength = zc->litlengthCTable; - FSE_CTable *CTable_OffsetBits = zc->offcodeCTable; - FSE_CTable *CTable_MatchLength = zc->matchlengthCTable; - U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */ - const seqDef *const sequences = seqStorePtr->sequencesStart; - const BYTE *const ofCodeTable = seqStorePtr->ofCode; - const BYTE *const llCodeTable = seqStorePtr->llCode; - const BYTE *const mlCodeTable = seqStorePtr->mlCode; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstCapacity; - BYTE *op = ostart; - size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart; - BYTE *seqHead; - BYTE scratchBuffer[1 << MAX(MLFSELog, LLFSELog)]; - - /* Compress literals */ - { - const BYTE *const literals = seqStorePtr->litStart; - size_t const litSize = seqStorePtr->lit - literals; - size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize); - if (ZSTD_isError(cSize)) - return cSize; - op += cSize; - } - - /* Sequences Header */ - if ((oend - op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) - return ERROR(dstSize_tooSmall); - if (nbSeq < 0x7F) - *op++ = (BYTE)nbSeq; - else if (nbSeq < LONGNBSEQ) - op[0] = (BYTE)((nbSeq >> 8) + 0x80), op[1] = (BYTE)nbSeq, op += 2; - else - op[0] = 0xFF, MEM_writeLE16(op + 1, (U16)(nbSeq - LONGNBSEQ)), op += 3; - if (nbSeq == 0) - goto _check_compressibility; - - /* seqHead : flags for FSE encoding type */ - seqHead = op++; - -#define MIN_SEQ_FOR_DYNAMIC_FSE 64 -#define MAX_SEQ_FOR_STATIC_FSE 1000 - - /* convert length/distances into codes */ - ZSTD_seqToCodes(seqStorePtr); - - /* CTable for Literal Lengths */ - { - U32 max = MaxLL; - size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, zc->tmpCounters); - if ((mostFrequent == nbSeq) && (nbSeq > 2)) - { - *op++ = llCodeTable[0]; - FSE_buildCTable_rle(CTable_LitLength, (BYTE)max); - LLtype = set_rle; - } - else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) - { - LLtype = set_repeat; - } - else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog - 1)))) - { - FSE_buildCTable_wksp(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); - LLtype = set_basic; - } - else - { - size_t nbSeq_1 = nbSeq; - const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max); - if (count[llCodeTable[nbSeq - 1]] > 1) - { - count[llCodeTable[nbSeq - 1]]--; - nbSeq_1--; - } - FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); - { - size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ - if (FSE_isError(NCountSize)) - return ERROR(GENERIC); - op += NCountSize; - } - FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer)); - LLtype = set_compressed; - } - } - - /* CTable for Offsets */ - { - U32 max = MaxOff; - size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, zc->tmpCounters); - if ((mostFrequent == nbSeq) && (nbSeq > 2)) - { - *op++ = ofCodeTable[0]; - FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max); - Offtype = set_rle; - } - else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) - { - Offtype = set_repeat; - } - else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (OF_defaultNormLog - 1)))) - { - FSE_buildCTable_wksp(CTable_OffsetBits, OF_defaultNorm, MaxOff, OF_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); - Offtype = set_basic; - } - else - { - size_t nbSeq_1 = nbSeq; - const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max); - if (count[ofCodeTable[nbSeq - 1]] > 1) - { - count[ofCodeTable[nbSeq - 1]]--; - nbSeq_1--; - } - FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); - { - size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ - if (FSE_isError(NCountSize)) - return ERROR(GENERIC); - op += NCountSize; - } - FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer)); - Offtype = set_compressed; - } - } - - /* CTable for MatchLengths */ - { - U32 max = MaxML; - size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, zc->tmpCounters); - if ((mostFrequent == nbSeq) && (nbSeq > 2)) - { - *op++ = *mlCodeTable; - FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max); - MLtype = set_rle; - } - else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) - { - MLtype = set_repeat; - } - else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog - 1)))) - { - FSE_buildCTable_wksp(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog, scratchBuffer, sizeof(scratchBuffer)); - MLtype = set_basic; - } - else - { - size_t nbSeq_1 = nbSeq; - const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max); - if (count[mlCodeTable[nbSeq - 1]] > 1) - { - count[mlCodeTable[nbSeq - 1]]--; - nbSeq_1--; - } - FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max); - { - size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ - if (FSE_isError(NCountSize)) - return ERROR(GENERIC); - op += NCountSize; - } - FSE_buildCTable_wksp(CTable_MatchLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer)); - MLtype = set_compressed; - } - } - - *seqHead = (BYTE)((LLtype << 6) + (Offtype << 4) + (MLtype << 2)); - zc->flagStaticTables = 0; - - /* Encoding Sequences */ - { - BIT_CStream_t blockStream; - FSE_CState_t stateMatchLength; - FSE_CState_t stateOffsetBits; - FSE_CState_t stateLitLength; - - CHECK_E(BIT_initCStream(&blockStream, op, oend - op), dstSize_tooSmall); /* not enough space remaining */ - - /* first symbols */ - FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq - 1]); - FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq - 1]); - FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq - 1]); - BIT_addBits(&blockStream, sequences[nbSeq - 1].litLength, LL_bits[llCodeTable[nbSeq - 1]]); - if (MEM_32bits()) - BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, sequences[nbSeq - 1].matchLength, ML_bits[mlCodeTable[nbSeq - 1]]); - if (MEM_32bits()) - BIT_flushBits(&blockStream); - if (longOffsets) - { - U32 const ofBits = ofCodeTable[nbSeq - 1]; - int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN - 1); - if (extraBits) - { - BIT_addBits(&blockStream, sequences[nbSeq - 1].offset, extraBits); - BIT_flushBits(&blockStream); - } - BIT_addBits(&blockStream, sequences[nbSeq - 1].offset >> extraBits, - ofBits - extraBits); - } - else - { - BIT_addBits(&blockStream, sequences[nbSeq - 1].offset, ofCodeTable[nbSeq - 1]); - } - BIT_flushBits(&blockStream); - - { - size_t n; - for (n = nbSeq - 2; n < nbSeq; n--) - { /* intentional underflow */ - BYTE const llCode = llCodeTable[n]; - BYTE const ofCode = ofCodeTable[n]; - BYTE const mlCode = mlCodeTable[n]; - U32 const llBits = LL_bits[llCode]; - U32 const ofBits = ofCode; /* 32b*/ /* 64b*/ - U32 const mlBits = ML_bits[mlCode]; - /* (7)*/ /* (7)*/ - FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */ - FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */ - if (MEM_32bits()) - BIT_flushBits(&blockStream); /* (7)*/ - FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */ - if (MEM_32bits() || (ofBits + mlBits + llBits >= 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) - BIT_flushBits(&blockStream); /* (7)*/ - BIT_addBits(&blockStream, sequences[n].litLength, llBits); - if (MEM_32bits() && ((llBits + mlBits) > 24)) - BIT_flushBits(&blockStream); - BIT_addBits(&blockStream, sequences[n].matchLength, mlBits); - if (MEM_32bits()) - BIT_flushBits(&blockStream); /* (7)*/ - if (longOffsets) - { - int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN - 1); - if (extraBits) - { - BIT_addBits(&blockStream, sequences[n].offset, extraBits); - BIT_flushBits(&blockStream); /* (7)*/ - } - BIT_addBits(&blockStream, sequences[n].offset >> extraBits, - ofBits - extraBits); /* 31 */ - } - else - { - BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */ - } - BIT_flushBits(&blockStream); /* (7)*/ - } - } - - FSE_flushCState(&blockStream, &stateMatchLength); - FSE_flushCState(&blockStream, &stateOffsetBits); - FSE_flushCState(&blockStream, &stateLitLength); - - { - size_t const streamSize = BIT_closeCStream(&blockStream); - if (streamSize == 0) - return ERROR(dstSize_tooSmall); /* not enough space */ - op += streamSize; - } - } - - /* check compressibility */ -_check_compressibility: -{ - size_t const minGain = ZSTD_minGain(srcSize); - size_t const maxCSize = srcSize - minGain; - if ((size_t)(op - ostart) >= maxCSize) - { - zc->flagStaticHufTable = HUF_repeat_none; - return 0; - } -} - - /* confirm repcodes */ - { - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - zc->rep[i] = zc->repToConfirm[i]; - } - - return op - ostart; -} - -#if 0 /* for debug */ -#define STORESEQ_DEBUG -#include /* fprintf */ -U32 g_startDebug = 0; -const BYTE* g_start = NULL; -#endif - -/*! ZSTD_storeSeq() : - Store a sequence (literal length, literals, offset code and match length code) into seqStore_t. - `offsetCode` : distance to match, or 0 == repCode. - `matchCode` : matchLength - MINMATCH -*/ -MEM_STATIC void ZSTD_storeSeq(seqStore_t *seqStorePtr, size_t litLength, const void *literals, U32 offsetCode, size_t matchCode) -{ -#ifdef STORESEQ_DEBUG - if (g_startDebug) - { - const U32 pos = (U32)((const BYTE *)literals - g_start); - if (g_start == NULL) - g_start = (const BYTE *)literals; - if ((pos > 1895000) && (pos < 1895300)) - fprintf(stderr, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n", - pos, (U32)litLength, (U32)matchCode + MINMATCH, (U32)offsetCode); - } -#endif - /* copy Literals */ - ZSTD_wildcopy(seqStorePtr->lit, literals, litLength); - seqStorePtr->lit += litLength; - - /* literal Length */ - if (litLength > 0xFFFF) - { - seqStorePtr->longLengthID = 1; - seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - } - seqStorePtr->sequences[0].litLength = (U16)litLength; - - /* match offset */ - seqStorePtr->sequences[0].offset = offsetCode + 1; - - /* match Length */ - if (matchCode > 0xFFFF) - { - seqStorePtr->longLengthID = 2; - seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); - } - seqStorePtr->sequences[0].matchLength = (U16)matchCode; - - seqStorePtr->sequences++; -} - -/*-************************************* - * Match length counter - ***************************************/ -static unsigned ZSTD_NbCommonBytes(register size_t val) -{ - if (MEM_isLittleEndian()) - { - if (MEM_64bits()) - { -#if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - _BitScanForward64(&r, (U64)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_ctzll((U64)val) >> 3); -#else - static const int DeBruijnBytePos[64] = {0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7}; - return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; -#endif - } - else - { /* 32 bits */ -#if defined(_MSC_VER) - unsigned long r = 0; - _BitScanForward(&r, (U32)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_ctz((U32)val) >> 3); -#else - static const int DeBruijnBytePos[32] = {0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1}; - return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; -#endif - } - } - else - { /* Big Endian CPU */ - if (MEM_64bits()) - { -#if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - _BitScanReverse64(&r, val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_clzll(val) >> 3); -#else - unsigned r; - const unsigned n32 = sizeof(size_t) * 4; /* calculate this way due to compiler complaining in 32-bits mode */ - if (!(val >> n32)) - { - r = 4; - } - else - { - r = 0; - val >>= n32; - } - if (!(val >> 16)) - { - r += 2; - val >>= 8; - } - else - { - val >>= 24; - } - r += (!val); - return r; -#endif - } - else - { /* 32 bits */ -#if defined(_MSC_VER) - unsigned long r = 0; - _BitScanReverse(&r, (unsigned long)val); - return (unsigned)(r >> 3); -#elif defined(__GNUC__) && (__GNUC__ >= 3) - return (__builtin_clz((U32)val) >> 3); -#else - unsigned r; - if (!(val >> 16)) - { - r = 2; - val >>= 8; - } - else - { - r = 0; - val >>= 24; - } - r += (!val); - return r; -#endif - } - } -} - -static size_t ZSTD_count(const BYTE *pIn, const BYTE *pMatch, const BYTE *const pInLimit) -{ - const BYTE *const pStart = pIn; - const BYTE *const pInLoopLimit = pInLimit - (sizeof(size_t) - 1); - - while (pIn < pInLoopLimit) - { - size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn); - if (!diff) - { - pIn += sizeof(size_t); - pMatch += sizeof(size_t); - continue; - } - pIn += ZSTD_NbCommonBytes(diff); - return (size_t)(pIn - pStart); - } - if (MEM_64bits()) - if ((pIn < (pInLimit - 3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) - { - pIn += 4; - pMatch += 4; - } - if ((pIn < (pInLimit - 1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) - { - pIn += 2; - pMatch += 2; - } - if ((pIn < pInLimit) && (*pMatch == *pIn)) - pIn++; - return (size_t)(pIn - pStart); -} - -/** ZSTD_count_2segments() : - * can count match length with `ip` & `match` in 2 different segments. - * convention : on reaching mEnd, match count continue starting from iStart - */ -static size_t ZSTD_count_2segments(const BYTE *ip, const BYTE *match, const BYTE *iEnd, const BYTE *mEnd, const BYTE *iStart) -{ - const BYTE *const vEnd = MIN(ip + (mEnd - match), iEnd); - size_t const matchLength = ZSTD_count(ip, match, vEnd); - if (match + matchLength != mEnd) - return matchLength; - return matchLength + ZSTD_count(ip + matchLength, iStart, iEnd); -} - -/*-************************************* - * Hashes - ***************************************/ -static const U32 prime3bytes = 506832829U; -static U32 ZSTD_hash3(U32 u, U32 h) { return ((u << (32 - 24)) * prime3bytes) >> (32 - h); } -MEM_STATIC size_t ZSTD_hash3Ptr(const void *ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h); } /* only in zstd_opt.h */ - -static const U32 prime4bytes = 2654435761U; -static U32 ZSTD_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32 - h); } -static size_t ZSTD_hash4Ptr(const void *ptr, U32 h) { return ZSTD_hash4(MEM_read32(ptr), h); } - -static const U64 prime5bytes = 889523592379ULL; -static size_t ZSTD_hash5(U64 u, U32 h) { return (size_t)(((u << (64 - 40)) * prime5bytes) >> (64 - h)); } -static size_t ZSTD_hash5Ptr(const void *p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h); } - -static const U64 prime6bytes = 227718039650203ULL; -static size_t ZSTD_hash6(U64 u, U32 h) { return (size_t)(((u << (64 - 48)) * prime6bytes) >> (64 - h)); } -static size_t ZSTD_hash6Ptr(const void *p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h); } - -static const U64 prime7bytes = 58295818150454627ULL; -static size_t ZSTD_hash7(U64 u, U32 h) { return (size_t)(((u << (64 - 56)) * prime7bytes) >> (64 - h)); } -static size_t ZSTD_hash7Ptr(const void *p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h); } - -static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; -static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u)*prime8bytes) >> (64 - h)); } -static size_t ZSTD_hash8Ptr(const void *p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } - -static size_t ZSTD_hashPtr(const void *p, U32 hBits, U32 mls) -{ - switch (mls) - { - default: - case 4: - return ZSTD_hash4Ptr(p, hBits); - case 5: - return ZSTD_hash5Ptr(p, hBits); - case 6: - return ZSTD_hash6Ptr(p, hBits); - case 7: - return ZSTD_hash7Ptr(p, hBits); - case 8: - return ZSTD_hash8Ptr(p, hBits); - } -} - -/*-************************************* - * Fast Scan - ***************************************/ -static void ZSTD_fillHashTable(ZSTD_CCtx *zc, const void *end, const U32 mls) -{ - U32 *const hashTable = zc->hashTable; - U32 const hBits = zc->params.cParams.hashLog; - const BYTE *const base = zc->base; - const BYTE *ip = base + zc->nextToUpdate; - const BYTE *const iend = ((const BYTE *)end) - HASH_READ_SIZE; - const size_t fastHashFillStep = 3; - - while (ip <= iend) - { - hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); - ip += fastHashFillStep; - } -} - -FORCE_INLINE -void ZSTD_compressBlock_fast_generic(ZSTD_CCtx *cctx, - const void *src, size_t srcSize, - const U32 mls) -{ - U32 *const hashTable = cctx->hashTable; - U32 const hBits = cctx->params.cParams.hashLog; - seqStore_t *seqStorePtr = &(cctx->seqStore); - const BYTE *const base = cctx->base; - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const U32 lowestIndex = cctx->dictLimit; - const BYTE *const lowest = base + lowestIndex; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - HASH_READ_SIZE; - U32 offset_1 = cctx->rep[0], offset_2 = cctx->rep[1]; - U32 offsetSaved = 0; - - /* init */ - ip += (ip == lowest); - { - U32 const maxRep = (U32)(ip - lowest); - if (offset_2 > maxRep) - offsetSaved = offset_2, offset_2 = 0; - if (offset_1 > maxRep) - offsetSaved = offset_1, offset_1 = 0; - } - - /* Main Search Loop */ - while (ip < ilimit) - { /* < instead of <=, because repcode check at (ip+1) */ - size_t mLength; - size_t const h = ZSTD_hashPtr(ip, hBits, mls); - U32 const current = (U32)(ip - base); - U32 const matchIndex = hashTable[h]; - const BYTE *match = base + matchIndex; - hashTable[h] = current; /* update hash table */ - - if ((offset_1 > 0) & (MEM_read32(ip + 1 - offset_1) == MEM_read32(ip + 1))) - { - mLength = ZSTD_count(ip + 1 + 4, ip + 1 + 4 - offset_1, iend) + 4; - ip++; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); - } - else - { - U32 offset; - if ((matchIndex <= lowestIndex) || (MEM_read32(match) != MEM_read32(ip))) - { - ip += ((ip - anchor) >> g_searchStrength) + 1; - continue; - } - mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; - offset = (U32)(ip - match); - while (((ip > anchor) & (match > lowest)) && (ip[-1] == match[-1])) - { - ip--; - match--; - mLength++; - } /* catch up */ - offset_2 = offset_1; - offset_1 = offset; - - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); - } - - /* match found */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) - { - /* Fill Table */ - hashTable[ZSTD_hashPtr(base + current + 2, hBits, mls)] = current + 2; /* here because current+2 could be > iend-8 */ - hashTable[ZSTD_hashPtr(ip - 2, hBits, mls)] = (U32)(ip - 2 - base); - /* check immediate repcode */ - while ((ip <= ilimit) && ((offset_2 > 0) & (MEM_read32(ip) == MEM_read32(ip - offset_2)))) - { - /* store sequence */ - size_t const rLength = ZSTD_count(ip + 4, ip + 4 - offset_2, iend) + 4; - { - U32 const tmpOff = offset_2; - offset_2 = offset_1; - offset_1 = tmpOff; - } /* swap offset_2 <=> offset_1 */ - hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength - MINMATCH); - ip += rLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } - } - } - - /* save reps for next block */ - cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved; - cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -static void ZSTD_compressBlock_fast(ZSTD_CCtx *ctx, - const void *src, size_t srcSize) -{ - const U32 mls = ctx->params.cParams.searchLength; - switch (mls) - { - default: - case 4: - ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); - return; - case 5: - ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); - return; - case 6: - ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); - return; - case 7: - ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); - return; - } -} - -static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, - const U32 mls) -{ - U32 *hashTable = ctx->hashTable; - const U32 hBits = ctx->params.cParams.hashLog; - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const base = ctx->base; - const BYTE *const dictBase = ctx->dictBase; - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const U32 lowestIndex = ctx->lowLimit; - const BYTE *const dictStart = dictBase + lowestIndex; - const U32 dictLimit = ctx->dictLimit; - const BYTE *const lowPrefixPtr = base + dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; - - /* Search Loop */ - while (ip < ilimit) - { /* < instead of <=, because (ip+1) */ - const size_t h = ZSTD_hashPtr(ip, hBits, mls); - const U32 matchIndex = hashTable[h]; - const BYTE *matchBase = matchIndex < dictLimit ? dictBase : base; - const BYTE *match = matchBase + matchIndex; - const U32 current = (U32)(ip - base); - const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */ - const BYTE *repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *repMatch = repBase + repIndex; - size_t mLength; - hashTable[h] = current; /* update hash table */ - - if ((((U32)((dictLimit - 1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex)) && (MEM_read32(repMatch) == MEM_read32(ip + 1))) - { - const BYTE *repMatchEnd = repIndex < dictLimit ? dictEnd : iend; - mLength = ZSTD_count_2segments(ip + 1 + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repMatchEnd, lowPrefixPtr) + EQUAL_READ32; - ip++; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); - } - else - { - if ((matchIndex < lowestIndex) || - (MEM_read32(match) != MEM_read32(ip))) - { - ip += ((ip - anchor) >> g_searchStrength) + 1; - continue; - } - { - const BYTE *matchEnd = matchIndex < dictLimit ? dictEnd : iend; - const BYTE *lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr; - U32 offset; - mLength = ZSTD_count_2segments(ip + EQUAL_READ32, match + EQUAL_READ32, iend, matchEnd, lowPrefixPtr) + EQUAL_READ32; - while (((ip > anchor) & (match > lowMatchPtr)) && (ip[-1] == match[-1])) - { - ip--; - match--; - mLength++; - } /* catch up */ - offset = current - matchIndex; - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); - } - } - - /* found a match : store it */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) - { - /* Fill Table */ - hashTable[ZSTD_hashPtr(base + current + 2, hBits, mls)] = current + 2; - hashTable[ZSTD_hashPtr(ip - 2, hBits, mls)] = (U32)(ip - 2 - base); - /* check immediate repcode */ - while (ip <= ilimit) - { - U32 const current2 = (U32)(ip - base); - U32 const repIndex2 = current2 - offset_2; - const BYTE *repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2; - if ((((U32)((dictLimit - 1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */ - && (MEM_read32(repMatch2) == MEM_read32(ip))) - { - const BYTE *const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend; - size_t repLength2 = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch2 + EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32; - U32 tmpOffset = offset_2; - offset_2 = offset_1; - offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2 - MINMATCH); - hashTable[ZSTD_hashPtr(ip, hBits, mls)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } - } - } - - /* save reps for next block */ - ctx->repToConfirm[0] = offset_1; - ctx->repToConfirm[1] = offset_2; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx *ctx, - const void *src, size_t srcSize) -{ - U32 const mls = ctx->params.cParams.searchLength; - switch (mls) - { - default: - case 4: - ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); - return; - case 5: - ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5); - return; - case 6: - ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6); - return; - case 7: - ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7); - return; - } -} - -/*-************************************* - * Double Fast - ***************************************/ -static void ZSTD_fillDoubleHashTable(ZSTD_CCtx *cctx, const void *end, const U32 mls) -{ - U32 *const hashLarge = cctx->hashTable; - U32 const hBitsL = cctx->params.cParams.hashLog; - U32 *const hashSmall = cctx->chainTable; - U32 const hBitsS = cctx->params.cParams.chainLog; - const BYTE *const base = cctx->base; - const BYTE *ip = base + cctx->nextToUpdate; - const BYTE *const iend = ((const BYTE *)end) - HASH_READ_SIZE; - const size_t fastHashFillStep = 3; - - while (ip <= iend) - { - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base); - hashLarge[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base); - ip += fastHashFillStep; - } -} - -FORCE_INLINE -void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx *cctx, - const void *src, size_t srcSize, - const U32 mls) -{ - U32 *const hashLong = cctx->hashTable; - const U32 hBitsL = cctx->params.cParams.hashLog; - U32 *const hashSmall = cctx->chainTable; - const U32 hBitsS = cctx->params.cParams.chainLog; - seqStore_t *seqStorePtr = &(cctx->seqStore); - const BYTE *const base = cctx->base; - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const U32 lowestIndex = cctx->dictLimit; - const BYTE *const lowest = base + lowestIndex; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - HASH_READ_SIZE; - U32 offset_1 = cctx->rep[0], offset_2 = cctx->rep[1]; - U32 offsetSaved = 0; - - /* init */ - ip += (ip == lowest); - { - U32 const maxRep = (U32)(ip - lowest); - if (offset_2 > maxRep) - offsetSaved = offset_2, offset_2 = 0; - if (offset_1 > maxRep) - offsetSaved = offset_1, offset_1 = 0; - } - - /* Main Search Loop */ - while (ip < ilimit) - { /* < instead of <=, because repcode check at (ip+1) */ - size_t mLength; - size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8); - size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); - U32 const current = (U32)(ip - base); - U32 const matchIndexL = hashLong[h2]; - U32 const matchIndexS = hashSmall[h]; - const BYTE *matchLong = base + matchIndexL; - const BYTE *match = base + matchIndexS; - hashLong[h2] = hashSmall[h] = current; /* update hash tables */ - - if ((offset_1 > 0) & (MEM_read32(ip + 1 - offset_1) == MEM_read32(ip + 1))) - { /* note : by construction, offset_1 <= current */ - mLength = ZSTD_count(ip + 1 + 4, ip + 1 + 4 - offset_1, iend) + 4; - ip++; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); - } - else - { - U32 offset; - if ((matchIndexL > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) - { - mLength = ZSTD_count(ip + 8, matchLong + 8, iend) + 8; - offset = (U32)(ip - matchLong); - while (((ip > anchor) & (matchLong > lowest)) && (ip[-1] == matchLong[-1])) - { - ip--; - matchLong--; - mLength++; - } /* catch up */ - } - else if ((matchIndexS > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) - { - size_t const h3 = ZSTD_hashPtr(ip + 1, hBitsL, 8); - U32 const matchIndex3 = hashLong[h3]; - const BYTE *match3 = base + matchIndex3; - hashLong[h3] = current + 1; - if ((matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip + 1))) - { - mLength = ZSTD_count(ip + 9, match3 + 8, iend) + 8; - ip++; - offset = (U32)(ip - match3); - while (((ip > anchor) & (match3 > lowest)) && (ip[-1] == match3[-1])) - { - ip--; - match3--; - mLength++; - } /* catch up */ - } - else - { - mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; - offset = (U32)(ip - match); - while (((ip > anchor) & (match > lowest)) && (ip[-1] == match[-1])) - { - ip--; - match--; - mLength++; - } /* catch up */ - } - } - else - { - ip += ((ip - anchor) >> g_searchStrength) + 1; - continue; - } - - offset_2 = offset_1; - offset_1 = offset; - - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); - } - - /* match found */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) - { - /* Fill Table */ - hashLong[ZSTD_hashPtr(base + current + 2, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(base + current + 2, hBitsS, mls)] = current + 2; /* here because current+2 could be > iend-8 */ - hashLong[ZSTD_hashPtr(ip - 2, hBitsL, 8)] = - hashSmall[ZSTD_hashPtr(ip - 2, hBitsS, mls)] = (U32)(ip - 2 - base); - - /* check immediate repcode */ - while ((ip <= ilimit) && ((offset_2 > 0) & (MEM_read32(ip) == MEM_read32(ip - offset_2)))) - { - /* store sequence */ - size_t const rLength = ZSTD_count(ip + 4, ip + 4 - offset_2, iend) + 4; - { - U32 const tmpOff = offset_2; - offset_2 = offset_1; - offset_1 = tmpOff; - } /* swap offset_2 <=> offset_1 */ - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip - base); - hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip - base); - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rLength - MINMATCH); - ip += rLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } - } - } - - /* save reps for next block */ - cctx->repToConfirm[0] = offset_1 ? offset_1 : offsetSaved; - cctx->repToConfirm[1] = offset_2 ? offset_2 : offsetSaved; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - const U32 mls = ctx->params.cParams.searchLength; - switch (mls) - { - default: - case 4: - ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); - return; - case 5: - ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 5); - return; - case 6: - ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 6); - return; - case 7: - ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 7); - return; - } -} - -static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, - const U32 mls) -{ - U32 *const hashLong = ctx->hashTable; - U32 const hBitsL = ctx->params.cParams.hashLog; - U32 *const hashSmall = ctx->chainTable; - U32 const hBitsS = ctx->params.cParams.chainLog; - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const base = ctx->base; - const BYTE *const dictBase = ctx->dictBase; - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const U32 lowestIndex = ctx->lowLimit; - const BYTE *const dictStart = dictBase + lowestIndex; - const U32 dictLimit = ctx->dictLimit; - const BYTE *const lowPrefixPtr = base + dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; - - /* Search Loop */ - while (ip < ilimit) - { /* < instead of <=, because (ip+1) */ - const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls); - const U32 matchIndex = hashSmall[hSmall]; - const BYTE *matchBase = matchIndex < dictLimit ? dictBase : base; - const BYTE *match = matchBase + matchIndex; - - const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8); - const U32 matchLongIndex = hashLong[hLong]; - const BYTE *matchLongBase = matchLongIndex < dictLimit ? dictBase : base; - const BYTE *matchLong = matchLongBase + matchLongIndex; - - const U32 current = (U32)(ip - base); - const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */ - const BYTE *repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *repMatch = repBase + repIndex; - size_t mLength; - hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */ - - if ((((U32)((dictLimit - 1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > lowestIndex)) && (MEM_read32(repMatch) == MEM_read32(ip + 1))) - { - const BYTE *repMatchEnd = repIndex < dictLimit ? dictEnd : iend; - mLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, lowPrefixPtr) + 4; - ip++; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, 0, mLength - MINMATCH); - } - else - { - if ((matchLongIndex > lowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) - { - const BYTE *matchEnd = matchLongIndex < dictLimit ? dictEnd : iend; - const BYTE *lowMatchPtr = matchLongIndex < dictLimit ? dictStart : lowPrefixPtr; - U32 offset; - mLength = ZSTD_count_2segments(ip + 8, matchLong + 8, iend, matchEnd, lowPrefixPtr) + 8; - offset = current - matchLongIndex; - while (((ip > anchor) & (matchLong > lowMatchPtr)) && (ip[-1] == matchLong[-1])) - { - ip--; - matchLong--; - mLength++; - } /* catch up */ - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); - } - else if ((matchIndex > lowestIndex) && (MEM_read32(match) == MEM_read32(ip))) - { - size_t const h3 = ZSTD_hashPtr(ip + 1, hBitsL, 8); - U32 const matchIndex3 = hashLong[h3]; - const BYTE *const match3Base = matchIndex3 < dictLimit ? dictBase : base; - const BYTE *match3 = match3Base + matchIndex3; - U32 offset; - hashLong[h3] = current + 1; - if ((matchIndex3 > lowestIndex) && (MEM_read64(match3) == MEM_read64(ip + 1))) - { - const BYTE *matchEnd = matchIndex3 < dictLimit ? dictEnd : iend; - const BYTE *lowMatchPtr = matchIndex3 < dictLimit ? dictStart : lowPrefixPtr; - mLength = ZSTD_count_2segments(ip + 9, match3 + 8, iend, matchEnd, lowPrefixPtr) + 8; - ip++; - offset = current + 1 - matchIndex3; - while (((ip > anchor) & (match3 > lowMatchPtr)) && (ip[-1] == match3[-1])) - { - ip--; - match3--; - mLength++; - } /* catch up */ - } - else - { - const BYTE *matchEnd = matchIndex < dictLimit ? dictEnd : iend; - const BYTE *lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr; - mLength = ZSTD_count_2segments(ip + 4, match + 4, iend, matchEnd, lowPrefixPtr) + 4; - offset = current - matchIndex; - while (((ip > anchor) & (match > lowMatchPtr)) && (ip[-1] == match[-1])) - { - ip--; - match--; - mLength++; - } /* catch up */ - } - offset_2 = offset_1; - offset_1 = offset; - ZSTD_storeSeq(seqStorePtr, ip - anchor, anchor, offset + ZSTD_REP_MOVE, mLength - MINMATCH); - } - else - { - ip += ((ip - anchor) >> g_searchStrength) + 1; - continue; - } - } - - /* found a match : store it */ - ip += mLength; - anchor = ip; - - if (ip <= ilimit) - { - /* Fill Table */ - hashSmall[ZSTD_hashPtr(base + current + 2, hBitsS, mls)] = current + 2; - hashLong[ZSTD_hashPtr(base + current + 2, hBitsL, 8)] = current + 2; - hashSmall[ZSTD_hashPtr(ip - 2, hBitsS, mls)] = (U32)(ip - 2 - base); - hashLong[ZSTD_hashPtr(ip - 2, hBitsL, 8)] = (U32)(ip - 2 - base); - /* check immediate repcode */ - while (ip <= ilimit) - { - U32 const current2 = (U32)(ip - base); - U32 const repIndex2 = current2 - offset_2; - const BYTE *repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2; - if ((((U32)((dictLimit - 1) - repIndex2) >= 3) & (repIndex2 > lowestIndex)) /* intentional overflow */ - && (MEM_read32(repMatch2) == MEM_read32(ip))) - { - const BYTE *const repEnd2 = repIndex2 < dictLimit ? dictEnd : iend; - size_t const repLength2 = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch2 + EQUAL_READ32, iend, repEnd2, lowPrefixPtr) + EQUAL_READ32; - U32 tmpOffset = offset_2; - offset_2 = offset_1; - offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */ - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, repLength2 - MINMATCH); - hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2; - hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2; - ip += repLength2; - anchor = ip; - continue; - } - break; - } - } - } - - /* save reps for next block */ - ctx->repToConfirm[0] = offset_1; - ctx->repToConfirm[1] = offset_2; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx *ctx, - const void *src, size_t srcSize) -{ - U32 const mls = ctx->params.cParams.searchLength; - switch (mls) - { - default: - case 4: - ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); - return; - case 5: - ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 5); - return; - case 6: - ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 6); - return; - case 7: - ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 7); - return; - } -} - -/*-************************************* - * Binary Tree search - ***************************************/ -/** ZSTD_insertBt1() : add one or multiple positions to tree. - * ip : assumed <= iend-8 . - * @return : nb of positions added */ -static U32 ZSTD_insertBt1(ZSTD_CCtx *zc, const BYTE *const ip, const U32 mls, const BYTE *const iend, U32 nbCompares, - U32 extDict) -{ - U32 *const hashTable = zc->hashTable; - U32 const hashLog = zc->params.cParams.hashLog; - size_t const h = ZSTD_hashPtr(ip, hashLog, mls); - U32 *const bt = zc->chainTable; - U32 const btLog = zc->params.cParams.chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - U32 matchIndex = hashTable[h]; - size_t commonLengthSmaller = 0, commonLengthLarger = 0; - const BYTE *const base = zc->base; - const BYTE *const dictBase = zc->dictBase; - const U32 dictLimit = zc->dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const prefixStart = base + dictLimit; - const BYTE *match; - const U32 current = (U32)(ip - base); - const U32 btLow = btMask >= current ? 0 : current - btMask; - U32 *smallerPtr = bt + 2 * (current & btMask); - U32 *largerPtr = smallerPtr + 1; - U32 dummy32; /* to be nullified at the end */ - U32 const windowLow = zc->lowLimit; - U32 matchEndIdx = current + 8; - size_t bestLength = 8; -#ifdef ZSTD_C_PREDICT - U32 predictedSmall = *(bt + 2 * ((current - 1) & btMask) + 0); - U32 predictedLarge = *(bt + 2 * ((current - 1) & btMask) + 1); - predictedSmall += (predictedSmall > 0); - predictedLarge += (predictedLarge > 0); -#endif /* ZSTD_C_PREDICT */ - - hashTable[h] = current; /* Update Hash Table */ - - while (nbCompares-- && (matchIndex > windowLow)) - { - U32 *const nextPtr = bt + 2 * (matchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - -#ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */ - const U32 *predictPtr = bt + 2 * ((matchIndex - 1) & btMask); /* written this way, as bt is a roll buffer */ - if (matchIndex == predictedSmall) - { - /* no need to check length, result known */ - *smallerPtr = matchIndex; - if (matchIndex <= btLow) - { - smallerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ - matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - predictedSmall = predictPtr[1] + (predictPtr[1] > 0); - continue; - } - if (matchIndex == predictedLarge) - { - *largerPtr = matchIndex; - if (matchIndex <= btLow) - { - largerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - predictedLarge = predictPtr[0] + (predictPtr[0] > 0); - continue; - } -#endif - if ((!extDict) || (matchIndex + matchLength >= dictLimit)) - { - match = base + matchIndex; - if (match[matchLength] == ip[matchLength]) - matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iend) + 1; - } - else - { - match = dictBase + matchIndex; - matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iend, dictEnd, prefixStart); - if (matchIndex + matchLength >= dictLimit) - match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ - } - - if (matchLength > bestLength) - { - bestLength = matchLength; - if (matchLength > matchEndIdx - matchIndex) - matchEndIdx = matchIndex + (U32)matchLength; - } - - if (ip + matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt the tree */ - - if (match[matchLength] < ip[matchLength]) - { /* necessarily within correct buffer */ - /* match is smaller than current */ - *smallerPtr = matchIndex; /* update smaller idx */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) - { - smallerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ - matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } - else - { - /* match is larger than current */ - *largerPtr = matchIndex; - commonLengthLarger = matchLength; - if (matchIndex <= btLow) - { - largerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - } - } - - *smallerPtr = *largerPtr = 0; - if (bestLength > 384) - return MIN(192, (U32)(bestLength - 384)); /* speed optimization */ - if (matchEndIdx > current + 8) - return matchEndIdx - current - 8; - return 1; -} - -static size_t ZSTD_insertBtAndFindBestMatch( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iend, - size_t *offsetPtr, - U32 nbCompares, const U32 mls, - U32 extDict) -{ - U32 *const hashTable = zc->hashTable; - U32 const hashLog = zc->params.cParams.hashLog; - size_t const h = ZSTD_hashPtr(ip, hashLog, mls); - U32 *const bt = zc->chainTable; - U32 const btLog = zc->params.cParams.chainLog - 1; - U32 const btMask = (1 << btLog) - 1; - U32 matchIndex = hashTable[h]; - size_t commonLengthSmaller = 0, commonLengthLarger = 0; - const BYTE *const base = zc->base; - const BYTE *const dictBase = zc->dictBase; - const U32 dictLimit = zc->dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const prefixStart = base + dictLimit; - const U32 current = (U32)(ip - base); - const U32 btLow = btMask >= current ? 0 : current - btMask; - const U32 windowLow = zc->lowLimit; - U32 *smallerPtr = bt + 2 * (current & btMask); - U32 *largerPtr = bt + 2 * (current & btMask) + 1; - U32 matchEndIdx = current + 8; - U32 dummy32; /* to be nullified at the end */ - size_t bestLength = 0; - - hashTable[h] = current; /* Update Hash Table */ - - while (nbCompares-- && (matchIndex > windowLow)) - { - U32 *const nextPtr = bt + 2 * (matchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - const BYTE *match; - - if ((!extDict) || (matchIndex + matchLength >= dictLimit)) - { - match = base + matchIndex; - if (match[matchLength] == ip[matchLength]) - matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iend) + 1; - } - else - { - match = dictBase + matchIndex; - matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iend, dictEnd, prefixStart); - if (matchIndex + matchLength >= dictLimit) - match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ - } - - if (matchLength > bestLength) - { - if (matchLength > matchEndIdx - matchIndex) - matchEndIdx = matchIndex + (U32)matchLength; - if ((4 * (int)(matchLength - bestLength)) > (int)(ZSTD_highbit32(current - matchIndex + 1) - ZSTD_highbit32((U32)offsetPtr[0] + 1))) - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; - if (ip + matchLength == iend) /* equal : no way to know if inf or sup */ - break; /* drop, to guarantee consistency (miss a little bit of compression) */ - } - - if (match[matchLength] < ip[matchLength]) - { - /* match is smaller than current */ - *smallerPtr = matchIndex; /* update smaller idx */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) - { - smallerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ - matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } - else - { - /* match is larger than current */ - *largerPtr = matchIndex; - commonLengthLarger = matchLength; - if (matchIndex <= btLow) - { - largerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - } - } - - *smallerPtr = *largerPtr = 0; - - zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current + 1; - return bestLength; -} - -static void ZSTD_updateTree(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iend, const U32 nbCompares, const U32 mls) -{ - const BYTE *const base = zc->base; - const U32 target = (U32)(ip - base); - U32 idx = zc->nextToUpdate; - - while (idx < target) - idx += ZSTD_insertBt1(zc, base + idx, mls, iend, nbCompares, 0); -} - -/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */ -static size_t ZSTD_BtFindBestMatch( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 mls) -{ - if (ip < zc->base + zc->nextToUpdate) - return 0; /* skipped area */ - ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls); - return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 0); -} - -static size_t ZSTD_BtFindBestMatch_selectMLS( - ZSTD_CCtx *zc, /* Index table will be updated */ - const BYTE *ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 matchLengthSearch) -{ - switch (matchLengthSearch) - { - default: - case 4: - return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); - case 5: - return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); - case 6: - return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); - } -} - -static void ZSTD_updateTree_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iend, const U32 nbCompares, const U32 mls) -{ - const BYTE *const base = zc->base; - const U32 target = (U32)(ip - base); - U32 idx = zc->nextToUpdate; - - while (idx < target) - idx += ZSTD_insertBt1(zc, base + idx, mls, iend, nbCompares, 1); -} - -/** Tree updater, providing best match */ -static size_t ZSTD_BtFindBestMatch_extDict( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 mls) -{ - if (ip < zc->base + zc->nextToUpdate) - return 0; /* skipped area */ - ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls); - return ZSTD_insertBtAndFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, mls, 1); -} - -static size_t ZSTD_BtFindBestMatch_selectMLS_extDict( - ZSTD_CCtx *zc, /* Index table will be updated */ - const BYTE *ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 matchLengthSearch) -{ - switch (matchLengthSearch) - { - default: - case 4: - return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4); - case 5: - return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5); - case 6: - return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6); - } -} - -/* ********************************* - * Hash Chain - ***********************************/ -#define NEXT_IN_CHAIN(d, mask) chainTable[(d) & mask] - -/* Update chains up to ip (excluded) - Assumption : always within prefix (i.e. not within extDict) */ -FORCE_INLINE -U32 ZSTD_insertAndFindFirstIndex(ZSTD_CCtx *zc, const BYTE *ip, U32 mls) -{ - U32 *const hashTable = zc->hashTable; - const U32 hashLog = zc->params.cParams.hashLog; - U32 *const chainTable = zc->chainTable; - const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1; - const BYTE *const base = zc->base; - const U32 target = (U32)(ip - base); - U32 idx = zc->nextToUpdate; - - while (idx < target) - { /* catch up */ - size_t const h = ZSTD_hashPtr(base + idx, hashLog, mls); - NEXT_IN_CHAIN(idx, chainMask) = hashTable[h]; - hashTable[h] = idx; - idx++; - } - - zc->nextToUpdate = target; - return hashTable[ZSTD_hashPtr(ip, hashLog, mls)]; -} - -FORCE_INLINE /* inlining is important to hardwire a hot branch (template emulation) */ - size_t - ZSTD_HcFindBestMatch_generic( - ZSTD_CCtx *zc, /* Index table will be updated */ - const BYTE *const ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 mls, const U32 extDict) -{ - U32 *const chainTable = zc->chainTable; - const U32 chainSize = (1 << zc->params.cParams.chainLog); - const U32 chainMask = chainSize - 1; - const BYTE *const base = zc->base; - const BYTE *const dictBase = zc->dictBase; - const U32 dictLimit = zc->dictLimit; - const BYTE *const prefixStart = base + dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const U32 lowLimit = zc->lowLimit; - const U32 current = (U32)(ip - base); - const U32 minChain = current > chainSize ? current - chainSize : 0; - int nbAttempts = maxNbAttempts; - size_t ml = EQUAL_READ32 - 1; - - /* HC4 match finder */ - U32 matchIndex = ZSTD_insertAndFindFirstIndex(zc, ip, mls); - - for (; (matchIndex > lowLimit) & (nbAttempts > 0); nbAttempts--) - { - const BYTE *match; - size_t currentMl = 0; - if ((!extDict) || matchIndex >= dictLimit) - { - match = base + matchIndex; - if (match[ml] == ip[ml]) /* potentially better */ - currentMl = ZSTD_count(ip, match, iLimit); - } - else - { - match = dictBase + matchIndex; - if (MEM_read32(match) == MEM_read32(ip)) /* assumption : matchIndex <= dictLimit-4 (by table construction) */ - currentMl = ZSTD_count_2segments(ip + EQUAL_READ32, match + EQUAL_READ32, iLimit, dictEnd, prefixStart) + EQUAL_READ32; - } - - /* save best solution */ - if (currentMl > ml) - { - ml = currentMl; - *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; - if (ip + currentMl == iLimit) - break; /* best possible, and avoid read overflow*/ - } - - if (matchIndex <= minChain) - break; - matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); - } - - return ml; -} - -FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS( - ZSTD_CCtx *zc, - const BYTE *ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 matchLengthSearch) -{ - switch (matchLengthSearch) - { - default: - case 4: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 0); - case 5: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 0); - case 6: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0); - } -} - -FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS( - ZSTD_CCtx *zc, - const BYTE *ip, const BYTE *const iLimit, - size_t *offsetPtr, - const U32 maxNbAttempts, const U32 matchLengthSearch) -{ - switch (matchLengthSearch) - { - default: - case 4: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4, 1); - case 5: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5, 1); - case 6: - return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1); - } -} - -/* ******************************* - * Common parser - lazy strategy - *********************************/ -FORCE_INLINE -void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, - const U32 searchMethod, const U32 depth) -{ - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - const BYTE *const base = ctx->base + ctx->dictLimit; - - U32 const maxSearches = 1 << ctx->params.cParams.searchLog; - U32 const mls = ctx->params.cParams.searchLength; - - typedef size_t (*searchMax_f)(ZSTD_CCtx *zc, const BYTE *ip, const BYTE *iLimit, - size_t *offsetPtr, - U32 maxNbAttempts, U32 matchLengthSearch); - searchMax_f const searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS : ZSTD_HcFindBestMatch_selectMLS; - U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1], savedOffset = 0; - - /* init */ - ip += (ip == base); - ctx->nextToUpdate3 = ctx->nextToUpdate; - { - U32 const maxRep = (U32)(ip - base); - if (offset_2 > maxRep) - savedOffset = offset_2, offset_2 = 0; - if (offset_1 > maxRep) - savedOffset = offset_1, offset_1 = 0; - } - - /* Match Loop */ - while (ip < ilimit) - { - size_t matchLength = 0; - size_t offset = 0; - const BYTE *start = ip + 1; - - /* check repCode */ - if ((offset_1 > 0) & (MEM_read32(ip + 1) == MEM_read32(ip + 1 - offset_1))) - { - /* repcode : we take it */ - matchLength = ZSTD_count(ip + 1 + EQUAL_READ32, ip + 1 + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; - if (depth == 0) - goto _storeSequence; - } - - /* first search (depth 0) */ - { - size_t offsetFound = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls); - if (ml2 > matchLength) - matchLength = ml2, start = ip, offset = offsetFound; - } - - if (matchLength < EQUAL_READ32) - { - ip += ((ip - anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ - continue; - } - - /* let's try to find a better solution */ - if (depth >= 1) - while (ip < ilimit) - { - ip++; - if ((offset) && ((offset_1 > 0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) - { - size_t const mlRep = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; - int const gain2 = (int)(mlRep * 3); - int const gain1 = (int)(matchLength * 3 - ZSTD_highbit32((U32)offset + 1) + 1); - if ((mlRep >= EQUAL_READ32) && (gain2 > gain1)) - matchLength = mlRep, offset = 0, start = ip; - } - { - size_t offset2 = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); - int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ - int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 4); - if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) - { - matchLength = ml2, offset = offset2, start = ip; - continue; /* search a better one */ - } - } - - /* let's find an even better one */ - if ((depth == 2) && (ip < ilimit)) - { - ip++; - if ((offset) && ((offset_1 > 0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) - { - size_t const ml2 = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_1, iend) + EQUAL_READ32; - int const gain2 = (int)(ml2 * 4); - int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 1); - if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) - matchLength = ml2, offset = 0, start = ip; - } - { - size_t offset2 = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); - int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ - int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 7); - if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) - { - matchLength = ml2, offset = offset2, start = ip; - continue; - } - } - } - break; /* nothing found : store previous solution */ - } - - /* catch up */ - if (offset) - { - while ((start > anchor) && (start > base + offset - ZSTD_REP_MOVE) && (start[-1] == start[-1 - offset + ZSTD_REP_MOVE])) /* only search for offset within prefix */ - { - start--; - matchLength++; - } - offset_2 = offset_1; - offset_1 = (U32)(offset - ZSTD_REP_MOVE); - } - - /* store sequence */ - _storeSequence: - { - size_t const litLength = start - anchor; - ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength - MINMATCH); - anchor = ip = start + matchLength; - } - - /* check immediate repcode */ - while ((ip <= ilimit) && ((offset_2 > 0) & (MEM_read32(ip) == MEM_read32(ip - offset_2)))) - { - /* store sequence */ - matchLength = ZSTD_count(ip + EQUAL_READ32, ip + EQUAL_READ32 - offset_2, iend) + EQUAL_READ32; - offset = offset_2; - offset_2 = offset_1; - offset_1 = (U32)offset; /* swap repcodes */ - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength - MINMATCH); - ip += matchLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } - } - - /* Save reps for next block */ - ctx->repToConfirm[0] = offset_1 ? offset_1 : savedOffset; - ctx->repToConfirm[1] = offset_2 ? offset_2 : savedOffset; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2); -} - -static void ZSTD_compressBlock_lazy2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2); -} - -static void ZSTD_compressBlock_lazy(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1); -} - -static void ZSTD_compressBlock_greedy(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0); -} - -FORCE_INLINE -void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, - const U32 searchMethod, const U32 depth) -{ - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - const BYTE *const base = ctx->base; - const U32 dictLimit = ctx->dictLimit; - const U32 lowestIndex = ctx->lowLimit; - const BYTE *const prefixStart = base + dictLimit; - const BYTE *const dictBase = ctx->dictBase; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const dictStart = dictBase + ctx->lowLimit; - - const U32 maxSearches = 1 << ctx->params.cParams.searchLog; - const U32 mls = ctx->params.cParams.searchLength; - - typedef size_t (*searchMax_f)(ZSTD_CCtx *zc, const BYTE *ip, const BYTE *iLimit, - size_t *offsetPtr, - U32 maxNbAttempts, U32 matchLengthSearch); - searchMax_f searchMax = searchMethod ? ZSTD_BtFindBestMatch_selectMLS_extDict : ZSTD_HcFindBestMatch_extDict_selectMLS; - - U32 offset_1 = ctx->rep[0], offset_2 = ctx->rep[1]; - - /* init */ - ctx->nextToUpdate3 = ctx->nextToUpdate; - ip += (ip == prefixStart); - - /* Match Loop */ - while (ip < ilimit) - { - size_t matchLength = 0; - size_t offset = 0; - const BYTE *start = ip + 1; - U32 current = (U32)(ip - base); - - /* check repCode */ - { - const U32 repIndex = (U32)(current + 1 - offset_1); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - if (MEM_read32(ip + 1) == MEM_read32(repMatch)) - { - /* repcode detected we should take it */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip + 1 + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; - if (depth == 0) - goto _storeSequence; - } - } - - /* first search (depth 0) */ - { - size_t offsetFound = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls); - if (ml2 > matchLength) - matchLength = ml2, start = ip, offset = offsetFound; - } - - if (matchLength < EQUAL_READ32) - { - ip += ((ip - anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ - continue; - } - - /* let's try to find a better solution */ - if (depth >= 1) - while (ip < ilimit) - { - ip++; - current++; - /* check repCode */ - if (offset) - { - const U32 repIndex = (U32)(current - offset_1); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) - { - /* repcode detected */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - size_t const repLength = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; - int const gain2 = (int)(repLength * 3); - int const gain1 = (int)(matchLength * 3 - ZSTD_highbit32((U32)offset + 1) + 1); - if ((repLength >= EQUAL_READ32) && (gain2 > gain1)) - matchLength = repLength, offset = 0, start = ip; - } - } - - /* search match, depth 1 */ - { - size_t offset2 = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); - int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ - int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 4); - if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) - { - matchLength = ml2, offset = offset2, start = ip; - continue; /* search a better one */ - } - } - - /* let's find an even better one */ - if ((depth == 2) && (ip < ilimit)) - { - ip++; - current++; - /* check repCode */ - if (offset) - { - const U32 repIndex = (U32)(current - offset_1); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) - { - /* repcode detected */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - size_t repLength = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; - int gain2 = (int)(repLength * 4); - int gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 1); - if ((repLength >= EQUAL_READ32) && (gain2 > gain1)) - matchLength = repLength, offset = 0, start = ip; - } - } - - /* search match, depth 2 */ - { - size_t offset2 = 99999999; - size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls); - int const gain2 = (int)(ml2 * 4 - ZSTD_highbit32((U32)offset2 + 1)); /* raw approx */ - int const gain1 = (int)(matchLength * 4 - ZSTD_highbit32((U32)offset + 1) + 7); - if ((ml2 >= EQUAL_READ32) && (gain2 > gain1)) - { - matchLength = ml2, offset = offset2, start = ip; - continue; - } - } - } - break; /* nothing found : store previous solution */ - } - - /* catch up */ - if (offset) - { - U32 const matchIndex = (U32)((start - base) - (offset - ZSTD_REP_MOVE)); - const BYTE *match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex; - const BYTE *const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart; - while ((start > anchor) && (match > mStart) && (start[-1] == match[-1])) - { - start--; - match--; - matchLength++; - } /* catch up */ - offset_2 = offset_1; - offset_1 = (U32)(offset - ZSTD_REP_MOVE); - } - - /* store sequence */ - _storeSequence: - { - size_t const litLength = start - anchor; - ZSTD_storeSeq(seqStorePtr, litLength, anchor, (U32)offset, matchLength - MINMATCH); - anchor = ip = start + matchLength; - } - - /* check immediate repcode */ - while (ip <= ilimit) - { - const U32 repIndex = (U32)((ip - base) - offset_2); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - if (MEM_read32(ip) == MEM_read32(repMatch)) - { - /* repcode detected we should take it */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - matchLength = ZSTD_count_2segments(ip + EQUAL_READ32, repMatch + EQUAL_READ32, iend, repEnd, prefixStart) + EQUAL_READ32; - offset = offset_2; - offset_2 = offset_1; - offset_1 = (U32)offset; /* swap offset history */ - ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength - MINMATCH); - ip += matchLength; - anchor = ip; - continue; /* faster when present ... (?) */ - } - break; - } - } - - /* Save reps for next block */ - ctx->repToConfirm[0] = offset_1; - ctx->repToConfirm[1] = offset_2; - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0); -} - -static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1); -} - -static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2); -} - -static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ - ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2); -} - -/* The optimal parser */ -#include "zstd_opt.h" - -static void ZSTD_compressBlock_btopt(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ -#ifdef ZSTD_OPT_H_91842398743 - ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 0); -#else - (void)ctx; - (void)src; - (void)srcSize; - return; -#endif -} - -static void ZSTD_compressBlock_btopt2(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ -#ifdef ZSTD_OPT_H_91842398743 - ZSTD_compressBlock_opt_generic(ctx, src, srcSize, 1); -#else - (void)ctx; - (void)src; - (void)srcSize; - return; -#endif -} - -static void ZSTD_compressBlock_btopt_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ -#ifdef ZSTD_OPT_H_91842398743 - ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 0); -#else - (void)ctx; - (void)src; - (void)srcSize; - return; -#endif -} - -static void ZSTD_compressBlock_btopt2_extDict(ZSTD_CCtx *ctx, const void *src, size_t srcSize) -{ -#ifdef ZSTD_OPT_H_91842398743 - ZSTD_compressBlock_opt_extDict_generic(ctx, src, srcSize, 1); -#else - (void)ctx; - (void)src; - (void)srcSize; - return; -#endif -} - -typedef void (*ZSTD_blockCompressor)(ZSTD_CCtx *ctx, const void *src, size_t srcSize); - -static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict) -{ - static const ZSTD_blockCompressor blockCompressor[2][8] = { - {ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2, ZSTD_compressBlock_btopt, ZSTD_compressBlock_btopt2}, - {ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict, ZSTD_compressBlock_lazy_extDict, ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict, ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btopt2_extDict}}; - - return blockCompressor[extDict][(U32)strat]; -} - -static size_t ZSTD_compressBlock_internal(ZSTD_CCtx *zc, void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit); - const BYTE *const base = zc->base; - const BYTE *const istart = (const BYTE *)src; - const U32 current = (U32)(istart - base); - if (srcSize < MIN_CBLOCK_SIZE + ZSTD_blockHeaderSize + 1) - return 0; /* don't even attempt compression below a certain srcSize */ - ZSTD_resetSeqStore(&(zc->seqStore)); - if (current > zc->nextToUpdate + 384) - zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* update tree not updated after finding very long rep matches */ - blockCompressor(zc, src, srcSize); - return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize); -} - -/*! ZSTD_compress_generic() : - * Compress a chunk of data into one or multiple blocks. - * All blocks will be terminated, all input will be consumed. - * Function will issue an error if there is not enough `dstCapacity` to hold the compressed content. - * Frame is supposed already started (header already produced) - * @return : compressed size, or an error code - */ -static size_t ZSTD_compress_generic(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - U32 lastFrameChunk) -{ - size_t blockSize = cctx->blockSize; - size_t remaining = srcSize; - const BYTE *ip = (const BYTE *)src; - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - U32 const maxDist = 1 << cctx->params.cParams.windowLog; - - if (cctx->params.fParams.checksumFlag && srcSize) - XXH64_update(&cctx->xxhState, src, srcSize); - - while (remaining) - { - U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); - size_t cSize; - - if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) - return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */ - if (remaining < blockSize) - blockSize = remaining; - - /* preemptive overflow correction */ - if (cctx->lowLimit > (3U << 29)) - { - U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->params.cParams.hashLog, cctx->params.cParams.strategy)) - 1; - U32 const current = (U32)(ip - cctx->base); - U32 const newCurrent = (current & cycleMask) + (1 << cctx->params.cParams.windowLog); - U32 const correction = current - newCurrent; - ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30); - ZSTD_reduceIndex(cctx, correction); - cctx->base += correction; - cctx->dictBase += correction; - cctx->lowLimit -= correction; - cctx->dictLimit -= correction; - if (cctx->nextToUpdate < correction) - cctx->nextToUpdate = 0; - else - cctx->nextToUpdate -= correction; - } - - if ((U32)(ip + blockSize - cctx->base) > cctx->loadedDictEnd + maxDist) - { - /* enforce maxDist */ - U32 const newLowLimit = (U32)(ip + blockSize - cctx->base) - maxDist; - if (cctx->lowLimit < newLowLimit) - cctx->lowLimit = newLowLimit; - if (cctx->dictLimit < cctx->lowLimit) - cctx->dictLimit = cctx->lowLimit; - } - - cSize = ZSTD_compressBlock_internal(cctx, op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize, ip, blockSize); - if (ZSTD_isError(cSize)) - return cSize; - - if (cSize == 0) - { /* block is not compressible */ - U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw) << 1) + (U32)(blockSize << 3); - if (blockSize + ZSTD_blockHeaderSize > dstCapacity) - return ERROR(dstSize_tooSmall); - MEM_writeLE32(op, cBlockHeader24); /* no pb, 4th byte will be overwritten */ - memcpy(op + ZSTD_blockHeaderSize, ip, blockSize); - cSize = ZSTD_blockHeaderSize + blockSize; - } - else - { - U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed) << 1) + (U32)(cSize << 3); - MEM_writeLE24(op, cBlockHeader24); - cSize += ZSTD_blockHeaderSize; - } - - remaining -= blockSize; - dstCapacity -= cSize; - ip += blockSize; - op += cSize; - } - - if (lastFrameChunk && (op > ostart)) - cctx->stage = ZSTDcs_ending; - return op - ostart; -} - -static size_t ZSTD_writeFrameHeader(void *dst, size_t dstCapacity, - ZSTD_parameters params, U64 pledgedSrcSize, U32 dictID) -{ - BYTE *const op = (BYTE *)dst; - U32 const dictIDSizeCode = (dictID > 0) + (dictID >= 256) + (dictID >= 65536); /* 0-3 */ - U32 const checksumFlag = params.fParams.checksumFlag > 0; - U32 const windowSize = 1U << params.cParams.windowLog; - U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize); - BYTE const windowLogByte = (BYTE)((params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3); - U32 const fcsCode = params.fParams.contentSizeFlag ? (pledgedSrcSize >= 256) + (pledgedSrcSize >= 65536 + 256) + (pledgedSrcSize >= 0xFFFFFFFFU) : /* 0-3 */ - 0; - BYTE const frameHeaderDecriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag << 2) + (singleSegment << 5) + (fcsCode << 6)); - size_t pos; - - if (dstCapacity < ZSTD_frameHeaderSize_max) - return ERROR(dstSize_tooSmall); - - MEM_writeLE32(dst, ZSTD_MAGICNUMBER); - op[4] = frameHeaderDecriptionByte; - pos = 5; - if (!singleSegment) - op[pos++] = windowLogByte; - switch (dictIDSizeCode) - { - default: /* impossible */ - case 0: - break; - case 1: - op[pos] = (BYTE)(dictID); - pos++; - break; - case 2: - MEM_writeLE16(op + pos, (U16)dictID); - pos += 2; - break; - case 3: - MEM_writeLE32(op + pos, dictID); - pos += 4; - break; - } - switch (fcsCode) - { - default: /* impossible */ - case 0: - if (singleSegment) - op[pos++] = (BYTE)(pledgedSrcSize); - break; - case 1: - MEM_writeLE16(op + pos, (U16)(pledgedSrcSize - 256)); - pos += 2; - break; - case 2: - MEM_writeLE32(op + pos, (U32)(pledgedSrcSize)); - pos += 4; - break; - case 3: - MEM_writeLE64(op + pos, (U64)(pledgedSrcSize)); - pos += 8; - break; - } - return pos; -} - -static size_t ZSTD_compressContinue_internal(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - U32 frame, U32 lastFrameChunk) -{ - const BYTE *const ip = (const BYTE *)src; - size_t fhSize = 0; - - if (cctx->stage == ZSTDcs_created) - return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */ - - if (frame && (cctx->stage == ZSTDcs_init)) - { - fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, cctx->frameContentSize, cctx->dictID); - if (ZSTD_isError(fhSize)) - return fhSize; - dstCapacity -= fhSize; - dst = (char *)dst + fhSize; - cctx->stage = ZSTDcs_ongoing; - } - - /* Check if blocks follow each other */ - if (src != cctx->nextSrc) - { - /* not contiguous */ - ptrdiff_t const delta = cctx->nextSrc - ip; - cctx->lowLimit = cctx->dictLimit; - cctx->dictLimit = (U32)(cctx->nextSrc - cctx->base); - cctx->dictBase = cctx->base; - cctx->base -= delta; - cctx->nextToUpdate = cctx->dictLimit; - if (cctx->dictLimit - cctx->lowLimit < HASH_READ_SIZE) - cctx->lowLimit = cctx->dictLimit; /* too small extDict */ - } - - /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */ - if ((ip + srcSize > cctx->dictBase + cctx->lowLimit) & (ip < cctx->dictBase + cctx->dictLimit)) - { - ptrdiff_t const highInputIdx = (ip + srcSize) - cctx->dictBase; - U32 const lowLimitMax = (highInputIdx > (ptrdiff_t)cctx->dictLimit) ? cctx->dictLimit : (U32)highInputIdx; - cctx->lowLimit = lowLimitMax; - } - - cctx->nextSrc = ip + srcSize; - - if (srcSize) - { - size_t const cSize = frame ? ZSTD_compress_generic(cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) : ZSTD_compressBlock_internal(cctx, dst, dstCapacity, src, srcSize); - if (ZSTD_isError(cSize)) - return cSize; - return cSize + fhSize; - } - else - return fhSize; -} - -size_t ZSTD_compressContinue(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize) -{ - return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 0); -} - -size_t ZSTD_getBlockSizeMax(ZSTD_CCtx *cctx) -{ - return MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << cctx->params.cParams.windowLog); -} - -size_t ZSTD_compressBlock(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx); - if (srcSize > blockSizeMax) - return ERROR(srcSize_wrong); - return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0, 0); -} - -static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx *zc, const void *src, size_t srcSize) -{ - const BYTE *const ip = (const BYTE *)src; - const BYTE *const iend = ip + srcSize; - - /* input becomes current prefix */ - zc->lowLimit = zc->dictLimit; - zc->dictLimit = (U32)(zc->nextSrc - zc->base); - zc->dictBase = zc->base; - zc->base += ip - zc->nextSrc; - zc->nextToUpdate = zc->dictLimit; - zc->loadedDictEnd = zc->forceWindow ? 0 : (U32)(iend - zc->base); - - zc->nextSrc = iend; - if (srcSize <= HASH_READ_SIZE) - return 0; - - switch (zc->params.cParams.strategy) - { - case ZSTD_fast: - ZSTD_fillHashTable(zc, iend, zc->params.cParams.searchLength); - break; - - case ZSTD_dfast: - ZSTD_fillDoubleHashTable(zc, iend, zc->params.cParams.searchLength); - break; - - case ZSTD_greedy: - case ZSTD_lazy: - case ZSTD_lazy2: - ZSTD_insertAndFindFirstIndex(zc, iend - HASH_READ_SIZE, zc->params.cParams.searchLength); - break; - - case ZSTD_btlazy2: - case ZSTD_btopt: - case ZSTD_btopt2: - ZSTD_updateTree(zc, iend - HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength); - break; - - default: - return ERROR(GENERIC); /* strategy doesn't exist; impossible */ - } - - zc->nextToUpdate = (U32)(iend - zc->base); - return 0; -} - -/* Dictionaries that assign zero probability to symbols that show up causes problems - when FSE encoding. Refuse dictionaries that assign zero probability to symbols - that we may encounter during compression. - NOTE: This behavior is not standard and could be improved in the future. */ -static size_t ZSTD_checkDictNCount(short *normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) -{ - U32 s; - if (dictMaxSymbolValue < maxSymbolValue) - return ERROR(dictionary_corrupted); - for (s = 0; s <= maxSymbolValue; ++s) - { - if (normalizedCounter[s] == 0) - return ERROR(dictionary_corrupted); - } - return 0; -} - -/* Dictionary format : - Magic == ZSTD_DICT_MAGIC (4 bytes) - HUF_writeCTable(256) - FSE_writeNCount(off) - FSE_writeNCount(ml) - FSE_writeNCount(ll) - RepOffsets - Dictionary content -*/ -/*! ZSTD_loadDictEntropyStats() : - @return : size read from dictionary - note : magic number supposed already checked */ -static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx *cctx, const void *dict, size_t dictSize) -{ - const BYTE *dictPtr = (const BYTE *)dict; - const BYTE *const dictEnd = dictPtr + dictSize; - short offcodeNCount[MaxOff + 1]; - unsigned offcodeMaxValue = MaxOff; - BYTE scratchBuffer[1 << MAX(MLFSELog, LLFSELog)]; - - { - size_t const hufHeaderSize = HUF_readCTable(cctx->hufTable, 255, dict, dictSize); - if (HUF_isError(hufHeaderSize)) - return ERROR(dictionary_corrupted); - dictPtr += hufHeaderSize; - } - - { - unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(offcodeHeaderSize)) - return ERROR(dictionary_corrupted); - if (offcodeLog > OffFSELog) - return ERROR(dictionary_corrupted); - /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ - CHECK_E(FSE_buildCTable_wksp(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted); - dictPtr += offcodeHeaderSize; - } - - { - short matchlengthNCount[MaxML + 1]; - unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(matchlengthHeaderSize)) - return ERROR(dictionary_corrupted); - if (matchlengthLog > MLFSELog) - return ERROR(dictionary_corrupted); - /* Every match length code must have non-zero probability */ - CHECK_F(ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML)); - CHECK_E(FSE_buildCTable_wksp(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted); - dictPtr += matchlengthHeaderSize; - } - - { - short litlengthNCount[MaxLL + 1]; - unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(litlengthHeaderSize)) - return ERROR(dictionary_corrupted); - if (litlengthLog > LLFSELog) - return ERROR(dictionary_corrupted); - /* Every literal length code must have non-zero probability */ - CHECK_F(ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL)); - CHECK_E(FSE_buildCTable_wksp(cctx->litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, scratchBuffer, sizeof(scratchBuffer)), dictionary_corrupted); - dictPtr += litlengthHeaderSize; - } - - if (dictPtr + 12 > dictEnd) - return ERROR(dictionary_corrupted); - cctx->rep[0] = MEM_readLE32(dictPtr + 0); - if (cctx->rep[0] == 0 || cctx->rep[0] >= dictSize) - return ERROR(dictionary_corrupted); - cctx->rep[1] = MEM_readLE32(dictPtr + 4); - if (cctx->rep[1] == 0 || cctx->rep[1] >= dictSize) - return ERROR(dictionary_corrupted); - cctx->rep[2] = MEM_readLE32(dictPtr + 8); - if (cctx->rep[2] == 0 || cctx->rep[2] >= dictSize) - return ERROR(dictionary_corrupted); - dictPtr += 12; - - { - U32 offcodeMax = MaxOff; - if ((size_t)(dictEnd - dictPtr) <= ((U32)-1) - 128 KB) - { - U32 const maxOffset = (U32)(dictEnd - dictPtr) + 128 KB; /* The maximum offset that must be supported */ - /* Calculate minimum offset code required to represent maxOffset */ - offcodeMax = ZSTD_highbit32(maxOffset); - } - /* Every possible supported offset <= dictContentSize + 128 KB must be representable */ - CHECK_F(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff))); - } - - cctx->flagStaticTables = 1; - cctx->flagStaticHufTable = HUF_repeat_valid; - return dictPtr - (const BYTE *)dict; -} - -/** ZSTD_compress_insertDictionary() : - * @return : 0, or an error code */ -static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx *zc, const void *dict, size_t dictSize) -{ - if ((dict == NULL) || (dictSize <= 8)) - return 0; - - /* dict as pure content */ - if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (zc->forceRawDict)) - return ZSTD_loadDictionaryContent(zc, dict, dictSize); - zc->dictID = zc->params.fParams.noDictIDFlag ? 0 : MEM_readLE32((const char *)dict + 4); - - /* known magic number : dict is parsed for entropy stats and content */ - { - size_t const loadError = ZSTD_loadDictEntropyStats(zc, (const char *)dict + 8 /* skip dictHeader */, dictSize - 8); - size_t const eSize = loadError + 8; - if (ZSTD_isError(loadError)) - return loadError; - return ZSTD_loadDictionaryContent(zc, (const char *)dict + eSize, dictSize - eSize); - } -} - -/*! ZSTD_compressBegin_internal() : - * @return : 0, or an error code */ -static size_t ZSTD_compressBegin_internal(ZSTD_CCtx *cctx, - const void *dict, size_t dictSize, - ZSTD_parameters params, U64 pledgedSrcSize) -{ - ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue; - CHECK_F(ZSTD_resetCCtx_advanced(cctx, params, pledgedSrcSize, crp)); - return ZSTD_compress_insertDictionary(cctx, dict, dictSize); -} - -/*! ZSTD_compressBegin_advanced() : - * @return : 0, or an error code */ -size_t ZSTD_compressBegin_advanced(ZSTD_CCtx *cctx, - const void *dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize) -{ - /* compression parameters verification and optimization */ - CHECK_F(ZSTD_checkCParams(params.cParams)); - return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize); -} - -size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx *cctx, const void *dict, size_t dictSize, int compressionLevel) -{ - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize); - return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0); -} - -size_t ZSTD_compressBegin(ZSTD_CCtx *cctx, int compressionLevel) -{ - return ZSTD_compressBegin_usingDict(cctx, NULL, 0, compressionLevel); -} - -/*! ZSTD_writeEpilogue() : - * Ends a frame. - * @return : nb of bytes written into dst (or an error code) */ -static size_t ZSTD_writeEpilogue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - size_t fhSize = 0; - - if (cctx->stage == ZSTDcs_created) - return ERROR(stage_wrong); /* init missing */ - - /* special case : empty frame */ - if (cctx->stage == ZSTDcs_init) - { - fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0); - if (ZSTD_isError(fhSize)) - return fhSize; - dstCapacity -= fhSize; - op += fhSize; - cctx->stage = ZSTDcs_ongoing; - } - - if (cctx->stage != ZSTDcs_ending) - { - /* write one last empty block, make it the "last" block */ - U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw) << 1) + 0; - if (dstCapacity < 4) - return ERROR(dstSize_tooSmall); - MEM_writeLE32(op, cBlockHeader24); - op += ZSTD_blockHeaderSize; - dstCapacity -= ZSTD_blockHeaderSize; - } - - if (cctx->params.fParams.checksumFlag) - { - U32 const checksum = (U32)XXH64_digest(&cctx->xxhState); - if (dstCapacity < 4) - return ERROR(dstSize_tooSmall); - MEM_writeLE32(op, checksum); - op += 4; - } - - cctx->stage = ZSTDcs_created; /* return to "created but no init" status */ - return op - ostart; -} - -size_t ZSTD_compressEnd(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize) -{ - size_t endResult; - size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 1); - if (ZSTD_isError(cSize)) - return cSize; - endResult = ZSTD_writeEpilogue(cctx, (char *)dst + cSize, dstCapacity - cSize); - if (ZSTD_isError(endResult)) - return endResult; - return cSize + endResult; -} - -static size_t ZSTD_compress_internal(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize, - ZSTD_parameters params) -{ - CHECK_F(ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize)); - return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); -} - -size_t ZSTD_compress_advanced(ZSTD_CCtx *ctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize, - ZSTD_parameters params) -{ - CHECK_F(ZSTD_checkCParams(params.cParams)); - return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params); -} - -size_t ZSTD_compress_usingDict(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize, int compressionLevel) -{ - ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, dict ? dictSize : 0); - params.fParams.contentSizeFlag = 1; - return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params); -} - -size_t ZSTD_compressCCtx(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel) -{ - return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel); -} - -size_t ZSTD_compress(void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel) -{ - size_t result; - ZSTD_CCtx ctxBody; - memset(&ctxBody, 0, sizeof(ctxBody)); - memcpy(&ctxBody.customMem, &defaultCustomMem, sizeof(ZSTD_customMem)); - result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); - ZSTD_free(ctxBody.workSpace, defaultCustomMem); /* can't free ctxBody itself, as it's on stack; free only heap content */ - return result; -} - -/* ===== Dictionary API ===== */ - -struct ZSTD_CDict_s -{ - void *dictBuffer; - const void *dictContent; - size_t dictContentSize; - ZSTD_CCtx *refContext; -}; /* typedef'd tp ZSTD_CDict within "zstd.h" */ - -size_t ZSTD_sizeof_CDict(const ZSTD_CDict *cdict) -{ - if (cdict == NULL) - return 0; /* support sizeof on NULL */ - return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict); -} - -ZSTD_CDict *ZSTD_createCDict_advanced(const void *dictBuffer, size_t dictSize, unsigned byReference, - ZSTD_parameters params, ZSTD_customMem customMem) -{ - if (!customMem.customAlloc && !customMem.customFree) - customMem = defaultCustomMem; - if (!customMem.customAlloc || !customMem.customFree) - return NULL; - - { - ZSTD_CDict *const cdict = (ZSTD_CDict *)ZSTD_malloc(sizeof(ZSTD_CDict), customMem); - ZSTD_CCtx *const cctx = ZSTD_createCCtx_advanced(customMem); - - if (!cdict || !cctx) - { - ZSTD_free(cdict, customMem); - ZSTD_freeCCtx(cctx); - return NULL; - } - - if ((byReference) || (!dictBuffer) || (!dictSize)) - { - cdict->dictBuffer = NULL; - cdict->dictContent = dictBuffer; - } - else - { - void *const internalBuffer = ZSTD_malloc(dictSize, customMem); - if (!internalBuffer) - { - ZSTD_free(cctx, customMem); - ZSTD_free(cdict, customMem); - return NULL; - } - memcpy(internalBuffer, dictBuffer, dictSize); - cdict->dictBuffer = internalBuffer; - cdict->dictContent = internalBuffer; - } - - { - size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0); - if (ZSTD_isError(errorCode)) - { - ZSTD_free(cdict->dictBuffer, customMem); - ZSTD_free(cdict, customMem); - ZSTD_freeCCtx(cctx); - return NULL; - } - } - - cdict->refContext = cctx; - cdict->dictContentSize = dictSize; - return cdict; - } -} - -ZSTD_CDict *ZSTD_createCDict(const void *dict, size_t dictSize, int compressionLevel) -{ - ZSTD_customMem const allocator = {NULL, NULL, NULL}; - ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize); - params.fParams.contentSizeFlag = 1; - return ZSTD_createCDict_advanced(dict, dictSize, 0, params, allocator); -} - -ZSTD_CDict *ZSTD_createCDict_byReference(const void *dict, size_t dictSize, int compressionLevel) -{ - ZSTD_customMem const allocator = {NULL, NULL, NULL}; - ZSTD_parameters params = ZSTD_getParams(compressionLevel, 0, dictSize); - params.fParams.contentSizeFlag = 1; - return ZSTD_createCDict_advanced(dict, dictSize, 1, params, allocator); -} - -size_t ZSTD_freeCDict(ZSTD_CDict *cdict) -{ - if (cdict == NULL) - return 0; /* support free on NULL */ - { - ZSTD_customMem const cMem = cdict->refContext->customMem; - ZSTD_freeCCtx(cdict->refContext); - ZSTD_free(cdict->dictBuffer, cMem); - ZSTD_free(cdict, cMem); - return 0; - } -} - -static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict *cdict) -{ - return ZSTD_getParamsFromCCtx(cdict->refContext); -} - -size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx *cctx, const ZSTD_CDict *cdict, unsigned long long pledgedSrcSize) -{ - if (cdict->dictContentSize) - CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize)) - else - { - ZSTD_parameters params = cdict->refContext->params; - params.fParams.contentSizeFlag = (pledgedSrcSize > 0); - CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, params, pledgedSrcSize)); - } - return 0; -} - -/*! ZSTD_compress_usingCDict() : - * Compression using a digested Dictionary. - * Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times. - * Note that compression level is decided during dictionary creation */ -size_t ZSTD_compress_usingCDict(ZSTD_CCtx *cctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const ZSTD_CDict *cdict) -{ - CHECK_F(ZSTD_compressBegin_usingCDict(cctx, cdict, srcSize)); - - if (cdict->refContext->params.fParams.contentSizeFlag == 1) - { - cctx->params.fParams.contentSizeFlag = 1; - cctx->frameContentSize = srcSize; - } - - return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize); -} - -/* ****************************************************************** - * Streaming - ********************************************************************/ - -typedef enum -{ - zcss_init, - zcss_load, - zcss_flush, - zcss_final -} ZSTD_cStreamStage; - -struct ZSTD_CStream_s -{ - ZSTD_CCtx *cctx; - ZSTD_CDict *cdictLocal; - const ZSTD_CDict *cdict; - char *inBuff; - size_t inBuffSize; - size_t inToCompress; - size_t inBuffPos; - size_t inBuffTarget; - size_t blockSize; - char *outBuff; - size_t outBuffSize; - size_t outBuffContentSize; - size_t outBuffFlushedSize; - ZSTD_cStreamStage stage; - U32 checksum; - U32 frameEnded; - U64 pledgedSrcSize; - U64 inputProcessed; - ZSTD_parameters params; - ZSTD_customMem customMem; -}; /* typedef'd to ZSTD_CStream within "zstd.h" */ - -ZSTD_CStream *ZSTD_createCStream(void) -{ - return ZSTD_createCStream_advanced(defaultCustomMem); -} - -ZSTD_CStream *ZSTD_createCStream_advanced(ZSTD_customMem customMem) -{ - ZSTD_CStream *zcs; - - if (!customMem.customAlloc && !customMem.customFree) - customMem = defaultCustomMem; - if (!customMem.customAlloc || !customMem.customFree) - return NULL; - - zcs = (ZSTD_CStream *)ZSTD_malloc(sizeof(ZSTD_CStream), customMem); - if (zcs == NULL) - return NULL; - memset(zcs, 0, sizeof(ZSTD_CStream)); - memcpy(&zcs->customMem, &customMem, sizeof(ZSTD_customMem)); - zcs->cctx = ZSTD_createCCtx_advanced(customMem); - if (zcs->cctx == NULL) - { - ZSTD_freeCStream(zcs); - return NULL; - } - return zcs; -} - -size_t ZSTD_freeCStream(ZSTD_CStream *zcs) -{ - if (zcs == NULL) - return 0; /* support free on NULL */ - { - ZSTD_customMem const cMem = zcs->customMem; - ZSTD_freeCCtx(zcs->cctx); - ZSTD_freeCDict(zcs->cdictLocal); - ZSTD_free(zcs->inBuff, cMem); - ZSTD_free(zcs->outBuff, cMem); - ZSTD_free(zcs, cMem); - return 0; - } -} - -/*====== Initialization ======*/ - -size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } -size_t ZSTD_CStreamOutSize(void) { return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */; } - -static size_t ZSTD_resetCStream_internal(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize) -{ - if (zcs->inBuffSize == 0) - return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */ - - if (zcs->cdict) - CHECK_F(ZSTD_compressBegin_usingCDict(zcs->cctx, zcs->cdict, pledgedSrcSize)) - else - CHECK_F(ZSTD_compressBegin_advanced(zcs->cctx, NULL, 0, zcs->params, pledgedSrcSize)); - - zcs->inToCompress = 0; - zcs->inBuffPos = 0; - zcs->inBuffTarget = zcs->blockSize; - zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; - zcs->stage = zcss_load; - zcs->frameEnded = 0; - zcs->pledgedSrcSize = pledgedSrcSize; - zcs->inputProcessed = 0; - return 0; /* ready to go */ -} - -size_t ZSTD_resetCStream(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize) -{ - - zcs->params.fParams.contentSizeFlag = (pledgedSrcSize > 0); - - return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); -} - -size_t ZSTD_initCStream_advanced(ZSTD_CStream *zcs, - const void *dict, size_t dictSize, - ZSTD_parameters params, unsigned long long pledgedSrcSize) -{ - /* allocate buffers */ - { - size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog; - if (zcs->inBuffSize < neededInBuffSize) - { - zcs->inBuffSize = neededInBuffSize; - ZSTD_free(zcs->inBuff, zcs->customMem); - zcs->inBuff = (char *)ZSTD_malloc(neededInBuffSize, zcs->customMem); - if (zcs->inBuff == NULL) - return ERROR(memory_allocation); - } - zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, neededInBuffSize); - } - if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize) + 1) - { - zcs->outBuffSize = ZSTD_compressBound(zcs->blockSize) + 1; - ZSTD_free(zcs->outBuff, zcs->customMem); - zcs->outBuff = (char *)ZSTD_malloc(zcs->outBuffSize, zcs->customMem); - if (zcs->outBuff == NULL) - return ERROR(memory_allocation); - } - - if (dict && dictSize >= 8) - { - ZSTD_freeCDict(zcs->cdictLocal); - zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0, params, zcs->customMem); - if (zcs->cdictLocal == NULL) - return ERROR(memory_allocation); - zcs->cdict = zcs->cdictLocal; - } - else - zcs->cdict = NULL; - - zcs->checksum = params.fParams.checksumFlag > 0; - zcs->params = params; - - return ZSTD_resetCStream_internal(zcs, pledgedSrcSize); -} - -/* note : cdict must outlive compression session */ -size_t ZSTD_initCStream_usingCDict(ZSTD_CStream *zcs, const ZSTD_CDict *cdict) -{ - ZSTD_parameters const params = ZSTD_getParamsFromCDict(cdict); - size_t const initError = ZSTD_initCStream_advanced(zcs, NULL, 0, params, 0); - zcs->cdict = cdict; - zcs->cctx->dictID = params.fParams.noDictIDFlag ? 0 : cdict->refContext->dictID; - return initError; -} - -size_t ZSTD_initCStream_usingDict(ZSTD_CStream *zcs, const void *dict, size_t dictSize, int compressionLevel) -{ - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize); - return ZSTD_initCStream_advanced(zcs, dict, dictSize, params, 0); -} - -size_t ZSTD_initCStream_srcSize(ZSTD_CStream *zcs, int compressionLevel, unsigned long long pledgedSrcSize) -{ - ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0); - if (pledgedSrcSize) - params.fParams.contentSizeFlag = 1; - return ZSTD_initCStream_advanced(zcs, NULL, 0, params, pledgedSrcSize); -} - -size_t ZSTD_initCStream(ZSTD_CStream *zcs, int compressionLevel) -{ - return ZSTD_initCStream_usingDict(zcs, NULL, 0, compressionLevel); -} - -size_t ZSTD_sizeof_CStream(const ZSTD_CStream *zcs) -{ - if (zcs == NULL) - return 0; /* support sizeof on NULL */ - return sizeof(*zcs) + ZSTD_sizeof_CCtx(zcs->cctx) + ZSTD_sizeof_CDict(zcs->cdictLocal) + zcs->outBuffSize + zcs->inBuffSize; -} - -/*====== Compression ======*/ - -typedef enum -{ - zsf_gather, - zsf_flush, - zsf_end -} ZSTD_flush_e; - -MEM_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - size_t const length = MIN(dstCapacity, srcSize); - memcpy(dst, src, length); - return length; -} - -static size_t ZSTD_compressStream_generic(ZSTD_CStream *zcs, - void *dst, size_t *dstCapacityPtr, - const void *src, size_t *srcSizePtr, - ZSTD_flush_e const flush) -{ - U32 someMoreWork = 1; - const char *const istart = (const char *)src; - const char *const iend = istart + *srcSizePtr; - const char *ip = istart; - char *const ostart = (char *)dst; - char *const oend = ostart + *dstCapacityPtr; - char *op = ostart; - - while (someMoreWork) - { - switch (zcs->stage) - { - case zcss_init: - return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */ - - case zcss_load: - /* complete inBuffer */ - { - size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; - size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend - ip); - zcs->inBuffPos += loaded; - ip += loaded; - if ((zcs->inBuffPos == zcs->inToCompress) || (!flush && (toLoad != loaded))) - { - someMoreWork = 0; - break; /* not enough input to get a full block : stop there, wait for more */ - } - } - /* compress current block (note : this stage cannot be stopped in the middle) */ - { - void *cDst; - size_t cSize; - size_t const iSize = zcs->inBuffPos - zcs->inToCompress; - size_t oSize = oend - op; - if (oSize >= ZSTD_compressBound(iSize)) - cDst = op; /* compress directly into output buffer (avoid flush stage) */ - else - cDst = zcs->outBuff, oSize = zcs->outBuffSize; - cSize = (flush == zsf_end) ? ZSTD_compressEnd(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) : ZSTD_compressContinue(zcs->cctx, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize); - if (ZSTD_isError(cSize)) - return cSize; - if (flush == zsf_end) - zcs->frameEnded = 1; - /* prepare next block */ - zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; - if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffSize >= blockSize */ - zcs->inToCompress = zcs->inBuffPos; - if (cDst == op) - { - op += cSize; - break; - } /* no need to flush */ - zcs->outBuffContentSize = cSize; - zcs->outBuffFlushedSize = 0; - - zcs->stage = zcss_flush; /* fall through */ /* pass-through to flush stage */ - /* fall through */ - } - - case zcss_flush: - { - size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; - size_t const flushed = ZSTD_limitCopy(op, oend - op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); - op += flushed; - zcs->outBuffFlushedSize += flushed; - if (toFlush != flushed) - { - someMoreWork = 0; - break; - } /* dst too small to store flushed data : stop there */ - zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0; - zcs->stage = zcss_load; - break; - } - - case zcss_final: - someMoreWork = 0; /* do nothing */ - break; - - default: - return ERROR(GENERIC); /* impossible */ - } - } - - *srcSizePtr = ip - istart; - *dstCapacityPtr = op - ostart; - zcs->inputProcessed += *srcSizePtr; - if (zcs->frameEnded) - return 0; - { - size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos; - if (hintInSize == 0) - hintInSize = zcs->blockSize; - return hintInSize; - } -} - -size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output, ZSTD_inBuffer *input) -{ - size_t sizeRead = input->size - input->pos; - size_t sizeWritten = output->size - output->pos; - size_t const result = ZSTD_compressStream_generic(zcs, - (char *)(output->dst) + output->pos, &sizeWritten, - (const char *)(input->src) + input->pos, &sizeRead, zsf_gather); - input->pos += sizeRead; - output->pos += sizeWritten; - return result; -} - -/*====== Finalize ======*/ - -/*! ZSTD_flushStream() : - * @return : amount of data remaining to flush */ -size_t ZSTD_flushStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output) -{ - size_t srcSize = 0; - size_t sizeWritten = output->size - output->pos; - size_t const result = ZSTD_compressStream_generic(zcs, - (char *)(output->dst) + output->pos, &sizeWritten, - &srcSize, &srcSize, /* use a valid src address instead of NULL */ - zsf_flush); - output->pos += sizeWritten; - if (ZSTD_isError(result)) - return result; - return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */ -} - -size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output) -{ - BYTE *const ostart = (BYTE *)(output->dst) + output->pos; - BYTE *const oend = (BYTE *)(output->dst) + output->size; - BYTE *op = ostart; - - if ((zcs->pledgedSrcSize) && (zcs->inputProcessed != zcs->pledgedSrcSize)) - return ERROR(srcSize_wrong); /* pledgedSrcSize not respected */ - - if (zcs->stage != zcss_final) - { - /* flush whatever remains */ - size_t srcSize = 0; - size_t sizeWritten = output->size - output->pos; - size_t const notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten, &srcSize, &srcSize, zsf_end); /* use a valid src address instead of NULL */ - size_t const remainingToFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; - op += sizeWritten; - if (remainingToFlush) - { - output->pos += sizeWritten; - return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */ + (zcs->checksum * 4); - } - /* create epilogue */ - zcs->stage = zcss_final; - zcs->outBuffContentSize = !notEnded ? 0 : ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0); /* write epilogue, including final empty block, into outBuff */ - } - - /* flush epilogue */ - { - size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; - size_t const flushed = ZSTD_limitCopy(op, oend - op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush); - op += flushed; - zcs->outBuffFlushedSize += flushed; - output->pos += op - ostart; - if (toFlush == flushed) - zcs->stage = zcss_init; /* end reached */ - return toFlush - flushed; - } -} - -/*-===== Pre-defined compression levels =====-*/ - -#define ZSTD_DEFAULT_CLEVEL 1 -#define ZSTD_MAX_CLEVEL 22 -int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; } - -static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL + 1] = { - { - /* "default" */ - /* W, C, H, S, L, TL, strat */ - {18, 12, 12, 1, 7, 16, ZSTD_fast}, /* level 0 - never used */ - {19, 13, 14, 1, 7, 16, ZSTD_fast}, /* level 1 */ - {19, 15, 16, 1, 6, 16, ZSTD_fast}, /* level 2 */ - {20, 16, 17, 1, 5, 16, ZSTD_dfast}, /* level 3.*/ - {20, 18, 18, 1, 5, 16, ZSTD_dfast}, /* level 4.*/ - {20, 15, 18, 3, 5, 16, ZSTD_greedy}, /* level 5 */ - {21, 16, 19, 2, 5, 16, ZSTD_lazy}, /* level 6 */ - {21, 17, 20, 3, 5, 16, ZSTD_lazy}, /* level 7 */ - {21, 18, 20, 3, 5, 16, ZSTD_lazy2}, /* level 8 */ - {21, 20, 20, 3, 5, 16, ZSTD_lazy2}, /* level 9 */ - {21, 19, 21, 4, 5, 16, ZSTD_lazy2}, /* level 10 */ - {22, 20, 22, 4, 5, 16, ZSTD_lazy2}, /* level 11 */ - {22, 20, 22, 5, 5, 16, ZSTD_lazy2}, /* level 12 */ - {22, 21, 22, 5, 5, 16, ZSTD_lazy2}, /* level 13 */ - {22, 21, 22, 6, 5, 16, ZSTD_lazy2}, /* level 14 */ - {22, 21, 21, 5, 5, 16, ZSTD_btlazy2}, /* level 15 */ - {23, 22, 22, 5, 5, 16, ZSTD_btlazy2}, /* level 16 */ - {23, 21, 22, 4, 5, 24, ZSTD_btopt}, /* level 17 */ - {23, 23, 22, 6, 5, 32, ZSTD_btopt}, /* level 18 */ - {23, 23, 22, 6, 3, 48, ZSTD_btopt}, /* level 19 */ - {25, 25, 23, 7, 3, 64, ZSTD_btopt2}, /* level 20 */ - {26, 26, 23, 7, 3, 256, ZSTD_btopt2}, /* level 21 */ - {27, 27, 25, 9, 3, 512, ZSTD_btopt2}, /* level 22 */ - }, - { - /* for srcSize <= 256 KB */ - /* W, C, H, S, L, T, strat */ - {0, 0, 0, 0, 0, 0, ZSTD_fast}, /* level 0 - not used */ - {18, 13, 14, 1, 6, 8, ZSTD_fast}, /* level 1 */ - {18, 14, 13, 1, 5, 8, ZSTD_dfast}, /* level 2 */ - {18, 16, 15, 1, 5, 8, ZSTD_dfast}, /* level 3 */ - {18, 15, 17, 1, 5, 8, ZSTD_greedy}, /* level 4.*/ - {18, 16, 17, 4, 5, 8, ZSTD_greedy}, /* level 5.*/ - {18, 16, 17, 3, 5, 8, ZSTD_lazy}, /* level 6.*/ - {18, 17, 17, 4, 4, 8, ZSTD_lazy}, /* level 7 */ - {18, 17, 17, 4, 4, 8, ZSTD_lazy2}, /* level 8 */ - {18, 17, 17, 5, 4, 8, ZSTD_lazy2}, /* level 9 */ - {18, 17, 17, 6, 4, 8, ZSTD_lazy2}, /* level 10 */ - {18, 18, 17, 6, 4, 8, ZSTD_lazy2}, /* level 11.*/ - {18, 18, 17, 7, 4, 8, ZSTD_lazy2}, /* level 12.*/ - {18, 19, 17, 6, 4, 8, ZSTD_btlazy2}, /* level 13 */ - {18, 18, 18, 4, 4, 16, ZSTD_btopt}, /* level 14.*/ - {18, 18, 18, 4, 3, 16, ZSTD_btopt}, /* level 15.*/ - {18, 19, 18, 6, 3, 32, ZSTD_btopt}, /* level 16.*/ - {18, 19, 18, 8, 3, 64, ZSTD_btopt}, /* level 17.*/ - {18, 19, 18, 9, 3, 128, ZSTD_btopt}, /* level 18.*/ - {18, 19, 18, 10, 3, 256, ZSTD_btopt}, /* level 19.*/ - {18, 19, 18, 11, 3, 512, ZSTD_btopt2}, /* level 20.*/ - {18, 19, 18, 12, 3, 512, ZSTD_btopt2}, /* level 21.*/ - {18, 19, 18, 13, 3, 512, ZSTD_btopt2}, /* level 22.*/ - }, - { - /* for srcSize <= 128 KB */ - /* W, C, H, S, L, T, strat */ - {17, 12, 12, 1, 7, 8, ZSTD_fast}, /* level 0 - not used */ - {17, 12, 13, 1, 6, 8, ZSTD_fast}, /* level 1 */ - {17, 13, 16, 1, 5, 8, ZSTD_fast}, /* level 2 */ - {17, 16, 16, 2, 5, 8, ZSTD_dfast}, /* level 3 */ - {17, 13, 15, 3, 4, 8, ZSTD_greedy}, /* level 4 */ - {17, 15, 17, 4, 4, 8, ZSTD_greedy}, /* level 5 */ - {17, 16, 17, 3, 4, 8, ZSTD_lazy}, /* level 6 */ - {17, 15, 17, 4, 4, 8, ZSTD_lazy2}, /* level 7 */ - {17, 17, 17, 4, 4, 8, ZSTD_lazy2}, /* level 8 */ - {17, 17, 17, 5, 4, 8, ZSTD_lazy2}, /* level 9 */ - {17, 17, 17, 6, 4, 8, ZSTD_lazy2}, /* level 10 */ - {17, 17, 17, 7, 4, 8, ZSTD_lazy2}, /* level 11 */ - {17, 17, 17, 8, 4, 8, ZSTD_lazy2}, /* level 12 */ - {17, 18, 17, 6, 4, 8, ZSTD_btlazy2}, /* level 13.*/ - {17, 17, 17, 7, 3, 8, ZSTD_btopt}, /* level 14.*/ - {17, 17, 17, 7, 3, 16, ZSTD_btopt}, /* level 15.*/ - {17, 18, 17, 7, 3, 32, ZSTD_btopt}, /* level 16.*/ - {17, 18, 17, 7, 3, 64, ZSTD_btopt}, /* level 17.*/ - {17, 18, 17, 7, 3, 256, ZSTD_btopt}, /* level 18.*/ - {17, 18, 17, 8, 3, 256, ZSTD_btopt}, /* level 19.*/ - {17, 18, 17, 9, 3, 256, ZSTD_btopt2}, /* level 20.*/ - {17, 18, 17, 10, 3, 256, ZSTD_btopt2}, /* level 21.*/ - {17, 18, 17, 11, 3, 512, ZSTD_btopt2}, /* level 22.*/ - }, - { - /* for srcSize <= 16 KB */ - /* W, C, H, S, L, T, strat */ - {14, 12, 12, 1, 7, 6, ZSTD_fast}, /* level 0 - not used */ - {14, 14, 14, 1, 6, 6, ZSTD_fast}, /* level 1 */ - {14, 14, 14, 1, 4, 6, ZSTD_fast}, /* level 2 */ - {14, 14, 14, 1, 4, 6, ZSTD_dfast}, /* level 3.*/ - {14, 14, 14, 4, 4, 6, ZSTD_greedy}, /* level 4.*/ - {14, 14, 14, 3, 4, 6, ZSTD_lazy}, /* level 5.*/ - {14, 14, 14, 4, 4, 6, ZSTD_lazy2}, /* level 6 */ - {14, 14, 14, 5, 4, 6, ZSTD_lazy2}, /* level 7 */ - {14, 14, 14, 6, 4, 6, ZSTD_lazy2}, /* level 8.*/ - {14, 15, 14, 6, 4, 6, ZSTD_btlazy2}, /* level 9.*/ - {14, 15, 14, 3, 3, 6, ZSTD_btopt}, /* level 10.*/ - {14, 15, 14, 6, 3, 8, ZSTD_btopt}, /* level 11.*/ - {14, 15, 14, 6, 3, 16, ZSTD_btopt}, /* level 12.*/ - {14, 15, 14, 6, 3, 24, ZSTD_btopt}, /* level 13.*/ - {14, 15, 15, 6, 3, 48, ZSTD_btopt}, /* level 14.*/ - {14, 15, 15, 6, 3, 64, ZSTD_btopt}, /* level 15.*/ - {14, 15, 15, 6, 3, 96, ZSTD_btopt}, /* level 16.*/ - {14, 15, 15, 6, 3, 128, ZSTD_btopt}, /* level 17.*/ - {14, 15, 15, 6, 3, 256, ZSTD_btopt}, /* level 18.*/ - {14, 15, 15, 7, 3, 256, ZSTD_btopt}, /* level 19.*/ - {14, 15, 15, 8, 3, 256, ZSTD_btopt2}, /* level 20.*/ - {14, 15, 15, 9, 3, 256, ZSTD_btopt2}, /* level 21.*/ - {14, 15, 15, 10, 3, 256, ZSTD_btopt2}, /* level 22.*/ - }, -}; - -/*! ZSTD_getCParams() : - * @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`. - * Size values are optional, provide 0 if not known or unused */ -ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) -{ - ZSTD_compressionParameters cp; - size_t const addedSize = srcSize ? 0 : 500; - U64 const rSize = srcSize + dictSize ? srcSize + dictSize + addedSize : (U64)-1; - U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */ - if (compressionLevel <= 0) - compressionLevel = ZSTD_DEFAULT_CLEVEL; /* 0 == default; no negative compressionLevel yet */ - if (compressionLevel > ZSTD_MAX_CLEVEL) - compressionLevel = ZSTD_MAX_CLEVEL; - cp = ZSTD_defaultCParameters[tableID][compressionLevel]; - if (MEM_32bits()) - { /* auto-correction, for 32-bits mode */ - if (cp.windowLog > ZSTD_WINDOWLOG_MAX) - cp.windowLog = ZSTD_WINDOWLOG_MAX; - if (cp.chainLog > ZSTD_CHAINLOG_MAX) - cp.chainLog = ZSTD_CHAINLOG_MAX; - if (cp.hashLog > ZSTD_HASHLOG_MAX) - cp.hashLog = ZSTD_HASHLOG_MAX; - } - cp = ZSTD_adjustCParams(cp, srcSize, dictSize); - return cp; -} - -/*! ZSTD_getParams() : - * same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`). - * All fields of `ZSTD_frameParameters` are set to default (0) */ -ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) -{ - ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize); - memset(¶ms, 0, sizeof(params)); - params.cParams = cParams; - return params; -} diff --git a/extra/zstd/zstd_decompress.c b/extra/zstd/zstd_decompress.c deleted file mode 100644 index 3e9bedb1..00000000 --- a/extra/zstd/zstd_decompress.c +++ /dev/null @@ -1,2905 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* *************************************************************** - * Tuning parameters - *****************************************************************/ -/*! - * HEAPMODE : - * Select how default decompression function ZSTD_decompress() will allocate memory, - * in memory stack (0), or in memory heap (1, requires malloc()) - */ -#ifndef ZSTD_HEAPMODE -#define ZSTD_HEAPMODE 1 -#endif - -/*! - * LEGACY_SUPPORT : - * if set to 1, ZSTD_decompress() can decode older formats (v0.1+) - */ -#ifndef ZSTD_LEGACY_SUPPORT -#define ZSTD_LEGACY_SUPPORT 0 -#endif - -/*! - * MAXWINDOWSIZE_DEFAULT : - * maximum window size accepted by DStream, by default. - * Frames requiring more memory will be rejected. - */ -#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT -#define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */ -#endif - -/*-******************************************************* - * Dependencies - *********************************************************/ -#include /* memcpy, memmove, memset */ -#include "mem.h" /* low level memory routines */ -#define FSE_STATIC_LINKING_ONLY -#include "fse.h" -#define HUF_STATIC_LINKING_ONLY -#include "huf.h" -#include "zstd_internal.h" - -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) -#include "zstd_legacy.h" -#endif - -#if defined(_MSC_VER) -#include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ -#define ZSTD_PREFETCH(ptr) _mm_prefetch((const char *)ptr, _MM_HINT_T0) -#elif defined(__GNUC__) -#define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0) -#else -#define ZSTD_PREFETCH(ptr) /* disabled */ -#endif - -/*-************************************* - * Macros - ***************************************/ -#define ZSTD_isError ERR_isError /* for inlining */ -#define FSE_isError ERR_isError -#define HUF_isError ERR_isError - -/*_******************************************************* - * Memory operations - **********************************************************/ -static void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); } - -/*-************************************************************* - * Context management - ***************************************************************/ -typedef enum -{ - ZSTDds_getFrameHeaderSize, - ZSTDds_decodeFrameHeader, - ZSTDds_decodeBlockHeader, - ZSTDds_decompressBlock, - ZSTDds_decompressLastBlock, - ZSTDds_checkChecksum, - ZSTDds_decodeSkippableHeader, - ZSTDds_skipFrame -} ZSTD_dStage; - -typedef struct -{ - FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; - FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; - FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; - HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ - U32 rep[ZSTD_REP_NUM]; -} ZSTD_entropyTables_t; - -struct ZSTD_DCtx_s -{ - const FSE_DTable *LLTptr; - const FSE_DTable *MLTptr; - const FSE_DTable *OFTptr; - const HUF_DTable *HUFptr; - ZSTD_entropyTables_t entropy; - const void *previousDstEnd; /* detect continuity */ - const void *base; /* start of current segment */ - const void *vBase; /* virtual start of previous segment if it was just before current one */ - const void *dictEnd; /* end of previous segment */ - size_t expected; - ZSTD_frameParams fParams; - blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */ - ZSTD_dStage stage; - U32 litEntropy; - U32 fseEntropy; - XXH64_state_t xxhState; - size_t headerSize; - U32 dictID; - const BYTE *litPtr; - ZSTD_customMem customMem; - size_t litSize; - size_t rleSize; - BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH]; - BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; -}; /* typedef'd to ZSTD_DCtx within "zstd.h" */ - -size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx *dctx) { return (dctx == NULL) ? 0 : sizeof(ZSTD_DCtx); } - -size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); } - -size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx) -{ - dctx->expected = ZSTD_frameHeaderSize_prefix; - dctx->stage = ZSTDds_getFrameHeaderSize; - dctx->previousDstEnd = NULL; - dctx->base = NULL; - dctx->vBase = NULL; - dctx->dictEnd = NULL; - dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog) * 0x1000001); /* cover both little and big endian */ - dctx->litEntropy = dctx->fseEntropy = 0; - dctx->dictID = 0; - MEM_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); - memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ - dctx->LLTptr = dctx->entropy.LLTable; - dctx->MLTptr = dctx->entropy.MLTable; - dctx->OFTptr = dctx->entropy.OFTable; - dctx->HUFptr = dctx->entropy.hufTable; - return 0; -} - -ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem) -{ - ZSTD_DCtx *dctx; - - if (!customMem.customAlloc && !customMem.customFree) - customMem = defaultCustomMem; - if (!customMem.customAlloc || !customMem.customFree) - return NULL; - - dctx = (ZSTD_DCtx *)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem); - if (!dctx) - return NULL; - memcpy(&dctx->customMem, &customMem, sizeof(customMem)); - ZSTD_decompressBegin(dctx); - return dctx; -} - -ZSTD_DCtx *ZSTD_createDCtx(void) -{ - return ZSTD_createDCtx_advanced(defaultCustomMem); -} - -size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx) -{ - if (dctx == NULL) - return 0; /* support free on NULL */ - ZSTD_free(dctx, dctx->customMem); - return 0; /* reserved as a potential error code in the future */ -} - -void ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx) -{ - size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max; - memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */ -} - -#if 0 -/* deprecated */ -static void ZSTD_refDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) -{ - ZSTD_decompressBegin(dstDCtx); /* init */ - if (srcDCtx) { /* support refDCtx on NULL */ - dstDCtx->dictEnd = srcDCtx->dictEnd; - dstDCtx->vBase = srcDCtx->vBase; - dstDCtx->base = srcDCtx->base; - dstDCtx->previousDstEnd = srcDCtx->previousDstEnd; - dstDCtx->dictID = srcDCtx->dictID; - dstDCtx->litEntropy = srcDCtx->litEntropy; - dstDCtx->fseEntropy = srcDCtx->fseEntropy; - dstDCtx->LLTptr = srcDCtx->entropy.LLTable; - dstDCtx->MLTptr = srcDCtx->entropy.MLTable; - dstDCtx->OFTptr = srcDCtx->entropy.OFTable; - dstDCtx->HUFptr = srcDCtx->entropy.hufTable; - dstDCtx->entropy.rep[0] = srcDCtx->entropy.rep[0]; - dstDCtx->entropy.rep[1] = srcDCtx->entropy.rep[1]; - dstDCtx->entropy.rep[2] = srcDCtx->entropy.rep[2]; - } -} -#endif - -static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict); - -/*-************************************************************* - * Decompression section - ***************************************************************/ - -/*! ZSTD_isFrame() : - * Tells if the content of `buffer` starts with a valid Frame Identifier. - * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0. - * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled. - * Note 3 : Skippable Frame Identifiers are considered valid. */ -unsigned ZSTD_isFrame(const void *buffer, size_t size) -{ - if (size < 4) - return 0; - { - U32 const magic = MEM_readLE32(buffer); - if (magic == ZSTD_MAGICNUMBER) - return 1; - if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - return 1; - } -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(buffer, size)) - return 1; -#endif - return 0; -} - -/** ZSTD_frameHeaderSize() : - * srcSize must be >= ZSTD_frameHeaderSize_prefix. - * @return : size of the Frame Header */ -static size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize) -{ - if (srcSize < ZSTD_frameHeaderSize_prefix) - return ERROR(srcSize_wrong); - { - BYTE const fhd = ((const BYTE *)src)[4]; - U32 const dictID = fhd & 3; - U32 const singleSegment = (fhd >> 5) & 1; - U32 const fcsId = fhd >> 6; - return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + (singleSegment && !fcsId); - } -} - -/** ZSTD_getFrameParams() : - * decode Frame Header, or require larger `srcSize`. - * @return : 0, `fparamsPtr` is correctly filled, - * >0, `srcSize` is too small, result is expected `srcSize`, - * or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize) -{ - const BYTE *ip = (const BYTE *)src; - - if (srcSize < ZSTD_frameHeaderSize_prefix) - return ZSTD_frameHeaderSize_prefix; - if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) - { - if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - { - if (srcSize < ZSTD_skippableHeaderSize) - return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */ - memset(fparamsPtr, 0, sizeof(*fparamsPtr)); - fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4); - fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */ - return 0; - } - return ERROR(prefix_unknown); - } - - /* ensure there is enough `srcSize` to fully read/decode frame header */ - { - size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize); - if (srcSize < fhsize) - return fhsize; - } - - { - BYTE const fhdByte = ip[4]; - size_t pos = 5; - U32 const dictIDSizeCode = fhdByte & 3; - U32 const checksumFlag = (fhdByte >> 2) & 1; - U32 const singleSegment = (fhdByte >> 5) & 1; - U32 const fcsID = fhdByte >> 6; - U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; - U32 windowSize = 0; - U32 dictID = 0; - U64 frameContentSize = 0; - if ((fhdByte & 0x08) != 0) - return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */ - if (!singleSegment) - { - BYTE const wlByte = ip[pos++]; - U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN; - if (windowLog > ZSTD_WINDOWLOG_MAX) - return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */ - windowSize = (1U << windowLog); - windowSize += (windowSize >> 3) * (wlByte & 7); - } - - switch (dictIDSizeCode) - { - default: /* impossible */ - case 0: - break; - case 1: - dictID = ip[pos]; - pos++; - break; - case 2: - dictID = MEM_readLE16(ip + pos); - pos += 2; - break; - case 3: - dictID = MEM_readLE32(ip + pos); - pos += 4; - break; - } - switch (fcsID) - { - default: /* impossible */ - case 0: - if (singleSegment) - frameContentSize = ip[pos]; - break; - case 1: - frameContentSize = MEM_readLE16(ip + pos) + 256; - break; - case 2: - frameContentSize = MEM_readLE32(ip + pos); - break; - case 3: - frameContentSize = MEM_readLE64(ip + pos); - break; - } - if (!windowSize) - windowSize = (U32)frameContentSize; - if (windowSize > windowSizeMax) - return ERROR(frameParameter_windowTooLarge); - fparamsPtr->frameContentSize = frameContentSize; - fparamsPtr->windowSize = windowSize; - fparamsPtr->dictID = dictID; - fparamsPtr->checksumFlag = checksumFlag; - } - return 0; -} - -/** ZSTD_getFrameContentSize() : - * compatible with legacy mode - * @return : decompressed size of the single frame pointed to be `src` if known, otherwise - * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined - * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */ -unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize) -{ -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) - { - unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize); - return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret; - } -#endif - { - ZSTD_frameParams fParams; - if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0) - return ZSTD_CONTENTSIZE_ERROR; - if (fParams.windowSize == 0) - { - /* Either skippable or empty frame, size == 0 either way */ - return 0; - } - else if (fParams.frameContentSize != 0) - { - return fParams.frameContentSize; - } - else - { - return ZSTD_CONTENTSIZE_UNKNOWN; - } - } -} - -/** ZSTD_findDecompressedSize() : - * compatible with legacy mode - * `srcSize` must be the exact length of some number of ZSTD compressed and/or - * skippable frames - * @return : decompressed size of the frames contained */ -unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize) -{ - { - unsigned long long totalDstSize = 0; - while (srcSize >= ZSTD_frameHeaderSize_prefix) - { - const U32 magicNumber = MEM_readLE32(src); - - if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - { - size_t skippableSize; - if (srcSize < ZSTD_skippableHeaderSize) - return ERROR(srcSize_wrong); - skippableSize = MEM_readLE32((const BYTE *)src + 4) + - ZSTD_skippableHeaderSize; - if (srcSize < skippableSize) - { - return ZSTD_CONTENTSIZE_ERROR; - } - - src = (const BYTE *)src + skippableSize; - srcSize -= skippableSize; - continue; - } - - { - unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); - if (ret >= ZSTD_CONTENTSIZE_ERROR) - return ret; - - /* check for overflow */ - if (totalDstSize + ret < totalDstSize) - return ZSTD_CONTENTSIZE_ERROR; - totalDstSize += ret; - } - { - size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize); - if (ZSTD_isError(frameSrcSize)) - { - return ZSTD_CONTENTSIZE_ERROR; - } - - src = (const BYTE *)src + frameSrcSize; - srcSize -= frameSrcSize; - } - } - - if (srcSize) - { - return ZSTD_CONTENTSIZE_ERROR; - } - - return totalDstSize; - } -} - -/** ZSTD_getDecompressedSize() : -* compatible with legacy mode -* @return : decompressed size if known, 0 otherwise - note : 0 can mean any of the following : - - decompressed size is not present within frame header - - frame header unknown / not supported - - frame header not complete (`srcSize` too small) */ -unsigned long long ZSTD_getDecompressedSize(const void *src, size_t srcSize) -{ - unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize); - return ret >= ZSTD_CONTENTSIZE_ERROR ? 0 : ret; -} - -/** ZSTD_decodeFrameHeader() : - * `headerSize` must be the size provided by ZSTD_frameHeaderSize(). - * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */ -static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize) -{ - size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize); - if (ZSTD_isError(result)) - return result; /* invalid header */ - if (result > 0) - return ERROR(srcSize_wrong); /* headerSize too small */ - if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) - return ERROR(dictionary_wrong); - if (dctx->fParams.checksumFlag) - XXH64_reset(&dctx->xxhState, 0); - return 0; -} - -typedef struct -{ - blockType_e blockType; - U32 lastBlock; - U32 origSize; -} blockProperties_t; - -/*! ZSTD_getcBlockSize() : - * Provides the size of compressed block from block header `src` */ -size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr) -{ - if (srcSize < ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - { - U32 const cBlockHeader = MEM_readLE24(src); - U32 const cSize = cBlockHeader >> 3; - bpPtr->lastBlock = cBlockHeader & 1; - bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3); - bpPtr->origSize = cSize; /* only useful for RLE */ - if (bpPtr->blockType == bt_rle) - return 1; - if (bpPtr->blockType == bt_reserved) - return ERROR(corruption_detected); - return cSize; - } -} - -static size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - if (srcSize > dstCapacity) - return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); - return srcSize; -} - -static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize, size_t regenSize) -{ - if (srcSize != 1) - return ERROR(srcSize_wrong); - if (regenSize > dstCapacity) - return ERROR(dstSize_tooSmall); - memset(dst, *(const BYTE *)src, regenSize); - return regenSize; -} - -/*! ZSTD_decodeLiteralsBlock() : - @return : nb of bytes read from src (< srcSize ) */ -size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, - const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ -{ - if (srcSize < MIN_CBLOCK_SIZE) - return ERROR(corruption_detected); - - { - const BYTE *const istart = (const BYTE *)src; - symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3); - - switch (litEncType) - { - case set_repeat: - if (dctx->litEntropy == 0) - return ERROR(dictionary_corrupted); - /* fall-through */ - case set_compressed: - if (srcSize < 5) - return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ - { - size_t lhSize, litSize, litCSize; - U32 singleStream = 0; - U32 const lhlCode = (istart[0] >> 2) & 3; - U32 const lhc = MEM_readLE32(istart); - switch (lhlCode) - { - case 0: - case 1: - default: /* note : default is impossible, since lhlCode into [0..3] */ - /* 2 - 2 - 10 - 10 */ - singleStream = !lhlCode; - lhSize = 3; - litSize = (lhc >> 4) & 0x3FF; - litCSize = (lhc >> 14) & 0x3FF; - break; - case 2: - /* 2 - 2 - 14 - 14 */ - lhSize = 4; - litSize = (lhc >> 4) & 0x3FFF; - litCSize = lhc >> 18; - break; - case 3: - /* 2 - 2 - 18 - 18 */ - lhSize = 5; - litSize = (lhc >> 4) & 0x3FFFF; - litCSize = (lhc >> 22) + (istart[4] << 10); - break; - } - if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) - return ERROR(corruption_detected); - if (litCSize + lhSize > srcSize) - return ERROR(corruption_detected); - - if (HUF_isError((litEncType == set_repeat) ? (singleStream ? HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr) : HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr)) : (singleStream ? HUF_decompress1X2_DCtx(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize) : HUF_decompress4X_hufOnly(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize)))) - return ERROR(corruption_detected); - - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - dctx->litEntropy = 1; - if (litEncType == set_compressed) - dctx->HUFptr = dctx->entropy.hufTable; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); - return litCSize + lhSize; - } - - case set_basic: - { - size_t litSize, lhSize; - U32 const lhlCode = ((istart[0]) >> 2) & 3; - switch (lhlCode) - { - case 0: - case 2: - default: /* note : default is impossible, since lhlCode into [0..3] */ - lhSize = 1; - litSize = istart[0] >> 3; - break; - case 1: - lhSize = 2; - litSize = MEM_readLE16(istart) >> 4; - break; - case 3: - lhSize = 3; - litSize = MEM_readLE24(istart) >> 4; - break; - } - - if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize) - { /* risk reading beyond src buffer with wildcopy */ - if (litSize + lhSize > srcSize) - return ERROR(corruption_detected); - memcpy(dctx->litBuffer, istart + lhSize, litSize); - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); - return lhSize + litSize; - } - /* direct reference into compressed stream */ - dctx->litPtr = istart + lhSize; - dctx->litSize = litSize; - return lhSize + litSize; - } - - case set_rle: - { - U32 const lhlCode = ((istart[0]) >> 2) & 3; - size_t litSize, lhSize; - switch (lhlCode) - { - case 0: - case 2: - default: /* note : default is impossible, since lhlCode into [0..3] */ - lhSize = 1; - litSize = istart[0] >> 3; - break; - case 1: - lhSize = 2; - litSize = MEM_readLE16(istart) >> 4; - break; - case 3: - lhSize = 3; - litSize = MEM_readLE24(istart) >> 4; - if (srcSize < 4) - return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */ - break; - } - if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) - return ERROR(corruption_detected); - memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); - dctx->litPtr = dctx->litBuffer; - dctx->litSize = litSize; - return lhSize + 1; - } - default: - return ERROR(corruption_detected); /* impossible */ - } - } -} - -typedef union -{ - FSE_decode_t realData; - U32 alignedBy4; -} FSE_decode_t4; - -static const FSE_decode_t4 LL_defaultDTable[(1 << LL_DEFAULTNORMLOG) + 1] = { - {{LL_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ - {{0, 0, 4}}, /* 0 : base, symbol, bits */ - {{16, 0, 4}}, - {{32, 1, 5}}, - {{0, 3, 5}}, - {{0, 4, 5}}, - {{0, 6, 5}}, - {{0, 7, 5}}, - {{0, 9, 5}}, - {{0, 10, 5}}, - {{0, 12, 5}}, - {{0, 14, 6}}, - {{0, 16, 5}}, - {{0, 18, 5}}, - {{0, 19, 5}}, - {{0, 21, 5}}, - {{0, 22, 5}}, - {{0, 24, 5}}, - {{32, 25, 5}}, - {{0, 26, 5}}, - {{0, 27, 6}}, - {{0, 29, 6}}, - {{0, 31, 6}}, - {{32, 0, 4}}, - {{0, 1, 4}}, - {{0, 2, 5}}, - {{32, 4, 5}}, - {{0, 5, 5}}, - {{32, 7, 5}}, - {{0, 8, 5}}, - {{32, 10, 5}}, - {{0, 11, 5}}, - {{0, 13, 6}}, - {{32, 16, 5}}, - {{0, 17, 5}}, - {{32, 19, 5}}, - {{0, 20, 5}}, - {{32, 22, 5}}, - {{0, 23, 5}}, - {{0, 25, 4}}, - {{16, 25, 4}}, - {{32, 26, 5}}, - {{0, 28, 6}}, - {{0, 30, 6}}, - {{48, 0, 4}}, - {{16, 1, 4}}, - {{32, 2, 5}}, - {{32, 3, 5}}, - {{32, 5, 5}}, - {{32, 6, 5}}, - {{32, 8, 5}}, - {{32, 9, 5}}, - {{32, 11, 5}}, - {{32, 12, 5}}, - {{0, 15, 6}}, - {{32, 17, 5}}, - {{32, 18, 5}}, - {{32, 20, 5}}, - {{32, 21, 5}}, - {{32, 23, 5}}, - {{32, 24, 5}}, - {{0, 35, 6}}, - {{0, 34, 6}}, - {{0, 33, 6}}, - {{0, 32, 6}}, -}; /* LL_defaultDTable */ - -static const FSE_decode_t4 ML_defaultDTable[(1 << ML_DEFAULTNORMLOG) + 1] = { - {{ML_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ - {{0, 0, 6}}, /* 0 : base, symbol, bits */ - {{0, 1, 4}}, - {{32, 2, 5}}, - {{0, 3, 5}}, - {{0, 5, 5}}, - {{0, 6, 5}}, - {{0, 8, 5}}, - {{0, 10, 6}}, - {{0, 13, 6}}, - {{0, 16, 6}}, - {{0, 19, 6}}, - {{0, 22, 6}}, - {{0, 25, 6}}, - {{0, 28, 6}}, - {{0, 31, 6}}, - {{0, 33, 6}}, - {{0, 35, 6}}, - {{0, 37, 6}}, - {{0, 39, 6}}, - {{0, 41, 6}}, - {{0, 43, 6}}, - {{0, 45, 6}}, - {{16, 1, 4}}, - {{0, 2, 4}}, - {{32, 3, 5}}, - {{0, 4, 5}}, - {{32, 6, 5}}, - {{0, 7, 5}}, - {{0, 9, 6}}, - {{0, 12, 6}}, - {{0, 15, 6}}, - {{0, 18, 6}}, - {{0, 21, 6}}, - {{0, 24, 6}}, - {{0, 27, 6}}, - {{0, 30, 6}}, - {{0, 32, 6}}, - {{0, 34, 6}}, - {{0, 36, 6}}, - {{0, 38, 6}}, - {{0, 40, 6}}, - {{0, 42, 6}}, - {{0, 44, 6}}, - {{32, 1, 4}}, - {{48, 1, 4}}, - {{16, 2, 4}}, - {{32, 4, 5}}, - {{32, 5, 5}}, - {{32, 7, 5}}, - {{32, 8, 5}}, - {{0, 11, 6}}, - {{0, 14, 6}}, - {{0, 17, 6}}, - {{0, 20, 6}}, - {{0, 23, 6}}, - {{0, 26, 6}}, - {{0, 29, 6}}, - {{0, 52, 6}}, - {{0, 51, 6}}, - {{0, 50, 6}}, - {{0, 49, 6}}, - {{0, 48, 6}}, - {{0, 47, 6}}, - {{0, 46, 6}}, -}; /* ML_defaultDTable */ - -static const FSE_decode_t4 OF_defaultDTable[(1 << OF_DEFAULTNORMLOG) + 1] = { - {{OF_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */ - {{0, 0, 5}}, /* 0 : base, symbol, bits */ - {{0, 6, 4}}, - {{0, 9, 5}}, - {{0, 15, 5}}, - {{0, 21, 5}}, - {{0, 3, 5}}, - {{0, 7, 4}}, - {{0, 12, 5}}, - {{0, 18, 5}}, - {{0, 23, 5}}, - {{0, 5, 5}}, - {{0, 8, 4}}, - {{0, 14, 5}}, - {{0, 20, 5}}, - {{0, 2, 5}}, - {{16, 7, 4}}, - {{0, 11, 5}}, - {{0, 17, 5}}, - {{0, 22, 5}}, - {{0, 4, 5}}, - {{16, 8, 4}}, - {{0, 13, 5}}, - {{0, 19, 5}}, - {{0, 1, 5}}, - {{16, 6, 4}}, - {{0, 10, 5}}, - {{0, 16, 5}}, - {{0, 28, 5}}, - {{0, 27, 5}}, - {{0, 26, 5}}, - {{0, 25, 5}}, - {{0, 24, 5}}, -}; /* OF_defaultDTable */ - -/*! ZSTD_buildSeqTable() : - @return : nb bytes read from src, - or an error code if it fails, testable with ZSTD_isError() -*/ -static size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTablePtr, - symbolEncodingType_e type, U32 max, U32 maxLog, - const void *src, size_t srcSize, - const FSE_decode_t4 *defaultTable, U32 flagRepeatTable) -{ - const void *const tmpPtr = defaultTable; /* bypass strict aliasing */ - switch (type) - { - case set_rle: - if (!srcSize) - return ERROR(srcSize_wrong); - if ((*(const BYTE *)src) > max) - return ERROR(corruption_detected); - FSE_buildDTable_rle(DTableSpace, *(const BYTE *)src); - *DTablePtr = DTableSpace; - return 1; - case set_basic: - *DTablePtr = (const FSE_DTable *)tmpPtr; - return 0; - case set_repeat: - if (!flagRepeatTable) - return ERROR(corruption_detected); - return 0; - default: /* impossible */ - case set_compressed: - { - U32 tableLog; - S16 norm[MaxSeq + 1]; - size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); - if (FSE_isError(headerSize)) - return ERROR(corruption_detected); - if (tableLog > maxLog) - return ERROR(corruption_detected); - FSE_buildDTable(DTableSpace, norm, max, tableLog); - *DTablePtr = DTableSpace; - return headerSize; - } - } -} - -size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, - const void *src, size_t srcSize) -{ - const BYTE *const istart = (const BYTE *const)src; - const BYTE *const iend = istart + srcSize; - const BYTE *ip = istart; - - /* check */ - if (srcSize < MIN_SEQUENCES_SIZE) - return ERROR(srcSize_wrong); - - /* SeqHead */ - { - int nbSeq = *ip++; - if (!nbSeq) - { - *nbSeqPtr = 0; - return 1; - } - if (nbSeq > 0x7F) - { - if (nbSeq == 0xFF) - { - if (ip + 2 > iend) - return ERROR(srcSize_wrong); - nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip += 2; - } - else - { - if (ip >= iend) - return ERROR(srcSize_wrong); - nbSeq = ((nbSeq - 0x80) << 8) + *ip++; - } - } - *nbSeqPtr = nbSeq; - } - - /* FSE table descriptors */ - if (ip + 4 > iend) - return ERROR(srcSize_wrong); /* minimum possible size */ - { - symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6); - symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3); - symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3); - ip++; - - /* Build DTables */ - { - size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, - LLtype, MaxLL, LLFSELog, - ip, iend - ip, LL_defaultDTable, dctx->fseEntropy); - if (ZSTD_isError(llhSize)) - return ERROR(corruption_detected); - ip += llhSize; - } - { - size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, - OFtype, MaxOff, OffFSELog, - ip, iend - ip, OF_defaultDTable, dctx->fseEntropy); - if (ZSTD_isError(ofhSize)) - return ERROR(corruption_detected); - ip += ofhSize; - } - { - size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, - MLtype, MaxML, MLFSELog, - ip, iend - ip, ML_defaultDTable, dctx->fseEntropy); - if (ZSTD_isError(mlhSize)) - return ERROR(corruption_detected); - ip += mlhSize; - } - } - - return ip - istart; -} - -typedef struct -{ - size_t litLength; - size_t matchLength; - size_t offset; - const BYTE *match; -} seq_t; - -typedef struct -{ - BIT_DStream_t DStream; - FSE_DState_t stateLL; - FSE_DState_t stateOffb; - FSE_DState_t stateML; - size_t prevOffset[ZSTD_REP_NUM]; - const BYTE *base; - size_t pos; - uPtrDiff gotoDict; -} seqState_t; - -FORCE_NOINLINE -size_t ZSTD_execSequenceLast7(BYTE *op, - BYTE *const oend, seq_t sequence, - const BYTE **litPtr, const BYTE *const litLimit, - const BYTE *const base, const BYTE *const vBase, const BYTE *const dictEnd) -{ - BYTE *const oLitEnd = op + sequence.litLength; - size_t const sequenceLength = sequence.litLength + sequence.matchLength; - BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; - const BYTE *const iLitEnd = *litPtr + sequence.litLength; - const BYTE *match = oLitEnd - sequence.offset; - - /* check */ - if (oMatchEnd > oend) - return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ - if (iLitEnd > litLimit) - return ERROR(corruption_detected); /* over-read beyond lit buffer */ - if (oLitEnd <= oend_w) - return ERROR(GENERIC); /* Precondition */ - - /* copy literals */ - if (op < oend_w) - { - ZSTD_wildcopy(op, *litPtr, oend_w - op); - *litPtr += oend_w - op; - op = oend_w; - } - while (op < oLitEnd) - *op++ = *(*litPtr)++; - - /* copy Match */ - if (sequence.offset > (size_t)(oLitEnd - base)) - { - /* offset beyond prefix */ - if (sequence.offset > (size_t)(oLitEnd - vBase)) - return ERROR(corruption_detected); - match = dictEnd - (base - match); - if (match + sequence.matchLength <= dictEnd) - { - memmove(oLitEnd, match, sequence.matchLength); - return sequenceLength; - } - /* span extDict & currentPrefixSegment */ - { - size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); - op = oLitEnd + length1; - sequence.matchLength -= length1; - match = base; - } - } - while (op < oMatchEnd) - *op++ = *match++; - return sequenceLength; -} - -static seq_t ZSTD_decodeSequence(seqState_t *seqState) -{ - seq_t seq; - - U32 const llCode = FSE_peekSymbol(&seqState->stateLL); - U32 const mlCode = FSE_peekSymbol(&seqState->stateML); - U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */ - - U32 const llBits = LL_bits[llCode]; - U32 const mlBits = ML_bits[mlCode]; - U32 const ofBits = ofCode; - U32 const totalBits = llBits + mlBits + ofBits; - - static const U32 LL_base[MaxLL + 1] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, - 0x2000, 0x4000, 0x8000, 0x10000}; - - static const U32 ML_base[MaxML + 1] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, - 0x1003, 0x2003, 0x4003, 0x8003, 0x10003}; - - static const U32 OF_base[MaxOff + 1] = { - 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, - 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, - 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, - 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD}; - - /* sequence */ - { - size_t offset; - if (!ofCode) - offset = 0; - else - { - offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); - } - - if (ofCode <= 1) - { - offset += (llCode == 0); - if (offset) - { - size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ - if (offset != 1) - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset = temp; - } - else - { - offset = seqState->prevOffset[0]; - } - } - else - { - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset; - } - seq.offset = offset; - } - - seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ - if (MEM_32bits() && (mlBits + llBits > 24)) - BIT_reloadDStream(&seqState->DStream); - - seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ - if (MEM_32bits() || - (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) - BIT_reloadDStream(&seqState->DStream); - - /* ANS state update */ - FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ - FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ - - return seq; -} - -FORCE_INLINE -size_t ZSTD_execSequence(BYTE *op, - BYTE *const oend, seq_t sequence, - const BYTE **litPtr, const BYTE *const litLimit, - const BYTE *const base, const BYTE *const vBase, const BYTE *const dictEnd) -{ - BYTE *const oLitEnd = op + sequence.litLength; - size_t const sequenceLength = sequence.litLength + sequence.matchLength; - BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; - const BYTE *const iLitEnd = *litPtr + sequence.litLength; - const BYTE *match = oLitEnd - sequence.offset; - - /* check */ - if (oMatchEnd > oend) - return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ - if (iLitEnd > litLimit) - return ERROR(corruption_detected); /* over-read beyond lit buffer */ - if (oLitEnd > oend_w) - return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd); - - /* copy Literals */ - ZSTD_copy8(op, *litPtr); - if (sequence.litLength > 8) - ZSTD_wildcopy(op + 8, (*litPtr) + 8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ - op = oLitEnd; - *litPtr = iLitEnd; /* update for next sequence */ - - /* copy Match */ - if (sequence.offset > (size_t)(oLitEnd - base)) - { - /* offset beyond prefix */ - if (sequence.offset > (size_t)(oLitEnd - vBase)) - return ERROR(corruption_detected); - match = dictEnd + (match - base); - if (match + sequence.matchLength <= dictEnd) - { - memmove(oLitEnd, match, sequence.matchLength); - return sequenceLength; - } - /* span extDict & currentPrefixSegment */ - { - size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); - op = oLitEnd + length1; - sequence.matchLength -= length1; - match = base; - if (op > oend_w || sequence.matchLength < MINMATCH) - { - U32 i; - for (i = 0; i < sequence.matchLength; ++i) - op[i] = match[i]; - return sequenceLength; - } - } - } - /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */ - - /* match within prefix */ - if (sequence.offset < 8) - { - /* close range match, overlap */ - static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ - static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */ - int const sub2 = dec64table[sequence.offset]; - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += dec32table[sequence.offset]; - ZSTD_copy4(op + 4, match); - match -= sub2; - } - else - { - ZSTD_copy8(op, match); - } - op += 8; - match += 8; - - if (oMatchEnd > oend - (16 - MINMATCH)) - { - if (op < oend_w) - { - ZSTD_wildcopy(op, match, oend_w - op); - match += oend_w - op; - op = oend_w; - } - while (op < oMatchEnd) - *op++ = *match++; - } - else - { - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */ - } - return sequenceLength; -} - -static size_t ZSTD_decompressSequences( - ZSTD_DCtx *dctx, - void *dst, size_t maxDstSize, - const void *seqStart, size_t seqSize) -{ - const BYTE *ip = (const BYTE *)seqStart; - const BYTE *const iend = ip + seqSize; - BYTE *const ostart = (BYTE *const)dst; - BYTE *const oend = ostart + maxDstSize; - BYTE *op = ostart; - const BYTE *litPtr = dctx->litPtr; - const BYTE *const litEnd = litPtr + dctx->litSize; - const BYTE *const base = (const BYTE *)(dctx->base); - const BYTE *const vBase = (const BYTE *)(dctx->vBase); - const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd); - int nbSeq; - - /* Build Decoding Tables */ - { - size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize); - if (ZSTD_isError(seqHSize)) - return seqHSize; - ip += seqHSize; - } - - /* Regen sequences */ - if (nbSeq) - { - seqState_t seqState; - dctx->fseEntropy = 1; - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - seqState.prevOffset[i] = dctx->entropy.rep[i]; - } - CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected); - FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); - FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); - FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); - - for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq;) - { - nbSeq--; - { - seq_t const sequence = ZSTD_decodeSequence(&seqState); - size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd); - if (ZSTD_isError(oneSeqSize)) - return oneSeqSize; - op += oneSeqSize; - } - } - - /* check if reached exact end */ - if (nbSeq) - return ERROR(corruption_detected); - /* save reps for next block */ - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); - } - } - - /* last literal segment */ - { - size_t const lastLLSize = litEnd - litPtr; - if (lastLLSize > (size_t)(oend - op)) - return ERROR(dstSize_tooSmall); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; - } - - return op - ostart; -} - -FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t *seqState, int const longOffsets) -{ - seq_t seq; - - U32 const llCode = FSE_peekSymbol(&seqState->stateLL); - U32 const mlCode = FSE_peekSymbol(&seqState->stateML); - U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */ - - U32 const llBits = LL_bits[llCode]; - U32 const mlBits = ML_bits[mlCode]; - U32 const ofBits = ofCode; - U32 const totalBits = llBits + mlBits + ofBits; - - static const U32 LL_base[MaxLL + 1] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, - 0x2000, 0x4000, 0x8000, 0x10000}; - - static const U32 ML_base[MaxML + 1] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, - 0x1003, 0x2003, 0x4003, 0x8003, 0x10003}; - - static const U32 OF_base[MaxOff + 1] = { - 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, - 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, - 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, - 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD}; - - /* sequence */ - { - size_t offset; - if (!ofCode) - offset = 0; - else - { - if (longOffsets) - { - int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN); - offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits); - if (MEM_32bits() || extraBits) - BIT_reloadDStream(&seqState->DStream); - if (extraBits) - offset += BIT_readBitsFast(&seqState->DStream, extraBits); - } - else - { - offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */ - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); - } - } - - if (ofCode <= 1) - { - offset += (llCode == 0); - if (offset) - { - size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset]; - temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */ - if (offset != 1) - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset = temp; - } - else - { - offset = seqState->prevOffset[0]; - } - } - else - { - seqState->prevOffset[2] = seqState->prevOffset[1]; - seqState->prevOffset[1] = seqState->prevOffset[0]; - seqState->prevOffset[0] = offset; - } - seq.offset = offset; - } - - seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */ - if (MEM_32bits() && (mlBits + llBits > 24)) - BIT_reloadDStream(&seqState->DStream); - - seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */ - if (MEM_32bits() || - (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog))) - BIT_reloadDStream(&seqState->DStream); - - { - size_t const pos = seqState->pos + seq.litLength; - seq.match = seqState->base + pos - seq.offset; /* single memory segment */ - if (seq.offset > pos) - seq.match += seqState->gotoDict; /* separate memory segment */ - seqState->pos = pos + seq.matchLength; - } - - /* ANS state update */ - FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ - FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ - if (MEM_32bits()) - BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ - FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ - - return seq; -} - -static seq_t ZSTD_decodeSequenceLong(seqState_t *seqState, unsigned const windowSize) -{ - if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) - { - return ZSTD_decodeSequenceLong_generic(seqState, 1); - } - else - { - return ZSTD_decodeSequenceLong_generic(seqState, 0); - } -} - -FORCE_INLINE -size_t ZSTD_execSequenceLong(BYTE *op, - BYTE *const oend, seq_t sequence, - const BYTE **litPtr, const BYTE *const litLimit, - const BYTE *const base, const BYTE *const vBase, const BYTE *const dictEnd) -{ - BYTE *const oLitEnd = op + sequence.litLength; - size_t const sequenceLength = sequence.litLength + sequence.matchLength; - BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */ - BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH; - const BYTE *const iLitEnd = *litPtr + sequence.litLength; - const BYTE *match = sequence.match; - - /* check */ -#if 1 - if (oMatchEnd > oend) - return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */ - if (iLitEnd > litLimit) - return ERROR(corruption_detected); /* over-read beyond lit buffer */ - if (oLitEnd > oend_w) - return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd); -#endif - - /* copy Literals */ - ZSTD_copy8(op, *litPtr); - if (sequence.litLength > 8) - ZSTD_wildcopy(op + 8, (*litPtr) + 8, sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */ - op = oLitEnd; - *litPtr = iLitEnd; /* update for next sequence */ - - /* copy Match */ -#if 1 - if (sequence.offset > (size_t)(oLitEnd - base)) - { - /* offset beyond prefix */ - if (sequence.offset > (size_t)(oLitEnd - vBase)) - return ERROR(corruption_detected); - if (match + sequence.matchLength <= dictEnd) - { - memmove(oLitEnd, match, sequence.matchLength); - return sequenceLength; - } - /* span extDict & currentPrefixSegment */ - { - size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); - op = oLitEnd + length1; - sequence.matchLength -= length1; - match = base; - if (op > oend_w || sequence.matchLength < MINMATCH) - { - U32 i; - for (i = 0; i < sequence.matchLength; ++i) - op[i] = match[i]; - return sequenceLength; - } - } - } - /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */ -#endif - - /* match within prefix */ - if (sequence.offset < 8) - { - /* close range match, overlap */ - static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ - static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */ - int const sub2 = dec64table[sequence.offset]; - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += dec32table[sequence.offset]; - ZSTD_copy4(op + 4, match); - match -= sub2; - } - else - { - ZSTD_copy8(op, match); - } - op += 8; - match += 8; - - if (oMatchEnd > oend - (16 - MINMATCH)) - { - if (op < oend_w) - { - ZSTD_wildcopy(op, match, oend_w - op); - match += oend_w - op; - op = oend_w; - } - while (op < oMatchEnd) - *op++ = *match++; - } - else - { - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */ - } - return sequenceLength; -} - -static size_t ZSTD_decompressSequencesLong( - ZSTD_DCtx *dctx, - void *dst, size_t maxDstSize, - const void *seqStart, size_t seqSize) -{ - const BYTE *ip = (const BYTE *)seqStart; - const BYTE *const iend = ip + seqSize; - BYTE *const ostart = (BYTE *const)dst; - BYTE *const oend = ostart + maxDstSize; - BYTE *op = ostart; - const BYTE *litPtr = dctx->litPtr; - const BYTE *const litEnd = litPtr + dctx->litSize; - const BYTE *const base = (const BYTE *)(dctx->base); - const BYTE *const vBase = (const BYTE *)(dctx->vBase); - const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd); - unsigned const windowSize = dctx->fParams.windowSize; - int nbSeq; - - /* Build Decoding Tables */ - { - size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize); - if (ZSTD_isError(seqHSize)) - return seqHSize; - ip += seqHSize; - } - - /* Regen sequences */ - if (nbSeq) - { -#define STORED_SEQS 4 -#define STOSEQ_MASK (STORED_SEQS - 1) -#define ADVANCED_SEQS 4 - seq_t sequences[STORED_SEQS]; - int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS); - seqState_t seqState; - int seqNb; - dctx->fseEntropy = 1; - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - seqState.prevOffset[i] = dctx->entropy.rep[i]; - } - seqState.base = base; - seqState.pos = (size_t)(op - base); - seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */ - CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected); - FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); - FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr); - FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr); - - /* prepare in advance */ - for (seqNb = 0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb < seqAdvance; seqNb++) - { - sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize); - } - if (seqNb < seqAdvance) - return ERROR(corruption_detected); - - /* decode and decompress */ - for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb < nbSeq; seqNb++) - { - seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize); - size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd); - if (ZSTD_isError(oneSeqSize)) - return oneSeqSize; - ZSTD_PREFETCH(sequence.match); - sequences[seqNb & STOSEQ_MASK] = sequence; - op += oneSeqSize; - } - if (seqNb < nbSeq) - return ERROR(corruption_detected); - - /* finish queue */ - seqNb -= seqAdvance; - for (; seqNb < nbSeq; seqNb++) - { - size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd); - if (ZSTD_isError(oneSeqSize)) - return oneSeqSize; - op += oneSeqSize; - } - - /* save reps for next block */ - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); - } - } - - /* last literal segment */ - { - size_t const lastLLSize = litEnd - litPtr; - if (lastLLSize > (size_t)(oend - op)) - return ERROR(dstSize_tooSmall); - memcpy(op, litPtr, lastLLSize); - op += lastLLSize; - } - - return op - ostart; -} - -static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize) -{ /* blockType == blockCompressed */ - const BYTE *ip = (const BYTE *)src; - - if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) - return ERROR(srcSize_wrong); - - /* Decode literals section */ - { - size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize); - if (ZSTD_isError(litCSize)) - return litCSize; - ip += litCSize; - srcSize -= litCSize; - } - if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */ - /* likely because of register pressure */ - /* if that's the correct cause, then 32-bits ARM should be affected differently */ - /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */ - if (dctx->fParams.windowSize > (1 << 23)) - return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize); - return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize); -} - -static void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst) -{ - if (dst != dctx->previousDstEnd) - { /* not contiguous */ - dctx->dictEnd = dctx->previousDstEnd; - dctx->vBase = (const char *)dst - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base)); - dctx->base = dst; - dctx->previousDstEnd = dst; - } -} - -size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize) -{ - size_t dSize; - ZSTD_checkContinuity(dctx, dst); - dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); - dctx->previousDstEnd = (char *)dst + dSize; - return dSize; -} - -/** ZSTD_insertBlock() : - insert `src` block into `dctx` history. Useful to track uncompressed blocks. */ -ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize) -{ - ZSTD_checkContinuity(dctx, blockStart); - dctx->previousDstEnd = (const char *)blockStart + blockSize; - return blockSize; -} - -size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length) -{ - if (length > dstCapacity) - return ERROR(dstSize_tooSmall); - memset(dst, byte, length); - return length; -} - -/** ZSTD_findFrameCompressedSize() : - * compatible with legacy mode - * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame - * `srcSize` must be at least as large as the frame contained - * @return : the compressed size of the frame starting at `src` */ -size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) -{ -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) - return ZSTD_findFrameCompressedSizeLegacy(src, srcSize); -#endif - if (srcSize >= ZSTD_skippableHeaderSize && - (MEM_readLE32(src) & 0xFFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - { - return ZSTD_skippableHeaderSize + MEM_readLE32((const BYTE *)src + 4); - } - else - { - const BYTE *ip = (const BYTE *)src; - const BYTE *const ipstart = ip; - size_t remainingSize = srcSize; - ZSTD_frameParams fParams; - - size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize); - if (ZSTD_isError(headerSize)) - return headerSize; - - /* Frame Header */ - { - size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize); - if (ZSTD_isError(ret)) - return ret; - if (ret > 0) - return ERROR(srcSize_wrong); - } - - ip += headerSize; - remainingSize -= headerSize; - - /* Loop on each block */ - while (1) - { - blockProperties_t blockProperties; - size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTD_isError(cBlockSize)) - return cBlockSize; - - if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) - return ERROR(srcSize_wrong); - - ip += ZSTD_blockHeaderSize + cBlockSize; - remainingSize -= ZSTD_blockHeaderSize + cBlockSize; - - if (blockProperties.lastBlock) - break; - } - - if (fParams.checksumFlag) - { /* Frame content checksum */ - if (remainingSize < 4) - return ERROR(srcSize_wrong); - ip += 4; - remainingSize -= 4; - } - - return ip - ipstart; - } -} - -/*! ZSTD_decompressFrame() : - * @dctx must be properly initialized */ -static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void **srcPtr, size_t *srcSizePtr) -{ - const BYTE *ip = (const BYTE *)(*srcPtr); - BYTE *const ostart = (BYTE *const)dst; - BYTE *const oend = ostart + dstCapacity; - BYTE *op = ostart; - size_t remainingSize = *srcSizePtr; - - /* check */ - if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - - /* Frame Header */ - { - size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix); - if (ZSTD_isError(frameHeaderSize)) - return frameHeaderSize; - if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize)); - ip += frameHeaderSize; - remainingSize -= frameHeaderSize; - } - - /* Loop on each block */ - while (1) - { - size_t decodedSize; - blockProperties_t blockProperties; - size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTD_isError(cBlockSize)) - return cBlockSize; - - ip += ZSTD_blockHeaderSize; - remainingSize -= ZSTD_blockHeaderSize; - if (cBlockSize > remainingSize) - return ERROR(srcSize_wrong); - - switch (blockProperties.blockType) - { - case bt_compressed: - decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); - break; - case bt_raw: - decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); - break; - case bt_rle: - decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); - break; - case bt_reserved: - default: - return ERROR(corruption_detected); - } - - if (ZSTD_isError(decodedSize)) - return decodedSize; - if (dctx->fParams.checksumFlag) - XXH64_update(&dctx->xxhState, op, decodedSize); - op += decodedSize; - ip += cBlockSize; - remainingSize -= cBlockSize; - if (blockProperties.lastBlock) - break; - } - - if (dctx->fParams.checksumFlag) - { /* Frame content checksum verification */ - U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); - U32 checkRead; - if (remainingSize < 4) - return ERROR(checksum_wrong); - checkRead = MEM_readLE32(ip); - if (checkRead != checkCalc) - return ERROR(checksum_wrong); - ip += 4; - remainingSize -= 4; - } - - /* Allow caller to get size read */ - *srcPtr = ip; - *srcSizePtr = remainingSize; - return op - ostart; -} - -static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict); -static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict); - -static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize, - const ZSTD_DDict *ddict) -{ - void *const dststart = dst; - - if (ddict) - { - if (dict) - { - /* programmer error, these two cases should be mutually exclusive */ - return ERROR(GENERIC); - } - - dict = ZSTD_DDictDictContent(ddict); - dictSize = ZSTD_DDictDictSize(ddict); - } - - while (srcSize >= ZSTD_frameHeaderSize_prefix) - { - U32 magicNumber; - -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) - { - size_t decodedSize; - size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize); - if (ZSTD_isError(frameSize)) - return frameSize; - - decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); - - dst = (BYTE *)dst + decodedSize; - dstCapacity -= decodedSize; - - src = (const BYTE *)src + frameSize; - srcSize -= frameSize; - - continue; - } -#endif - - magicNumber = MEM_readLE32(src); - if (magicNumber != ZSTD_MAGICNUMBER) - { - if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - { - size_t skippableSize; - if (srcSize < ZSTD_skippableHeaderSize) - return ERROR(srcSize_wrong); - skippableSize = MEM_readLE32((const BYTE *)src + 4) + - ZSTD_skippableHeaderSize; - if (srcSize < skippableSize) - { - return ERROR(srcSize_wrong); - } - - src = (const BYTE *)src + skippableSize; - srcSize -= skippableSize; - continue; - } - else - { - return ERROR(prefix_unknown); - } - } - - if (ddict) - { - /* we were called from ZSTD_decompress_usingDDict */ - ZSTD_refDDict(dctx, ddict); - } - else - { - /* this will initialize correctly with no dict if dict == NULL, so - * use this in all cases but ddict */ - CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize)); - } - ZSTD_checkContinuity(dctx, dst); - - { - const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, - &src, &srcSize); - if (ZSTD_isError(res)) - return res; - /* don't need to bounds check this, ZSTD_decompressFrame will have - * already */ - dst = (BYTE *)dst + res; - dstCapacity -= res; - } - } - - if (srcSize) - return ERROR(srcSize_wrong); /* input not entirely consumed */ - - return (BYTE *)dst - (BYTE *)dststart; -} - -size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const void *dict, size_t dictSize) -{ - return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL); -} - -size_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0); -} - -size_t ZSTD_decompress(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ -#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE == 1) - size_t regenSize; - ZSTD_DCtx *const dctx = ZSTD_createDCtx(); - if (dctx == NULL) - return ERROR(memory_allocation); - regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); - ZSTD_freeDCtx(dctx); - return regenSize; -#else /* stack mode */ - ZSTD_DCtx dctx; - return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize); -#endif -} - -/*-************************************** - * Advanced Streaming Decompression API - * Bufferless and synchronous - ****************************************/ -size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx) { return dctx->expected; } - -ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx) -{ - switch (dctx->stage) - { - default: /* should not happen */ - case ZSTDds_getFrameHeaderSize: - case ZSTDds_decodeFrameHeader: - return ZSTDnit_frameHeader; - case ZSTDds_decodeBlockHeader: - return ZSTDnit_blockHeader; - case ZSTDds_decompressBlock: - return ZSTDnit_block; - case ZSTDds_decompressLastBlock: - return ZSTDnit_lastBlock; - case ZSTDds_checkChecksum: - return ZSTDnit_checksum; - case ZSTDds_decodeSkippableHeader: - case ZSTDds_skipFrame: - return ZSTDnit_skippableFrame; - } -} - -int ZSTD_isSkipFrame(ZSTD_DCtx *dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */ - -/** ZSTD_decompressContinue() : - * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity) - * or an error code, which can be tested using ZSTD_isError() */ -size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - /* Sanity check */ - if (srcSize != dctx->expected) - return ERROR(srcSize_wrong); - if (dstCapacity) - ZSTD_checkContinuity(dctx, dst); - - switch (dctx->stage) - { - case ZSTDds_getFrameHeaderSize: - if (srcSize != ZSTD_frameHeaderSize_prefix) - return ERROR(srcSize_wrong); /* impossible */ - if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) - { /* skippable frame */ - memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix); - dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */ - dctx->stage = ZSTDds_decodeSkippableHeader; - return 0; - } - dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix); - if (ZSTD_isError(dctx->headerSize)) - return dctx->headerSize; - memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix); - if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) - { - dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix; - dctx->stage = ZSTDds_decodeFrameHeader; - return 0; - } - /* fall through */ - dctx->expected = 0; /* not necessary to copy more */ - - case ZSTDds_decodeFrameHeader: - memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); - CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize)); - dctx->expected = ZSTD_blockHeaderSize; - dctx->stage = ZSTDds_decodeBlockHeader; - return 0; - - case ZSTDds_decodeBlockHeader: - { - blockProperties_t bp; - size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); - if (ZSTD_isError(cBlockSize)) - return cBlockSize; - dctx->expected = cBlockSize; - dctx->bType = bp.blockType; - dctx->rleSize = bp.origSize; - if (cBlockSize) - { - dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock; - return 0; - } - /* empty block */ - if (bp.lastBlock) - { - if (dctx->fParams.checksumFlag) - { - dctx->expected = 4; - dctx->stage = ZSTDds_checkChecksum; - } - else - { - dctx->expected = 0; /* end of frame */ - dctx->stage = ZSTDds_getFrameHeaderSize; - } - } - else - { - dctx->expected = 3; /* go directly to next header */ - dctx->stage = ZSTDds_decodeBlockHeader; - } - return 0; - } - case ZSTDds_decompressLastBlock: - case ZSTDds_decompressBlock: - { - size_t rSize; - switch (dctx->bType) - { - case bt_compressed: - rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); - break; - case bt_raw: - rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); - break; - case bt_rle: - rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); - break; - case bt_reserved: /* should never happen */ - default: - return ERROR(corruption_detected); - } - if (ZSTD_isError(rSize)) - return rSize; - if (dctx->fParams.checksumFlag) - XXH64_update(&dctx->xxhState, dst, rSize); - - if (dctx->stage == ZSTDds_decompressLastBlock) - { /* end of frame */ - if (dctx->fParams.checksumFlag) - { /* another round for frame checksum */ - dctx->expected = 4; - dctx->stage = ZSTDds_checkChecksum; - } - else - { - dctx->expected = 0; /* ends here */ - dctx->stage = ZSTDds_getFrameHeaderSize; - } - } - else - { - dctx->stage = ZSTDds_decodeBlockHeader; - dctx->expected = ZSTD_blockHeaderSize; - dctx->previousDstEnd = (char *)dst + rSize; - } - return rSize; - } - case ZSTDds_checkChecksum: - { - U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); - U32 const check32 = MEM_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */ - if (check32 != h32) - return ERROR(checksum_wrong); - dctx->expected = 0; - dctx->stage = ZSTDds_getFrameHeaderSize; - return 0; - } - case ZSTDds_decodeSkippableHeader: - { - memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); - dctx->expected = MEM_readLE32(dctx->headerBuffer + 4); - dctx->stage = ZSTDds_skipFrame; - return 0; - } - case ZSTDds_skipFrame: - { - dctx->expected = 0; - dctx->stage = ZSTDds_getFrameHeaderSize; - return 0; - } - default: - return ERROR(GENERIC); /* impossible */ - } -} - -static size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) -{ - dctx->dictEnd = dctx->previousDstEnd; - dctx->vBase = (const char *)dict - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base)); - dctx->base = dict; - dctx->previousDstEnd = (const char *)dict + dictSize; - return 0; -} - -/* ZSTD_loadEntropy() : - * dict : must point at beginning of a valid zstd dictionary - * @return : size of entropy tables read */ -static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t *entropy, const void *const dict, size_t const dictSize) -{ - const BYTE *dictPtr = (const BYTE *)dict; - const BYTE *const dictEnd = dictPtr + dictSize; - - if (dictSize <= 8) - return ERROR(dictionary_corrupted); - dictPtr += 8; /* skip header = magic + dictID */ - - { - size_t const hSize = HUF_readDTableX4(entropy->hufTable, dictPtr, dictEnd - dictPtr); - if (HUF_isError(hSize)) - return ERROR(dictionary_corrupted); - dictPtr += hSize; - } - - { - short offcodeNCount[MaxOff + 1]; - U32 offcodeMaxValue = MaxOff, offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(offcodeHeaderSize)) - return ERROR(dictionary_corrupted); - if (offcodeLog > OffFSELog) - return ERROR(dictionary_corrupted); - CHECK_E(FSE_buildDTable(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog), dictionary_corrupted); - dictPtr += offcodeHeaderSize; - } - - { - short matchlengthNCount[MaxML + 1]; - unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(matchlengthHeaderSize)) - return ERROR(dictionary_corrupted); - if (matchlengthLog > MLFSELog) - return ERROR(dictionary_corrupted); - CHECK_E(FSE_buildDTable(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog), dictionary_corrupted); - dictPtr += matchlengthHeaderSize; - } - - { - short litlengthNCount[MaxLL + 1]; - unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr); - if (FSE_isError(litlengthHeaderSize)) - return ERROR(dictionary_corrupted); - if (litlengthLog > LLFSELog) - return ERROR(dictionary_corrupted); - CHECK_E(FSE_buildDTable(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog), dictionary_corrupted); - dictPtr += litlengthHeaderSize; - } - - if (dictPtr + 12 > dictEnd) - return ERROR(dictionary_corrupted); - { - int i; - size_t const dictContentSize = (size_t)(dictEnd - (dictPtr + 12)); - for (i = 0; i < 3; i++) - { - U32 const rep = MEM_readLE32(dictPtr); - dictPtr += 4; - if (rep == 0 || rep >= dictContentSize) - return ERROR(dictionary_corrupted); - entropy->rep[i] = rep; - } - } - - return dictPtr - (const BYTE *)dict; -} - -static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) -{ - if (dictSize < 8) - return ZSTD_refDictContent(dctx, dict, dictSize); - { - U32 const magic = MEM_readLE32(dict); - if (magic != ZSTD_DICT_MAGIC) - { - return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */ - } - } - dctx->dictID = MEM_readLE32((const char *)dict + 4); - - /* load entropy tables */ - { - size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize); - if (ZSTD_isError(eSize)) - return ERROR(dictionary_corrupted); - dict = (const char *)dict + eSize; - dictSize -= eSize; - } - dctx->litEntropy = dctx->fseEntropy = 1; - - /* reference dictionary content */ - return ZSTD_refDictContent(dctx, dict, dictSize); -} - -size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize) -{ - CHECK_F(ZSTD_decompressBegin(dctx)); - if (dict && dictSize) - CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted); - return 0; -} - -/* ====== ZSTD_DDict ====== */ - -struct ZSTD_DDict_s -{ - void *dictBuffer; - const void *dictContent; - size_t dictSize; - ZSTD_entropyTables_t entropy; - U32 dictID; - U32 entropyPresent; - ZSTD_customMem cMem; -}; /* typedef'd to ZSTD_DDict within "zstd.h" */ - -static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict) -{ - return ddict->dictContent; -} - -static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict) -{ - return ddict->dictSize; -} - -static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict) -{ - ZSTD_decompressBegin(dstDCtx); /* init */ - if (ddict) - { /* support refDDict on NULL */ - dstDCtx->dictID = ddict->dictID; - dstDCtx->base = ddict->dictContent; - dstDCtx->vBase = ddict->dictContent; - dstDCtx->dictEnd = (const BYTE *)ddict->dictContent + ddict->dictSize; - dstDCtx->previousDstEnd = dstDCtx->dictEnd; - if (ddict->entropyPresent) - { - dstDCtx->litEntropy = 1; - dstDCtx->fseEntropy = 1; - dstDCtx->LLTptr = ddict->entropy.LLTable; - dstDCtx->MLTptr = ddict->entropy.MLTable; - dstDCtx->OFTptr = ddict->entropy.OFTable; - dstDCtx->HUFptr = ddict->entropy.hufTable; - dstDCtx->entropy.rep[0] = ddict->entropy.rep[0]; - dstDCtx->entropy.rep[1] = ddict->entropy.rep[1]; - dstDCtx->entropy.rep[2] = ddict->entropy.rep[2]; - } - else - { - dstDCtx->litEntropy = 0; - dstDCtx->fseEntropy = 0; - } - } -} - -static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict *ddict) -{ - ddict->dictID = 0; - ddict->entropyPresent = 0; - if (ddict->dictSize < 8) - return 0; - { - U32 const magic = MEM_readLE32(ddict->dictContent); - if (magic != ZSTD_DICT_MAGIC) - return 0; /* pure content mode */ - } - ddict->dictID = MEM_readLE32((const char *)ddict->dictContent + 4); - - /* load entropy tables */ - CHECK_E(ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted); - ddict->entropyPresent = 1; - return 0; -} - -ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem) -{ - if (!customMem.customAlloc && !customMem.customFree) - customMem = defaultCustomMem; - if (!customMem.customAlloc || !customMem.customFree) - return NULL; - - { - ZSTD_DDict *const ddict = (ZSTD_DDict *)ZSTD_malloc(sizeof(ZSTD_DDict), customMem); - if (!ddict) - return NULL; - ddict->cMem = customMem; - - if ((byReference) || (!dict) || (!dictSize)) - { - ddict->dictBuffer = NULL; - ddict->dictContent = dict; - } - else - { - void *const internalBuffer = ZSTD_malloc(dictSize, customMem); - if (!internalBuffer) - { - ZSTD_freeDDict(ddict); - return NULL; - } - memcpy(internalBuffer, dict, dictSize); - ddict->dictBuffer = internalBuffer; - ddict->dictContent = internalBuffer; - } - ddict->dictSize = dictSize; - ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog) * 0x1000001); /* cover both little and big endian */ - /* parse dictionary content */ - { - size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict); - if (ZSTD_isError(errorCode)) - { - ZSTD_freeDDict(ddict); - return NULL; - } - } - - return ddict; - } -} - -/*! ZSTD_createDDict() : - * Create a digested dictionary, to start decompression without startup delay. - * `dict` content is copied inside DDict. - * Consequently, `dict` can be released after `ZSTD_DDict` creation */ -ZSTD_DDict *ZSTD_createDDict(const void *dict, size_t dictSize) -{ - ZSTD_customMem const allocator = {NULL, NULL, NULL}; - return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator); -} - -/*! ZSTD_createDDict_byReference() : - * Create a digested dictionary, to start decompression without startup delay. - * Dictionary content is simply referenced, it will be accessed during decompression. - * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */ -ZSTD_DDict *ZSTD_createDDict_byReference(const void *dictBuffer, size_t dictSize) -{ - ZSTD_customMem const allocator = {NULL, NULL, NULL}; - return ZSTD_createDDict_advanced(dictBuffer, dictSize, 1, allocator); -} - -size_t ZSTD_freeDDict(ZSTD_DDict *ddict) -{ - if (ddict == NULL) - return 0; /* support free on NULL */ - { - ZSTD_customMem const cMem = ddict->cMem; - ZSTD_free(ddict->dictBuffer, cMem); - ZSTD_free(ddict, cMem); - return 0; - } -} - -size_t ZSTD_sizeof_DDict(const ZSTD_DDict *ddict) -{ - if (ddict == NULL) - return 0; /* support sizeof on NULL */ - return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0); -} - -/*! ZSTD_getDictID_fromDict() : - * Provides the dictID stored within dictionary. - * if @return == 0, the dictionary is not conformant with Zstandard specification. - * It can still be loaded, but as a content-only dictionary. */ -unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize) -{ - if (dictSize < 8) - return 0; - if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) - return 0; - return MEM_readLE32((const char *)dict + 4); -} - -/*! ZSTD_getDictID_fromDDict() : - * Provides the dictID of the dictionary loaded into `ddict`. - * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. - * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ -unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict) -{ - if (ddict == NULL) - return 0; - return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize); -} - -/*! ZSTD_getDictID_fromFrame() : - * Provides the dictID required to decompressed the frame stored within `src`. - * If @return == 0, the dictID could not be decoded. - * This could for one of the following reasons : - * - The frame does not require a dictionary to be decoded (most common case). - * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information. - * Note : this use case also happens when using a non-conformant dictionary. - * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`). - * - This is not a Zstandard frame. - * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */ -unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize) -{ - ZSTD_frameParams zfp = {0, 0, 0, 0}; - size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize); - if (ZSTD_isError(hError)) - return 0; - return zfp.dictID; -} - -/*! ZSTD_decompress_usingDDict() : - * Decompression using a pre-digested Dictionary - * Use dictionary without significant overhead. */ -size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, - void *dst, size_t dstCapacity, - const void *src, size_t srcSize, - const ZSTD_DDict *ddict) -{ - /* pass content and size in case legacy frames are encountered */ - return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, - NULL, 0, - ddict); -} - -/*===================================== - * Streaming decompression - *====================================*/ - -typedef enum -{ - zdss_init, - zdss_loadHeader, - zdss_read, - zdss_load, - zdss_flush -} ZSTD_dStreamStage; - -/* *** Resource management *** */ -struct ZSTD_DStream_s -{ - ZSTD_DCtx *dctx; - ZSTD_DDict *ddictLocal; - const ZSTD_DDict *ddict; - ZSTD_frameParams fParams; - ZSTD_dStreamStage stage; - char *inBuff; - size_t inBuffSize; - size_t inPos; - size_t maxWindowSize; - char *outBuff; - size_t outBuffSize; - size_t outStart; - size_t outEnd; - size_t blockSize; - BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */ - size_t lhSize; - ZSTD_customMem customMem; - void *legacyContext; - U32 previousLegacyVersion; - U32 legacyVersion; - U32 hostageByte; -}; /* typedef'd to ZSTD_DStream within "zstd.h" */ - -ZSTD_DStream *ZSTD_createDStream(void) -{ - return ZSTD_createDStream_advanced(defaultCustomMem); -} - -ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem) -{ - ZSTD_DStream *zds; - - if (!customMem.customAlloc && !customMem.customFree) - customMem = defaultCustomMem; - if (!customMem.customAlloc || !customMem.customFree) - return NULL; - - zds = (ZSTD_DStream *)ZSTD_malloc(sizeof(ZSTD_DStream), customMem); - if (zds == NULL) - return NULL; - memset(zds, 0, sizeof(ZSTD_DStream)); - memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem)); - zds->dctx = ZSTD_createDCtx_advanced(customMem); - if (zds->dctx == NULL) - { - ZSTD_freeDStream(zds); - return NULL; - } - zds->stage = zdss_init; - zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; - return zds; -} - -size_t ZSTD_freeDStream(ZSTD_DStream *zds) -{ - if (zds == NULL) - return 0; /* support free on null */ - { - ZSTD_customMem const cMem = zds->customMem; - ZSTD_freeDCtx(zds->dctx); - ZSTD_freeDDict(zds->ddictLocal); - ZSTD_free(zds->inBuff, cMem); - ZSTD_free(zds->outBuff, cMem); -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (zds->legacyContext) - ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion); -#endif - ZSTD_free(zds, cMem); - return 0; - } -} - -/* *** Initialization *** */ - -size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; } -size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; } - -size_t ZSTD_initDStream_usingDict(ZSTD_DStream *zds, const void *dict, size_t dictSize) -{ - zds->stage = zdss_loadHeader; - zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; - ZSTD_freeDDict(zds->ddictLocal); - if (dict && dictSize >= 8) - { - zds->ddictLocal = ZSTD_createDDict(dict, dictSize); - if (zds->ddictLocal == NULL) - return ERROR(memory_allocation); - } - else - zds->ddictLocal = NULL; - zds->ddict = zds->ddictLocal; - zds->legacyVersion = 0; - zds->hostageByte = 0; - return ZSTD_frameHeaderSize_prefix; -} - -size_t ZSTD_initDStream(ZSTD_DStream *zds) -{ - return ZSTD_initDStream_usingDict(zds, NULL, 0); -} - -size_t ZSTD_initDStream_usingDDict(ZSTD_DStream *zds, const ZSTD_DDict *ddict) /**< note : ddict will just be referenced, and must outlive decompression session */ -{ - size_t const initResult = ZSTD_initDStream(zds); - zds->ddict = ddict; - return initResult; -} - -size_t ZSTD_resetDStream(ZSTD_DStream *zds) -{ - zds->stage = zdss_loadHeader; - zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0; - zds->legacyVersion = 0; - zds->hostageByte = 0; - return ZSTD_frameHeaderSize_prefix; -} - -size_t ZSTD_setDStreamParameter(ZSTD_DStream *zds, - ZSTD_DStreamParameter_e paramType, unsigned paramValue) -{ - switch (paramType) - { - default: - return ERROR(parameter_unknown); - case DStream_p_maxWindowSize: - zds->maxWindowSize = paramValue ? paramValue : (U32)(-1); - break; - } - return 0; -} - -size_t ZSTD_sizeof_DStream(const ZSTD_DStream *zds) -{ - if (zds == NULL) - return 0; /* support sizeof on NULL */ - return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->dctx) + ZSTD_sizeof_DDict(zds->ddictLocal) + zds->inBuffSize + zds->outBuffSize; -} - -/* ***** Decompression ***** */ - -MEM_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize) -{ - size_t const length = MIN(dstCapacity, srcSize); - memcpy(dst, src, length); - return length; -} - -size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input) -{ - const char *const istart = (const char *)(input->src) + input->pos; - const char *const iend = (const char *)(input->src) + input->size; - const char *ip = istart; - char *const ostart = (char *)(output->dst) + output->pos; - char *const oend = (char *)(output->dst) + output->size; - char *op = ostart; - U32 someMoreWork = 1; - -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (zds->legacyVersion) - return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); -#endif - - while (someMoreWork) - { - switch (zds->stage) - { - case zdss_init: - ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ - /* fall-through */ - - case zdss_loadHeader: - { - size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); - if (ZSTD_isError(hSize)) -#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - { - U32 const legacyVersion = ZSTD_isLegacy(istart, iend - istart); - if (legacyVersion) - { - const void *const dict = zds->ddict ? zds->ddict->dictContent : NULL; - size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0; - CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion, - dict, dictSize)); - zds->legacyVersion = zds->previousLegacyVersion = legacyVersion; - return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input); - } - else - { - return hSize; /* error */ - } - } -#else - return hSize; -#endif - if (hSize != 0) - { /* need more input */ - size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */ - if (toLoad > (size_t)(iend - ip)) - { /* not enough input to load full header */ - memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip); - zds->lhSize += iend - ip; - input->pos = input->size; - return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ - } - memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); - zds->lhSize = hSize; - ip += toLoad; - break; - } - } - - /* check for single-pass mode opportunity */ - if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */ - && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) - { - size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart); - if (cSize <= (size_t)(iend - istart)) - { - size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict); - if (ZSTD_isError(decompressedSize)) - return decompressedSize; - ip = istart + cSize; - op += decompressedSize; - zds->dctx->expected = 0; - zds->stage = zdss_init; - someMoreWork = 0; - break; - } - } - - /* Consume header */ - ZSTD_refDDict(zds->dctx, zds->ddict); - { - size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */ - CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size)); - { - size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); - CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size)); - } - } - - zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN); - if (zds->fParams.windowSize > zds->maxWindowSize) - return ERROR(frameParameter_windowTooLarge); - - /* Adapt buffer sizes to frame header instructions */ - { - size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); - size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2; - zds->blockSize = blockSize; - if (zds->inBuffSize < blockSize) - { - ZSTD_free(zds->inBuff, zds->customMem); - zds->inBuffSize = blockSize; - zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem); - if (zds->inBuff == NULL) - return ERROR(memory_allocation); - } - if (zds->outBuffSize < neededOutSize) - { - ZSTD_free(zds->outBuff, zds->customMem); - zds->outBuffSize = neededOutSize; - zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem); - if (zds->outBuff == NULL) - return ERROR(memory_allocation); - } - } - /* fall through */ - zds->stage = zdss_read; - /* pass-through */ - - case zdss_read: - { - size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); - if (neededInSize == 0) - { /* end of frame */ - zds->stage = zdss_init; - someMoreWork = 0; - break; - } - if ((size_t)(iend - ip) >= neededInSize) - { /* decode directly from src */ - const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx); - size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, - zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), - ip, neededInSize); - if (ZSTD_isError(decodedSize)) - return decodedSize; - ip += neededInSize; - if (!decodedSize && !isSkipFrame) - break; /* this was just a header */ - zds->outEnd = zds->outStart + decodedSize; - zds->stage = zdss_flush; - break; - } - if (ip == iend) - { - someMoreWork = 0; - break; - } /* no more input */ - /* fall through */ - zds->stage = zdss_load; - /* pass-through */ - } - - case zdss_load: - { - size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); - size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */ - size_t loadedSize; - if (toLoad > zds->inBuffSize - zds->inPos) - return ERROR(corruption_detected); /* should never happen */ - loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip); - ip += loadedSize; - zds->inPos += loadedSize; - if (loadedSize < toLoad) - { - someMoreWork = 0; - break; - } /* not enough input, wait for more */ - - /* decode loaded input */ - { - const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx); - size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, - zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart, - zds->inBuff, neededInSize); - if (ZSTD_isError(decodedSize)) - return decodedSize; - zds->inPos = 0; /* input is consumed */ - if (!decodedSize && !isSkipFrame) - { - zds->stage = zdss_read; - break; - } /* this was just a header */ - zds->outEnd = zds->outStart + decodedSize; - - zds->stage = zdss_flush; /* fall through */ - /* pass-through */ - } - } - - case zdss_flush: - { - size_t const toFlushSize = zds->outEnd - zds->outStart; - size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize); - op += flushedSize; - zds->outStart += flushedSize; - if (flushedSize == toFlushSize) - { /* flush completed */ - zds->stage = zdss_read; - if (zds->outStart + zds->blockSize > zds->outBuffSize) - zds->outStart = zds->outEnd = 0; - break; - } - /* cannot complete flush */ - someMoreWork = 0; - break; - } - default: - return ERROR(GENERIC); /* impossible */ - } - } - - /* result */ - input->pos += (size_t)(ip - istart); - output->pos += (size_t)(op - ostart); - { - size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx); - if (!nextSrcSizeHint) - { /* frame fully decoded */ - if (zds->outEnd == zds->outStart) - { /* output fully flushed */ - if (zds->hostageByte) - { - if (input->pos >= input->size) - { - zds->stage = zdss_read; - return 1; - } /* can't release hostage (not present) */ - input->pos++; /* release hostage */ - } - return 0; - } - if (!zds->hostageByte) - { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */ - input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */ - zds->hostageByte = 1; - } - return 1; - } - nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */ - if (zds->inPos > nextSrcSizeHint) - return ERROR(GENERIC); /* should never happen */ - nextSrcSizeHint -= zds->inPos; /* already loaded*/ - return nextSrcSizeHint; - } -} diff --git a/extra/zstd/zstd_errors.h b/extra/zstd/zstd_errors.h deleted file mode 100644 index e0440b04..00000000 --- a/extra/zstd/zstd_errors.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef ZSTD_ERRORS_H_398273423 -#define ZSTD_ERRORS_H_398273423 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/*===== dependency =====*/ -#include /* size_t */ - -/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */ -#if defined(__GNUC__) && (__GNUC__ >= 4) -#define ZSTDERRORLIB_VISIBILITY __attribute__((visibility("default"))) -#else -#define ZSTDERRORLIB_VISIBILITY -#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 - ******************************************/ - typedef enum - { - ZSTD_error_no_error, - ZSTD_error_GENERIC, - ZSTD_error_prefix_unknown, - ZSTD_error_version_unsupported, - ZSTD_error_parameter_unknown, - ZSTD_error_frameParameter_unsupported, - ZSTD_error_frameParameter_unsupportedBy32bits, - ZSTD_error_frameParameter_windowTooLarge, - ZSTD_error_compressionParameter_unsupported, - ZSTD_error_init_missing, - ZSTD_error_memory_allocation, - ZSTD_error_stage_wrong, - ZSTD_error_dstSize_tooSmall, - ZSTD_error_srcSize_wrong, - ZSTD_error_corruption_detected, - ZSTD_error_checksum_wrong, - ZSTD_error_tableLog_tooLarge, - ZSTD_error_maxSymbolValue_tooLarge, - ZSTD_error_maxSymbolValue_tooSmall, - ZSTD_error_dictionary_corrupted, - ZSTD_error_dictionary_wrong, - ZSTD_error_maxCode - } ZSTD_ErrorCode; - - /*! ZSTD_getErrorCode() : - convert a `size_t` function result into a `ZSTD_ErrorCode` enum type, - which can be used to compare directly with enum list published into "error_public.h" */ - ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); - ZSTDERRORLIB_API const char *ZSTD_getErrorString(ZSTD_ErrorCode code); - -#if defined(__cplusplus) -} -#endif - -#endif /* ZSTD_ERRORS_H_398273423 */ diff --git a/extra/zstd/zstd_internal.h b/extra/zstd/zstd_internal.h deleted file mode 100644 index c47c48a1..00000000 --- a/extra/zstd/zstd_internal.h +++ /dev/null @@ -1,304 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef ZSTD_CCOMMON_H_MODULE -#define ZSTD_CCOMMON_H_MODULE - -/*-******************************************************* - * Compiler specifics - *********************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4324) /* disable: C4324: padded structure */ -#pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -#ifdef _MSC_VER -#define FORCE_NOINLINE static __declspec(noinline) -#else -#ifdef __GNUC__ -#define FORCE_NOINLINE static __attribute__((__noinline__)) -#else -#define FORCE_NOINLINE static -#endif -#endif - -/*-************************************* - * Dependencies - ***************************************/ -#include "mem.h" -#include "error_private.h" -#define ZSTD_STATIC_LINKING_ONLY -#include "zstd.h" -#ifndef XXH_STATIC_LINKING_ONLY -#define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */ -#endif -#include "xxhash.h" /* XXH_reset, update, digest */ - -/*-************************************* - * shared macros - ***************************************/ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define CHECK_F(f) \ - { \ - size_t const errcod = f; \ - if (ERR_isError(errcod)) \ - return errcod; \ - } /* check and Forward error code */ -#define CHECK_E(f, e) \ - { \ - size_t const errcod = f; \ - if (ERR_isError(errcod)) \ - return ERROR(e); \ - } /* check and send Error code */ - -/*-************************************* - * Common constants - ***************************************/ -#define ZSTD_OPT_NUM (1 << 12) -#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */ - -#define ZSTD_REP_NUM 3 /* number of repcodes */ -#define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */ -#define ZSTD_REP_MOVE (ZSTD_REP_NUM - 1) -#define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM) -static const U32 repStartValue[ZSTD_REP_NUM] = {1, 4, 8}; - -#define KB *(1 << 10) -#define MB *(1 << 20) -#define GB *(1U << 30) - -#define BIT7 128 -#define BIT6 64 -#define BIT5 32 -#define BIT4 16 -#define BIT1 2 -#define BIT0 1 - -#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 -static const size_t ZSTD_fcs_fieldSize[4] = {0, 2, 4, 8}; -static const size_t ZSTD_did_fieldSize[4] = {0, 1, 2, 4}; - -#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ -static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; -typedef enum -{ - bt_raw, - bt_rle, - bt_compressed, - bt_reserved -} blockType_e; - -#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ -#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */ - -#define HufLog 12 -typedef enum -{ - set_basic, - set_rle, - set_compressed, - set_repeat -} symbolEncodingType_e; - -#define LONGNBSEQ 0x7F00 - -#define MINMATCH 3 -#define EQUAL_READ32 4 - -#define Litbits 8 -#define MaxLit ((1 << Litbits) - 1) -#define MaxML 52 -#define MaxLL 35 -#define MaxOff 28 -#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */ -#define MLFSELog 9 -#define LLFSELog 9 -#define OffFSELog 8 - -static const U32 LL_bits[MaxLL + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16}; -static const S16 LL_defaultNorm[MaxLL + 1] = {4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, - -1, -1, -1, -1}; -#define LL_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; - -static const U32 ML_bits[MaxML + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16}; -static const S16 ML_defaultNorm[MaxML + 1] = {1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, - -1, -1, -1, -1, -1}; -#define ML_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; - -static const S16 OF_defaultNorm[MaxOff + 1] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1}; -#define OF_DEFAULTNORMLOG 5 /* for static allocation */ -static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; - -/*-******************************************* - * Shared functions to include for inlining - *********************************************/ -static void ZSTD_copy8(void *dst, const void *src) { memcpy(dst, src, 8); } -#define COPY8(d, s) \ - { \ - ZSTD_copy8(d, s); \ - d += 8; \ - s += 8; \ - } - -/*! ZSTD_wildcopy() : - * custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */ -#define WILDCOPY_OVERLENGTH 8 -MEM_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length) -{ - const BYTE *ip = (const BYTE *)src; - BYTE *op = (BYTE *)dst; - BYTE *const oend = op + length; - do - COPY8(op, ip) - while (op < oend); -} - -MEM_STATIC void ZSTD_wildcopy_e(void *dst, const void *src, void *dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */ -{ - const BYTE *ip = (const BYTE *)src; - BYTE *op = (BYTE *)dst; - BYTE *const oend = (BYTE *)dstEnd; - do - COPY8(op, ip) - while (op < oend); -} - -/*-******************************************* - * Private interfaces - *********************************************/ -typedef struct ZSTD_stats_s ZSTD_stats_t; - -typedef struct -{ - U32 off; - U32 len; -} ZSTD_match_t; - -typedef struct -{ - U32 price; - U32 off; - U32 mlen; - U32 litlen; - U32 rep[ZSTD_REP_NUM]; -} ZSTD_optimal_t; - -typedef struct seqDef_s -{ - U32 offset; - U16 litLength; - U16 matchLength; -} seqDef; - -typedef struct -{ - seqDef *sequencesStart; - seqDef *sequences; - BYTE *litStart; - BYTE *lit; - BYTE *llCode; - BYTE *mlCode; - BYTE *ofCode; - U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ - U32 longLengthPos; - /* opt */ - ZSTD_optimal_t *priceTable; - ZSTD_match_t *matchTable; - U32 *matchLengthFreq; - U32 *litLengthFreq; - U32 *litFreq; - U32 *offCodeFreq; - U32 matchLengthSum; - U32 matchSum; - U32 litLengthSum; - U32 litSum; - U32 offCodeSum; - U32 log2matchLengthSum; - U32 log2matchSum; - U32 log2litLengthSum; - U32 log2litSum; - U32 log2offCodeSum; - U32 factor; - U32 staticPrices; - U32 cachedPrice; - U32 cachedLitLength; - const BYTE *cachedLiterals; -} seqStore_t; - -const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx); -void ZSTD_seqToCodes(const seqStore_t *seqStorePtr); -int ZSTD_isSkipFrame(ZSTD_DCtx *dctx); - -/* custom memory allocation functions */ -void *ZSTD_defaultAllocFunction(void *opaque, size_t size); -void ZSTD_defaultFreeFunction(void *opaque, void *address); -#ifndef ZSTD_DLL_IMPORT -static const ZSTD_customMem defaultCustomMem = {ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL}; -#endif -void *ZSTD_malloc(size_t size, ZSTD_customMem customMem); -void ZSTD_free(void *ptr, ZSTD_customMem customMem); - -/*====== common function ======*/ - -MEM_STATIC U32 ZSTD_highbit32(U32 val) -{ -#if defined(_MSC_VER) /* Visual */ - unsigned long r = 0; - _BitScanReverse(&r, val); - return (unsigned)r; -#elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ - return 31 - __builtin_clz(val); -#else /* Software version */ - static const int 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; - int r; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; - return r; -#endif -} - -/* hidden functions */ - -/* ZSTD_invalidateRepCodes() : - * ensures next compression will not use repcodes from previous block. - * Note : only works with regular variant; - * do not use with extDict variant ! */ -void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx); - -#endif /* ZSTD_CCOMMON_H_MODULE */ diff --git a/extra/zstd/zstd_legacy.h b/extra/zstd/zstd_legacy.h deleted file mode 100644 index 8f23afb6..00000000 --- a/extra/zstd/zstd_legacy.h +++ /dev/null @@ -1,400 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef ZSTD_LEGACY_H -#define ZSTD_LEGACY_H - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* ************************************* - * Includes - ***************************************/ -#include "mem.h" /* MEM_STATIC */ -#include "error_private.h" /* ERROR */ -#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */ - -#if !defined(ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0) -#undef ZSTD_LEGACY_SUPPORT -#define ZSTD_LEGACY_SUPPORT 8 -#endif - -#if (ZSTD_LEGACY_SUPPORT <= 1) -#include "zstd_v01.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 2) -#include "zstd_v02.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 3) -#include "zstd_v03.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 4) -#include "zstd_v04.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) -#include "zstd_v05.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) -#include "zstd_v06.h" -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) -#include "zstd_v07.h" -#endif - - /** ZSTD_isLegacy() : - @return : > 0 if supported by legacy decoder. 0 otherwise. - return value is the version. - */ - MEM_STATIC unsigned ZSTD_isLegacy(const void *src, size_t srcSize) - { - U32 magicNumberLE; - if (srcSize < 4) - return 0; - magicNumberLE = MEM_readLE32(src); - switch (magicNumberLE) - { -#if (ZSTD_LEGACY_SUPPORT <= 1) - case ZSTDv01_magicNumberLE: - return 1; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 2) - case ZSTDv02_magicNumber: - return 2; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 3) - case ZSTDv03_magicNumber: - return 3; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 4) - case ZSTDv04_magicNumber: - return 4; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case ZSTDv05_MAGICNUMBER: - return 5; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case ZSTDv06_MAGICNUMBER: - return 6; -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case ZSTDv07_MAGICNUMBER: - return 7; -#endif - default: - return 0; - } - } - - MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void *src, size_t srcSize) - { - U32 const version = ZSTD_isLegacy(src, srcSize); - if (version < 5) - return 0; /* no decompressed size in frame header, or not a legacy format */ -#if (ZSTD_LEGACY_SUPPORT <= 5) - if (version == 5) - { - ZSTDv05_parameters fParams; - size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize); - if (frResult != 0) - return 0; - return fParams.srcSize; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - if (version == 6) - { - ZSTDv06_frameParams fParams; - size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize); - if (frResult != 0) - return 0; - return fParams.frameContentSize; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - if (version == 7) - { - ZSTDv07_frameParams fParams; - size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize); - if (frResult != 0) - return 0; - return fParams.frameContentSize; - } -#endif - return 0; /* should not be possible */ - } - - MEM_STATIC size_t ZSTD_decompressLegacy( - void *dst, size_t dstCapacity, - const void *src, size_t compressedSize, - const void *dict, size_t dictSize) - { - U32 const version = ZSTD_isLegacy(src, compressedSize); - switch (version) - { -#if (ZSTD_LEGACY_SUPPORT <= 1) - case 1: - return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 2) - case 2: - return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 3) - case 3: - return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 4) - case 4: - return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case 5: - { - size_t result; - ZSTDv05_DCtx *const zd = ZSTDv05_createDCtx(); - if (zd == NULL) - return ERROR(memory_allocation); - result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); - ZSTDv05_freeDCtx(zd); - return result; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case 6: - { - size_t result; - ZSTDv06_DCtx *const zd = ZSTDv06_createDCtx(); - if (zd == NULL) - return ERROR(memory_allocation); - result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); - ZSTDv06_freeDCtx(zd); - return result; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case 7: - { - size_t result; - ZSTDv07_DCtx *const zd = ZSTDv07_createDCtx(); - if (zd == NULL) - return ERROR(memory_allocation); - result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize); - ZSTDv07_freeDCtx(zd); - return result; - } -#endif - default: - return ERROR(prefix_unknown); - } - } - - MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, - size_t compressedSize) - { - U32 const version = ZSTD_isLegacy(src, compressedSize); - switch (version) - { -#if (ZSTD_LEGACY_SUPPORT <= 1) - case 1: - return ZSTDv01_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 2) - case 2: - return ZSTDv02_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 3) - case 3: - return ZSTDv03_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 4) - case 4: - return ZSTDv04_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case 5: - return ZSTDv05_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case 6: - return ZSTDv06_findFrameCompressedSize(src, compressedSize); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case 7: - return ZSTDv07_findFrameCompressedSize(src, compressedSize); -#endif - default: - return ERROR(prefix_unknown); - } - } - - MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void *legacyContext, U32 version) - { - switch (version) - { - default: - case 1: - case 2: - case 3: - return ERROR(version_unsupported); -#if (ZSTD_LEGACY_SUPPORT <= 4) - case 4: - return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx *)legacyContext); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case 5: - return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx *)legacyContext); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case 6: - return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx *)legacyContext); -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case 7: - return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx *)legacyContext); -#endif - } - } - - MEM_STATIC size_t ZSTD_initLegacyStream(void **legacyContext, U32 prevVersion, U32 newVersion, - const void *dict, size_t dictSize) - { - if (prevVersion != newVersion) - ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion); - switch (newVersion) - { - default: - case 1: - case 2: - case 3: - return 0; -#if (ZSTD_LEGACY_SUPPORT <= 4) - case 4: - { - ZBUFFv04_DCtx *dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx *)*legacyContext; - if (dctx == NULL) - return ERROR(memory_allocation); - ZBUFFv04_decompressInit(dctx); - ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize); - *legacyContext = dctx; - return 0; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case 5: - { - ZBUFFv05_DCtx *dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx *)*legacyContext; - if (dctx == NULL) - return ERROR(memory_allocation); - ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize); - *legacyContext = dctx; - return 0; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case 6: - { - ZBUFFv06_DCtx *dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx *)*legacyContext; - if (dctx == NULL) - return ERROR(memory_allocation); - ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize); - *legacyContext = dctx; - return 0; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case 7: - { - ZBUFFv07_DCtx *dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx *)*legacyContext; - if (dctx == NULL) - return ERROR(memory_allocation); - ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize); - *legacyContext = dctx; - return 0; - } -#endif - } - } - - MEM_STATIC size_t ZSTD_decompressLegacyStream(void *legacyContext, U32 version, - ZSTD_outBuffer *output, ZSTD_inBuffer *input) - { - switch (version) - { - default: - case 1: - case 2: - case 3: - return ERROR(version_unsupported); -#if (ZSTD_LEGACY_SUPPORT <= 4) - case 4: - { - ZBUFFv04_DCtx *dctx = (ZBUFFv04_DCtx *)legacyContext; - const void *src = (const char *)input->src + input->pos; - size_t readSize = input->size - input->pos; - void *dst = (char *)output->dst + output->pos; - size_t decodedSize = output->size - output->pos; - size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize); - output->pos += decodedSize; - input->pos += readSize; - return hintSize; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 5) - case 5: - { - ZBUFFv05_DCtx *dctx = (ZBUFFv05_DCtx *)legacyContext; - const void *src = (const char *)input->src + input->pos; - size_t readSize = input->size - input->pos; - void *dst = (char *)output->dst + output->pos; - size_t decodedSize = output->size - output->pos; - size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize); - output->pos += decodedSize; - input->pos += readSize; - return hintSize; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 6) - case 6: - { - ZBUFFv06_DCtx *dctx = (ZBUFFv06_DCtx *)legacyContext; - const void *src = (const char *)input->src + input->pos; - size_t readSize = input->size - input->pos; - void *dst = (char *)output->dst + output->pos; - size_t decodedSize = output->size - output->pos; - size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize); - output->pos += decodedSize; - input->pos += readSize; - return hintSize; - } -#endif -#if (ZSTD_LEGACY_SUPPORT <= 7) - case 7: - { - ZBUFFv07_DCtx *dctx = (ZBUFFv07_DCtx *)legacyContext; - const void *src = (const char *)input->src + input->pos; - size_t readSize = input->size - input->pos; - void *dst = (char *)output->dst + output->pos; - size_t decodedSize = output->size - output->pos; - size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize); - output->pos += decodedSize; - input->pos += readSize; - return hintSize; - } -#endif - } - } - -#if defined(__cplusplus) -} -#endif - -#endif /* ZSTD_LEGACY_H */ diff --git a/extra/zstd/zstd_opt.h b/extra/zstd/zstd_opt.h deleted file mode 100644 index 0df38795..00000000 --- a/extra/zstd/zstd_opt.h +++ /dev/null @@ -1,1130 +0,0 @@ -/** - * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/* Note : this file is intended to be included within zstd_compress.c */ - -#ifndef ZSTD_OPT_H_91842398743 -#define ZSTD_OPT_H_91842398743 - -#define ZSTD_LITFREQ_ADD 2 -#define ZSTD_FREQ_DIV 4 -#define ZSTD_MAX_PRICE (1 << 30) - -/*-************************************* - * Price functions for optimal parser - ***************************************/ -FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t *ssPtr) -{ - ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum + 1); - ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum + 1); - ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum + 1); - ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum + 1); - ssPtr->factor = 1 + ((ssPtr->litSum >> 5) / ssPtr->litLengthSum) + ((ssPtr->litSum << 1) / (ssPtr->litSum + ssPtr->matchSum)); -} - -MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t *ssPtr, const BYTE *src, size_t srcSize) -{ - unsigned u; - - ssPtr->cachedLiterals = NULL; - ssPtr->cachedPrice = ssPtr->cachedLitLength = 0; - ssPtr->staticPrices = 0; - - if (ssPtr->litLengthSum == 0) - { - if (srcSize <= 1024) - ssPtr->staticPrices = 1; - - for (u = 0; u <= MaxLit; u++) - ssPtr->litFreq[u] = 0; - for (u = 0; u < srcSize; u++) - ssPtr->litFreq[src[u]]++; - - ssPtr->litSum = 0; - ssPtr->litLengthSum = MaxLL + 1; - ssPtr->matchLengthSum = MaxML + 1; - ssPtr->offCodeSum = (MaxOff + 1); - ssPtr->matchSum = (ZSTD_LITFREQ_ADD << Litbits); - - for (u = 0; u <= MaxLit; u++) - { - ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> ZSTD_FREQ_DIV); - ssPtr->litSum += ssPtr->litFreq[u]; - } - for (u = 0; u <= MaxLL; u++) - ssPtr->litLengthFreq[u] = 1; - for (u = 0; u <= MaxML; u++) - ssPtr->matchLengthFreq[u] = 1; - for (u = 0; u <= MaxOff; u++) - ssPtr->offCodeFreq[u] = 1; - } - else - { - ssPtr->matchLengthSum = 0; - ssPtr->litLengthSum = 0; - ssPtr->offCodeSum = 0; - ssPtr->matchSum = 0; - ssPtr->litSum = 0; - - for (u = 0; u <= MaxLit; u++) - { - ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> (ZSTD_FREQ_DIV + 1)); - ssPtr->litSum += ssPtr->litFreq[u]; - } - for (u = 0; u <= MaxLL; u++) - { - ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u] >> (ZSTD_FREQ_DIV + 1)); - ssPtr->litLengthSum += ssPtr->litLengthFreq[u]; - } - for (u = 0; u <= MaxML; u++) - { - ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u] >> ZSTD_FREQ_DIV); - ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u]; - ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3); - } - ssPtr->matchSum *= ZSTD_LITFREQ_ADD; - for (u = 0; u <= MaxOff; u++) - { - ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u] >> ZSTD_FREQ_DIV); - ssPtr->offCodeSum += ssPtr->offCodeFreq[u]; - } - } - - ZSTD_setLog2Prices(ssPtr); -} - -FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t *ssPtr, U32 litLength, const BYTE *literals) -{ - U32 price, u; - - if (ssPtr->staticPrices) - return ZSTD_highbit32((U32)litLength + 1) + (litLength * 6); - - if (litLength == 0) - return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0] + 1); - - /* literals */ - if (ssPtr->cachedLiterals == literals) - { - U32 const additional = litLength - ssPtr->cachedLitLength; - const BYTE *literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength; - price = ssPtr->cachedPrice + additional * ssPtr->log2litSum; - for (u = 0; u < additional; u++) - price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]] + 1); - ssPtr->cachedPrice = price; - ssPtr->cachedLitLength = litLength; - } - else - { - price = litLength * ssPtr->log2litSum; - for (u = 0; u < litLength; u++) - price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]] + 1); - - if (litLength >= 12) - { - ssPtr->cachedLiterals = literals; - ssPtr->cachedPrice = price; - ssPtr->cachedLitLength = litLength; - } - } - - /* literal Length */ - { - const BYTE LL_deltaCode = 19; - const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength]; - price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode] + 1); - } - - return price; -} - -FORCE_INLINE U32 ZSTD_getPrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength, const int ultra) -{ - /* offset */ - U32 price; - BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1); - - if (seqStorePtr->staticPrices) - return ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit32((U32)matchLength + 1) + 16 + offCode; - - price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode] + 1); - if (!ultra && offCode >= 20) - price += (offCode - 19) * 2; - - /* match Length */ - { - const BYTE ML_deltaCode = 36; - const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength]; - price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode] + 1); - } - - return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor; -} - -MEM_STATIC void ZSTD_updatePrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength) -{ - U32 u; - - /* literals */ - seqStorePtr->litSum += litLength * ZSTD_LITFREQ_ADD; - for (u = 0; u < litLength; u++) - seqStorePtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD; - - /* literal Length */ - { - const BYTE LL_deltaCode = 19; - const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength]; - seqStorePtr->litLengthFreq[llCode]++; - seqStorePtr->litLengthSum++; - } - - /* match offset */ - { - BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1); - seqStorePtr->offCodeSum++; - seqStorePtr->offCodeFreq[offCode]++; - } - - /* match Length */ - { - const BYTE ML_deltaCode = 36; - const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength]; - seqStorePtr->matchLengthFreq[mlCode]++; - seqStorePtr->matchLengthSum++; - } - - ZSTD_setLog2Prices(seqStorePtr); -} - -#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \ - { \ - while (last_pos < pos) \ - { \ - opt[last_pos + 1].price = ZSTD_MAX_PRICE; \ - last_pos++; \ - } \ - opt[pos].mlen = mlen_; \ - opt[pos].off = offset_; \ - opt[pos].litlen = litlen_; \ - opt[pos].price = price_; \ - } - -/* Update hashTable3 up to ip (excluded) - Assumption : always within prefix (i.e. not within extDict) */ -FORCE_INLINE -U32 ZSTD_insertAndFindFirstIndexHash3(ZSTD_CCtx *zc, const BYTE *ip) -{ - U32 *const hashTable3 = zc->hashTable3; - U32 const hashLog3 = zc->hashLog3; - const BYTE *const base = zc->base; - U32 idx = zc->nextToUpdate3; - const U32 target = zc->nextToUpdate3 = (U32)(ip - base); - const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3); - - while (idx < target) - { - hashTable3[ZSTD_hash3Ptr(base + idx, hashLog3)] = idx; - idx++; - } - - return hashTable3[hash3]; -} - -/*-************************************* - * Binary Tree search - ***************************************/ -static U32 ZSTD_insertBtAndGetAllMatches( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iLimit, - U32 nbCompares, const U32 mls, - U32 extDict, ZSTD_match_t *matches, const U32 minMatchLen) -{ - const BYTE *const base = zc->base; - const U32 current = (U32)(ip - base); - const U32 hashLog = zc->params.cParams.hashLog; - const size_t h = ZSTD_hashPtr(ip, hashLog, mls); - U32 *const hashTable = zc->hashTable; - U32 matchIndex = hashTable[h]; - U32 *const bt = zc->chainTable; - const U32 btLog = zc->params.cParams.chainLog - 1; - const U32 btMask = (1U << btLog) - 1; - size_t commonLengthSmaller = 0, commonLengthLarger = 0; - const BYTE *const dictBase = zc->dictBase; - const U32 dictLimit = zc->dictLimit; - const BYTE *const dictEnd = dictBase + dictLimit; - const BYTE *const prefixStart = base + dictLimit; - const U32 btLow = btMask >= current ? 0 : current - btMask; - const U32 windowLow = zc->lowLimit; - U32 *smallerPtr = bt + 2 * (current & btMask); - U32 *largerPtr = bt + 2 * (current & btMask) + 1; - U32 matchEndIdx = current + 8; - U32 dummy32; /* to be nullified at the end */ - U32 mnum = 0; - - const U32 minMatch = (mls == 3) ? 3 : 4; - size_t bestLength = minMatchLen - 1; - - if (minMatch == 3) - { /* HC3 match finder */ - U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(zc, ip); - if (matchIndex3 > windowLow && (current - matchIndex3 < (1 << 18))) - { - const BYTE *match; - size_t currentMl = 0; - if ((!extDict) || matchIndex3 >= dictLimit) - { - match = base + matchIndex3; - if (match[bestLength] == ip[bestLength]) - currentMl = ZSTD_count(ip, match, iLimit); - } - else - { - match = dictBase + matchIndex3; - if (MEM_readMINMATCH(match, MINMATCH) == MEM_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */ - currentMl = ZSTD_count_2segments(ip + MINMATCH, match + MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH; - } - - /* save best solution */ - if (currentMl > bestLength) - { - bestLength = currentMl; - matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex3; - matches[mnum].len = (U32)currentMl; - mnum++; - if (currentMl > ZSTD_OPT_NUM) - goto update; - if (ip + currentMl == iLimit) - goto update; /* best possible, and avoid read overflow*/ - } - } - } - - hashTable[h] = current; /* Update Hash Table */ - - while (nbCompares-- && (matchIndex > windowLow)) - { - U32 *nextPtr = bt + 2 * (matchIndex & btMask); - size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - const BYTE *match; - - if ((!extDict) || (matchIndex + matchLength >= dictLimit)) - { - match = base + matchIndex; - if (match[matchLength] == ip[matchLength]) - { - matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iLimit) + 1; - } - } - else - { - match = dictBase + matchIndex; - matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iLimit, dictEnd, prefixStart); - if (matchIndex + matchLength >= dictLimit) - match = base + matchIndex; /* to prepare for next usage of match[matchLength] */ - } - - if (matchLength > bestLength) - { - if (matchLength > matchEndIdx - matchIndex) - matchEndIdx = matchIndex + (U32)matchLength; - bestLength = matchLength; - matches[mnum].off = ZSTD_REP_MOVE_OPT + current - matchIndex; - matches[mnum].len = (U32)matchLength; - mnum++; - if (matchLength > ZSTD_OPT_NUM) - break; - if (ip + matchLength == iLimit) /* equal : no way to know if inf or sup */ - break; /* drop, to guarantee consistency (miss a little bit of compression) */ - } - - if (match[matchLength] < ip[matchLength]) - { - /* match is smaller than current */ - *smallerPtr = matchIndex; /* update smaller idx */ - commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */ - if (matchIndex <= btLow) - { - smallerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */ - matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to current) */ - } - else - { - /* match is larger than current */ - *largerPtr = matchIndex; - commonLengthLarger = matchLength; - if (matchIndex <= btLow) - { - largerPtr = &dummy32; - break; - } /* beyond tree size, stop the search */ - largerPtr = nextPtr; - matchIndex = nextPtr[0]; - } - } - - *smallerPtr = *largerPtr = 0; - -update: - zc->nextToUpdate = (matchEndIdx > current + 8) ? matchEndIdx - 8 : current + 1; - return mnum; -} - -/** Tree updater, providing best match */ -static U32 ZSTD_BtGetAllMatches( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iLimit, - const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches, const U32 minMatchLen) -{ - if (ip < zc->base + zc->nextToUpdate) - return 0; /* skipped area */ - ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls); - return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen); -} - -static U32 ZSTD_BtGetAllMatches_selectMLS( - ZSTD_CCtx *zc, /* Index table will be updated */ - const BYTE *ip, const BYTE *const iHighLimit, - const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t *matches, const U32 minMatchLen) -{ - switch (matchLengthSearch) - { - case 3: - return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen); - default: - case 4: - return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen); - case 5: - return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen); - case 6: - return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen); - } -} - -/** Tree updater, providing best match */ -static U32 ZSTD_BtGetAllMatches_extDict( - ZSTD_CCtx *zc, - const BYTE *const ip, const BYTE *const iLimit, - const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches, const U32 minMatchLen) -{ - if (ip < zc->base + zc->nextToUpdate) - return 0; /* skipped area */ - ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls); - return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen); -} - -static U32 ZSTD_BtGetAllMatches_selectMLS_extDict( - ZSTD_CCtx *zc, /* Index table will be updated */ - const BYTE *ip, const BYTE *const iHighLimit, - const U32 maxNbAttempts, const U32 matchLengthSearch, ZSTD_match_t *matches, const U32 minMatchLen) -{ - switch (matchLengthSearch) - { - case 3: - return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen); - default: - case 4: - return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen); - case 5: - return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen); - case 6: - return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen); - } -} - -/*-******************************* - * Optimal parser - *********************************/ -FORCE_INLINE -void ZSTD_compressBlock_opt_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, const int ultra) -{ - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - const BYTE *const base = ctx->base; - const BYTE *const prefixStart = base + ctx->dictLimit; - - const U32 maxSearches = 1U << ctx->params.cParams.searchLog; - const U32 sufficient_len = ctx->params.cParams.targetLength; - const U32 mls = ctx->params.cParams.searchLength; - const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4; - - ZSTD_optimal_t *opt = seqStorePtr->priceTable; - ZSTD_match_t *matches = seqStorePtr->matchTable; - const BYTE *inr; - U32 offset, rep[ZSTD_REP_NUM]; - - /* init */ - ctx->nextToUpdate3 = ctx->nextToUpdate; - ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize); - ip += (ip == prefixStart); - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - rep[i] = ctx->rep[i]; - } - - /* Match Loop */ - while (ip < ilimit) - { - U32 cur, match_num, last_pos, litlen, price; - U32 u, mlen, best_mlen, best_off, litLength; - memset(opt, 0, sizeof(ZSTD_optimal_t)); - last_pos = 0; - litlen = (U32)(ip - anchor); - - /* check repCode */ - { - U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor); - for (i = (ip == anchor); i < last_i; i++) - { - const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i]; - if ((repCur > 0) && (repCur < (S32)(ip - prefixStart)) && (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(ip - repCur, minMatch))) - { - mlen = (U32)ZSTD_count(ip + minMatch, ip + minMatch - repCur, iend) + minMatch; - if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) - { - best_mlen = mlen; - best_off = i; - cur = 0; - last_pos = 1; - goto _storeSequence; - } - best_off = i - (ip == anchor); - do - { - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra); - if (mlen > last_pos || price < opt[mlen].price) - SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */ - mlen--; - } while (mlen >= minMatch); - } - } - } - - match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch); - - if (!last_pos && !match_num) - { - ip++; - continue; - } - - if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) - { - best_mlen = matches[match_num - 1].len; - best_off = matches[match_num - 1].off; - cur = 0; - last_pos = 1; - goto _storeSequence; - } - - /* set prices using matches at position = 0 */ - best_mlen = (last_pos) ? last_pos : minMatch; - for (u = 0; u < match_num; u++) - { - mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen; - best_mlen = matches[u].len; - while (mlen <= best_mlen) - { - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra); - if (mlen > last_pos || price < opt[mlen].price) - SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */ - mlen++; - } - } - - if (last_pos < minMatch) - { - ip++; - continue; - } - - /* initialize opt[0] */ - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - opt[0].rep[i] = rep[i]; - } - opt[0].mlen = 1; - opt[0].litlen = litlen; - - /* check further positions */ - for (cur = 1; cur <= last_pos; cur++) - { - inr = ip + cur; - - if (opt[cur - 1].mlen == 1) - { - litlen = opt[cur - 1].litlen + 1; - if (cur > litlen) - { - price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen); - } - else - price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor); - } - else - { - litlen = 1; - price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1); - } - - if (cur > last_pos || price <= opt[cur].price) - SET_PRICE(cur, 1, 0, litlen, price); - - if (cur == last_pos) - break; - - if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */ - continue; - - mlen = opt[cur].mlen; - if (opt[cur].off > ZSTD_REP_MOVE_OPT) - { - opt[cur].rep[2] = opt[cur - mlen].rep[1]; - opt[cur].rep[1] = opt[cur - mlen].rep[0]; - opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT; - } - else - { - opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2]; - opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1]; - opt[cur].rep[0] = ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]); - } - - best_mlen = minMatch; - { - U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1); - for (i = (opt[cur].mlen != 1); i < last_i; i++) - { /* check rep */ - const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i]; - if ((repCur > 0) && (repCur < (S32)(inr - prefixStart)) && (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(inr - repCur, minMatch))) - { - mlen = (U32)ZSTD_count(inr + minMatch, inr + minMatch - repCur, iend) + minMatch; - - if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) - { - best_mlen = mlen; - best_off = i; - last_pos = cur + 1; - goto _storeSequence; - } - - best_off = i - (opt[cur].mlen != 1); - if (mlen > best_mlen) - best_mlen = mlen; - - do - { - if (opt[cur].mlen == 1) - { - litlen = opt[cur].litlen; - if (cur > litlen) - { - price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen, best_off, mlen - MINMATCH, ultra); - } - else - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra); - } - else - { - litlen = 0; - price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra); - } - - if (cur + mlen > last_pos || price <= opt[cur + mlen].price) - SET_PRICE(cur + mlen, mlen, i, litlen, price); - mlen--; - } while (mlen >= minMatch); - } - } - } - - match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen); - - if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) - { - best_mlen = matches[match_num - 1].len; - best_off = matches[match_num - 1].off; - last_pos = cur + 1; - goto _storeSequence; - } - - /* set prices using matches at position = cur */ - for (u = 0; u < match_num; u++) - { - mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen; - best_mlen = matches[u].len; - - while (mlen <= best_mlen) - { - if (opt[cur].mlen == 1) - { - litlen = opt[cur].litlen; - if (cur > litlen) - price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen, matches[u].off - 1, mlen - MINMATCH, ultra); - else - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra); - } - else - { - litlen = 0; - price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra); - } - - if (cur + mlen > last_pos || (price < opt[cur + mlen].price)) - SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price); - - mlen++; - } - } - } - - best_mlen = opt[last_pos].mlen; - best_off = opt[last_pos].off; - cur = last_pos - best_mlen; - - /* store sequence */ - _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ - opt[0].mlen = 1; - - while (1) - { - mlen = opt[cur].mlen; - offset = opt[cur].off; - opt[cur].mlen = best_mlen; - opt[cur].off = best_off; - best_mlen = mlen; - best_off = offset; - if (mlen > cur) - break; - cur -= mlen; - } - - for (u = 0; u <= last_pos;) - { - u += opt[u].mlen; - } - - for (cur = 0; cur < last_pos;) - { - mlen = opt[cur].mlen; - if (mlen == 1) - { - ip++; - cur++; - continue; - } - offset = opt[cur].off; - cur += mlen; - litLength = (U32)(ip - anchor); - - if (offset > ZSTD_REP_MOVE_OPT) - { - rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = offset - ZSTD_REP_MOVE_OPT; - offset--; - } - else - { - if (offset != 0) - { - best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]); - if (offset != 1) - rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = best_off; - } - if (litLength == 0) - offset--; - } - - ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH); - ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH); - anchor = ip = ip + mlen; - } - } /* for (cur=0; cur < last_pos; ) */ - - /* Save reps for next block */ - { - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - ctx->repToConfirm[i] = rep[i]; - } - - /* Last Literals */ - { - size_t const lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -FORCE_INLINE -void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx *ctx, - const void *src, size_t srcSize, const int ultra) -{ - seqStore_t *seqStorePtr = &(ctx->seqStore); - const BYTE *const istart = (const BYTE *)src; - const BYTE *ip = istart; - const BYTE *anchor = istart; - const BYTE *const iend = istart + srcSize; - const BYTE *const ilimit = iend - 8; - const BYTE *const base = ctx->base; - const U32 lowestIndex = ctx->lowLimit; - const U32 dictLimit = ctx->dictLimit; - const BYTE *const prefixStart = base + dictLimit; - const BYTE *const dictBase = ctx->dictBase; - const BYTE *const dictEnd = dictBase + dictLimit; - - const U32 maxSearches = 1U << ctx->params.cParams.searchLog; - const U32 sufficient_len = ctx->params.cParams.targetLength; - const U32 mls = ctx->params.cParams.searchLength; - const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4; - - ZSTD_optimal_t *opt = seqStorePtr->priceTable; - ZSTD_match_t *matches = seqStorePtr->matchTable; - const BYTE *inr; - - /* init */ - U32 offset, rep[ZSTD_REP_NUM]; - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - rep[i] = ctx->rep[i]; - } - - ctx->nextToUpdate3 = ctx->nextToUpdate; - ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize); - ip += (ip == prefixStart); - - /* Match Loop */ - while (ip < ilimit) - { - U32 cur, match_num, last_pos, litlen, price; - U32 u, mlen, best_mlen, best_off, litLength; - U32 current = (U32)(ip - base); - memset(opt, 0, sizeof(ZSTD_optimal_t)); - last_pos = 0; - opt[0].litlen = (U32)(ip - anchor); - - /* check repCode */ - { - U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor); - for (i = (ip == anchor); i < last_i; i++) - { - const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i]; - const U32 repIndex = (U32)(current - repCur); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if ((repCur > 0 && repCur <= (S32)current) && (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - && (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(repMatch, minMatch))) - { - /* repcode detected we should take it */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - mlen = (U32)ZSTD_count_2segments(ip + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch; - - if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) - { - best_mlen = mlen; - best_off = i; - cur = 0; - last_pos = 1; - goto _storeSequence; - } - - best_off = i - (ip == anchor); - litlen = opt[0].litlen; - do - { - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra); - if (mlen > last_pos || price < opt[mlen].price) - SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */ - mlen--; - } while (mlen >= minMatch); - } - } - } - - match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */ - - if (!last_pos && !match_num) - { - ip++; - continue; - } - - { - U32 i; - for (i = 0; i < ZSTD_REP_NUM; i++) - opt[0].rep[i] = rep[i]; - } - opt[0].mlen = 1; - - if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) - { - best_mlen = matches[match_num - 1].len; - best_off = matches[match_num - 1].off; - cur = 0; - last_pos = 1; - goto _storeSequence; - } - - best_mlen = (last_pos) ? last_pos : minMatch; - - /* set prices using matches at position = 0 */ - for (u = 0; u < match_num; u++) - { - mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen; - best_mlen = matches[u].len; - litlen = opt[0].litlen; - while (mlen <= best_mlen) - { - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra); - if (mlen > last_pos || price < opt[mlen].price) - SET_PRICE(mlen, mlen, matches[u].off, litlen, price); - mlen++; - } - } - - if (last_pos < minMatch) - { - ip++; - continue; - } - - /* check further positions */ - for (cur = 1; cur <= last_pos; cur++) - { - inr = ip + cur; - - if (opt[cur - 1].mlen == 1) - { - litlen = opt[cur - 1].litlen + 1; - if (cur > litlen) - { - price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen); - } - else - price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor); - } - else - { - litlen = 1; - price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1); - } - - if (cur > last_pos || price <= opt[cur].price) - SET_PRICE(cur, 1, 0, litlen, price); - - if (cur == last_pos) - break; - - if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */ - continue; - - mlen = opt[cur].mlen; - if (opt[cur].off > ZSTD_REP_MOVE_OPT) - { - opt[cur].rep[2] = opt[cur - mlen].rep[1]; - opt[cur].rep[1] = opt[cur - mlen].rep[0]; - opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT; - } - else - { - opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2]; - opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1]; - opt[cur].rep[0] = ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]); - } - - best_mlen = minMatch; - { - U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1); - for (i = (mlen != 1); i < last_i; i++) - { - const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i]; - const U32 repIndex = (U32)(current + cur - repCur); - const BYTE *const repBase = repIndex < dictLimit ? dictBase : base; - const BYTE *const repMatch = repBase + repIndex; - if ((repCur > 0 && repCur <= (S32)(current + cur)) && (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */ - && (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(repMatch, minMatch))) - { - /* repcode detected */ - const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend; - mlen = (U32)ZSTD_count_2segments(inr + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch; - - if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) - { - best_mlen = mlen; - best_off = i; - last_pos = cur + 1; - goto _storeSequence; - } - - best_off = i - (opt[cur].mlen != 1); - if (mlen > best_mlen) - best_mlen = mlen; - - do - { - if (opt[cur].mlen == 1) - { - litlen = opt[cur].litlen; - if (cur > litlen) - { - price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen, best_off, mlen - MINMATCH, ultra); - } - else - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra); - } - else - { - litlen = 0; - price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra); - } - - if (cur + mlen > last_pos || price <= opt[cur + mlen].price) - SET_PRICE(cur + mlen, mlen, i, litlen, price); - mlen--; - } while (mlen >= minMatch); - } - } - } - - match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch); - - if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) - { - best_mlen = matches[match_num - 1].len; - best_off = matches[match_num - 1].off; - last_pos = cur + 1; - goto _storeSequence; - } - - /* set prices using matches at position = cur */ - for (u = 0; u < match_num; u++) - { - mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen; - best_mlen = matches[u].len; - - while (mlen <= best_mlen) - { - if (opt[cur].mlen == 1) - { - litlen = opt[cur].litlen; - if (cur > litlen) - price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen, matches[u].off - 1, mlen - MINMATCH, ultra); - else - price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra); - } - else - { - litlen = 0; - price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra); - } - - if (cur + mlen > last_pos || (price < opt[cur + mlen].price)) - SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price); - - mlen++; - } - } - } /* for (cur = 1; cur <= last_pos; cur++) */ - - best_mlen = opt[last_pos].mlen; - best_off = opt[last_pos].off; - cur = last_pos - best_mlen; - - /* store sequence */ - _storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */ - opt[0].mlen = 1; - - while (1) - { - mlen = opt[cur].mlen; - offset = opt[cur].off; - opt[cur].mlen = best_mlen; - opt[cur].off = best_off; - best_mlen = mlen; - best_off = offset; - if (mlen > cur) - break; - cur -= mlen; - } - - for (u = 0; u <= last_pos;) - { - u += opt[u].mlen; - } - - for (cur = 0; cur < last_pos;) - { - mlen = opt[cur].mlen; - if (mlen == 1) - { - ip++; - cur++; - continue; - } - offset = opt[cur].off; - cur += mlen; - litLength = (U32)(ip - anchor); - - if (offset > ZSTD_REP_MOVE_OPT) - { - rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = offset - ZSTD_REP_MOVE_OPT; - offset--; - } - else - { - if (offset != 0) - { - best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]); - if (offset != 1) - rep[2] = rep[1]; - rep[1] = rep[0]; - rep[0] = best_off; - } - - if (litLength == 0) - offset--; - } - - ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH); - ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH); - anchor = ip = ip + mlen; - } - } /* for (cur=0; cur < last_pos; ) */ - - /* Save reps for next block */ - { - int i; - for (i = 0; i < ZSTD_REP_NUM; i++) - ctx->repToConfirm[i] = rep[i]; - } - - /* Last Literals */ - { - size_t lastLLSize = iend - anchor; - memcpy(seqStorePtr->lit, anchor, lastLLSize); - seqStorePtr->lit += lastLLSize; - } -} - -#endif /* ZSTD_OPT_H_91842398743 */ diff --git a/extra/zstd/zstd_v01.c b/extra/zstd/zstd_v01.c deleted file mode 100644 index e812b0ef..00000000 --- a/extra/zstd/zstd_v01.c +++ /dev/null @@ -1,2259 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -/****************************************** - * Includes - ******************************************/ -#include /* size_t, ptrdiff_t */ -#include "zstd_v01.h" -#include "error_private.h" - -/****************************************** - * Static allocation - ******************************************/ -/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */ -#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog)) - -/* You can statically allocate Huff0 DTable as a table of unsigned short using below macro */ -#define HUF_DTABLE_SIZE_U16(maxTableLog) (1 + (1 << maxTableLog)) -#define HUF_CREATE_STATIC_DTABLE(DTable, maxTableLog) \ - unsigned short DTable[HUF_DTABLE_SIZE_U16(maxTableLog)] = {maxTableLog} - -/****************************************** - * Error Management - ******************************************/ -#define FSE_LIST_ERRORS(ITEM) \ - ITEM(FSE_OK_NoError) \ - ITEM(FSE_ERROR_GENERIC) \ - ITEM(FSE_ERROR_tableLog_tooLarge) \ - ITEM(FSE_ERROR_maxSymbolValue_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooSmall) \ - ITEM(FSE_ERROR_dstSize_tooSmall) ITEM(FSE_ERROR_srcSize_wrong) \ - ITEM(FSE_ERROR_corruptionDetected) \ - ITEM(FSE_ERROR_maxCode) - -#define FSE_GENERATE_ENUM(ENUM) ENUM, -typedef enum -{ - FSE_LIST_ERRORS(FSE_GENERATE_ENUM) -} FSE_errorCodes; /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */ - -/****************************************** - * FSE symbol compression API - ******************************************/ -/* - This API consists of small unitary functions, which highly benefit from being inlined. - You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary. - Visual seems to do it automatically. - For gcc or clang, you'll need to add -flto flag at compilation and linking stages. - If none of these solutions is applicable, include "fse.c" directly. -*/ - -typedef unsigned FSE_CTable; /* don't allocate that. It's just a way to be more restrictive than void* */ -typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ - -typedef struct -{ - size_t bitContainer; - int bitPos; - char *startPtr; - char *ptr; - char *endPtr; -} FSE_CStream_t; - -typedef struct -{ - ptrdiff_t value; - const void *stateTable; - const void *symbolTT; - unsigned stateLog; -} FSE_CState_t; - -typedef struct -{ - size_t bitContainer; - unsigned bitsConsumed; - const char *ptr; - const char *start; -} FSE_DStream_t; - -typedef struct -{ - size_t state; - const void *table; /* precise table may vary, depending on U16 */ -} FSE_DState_t; - -typedef enum -{ - FSE_DStream_unfinished = 0, - FSE_DStream_endOfBuffer = 1, - FSE_DStream_completed = 2, - FSE_DStream_tooFar = 3 -} FSE_DStream_status; /* result of FSE_reloadDStream() */ - /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... ?! */ - -/**************************************************************** - * 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 */ -#define FSE_MAX_MEMORY_USAGE 14 -#define FSE_DEFAULT_MEMORY_USAGE 13 - -/* FSE_MAX_SYMBOL_VALUE : - * Maximum symbol value authorized. - * Required for proper stack allocation */ -#define FSE_MAX_SYMBOL_VALUE 255 - -/**************************************************************** - * template functions type & suffix - ****************************************************************/ -#define FSE_FUNCTION_TYPE BYTE -#define FSE_FUNCTION_EXTENSION - -/**************************************************************** - * Byte symbol type - ****************************************************************/ -typedef struct -{ - unsigned short newState; - unsigned char symbol; - unsigned char nbBits; -} FSE_decode_t; /* size == U32 */ - -/**************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ -#else -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/**************************************************************** - * Includes - ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include /* printf (debug) */ - -#ifndef MEM_ACCESS_MODULE -#define MEM_ACCESS_MODULE -/**************************************************************** - * Basic Types - *****************************************************************/ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#include -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 -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef signed short S16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; -typedef signed long long S64; -#endif - -#endif /* MEM_ACCESS_MODULE */ - -/**************************************************************** - * Memory I/O - *****************************************************************/ -/* FSE_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 (ie, 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 generating assembly depending on alignment. - * But in some circumstances, it's the only known way to get the most performance (ie 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 FSE_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 FSE_FORCE_MEMORY_ACCESS 2 -#elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \ - (defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__))) -#define FSE_FORCE_MEMORY_ACCESS 1 -#endif -#endif - -static unsigned FSE_32bits(void) -{ - return sizeof(void *) == 4; -} - -static unsigned FSE_isLittleEndian(void) -{ - const union - { - U32 i; - BYTE c[4]; - } one = {1}; /* don't use static : performance detrimental */ - return one.c[0]; -} - -#if defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS == 2) - -static U16 FSE_read16(const void *memPtr) { return *(const U16 *)memPtr; } -static U32 FSE_read32(const void *memPtr) { return *(const U32 *)memPtr; } -static U64 FSE_read64(const void *memPtr) { return *(const U64 *)memPtr; } - -#elif defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS == 1) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union -{ - U16 u16; - U32 u32; - U64 u64; -} __attribute__((packed)) unalign; - -static U16 FSE_read16(const void *ptr) { return ((const unalign *)ptr)->u16; } -static U32 FSE_read32(const void *ptr) { return ((const unalign *)ptr)->u32; } -static U64 FSE_read64(const void *ptr) { return ((const unalign *)ptr)->u64; } - -#else - -static U16 FSE_read16(const void *memPtr) -{ - U16 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -static U32 FSE_read32(const void *memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -static U64 FSE_read64(const void *memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif // FSE_FORCE_MEMORY_ACCESS - -static U16 FSE_readLE16(const void *memPtr) -{ - if (FSE_isLittleEndian()) - return FSE_read16(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U16)(p[0] + (p[1] << 8)); - } -} - -static U32 FSE_readLE32(const void *memPtr) -{ - if (FSE_isLittleEndian()) - return FSE_read32(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U32)((U32)p[0] + ((U32)p[1] << 8) + ((U32)p[2] << 16) + ((U32)p[3] << 24)); - } -} - -static U64 FSE_readLE64(const void *memPtr) -{ - if (FSE_isLittleEndian()) - return FSE_read64(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U64)((U64)p[0] + ((U64)p[1] << 8) + ((U64)p[2] << 16) + ((U64)p[3] << 24) + ((U64)p[4] << 32) + ((U64)p[5] << 40) + ((U64)p[6] << 48) + ((U64)p[7] << 56)); - } -} - -static size_t FSE_readLEST(const void *memPtr) -{ - if (FSE_32bits()) - return (size_t)FSE_readLE32(memPtr); - else - return (size_t)FSE_readLE64(memPtr); -} - -/**************************************************************** - * 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 - -/**************************************************************** - * Error Management - ****************************************************************/ -#define FSE_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - FSE_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/**************************************************************** - * Complex types - ****************************************************************/ -typedef struct -{ - int deltaFindState; - U32 deltaNbBits; -} FSE_symbolCompressionTransform; /* total 8 bytes */ - -typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; - -/**************************************************************** - * Internal functions - ****************************************************************/ -FORCE_INLINE unsigned FSE_highbit32(register U32 val) -{ -#if defined(_MSC_VER) /* Visual */ - unsigned long r; - _BitScanReverse(&r, val); - return (unsigned)r; -#elif defined(__GNUC__) && (GCC_VERSION >= 304) /* GCC Intrinsic */ - return 31 - __builtin_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; - unsigned r; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; - return r; -#endif -} - -/**************************************************************** - * Templates - ****************************************************************/ -/* - designed to be included - for type-specific functions (template emulation in C) - Objective is to write these functions only once, for improved maintenance -*/ - -/* safety checks */ -#ifndef FSE_FUNCTION_EXTENSION -#error "FSE_FUNCTION_EXTENSION must be defined" -#endif -#ifndef FSE_FUNCTION_TYPE -#error "FSE_FUNCTION_TYPE must be defined" -#endif - -/* Function names */ -#define FSE_CAT(X, Y) X##Y -#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y) -#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y) - -static U32 FSE_tableStep(U32 tableSize) { return (tableSize >> 1) + (tableSize >> 3) + 3; } - -#define FSE_DECODE_TYPE FSE_decode_t - -typedef struct -{ - U16 tableLog; - U16 fastMode; -} FSE_DTableHeader; /* sizeof U32 */ - -static size_t FSE_buildDTable(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(ptr) + 1; /* because dt is unsigned, 32-bits aligned on 32-bits */ - const U32 tableSize = 1 << tableLog; - const U32 tableMask = tableSize - 1; - const U32 step = FSE_tableStep(tableSize); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE + 1]; - U32 position = 0; - U32 highThreshold = tableSize - 1; - const S16 largeLimit = (S16)(1 << (tableLog - 1)); - U32 noLarge = 1; - U32 s; - - /* Sanity Checks */ - if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) - return (size_t)-FSE_ERROR_maxSymbolValue_tooLarge; - if (tableLog > FSE_MAX_TABLELOG) - return (size_t)-FSE_ERROR_tableLog_tooLarge; - - /* Init, lay down lowprob symbols */ - DTableH[0].tableLog = (U16)tableLog; - for (s = 0; s <= maxSymbolValue; s++) - { - if (normalizedCounter[s] == -1) - { - tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; - symbolNext[s] = 1; - } - else - { - if (normalizedCounter[s] >= largeLimit) - noLarge = 0; - symbolNext[s] = normalizedCounter[s]; - } - } - - /* Spread symbols */ - for (s = 0; s <= maxSymbolValue; s++) - { - int i; - for (i = 0; i < normalizedCounter[s]; i++) - { - tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; - position = (position + step) & tableMask; - while (position > highThreshold) - position = (position + step) & tableMask; /* lowprob area */ - } - } - - if (position != 0) - return (size_t)-FSE_ERROR_GENERIC; /* position must reach all cells once, otherwise normalizedCounter is incorrect */ - - /* Build Decoding table */ - { - U32 i; - for (i = 0; i < tableSize; i++) - { - FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol); - U16 nextState = symbolNext[symbol]++; - tableDecode[i].nbBits = (BYTE)(tableLog - FSE_highbit32((U32)nextState)); - tableDecode[i].newState = (U16)((nextState << tableDecode[i].nbBits) - tableSize); - } - } - - DTableH->fastMode = (U16)noLarge; - return 0; -} - -/****************************************** - * FSE byte symbol - ******************************************/ -#ifndef FSE_COMMONDEFS_ONLY - -static unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_maxCode)); } - -static short FSE_abs(short a) -{ - return a < 0 ? -a : a; -} - -/**************************************************************** - * Header bitstream management - ****************************************************************/ -static size_t FSE_readNCount(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; - int previous0 = 0; - - if (hbSize < 4) - return (size_t)-FSE_ERROR_srcSize_wrong; - bitStream = FSE_readLE32(ip); - nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ - if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) - return (size_t)-FSE_ERROR_tableLog_tooLarge; - bitStream >>= 4; - bitCount = 4; - *tableLogPtr = nbBits; - remaining = (1 << nbBits) + 1; - threshold = 1 << nbBits; - nbBits++; - - while ((remaining > 1) && (charnum <= *maxSVPtr)) - { - if (previous0) - { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) - { - n0 += 24; - if (ip < iend - 5) - { - ip += 2; - bitStream = FSE_readLE32(ip) >> bitCount; - } - else - { - bitStream >>= 16; - bitCount += 16; - } - } - while ((bitStream & 3) == 3) - { - n0 += 3; - bitStream >>= 2; - bitCount += 2; - } - n0 += bitStream & 3; - bitCount += 2; - if (n0 > *maxSVPtr) - return (size_t)-FSE_ERROR_maxSymbolValue_tooSmall; - while (charnum < n0) - normalizedCounter[charnum++] = 0; - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - bitStream = FSE_readLE32(ip) >> bitCount; - } - else - bitStream >>= 2; - } - { - const short max = (short)((2 * threshold - 1) - remaining); - short count; - - if ((bitStream & (threshold - 1)) < (U32)max) - { - count = (short)(bitStream & (threshold - 1)); - bitCount += nbBits - 1; - } - else - { - count = (short)(bitStream & (2 * threshold - 1)); - if (count >= threshold) - count -= max; - bitCount += nbBits; - } - - count--; /* extra accuracy */ - remaining -= FSE_abs(count); - normalizedCounter[charnum++] = count; - previous0 = !count; - while (remaining < threshold) - { - nbBits--; - threshold >>= 1; - } - - { - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - } - else - { - bitCount -= (int)(8 * (iend - 4 - ip)); - ip = iend - 4; - } - bitStream = FSE_readLE32(ip) >> (bitCount & 31); - } - } - } - if (remaining != 1) - return (size_t)-FSE_ERROR_GENERIC; - *maxSVPtr = charnum - 1; - - ip += (bitCount + 7) >> 3; - if ((size_t)(ip - istart) > hbSize) - return (size_t)-FSE_ERROR_srcSize_wrong; - return ip - istart; -} - -/********************************************************* - * Decompression (Byte symbols) - *********************************************************/ -static size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - FSE_decode_t *const cell = (FSE_decode_t *)(ptr) + 1; /* because dt is unsigned */ - - DTableH->tableLog = 0; - DTableH->fastMode = 0; - - cell->newState = 0; - cell->symbol = symbolValue; - cell->nbBits = 0; - - return 0; -} - -static size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - FSE_decode_t *const dinfo = (FSE_decode_t *)(ptr) + 1; /* because dt is unsigned */ - const unsigned tableSize = 1 << nbBits; - const unsigned tableMask = tableSize - 1; - const unsigned maxSymbolValue = tableMask; - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) - return (size_t)-FSE_ERROR_GENERIC; /* min size */ - - /* Build Decoding Table */ - DTableH->tableLog = (U16)nbBits; - DTableH->fastMode = 1; - for (s = 0; s <= maxSymbolValue; s++) - { - dinfo[s].newState = 0; - dinfo[s].symbol = (BYTE)s; - dinfo[s].nbBits = (BYTE)nbBits; - } - - return 0; -} - -/* FSE_initDStream - * Initialize a FSE_DStream_t. - * srcBuffer must point at the beginning of an FSE block. - * The function result is the size of the FSE_block (== srcSize). - * If srcSize is too small, the function will return an errorCode; - */ -static size_t FSE_initDStream(FSE_DStream_t *bitD, const void *srcBuffer, size_t srcSize) -{ - if (srcSize < 1) - return (size_t)-FSE_ERROR_srcSize_wrong; - - if (srcSize >= sizeof(size_t)) - { - U32 contain32; - bitD->start = (const char *)srcBuffer; - bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(size_t); - bitD->bitContainer = FSE_readLEST(bitD->ptr); - contain32 = ((const BYTE *)srcBuffer)[srcSize - 1]; - if (contain32 == 0) - return (size_t)-FSE_ERROR_GENERIC; /* stop bit not present */ - bitD->bitsConsumed = 8 - FSE_highbit32(contain32); - } - else - { - U32 contain32; - bitD->start = (const char *)srcBuffer; - bitD->ptr = bitD->start; - bitD->bitContainer = *(const BYTE *)(bitD->start); - /* fall through */ - switch (srcSize) - { - case 7: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[6]) << (sizeof(size_t) * 8 - 16); /* fall through */ - case 6: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[5]) << (sizeof(size_t) * 8 - 24); /* fall through */ - case 5: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[4]) << (sizeof(size_t) * 8 - 32); /* fall through */ - case 4: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[3]) << 24; /* fall through */ - case 3: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[2]) << 16; /* fall through */ - case 2: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[1]) << 8; /* fall through */ - default:; - } - contain32 = ((const BYTE *)srcBuffer)[srcSize - 1]; - if (contain32 == 0) - return (size_t)-FSE_ERROR_GENERIC; /* stop bit not present */ - bitD->bitsConsumed = 8 - FSE_highbit32(contain32); - bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize) * 8; - } - - return srcSize; -} - -/*!FSE_lookBits - * Provides next n bits from the bitContainer. - * bitContainer is not modified (bits are still present for next read/look) - * On 32-bits, maxNbBits==25 - * On 64-bits, maxNbBits==57 - * return : value extracted. - */ -static size_t FSE_lookBits(FSE_DStream_t *bitD, U32 nbBits) -{ - const U32 bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask); -} - -static size_t FSE_lookBitsFast(FSE_DStream_t *bitD, U32 nbBits) /* only if nbBits >= 1 !! */ -{ - const U32 bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask); -} - -static void FSE_skipBits(FSE_DStream_t *bitD, U32 nbBits) -{ - bitD->bitsConsumed += nbBits; -} - -/*!FSE_readBits - * Read next n bits from the bitContainer. - * On 32-bits, don't read more than maxNbBits==25 - * On 64-bits, don't read more than maxNbBits==57 - * Use the fast variant *only* if n >= 1. - * return : value extracted. - */ -static size_t FSE_readBits(FSE_DStream_t *bitD, U32 nbBits) -{ - size_t value = FSE_lookBits(bitD, nbBits); - FSE_skipBits(bitD, nbBits); - return value; -} - -static size_t FSE_readBitsFast(FSE_DStream_t *bitD, U32 nbBits) /* only if nbBits >= 1 !! */ -{ - size_t value = FSE_lookBitsFast(bitD, nbBits); - FSE_skipBits(bitD, nbBits); - return value; -} - -static unsigned FSE_reloadDStream(FSE_DStream_t *bitD) -{ - if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should never happen */ - return FSE_DStream_tooFar; - - if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) - { - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = FSE_readLEST(bitD->ptr); - return FSE_DStream_unfinished; - } - if (bitD->ptr == bitD->start) - { - if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8) - return FSE_DStream_endOfBuffer; - return FSE_DStream_completed; - } - { - U32 nbBytes = bitD->bitsConsumed >> 3; - U32 result = FSE_DStream_unfinished; - if (bitD->ptr - nbBytes < bitD->start) - { - nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ - result = FSE_DStream_endOfBuffer; - } - bitD->ptr -= nbBytes; - bitD->bitsConsumed -= nbBytes * 8; - bitD->bitContainer = FSE_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ - return result; - } -} - -static void FSE_initDState(FSE_DState_t *DStatePtr, FSE_DStream_t *bitD, const FSE_DTable *dt) -{ - const void *ptr = dt; - const FSE_DTableHeader *const DTableH = (const FSE_DTableHeader *)ptr; - DStatePtr->state = FSE_readBits(bitD, DTableH->tableLog); - FSE_reloadDStream(bitD); - DStatePtr->table = dt + 1; -} - -static BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, FSE_DStream_t *bitD) -{ - const FSE_decode_t DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state]; - const U32 nbBits = DInfo.nbBits; - BYTE symbol = DInfo.symbol; - size_t lowBits = FSE_readBits(bitD, nbBits); - - DStatePtr->state = DInfo.newState + lowBits; - return symbol; -} - -static BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, FSE_DStream_t *bitD) -{ - const FSE_decode_t DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state]; - const U32 nbBits = DInfo.nbBits; - BYTE symbol = DInfo.symbol; - size_t lowBits = FSE_readBitsFast(bitD, nbBits); - - DStatePtr->state = DInfo.newState + lowBits; - return symbol; -} - -/* FSE_endOfDStream - Tells if bitD has reached end of bitStream or not */ - -static unsigned FSE_endOfDStream(const FSE_DStream_t *bitD) -{ - return ((bitD->ptr == bitD->start) && (bitD->bitsConsumed == sizeof(bitD->bitContainer) * 8)); -} - -static unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr) -{ - return DStatePtr->state == 0; -} - -FORCE_INLINE size_t FSE_decompress_usingDTable_generic( - void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt, const unsigned fast) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - BYTE *const omax = op + maxDstSize; - BYTE *const olimit = omax - 3; - - FSE_DStream_t bitD; - FSE_DState_t state1; - FSE_DState_t state2; - size_t errorCode; - - /* Init */ - errorCode = FSE_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ - if (FSE_isError(errorCode)) - return errorCode; - - FSE_initDState(&state1, &bitD, dt); - FSE_initDState(&state2, &bitD, dt); - -#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) - - /* 4 symbols per loop */ - for (; (FSE_reloadDStream(&bitD) == FSE_DStream_unfinished) && (op < olimit); op += 4) - { - op[0] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - FSE_reloadDStream(&bitD); - - op[1] = FSE_GETSYMBOL(&state2); - - if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - { - if (FSE_reloadDStream(&bitD) > FSE_DStream_unfinished) - { - op += 2; - break; - } - } - - op[2] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - FSE_reloadDStream(&bitD); - - op[3] = FSE_GETSYMBOL(&state2); - } - - /* tail */ - /* note : FSE_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly FSE_DStream_completed */ - while (1) - { - if ((FSE_reloadDStream(&bitD) > FSE_DStream_completed) || (op == omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1)))) - break; - - *op++ = FSE_GETSYMBOL(&state1); - - if ((FSE_reloadDStream(&bitD) > FSE_DStream_completed) || (op == omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2)))) - break; - - *op++ = FSE_GETSYMBOL(&state2); - } - - /* end ? */ - if (FSE_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) - return op - ostart; - - if (op == omax) - return (size_t)-FSE_ERROR_dstSize_tooSmall; /* dst buffer is full, but cSrc unfinished */ - - return (size_t)-FSE_ERROR_corruptionDetected; -} - -static size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt) -{ - FSE_DTableHeader DTableH; - memcpy(&DTableH, dt, sizeof(DTableH)); /* memcpy() into local variable, to avoid strict aliasing warning */ - - /* select fast mode (static) */ - if (DTableH.fastMode) - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); -} - -static size_t FSE_decompress(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *const istart = (const BYTE *)cSrc; - const BYTE *ip = istart; - short counting[FSE_MAX_SYMBOL_VALUE + 1]; - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - unsigned tableLog; - unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; - size_t errorCode; - - if (cSrcSize < 2) - return (size_t)-FSE_ERROR_srcSize_wrong; /* too small input size */ - - /* normal FSE decoding mode */ - errorCode = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize); - if (FSE_isError(errorCode)) - return errorCode; - if (errorCode >= cSrcSize) - return (size_t)-FSE_ERROR_srcSize_wrong; /* too small input size */ - ip += errorCode; - cSrcSize -= errorCode; - - errorCode = FSE_buildDTable(dt, counting, maxSymbolValue, tableLog); - if (FSE_isError(errorCode)) - return errorCode; - - /* always return, even if it is an error code */ - return FSE_decompress_usingDTable(dst, maxDstSize, ip, cSrcSize, dt); -} - -/* ******************************************************* - * Huff0 : Huffman block compression - *********************************************************/ -#define HUF_MAX_SYMBOL_VALUE 255 -#define HUF_DEFAULT_TABLELOG 12 /* used by default, when not specified */ -#define HUF_MAX_TABLELOG 12 /* max possible tableLog; for allocation purpose; can be modified */ -#define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ -#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) -#error "HUF_MAX_TABLELOG is too large !" -#endif - -typedef struct HUF_CElt_s -{ - U16 val; - BYTE nbBits; -} HUF_CElt; - -typedef struct nodeElt_s -{ - U32 count; - U16 parent; - BYTE byte; - BYTE nbBits; -} nodeElt; - -/* ******************************************************* - * Huff0 : Huffman block decompression - *********************************************************/ -typedef struct -{ - BYTE byte; - BYTE nbBits; -} HUF_DElt; - -static size_t HUF_readDTable(U16 *DTable, const void *src, size_t srcSize) -{ - BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; - U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ - U32 weightTotal; - U32 maxBits; - const BYTE *ip = (const BYTE *)src; - size_t iSize; - size_t oSize; - U32 n; - U32 nextRankStart; - void *ptr = DTable + 1; - HUF_DElt *const dt = (HUF_DElt *)ptr; - - if (!srcSize) - return (size_t)-FSE_ERROR_srcSize_wrong; - iSize = ip[0]; - - FSE_STATIC_ASSERT(sizeof(HUF_DElt) == sizeof(U16)); /* if compilation fails here, assertion is false */ - // memset(huffWeight, 0, sizeof(huffWeight)); /* should not be necessary, but some analyzer complain ... */ - if (iSize >= 128) /* special header */ - { - if (iSize >= (242)) /* RLE */ - { - static int l[14] = {1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128}; - oSize = l[iSize - 242]; - memset(huffWeight, 1, sizeof(huffWeight)); - iSize = 0; - } - else /* Incompressible */ - { - oSize = iSize - 127; - iSize = ((oSize + 1) / 2); - if (iSize + 1 > srcSize) - return (size_t)-FSE_ERROR_srcSize_wrong; - ip += 1; - 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 (size_t)-FSE_ERROR_srcSize_wrong; - oSize = FSE_decompress(huffWeight, HUF_MAX_SYMBOL_VALUE, ip + 1, iSize); /* max 255 values decoded, last one is implied */ - if (FSE_isError(oSize)) - return oSize; - } - - /* collect weight stats */ - memset(rankVal, 0, sizeof(rankVal)); - weightTotal = 0; - for (n = 0; n < oSize; n++) - { - if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) - return (size_t)-FSE_ERROR_corruptionDetected; - rankVal[huffWeight[n]]++; - weightTotal += (1 << huffWeight[n]) >> 1; - } - if (weightTotal == 0) - return (size_t)-FSE_ERROR_corruptionDetected; - - /* get last non-null symbol weight (implied, total must be 2^n) */ - maxBits = FSE_highbit32(weightTotal) + 1; - if (maxBits > DTable[0]) - return (size_t)-FSE_ERROR_tableLog_tooLarge; /* DTable is too small */ - DTable[0] = (U16)maxBits; - { - U32 total = 1 << maxBits; - U32 rest = total - weightTotal; - U32 verif = 1 << FSE_highbit32(rest); - U32 lastWeight = FSE_highbit32(rest) + 1; - if (verif != rest) - return (size_t)-FSE_ERROR_corruptionDetected; /* last value must be a clean power of 2 */ - huffWeight[oSize] = (BYTE)lastWeight; - rankVal[lastWeight]++; - } - - /* check tree construction validity */ - if ((rankVal[1] < 2) || (rankVal[1] & 1)) - return (size_t)-FSE_ERROR_corruptionDetected; /* by construction : at least 2 elts of rank 1, must be even */ - - /* Prepare ranks */ - nextRankStart = 0; - for (n = 1; n <= maxBits; n++) - { - U32 current = nextRankStart; - nextRankStart += (rankVal[n] << (n - 1)); - rankVal[n] = current; - } - - /* fill DTable */ - for (n = 0; n <= oSize; n++) - { - const U32 w = huffWeight[n]; - const U32 length = (1 << w) >> 1; - U32 i; - HUF_DElt D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(maxBits + 1 - w); - for (i = rankVal[w]; i < rankVal[w] + length; i++) - dt[i] = D; - rankVal[w] += length; - } - - return iSize + 1; -} - -static BYTE HUF_decodeSymbol(FSE_DStream_t *Dstream, const HUF_DElt *dt, const U32 dtLog) -{ - const size_t val = FSE_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ - const BYTE c = dt[val].byte; - FSE_skipBits(Dstream, dt[val].nbBits); - return c; -} - -static size_t HUF_decompress_usingDTable(/* -3% slower when non static */ - void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const U16 *DTable) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - BYTE *const omax = op + maxDstSize; - BYTE *const olimit = omax - 15; - - const void *ptr = DTable; - const HUF_DElt *const dt = (const HUF_DElt *)(ptr) + 1; - const U32 dtLog = DTable[0]; - size_t errorCode; - U32 reloadStatus; - - /* Init */ - - const U16 *jumpTable = (const U16 *)cSrc; - const size_t length1 = FSE_readLE16(jumpTable); - const size_t length2 = FSE_readLE16(jumpTable + 1); - const size_t length3 = FSE_readLE16(jumpTable + 2); - const size_t length4 = cSrcSize - 6 - length1 - length2 - length3; // check coherency !! - const char *const start1 = (const char *)(cSrc) + 6; - const char *const start2 = start1 + length1; - const char *const start3 = start2 + length2; - const char *const start4 = start3 + length3; - FSE_DStream_t bitD1, bitD2, bitD3, bitD4; - - if (length1 + length2 + length3 + 6 >= cSrcSize) - return (size_t)-FSE_ERROR_srcSize_wrong; - - errorCode = FSE_initDStream(&bitD1, start1, length1); - if (FSE_isError(errorCode)) - return errorCode; - errorCode = FSE_initDStream(&bitD2, start2, length2); - if (FSE_isError(errorCode)) - return errorCode; - errorCode = FSE_initDStream(&bitD3, start3, length3); - if (FSE_isError(errorCode)) - return errorCode; - errorCode = FSE_initDStream(&bitD4, start4, length4); - if (FSE_isError(errorCode)) - return errorCode; - - reloadStatus = FSE_reloadDStream(&bitD2); - - /* 16 symbols per loop */ - for (; (reloadStatus < FSE_DStream_completed) && (op < olimit); /* D2-3-4 are supposed to be synchronized and finish together */ - op += 16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1)) - { -#define HUF_DECODE_SYMBOL_0(n, Dstream) \ - op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); - -#define HUF_DECODE_SYMBOL_1(n, Dstream) \ - op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ - if (FSE_32bits() && (HUF_MAX_TABLELOG > 12)) \ - FSE_reloadDStream(&Dstream) - -#define HUF_DECODE_SYMBOL_2(n, Dstream) \ - op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ - if (FSE_32bits()) \ - FSE_reloadDStream(&Dstream) - - HUF_DECODE_SYMBOL_1(0, bitD1); - HUF_DECODE_SYMBOL_1(1, bitD2); - HUF_DECODE_SYMBOL_1(2, bitD3); - HUF_DECODE_SYMBOL_1(3, bitD4); - HUF_DECODE_SYMBOL_2(4, bitD1); - HUF_DECODE_SYMBOL_2(5, bitD2); - HUF_DECODE_SYMBOL_2(6, bitD3); - HUF_DECODE_SYMBOL_2(7, bitD4); - HUF_DECODE_SYMBOL_1(8, bitD1); - HUF_DECODE_SYMBOL_1(9, bitD2); - HUF_DECODE_SYMBOL_1(10, bitD3); - HUF_DECODE_SYMBOL_1(11, bitD4); - HUF_DECODE_SYMBOL_0(12, bitD1); - HUF_DECODE_SYMBOL_0(13, bitD2); - HUF_DECODE_SYMBOL_0(14, bitD3); - HUF_DECODE_SYMBOL_0(15, bitD4); - } - - if (reloadStatus != FSE_DStream_completed) /* not complete : some bitStream might be FSE_DStream_unfinished */ - return (size_t)-FSE_ERROR_corruptionDetected; - - /* tail */ - { - // bitTail = bitD1; // *much* slower : -20% !??! - FSE_DStream_t bitTail; - bitTail.ptr = bitD1.ptr; - bitTail.bitsConsumed = bitD1.bitsConsumed; - bitTail.bitContainer = bitD1.bitContainer; // required in case of FSE_DStream_endOfBuffer - bitTail.start = start1; - for (; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op < omax); op++) - { - HUF_DECODE_SYMBOL_0(0, bitTail); - } - - if (FSE_endOfDStream(&bitTail)) - return op - ostart; - } - - if (op == omax) - return (size_t)-FSE_ERROR_dstSize_tooSmall; /* dst buffer is full, but cSrc unfinished */ - - return (size_t)-FSE_ERROR_corruptionDetected; -} - -static size_t HUF_decompress(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLE(DTable, HUF_MAX_TABLELOG); - const BYTE *ip = (const BYTE *)cSrc; - size_t errorCode; - - errorCode = HUF_readDTable(DTable, cSrc, cSrcSize); - if (FSE_isError(errorCode)) - return errorCode; - if (errorCode >= cSrcSize) - return (size_t)-FSE_ERROR_srcSize_wrong; - ip += errorCode; - cSrcSize -= errorCode; - - return HUF_decompress_usingDTable(dst, maxDstSize, ip, cSrcSize, DTable); -} - -#endif /* FSE_COMMONDEFS_ONLY */ - -/* - zstd - standard compression library - Copyright (C) 2014-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - zstd source repository : https://github.com/Cyan4973/zstd - - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -/**************************************************************** - * 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 */ -#define ZSTD_MEMORY_USAGE 17 - -/************************************** - CPU Feature Detection -**************************************/ -/* - * Automated efficient unaligned memory access detection - * Based on known hardware architectures - * This list will be updated thanks to feedbacks - */ -#if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) || defined(__ARM_FEATURE_UNALIGNED) || defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) || (defined(_M_ARM) && (_M_ARM >= 7)) -#define ZSTD_UNALIGNED_ACCESS 1 -#else -#define ZSTD_UNALIGNED_ACCESS 0 -#endif - -/******************************************************** - * Includes - *********************************************************/ -#include /* calloc */ -#include /* memcpy, memmove */ -#include /* debug : printf */ - -/******************************************************** - * Compiler specifics - *********************************************************/ -#ifdef __AVX2__ -#include /* AVX2 intrinsics */ -#endif - -#ifdef _MSC_VER /* Visual Studio */ -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4324) /* disable: C4324: padded structure */ -#endif - -#ifndef MEM_ACCESS_MODULE -#define MEM_ACCESS_MODULE -/******************************************************** - * Basic Types - *********************************************************/ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#include -typedef uint8_t BYTE; -typedef uint16_t U16; -typedef int16_t S16; -typedef uint32_t U32; -typedef int32_t S32; -typedef uint64_t U64; -#else -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef signed short S16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; -#endif - -#endif /* MEM_ACCESS_MODULE */ - -/******************************************************** - * Constants - *********************************************************/ -static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header */ - -#define HASH_LOG (ZSTD_MEMORY_USAGE - 2) -#define HASH_TABLESIZE (1 << HASH_LOG) -#define HASH_MASK (HASH_TABLESIZE - 1) - -#define KNUTH 2654435761 - -#define BIT7 128 -#define BIT6 64 -#define BIT5 32 -#define BIT4 16 - -#define KB *(1 << 10) -#define MB *(1 << 20) -#define GB *(1U << 30) - -#define BLOCKSIZE (128 KB) /* define, for static allocation */ - -#define WORKPLACESIZE (BLOCKSIZE * 3) -#define MINMATCH 4 -#define MLbits 7 -#define LLbits 6 -#define Offbits 5 -#define MaxML ((1 << MLbits) - 1) -#define MaxLL ((1 << LLbits) - 1) -#define MaxOff ((1 << Offbits) - 1) -#define LitFSELog 11 -#define MLFSELog 10 -#define LLFSELog 10 -#define OffFSELog 9 -#define MAX(a, b) ((a) < (b) ? (b) : (a)) -#define MaxSeq MAX(MaxLL, MaxML) - -#define LITERAL_NOENTROPY 63 -#define COMMAND_NOENTROPY 7 /* to remove */ - -static const size_t ZSTD_blockHeaderSize = 3; -static const size_t ZSTD_frameHeaderSize = 4; - -/******************************************************** - * Memory operations - *********************************************************/ -static unsigned ZSTD_32bits(void) { return sizeof(void *) == 4; } - -static unsigned ZSTD_isLittleEndian(void) -{ - const union - { - U32 i; - BYTE c[4]; - } one = {1}; /* don't use static : performance detrimental */ - return one.c[0]; -} - -static U16 ZSTD_read16(const void *p) -{ - U16 r; - memcpy(&r, p, sizeof(r)); - return r; -} - -static U32 ZSTD_read32(const void *p) -{ - U32 r; - memcpy(&r, p, sizeof(r)); - return r; -} - -static void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); } - -static void ZSTD_copy8(void *dst, const void *src) { memcpy(dst, src, 8); } - -#define COPY8(d, s) \ - { \ - ZSTD_copy8(d, s); \ - d += 8; \ - s += 8; \ - } - -static void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length) -{ - const BYTE *ip = (const BYTE *)src; - BYTE *op = (BYTE *)dst; - BYTE *const oend = op + length; - while (op < oend) - COPY8(op, ip); -} - -static U16 ZSTD_readLE16(const void *memPtr) -{ - if (ZSTD_isLittleEndian()) - return ZSTD_read16(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U16)((U16)p[0] + ((U16)p[1] << 8)); - } -} - -static U32 ZSTD_readLE32(const void *memPtr) -{ - if (ZSTD_isLittleEndian()) - return ZSTD_read32(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U32)((U32)p[0] + ((U32)p[1] << 8) + ((U32)p[2] << 16) + ((U32)p[3] << 24)); - } -} - -static U32 ZSTD_readBE32(const void *memPtr) -{ - const BYTE *p = (const BYTE *)memPtr; - return (U32)(((U32)p[0] << 24) + ((U32)p[1] << 16) + ((U32)p[2] << 8) + ((U32)p[3] << 0)); -} - -/************************************** - * Local structures - ***************************************/ -typedef struct ZSTD_Cctx_s ZSTD_Cctx; - -typedef enum -{ - bt_compressed, - bt_raw, - bt_rle, - bt_end -} blockType_t; - -typedef struct -{ - blockType_t blockType; - U32 origSize; -} blockProperties_t; - -typedef struct -{ - void *buffer; - U32 *offsetStart; - U32 *offset; - BYTE *offCodeStart; - BYTE *offCode; - BYTE *litStart; - BYTE *lit; - BYTE *litLengthStart; - BYTE *litLength; - BYTE *matchLengthStart; - BYTE *matchLength; - BYTE *dumpsStart; - BYTE *dumps; -} seqStore_t; - -typedef struct ZSTD_Cctx_s -{ - const BYTE *base; - U32 current; - U32 nextUpdate; - seqStore_t seqStore; -#ifdef __AVX2__ - __m256i hashTable[HASH_TABLESIZE >> 3]; -#else - U32 hashTable[HASH_TABLESIZE]; -#endif - BYTE buffer[WORKPLACESIZE]; -} cctxi_t; - -/************************************** - * Error Management - **************************************/ -/* published entry point */ -unsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); } - -/************************************** - * Tool functions - **************************************/ -#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ -#define ZSTD_VERSION_MINOR 1 /* for new (non-breaking) interface capabilities */ -#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ -#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR * 100 * 100 + ZSTD_VERSION_MINOR * 100 + ZSTD_VERSION_RELEASE) - -/************************************************************** - * Decompression code - **************************************************************/ - -size_t ZSTDv01_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr) -{ - const BYTE *const in = (const BYTE *const)src; - BYTE headerFlags; - U32 cSize; - - if (srcSize < 3) - return ERROR(srcSize_wrong); - - headerFlags = *in; - cSize = in[2] + (in[1] << 8) + ((in[0] & 7) << 16); - - bpPtr->blockType = (blockType_t)(headerFlags >> 6); - bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0; - - if (bpPtr->blockType == bt_end) - return 0; - if (bpPtr->blockType == bt_rle) - return 1; - return cSize; -} - -static size_t ZSTD_copyUncompressedBlock(void *dst, size_t maxDstSize, const void *src, size_t srcSize) -{ - if (srcSize > maxDstSize) - return ERROR(dstSize_tooSmall); - memcpy(dst, src, srcSize); - return srcSize; -} - -static size_t ZSTD_decompressLiterals(void *ctx, - void *dst, size_t maxDstSize, - const void *src, size_t srcSize) -{ - BYTE *op = (BYTE *)dst; - BYTE *const oend = op + maxDstSize; - const BYTE *ip = (const BYTE *)src; - size_t errorCode; - size_t litSize; - - /* check : minimum 2, for litSize, +1, for content */ - if (srcSize <= 3) - return ERROR(corruption_detected); - - litSize = ip[1] + (ip[0] << 8); - litSize += ((ip[-3] >> 3) & 7) << 16; // mmmmh.... - op = oend - litSize; - - (void)ctx; - if (litSize > maxDstSize) - return ERROR(dstSize_tooSmall); - errorCode = HUF_decompress(op, litSize, ip + 2, srcSize - 2); - if (FSE_isError(errorCode)) - return ERROR(GENERIC); - return litSize; -} - -size_t ZSTDv01_decodeLiteralsBlock(void *ctx, - void *dst, size_t maxDstSize, - const BYTE **litStart, size_t *litSize, - const void *src, size_t srcSize) -{ - const BYTE *const istart = (const BYTE *const)src; - const BYTE *ip = istart; - BYTE *const ostart = (BYTE *const)dst; - BYTE *const oend = ostart + maxDstSize; - blockProperties_t litbp; - - size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp); - if (ZSTDv01_isError(litcSize)) - return litcSize; - if (litcSize > srcSize - ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - ip += ZSTD_blockHeaderSize; - - switch (litbp.blockType) - { - case bt_raw: - *litStart = ip; - ip += litcSize; - *litSize = litcSize; - break; - case bt_rle: - { - size_t rleSize = litbp.origSize; - if (rleSize > maxDstSize) - return ERROR(dstSize_tooSmall); - if (!srcSize) - return ERROR(srcSize_wrong); - memset(oend - rleSize, *ip, rleSize); - *litStart = oend - rleSize; - *litSize = rleSize; - ip++; - break; - } - case bt_compressed: - { - size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize); - if (ZSTDv01_isError(decodedLitSize)) - return decodedLitSize; - *litStart = oend - decodedLitSize; - *litSize = decodedLitSize; - ip += litcSize; - break; - } - case bt_end: - default: - return ERROR(GENERIC); - } - - return ip - istart; -} - -size_t ZSTDv01_decodeSeqHeaders(int *nbSeq, const BYTE **dumpsPtr, size_t *dumpsLengthPtr, - FSE_DTable *DTableLL, FSE_DTable *DTableML, FSE_DTable *DTableOffb, - const void *src, size_t srcSize) -{ - const BYTE *const istart = (const BYTE *const)src; - const BYTE *ip = istart; - const BYTE *const iend = istart + srcSize; - U32 LLtype, Offtype, MLtype; - U32 LLlog, Offlog, MLlog; - size_t dumpsLength; - - /* check */ - if (srcSize < 5) - return ERROR(srcSize_wrong); - - /* SeqHead */ - *nbSeq = ZSTD_readLE16(ip); - ip += 2; - LLtype = *ip >> 6; - Offtype = (*ip >> 4) & 3; - MLtype = (*ip >> 2) & 3; - if (*ip & 2) - { - dumpsLength = ip[2]; - dumpsLength += ip[1] << 8; - ip += 3; - } - else - { - dumpsLength = ip[1]; - dumpsLength += (ip[0] & 1) << 8; - ip += 2; - } - *dumpsPtr = ip; - ip += dumpsLength; - *dumpsLengthPtr = dumpsLength; - - /* check */ - if (ip > iend - 3) - return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */ - - /* sequences */ - { - S16 norm[MaxML + 1]; /* assumption : MaxML >= MaxLL and MaxOff */ - size_t headerSize; - - /* Build DTables */ - switch (LLtype) - { - case bt_rle: - LLlog = 0; - FSE_buildDTable_rle(DTableLL, *ip++); - break; - case bt_raw: - LLlog = LLbits; - FSE_buildDTable_raw(DTableLL, LLbits); - break; - default: - { - U32 max = MaxLL; - headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend - ip); - if (FSE_isError(headerSize)) - return ERROR(GENERIC); - if (LLlog > LLFSELog) - return ERROR(corruption_detected); - ip += headerSize; - FSE_buildDTable(DTableLL, norm, max, LLlog); - } - } - - switch (Offtype) - { - case bt_rle: - Offlog = 0; - if (ip > iend - 2) - return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ - FSE_buildDTable_rle(DTableOffb, *ip++); - break; - case bt_raw: - Offlog = Offbits; - FSE_buildDTable_raw(DTableOffb, Offbits); - break; - default: - { - U32 max = MaxOff; - headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend - ip); - if (FSE_isError(headerSize)) - return ERROR(GENERIC); - if (Offlog > OffFSELog) - return ERROR(corruption_detected); - ip += headerSize; - FSE_buildDTable(DTableOffb, norm, max, Offlog); - } - } - - switch (MLtype) - { - case bt_rle: - MLlog = 0; - if (ip > iend - 2) - return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */ - FSE_buildDTable_rle(DTableML, *ip++); - break; - case bt_raw: - MLlog = MLbits; - FSE_buildDTable_raw(DTableML, MLbits); - break; - default: - { - U32 max = MaxML; - headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend - ip); - if (FSE_isError(headerSize)) - return ERROR(GENERIC); - if (MLlog > MLFSELog) - return ERROR(corruption_detected); - ip += headerSize; - FSE_buildDTable(DTableML, norm, max, MLlog); - } - } - } - - return ip - istart; -} - -typedef struct -{ - size_t litLength; - size_t offset; - size_t matchLength; -} seq_t; - -typedef struct -{ - FSE_DStream_t DStream; - FSE_DState_t stateLL; - FSE_DState_t stateOffb; - FSE_DState_t stateML; - size_t prevOffset; - const BYTE *dumps; - const BYTE *dumpsEnd; -} seqState_t; - -static void ZSTD_decodeSequence(seq_t *seq, seqState_t *seqState) -{ - size_t litLength; - size_t prevOffset; - size_t offset; - size_t matchLength; - const BYTE *dumps = seqState->dumps; - const BYTE *const de = seqState->dumpsEnd; - - /* Literal length */ - litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); - prevOffset = litLength ? seq->offset : seqState->prevOffset; - seqState->prevOffset = seq->offset; - if (litLength == MaxLL) - { - U32 add = dumps < de ? *dumps++ : 0; - if (add < 255) - litLength += add; - else - { - if (dumps <= (de - 3)) - { - litLength = ZSTD_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ - dumps += 3; - } - } - } - - /* Offset */ - { - U32 offsetCode, nbBits; - offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); - if (ZSTD_32bits()) - FSE_reloadDStream(&(seqState->DStream)); - nbBits = offsetCode - 1; - if (offsetCode == 0) - nbBits = 0; /* cmove */ - offset = ((size_t)1 << (nbBits & ((sizeof(offset) * 8) - 1))) + FSE_readBits(&(seqState->DStream), nbBits); - if (ZSTD_32bits()) - FSE_reloadDStream(&(seqState->DStream)); - if (offsetCode == 0) - offset = prevOffset; - } - - /* MatchLength */ - matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream)); - if (matchLength == MaxML) - { - U32 add = dumps < de ? *dumps++ : 0; - if (add < 255) - matchLength += add; - else - { - if (dumps <= (de - 3)) - { - matchLength = ZSTD_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ - dumps += 3; - } - } - } - matchLength += MINMATCH; - - /* save result */ - seq->litLength = litLength; - seq->offset = offset; - seq->matchLength = matchLength; - seqState->dumps = dumps; -} - -static size_t ZSTD_execSequence(BYTE *op, - seq_t sequence, - const BYTE **litPtr, const BYTE *const litLimit, - BYTE *const base, BYTE *const oend) -{ - static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */ - static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* substracted */ - const BYTE *const ostart = op; - const size_t litLength = sequence.litLength; - BYTE *const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ - const BYTE *const litEnd = *litPtr + litLength; - - /* check */ - if (endMatch > oend) - return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */ - if (litEnd > litLimit) - return ERROR(corruption_detected); - if (sequence.matchLength > (size_t)(*litPtr - op)) - return ERROR(dstSize_tooSmall); /* overwrite literal segment */ - - /* copy Literals */ - if (((size_t)(*litPtr - op) < 8) || ((size_t)(oend - litEnd) < 8) || (op + litLength > oend - 8)) - memmove(op, *litPtr, litLength); /* overwrite risk */ - else - ZSTD_wildcopy(op, *litPtr, litLength); - op += litLength; - *litPtr = litEnd; /* update for next sequence */ - - /* check : last match must be at a minimum distance of 8 from end of dest buffer */ - if (oend - op < 8) - return ERROR(dstSize_tooSmall); - - /* copy Match */ - { - const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12); - const BYTE *match = op - sequence.offset; /* possible underflow at op - offset ? */ - size_t qutt = 12; - U64 saved[2]; - - /* check */ - if (match < base) - return ERROR(corruption_detected); - if (sequence.offset > (size_t)base) - return ERROR(corruption_detected); - - /* save beginning of literal sequence, in case of write overlap */ - if (overlapRisk) - { - if ((endMatch + qutt) > oend) - qutt = oend - endMatch; - memcpy(saved, endMatch, qutt); - } - - if (sequence.offset < 8) - { - const int dec64 = dec64table[sequence.offset]; - op[0] = match[0]; - op[1] = match[1]; - op[2] = match[2]; - op[3] = match[3]; - match += dec32table[sequence.offset]; - ZSTD_copy4(op + 4, match); - match -= dec64; - } - else - { - ZSTD_copy8(op, match); - } - op += 8; - match += 8; - - if (endMatch > oend - (16 - MINMATCH)) - { - if (op < oend - 8) - { - ZSTD_wildcopy(op, match, (oend - 8) - op); - match += (oend - 8) - op; - op = oend - 8; - } - while (op < endMatch) - *op++ = *match++; - } - else - ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */ - - /* restore, in case of overlap */ - if (overlapRisk) - memcpy(endMatch, saved, qutt); - } - - return endMatch - ostart; -} - -typedef struct ZSTDv01_Dctx_s -{ - U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; - U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; - U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; - void *previousDstEnd; - void *base; - size_t expected; - blockType_t bType; - U32 phase; -} dctx_t; - -static size_t ZSTD_decompressSequences( - void *ctx, - void *dst, size_t maxDstSize, - const void *seqStart, size_t seqSize, - const BYTE *litStart, size_t litSize) -{ - dctx_t *dctx = (dctx_t *)ctx; - const BYTE *ip = (const BYTE *)seqStart; - const BYTE *const iend = ip + seqSize; - BYTE *const ostart = (BYTE *const)dst; - BYTE *op = ostart; - BYTE *const oend = ostart + maxDstSize; - size_t errorCode, dumpsLength; - const BYTE *litPtr = litStart; - const BYTE *const litEnd = litStart + litSize; - int nbSeq; - const BYTE *dumps; - U32 *DTableLL = dctx->LLTable; - U32 *DTableML = dctx->MLTable; - U32 *DTableOffb = dctx->OffTable; - BYTE *const base = (BYTE *)(dctx->base); - - /* Build Decoding Tables */ - errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, - DTableLL, DTableML, DTableOffb, - ip, iend - ip); - if (ZSTDv01_isError(errorCode)) - return errorCode; - ip += errorCode; - - /* Regen sequences */ - { - seq_t sequence; - seqState_t seqState; - - memset(&sequence, 0, sizeof(sequence)); - seqState.dumps = dumps; - seqState.dumpsEnd = dumps + dumpsLength; - seqState.prevOffset = 1; - errorCode = FSE_initDStream(&(seqState.DStream), ip, iend - ip); - if (FSE_isError(errorCode)) - return ERROR(corruption_detected); - FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL); - FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb); - FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML); - - for (; (FSE_reloadDStream(&(seqState.DStream)) <= FSE_DStream_completed) && (nbSeq > 0);) - { - size_t oneSeqSize; - nbSeq--; - ZSTD_decodeSequence(&sequence, &seqState); - oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend); - if (ZSTDv01_isError(oneSeqSize)) - return oneSeqSize; - op += oneSeqSize; - } - - /* check if reached exact end */ - if (!FSE_endOfDStream(&(seqState.DStream))) - return ERROR(corruption_detected); /* requested too much : data is corrupted */ - if (nbSeq < 0) - return ERROR(corruption_detected); /* requested too many sequences : data is corrupted */ - - /* last literal segment */ - { - size_t lastLLSize = litEnd - litPtr; - if (op + lastLLSize > oend) - return ERROR(dstSize_tooSmall); - if (op != litPtr) - memmove(op, litPtr, lastLLSize); - op += lastLLSize; - } - } - - return op - ostart; -} - -static size_t ZSTD_decompressBlock( - void *ctx, - void *dst, size_t maxDstSize, - const void *src, size_t srcSize) -{ - /* blockType == blockCompressed, srcSize is trusted */ - const BYTE *ip = (const BYTE *)src; - const BYTE *litPtr = NULL; - size_t litSize = 0; - size_t errorCode; - - /* Decode literals sub-block */ - errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize); - if (ZSTDv01_isError(errorCode)) - return errorCode; - ip += errorCode; - srcSize -= errorCode; - - return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize, litPtr, litSize); -} - -size_t ZSTDv01_decompressDCtx(void *ctx, void *dst, size_t maxDstSize, const void *src, size_t srcSize) -{ - const BYTE *ip = (const BYTE *)src; - const BYTE *iend = ip + srcSize; - BYTE *const ostart = (BYTE *const)dst; - BYTE *op = ostart; - BYTE *const oend = ostart + maxDstSize; - size_t remainingSize = srcSize; - U32 magicNumber; - size_t errorCode = 0; - blockProperties_t blockProperties; - - /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize + ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - magicNumber = ZSTD_readBE32(src); - if (magicNumber != ZSTD_magicNumber) - return ERROR(prefix_unknown); - ip += ZSTD_frameHeaderSize; - remainingSize -= ZSTD_frameHeaderSize; - - /* Loop on each block */ - while (1) - { - size_t blockSize = ZSTDv01_getcBlockSize(ip, iend - ip, &blockProperties); - if (ZSTDv01_isError(blockSize)) - return blockSize; - - ip += ZSTD_blockHeaderSize; - remainingSize -= ZSTD_blockHeaderSize; - if (blockSize > remainingSize) - return ERROR(srcSize_wrong); - - switch (blockProperties.blockType) - { - case bt_compressed: - errorCode = ZSTD_decompressBlock(ctx, op, oend - op, ip, blockSize); - break; - case bt_raw: - errorCode = ZSTD_copyUncompressedBlock(op, oend - op, ip, blockSize); - break; - case bt_rle: - return ERROR(GENERIC); /* not yet supported */ - break; - case bt_end: - /* end of frame */ - if (remainingSize) - return ERROR(srcSize_wrong); - break; - default: - return ERROR(GENERIC); - } - if (blockSize == 0) - break; /* bt_end */ - - if (ZSTDv01_isError(errorCode)) - return errorCode; - op += errorCode; - ip += blockSize; - remainingSize -= blockSize; - } - - return op - ostart; -} - -size_t ZSTDv01_decompress(void *dst, size_t maxDstSize, const void *src, size_t srcSize) -{ - dctx_t ctx; - ctx.base = dst; - return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); -} - -size_t ZSTDv01_findFrameCompressedSize(const void *src, size_t srcSize) -{ - const BYTE *ip = (const BYTE *)src; - size_t remainingSize = srcSize; - U32 magicNumber; - blockProperties_t blockProperties; - - /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize + ZSTD_blockHeaderSize) - return ERROR(srcSize_wrong); - magicNumber = ZSTD_readBE32(src); - if (magicNumber != ZSTD_magicNumber) - return ERROR(prefix_unknown); - ip += ZSTD_frameHeaderSize; - remainingSize -= ZSTD_frameHeaderSize; - - /* Loop on each block */ - while (1) - { - size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTDv01_isError(blockSize)) - return blockSize; - - ip += ZSTD_blockHeaderSize; - remainingSize -= ZSTD_blockHeaderSize; - if (blockSize > remainingSize) - return ERROR(srcSize_wrong); - - if (blockSize == 0) - break; /* bt_end */ - - ip += blockSize; - remainingSize -= blockSize; - } - - return ip - (const BYTE *)src; -} - -/******************************* - * Streaming Decompression API - *******************************/ - -size_t ZSTDv01_resetDCtx(ZSTDv01_Dctx *dctx) -{ - dctx->expected = ZSTD_frameHeaderSize; - dctx->phase = 0; - dctx->previousDstEnd = NULL; - dctx->base = NULL; - return 0; -} - -ZSTDv01_Dctx *ZSTDv01_createDCtx(void) -{ - ZSTDv01_Dctx *dctx = (ZSTDv01_Dctx *)malloc(sizeof(ZSTDv01_Dctx)); - if (dctx == NULL) - return NULL; - ZSTDv01_resetDCtx(dctx); - return dctx; -} - -size_t ZSTDv01_freeDCtx(ZSTDv01_Dctx *dctx) -{ - free(dctx); - return 0; -} - -size_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx *dctx) -{ - return ((dctx_t *)dctx)->expected; -} - -size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx *dctx, void *dst, size_t maxDstSize, const void *src, size_t srcSize) -{ - dctx_t *ctx = (dctx_t *)dctx; - - /* Sanity check */ - if (srcSize != ctx->expected) - return ERROR(srcSize_wrong); - if (dst != ctx->previousDstEnd) /* not contiguous */ - ctx->base = dst; - - /* Decompress : frame header */ - if (ctx->phase == 0) - { - /* Check frame magic header */ - U32 magicNumber = ZSTD_readBE32(src); - if (magicNumber != ZSTD_magicNumber) - return ERROR(prefix_unknown); - ctx->phase = 1; - ctx->expected = ZSTD_blockHeaderSize; - return 0; - } - - /* Decompress : block header */ - if (ctx->phase == 1) - { - blockProperties_t bp; - size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp); - if (ZSTDv01_isError(blockSize)) - return blockSize; - if (bp.blockType == bt_end) - { - ctx->expected = 0; - ctx->phase = 0; - } - else - { - ctx->expected = blockSize; - ctx->bType = bp.blockType; - ctx->phase = 2; - } - - return 0; - } - - /* Decompress : block content */ - { - size_t rSize; - switch (ctx->bType) - { - case bt_compressed: - rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize); - break; - case bt_raw: - rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize); - break; - case bt_rle: - return ERROR(GENERIC); /* not yet handled */ - break; - case bt_end: /* should never happen (filtered at phase 1) */ - rSize = 0; - break; - default: - return ERROR(GENERIC); - } - ctx->phase = 1; - ctx->expected = ZSTD_blockHeaderSize; - ctx->previousDstEnd = (void *)(((char *)dst) + rSize); - return rSize; - } -} diff --git a/extra/zstd/zstd_v01.h b/extra/zstd/zstd_v01.h deleted file mode 100644 index 1f88edb9..00000000 --- a/extra/zstd/zstd_v01.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#ifndef ZSTD_V01_H_28739879432 -#define ZSTD_V01_H_28739879432 - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* ************************************* - * Includes - ***************************************/ -#include /* size_t */ - - /* ************************************* - * Simple one-step function - ***************************************/ - /** - ZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format - compressedSize : is the exact source size - maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated. - It must be equal or larger than originalSize, otherwise decompression will fail. - return : the number of bytes decompressed into destination buffer (originalSize) - or an errorCode if it fails (which can be tested using ZSTDv01_isError()) - */ - size_t ZSTDv01_decompress(void *dst, size_t maxOriginalSize, - const void *src, size_t compressedSize); - - /** - ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv01_isError()) - */ - size_t ZSTDv01_findFrameCompressedSize(const void *src, size_t compressedSize); - - /** - ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error - */ - unsigned ZSTDv01_isError(size_t code); - - /* ************************************* - * Advanced functions - ***************************************/ - typedef struct ZSTDv01_Dctx_s ZSTDv01_Dctx; - ZSTDv01_Dctx *ZSTDv01_createDCtx(void); - size_t ZSTDv01_freeDCtx(ZSTDv01_Dctx *dctx); - - size_t ZSTDv01_decompressDCtx(void *ctx, - void *dst, size_t maxOriginalSize, - const void *src, size_t compressedSize); - - /* ************************************* - * Streaming functions - ***************************************/ - size_t ZSTDv01_resetDCtx(ZSTDv01_Dctx *dctx); - - size_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx *dctx); - size_t ZSTDv01_decompressContinue(ZSTDv01_Dctx *dctx, void *dst, size_t maxDstSize, const void *src, size_t srcSize); -/** - Use above functions alternatively. - ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. - Result is the number of bytes regenerated within 'dst'. - It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. -*/ - -/* ************************************* - * Prefix - version detection - ***************************************/ -#define ZSTDv01_magicNumber 0xFD2FB51E /* Big Endian version */ -#define ZSTDv01_magicNumberLE 0x1EB52FFD /* Little Endian version */ - -#if defined(__cplusplus) -} -#endif - -#endif /* ZSTD_V01_H_28739879432 */ diff --git a/extra/zstd/zstd_v02.c b/extra/zstd/zstd_v02.c deleted file mode 100644 index b5dcdb55..00000000 --- a/extra/zstd/zstd_v02.c +++ /dev/null @@ -1,3740 +0,0 @@ -/** - * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#include /* size_t, ptrdiff_t */ -#include "zstd_v02.h" -#include "error_private.h" - -/****************************************** - * Compiler-specific - ******************************************/ -#if defined(_MSC_VER) /* Visual Studio */ -#include /* _byteswap_ulong */ -#include /* _byteswap_* */ -#endif - -/* ****************************************************************** - mem.h - low-level memory access routines - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ -#ifndef MEM_H_MODULE -#define MEM_H_MODULE - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/****************************************** - * Includes - ******************************************/ -#include /* size_t, ptrdiff_t */ -#include /* memcpy */ - -/****************************************** - * Compiler-specific - ******************************************/ -#if defined(__GNUC__) -#define MEM_STATIC static __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(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -#include - 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 -typedef unsigned char BYTE; -typedef unsigned short U16; -typedef signed short S16; -typedef unsigned int U32; -typedef signed int S32; -typedef unsigned long long U64; -typedef signed long long S64; -#endif - -/**************************************************************** - * Memory I/O - *****************************************************************/ -/* 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 (ie, 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 generating assembly depending on alignment. - * But in some circumstances, it's the only known way to get the most performance (ie 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(WIN32)) || \ - (defined(__GNUC__) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__))) -#define MEM_FORCE_MEMORY_ACCESS 1 -#endif -#endif - - MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void *) == 4; } - MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void *) == 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 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 void MEM_write16(void *memPtr, U16 value) { *(U16 *)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 */ -typedef union -{ - U16 u16; - U32 u32; - U64 u64; -} __attribute__((packed)) unalign; - -MEM_STATIC U16 MEM_read16(const void *ptr) { return ((const unalign *)ptr)->u16; } -MEM_STATIC U32 MEM_read32(const void *ptr) { return ((const unalign *)ptr)->u32; } -MEM_STATIC U64 MEM_read64(const void *ptr) { return ((const unalign *)ptr)->u64; } - -MEM_STATIC void MEM_write16(void *memPtr, U16 value) { ((unalign *)memPtr)->u16 = value; } - -#else - -/* default method, safe and standard. - can sometimes prove slower */ - -MEM_STATIC U16 MEM_read16(const void *memPtr) -{ - U16 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC U32 MEM_read32(const void *memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC U64 MEM_read64(const void *memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -MEM_STATIC void MEM_write16(void *memPtr, U16 value) -{ - memcpy(memPtr, &value, sizeof(value)); -} - -#endif // MEM_FORCE_MEMORY_ACCESS - - 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_readLE32(const void *memPtr) - { - if (MEM_isLittleEndian()) - return MEM_read32(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U32)((U32)p[0] + ((U32)p[1] << 8) + ((U32)p[2] << 16) + ((U32)p[3] << 24)); - } - } - - MEM_STATIC U64 MEM_readLE64(const void *memPtr) - { - if (MEM_isLittleEndian()) - return MEM_read64(memPtr); - else - { - const BYTE *p = (const BYTE *)memPtr; - return (U64)((U64)p[0] + ((U64)p[1] << 8) + ((U64)p[2] << 16) + ((U64)p[3] << 24) + ((U64)p[4] << 32) + ((U64)p[5] << 40) + ((U64)p[6] << 48) + ((U64)p[7] << 56)); - } - } - - 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); - } - -#if defined(__cplusplus) -} -#endif - -#endif /* MEM_H_MODULE */ - -/* ****************************************************************** - bitstream - Part of NewGen Entropy library - header file (to include) - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ -#ifndef BITSTREAM_H_MODULE -#define BITSTREAM_H_MODULE - -#if defined(__cplusplus) -extern "C" -{ -#endif - - /* - * This API consists of small unitary functions, which highly benefit from being inlined. - * Since link-time-optimization is not available for all compilers, - * these functions are defined into a .h to be included. - */ - - /********************************************** - * bitStream decompression API (read backward) - **********************************************/ - typedef struct - { - size_t bitContainer; - unsigned bitsConsumed; - const char *ptr; - const char *start; - } 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 manually filled from memory by the BIT_reloadDStream() method. - * A reload guarantee a minimum of ((8*sizeof(size_t))-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 size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits); - /* faster, but works only if nbBits >= 1 */ - - /**************************************************************** - * Helper functions - ****************************************************************/ - MEM_STATIC unsigned BIT_highbit32(register U32 val) - { -#if defined(_MSC_VER) /* Visual */ - unsigned long r = 0; - _BitScanReverse(&r, val); - return (unsigned)r; -#elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ - return 31 - __builtin_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; - unsigned r; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27]; - return r; -#endif - } - - /********************************************************** - * bitStream decoding - **********************************************************/ - - /*!BIT_initDStream - * Initialize a BIT_DStream_t. - * @bitD : a pointer to an already allocated BIT_DStream_t structure - * @srcBuffer must point at the beginning of a bitStream - * @srcSize must be the exact size of the bitStream - * @result : 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) - { - memset(bitD, 0, sizeof(*bitD)); - return ERROR(srcSize_wrong); - } - - if (srcSize >= sizeof(size_t)) /* normal case */ - { - U32 contain32; - bitD->start = (const char *)srcBuffer; - bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(size_t); - bitD->bitContainer = MEM_readLEST(bitD->ptr); - contain32 = ((const BYTE *)srcBuffer)[srcSize - 1]; - if (contain32 == 0) - return ERROR(GENERIC); /* endMark not present */ - bitD->bitsConsumed = 8 - BIT_highbit32(contain32); - } - else - { - U32 contain32; - bitD->start = (const char *)srcBuffer; - bitD->ptr = bitD->start; - bitD->bitContainer = *(const BYTE *)(bitD->start); - - switch (srcSize) - { - case 7: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[6]) << (sizeof(size_t) * 8 - 16); /* fall through */ - case 6: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[5]) << (sizeof(size_t) * 8 - 24); /* fall through */ - case 5: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[4]) << (sizeof(size_t) * 8 - 32); /* fall through */ - case 4: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[3]) << 24; /* fall through */ - case 3: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[2]) << 16; /* fall through */ - case 2: - bitD->bitContainer += (size_t)(((const BYTE *)(bitD->start))[1]) << 8; /* fall through */ - default:; - } - contain32 = ((const BYTE *)srcBuffer)[srcSize - 1]; - if (contain32 == 0) - return ERROR(GENERIC); /* endMark not present */ - bitD->bitsConsumed = 8 - BIT_highbit32(contain32); - bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize) * 8; - } - - return srcSize; - } - - /*!BIT_lookBits - * Provides next n bits from local register - * local register is not modified (bits are still present for next read/look) - * On 32-bits, maxNbBits==25 - * On 64-bits, maxNbBits==57 - * @return : value extracted - */ - MEM_STATIC size_t BIT_lookBits(BIT_DStream_t *bitD, U32 nbBits) - { - const U32 bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask); - } - - /*! BIT_lookBitsFast : - * unsafe version; only works only if nbBits >= 1 */ - MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t *bitD, U32 nbBits) - { - const U32 bitMask = sizeof(bitD->bitContainer) * 8 - 1; - return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask); - } - - MEM_STATIC void BIT_skipBits(BIT_DStream_t *bitD, U32 nbBits) - { - bitD->bitsConsumed += nbBits; - } - - /*!BIT_readBits - * Read next n bits from local register. - * pay attention to not read more than nbBits contained into local register. - * @return : extracted value. - */ - MEM_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, U32 nbBits) - { - size_t 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, U32 nbBits) - { - size_t value = BIT_lookBitsFast(bitD, nbBits); - BIT_skipBits(bitD, nbBits); - return value; - } - - MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD) - { - if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should never happen */ - return BIT_DStream_overflow; - - if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) - { - bitD->ptr -= bitD->bitsConsumed >> 3; - bitD->bitsConsumed &= 7; - bitD->bitContainer = MEM_readLEST(bitD->ptr); - return BIT_DStream_unfinished; - } - if (bitD->ptr == bitD->start) - { - if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8) - return BIT_DStream_endOfBuffer; - return BIT_DStream_completed; - } - { - 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) */ - return result; - } - } - - /*! BIT_endOfDStream - * @return Tells if DStream has reached its exact end - */ - 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 */ -/* ****************************************************************** - Error codes and messages - Copyright (C) 2013-2015, Yann Collet - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ -#ifndef ERROR_H_MODULE -#define ERROR_H_MODULE - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/****************************************** - * Compiler-specific - ******************************************/ -#if defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -#define ERR_STATIC static inline -#elif defined(_MSC_VER) -#define ERR_STATIC static __inline -#elif defined(__GNUC__) -#define ERR_STATIC static __attribute__((unused)) -#else -#define ERR_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ -#endif - -/****************************************** - * Error Management - ******************************************/ -#define PREFIX(name) ZSTD_error_##name - -#define ERROR(name) (size_t) - PREFIX(name) - -#define ERROR_LIST(ITEM) \ - ITEM(PREFIX(No_Error)) \ - ITEM(PREFIX(GENERIC)) \ - ITEM(PREFIX(dstSize_tooSmall)) \ - ITEM(PREFIX(srcSize_wrong)) \ - ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \ - ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \ - ITEM(PREFIX(maxCode)) - -#define ERROR_GENERATE_ENUM(ENUM) ENUM, - typedef enum - { - ERROR_LIST(ERROR_GENERATE_ENUM) - } ERR_codes; /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */ - -#define ERROR_CONVERTTOSTRING(STRING) #STRING, -#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR) - static const char *ERR_strings[] = {ERROR_LIST(ERROR_GENERATE_STRING)}; - - ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } - - ERR_STATIC const char *ERR_getErrorName(size_t code) - { - static const char *codeError = "Unspecified error code"; - if (ERR_isError(code)) - return ERR_strings[-(int)(code)]; - return codeError; - } - -#if defined(__cplusplus) -} -#endif - -#endif /* ERROR_H_MODULE */ -/* -Constructor and Destructor of type FSE_CTable - Note that its size depends on 'tableLog' and 'maxSymbolValue' */ -typedef unsigned FSE_CTable; /* don't allocate that. It's just a way to be more restrictive than void* */ -typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ - -/* ****************************************************************** - FSE : Finite State Entropy coder - header file for static linking (only) - Copyright (C) 2013-2015, Yann Collet - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ -#if defined(__cplusplus) -extern "C" -{ -#endif - -/****************************************** - * Static allocation - ******************************************/ -/* FSE buffer bounds */ -#define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size >> 7)) -#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ - -/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */ -#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1 << (maxTableLog - 1)) + ((maxSymbolValue + 1) * 2)) -#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog)) - - /****************************************** - * FSE advanced API - ******************************************/ - static size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits); - /* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */ - - static size_t FSE_buildDTable_rle(FSE_DTable *dt, unsigned char symbolValue); - /* build a fake FSE_DTable, designed to always generate the same symbolValue */ - - /****************************************** - * 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 inline functions - ******************************************/ - - /* 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) - { - FSE_DTableHeader DTableH; - memcpy(&DTableH, dt, sizeof(DTableH)); - DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog); - BIT_reloadDStream(bitD); - DStatePtr->table = dt + 1; - } - - MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD) - { - const FSE_decode_t DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state]; - const U32 nbBits = DInfo.nbBits; - BYTE symbol = DInfo.symbol; - size_t lowBits = BIT_readBits(bitD, nbBits); - - DStatePtr->state = DInfo.newState + lowBits; - return symbol; - } - - MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD) - { - const FSE_decode_t DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state]; - const U32 nbBits = DInfo.nbBits; - BYTE symbol = DInfo.symbol; - size_t 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; - } - -#if defined(__cplusplus) -} -#endif -/* ****************************************************************** - Huff0 : Huffman coder, part of New Generation Entropy library - header file for static linking (only) - Copyright (C) 2013-2015, Yann Collet - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - Source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/****************************************** - * Static allocation macros - ******************************************/ -/* Huff0 buffer bounds */ -#define HUF_CTABLEBOUND 129 -#define HUF_BLOCKBOUND(size) (size + (size >> 8) + 8) /* only true if incompressible pre-filtered with fast heuristic */ -#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ - -/* static allocation of Huff0's DTable */ -#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << maxTableLog)) /* nb Cells; use unsigned short for X2, unsigned int for X4 */ -#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ - unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = {maxTableLog} -#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \ - unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = {maxTableLog} -#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \ - unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = {maxTableLog} - - /****************************************** - * Advanced functions - ******************************************/ - static size_t HUF_decompress4X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /* single-symbol decoder */ - static size_t HUF_decompress4X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /* double-symbols decoder */ - static size_t HUF_decompress4X6(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /* quad-symbols decoder */ - -#if defined(__cplusplus) -} -#endif - -/* - zstd - standard compression library - Header File - Copyright (C) 2014-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - zstd source repository : https://github.com/Cyan4973/zstd - - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/* ************************************* - * Includes - ***************************************/ -#include /* size_t */ - -/* ************************************* - * Version - ***************************************/ -#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ -#define ZSTD_VERSION_MINOR 2 /* for new (non-breaking) interface capabilities */ -#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ -#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR * 100 * 100 + ZSTD_VERSION_MINOR * 100 + ZSTD_VERSION_RELEASE) - - /* ************************************* - * Advanced functions - ***************************************/ - typedef struct ZSTD_CCtx_s ZSTD_CCtx; /* incomplete type */ - -#if defined(__cplusplus) -} -#endif -/* - zstd - standard compression library - Header File for static linking only - Copyright (C) 2014-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - zstd source repository : https://github.com/Cyan4973/zstd - - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c -*/ - -/* The objects defined into this file should be considered experimental. - * They are not labelled stable, as their prototype may change in the future. - * You can use them for tests, provide feedback, or if you can endure risk of future changes. - */ - -#if defined(__cplusplus) -extern "C" -{ -#endif - - /* ************************************* - * Streaming functions - ***************************************/ - - typedef struct ZSTD_DCtx_s ZSTD_DCtx; - -/* - Use above functions alternatively. - ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block. - Result is the number of bytes regenerated within 'dst'. - It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. -*/ - -/* ************************************* - * Prefix - version detection - ***************************************/ -#define ZSTD_magicNumber 0xFD2FB522 /* v0.2 (current)*/ - -#if defined(__cplusplus) -} -#endif -/* ****************************************************************** - FSE : Finite State Entropy coder - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -#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 */ -#define FSE_MAX_MEMORY_USAGE 14 -#define FSE_DEFAULT_MEMORY_USAGE 13 - -/* FSE_MAX_SYMBOL_VALUE : - * Maximum symbol value authorized. - * Required for proper stack allocation */ -#define FSE_MAX_SYMBOL_VALUE 255 - -/**************************************************************** - * template functions type & suffix - ****************************************************************/ -#define FSE_FUNCTION_TYPE BYTE -#define FSE_FUNCTION_EXTENSION - -/**************************************************************** - * Byte symbol type - ****************************************************************/ -#endif /* !FSE_COMMONDEFS_ONLY */ - -/**************************************************************** - * Compiler specifics - ****************************************************************/ -#ifdef _MSC_VER /* Visual Studio */ -#define FORCE_INLINE static __forceinline -#include /* For Visual 2005 */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ -#else -#if defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -#ifdef __GNUC__ -#define FORCE_INLINE static inline __attribute__((always_inline)) -#else -#define FORCE_INLINE static inline -#endif -#else -#define FORCE_INLINE static -#endif /* __STDC_VERSION__ */ -#endif - -/**************************************************************** - * Includes - ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include /* printf (debug) */ - -/**************************************************************** - * 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 - -/**************************************************************** - * Error Management - ****************************************************************/ -#define FSE_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - FSE_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/**************************************************************** - * Complex types - ****************************************************************/ -typedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; - -/**************************************************************** - * Templates - ****************************************************************/ -/* - designed to be included - for type-specific functions (template emulation in C) - Objective is to write these functions only once, for improved maintenance -*/ - -/* safety checks */ -#ifndef FSE_FUNCTION_EXTENSION -#error "FSE_FUNCTION_EXTENSION must be defined" -#endif -#ifndef FSE_FUNCTION_TYPE -#error "FSE_FUNCTION_TYPE must be defined" -#endif - -/* Function names */ -#define FSE_CAT(X, Y) X##Y -#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y) -#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y) - -/* Function templates */ - -#define FSE_DECODE_TYPE FSE_decode_t - -static U32 FSE_tableStep(U32 tableSize) { return (tableSize >> 1) + (tableSize >> 3) + 3; } - -static size_t FSE_buildDTable(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) -{ - void *ptr = dt + 1; - FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)ptr; - FSE_DTableHeader DTableH; - const U32 tableSize = 1 << tableLog; - const U32 tableMask = tableSize - 1; - const U32 step = FSE_tableStep(tableSize); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE + 1]; - U32 position = 0; - U32 highThreshold = tableSize - 1; - const S16 largeLimit = (S16)(1 << (tableLog - 1)); - U32 noLarge = 1; - U32 s; - - /* Sanity Checks */ - if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) - return ERROR(maxSymbolValue_tooLarge); - if (tableLog > FSE_MAX_TABLELOG) - return ERROR(tableLog_tooLarge); - - /* Init, lay down lowprob symbols */ - DTableH.tableLog = (U16)tableLog; - for (s = 0; s <= maxSymbolValue; s++) - { - if (normalizedCounter[s] == -1) - { - tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; - symbolNext[s] = 1; - } - else - { - if (normalizedCounter[s] >= largeLimit) - noLarge = 0; - symbolNext[s] = normalizedCounter[s]; - } - } - - /* Spread symbols */ - for (s = 0; s <= maxSymbolValue; s++) - { - int i; - for (i = 0; i < normalizedCounter[s]; i++) - { - tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; - position = (position + step) & tableMask; - while (position > highThreshold) - position = (position + step) & tableMask; /* lowprob area */ - } - } - - if (position != 0) - return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */ - - /* Build Decoding table */ - { - U32 i; - for (i = 0; i < tableSize; i++) - { - FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol); - U16 nextState = symbolNext[symbol]++; - tableDecode[i].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState)); - tableDecode[i].newState = (U16)((nextState << tableDecode[i].nbBits) - tableSize); - } - } - - DTableH.fastMode = (U16)noLarge; - memcpy(dt, &DTableH, sizeof(DTableH)); /* memcpy(), to avoid strict aliasing warnings */ - return 0; -} - -#ifndef FSE_COMMONDEFS_ONLY -/****************************************** - * FSE helper functions - ******************************************/ -static unsigned FSE_isError(size_t code) { return ERR_isError(code); } - -/**************************************************************** - * FSE NCount encoding-decoding - ****************************************************************/ -static short FSE_abs(short a) -{ - return (short)(a < 0 ? -a : a); -} - -static size_t FSE_readNCount(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; - int previous0 = 0; - - if (hbSize < 4) - return ERROR(srcSize_wrong); - 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++; - - while ((remaining > 1) && (charnum <= *maxSVPtr)) - { - if (previous0) - { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) - { - n0 += 24; - if (ip < iend - 5) - { - ip += 2; - bitStream = MEM_readLE32(ip) >> bitCount; - } - else - { - bitStream >>= 16; - bitCount += 16; - } - } - while ((bitStream & 3) == 3) - { - n0 += 3; - bitStream >>= 2; - bitCount += 2; - } - n0 += bitStream & 3; - bitCount += 2; - if (n0 > *maxSVPtr) - return ERROR(maxSymbolValue_tooSmall); - while (charnum < n0) - normalizedCounter[charnum++] = 0; - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - bitStream = MEM_readLE32(ip) >> bitCount; - } - else - bitStream >>= 2; - } - { - const short max = (short)((2 * threshold - 1) - remaining); - short count; - - if ((bitStream & (threshold - 1)) < (U32)max) - { - count = (short)(bitStream & (threshold - 1)); - bitCount += nbBits - 1; - } - else - { - count = (short)(bitStream & (2 * threshold - 1)); - if (count >= threshold) - count -= max; - bitCount += nbBits; - } - - count--; /* extra accuracy */ - remaining -= FSE_abs(count); - normalizedCounter[charnum++] = count; - previous0 = !count; - while (remaining < threshold) - { - nbBits--; - threshold >>= 1; - } - - { - if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) - { - ip += bitCount >> 3; - bitCount &= 7; - } - else - { - bitCount -= (int)(8 * (iend - 4 - ip)); - ip = iend - 4; - } - bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } - } - } - if (remaining != 1) - return ERROR(GENERIC); - *maxSVPtr = charnum - 1; - - ip += (bitCount + 7) >> 3; - if ((size_t)(ip - istart) > hbSize) - return ERROR(srcSize_wrong); - return ip - istart; -} - -/********************************************************* - * Decompression (Byte symbols) - *********************************************************/ -static size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - FSE_decode_t *const cell = (FSE_decode_t *)(ptr) + 1; /* because dt is unsigned */ - - DTableH->tableLog = 0; - DTableH->fastMode = 0; - - cell->newState = 0; - cell->symbol = symbolValue; - cell->nbBits = 0; - - return 0; -} - -static size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits) -{ - void *ptr = dt; - FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr; - FSE_decode_t *const dinfo = (FSE_decode_t *)(ptr) + 1; /* because dt is unsigned */ - const unsigned tableSize = 1 << nbBits; - const unsigned tableMask = tableSize - 1; - const unsigned maxSymbolValue = tableMask; - unsigned s; - - /* Sanity checks */ - if (nbBits < 1) - return ERROR(GENERIC); /* min size */ - - /* Build Decoding Table */ - DTableH->tableLog = (U16)nbBits; - DTableH->fastMode = 1; - for (s = 0; s <= maxSymbolValue; s++) - { - dinfo[s].newState = 0; - dinfo[s].symbol = (BYTE)s; - dinfo[s].nbBits = (BYTE)nbBits; - } - - return 0; -} - -FORCE_INLINE size_t FSE_decompress_usingDTable_generic( - void *dst, size_t maxDstSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt, const unsigned fast) -{ - BYTE *const ostart = (BYTE *)dst; - BYTE *op = ostart; - BYTE *const omax = op + maxDstSize; - BYTE *const olimit = omax - 3; - - BIT_DStream_t bitD; - FSE_DState_t state1; - FSE_DState_t state2; - size_t errorCode; - - /* Init */ - errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize); /* replaced last arg by maxCompressed Size */ - if (FSE_isError(errorCode)) - return errorCode; - - FSE_initDState(&state1, &bitD, dt); - FSE_initDState(&state2, &bitD, dt); - -#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) - - /* 4 symbols per loop */ - for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) && (op < olimit); op += 4) - { - op[0] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[1] = FSE_GETSYMBOL(&state2); - - if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - { - if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) - { - op += 2; - break; - } - } - - op[2] = FSE_GETSYMBOL(&state1); - - if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */ - BIT_reloadDStream(&bitD); - - op[3] = FSE_GETSYMBOL(&state2); - } - - /* tail */ - /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ - while (1) - { - if ((BIT_reloadDStream(&bitD) > BIT_DStream_completed) || (op == omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1)))) - break; - - *op++ = FSE_GETSYMBOL(&state1); - - if ((BIT_reloadDStream(&bitD) > BIT_DStream_completed) || (op == omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2)))) - break; - - *op++ = FSE_GETSYMBOL(&state2); - } - - /* end ? */ - if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2)) - return op - ostart; - - if (op == omax) - return ERROR(dstSize_tooSmall); /* dst buffer is full, but cSrc unfinished */ - - return ERROR(corruption_detected); -} - -static size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, - const void *cSrc, size_t cSrcSize, - const FSE_DTable *dt) -{ - FSE_DTableHeader DTableH; - memcpy(&DTableH, dt, sizeof(DTableH)); - - /* select fast mode (static) */ - if (DTableH.fastMode) - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); - return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); -} - -static size_t FSE_decompress(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize) -{ - const BYTE *const istart = (const BYTE *)cSrc; - const BYTE *ip = istart; - short counting[FSE_MAX_SYMBOL_VALUE + 1]; - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - unsigned tableLog; - unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; - size_t errorCode; - - if (cSrcSize < 2) - return ERROR(srcSize_wrong); /* too small input size */ - - /* normal FSE decoding mode */ - errorCode = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize); - if (FSE_isError(errorCode)) - return errorCode; - if (errorCode >= cSrcSize) - return ERROR(srcSize_wrong); /* too small input size */ - ip += errorCode; - cSrcSize -= errorCode; - - errorCode = FSE_buildDTable(dt, counting, maxSymbolValue, tableLog); - if (FSE_isError(errorCode)) - return errorCode; - - /* always return, even if it is an error code */ - return FSE_decompress_usingDTable(dst, maxDstSize, ip, cSrcSize, dt); -} - -#endif /* FSE_COMMONDEFS_ONLY */ -/* ****************************************************************** - Huff0 : Huffman coder, part of New Generation Entropy library - Copyright (C) 2013-2015, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy - - Public forum : https://groups.google.com/forum/#!forum/lz4c -****************************************************************** */ - -/**************************************************************** - * Compiler specifics - ****************************************************************/ -#if defined(__cplusplus) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -/* inline is defined */ -#elif defined(_MSC_VER) -#define inline __inline -#else -#define inline /* disable inline */ -#endif - -#ifdef _MSC_VER /* Visual Studio */ -#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif - -/**************************************************************** - * Includes - ****************************************************************/ -#include /* malloc, free, qsort */ -#include /* memcpy, memset */ -#include /* printf (debug) */ - -/**************************************************************** - * Error Management - ****************************************************************/ -#define HUF_STATIC_ASSERT(c) \ - { \ - enum \ - { \ - HUF_static_assert = 1 / (int)(!!(c)) \ - }; \ - } /* use only *after* variable declarations */ - -/****************************************** - * Helper functions - ******************************************/ -static unsigned HUF_isError(size_t code) { return ERR_isError(code); } - -#define HUF_ABSOLUTEMAX_TABLELOG 16 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ -#define HUF_MAX_TABLELOG 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ -#define HUF_DEFAULT_TABLELOG HUF_MAX_TABLELOG /* tableLog by default, when not specified */ -#define HUF_MAX_SYMBOL_VALUE 255 -#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG) -#error "HUF_MAX_TABLELOG is too large !" -#endif - -/********************************************************* - * Huff0 : Huffman block decompression - *********************************************************/ -typedef struct -{ - BYTE byte; - BYTE nbBits; -} HUF_DEltX2; /* single-symbol decoding */ - -typedef struct -{ - U16 sequence; - BYTE nbBits; - BYTE length; -} HUF_DEltX4; /* double-symbols decoding */ - -typedef struct -{ - BYTE symbol; - BYTE weight; -} sortedSymbol_t; - -/*! HUF_readStats - Read compact Huffman tree, saved by HUF_writeCTable - @huffWeight : destination buffer - @return : size read from `src` -*/ -static size_t HUF_readStats(BYTE *huffWeight, size_t hwSize, U32 *rankStats, - U32 *nbSymbolsPtr, U32 *tableLogPtr, - const void *src, size_t srcSize) -{ - U32 weightTotal; - U32 tableLog; - const BYTE *ip = (const BYTE *)src; - size_t iSize; - size_t oSize; - U32 n; - - if (!srcSize) - return ERROR(srcSize_wrong); - iSize = ip[0]; - // memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */ - - if (iSize >= 128) /* special header */ - { - if (iSize >= (242)) /* RLE */ - { - static int l[14] = {1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128}; - oSize = l[iSize - 242]; - memset(huffWeight, 1, hwSize); - iSize = 0; - } - else /* Incompressible */ - { - oSize = iSize - 127; - iSize = ((oSize + 1) / 2); - if (iSize + 1 > srcSize) - return ERROR(srcSize_wrong); - if (oSize >= hwSize) - return ERROR(corruption_detected); - ip += 1; - 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); - oSize = FSE_decompress(huffWeight, hwSize - 1, ip + 1, iSize); /* max (hwSize-1) values decoded, as last one is implied */ - if (FSE_isError(oSize)) - return oSize; - } - - /* collect weight stats */ - memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32)); - weightTotal = 0; - for (n = 0; n < oSize; n++) - { - if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) - 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) */ - tableLog = BIT_highbit32(weightTotal) + 1; - if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) - return ERROR(corruption_detected); - { - U32 total = 1 << tableLog; - U32 rest = total - weightTotal; - U32 verif = 1 << BIT_highbit32(rest); - U32 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); - *tableLogPtr = tableLog; - return iSize + 1; -} - -/**************************/ -/* single-symbol decoding */ -/**************************/ - -static size_t HUF_readDTableX2(U16 *DTable, const void *src, size_t srcSize) -{ - BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1]; - U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */ - U32 tableLog = 0; - const BYTE *ip = (const BYTE *)src; - size_t iSize = ip[0]; - U32 nbSymbols = 0; - U32 n; - U32 nextRankStart; - void *ptr = DTable + 1; - HUF_DEltX2 *const dt = (HUF_DEltX2 *)ptr; - - HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16)); /* if compilation fails here, assertion is false */ - // memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) - return iSize; - - /* check result */ - if (tableLog > DTable[0]) - return ERROR(tableLog_tooLarge); /* DTable is too small */ - DTable[0] = (U16)tableLog; /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */ - - /* Prepare ranks */ - nextRankStart = 0; - for (n = 1; n <= tableLog; n++) - { - U32 current = nextRankStart; - nextRankStart += (rankVal[n] << (n - 1)); - rankVal[n] = current; - } - - /* fill DTable */ - for (n = 0; n < nbSymbols; n++) - { - const U32 w = huffWeight[n]; - const U32 length = (1 << w) >> 1; - U32 i; - HUF_DEltX2 D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(tableLog + 1 - w); - for (i = rankVal[w]; i < rankVal[w] + length; i++) - dt[i] = D; - rankVal[w] += length; - } - - return iSize; -} - -static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog) -{ - const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */ - const BYTE c = dt[val].byte; - BIT_skipBits(Dstream, dt[val].nbBits); - return c; -} - -#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \ - *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_MAX_TABLELOG <= 12)) \ - HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) - -#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) - -static inline size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog) -{ - BYTE *const pStart = p; - - /* up to 4 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) - { - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_1(p, bitDPtr); - HUF_DECODE_SYMBOLX2_2(p, bitDPtr); - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - } - - /* closer to the end */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd)) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - - /* no more data to retrieve from bitstream, hence no need to reload */ - while (p < pEnd) - HUF_DECODE_SYMBOLX2_0(p, bitDPtr); - - return pEnd - pStart; -} - -static size_t HUF_decompress4X2_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const U16 *DTable) -{ - if (cSrcSize < 10) - return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { - const BYTE *const istart = (const BYTE *)cSrc; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - - const void *ptr = DTable; - const HUF_DEltX2 *const dt = ((const HUF_DEltX2 *)ptr) + 1; - const U32 dtLog = DTable[0]; - size_t errorCode; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - const size_t length1 = MEM_readLE16(istart); - const size_t length2 = MEM_readLE16(istart + 2); - const size_t length3 = MEM_readLE16(istart + 4); - size_t length4; - const BYTE *const istart1 = istart + 6; /* jumpTable */ - const BYTE *const istart2 = istart1 + length1; - const BYTE *const istart3 = istart2 + length2; - const BYTE *const istart4 = istart3 + length3; - const size_t segmentSize = (dstSize + 3) / 4; - BYTE *const opStart2 = ostart + segmentSize; - BYTE *const opStart3 = opStart2 + segmentSize; - BYTE *const opStart4 = opStart3 + segmentSize; - BYTE *op1 = ostart; - BYTE *op2 = opStart2; - BYTE *op3 = opStart3; - BYTE *op4 = opStart4; - U32 endSignal; - - length4 = cSrcSize - (length1 + length2 + length3 + 6); - if (length4 > cSrcSize) - return ERROR(corruption_detected); /* overflow */ - errorCode = BIT_initDStream(&bitD1, istart1, length1); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD2, istart2, length2); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD3, istart3, length3); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD4, istart4, length4); - if (HUF_isError(errorCode)) - return errorCode; - - /* 16-32 symbols per loop (4-8 symbols per stream) */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) - { - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_1(op1, &bitD1); - HUF_DECODE_SYMBOLX2_1(op2, &bitD2); - HUF_DECODE_SYMBOLX2_1(op3, &bitD3); - HUF_DECODE_SYMBOLX2_1(op4, &bitD4); - HUF_DECODE_SYMBOLX2_2(op1, &bitD1); - HUF_DECODE_SYMBOLX2_2(op2, &bitD2); - HUF_DECODE_SYMBOLX2_2(op3, &bitD3); - HUF_DECODE_SYMBOLX2_2(op4, &bitD4); - HUF_DECODE_SYMBOLX2_0(op1, &bitD1); - HUF_DECODE_SYMBOLX2_0(op2, &bitD2); - HUF_DECODE_SYMBOLX2_0(op3, &bitD3); - HUF_DECODE_SYMBOLX2_0(op4, &bitD4); - - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - } - - /* check corruption */ - if (op1 > opStart2) - return ERROR(corruption_detected); - if (op2 > opStart3) - return ERROR(corruption_detected); - if (op3 > opStart4) - return ERROR(corruption_detected); - /* note : op4 supposed already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog); - - /* check */ - endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endSignal) - return ERROR(corruption_detected); - - /* decoded size */ - return dstSize; - } -} - -static size_t HUF_decompress4X2(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG); - const BYTE *ip = (const BYTE *)cSrc; - size_t errorCode; - - errorCode = HUF_readDTableX2(DTable, cSrc, cSrcSize); - if (HUF_isError(errorCode)) - return errorCode; - if (errorCode >= cSrcSize) - return ERROR(srcSize_wrong); - ip += errorCode; - cSrcSize -= errorCode; - - return HUF_decompress4X2_usingDTable(dst, dstSize, ip, cSrcSize, DTable); -} - -/***************************/ -/* double-symbols decoding */ -/***************************/ - -static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, - const U32 *rankValOrigin, const int minWeight, - const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, - U32 nbBitsBaseline, U16 baseSeq) -{ - HUF_DEltX4 DElt; - U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; - U32 s; - - /* get pre-calculated rankVal */ - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill skipped values */ - if (minWeight > 1) - { - U32 i, skipSize = rankVal[minWeight]; - MEM_writeLE16(&(DElt.sequence), baseSeq); - DElt.nbBits = (BYTE)(consumed); - DElt.length = 1; - for (i = 0; i < skipSize; i++) - DTable[i] = DElt; - } - - /* fill DTable */ - for (s = 0; s < sortedListSize; s++) /* note : sortedSymbols already skipped */ - { - const U32 symbol = sortedSymbols[s].symbol; - const U32 weight = sortedSymbols[s].weight; - const U32 nbBits = nbBitsBaseline - weight; - const U32 length = 1 << (sizeLog - nbBits); - const U32 start = rankVal[weight]; - U32 i = start; - const U32 end = start + length; - - MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8))); - DElt.nbBits = (BYTE)(nbBits + consumed); - DElt.length = 2; - do - { - DTable[i++] = DElt; - } while (i < end); /* since length >= 1 */ - - rankVal[weight] += length; - } -} - -typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1]; - -static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, - const sortedSymbol_t *sortedList, const U32 sortedListSize, - const U32 *rankStart, rankVal_t rankValOrigin, const U32 maxWeight, - const U32 nbBitsBaseline) -{ - U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; - const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */ - const U32 minBits = nbBitsBaseline - maxWeight; - U32 s; - - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); - - /* fill DTable */ - for (s = 0; s < sortedListSize; s++) - { - const U16 symbol = sortedList[s].symbol; - const U32 weight = sortedList[s].weight; - const U32 nbBits = nbBitsBaseline - weight; - const U32 start = rankVal[weight]; - const U32 length = 1 << (targetLog - nbBits); - - if (targetLog - nbBits >= minBits) /* enough room for a second symbol */ - { - U32 sortedRank; - int minWeight = nbBits + scaleLog; - if (minWeight < 1) - minWeight = 1; - sortedRank = rankStart[minWeight]; - HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, - rankValOrigin[nbBits], minWeight, - sortedList + sortedRank, sortedListSize - sortedRank, - nbBitsBaseline, symbol); - } - else - { - U32 i; - const U32 end = start + length; - HUF_DEltX4 DElt; - - MEM_writeLE16(&(DElt.sequence), symbol); - DElt.nbBits = (BYTE)(nbBits); - DElt.length = 1; - for (i = start; i < end; i++) - DTable[i] = DElt; - } - rankVal[weight] += length; - } -} - -static size_t HUF_readDTableX4(U32 *DTable, const void *src, size_t srcSize) -{ - BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1]; - sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1]; - U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = {0}; - U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = {0}; - U32 *const rankStart = rankStart0 + 1; - rankVal_t rankVal; - U32 tableLog, maxW, sizeOfSort, nbSymbols; - const U32 memLog = DTable[0]; - const BYTE *ip = (const BYTE *)src; - size_t iSize = ip[0]; - void *ptr = DTable; - HUF_DEltX4 *const dt = ((HUF_DEltX4 *)ptr) + 1; - - HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32)); /* if compilation fails here, assertion is false */ - if (memLog > HUF_ABSOLUTEMAX_TABLELOG) - return ERROR(tableLog_tooLarge); - // memset(weightList, 0, sizeof(weightList)); /* is not necessary, even though some analyzer complain ... */ - - iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); - if (HUF_isError(iSize)) - return iSize; - - /* check result */ - if (tableLog > memLog) - return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */ - - /* find maxWeight */ - for (maxW = tableLog; rankStats[maxW] == 0; maxW--) - { - if (!maxW) - return ERROR(GENERIC); - } /* necessarily finds a solution before maxW==0 */ - - /* Get start index of each weight */ - { - U32 w, nextRankStart = 0; - for (w = 1; w <= maxW; w++) - { - U32 current = nextRankStart; - nextRankStart += rankStats[w]; - rankStart[w] = current; - } - rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ - sizeOfSort = nextRankStart; - } - - /* sort symbols by weight */ - { - U32 s; - for (s = 0; s < nbSymbols; s++) - { - U32 w = weightList[s]; - U32 r = rankStart[w]++; - sortedSymbol[r].symbol = (BYTE)s; - sortedSymbol[r].weight = (BYTE)w; - } - rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */ - } - - /* Build rankVal */ - { - const U32 minBits = tableLog + 1 - maxW; - U32 nextRankVal = 0; - U32 w, consumed; - const int rescale = (memLog - tableLog) - 1; /* tableLog <= memLog */ - U32 *rankVal0 = rankVal[0]; - for (w = 1; w <= maxW; w++) - { - U32 current = nextRankVal; - nextRankVal += rankStats[w] << (w + rescale); - rankVal0[w] = current; - } - for (consumed = minBits; consumed <= memLog - minBits; consumed++) - { - U32 *rankValPtr = rankVal[consumed]; - for (w = 1; w <= maxW; w++) - { - rankValPtr[w] = rankVal0[w] >> consumed; - } - } - } - - HUF_fillDTableX4(dt, memLog, - sortedSymbol, sizeOfSort, - rankStart0, rankVal, maxW, - tableLog + 1); - - return iSize; -} - -static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog) -{ - const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt + val, 2); - BIT_skipBits(DStream, dt[val].nbBits); - return dt[val].length; -} - -static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog) -{ - const size_t val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt + val, 1); - if (dt[val].length == 1) - BIT_skipBits(DStream, dt[val].nbBits); - else - { - if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) - { - BIT_skipBits(DStream, dt[val].nbBits); - if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8)) - DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8); /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */ - } - } - return 1; -} - -#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \ - if (MEM_64bits() || (HUF_MAX_TABLELOG <= 12)) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \ - if (MEM_64bits()) \ - ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog) - -static inline size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog) -{ - BYTE *const pStart = p; - - /* up to 8 symbols at a time */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd - 7)) - { - HUF_DECODE_SYMBOLX4_2(p, bitDPtr); - HUF_DECODE_SYMBOLX4_1(p, bitDPtr); - HUF_DECODE_SYMBOLX4_2(p, bitDPtr); - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); - } - - /* closer to the end */ - while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 2)) - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); - - while (p <= pEnd - 2) - HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */ - - if (p < pEnd) - p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog); - - return p - pStart; -} - -static size_t HUF_decompress4X4_usingDTable( - void *dst, size_t dstSize, - const void *cSrc, size_t cSrcSize, - const U32 *DTable) -{ - if (cSrcSize < 10) - return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */ - - { - const BYTE *const istart = (const BYTE *)cSrc; - BYTE *const ostart = (BYTE *)dst; - BYTE *const oend = ostart + dstSize; - - const void *ptr = DTable; - const HUF_DEltX4 *const dt = ((const HUF_DEltX4 *)ptr) + 1; - const U32 dtLog = DTable[0]; - size_t errorCode; - - /* Init */ - BIT_DStream_t bitD1; - BIT_DStream_t bitD2; - BIT_DStream_t bitD3; - BIT_DStream_t bitD4; - const size_t length1 = MEM_readLE16(istart); - const size_t length2 = MEM_readLE16(istart + 2); - const size_t length3 = MEM_readLE16(istart + 4); - size_t length4; - const BYTE *const istart1 = istart + 6; /* jumpTable */ - const BYTE *const istart2 = istart1 + length1; - const BYTE *const istart3 = istart2 + length2; - const BYTE *const istart4 = istart3 + length3; - const size_t segmentSize = (dstSize + 3) / 4; - BYTE *const opStart2 = ostart + segmentSize; - BYTE *const opStart3 = opStart2 + segmentSize; - BYTE *const opStart4 = opStart3 + segmentSize; - BYTE *op1 = ostart; - BYTE *op2 = opStart2; - BYTE *op3 = opStart3; - BYTE *op4 = opStart4; - U32 endSignal; - - length4 = cSrcSize - (length1 + length2 + length3 + 6); - if (length4 > cSrcSize) - return ERROR(corruption_detected); /* overflow */ - errorCode = BIT_initDStream(&bitD1, istart1, length1); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD2, istart2, length2); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD3, istart3, length3); - if (HUF_isError(errorCode)) - return errorCode; - errorCode = BIT_initDStream(&bitD4, istart4, length4); - if (HUF_isError(errorCode)) - return errorCode; - - /* 16-32 symbols per loop (4-8 symbols per stream) */ - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) - { - HUF_DECODE_SYMBOLX4_2(op1, &bitD1); - HUF_DECODE_SYMBOLX4_2(op2, &bitD2); - HUF_DECODE_SYMBOLX4_2(op3, &bitD3); - HUF_DECODE_SYMBOLX4_2(op4, &bitD4); - HUF_DECODE_SYMBOLX4_1(op1, &bitD1); - HUF_DECODE_SYMBOLX4_1(op2, &bitD2); - HUF_DECODE_SYMBOLX4_1(op3, &bitD3); - HUF_DECODE_SYMBOLX4_1(op4, &bitD4); - HUF_DECODE_SYMBOLX4_2(op1, &bitD1); - HUF_DECODE_SYMBOLX4_2(op2, &bitD2); - HUF_DECODE_SYMBOLX4_2(op3, &bitD3); - HUF_DECODE_SYMBOLX4_2(op4, &bitD4); - HUF_DECODE_SYMBOLX4_0(op1, &bitD1); - HUF_DECODE_SYMBOLX4_0(op2, &bitD2); - HUF_DECODE_SYMBOLX4_0(op3, &bitD3); - HUF_DECODE_SYMBOLX4_0(op4, &bitD4); - - endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4); - } - - /* check corruption */ - if (op1 > opStart2) - return ERROR(corruption_detected); - if (op2 > opStart3) - return ERROR(corruption_detected); - if (op3 > opStart4) - return ERROR(corruption_detected); - /* note : op4 supposed already verified within main loop */ - - /* finish bitStreams one by one */ - HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog); - HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog); - HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog); - HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog); - - /* check */ - endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4); - if (!endSignal) - return ERROR(corruption_detected); - - /* decoded size */ - return dstSize; - } -} - -static size_t HUF_decompress4X4(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG); - const BYTE *ip = (const BYTE *)cSrc; - - size_t hSize = HUF_readDTableX4(DTable, cSrc, cSrcSize); - if (HUF_isError(hSize)) - return hSize; - if (hSize >= cSrcSize) - return ERROR(srcSize_wrong); - ip += hSize; - cSrcSize -= hSize; - - return HUF_decompress4X4_usingDTable(dst, dstSize, ip, cSrcSize, DTable); -} - -/**********************************/ -/* quad-symbol decoding */ -/**********************************/ -typedef struct -{ - BYTE nbBits; - BYTE nbBytes; -} HUF_DDescX6; -typedef union -{ - BYTE byte[4]; - U32 sequence; -} HUF_DSeqX6; - -/* recursive, up to level 3; may benefit from