Merge remote-tracking branch 'upstream/dev' into btopt
* upstream/dev: (305 commits) added test for ZSTD_estimateCStreamSize() changed variable name, for clarity fixed ZSTD_estimateCStreamSize() shortened ZSTD_createCStream_Advanced() fixed symbols test added ZSTD_estimateDStreamSize() changed name frameParams into frameHeader regroup memory usage function declarations separated ZSTD_estimateCStreamSize() from ZSTD_estimateCCtxSize() bumped version number added ZSTD_estimateCDictSize() and ZSTD_estimateDDictSize() Updated ZSTD_freeCCtx() updated ZSTD_estimateCCtxSize() Updated ZSTD_sizeof_CCtx() merged CCtx and CStream as a single same object cli : -d and -t do not stop after a failed decompression added dev branch CircleCI badge added dev branch Appveyor badge keep dev branch status only creates a binary archive without the `programs` directory ...
This commit is contained in:
+20
-7
@@ -22,7 +22,7 @@ VERSION?= $(LIBVER)
|
||||
|
||||
CPPFLAGS+= -I. -I./common -DXXH_NAMESPACE=ZSTD_
|
||||
CFLAGS ?= -O3
|
||||
DEBUGFLAGS = -g -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
DEBUGFLAGS = -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \
|
||||
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
|
||||
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security
|
||||
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
|
||||
@@ -31,12 +31,15 @@ FLAGS = $(CPPFLAGS) $(CFLAGS)
|
||||
|
||||
ZSTD_FILES := $(wildcard common/*.c compress/*.c decompress/*.c dictBuilder/*.c deprecated/*.c)
|
||||
|
||||
ifeq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||
CPPFLAGS += -DZSTD_LEGACY_SUPPORT=0
|
||||
else
|
||||
CPPFLAGS += -I./legacy -DZSTD_LEGACY_SUPPORT=1
|
||||
ZSTD_FILES+= $(wildcard legacy/*.c)
|
||||
ZSTD_LEGACY_SUPPORT ?= 4
|
||||
|
||||
ifneq ($(ZSTD_LEGACY_SUPPORT), 0)
|
||||
ifeq ($(shell test $(ZSTD_LEGACY_SUPPORT) -lt 8; echo $$?), 0)
|
||||
ZSTD_FILES += $(shell ls legacy/*.c | grep 'v0[$(ZSTD_LEGACY_SUPPORT)-7]')
|
||||
endif
|
||||
CPPFLAGS += -I./legacy
|
||||
endif
|
||||
CPPFLAGS += -DZSTD_LEGACY_SUPPORT=$(ZSTD_LEGACY_SUPPORT)
|
||||
|
||||
ZSTD_OBJ := $(patsubst %.c,%.o,$(ZSTD_FILES))
|
||||
|
||||
@@ -68,6 +71,9 @@ libzstd.a: $(ZSTD_OBJ)
|
||||
@echo compiling static library
|
||||
@$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
libzstd.a-mt: CPPFLAGS += -DZSTD_MULTHREAD
|
||||
libzstd.a-mt: libzstd.a
|
||||
|
||||
$(LIBZSTD): LDFLAGS += -shared -fPIC -fvisibility=hidden
|
||||
$(LIBZSTD): $(ZSTD_FILES)
|
||||
@echo compiling dynamic library $(LIBVER)
|
||||
@@ -83,10 +89,17 @@ endif
|
||||
|
||||
libzstd : $(LIBZSTD)
|
||||
|
||||
libzstd-mt : CPPFLAGS += -DZSTD_MULTITHREAD
|
||||
libzstd-mt : libzstd
|
||||
|
||||
lib: libzstd.a libzstd
|
||||
|
||||
lib-release: DEBUGFLAGS :=
|
||||
lib-mt: CPPFLAGS += -DZSTD_MULTITHREAD
|
||||
lib-mt: lib
|
||||
|
||||
lib-release lib-release-mt: DEBUGFLAGS :=
|
||||
lib-release: lib
|
||||
lib-release-mt: lib-mt
|
||||
|
||||
clean:
|
||||
@$(RM) -r *.dSYM # Mac OS-X specific
|
||||
|
||||
@@ -22,6 +22,14 @@ Some additional API may be useful if you're looking into advanced features :
|
||||
They are not "stable", their definition may change in the future.
|
||||
Only static linking is allowed.
|
||||
|
||||
#### ZSTDMT API
|
||||
|
||||
To enable multithreaded compression within the library, invoke `make lib-mt` target.
|
||||
Prototypes are defined in header file `compress/zstdmt_compress.h`.
|
||||
When linking a program that uses ZSTDMT API against libzstd.a on a POSIX system,
|
||||
`-pthread` flag must be provided to the compiler and linker.
|
||||
Note : ZSTDMT prototypes can still be used with a library built without multithread support,
|
||||
but in this case, they will be single threaded only.
|
||||
|
||||
#### Modular build
|
||||
|
||||
|
||||
+55
-26
@@ -2,7 +2,7 @@
|
||||
bitstream
|
||||
Part of FSE library
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
Copyright (C) 2013-2017, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
@@ -53,6 +53,16 @@ extern "C" {
|
||||
#include "error_private.h" /* error codes and messages */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Debug
|
||||
***************************************/
|
||||
#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# define assert(condition) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
/*=========================================
|
||||
* Target specific
|
||||
=========================================*/
|
||||
@@ -74,7 +84,7 @@ extern "C" {
|
||||
typedef struct
|
||||
{
|
||||
size_t bitContainer;
|
||||
int bitPos;
|
||||
unsigned bitPos;
|
||||
char* startPtr;
|
||||
char* ptr;
|
||||
char* endPtr;
|
||||
@@ -112,6 +122,7 @@ typedef struct
|
||||
unsigned bitsConsumed;
|
||||
const char* ptr;
|
||||
const char* start;
|
||||
const char* limitPtr;
|
||||
} BIT_DStream_t;
|
||||
|
||||
typedef enum { BIT_DStream_unfinished = 0,
|
||||
@@ -163,7 +174,10 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
||||
# 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 };
|
||||
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;
|
||||
@@ -175,31 +189,36 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
||||
}
|
||||
|
||||
/*===== 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 */
|
||||
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*)
|
||||
* `dstCapacity` must be > sizeof(size_t)
|
||||
* @return : 0 if success,
|
||||
otherwise an error code (can be tested using ERR_isError() ) */
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
|
||||
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);
|
||||
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
|
||||
if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! BIT_addBits() :
|
||||
can add up to 26 bits into `bitC`.
|
||||
Does not check for register overflow ! */
|
||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
||||
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;
|
||||
@@ -207,34 +226,42 @@ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned 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)
|
||||
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
|
||||
size_t value, unsigned nbBits)
|
||||
{
|
||||
assert((value>>nbBits) == 0);
|
||||
bitC->bitContainer |= value << bitC->bitPos;
|
||||
bitC->bitPos += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_flushBitsFast() :
|
||||
* assumption : bitContainer has not overflowed
|
||||
* unsafe version; does not check buffer overflow */
|
||||
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
|
||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||
bitC->ptr += nbBytes;
|
||||
assert(bitC->ptr <= bitC->endPtr);
|
||||
bitC->bitPos &= 7;
|
||||
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
|
||||
bitC->bitContainer >>= nbBytes*8;
|
||||
}
|
||||
|
||||
/*! BIT_flushBits() :
|
||||
* assumption : bitContainer has not overflowed
|
||||
* safe version; check for buffer overflow, and prevents it.
|
||||
* note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
|
||||
* note : does not signal buffer overflow.
|
||||
* overflow will be revealed later on using BIT_closeCStream() */
|
||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
|
||||
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 */
|
||||
bitC->bitContainer >>= nbBytes*8;
|
||||
}
|
||||
|
||||
/*! BIT_closeCStream() :
|
||||
@@ -244,9 +271,7 @@ 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 */
|
||||
|
||||
if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
|
||||
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
|
||||
}
|
||||
|
||||
@@ -264,15 +289,16 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
|
||||
{
|
||||
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||
|
||||
bitD->start = (const char*)srcBuffer;
|
||||
bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
|
||||
|
||||
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
||||
bitD->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)
|
||||
@@ -330,17 +356,18 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const 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);
|
||||
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! BIT_lookBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
* unsafe version; only works 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);
|
||||
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
assert(nbBits >= 1);
|
||||
return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
|
||||
}
|
||||
|
||||
MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
@@ -365,6 +392,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
||||
assert(nbBits >= 1);
|
||||
BIT_skipBits(bitD, nbBits);
|
||||
return value;
|
||||
}
|
||||
@@ -376,10 +404,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
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 */
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
|
||||
return BIT_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
|
||||
if (bitD->ptr >= bitD->limitPtr) {
|
||||
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||
bitD->bitsConsumed &= 7;
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||
@@ -389,6 +417,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
|
||||
return BIT_DStream_completed;
|
||||
}
|
||||
/* start < ptr < limitPtr */
|
||||
{ U32 nbBytes = bitD->bitsConsumed >> 3;
|
||||
BIT_DStream_status result = BIT_DStream_unfinished;
|
||||
if (bitD->ptr - nbBytes < bitD->start) {
|
||||
@@ -397,7 +426,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
}
|
||||
bitD->ptr -= nbBytes;
|
||||
bitD->bitsConsumed -= nbBytes*8;
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
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(srcSize_wrong): return "Src size is 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";
|
||||
@@ -37,6 +37,9 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
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(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
|
||||
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
||||
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
||||
case PREFIX(maxCode):
|
||||
default: return notErrorCode;
|
||||
}
|
||||
|
||||
+7
-3
@@ -316,6 +316,10 @@ If there is an error, the function will return an error code, which can be teste
|
||||
#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))
|
||||
#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog))
|
||||
|
||||
/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
|
||||
#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
|
||||
#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
|
||||
|
||||
|
||||
/* *****************************************
|
||||
* FSE advanced API
|
||||
@@ -353,7 +357,7 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
|
||||
* 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)) )
|
||||
#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
|
||||
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||
|
||||
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
|
||||
@@ -550,9 +554,9 @@ MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U3
|
||||
|
||||
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];
|
||||
FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
|
||||
const U16* const stateTable = (const U16*)(statePtr->stateTable);
|
||||
U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
|
||||
U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
|
||||
BIT_addBits(bitC, statePtr->value, nbBitsOut);
|
||||
statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
|
||||
}
|
||||
|
||||
+42
-19
@@ -43,6 +43,21 @@ extern "C" {
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/* *** library symbols visibility *** */
|
||||
/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
|
||||
* HUF symbols remain "private" (internal symbols for library only).
|
||||
* Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
|
||||
#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
|
||||
#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
|
||||
# define HUF_PUBLIC_API __declspec(dllexport)
|
||||
#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
|
||||
# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
|
||||
#else
|
||||
# define HUF_PUBLIC_API
|
||||
#endif
|
||||
|
||||
|
||||
/* *** simple functions *** */
|
||||
/**
|
||||
HUF_compress() :
|
||||
@@ -55,8 +70,8 @@ HUF_compress() :
|
||||
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_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/**
|
||||
HUF_decompress() :
|
||||
@@ -69,32 +84,42 @@ HUF_decompress() :
|
||||
@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);
|
||||
HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
|
||||
|
||||
/* *** Tool functions *** */
|
||||
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
|
||||
size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
|
||||
HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||
|
||||
/* Error Management */
|
||||
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) */
|
||||
HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
|
||||
HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
/* *** Advanced function *** */
|
||||
|
||||
/** HUF_compress2() :
|
||||
* Same as HUF_compress(), but offers 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);
|
||||
* Same as HUF_compress(), but offers direct control over `maxSymbolValue` and `tableLog`.
|
||||
* `tableLog` must be `<= HUF_TABLELOG_MAX` . */
|
||||
HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/** HUF_compress4X_wksp() :
|
||||
* Same as HUF_compress2(), but uses externally allocated `workSpace`, 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 */
|
||||
* Same as HUF_compress2(), but uses externally allocated `workSpace`.
|
||||
* `workspace` must have minimum alignment of 4, and be at least as large as following macro */
|
||||
#define HUF_WORKSPACE_SIZE (6 << 10)
|
||||
#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
|
||||
HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||
|
||||
|
||||
|
||||
/* ******************************************************************
|
||||
* WARNING !!
|
||||
* The following section contains advanced and experimental definitions
|
||||
* which shall never be used in the context of dll
|
||||
* because they are not guaranteed to remain stable in the future.
|
||||
* Only consider them in association with static linking.
|
||||
*******************************************************************/
|
||||
#ifdef HUF_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependencies *** */
|
||||
@@ -117,12 +142,14 @@ size_t HUF_compress4X_wksp (void* dst, size_t dstSize, const void* src, size_t s
|
||||
******************************************/
|
||||
/* 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_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */
|
||||
#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
|
||||
|
||||
/* static allocation of HUF's Compression Table */
|
||||
#define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */
|
||||
#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))
|
||||
#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
|
||||
U32 name##hb[maxSymbolValue+1]; \
|
||||
U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \
|
||||
void* name##hv = &(name##hb); \
|
||||
HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */
|
||||
|
||||
@@ -134,10 +161,6 @@ typedef U32 HUF_DTable;
|
||||
#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
|
||||
|
||||
+11
-10
@@ -48,14 +48,15 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
|
||||
*****************************************************************/
|
||||
#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
|
||||
# include <stdint.h>
|
||||
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 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;
|
||||
@@ -65,6 +66,7 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
|
||||
typedef unsigned long long U64;
|
||||
typedef signed long long S64;
|
||||
typedef ptrdiff_t iPtrDiff;
|
||||
typedef size_t uPtrDiff;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -87,8 +89,7 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
|
||||
#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__) ))
|
||||
# elif defined(__INTEL_COMPILER) || defined(__GNUC__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -57,6 +57,9 @@ typedef enum {
|
||||
ZSTD_error_maxSymbolValue_tooSmall,
|
||||
ZSTD_error_dictionary_corrupted,
|
||||
ZSTD_error_dictionary_wrong,
|
||||
ZSTD_error_dictionaryCreation_failed,
|
||||
ZSTD_error_frameIndex_tooLarge,
|
||||
ZSTD_error_seekableIO,
|
||||
ZSTD_error_maxCode
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 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__
|
||||
@@ -58,6 +58,8 @@
|
||||
/*-*************************************
|
||||
* shared macros
|
||||
***************************************/
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#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 */
|
||||
@@ -104,7 +106,6 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
|
||||
#define LONGNBSEQ 0x7F00
|
||||
|
||||
#define MINMATCH 3
|
||||
#define EQUAL_READ32 4
|
||||
|
||||
#define Litbits 8
|
||||
#define MaxLit ((1<<Litbits) - 1)
|
||||
|
||||
@@ -291,7 +291,7 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
|
||||
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_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported */
|
||||
if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC); /* Unsupported */
|
||||
|
||||
if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))
|
||||
@@ -808,7 +808,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src
|
||||
if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
|
||||
|
||||
/* Scan input and build symbol stats */
|
||||
{ CHECK_V_F(maxCount, FSE_count(count, &maxSymbolValue, src, srcSize) );
|
||||
{ CHECK_V_F(maxCount, FSE_count_wksp(count, &maxSymbolValue, src, srcSize, (unsigned*)scratchBuffer) );
|
||||
if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */
|
||||
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
|
||||
if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */
|
||||
|
||||
+554
-326
@@ -20,6 +20,26 @@
|
||||
#include "zstd_internal.h" /* includes zstd.h */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Debug
|
||||
***************************************/
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# define assert(condition) ((void)0)
|
||||
#endif
|
||||
|
||||
#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
|
||||
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
||||
# include <stdio.h>
|
||||
static unsigned g_debugLevel = ZSTD_DEBUG;
|
||||
# define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
|
||||
#else
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
@@ -27,12 +47,22 @@ static const U32 g_searchStrength = 8; /* control skip over incompressible dat
|
||||
#define HASH_READ_SIZE 8
|
||||
typedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;
|
||||
|
||||
/* entropy tables always have same size */
|
||||
static size_t const hufCTable_size = HUF_CTABLE_SIZE(255);
|
||||
static size_t const litlengthCTable_size = FSE_CTABLE_SIZE(LLFSELog, MaxLL);
|
||||
static size_t const offcodeCTable_size = FSE_CTABLE_SIZE(OffFSELog, MaxOff);
|
||||
static size_t const matchlengthCTable_size = FSE_CTABLE_SIZE(MLFSELog, MaxML);
|
||||
static size_t const entropyScratchSpace_size = HUF_WORKSPACE_SIZE;
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* 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; }
|
||||
size_t ZSTD_compressBound(size_t srcSize) {
|
||||
size_t const lowLimit = 256 KB;
|
||||
size_t const margin = (srcSize < lowLimit) ? (lowLimit-srcSize) >> 12 : 0; /* from 64 to 0 */
|
||||
return srcSize + (srcSize >> 8) + margin;
|
||||
}
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -49,6 +79,8 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
||||
/*-*************************************
|
||||
* Context memory management
|
||||
***************************************/
|
||||
typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage;
|
||||
|
||||
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 */
|
||||
@@ -70,6 +102,7 @@ struct ZSTD_CCtx_s {
|
||||
size_t workSpaceSize;
|
||||
size_t blockSize;
|
||||
U64 frameContentSize;
|
||||
U64 consumedSrcSize;
|
||||
XXH64_state_t xxhState;
|
||||
ZSTD_customMem customMem;
|
||||
|
||||
@@ -77,13 +110,29 @@ struct ZSTD_CCtx_s {
|
||||
U32* hashTable;
|
||||
U32* hashTable3;
|
||||
U32* chainTable;
|
||||
HUF_CElt* hufTable;
|
||||
U32 flagStaticTables;
|
||||
HUF_repeat flagStaticHufTable;
|
||||
FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
|
||||
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
|
||||
FSE_CTable litlengthCTable [FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
|
||||
unsigned tmpCounters[HUF_WORKSPACE_SIZE_U32];
|
||||
HUF_repeat hufCTable_repeatMode;
|
||||
HUF_CElt* hufCTable;
|
||||
U32 fseCTables_ready;
|
||||
FSE_CTable* offcodeCTable;
|
||||
FSE_CTable* matchlengthCTable;
|
||||
FSE_CTable* litlengthCTable;
|
||||
unsigned* entropyScratchSpace;
|
||||
|
||||
/* streaming */
|
||||
ZSTD_CDict* cdictLocal;
|
||||
const ZSTD_CDict* cdict;
|
||||
char* inBuff;
|
||||
size_t inBuffSize;
|
||||
size_t inToCompress;
|
||||
size_t inBuffPos;
|
||||
size_t inBuffTarget;
|
||||
char* outBuff;
|
||||
size_t outBuffSize;
|
||||
size_t outBuffContentSize;
|
||||
size_t outBuffFlushedSize;
|
||||
ZSTD_cStreamStage streamStage;
|
||||
U32 frameEnded;
|
||||
U64 pledgedSrcSize;
|
||||
};
|
||||
|
||||
ZSTD_CCtx* ZSTD_createCCtx(void)
|
||||
@@ -109,6 +158,13 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support free on NULL */
|
||||
ZSTD_free(cctx->workSpace, cctx->customMem);
|
||||
cctx->workSpace = NULL;
|
||||
ZSTD_freeCDict(cctx->cdictLocal);
|
||||
cctx->cdictLocal = NULL;
|
||||
ZSTD_free(cctx->inBuff, cctx->customMem);
|
||||
cctx->inBuff = NULL;
|
||||
ZSTD_free(cctx->outBuff, cctx->customMem);
|
||||
cctx->outBuff = NULL;
|
||||
ZSTD_free(cctx, cctx->customMem);
|
||||
return 0; /* reserved as a potential error code in the future */
|
||||
}
|
||||
@@ -116,7 +172,9 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
||||
return sizeof(*cctx) + cctx->workSpaceSize;
|
||||
return sizeof(*cctx) + cctx->workSpaceSize
|
||||
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
|
||||
+ cctx->outBuffSize + cctx->inBuffSize;
|
||||
}
|
||||
|
||||
size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
|
||||
@@ -150,9 +208,7 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
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.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
|
||||
CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
||||
if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) return ERROR(compressionParameter_unsupported);
|
||||
return 0;
|
||||
@@ -206,12 +262,15 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
|
||||
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 entropySpace = hufCTable_size + litlengthCTable_size
|
||||
+ offcodeCTable_size + matchlengthCTable_size
|
||||
+ entropyScratchSpace_size;
|
||||
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
|
||||
size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits))*sizeof(U32)
|
||||
size_t const optBudget = ((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_btultra)) ? optSpace : 0);
|
||||
size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
|
||||
size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace;
|
||||
|
||||
return sizeof(ZSTD_CCtx) + neededSpace;
|
||||
}
|
||||
@@ -221,8 +280,8 @@ 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));
|
||||
& (param1.cParams.strategy == param2.cParams.strategy) /* opt parser space */
|
||||
& ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3)); /* hashlog3 space */
|
||||
}
|
||||
|
||||
/*! ZSTD_continueCCtx() :
|
||||
@@ -232,6 +291,7 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra
|
||||
U32 const end = (U32)(cctx->nextSrc - cctx->base);
|
||||
cctx->params = params;
|
||||
cctx->frameContentSize = frameContentSize;
|
||||
cctx->consumedSrcSize = 0;
|
||||
cctx->lowLimit = end;
|
||||
cctx->dictLimit = end;
|
||||
cctx->nextToUpdate = end+1;
|
||||
@@ -246,16 +306,19 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra
|
||||
|
||||
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e;
|
||||
|
||||
/*! ZSTD_resetCCtx_advanced() :
|
||||
/*! ZSTD_resetCCtx_internal() :
|
||||
note : `params` must be validated */
|
||||
static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
ZSTD_parameters params, U64 frameContentSize,
|
||||
ZSTD_compResetPolicy_e const crp)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_resetCCtx_internal \n");
|
||||
|
||||
if (crp == ZSTDcrp_continue)
|
||||
if (ZSTD_equivalentParams(params, zc->params)) {
|
||||
zc->flagStaticTables = 0;
|
||||
zc->flagStaticHufTable = HUF_repeat_none;
|
||||
DEBUGLOG(5, "ZSTD_equivalentParams()==1 \n");
|
||||
zc->fseCTables_ready = 0;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
return ZSTD_continueCCtx(zc, params, frameContentSize);
|
||||
}
|
||||
|
||||
@@ -271,41 +334,71 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
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_btultra)) ? optSpace : 0);
|
||||
{ size_t const entropySpace = hufCTable_size + litlengthCTable_size
|
||||
+ offcodeCTable_size + matchlengthCTable_size
|
||||
+ entropyScratchSpace_size;
|
||||
size_t const optPotentialSpace = ((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 optSpace = ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) ? optPotentialSpace : 0;
|
||||
size_t const neededSpace = entropySpace + optSpace + tableSpace + tokenSpace;
|
||||
if (zc->workSpaceSize < neededSpace) {
|
||||
DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
|
||||
(unsigned)zc->workSpaceSize>>10, (unsigned)neededSpace>>10);
|
||||
zc->workSpaceSize = 0;
|
||||
ZSTD_free(zc->workSpace, zc->customMem);
|
||||
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
|
||||
if (zc->workSpace == NULL) return ERROR(memory_allocation);
|
||||
zc->workSpaceSize = neededSpace;
|
||||
ptr = zc->workSpace;
|
||||
|
||||
/* entropy space */
|
||||
zc->hufCTable = (HUF_CElt*)ptr;
|
||||
ptr = (char*)zc->hufCTable + hufCTable_size; /* note : HUF_CElt* is incomplete type, size is estimated via macro */
|
||||
zc->offcodeCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + offcodeCTable_size;
|
||||
zc->matchlengthCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + matchlengthCTable_size;
|
||||
zc->litlengthCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + litlengthCTable_size;
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure correct alignment */
|
||||
zc->entropyScratchSpace = (unsigned*) ptr;
|
||||
} }
|
||||
|
||||
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 */
|
||||
/* init params */
|
||||
zc->params = params;
|
||||
zc->blockSize = blockSize;
|
||||
DEBUGLOG(5, "blockSize = %uK \n", (U32)blockSize>>10);
|
||||
zc->frameContentSize = frameContentSize;
|
||||
zc->consumedSrcSize = 0;
|
||||
|
||||
XXH64_reset(&zc->xxhState, 0);
|
||||
zc->stage = ZSTDcs_init;
|
||||
zc->dictID = 0;
|
||||
zc->loadedDictEnd = 0;
|
||||
zc->fseCTables_ready = 0;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
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]; }
|
||||
zc->hashLog3 = hashLog3;
|
||||
zc->seqStore.litLengthSum = 0;
|
||||
|
||||
/* ensure entropy tables are close together at the beginning */
|
||||
assert((void*)zc->hufCTable == zc->workSpace);
|
||||
assert((char*)zc->offcodeCTable == (char*)zc->hufCTable + hufCTable_size);
|
||||
assert((char*)zc->matchlengthCTable == (char*)zc->offcodeCTable + offcodeCTable_size);
|
||||
assert((char*)zc->litlengthCTable == (char*)zc->matchlengthCTable + matchlengthCTable_size);
|
||||
assert((char*)zc->entropyScratchSpace == (char*)zc->litlengthCTable + litlengthCTable_size);
|
||||
ptr = (char*)zc->entropyScratchSpace + entropyScratchSpace_size;
|
||||
|
||||
/* opt parser space */
|
||||
if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
|
||||
DEBUGLOG(5, "reserving optimal parser space ");
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
||||
zc->seqStore.litFreq = (U32*)ptr;
|
||||
zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
|
||||
zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
|
||||
@@ -315,8 +408,17 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
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;
|
||||
}
|
||||
|
||||
/* table Space */
|
||||
if (crp!=ZSTDcrp_noMemset) memset(ptr, 0, tableSpace); /* reset tables only */
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
||||
zc->hashTable = (U32*)(ptr);
|
||||
zc->chainTable = zc->hashTable + hSize;
|
||||
zc->hashTable3 = zc->chainTable + chainSize;
|
||||
ptr = zc->hashTable3 + h3Size;
|
||||
|
||||
/* sequences storage */
|
||||
zc->seqStore.sequencesStart = (seqDef*)ptr;
|
||||
ptr = zc->seqStore.sequencesStart + maxNbSeq;
|
||||
zc->seqStore.llCode = (BYTE*) ptr;
|
||||
@@ -324,10 +426,6 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -341,27 +439,33 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
|
||||
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);
|
||||
|
||||
/*! ZSTD_copyCCtx_internal() :
|
||||
* 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()).
|
||||
* pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
|
||||
ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_copyCCtx_internal \n");
|
||||
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);
|
||||
params.fParams = fParams;
|
||||
DEBUGLOG(5, "ZSTD_resetCCtx_internal : dictIDFlag : %u \n", !fParams.noDictIDFlag);
|
||||
ZSTD_resetCCtx_internal(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 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);
|
||||
assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize); /* chainTable must follow hashTable */
|
||||
assert((U32*)dstCCtx->hashTable3 == (U32*)dstCCtx->chainTable + chainSize);
|
||||
memcpy(dstCCtx->hashTable, srcCCtx->hashTable, tableSpace); /* presumes all tables follow each other */
|
||||
}
|
||||
|
||||
/* copy dictionary offsets */
|
||||
@@ -376,23 +480,36 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
|
||||
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));
|
||||
dstCCtx->fseCTables_ready = srcCCtx->fseCTables_ready;
|
||||
if (srcCCtx->fseCTables_ready) {
|
||||
memcpy(dstCCtx->litlengthCTable, srcCCtx->litlengthCTable, litlengthCTable_size);
|
||||
memcpy(dstCCtx->matchlengthCTable, srcCCtx->matchlengthCTable, matchlengthCTable_size);
|
||||
memcpy(dstCCtx->offcodeCTable, srcCCtx->offcodeCTable, offcodeCTable_size);
|
||||
}
|
||||
if (srcCCtx->flagStaticHufTable) {
|
||||
memcpy(dstCCtx->hufTable, srcCCtx->hufTable, 256*4);
|
||||
dstCCtx->hufCTable_repeatMode = srcCCtx->hufCTable_repeatMode;
|
||||
if (srcCCtx->hufCTable_repeatMode) {
|
||||
memcpy(dstCCtx->hufCTable, srcCCtx->hufCTable, hufCTable_size);
|
||||
}
|
||||
|
||||
return 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()).
|
||||
* pledgedSrcSize==0 means "unknown".
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
||||
fParams.contentSizeFlag = pledgedSrcSize>0;
|
||||
|
||||
return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize);
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_reduceTable() :
|
||||
* reduce table indexes by `reducerValue` */
|
||||
* reduce table indexes by `reducerValue` */
|
||||
static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
|
||||
{
|
||||
U32 u;
|
||||
@@ -499,26 +616,28 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
|
||||
|
||||
/* small ? don't even attempt compression (speed opt) */
|
||||
# define LITERAL_NOENTROPY 63
|
||||
{ size_t const minLitSize = zc->flagStaticHufTable == HUF_repeat_valid ? 6 : LITERAL_NOENTROPY;
|
||||
{ size_t const minLitSize = zc->hufCTable_repeatMode == 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;
|
||||
{ HUF_repeat repeat = zc->hufCTable_repeatMode;
|
||||
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);
|
||||
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
||||
zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &repeat, preferRepeat)
|
||||
: HUF_compress4X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
||||
zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &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 */
|
||||
else { zc->hufCTable_repeatMode = HUF_repeat_check; } /* now have a table to reuse */
|
||||
}
|
||||
|
||||
if ((cLitSize==0) | (cLitSize >= srcSize - minGain)) {
|
||||
zc->flagStaticHufTable = HUF_repeat_none;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
if (cLitSize==1) {
|
||||
zc->flagStaticHufTable = HUF_repeat_none;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
@@ -637,12 +756,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
|
||||
/* CTable for Literal Lengths */
|
||||
{ U32 max = MaxLL;
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, zc->tmpCounters);
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, llCodeTable, nbSeq, zc->entropyScratchSpace);
|
||||
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)) {
|
||||
} else if ((zc->fseCTables_ready) && (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));
|
||||
@@ -653,7 +772,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
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);
|
||||
if (FSE_isError(NCountSize)) return NCountSize;
|
||||
op += NCountSize; }
|
||||
FSE_buildCTable_wksp(CTable_LitLength, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
|
||||
LLtype = set_compressed;
|
||||
@@ -661,12 +780,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
|
||||
/* CTable for Offsets */
|
||||
{ U32 max = MaxOff;
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, zc->tmpCounters);
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, ofCodeTable, nbSeq, zc->entropyScratchSpace);
|
||||
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)) {
|
||||
} else if ((zc->fseCTables_ready) && (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));
|
||||
@@ -677,7 +796,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
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);
|
||||
if (FSE_isError(NCountSize)) return NCountSize;
|
||||
op += NCountSize; }
|
||||
FSE_buildCTable_wksp(CTable_OffsetBits, norm, max, tableLog, scratchBuffer, sizeof(scratchBuffer));
|
||||
Offtype = set_compressed;
|
||||
@@ -685,12 +804,12 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
|
||||
/* CTable for MatchLengths */
|
||||
{ U32 max = MaxML;
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, zc->tmpCounters);
|
||||
size_t const mostFrequent = FSE_countFast_wksp(count, &max, mlCodeTable, nbSeq, zc->entropyScratchSpace);
|
||||
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)) {
|
||||
} else if ((zc->fseCTables_ready) && (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));
|
||||
@@ -701,14 +820,14 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
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);
|
||||
if (FSE_isError(NCountSize)) return NCountSize;
|
||||
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;
|
||||
zc->fseCTables_ready = 0;
|
||||
|
||||
/* Encoding Sequences */
|
||||
{ BIT_CStream_t blockStream;
|
||||
@@ -787,7 +906,7 @@ _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;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
return 0;
|
||||
} }
|
||||
|
||||
@@ -816,7 +935,7 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
|
||||
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",
|
||||
DEBUGLOG(5, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
||||
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||
}
|
||||
#endif
|
||||
@@ -825,14 +944,20 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const v
|
||||
seqStorePtr->lit += litLength;
|
||||
|
||||
/* literal Length */
|
||||
if (litLength>0xFFFF) { seqStorePtr->longLengthID = 1; seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart); }
|
||||
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); }
|
||||
if (matchCode>0xFFFF) {
|
||||
seqStorePtr->longLengthID = 2;
|
||||
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
}
|
||||
seqStorePtr->sequences[0].matchLength = (U16)matchCode;
|
||||
|
||||
seqStorePtr->sequences++;
|
||||
@@ -853,7 +978,14 @@ static unsigned ZSTD_NbCommonBytes (register size_t val)
|
||||
# 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 };
|
||||
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 */
|
||||
@@ -864,7 +996,10 @@ static unsigned ZSTD_NbCommonBytes (register size_t val)
|
||||
# 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 };
|
||||
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
|
||||
}
|
||||
@@ -936,7 +1071,7 @@ static size_t ZSTD_count_2segments(const BYTE* ip, const BYTE* match, const BYTE
|
||||
***************************************/
|
||||
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 */
|
||||
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) ; }
|
||||
@@ -1085,7 +1220,7 @@ static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
|
||||
case 5 :
|
||||
@@ -1135,7 +1270,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, lowPrefixPtr) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
} else {
|
||||
@@ -1147,7 +1282,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
{ 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;
|
||||
mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, lowPrefixPtr) + 4;
|
||||
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
|
||||
offset = current - matchIndex;
|
||||
offset_2 = offset_1;
|
||||
@@ -1171,7 +1306,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
|
||||
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;
|
||||
@@ -1199,7 +1334,7 @@ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
|
||||
U32 const mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4); return;
|
||||
case 5 :
|
||||
@@ -1274,7 +1409,9 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
||||
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 */
|
||||
assert(offset_1 <= current); /* supposed guaranteed by construction */
|
||||
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
|
||||
/* favor repcode */
|
||||
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
ip++;
|
||||
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mLength-MINMATCH);
|
||||
@@ -1285,15 +1422,15 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
||||
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;
|
||||
size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
|
||||
U32 const matchIndexL3 = hashLong[hl3];
|
||||
const BYTE* matchL3 = base + matchIndexL3;
|
||||
hashLong[hl3] = current + 1;
|
||||
if ( (matchIndexL3 > lowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1)) ) {
|
||||
mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;
|
||||
ip++;
|
||||
offset = (U32)(ip-match3);
|
||||
while (((ip>anchor) & (match3>lowest)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */
|
||||
offset = (U32)(ip-matchL3);
|
||||
while (((ip>anchor) & (matchL3>lowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
|
||||
} else {
|
||||
mLength = ZSTD_count(ip+4, match+4, iend) + 4;
|
||||
offset = (U32)(ip-match);
|
||||
@@ -1353,7 +1490,7 @@ static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
ZSTD_compressBlock_doubleFast_generic(ctx, src, srcSize, 4); return;
|
||||
case 5 :
|
||||
@@ -1474,7 +1611,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, lowPrefixPtr) + 4;
|
||||
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;
|
||||
@@ -1503,7 +1640,7 @@ static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
|
||||
U32 const mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
default: /* includes case 3 */
|
||||
case 4 :
|
||||
ZSTD_compressBlock_doubleFast_extDict_generic(ctx, src, srcSize, 4); return;
|
||||
case 5 :
|
||||
@@ -1733,9 +1870,10 @@ static size_t ZSTD_BtFindBestMatch_selectMLS (
|
||||
{
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
default :
|
||||
default : /* includes case 3 */
|
||||
case 4 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 4);
|
||||
case 5 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 5);
|
||||
case 7 :
|
||||
case 6 : return ZSTD_BtFindBestMatch(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
|
||||
}
|
||||
}
|
||||
@@ -1772,9 +1910,10 @@ static size_t ZSTD_BtFindBestMatch_selectMLS_extDict (
|
||||
{
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
default :
|
||||
default : /* includes case 3 */
|
||||
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 7 :
|
||||
case 6 : return ZSTD_BtFindBestMatch_extDict(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6);
|
||||
}
|
||||
}
|
||||
@@ -1831,7 +1970,7 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
const U32 current = (U32)(ip-base);
|
||||
const U32 minChain = current > chainSize ? current - chainSize : 0;
|
||||
int nbAttempts=maxNbAttempts;
|
||||
size_t ml=EQUAL_READ32-1;
|
||||
size_t ml=4-1;
|
||||
|
||||
/* HC4 match finder */
|
||||
U32 matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
|
||||
@@ -1846,11 +1985,15 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
} 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;
|
||||
currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;
|
||||
}
|
||||
|
||||
/* 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 (currentMl > ml) {
|
||||
ml = currentMl;
|
||||
*offsetPtr = current - matchIndex + ZSTD_REP_MOVE;
|
||||
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
|
||||
}
|
||||
|
||||
if (matchIndex <= minChain) break;
|
||||
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
|
||||
@@ -1868,9 +2011,10 @@ FORCE_INLINE size_t ZSTD_HcFindBestMatch_selectMLS (
|
||||
{
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
default :
|
||||
default : /* includes case 3 */
|
||||
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 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 0);
|
||||
}
|
||||
}
|
||||
@@ -1884,9 +2028,10 @@ FORCE_INLINE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
||||
{
|
||||
switch(matchLengthSearch)
|
||||
{
|
||||
default :
|
||||
default : /* includes case 3 */
|
||||
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 7 :
|
||||
case 6 : return ZSTD_HcFindBestMatch_generic(zc, ip, iLimit, offsetPtr, maxNbAttempts, 6, 1);
|
||||
}
|
||||
}
|
||||
@@ -1934,7 +2079,7 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
/* 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;
|
||||
matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
|
||||
if (depth==0) goto _storeSequence;
|
||||
}
|
||||
|
||||
@@ -1945,7 +2090,7 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
matchLength = ml2, start = ip, offset=offsetFound;
|
||||
}
|
||||
|
||||
if (matchLength < EQUAL_READ32) {
|
||||
if (matchLength < 4) {
|
||||
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
|
||||
continue;
|
||||
}
|
||||
@@ -1955,17 +2100,17 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
||||
int const gain2 = (int)(mlRep * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
if ((mlRep >= EQUAL_READ32) && (gain2 > gain1))
|
||||
if ((mlRep >= 4) && (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)) {
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
continue; /* search a better one */
|
||||
} }
|
||||
@@ -1974,17 +2119,17 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
size_t const ml2 = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
|
||||
int const gain2 = (int)(ml2 * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
if ((ml2 >= EQUAL_READ32) && (gain2 > gain1))
|
||||
if ((ml2 >= 4) && (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)) {
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
continue;
|
||||
} } }
|
||||
@@ -1993,7 +2138,9 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
|
||||
/* 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 */
|
||||
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);
|
||||
}
|
||||
@@ -2010,7 +2157,7 @@ _storeSequence:
|
||||
&& ((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;
|
||||
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
|
||||
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
|
||||
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
|
||||
ip += matchLength;
|
||||
@@ -2099,7 +2246,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
if (depth==0) goto _storeSequence;
|
||||
} }
|
||||
|
||||
@@ -2110,7 +2257,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
matchLength = ml2, start = ip, offset=offsetFound;
|
||||
}
|
||||
|
||||
if (matchLength < EQUAL_READ32) {
|
||||
if (matchLength < 4) {
|
||||
ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
|
||||
continue;
|
||||
}
|
||||
@@ -2129,10 +2276,10 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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;
|
||||
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
int const gain2 = (int)(repLength * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
if ((repLength >= EQUAL_READ32) && (gain2 > gain1))
|
||||
if ((repLength >= 4) && (gain2 > gain1))
|
||||
matchLength = repLength, offset = 0, start = ip;
|
||||
} }
|
||||
|
||||
@@ -2141,7 +2288,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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)) {
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
continue; /* search a better one */
|
||||
} }
|
||||
@@ -2159,10 +2306,10 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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))
|
||||
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
int const gain2 = (int)(repLength * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
|
||||
if ((repLength >= 4) && (gain2 > gain1))
|
||||
matchLength = repLength, offset = 0, start = ip;
|
||||
} }
|
||||
|
||||
@@ -2171,7 +2318,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
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)) {
|
||||
if ((ml2 >= 4) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2, start = ip;
|
||||
continue;
|
||||
} } }
|
||||
@@ -2203,7 +2350,7 @@ _storeSequence:
|
||||
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;
|
||||
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
|
||||
offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
|
||||
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, matchLength-MINMATCH);
|
||||
ip += matchLength;
|
||||
@@ -2294,8 +2441,12 @@ typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t sr
|
||||
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_btultra },
|
||||
{ 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_btultra_extDict }
|
||||
{ ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
|
||||
ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
|
||||
ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra },
|
||||
{ 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_btultra_extDict }
|
||||
};
|
||||
|
||||
return blockCompressor[extDict][(U32)strat];
|
||||
@@ -2311,7 +2462,7 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCa
|
||||
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 */
|
||||
zc->nextToUpdate = current - MIN(192, (U32)(current - zc->nextToUpdate - 384)); /* limited update after finding a very long match */
|
||||
blockCompressor(zc, src, srcSize);
|
||||
return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
|
||||
}
|
||||
@@ -2343,7 +2494,8 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
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 (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 */
|
||||
@@ -2398,7 +2550,8 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
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 dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536); /* 0-3 */
|
||||
U32 const dictIDSizeCode = params.fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength; /* 0-3 */
|
||||
U32 const checksumFlag = params.fParams.checksumFlag>0;
|
||||
U32 const windowSize = 1U << params.cParams.windowLog;
|
||||
U32 const singleSegment = params.fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);
|
||||
@@ -2410,6 +2563,8 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
size_t pos;
|
||||
|
||||
if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
|
||||
DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u \n",
|
||||
!params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
|
||||
|
||||
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||
op[4] = frameHeaderDecriptionByte; pos=5;
|
||||
@@ -2478,6 +2633,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
||||
ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
||||
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
cctx->consumedSrcSize += srcSize;
|
||||
return cSize + fhSize;
|
||||
} else
|
||||
return fhSize;
|
||||
@@ -2488,7 +2644,7 @@ 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);
|
||||
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);
|
||||
}
|
||||
|
||||
|
||||
@@ -2501,10 +2657,12 @@ size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const
|
||||
{
|
||||
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);
|
||||
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_loadDictionaryContent() :
|
||||
* @return : 0, or an error code
|
||||
*/
|
||||
static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
{
|
||||
const BYTE* const ip = (const BYTE*) src;
|
||||
@@ -2534,13 +2692,15 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
||||
case ZSTD_greedy:
|
||||
case ZSTD_lazy:
|
||||
case ZSTD_lazy2:
|
||||
ZSTD_insertAndFindFirstIndex (zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_btlazy2:
|
||||
case ZSTD_btopt:
|
||||
case ZSTD_btultra:
|
||||
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2567,18 +2727,15 @@ static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSym
|
||||
|
||||
|
||||
/* 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)
|
||||
* See :
|
||||
* https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format
|
||||
*/
|
||||
/*! ZSTD_loadZstdDictionary() :
|
||||
* @return : 0, or an error code
|
||||
* assumptions : magic number supposed already checked
|
||||
* dictSize supposed > 8
|
||||
*/
|
||||
static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
const BYTE* dictPtr = (const BYTE*)dict;
|
||||
const BYTE* const dictEnd = dictPtr + dictSize;
|
||||
@@ -2586,7 +2743,11 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
|
||||
unsigned offcodeMaxValue = MaxOff;
|
||||
BYTE scratchBuffer[1<<MAX(MLFSELog,LLFSELog)];
|
||||
|
||||
{ size_t const hufHeaderSize = HUF_readCTable(cctx->hufTable, 255, dict, dictSize);
|
||||
dictPtr += 4; /* skip magic number */
|
||||
cctx->dictID = cctx->params.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
|
||||
dictPtr += 4;
|
||||
|
||||
{ size_t const hufHeaderSize = HUF_readCTable(cctx->hufCTable, 255, dictPtr, dictEnd-dictPtr);
|
||||
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
dictPtr += hufHeaderSize;
|
||||
}
|
||||
@@ -2596,7 +2757,8 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
|
||||
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);
|
||||
CHECK_E( FSE_buildCTable_wksp(cctx->offcodeCTable, offcodeNCount, offcodeMaxValue, offcodeLog, scratchBuffer, sizeof(scratchBuffer)),
|
||||
dictionary_corrupted);
|
||||
dictPtr += offcodeHeaderSize;
|
||||
}
|
||||
|
||||
@@ -2606,8 +2768,9 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
|
||||
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);
|
||||
CHECK_F( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML));
|
||||
CHECK_E( FSE_buildCTable_wksp(cctx->matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, scratchBuffer, sizeof(scratchBuffer)),
|
||||
dictionary_corrupted);
|
||||
dictPtr += matchlengthHeaderSize;
|
||||
}
|
||||
|
||||
@@ -2617,49 +2780,51 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* cctx, const void* dict, size_
|
||||
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);
|
||||
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);
|
||||
cctx->rep[0] = MEM_readLE32(dictPtr+0);
|
||||
cctx->rep[1] = MEM_readLE32(dictPtr+4);
|
||||
cctx->rep[2] = MEM_readLE32(dictPtr+8);
|
||||
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);
|
||||
{ size_t const dictContentSize = (size_t)(dictEnd - dictPtr);
|
||||
U32 offcodeMax = MaxOff;
|
||||
if (dictContentSize <= ((U32)-1) - 128 KB) {
|
||||
U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */
|
||||
offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */
|
||||
}
|
||||
/* Every possible supported offset <= dictContentSize + 128 KB must be representable */
|
||||
/* All offset values <= dictContentSize + 128 KB must be representable */
|
||||
CHECK_F (ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)));
|
||||
}
|
||||
/* All repCodes must be <= dictContentSize and != 0*/
|
||||
{ U32 u;
|
||||
for (u=0; u<3; u++) {
|
||||
if (cctx->rep[u] == 0) return ERROR(dictionary_corrupted);
|
||||
if (cctx->rep[u] > dictContentSize) return ERROR(dictionary_corrupted);
|
||||
} }
|
||||
|
||||
cctx->flagStaticTables = 1;
|
||||
cctx->flagStaticHufTable = HUF_repeat_valid;
|
||||
return dictPtr - (const BYTE*)dict;
|
||||
cctx->fseCTables_ready = 1;
|
||||
cctx->hufCTable_repeatMode = HUF_repeat_valid;
|
||||
return ZSTD_loadDictionaryContent(cctx, dictPtr, dictContentSize);
|
||||
}
|
||||
}
|
||||
|
||||
/** ZSTD_compress_insertDictionary() :
|
||||
* @return : 0, or an error code */
|
||||
static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, size_t dictSize)
|
||||
static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx, 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);
|
||||
if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (cctx->forceRawDict))
|
||||
return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
/* dict as zstd dictionary */
|
||||
return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
|
||||
}
|
||||
|
||||
/*! ZSTD_compressBegin_internal() :
|
||||
@@ -2669,7 +2834,8 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
{
|
||||
ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue;
|
||||
CHECK_F(ZSTD_resetCCtx_advanced(cctx, params, pledgedSrcSize, crp));
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
CHECK_F(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, crp));
|
||||
return ZSTD_compress_insertDictionary(cctx, dict, dictSize);
|
||||
}
|
||||
|
||||
@@ -2708,6 +2874,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
BYTE* op = ostart;
|
||||
size_t fhSize = 0;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_writeEpilogue \n");
|
||||
if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
|
||||
|
||||
/* special case : empty frame */
|
||||
@@ -2745,10 +2912,15 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t endResult;
|
||||
size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1, 1);
|
||||
size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize,
|
||||
1 /* frame mode */, 1 /* last chunk */);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
||||
if (ZSTD_isError(endResult)) return endResult;
|
||||
if (cctx->params.fParams.contentSizeFlag) { /* control src size */
|
||||
if (cctx->frameContentSize != cctx->consumedSrcSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
return cSize + endResult;
|
||||
}
|
||||
|
||||
@@ -2773,7 +2945,8 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
||||
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)
|
||||
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;
|
||||
@@ -2806,14 +2979,30 @@ struct ZSTD_CDict_s {
|
||||
ZSTD_CCtx* refContext;
|
||||
}; /* typedef'd tp ZSTD_CDict within "zstd.h" */
|
||||
|
||||
/*! ZSTD_estimateCDictSize() :
|
||||
* Estimate amount of memory that will be needed to create a dictionary with following arguments */
|
||||
size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize)
|
||||
{
|
||||
cParams = ZSTD_adjustCParams(cParams, 0, dictSize);
|
||||
return sizeof(ZSTD_CDict) + dictSize + ZSTD_estimateCCtxSize(cParams);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_frameParameters fParams)
|
||||
{
|
||||
ZSTD_parameters params;
|
||||
params.cParams = cParams;
|
||||
params.fParams = fParams;
|
||||
return params;
|
||||
}
|
||||
|
||||
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
|
||||
ZSTD_parameters params, ZSTD_customMem customMem)
|
||||
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
|
||||
{
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
@@ -2838,7 +3027,9 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
|
||||
cdict->dictContent = internalBuffer;
|
||||
}
|
||||
|
||||
{ size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
|
||||
{ ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
|
||||
ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
|
||||
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);
|
||||
@@ -2855,17 +3046,15 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
|
||||
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_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize, 0, cParams, 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);
|
||||
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize, 1, cParams, allocator);
|
||||
}
|
||||
|
||||
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
||||
@@ -2883,34 +3072,55 @@ 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)
|
||||
/* ZSTD_compressBegin_usingCDict_advanced() :
|
||||
* cdict must be != NULL */
|
||||
size_t ZSTD_compressBegin_usingCDict_advanced(
|
||||
ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
|
||||
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
||||
{
|
||||
if (cdict->dictContentSize) CHECK_F(ZSTD_copyCCtx(cctx, cdict->refContext, pledgedSrcSize))
|
||||
if (cdict==NULL) return ERROR(GENERIC); /* does not support NULL cdict */
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced : dictIDFlag == %u \n", !fParams.noDictIDFlag);
|
||||
if (cdict->dictContentSize)
|
||||
CHECK_F( ZSTD_copyCCtx_internal(cctx, cdict->refContext, fParams, pledgedSrcSize) )
|
||||
else {
|
||||
ZSTD_parameters params = cdict->refContext->params;
|
||||
params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
|
||||
CHECK_F(ZSTD_compressBegin_advanced(cctx, NULL, 0, params, pledgedSrcSize));
|
||||
params.fParams = fParams;
|
||||
CHECK_F(ZSTD_compressBegin_internal(cctx, NULL, 0, params, pledgedSrcSize));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ZSTD_compressBegin_usingCDict() :
|
||||
* pledgedSrcSize=0 means "unknown"
|
||||
* if pledgedSrcSize>0, it will enable contentSizeFlag */
|
||||
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u \n", !fParams.noDictIDFlag);
|
||||
return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
|
||||
}
|
||||
|
||||
size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)
|
||||
{
|
||||
CHECK_F (ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, srcSize)); /* will check if cdict != NULL */
|
||||
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
/*! 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 */
|
||||
* Compression using a digested Dictionary.
|
||||
* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
|
||||
* Note that compression parameters are decided at CDict creation time
|
||||
* while frame parameters are hardcoded */
|
||||
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);
|
||||
ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
||||
return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -2919,31 +3129,6 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
* 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);
|
||||
@@ -2951,131 +3136,166 @@ ZSTD_CStream* ZSTD_createCStream(void)
|
||||
|
||||
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;
|
||||
/* CStream and CCtx are now same object */
|
||||
return ZSTD_createCCtx_advanced(customMem);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return ZSTD_freeCCtx(zcs); /* same object */
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
size_t const CCtxSize = ZSTD_estimateCCtxSize(cParams);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
||||
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
||||
size_t const streamingSize = inBuffSize + outBuffSize;
|
||||
|
||||
return CCtxSize + streamingSize;
|
||||
}
|
||||
|
||||
|
||||
/*====== 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)
|
||||
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, ZSTD_parameters params, 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));
|
||||
DEBUGLOG(5, "ZSTD_resetCStream_internal : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
|
||||
|
||||
if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs, zcs->cdict, params.fParams, pledgedSrcSize))
|
||||
else CHECK_F(ZSTD_compressBegin_internal(zcs, NULL, 0, params, pledgedSrcSize));
|
||||
|
||||
zcs->inToCompress = 0;
|
||||
zcs->inBuffPos = 0;
|
||||
zcs->inBuffTarget = zcs->blockSize;
|
||||
zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
|
||||
zcs->stage = zcss_load;
|
||||
zcs->streamStage = 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);
|
||||
ZSTD_parameters params = zcs->params;
|
||||
params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
|
||||
DEBUGLOG(5, "ZSTD_resetCStream : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
|
||||
return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
return ZSTD_resetCStream_internal(zcs, pledgedSrcSize);
|
||||
/* ZSTD_initCStream_internal() :
|
||||
* params are supposed validated at this stage
|
||||
* and zcs->cdict is supposed to be correct */
|
||||
static size_t ZSTD_initCStream_stage2(ZSTD_CStream* zcs,
|
||||
const ZSTD_parameters params,
|
||||
unsigned long long pledgedSrcSize)
|
||||
{
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
|
||||
|
||||
/* allocate buffers */
|
||||
{ size_t const neededInBuffSize = ((size_t)1 << params.cParams.windowLog) + zcs->blockSize;
|
||||
if (zcs->inBuffSize < neededInBuffSize) {
|
||||
zcs->inBuffSize = 0;
|
||||
ZSTD_free(zcs->inBuff, zcs->customMem);
|
||||
zcs->inBuff = (char*)ZSTD_malloc(neededInBuffSize, zcs->customMem);
|
||||
if (zcs->inBuff == NULL) return ERROR(memory_allocation);
|
||||
zcs->inBuffSize = neededInBuffSize;
|
||||
}
|
||||
}
|
||||
if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
|
||||
size_t const outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
|
||||
zcs->outBuffSize = 0;
|
||||
ZSTD_free(zcs->outBuff, zcs->customMem);
|
||||
zcs->outBuff = (char*)ZSTD_malloc(outBuffSize, zcs->customMem);
|
||||
if (zcs->outBuff == NULL) return ERROR(memory_allocation);
|
||||
zcs->outBuffSize = outBuffSize;
|
||||
}
|
||||
|
||||
DEBUGLOG(5, "ZSTD_initCStream_stage2 : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
|
||||
return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
/* ZSTD_initCStream_usingCDict_advanced() :
|
||||
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
|
||||
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams)
|
||||
{
|
||||
if (!cdict) return ERROR(GENERIC); /* cannot handle NULL cdict (does not know what to do) */
|
||||
{ ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
|
||||
params.fParams = fParams;
|
||||
zcs->cdict = cdict;
|
||||
return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* note : cdict must outlive compression session */
|
||||
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_frameParameters const fParams = { 0 /* content */, 0 /* checksum */, 0 /* noDictID */ };
|
||||
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, 0, fParams);
|
||||
}
|
||||
|
||||
static size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
zcs->cdict = NULL;
|
||||
|
||||
if (dict && dictSize >= 8) {
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0 /* copy */, params.cParams, zcs->customMem);
|
||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||
zcs->cdict = zcs->cdictLocal;
|
||||
}
|
||||
|
||||
DEBUGLOG(5, "ZSTD_initCStream_internal : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
|
||||
return ZSTD_initCStream_stage2(zcs, params, 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;
|
||||
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
||||
DEBUGLOG(5, "ZSTD_initCStream_advanced : pledgedSrcSize == %u \n", (U32)pledgedSrcSize);
|
||||
DEBUGLOG(5, "wlog %u \n", params.cParams.windowLog);
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
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);
|
||||
return ZSTD_initCStream_internal(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);
|
||||
params.fParams.contentSizeFlag = (pledgedSrcSize>0);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
||||
{
|
||||
return ZSTD_initCStream_usingDict(zcs, NULL, 0, compressionLevel);
|
||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, params, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
return ZSTD_sizeof_CCtx(zcs); /* same object */
|
||||
}
|
||||
|
||||
/*====== Compression ======*/
|
||||
@@ -3102,8 +3322,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
char* const oend = ostart + *dstCapacityPtr;
|
||||
char* op = ostart;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressStream_generic \n");
|
||||
while (someMoreWork) {
|
||||
switch(zcs->stage)
|
||||
switch(zcs->streamStage)
|
||||
{
|
||||
case zcss_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */
|
||||
|
||||
@@ -3111,12 +3332,14 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
/* complete inBuffer */
|
||||
{ size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
|
||||
size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip);
|
||||
DEBUGLOG(5, "loading %u/%u \n", (U32)loaded, (U32)toLoad);
|
||||
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) */
|
||||
DEBUGLOG(5, "stream compression stage (flush==%u)\n", flush);
|
||||
{ void* cDst;
|
||||
size_t cSize;
|
||||
size_t const iSize = zcs->inBuffPos - zcs->inToCompress;
|
||||
@@ -3126,29 +3349,33 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
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);
|
||||
ZSTD_compressEnd(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) :
|
||||
ZSTD_compressContinue(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
DEBUGLOG(5, "cSize = %u \n", (U32)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->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffTarget == blockSize <= inBuffSize */
|
||||
assert(zcs->inBuffTarget <= zcs->inBuffSize);
|
||||
zcs->inToCompress = zcs->inBuffPos;
|
||||
if (cDst == op) { op += cSize; break; } /* no need to flush */
|
||||
zcs->outBuffContentSize = cSize;
|
||||
zcs->outBuffFlushedSize = 0;
|
||||
zcs->stage = zcss_flush; /* pass-through to flush stage */
|
||||
zcs->streamStage = zcss_flush; /* pass-through to flush stage */
|
||||
}
|
||||
|
||||
case zcss_flush:
|
||||
DEBUGLOG(5, "flush stage \n");
|
||||
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
||||
DEBUGLOG(5, "toFlush: %u ; flushed: %u \n", (U32)toFlush, (U32)flushed);
|
||||
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;
|
||||
zcs->streamStage = zcss_load;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3163,7 +3390,6 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
|
||||
*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;
|
||||
@@ -3208,24 +3434,26 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
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) {
|
||||
DEBUGLOG(5, "ZSTD_endStream (dstCapacity : %u) \n", (U32)(oend-op));
|
||||
if (zcs->streamStage != 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 notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten,
|
||||
&srcSize /* use a valid src address instead of NULL */, &srcSize, zsf_end);
|
||||
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);
|
||||
return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */
|
||||
+ ((zcs->params.fParams.checksumFlag > 0) * 4) /* optional 32-bits checksum */;
|
||||
}
|
||||
/* create epilogue */
|
||||
zcs->stage = zcss_final;
|
||||
zcs->streamStage = zcss_final;
|
||||
zcs->outBuffContentSize = !notEnded ? 0 :
|
||||
ZSTD_compressEnd(zcs->cctx, zcs->outBuff, zcs->outBuffSize, NULL, 0); /* write epilogue, including final empty block, into outBuff */
|
||||
/* write epilogue, including final empty block, into outBuff */
|
||||
ZSTD_compressEnd(zcs, zcs->outBuff, zcs->outBuffSize, NULL, 0);
|
||||
if (ZSTD_isError(zcs->outBuffContentSize)) return zcs->outBuffContentSize;
|
||||
}
|
||||
|
||||
/* flush epilogue */
|
||||
@@ -3234,7 +3462,7 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
op += flushed;
|
||||
zcs->outBuffFlushedSize += flushed;
|
||||
output->pos += op-ostart;
|
||||
if (toFlush==flushed) zcs->stage = zcss_init; /* end reached */
|
||||
if (toFlush==flushed) zcs->streamStage = zcss_init; /* end reached */
|
||||
return toFlush - flushed;
|
||||
}
|
||||
}
|
||||
@@ -3268,7 +3496,7 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
||||
{ 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, 22, 22, 5, 4, 32, ZSTD_btopt }, /* level 18 */
|
||||
{ 23, 23, 22, 6, 3, 48, ZSTD_btopt }, /* level 19 */
|
||||
{ 25, 25, 23, 7, 3, 64, ZSTD_btultra }, /* level 20 */
|
||||
{ 26, 26, 23, 7, 3,256, ZSTD_btultra }, /* level 21 */
|
||||
|
||||
@@ -360,6 +360,7 @@ static U32 ZSTD_BtGetAllMatches_selectMLS (
|
||||
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 7 :
|
||||
case 6 : return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
|
||||
}
|
||||
}
|
||||
@@ -387,6 +388,7 @@ static U32 ZSTD_BtGetAllMatches_selectMLS_extDict (
|
||||
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 7 :
|
||||
case 6 : return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
# include <stdio.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/times.h>
|
||||
static unsigned g_debugLevel = 3;
|
||||
static unsigned g_debugLevel = 5;
|
||||
# define DEBUGLOGRAW(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __VA_ARGS__); }
|
||||
# define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
|
||||
|
||||
@@ -44,26 +44,26 @@
|
||||
DEBUGLOGRAW(l, " \n"); \
|
||||
}
|
||||
|
||||
static unsigned long long GetCurrentClockTimeMicroseconds()
|
||||
static unsigned long long GetCurrentClockTimeMicroseconds(void)
|
||||
{
|
||||
static clock_t _ticksPerSecond = 0;
|
||||
if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);
|
||||
|
||||
struct tms junk; clock_t newTicks = (clock_t) times(&junk);
|
||||
return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);
|
||||
{ struct tms junk; clock_t newTicks = (clock_t) times(&junk);
|
||||
return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond); }
|
||||
}
|
||||
|
||||
#define MUTEX_WAIT_TIME_DLEVEL 5
|
||||
#define PTHREAD_MUTEX_LOCK(mutex) \
|
||||
if (g_debugLevel>=MUTEX_WAIT_TIME_DLEVEL) { \
|
||||
unsigned long long beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
pthread_mutex_lock(mutex); \
|
||||
unsigned long long afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
pthread_mutex_lock(mutex); \
|
||||
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long const elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
elapsedTime, #mutex); \
|
||||
} \
|
||||
} } \
|
||||
} else pthread_mutex_lock(mutex);
|
||||
|
||||
#else
|
||||
@@ -228,17 +228,19 @@ void ZSTDMT_compressChunk(void* jobDescription)
|
||||
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
|
||||
const void* const src = (const char*)job->srcStart + job->dictSize;
|
||||
buffer_t const dstBuff = job->dstBuff;
|
||||
DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u", job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
|
||||
DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u",
|
||||
job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
|
||||
if (job->cdict) { /* should only happen for first segment */
|
||||
size_t const initError = ZSTD_compressBegin_usingCDict(job->cctx, job->cdict, job->fullFrameSize);
|
||||
size_t const initError = ZSTD_compressBegin_usingCDict_advanced(job->cctx, job->cdict, job->params.fParams, job->fullFrameSize);
|
||||
if (job->cdict) DEBUGLOG(3, "using CDict ");
|
||||
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
|
||||
} else { /* srcStart points at reloaded section */
|
||||
size_t const dictModeError = ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceRawDict, 1); /* Force loading dictionary in "content-only" mode (no header analysis) */
|
||||
size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, 0);
|
||||
if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
|
||||
ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
|
||||
}
|
||||
if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0; /* ensure no srcSize control */
|
||||
{ size_t const dictModeError = ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceRawDict, 1); /* Force loading dictionary in "content-only" mode (no header analysis) */
|
||||
size_t const initError = ZSTD_compressBegin_advanced(job->cctx, job->srcStart, job->dictSize, job->params, job->fullFrameSize);
|
||||
if (ZSTD_isError(initError) || ZSTD_isError(dictModeError)) { job->cSize = initError; goto _endJob; }
|
||||
ZSTD_setCCtxParameter(job->cctx, ZSTD_p_forceWindow, 1);
|
||||
} }
|
||||
if (!job->firstChunk) { /* flush and overwrite frame header when it's not first segment */
|
||||
size_t const hSize = ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, 0);
|
||||
if (ZSTD_isError(hSize)) { job->cSize = hSize; goto _endJob; }
|
||||
@@ -250,7 +252,9 @@ void ZSTDMT_compressChunk(void* jobDescription)
|
||||
job->cSize = (job->lastChunk) ?
|
||||
ZSTD_compressEnd (job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
|
||||
ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
|
||||
DEBUGLOG(3, "compressed %u bytes into %u bytes (first:%u) (last:%u)", (unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
|
||||
DEBUGLOG(3, "compressed %u bytes into %u bytes (first:%u) (last:%u)",
|
||||
(unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
|
||||
DEBUGLOG(5, "dstBuff.size : %u ; => %s", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
|
||||
|
||||
_endJob:
|
||||
PTHREAD_MUTEX_LOCK(job->jobCompleted_mutex);
|
||||
@@ -388,14 +392,17 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
|
||||
U32 const overlapLog = (compressionLevel >= ZSTD_maxCLevel()) ? 0 : 3;
|
||||
size_t const overlapSize = (size_t)1 << (params.cParams.windowLog - overlapLog);
|
||||
size_t const chunkTargetSize = (size_t)1 << (params.cParams.windowLog + 2);
|
||||
unsigned const nbChunksMax = (unsigned)(srcSize / chunkTargetSize) + (srcSize < chunkTargetSize) /* min 1 */;
|
||||
unsigned const nbChunksMax = (unsigned)(srcSize / chunkTargetSize) + 1;
|
||||
unsigned nbChunks = MIN(nbChunksMax, mtctx->nbThreads);
|
||||
size_t const proposedChunkSize = (srcSize + (nbChunks-1)) / nbChunks;
|
||||
size_t const avgChunkSize = ((proposedChunkSize & 0x1FFFF) < 0xFFFF) ? proposedChunkSize + 0xFFFF : proposedChunkSize; /* avoid too small last block */
|
||||
size_t remainingSrcSize = srcSize;
|
||||
const char* const srcStart = (const char*)src;
|
||||
size_t frameStartPos = 0;
|
||||
unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
|
||||
size_t frameStartPos = 0, dstBufferPos = 0;
|
||||
|
||||
DEBUGLOG(3, "windowLog : %2u => chunkTargetSize : %u bytes ", params.cParams.windowLog, (U32)chunkTargetSize);
|
||||
DEBUGLOG(2, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
|
||||
@@ -409,10 +416,11 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
{ unsigned u;
|
||||
for (u=0; u<nbChunks; u++) {
|
||||
size_t const chunkSize = MIN(remainingSrcSize, avgChunkSize);
|
||||
size_t const dstBufferCapacity = u ? ZSTD_compressBound(chunkSize) : dstCapacity;
|
||||
buffer_t const dstAsBuffer = { dst, dstCapacity };
|
||||
buffer_t const dstBuffer = u ? ZSTDMT_getBuffer(mtctx->buffPool, dstBufferCapacity) : dstAsBuffer;
|
||||
size_t const dstBufferCapacity = ZSTD_compressBound(chunkSize);
|
||||
buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
|
||||
buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : ZSTDMT_getBuffer(mtctx->buffPool, dstBufferCapacity);
|
||||
ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(mtctx->cctxPool);
|
||||
size_t dictSize = u ? overlapSize : 0;
|
||||
|
||||
if ((cctx==NULL) || (dstBuffer.start==NULL)) {
|
||||
mtctx->jobs[u].cSize = ERROR(memory_allocation); /* job result */
|
||||
@@ -421,7 +429,8 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
break; /* let's wait for previous jobs to complete, but don't start new ones */
|
||||
}
|
||||
|
||||
mtctx->jobs[u].srcStart = srcStart + frameStartPos;
|
||||
mtctx->jobs[u].srcStart = srcStart + frameStartPos - dictSize;
|
||||
mtctx->jobs[u].dictSize = dictSize;
|
||||
mtctx->jobs[u].srcSize = chunkSize;
|
||||
mtctx->jobs[u].fullFrameSize = srcSize;
|
||||
mtctx->jobs[u].params = params;
|
||||
@@ -438,6 +447,7 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
|
||||
|
||||
frameStartPos += chunkSize;
|
||||
dstBufferPos += dstBufferCapacity;
|
||||
remainingSrcSize -= chunkSize;
|
||||
} }
|
||||
/* note : since nbChunks <= nbThreads, all jobs should be running immediately in parallel */
|
||||
@@ -461,8 +471,10 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
if (ZSTD_isError(cSize)) error = cSize;
|
||||
if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
|
||||
if (chunkID) { /* note : chunk 0 is already written directly into dst */
|
||||
if (!error) memcpy((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize);
|
||||
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[chunkID].dstBuff);
|
||||
if (!error)
|
||||
memmove((char*)dst + dstPos, mtctx->jobs[chunkID].dstBuff.start, cSize); /* may overlap if chunk decompressed within dst */
|
||||
if (chunkID >= compressWithinDst) /* otherwise, it decompresses within dst */
|
||||
ZSTDMT_releaseBuffer(mtctx->buffPool, mtctx->jobs[chunkID].dstBuff);
|
||||
mtctx->jobs[chunkID].dstBuff = g_nullBuffer;
|
||||
}
|
||||
dstPos += cSize ;
|
||||
@@ -509,7 +521,7 @@ static size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||
if (updateDict) {
|
||||
ZSTD_freeCDict(zcs->cdict); zcs->cdict = NULL;
|
||||
if (dict && dictSize) {
|
||||
zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params, cmem);
|
||||
zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params.cParams, cmem);
|
||||
if (zcs->cdict == NULL) return ERROR(memory_allocation);
|
||||
} }
|
||||
zcs->frameContentSize = pledgedSrcSize;
|
||||
|
||||
+159
-246
@@ -105,7 +105,7 @@ struct ZSTD_DCtx_s
|
||||
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;
|
||||
ZSTD_frameHeader fParams;
|
||||
blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
|
||||
ZSTD_dStage stage;
|
||||
U32 litEntropy;
|
||||
@@ -177,30 +177,6 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
||||
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);
|
||||
|
||||
|
||||
@@ -243,22 +219,23 @@ static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
|
||||
}
|
||||
|
||||
|
||||
/** ZSTD_getFrameParams() :
|
||||
/** ZSTD_getFrameHeader() :
|
||||
* decode Frame Header, or require larger `srcSize`.
|
||||
* @return : 0, `fparamsPtr` is correctly filled,
|
||||
* @return : 0, `zfhPtr` 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)
|
||||
size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, 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) {
|
||||
/* skippable frame */
|
||||
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 */
|
||||
memset(zfhPtr, 0, sizeof(*zfhPtr));
|
||||
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
|
||||
zfhPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
|
||||
return 0;
|
||||
}
|
||||
return ERROR(prefix_unknown);
|
||||
@@ -305,10 +282,10 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
||||
}
|
||||
if (!windowSize) windowSize = (U32)frameContentSize;
|
||||
if (windowSize > windowSizeMax) return ERROR(frameParameter_windowTooLarge);
|
||||
fparamsPtr->frameContentSize = frameContentSize;
|
||||
fparamsPtr->windowSize = windowSize;
|
||||
fparamsPtr->dictID = dictID;
|
||||
fparamsPtr->checksumFlag = checksumFlag;
|
||||
zfhPtr->frameContentSize = frameContentSize;
|
||||
zfhPtr->windowSize = windowSize;
|
||||
zfhPtr->dictID = dictID;
|
||||
zfhPtr->checksumFlag = checksumFlag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -320,15 +297,14 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
||||
* - 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 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;
|
||||
{ ZSTD_frameHeader fParams;
|
||||
if (ZSTD_getFrameHeader(&fParams, src, srcSize) != 0) return ZSTD_CONTENTSIZE_ERROR;
|
||||
if (fParams.windowSize == 0) {
|
||||
/* Either skippable or empty frame, size == 0 either way */
|
||||
return 0;
|
||||
@@ -413,7 +389,7 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
||||
* @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);
|
||||
size_t const result = ZSTD_getFrameHeader(&(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);
|
||||
@@ -431,7 +407,8 @@ typedef struct
|
||||
|
||||
/*! 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)
|
||||
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);
|
||||
@@ -446,7 +423,8 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bp
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
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);
|
||||
@@ -454,7 +432,9 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src,
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, size_t regenSize)
|
||||
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);
|
||||
@@ -595,176 +575,70 @@ typedef union {
|
||||
U32 alignedBy4;
|
||||
} FSE_decode_t4;
|
||||
|
||||
/* Default FSE distribution table for Literal Lengths */
|
||||
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 } },
|
||||
/* base, symbol, bits */
|
||||
{ { 0, 0, 4 } }, { { 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 */
|
||||
|
||||
/* Default FSE distribution table for Match Lengths */
|
||||
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 } },
|
||||
/* base, symbol, bits */
|
||||
{ { 0, 0, 6 } }, { { 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 */
|
||||
|
||||
/* Default FSE distribution table for Offset Codes */
|
||||
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 } },
|
||||
/* base, symbol, bits */
|
||||
{ { 0, 0, 5 } }, { { 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() :
|
||||
@@ -876,7 +750,7 @@ typedef struct {
|
||||
size_t prevOffset[ZSTD_REP_NUM];
|
||||
const BYTE* base;
|
||||
size_t pos;
|
||||
iPtrDiff gotoDict;
|
||||
uPtrDiff gotoDict;
|
||||
} seqState_t;
|
||||
|
||||
|
||||
@@ -927,8 +801,6 @@ size_t ZSTD_execSequenceLast7(BYTE* op,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
||||
{
|
||||
seq_t seq;
|
||||
@@ -943,21 +815,26 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
||||
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,
|
||||
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,
|
||||
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 };
|
||||
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;
|
||||
@@ -1031,9 +908,9 @@ size_t ZSTD_execSequence(BYTE* op,
|
||||
|
||||
/* copy Match */
|
||||
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||
/* offset beyond prefix */
|
||||
/* offset beyond prefix -> go into extDict */
|
||||
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
||||
match += (dictEnd-base);
|
||||
match = dictEnd + (match - base);
|
||||
if (match + sequence.matchLength <= dictEnd) {
|
||||
memmove(oLitEnd, match, sequence.matchLength);
|
||||
return sequenceLength;
|
||||
@@ -1156,21 +1033,26 @@ FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t* seqState, int con
|
||||
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,
|
||||
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,
|
||||
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 };
|
||||
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;
|
||||
@@ -1356,7 +1238,7 @@ static size_t ZSTD_decompressSequencesLong(
|
||||
{ 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 = (iPtrDiff)(dictEnd - 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);
|
||||
@@ -1472,23 +1354,23 @@ size_t ZSTD_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t len
|
||||
* @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 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) {
|
||||
(MEM_readLE32(src) & 0xFFFFFFF0U) == 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;
|
||||
ZSTD_frameHeader 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);
|
||||
{ size_t const ret = ZSTD_getFrameHeader(&fParams, ip, remainingSize);
|
||||
if (ZSTD_isError(ret)) return ret;
|
||||
if (ret > 0) return ERROR(srcSize_wrong);
|
||||
}
|
||||
@@ -2087,6 +1969,14 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
||||
}
|
||||
}
|
||||
|
||||
/*! ZSTD_estimateDDictSize() :
|
||||
* Estimate amount of memory that will be needed to create a dictionary for decompression.
|
||||
* Note : if dictionary is created "byReference", reduce this amount by dictSize */
|
||||
size_t ZSTD_estimateDDictSize(size_t dictSize)
|
||||
{
|
||||
return dictSize + sizeof(ZSTD_DDict);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
||||
{
|
||||
if (ddict==NULL) return 0; /* support sizeof on NULL */
|
||||
@@ -2115,19 +2005,22 @@ unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
|
||||
}
|
||||
|
||||
/*! ZSTD_getDictID_fromFrame() :
|
||||
* Provides the dictID required to decompressed the frame stored within `src`.
|
||||
* Provides the dictID required to decompresse 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.
|
||||
* - The frame does not require a dictionary (most common case).
|
||||
* - The frame was built with dictID intentionally removed.
|
||||
* Needed dictionary 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`).
|
||||
* - `srcSize` is too small, and as a result, frame header could not be decoded.
|
||||
* Note : 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. */
|
||||
* When identifying the exact failure cause, it's possible to use
|
||||
* ZSTD_getFrameHeader(), 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);
|
||||
ZSTD_frameHeader zfp = { 0 , 0 , 0 , 0 };
|
||||
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
||||
if (ZSTD_isError(hError)) return 0;
|
||||
return zfp.dictID;
|
||||
}
|
||||
@@ -2160,7 +2053,7 @@ struct ZSTD_DStream_s {
|
||||
ZSTD_DCtx* dctx;
|
||||
ZSTD_DDict* ddictLocal;
|
||||
const ZSTD_DDict* ddict;
|
||||
ZSTD_frameParams fParams;
|
||||
ZSTD_frameHeader fParams;
|
||||
ZSTD_dStreamStage stage;
|
||||
char* inBuff;
|
||||
size_t inBuffSize;
|
||||
@@ -2209,9 +2102,13 @@ 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);
|
||||
zds->dctx = NULL;
|
||||
ZSTD_freeDDict(zds->ddictLocal);
|
||||
zds->ddictLocal = NULL;
|
||||
ZSTD_free(zds->inBuff, cMem);
|
||||
zds->inBuff = NULL;
|
||||
ZSTD_free(zds->outBuff, cMem);
|
||||
zds->outBuff = NULL;
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (zds->legacyContext)
|
||||
ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
|
||||
@@ -2247,7 +2144,9 @@ 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 */
|
||||
/* ZSTD_initDStream_usingDDict() :
|
||||
* ddict will just be referenced, and must outlive decompression session */
|
||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
|
||||
{
|
||||
size_t const initResult = ZSTD_initDStream(zds);
|
||||
zds->ddict = ddict;
|
||||
@@ -2277,8 +2176,20 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
|
||||
|
||||
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;
|
||||
if (zds==NULL) return 0; /* support sizeof NULL */
|
||||
return sizeof(*zds)
|
||||
+ ZSTD_sizeof_DCtx(zds->dctx)
|
||||
+ ZSTD_sizeof_DDict(zds->ddictLocal)
|
||||
+ zds->inBuffSize + zds->outBuffSize;
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader)
|
||||
{
|
||||
size_t const windowSize = fHeader.windowSize;
|
||||
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
||||
size_t const inBuffSize = blockSize; /* no block can be larger */
|
||||
size_t const outBuffSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
||||
return sizeof(ZSTD_DStream) + ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -2315,7 +2226,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
/* fall-through */
|
||||
|
||||
case zdss_loadHeader :
|
||||
{ size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
|
||||
{ size_t const hSize = ZSTD_getFrameHeader(&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);
|
||||
@@ -2376,15 +2287,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
zds->blockSize = blockSize;
|
||||
if (zds->inBuffSize < blockSize) {
|
||||
ZSTD_free(zds->inBuff, zds->customMem);
|
||||
zds->inBuffSize = blockSize;
|
||||
zds->inBuffSize = 0;
|
||||
zds->inBuff = (char*)ZSTD_malloc(blockSize, zds->customMem);
|
||||
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
||||
zds->inBuffSize = blockSize;
|
||||
}
|
||||
if (zds->outBuffSize < neededOutSize) {
|
||||
ZSTD_free(zds->outBuff, zds->customMem);
|
||||
zds->outBuffSize = neededOutSize;
|
||||
zds->outBuffSize = 0;
|
||||
zds->outBuff = (char*)ZSTD_malloc(neededOutSize, zds->customMem);
|
||||
if (zds->outBuff == NULL) return ERROR(memory_allocation);
|
||||
zds->outBuffSize = neededOutSize;
|
||||
} }
|
||||
zds->stage = zdss_read;
|
||||
/* pass-through */
|
||||
|
||||
+34
-13
@@ -59,8 +59,6 @@ static int g_displayLevel = 2;
|
||||
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__)
|
||||
@@ -236,10 +234,22 @@ static size_t COVER_sum(const size_t *samplesSizes, unsigned nbSamples) {
|
||||
* 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;
|
||||
U32 const lhs = *(U32 const *)lp;
|
||||
U32 const rhs = *(U32 const *)rp;
|
||||
return memcmp(ctx->samples + lhs, ctx->samples + rhs, ctx->d);
|
||||
}
|
||||
/**
|
||||
* Faster version for d <= 8.
|
||||
*/
|
||||
static int COVER_cmp8(COVER_ctx_t *ctx, const void *lp, const void *rp) {
|
||||
U64 const mask = (ctx->d == 8) ? (U64)-1 : (((U64)1 << (8 * ctx->d)) - 1);
|
||||
U64 const lhs = MEM_readLE64(ctx->samples + *(U32 const *)lp) & mask;
|
||||
U64 const rhs = MEM_readLE64(ctx->samples + *(U32 const *)rp) & mask;
|
||||
if (lhs < rhs) {
|
||||
return -1;
|
||||
}
|
||||
return (lhs > rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as COVER_cmp() except ties are broken by pointer value
|
||||
@@ -253,6 +263,16 @@ static int COVER_strict_cmp(const void *lp, const void *rp) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Faster version for d <= 8.
|
||||
*/
|
||||
static int COVER_strict_cmp8(const void *lp, const void *rp) {
|
||||
int result = COVER_cmp8(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
|
||||
@@ -508,7 +528,7 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
const BYTE *const samples = (const BYTE *)samplesBuffer;
|
||||
const size_t totalSamplesSize = COVER_sum(samplesSizes, nbSamples);
|
||||
/* Checks */
|
||||
if (totalSamplesSize < d ||
|
||||
if (totalSamplesSize < MAX(d, sizeof(U64)) ||
|
||||
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));
|
||||
@@ -522,7 +542,7 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
ctx->samplesSizes = samplesSizes;
|
||||
ctx->nbSamples = nbSamples;
|
||||
/* Partial suffix array */
|
||||
ctx->suffixSize = totalSamplesSize - d + 1;
|
||||
ctx->suffixSize = totalSamplesSize - MAX(d, sizeof(U64)) + 1;
|
||||
ctx->suffix = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||
/* Maps index to the dmerID */
|
||||
ctx->dmerAt = (U32 *)malloc(ctx->suffixSize * sizeof(U32));
|
||||
@@ -556,7 +576,8 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
}
|
||||
/* 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);
|
||||
qsort(ctx->suffix, ctx->suffixSize, sizeof(U32),
|
||||
(ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
|
||||
}
|
||||
DISPLAYLEVEL(2, "Computing frequencies\n");
|
||||
/* For each dmer group (group of positions with the same first d bytes):
|
||||
@@ -566,8 +587,8 @@ static int COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
* 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);
|
||||
COVER_groupBy(ctx->suffix, ctx->suffixSize, sizeof(U32), ctx,
|
||||
(ctx->d <= 8 ? &COVER_cmp8 : &COVER_cmp), &COVER_group);
|
||||
ctx->freqs = ctx->suffix;
|
||||
ctx->suffix = NULL;
|
||||
return 1;
|
||||
@@ -918,10 +939,10 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer,
|
||||
/* 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 kMaxD = parameters->d == 0 ? 8 : parameters->d;
|
||||
const unsigned kMinK = parameters->k == 0 ? 50 : parameters->k;
|
||||
const unsigned kMaxK = parameters->k == 0 ? 2000 : parameters->k;
|
||||
const unsigned kSteps = parameters->steps == 0 ? 40 : parameters->steps;
|
||||
const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1);
|
||||
const unsigned kIterations =
|
||||
(1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize);
|
||||
|
||||
+65
-43
@@ -11,8 +11,9 @@
|
||||
/*-**************************************
|
||||
* Tuning parameters
|
||||
****************************************/
|
||||
#define MINRATIO 4 /* minimum nb of apparition to be selected in dictionary */
|
||||
#define ZDICT_MAX_SAMPLES_SIZE (2000U << 20)
|
||||
#define ZDICT_MIN_SAMPLES_SIZE 512
|
||||
#define ZDICT_MIN_SAMPLES_SIZE (ZDICT_CONTENTSIZE_MIN * MINRATIO)
|
||||
|
||||
|
||||
/*-**************************************
|
||||
@@ -59,11 +60,8 @@
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -308,10 +306,10 @@ static dictItem ZDICT_analyzePos(
|
||||
/* 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--;
|
||||
length = ZDICT_count(b + pos, b + suffix[start - 1]);
|
||||
if (length >= LLIMIT) length = LLIMIT - 1;
|
||||
lengthList[length]++;
|
||||
if (length >= MINMATCHLENGTH) start--;
|
||||
}
|
||||
|
||||
/* largest useful length */
|
||||
@@ -363,21 +361,35 @@ static dictItem ZDICT_analyzePos(
|
||||
}
|
||||
|
||||
|
||||
static int isIncluded(const void* in, const void* container, size_t length)
|
||||
{
|
||||
const char* const ip = (const char*) in;
|
||||
const char* const into = (const char*) container;
|
||||
size_t u;
|
||||
|
||||
for (u=0; u<length; u++) { /* works because end of buffer is a noisy guard band */
|
||||
if (ip[u] != into[u]) break;
|
||||
}
|
||||
|
||||
return u==length;
|
||||
}
|
||||
|
||||
/*! 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)
|
||||
static U32 ZDICT_tryMerge(dictItem* table, dictItem elt, U32 eltNbToSkip, const void* buffer)
|
||||
{
|
||||
const U32 tableSize = table->pos;
|
||||
const U32 eltEnd = elt.pos + elt.length;
|
||||
const char* const buf = (const char*) buffer;
|
||||
|
||||
/* 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;
|
||||
U32 const 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 */
|
||||
@@ -393,9 +405,10 @@ static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
|
||||
/* 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);
|
||||
int const 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;
|
||||
@@ -407,7 +420,18 @@ static U32 ZDICT_checkMerge(dictItem* table, dictItem elt, U32 eltNbToSkip)
|
||||
table[u] = table[u-1], u--;
|
||||
table[u] = elt;
|
||||
return u;
|
||||
} }
|
||||
}
|
||||
|
||||
if (MEM_read64(buf + table[u].pos) == MEM_read64(buf + elt.pos + 1)) {
|
||||
if (isIncluded(buf + table[u].pos, buf + elt.pos + 1, table[u].length)) {
|
||||
size_t const addedLength = MAX( (int)elt.length - (int)table[u].length , 1 );
|
||||
table[u].pos = elt.pos;
|
||||
table[u].savings += (U32)(elt.savings * addedLength / elt.length);
|
||||
table[u].length = MIN(elt.length, table[u].length + 1);
|
||||
return u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -425,14 +449,14 @@ static void ZDICT_removeDictItem(dictItem* table, U32 id)
|
||||
}
|
||||
|
||||
|
||||
static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt)
|
||||
static void ZDICT_insertDictItem(dictItem* table, U32 maxSize, dictItem elt, const void* buffer)
|
||||
{
|
||||
/* merge if possible */
|
||||
U32 mergeId = ZDICT_checkMerge(table, elt, 0);
|
||||
U32 mergeId = ZDICT_tryMerge(table, elt, 0, buffer);
|
||||
if (mergeId) {
|
||||
U32 newMerge = 1;
|
||||
while (newMerge) {
|
||||
newMerge = ZDICT_checkMerge(table, table[mergeId], mergeId);
|
||||
newMerge = ZDICT_tryMerge(table, table[mergeId], mergeId, buffer);
|
||||
if (newMerge) ZDICT_removeDictItem(table, mergeId);
|
||||
mergeId = newMerge;
|
||||
}
|
||||
@@ -480,7 +504,7 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
|
||||
# define DISPLAYUPDATE(l, ...) if (notificationLevel>=l) { \
|
||||
if (ZDICT_clockSpan(displayClock) > refreshRate) \
|
||||
{ displayClock = clock(); DISPLAY(__VA_ARGS__); \
|
||||
if (notificationLevel>=4) fflush(stdout); } }
|
||||
if (notificationLevel>=4) fflush(stderr); } }
|
||||
|
||||
/* init */
|
||||
DISPLAYLEVEL(2, "\r%70s\r", ""); /* clean display line */
|
||||
@@ -521,7 +545,7 @@ static size_t ZDICT_trainBuffer(dictItem* dictList, U32 dictListSize,
|
||||
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);
|
||||
ZDICT_insertDictItem(dictList, dictListSize, solution, buffer);
|
||||
cursor += solution.length;
|
||||
DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100);
|
||||
} }
|
||||
@@ -683,19 +707,19 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
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;
|
||||
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;
|
||||
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)) {
|
||||
if (ZSTD_isError(beginResult)) {
|
||||
DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced() failed : %s \n", ZSTD_getErrorName(beginResult));
|
||||
eSize = ERROR(GENERIC);
|
||||
DISPLAYLEVEL(1, "error : ZSTD_compressBegin_advanced failed \n");
|
||||
goto _cleanup;
|
||||
} }
|
||||
|
||||
@@ -812,7 +836,6 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
MEM_writeLE32(dstPtr+4, repStartValue[1]);
|
||||
MEM_writeLE32(dstPtr+8, repStartValue[2]);
|
||||
#endif
|
||||
//dstPtr += 12;
|
||||
eSize += 12;
|
||||
|
||||
_cleanup:
|
||||
@@ -831,7 +854,7 @@ size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||
ZDICT_params_t params)
|
||||
{
|
||||
size_t hSize;
|
||||
#define HBUFFSIZE 256
|
||||
#define HBUFFSIZE 256 /* should prove large enough for all entropy headers */
|
||||
BYTE header[HBUFFSIZE];
|
||||
int const compressionLevel = (params.compressionLevel <= 0) ? g_compressionLevel_default : params.compressionLevel;
|
||||
U32 const notificationLevel = params.notificationLevel;
|
||||
@@ -877,20 +900,11 @@ size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictCo
|
||||
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;
|
||||
size_t hSize = 8;
|
||||
|
||||
/* 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 */
|
||||
/* calculate 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,
|
||||
@@ -902,6 +916,13 @@ size_t ZDICT_addEntropyTablesFromBuffer_advanced(void* dictBuffer, size_t dictCo
|
||||
hSize += eSize;
|
||||
}
|
||||
|
||||
/* add dictionary header (after entropy tables) */
|
||||
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);
|
||||
}
|
||||
|
||||
if (hSize + dictContentSize < dictBufferCapacity)
|
||||
memmove((char*)dictBuffer + hSize, (char*)dictBuffer + dictBufferCapacity - dictContentSize, dictContentSize);
|
||||
@@ -929,8 +950,8 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
|
||||
/* 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 */
|
||||
if (maxDictSize < ZDICT_DICTSIZE_MIN) { free(dictList); return ERROR(dstSize_tooSmall); } /* requested dictionary size is too small */
|
||||
if (samplesBuffSize < ZDICT_MIN_SAMPLES_SIZE) { free(dictList); return ERROR(dictionaryCreation_failed); } /* not enough source to create dictionary */
|
||||
|
||||
/* init */
|
||||
ZDICT_initDictItem(dictList);
|
||||
@@ -963,14 +984,15 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
|
||||
/* create dictionary */
|
||||
{ U32 dictContentSize = ZDICT_dictSize(dictList);
|
||||
if (dictContentSize < targetDictSize/3) {
|
||||
if (dictContentSize < ZDICT_CONTENTSIZE_MIN) { free(dictList); return ERROR(dictionaryCreation_failed); } /* dictionary content too small */
|
||||
if (dictContentSize < targetDictSize/4) {
|
||||
DISPLAYLEVEL(2, "! warning : selected content significantly smaller than requested (%u < %u) \n", dictContentSize, (U32)maxDictSize);
|
||||
if (samplesBuffSize < 10 * targetDictSize)
|
||||
DISPLAYLEVEL(2, "! consider increasing the number of samples (total size : %u MB)\n", (U32)(samplesBuffSize>>20));
|
||||
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)) {
|
||||
@@ -978,7 +1000,7 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
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");
|
||||
DISPLAYLEVEL(2, "! always test dictionary efficiency on real samples \n");
|
||||
}
|
||||
|
||||
/* limit dictionary size */
|
||||
|
||||
@@ -88,7 +88,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dict
|
||||
|
||||
/*! COVER_params_t :
|
||||
For all values 0 means default.
|
||||
kMin and d are the only required parameters.
|
||||
k and d are the only required parameters.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */
|
||||
@@ -147,18 +147,18 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void* dictBuffer, size_t dictB
|
||||
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.
|
||||
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
|
||||
note 2 : dictBuffer and dictContent can overlap
|
||||
*/
|
||||
#define ZDICT_CONTENTSIZE_MIN 256
|
||||
#define ZDICT_DICTSIZE_MIN 512
|
||||
#define ZDICT_CONTENTSIZE_MIN 128
|
||||
#define ZDICT_DICTSIZE_MIN 256
|
||||
ZDICTLIB_API size_t ZDICT_finalizeDictionary(void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* customDictContent, size_t dictContentSize,
|
||||
const void* dictContent, size_t dictContentSize,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||
ZDICT_params_t parameters);
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ ZSTD Windows binary package
|
||||
#### The package contents
|
||||
|
||||
- `zstd.exe` : Command Line Utility, supporting gzip-like arguments
|
||||
- `dll\libzstd.dll` : The DLL of ZSTD library
|
||||
- `dll\libzstd.lib` : The import library of ZSTD library for Visual C++
|
||||
- `example\` : The example of usage of ZSTD library
|
||||
- `include\` : Header files required with ZSTD library
|
||||
- `static\libzstd_static.lib` : The static ZSTD library
|
||||
- `dll\libzstd.dll` : The ZSTD dynamic library (DLL)
|
||||
- `dll\libzstd.lib` : The import library of the ZSTD dynamic library (DLL) for Visual C++
|
||||
- `example\` : The example of usage of the ZSTD library
|
||||
- `include\` : Header files required by the ZSTD library
|
||||
- `static\libzstd_static.lib` : The static ZSTD library (LIB)
|
||||
|
||||
|
||||
#### Usage of Command Line Interface
|
||||
|
||||
@@ -9,6 +9,7 @@ COPY lib\common\mem.h bin\example\
|
||||
COPY lib\common\zstd_errors.h bin\example\
|
||||
COPY lib\common\zstd_internal.h bin\example\
|
||||
COPY lib\common\error_private.h bin\example\
|
||||
COPY lib\common\xxhash.h bin\example\
|
||||
COPY lib\zstd.h bin\include\
|
||||
COPY lib\libzstd.a bin\static\libzstd_static.lib
|
||||
COPY lib\dll\libzstd.* bin\dll\
|
||||
|
||||
@@ -20,14 +20,33 @@ extern "C" {
|
||||
#include "mem.h" /* MEM_STATIC */
|
||||
#include "error_private.h" /* ERROR */
|
||||
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */
|
||||
#include "zstd_v01.h"
|
||||
#include "zstd_v02.h"
|
||||
#include "zstd_v03.h"
|
||||
#include "zstd_v04.h"
|
||||
#include "zstd_v05.h"
|
||||
#include "zstd_v06.h"
|
||||
#include "zstd_v07.h"
|
||||
|
||||
#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.
|
||||
@@ -40,13 +59,27 @@ MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize)
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -56,24 +89,30 @@ MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, s
|
||||
{
|
||||
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 */
|
||||
}
|
||||
|
||||
@@ -86,14 +125,23 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
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();
|
||||
@@ -102,6 +150,8 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
ZSTDv05_freeDCtx(zd);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
||||
case 6 :
|
||||
{ size_t result;
|
||||
ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx();
|
||||
@@ -110,6 +160,8 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
ZSTDv06_freeDCtx(zd);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
||||
case 7 :
|
||||
{ size_t result;
|
||||
ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx();
|
||||
@@ -118,6 +170,7 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
|
||||
ZSTDv07_freeDCtx(zd);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
default :
|
||||
return ERROR(prefix_unknown);
|
||||
}
|
||||
@@ -129,20 +182,34 @@ MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src,
|
||||
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);
|
||||
}
|
||||
@@ -157,10 +224,18 @@ MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +251,7 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
case 2 :
|
||||
case 3 :
|
||||
return 0;
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 4)
|
||||
case 4 :
|
||||
{
|
||||
ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext;
|
||||
@@ -185,6 +261,8 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
*legacyContext = dctx;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 5)
|
||||
case 5 :
|
||||
{
|
||||
ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext;
|
||||
@@ -193,6 +271,8 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
*legacyContext = dctx;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
||||
case 6 :
|
||||
{
|
||||
ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext;
|
||||
@@ -201,6 +281,8 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
*legacyContext = dctx;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
||||
case 7 :
|
||||
{
|
||||
ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext;
|
||||
@@ -209,6 +291,7 @@ MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U
|
||||
*legacyContext = dctx;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +307,7 @@ MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
case 2 :
|
||||
case 3 :
|
||||
return ERROR(version_unsupported);
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 4)
|
||||
case 4 :
|
||||
{
|
||||
ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext;
|
||||
@@ -236,6 +320,8 @@ MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
input->pos += readSize;
|
||||
return hintSize;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 5)
|
||||
case 5 :
|
||||
{
|
||||
ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext;
|
||||
@@ -248,6 +334,8 @@ MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
input->pos += readSize;
|
||||
return hintSize;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 6)
|
||||
case 6 :
|
||||
{
|
||||
ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext;
|
||||
@@ -260,6 +348,8 @@ MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
input->pos += readSize;
|
||||
return hintSize;
|
||||
}
|
||||
#endif
|
||||
#if (ZSTD_LEGACY_SUPPORT <= 7)
|
||||
case 7 :
|
||||
{
|
||||
ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext;
|
||||
@@ -272,6 +362,7 @@ MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
|
||||
input->pos += readSize;
|
||||
return hintSize;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1432,7 +1432,7 @@ typedef struct ZSTD_Cctx_s
|
||||
#else
|
||||
U32 hashTable[HASH_TABLESIZE];
|
||||
#endif
|
||||
BYTE buffer[WORKPLACESIZE];
|
||||
BYTE buffer[WORKPLACESIZE];
|
||||
} cctxi_t;
|
||||
|
||||
|
||||
|
||||
+21
-21
@@ -475,8 +475,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
|
||||
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->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BIT_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
|
||||
{
|
||||
@@ -1334,8 +1334,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
|
||||
else
|
||||
{
|
||||
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||
ip = iend - 4;
|
||||
}
|
||||
ip = iend - 4;
|
||||
}
|
||||
bitStream = MEM_readLE32(ip) >> (bitCount & 31);
|
||||
}
|
||||
}
|
||||
@@ -2040,7 +2040,7 @@ static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
|
||||
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
/* Build rankVal */
|
||||
{
|
||||
const U32 minBits = tableLog+1 - maxW;
|
||||
U32 nextRankVal = 0;
|
||||
@@ -2374,7 +2374,7 @@ static size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
|
||||
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
/* Build rankVal */
|
||||
{
|
||||
const U32 minBits = tableLog+1 - maxW;
|
||||
U32 nextRankVal = 0;
|
||||
@@ -2948,14 +2948,14 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
|
||||
const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
|
||||
if (litSize > srcSize-11) /* risk of reading too far with wildcopy */
|
||||
{
|
||||
if (litSize > srcSize-3) return ERROR(corruption_detected);
|
||||
memcpy(dctx->litBuffer, istart, litSize);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
memset(dctx->litBuffer + dctx->litSize, 0, 8);
|
||||
return litSize+3;
|
||||
}
|
||||
/* direct reference into compressed stream */
|
||||
if (litSize > srcSize-3) return ERROR(corruption_detected);
|
||||
memcpy(dctx->litBuffer, istart, litSize);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
memset(dctx->litBuffer + dctx->litSize, 0, 8);
|
||||
return litSize+3;
|
||||
}
|
||||
/* direct reference into compressed stream */
|
||||
dctx->litPtr = istart+3;
|
||||
dctx->litSize = litSize;
|
||||
return litSize+3;
|
||||
@@ -3515,13 +3515,13 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
|
||||
|
||||
unsigned ZSTDv02_isError(size_t code)
|
||||
{
|
||||
return ZSTD_isError(code);
|
||||
return ZSTD_isError(code);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize)
|
||||
{
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
|
||||
@@ -3531,25 +3531,25 @@ size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize)
|
||||
|
||||
ZSTDv02_Dctx* ZSTDv02_createDCtx(void)
|
||||
{
|
||||
return (ZSTDv02_Dctx*)ZSTD_createDCtx();
|
||||
return (ZSTDv02_Dctx*)ZSTD_createDCtx();
|
||||
}
|
||||
|
||||
size_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
|
||||
return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
|
||||
}
|
||||
|
||||
+20
-20
@@ -477,8 +477,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
|
||||
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->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BIT_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
|
||||
{
|
||||
@@ -1335,8 +1335,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
|
||||
else
|
||||
{
|
||||
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||
ip = iend - 4;
|
||||
}
|
||||
ip = iend - 4;
|
||||
}
|
||||
bitStream = MEM_readLE32(ip) >> (bitCount & 31);
|
||||
}
|
||||
}
|
||||
@@ -2037,7 +2037,7 @@ static size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
|
||||
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
/* Build rankVal */
|
||||
{
|
||||
const U32 minBits = tableLog+1 - maxW;
|
||||
U32 nextRankVal = 0;
|
||||
@@ -2589,14 +2589,14 @@ static size_t ZSTD_decodeLiteralsBlock(void* ctx,
|
||||
const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
|
||||
if (litSize > srcSize-11) /* risk of reading too far with wildcopy */
|
||||
{
|
||||
if (litSize > srcSize-3) return ERROR(corruption_detected);
|
||||
memcpy(dctx->litBuffer, istart, litSize);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
memset(dctx->litBuffer + dctx->litSize, 0, 8);
|
||||
return litSize+3;
|
||||
}
|
||||
/* direct reference into compressed stream */
|
||||
if (litSize > srcSize-3) return ERROR(corruption_detected);
|
||||
memcpy(dctx->litBuffer, istart, litSize);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
memset(dctx->litBuffer + dctx->litSize, 0, 8);
|
||||
return litSize+3;
|
||||
}
|
||||
/* direct reference into compressed stream */
|
||||
dctx->litPtr = istart+3;
|
||||
dctx->litSize = litSize;
|
||||
return litSize+3;
|
||||
@@ -3156,13 +3156,13 @@ static size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSi
|
||||
|
||||
unsigned ZSTDv03_isError(size_t code)
|
||||
{
|
||||
return ZSTD_isError(code);
|
||||
return ZSTD_isError(code);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,
|
||||
const void* src, size_t compressedSize)
|
||||
{
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
@@ -3172,25 +3172,25 @@ size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
|
||||
ZSTDv03_Dctx* ZSTDv03_createDCtx(void)
|
||||
{
|
||||
return (ZSTDv03_Dctx*)ZSTD_createDCtx();
|
||||
return (ZSTDv03_Dctx*)ZSTD_createDCtx();
|
||||
}
|
||||
|
||||
size_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx)
|
||||
{
|
||||
return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
|
||||
return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);
|
||||
}
|
||||
|
||||
size_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
|
||||
return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);
|
||||
}
|
||||
|
||||
@@ -882,8 +882,8 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
|
||||
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->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BIT_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))
|
||||
{
|
||||
@@ -1451,8 +1451,8 @@ static size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsi
|
||||
else
|
||||
{
|
||||
bitCount -= (int)(8 * (iend - 4 - ip));
|
||||
ip = iend - 4;
|
||||
}
|
||||
ip = iend - 4;
|
||||
}
|
||||
bitStream = MEM_readLE32(ip) >> (bitCount & 31);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -884,8 +884,8 @@ MEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, U32 nbBits)
|
||||
|
||||
MEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)
|
||||
{
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BITv05_DStream_overflow;
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BITv05_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
|
||||
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||
|
||||
@@ -982,8 +982,8 @@ MEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, U32 nbBits)
|
||||
if status == unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
|
||||
MEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD)
|
||||
{
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BITv06_DStream_overflow;
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
return BITv06_DStream_overflow;
|
||||
|
||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
|
||||
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||
|
||||
+175
-139
@@ -55,8 +55,8 @@ extern "C" {
|
||||
|
||||
/*------ Version ------*/
|
||||
#define ZSTD_VERSION_MAJOR 1
|
||||
#define ZSTD_VERSION_MINOR 1
|
||||
#define ZSTD_VERSION_RELEASE 4
|
||||
#define ZSTD_VERSION_MINOR 3
|
||||
#define ZSTD_VERSION_RELEASE 0
|
||||
|
||||
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
|
||||
#define ZSTD_QUOTE(str) #str
|
||||
@@ -71,48 +71,48 @@ ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< library version number; to
|
||||
* 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()). */
|
||||
* 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()). */
|
||||
* `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. */
|
||||
* 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);
|
||||
|
||||
|
||||
@@ -127,25 +127,29 @@ ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readab
|
||||
* 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. */
|
||||
* 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()). */
|
||||
* 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 */
|
||||
/*= 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()). */
|
||||
* 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);
|
||||
|
||||
|
||||
@@ -190,9 +194,10 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize
|
||||
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. */
|
||||
* 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.
|
||||
* Frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
@@ -276,10 +281,13 @@ typedef struct ZSTD_outBuffer_s {
|
||||
*
|
||||
* *******************************************************************/
|
||||
|
||||
typedef struct ZSTD_CStream_s ZSTD_CStream;
|
||||
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are effectively same object */
|
||||
/* Continue due distinghish them for compatibility with versions <= v1.2.0 */
|
||||
/*===== 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);
|
||||
@@ -313,9 +321,11 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
|
||||
* *******************************************************************************/
|
||||
|
||||
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);
|
||||
|
||||
@@ -340,9 +350,6 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
||||
#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))
|
||||
@@ -391,76 +398,109 @@ typedef struct {
|
||||
ZSTD_frameParameters fParams;
|
||||
} ZSTD_parameters;
|
||||
|
||||
typedef struct {
|
||||
unsigned long long frameContentSize;
|
||||
unsigned windowSize;
|
||||
unsigned dictID;
|
||||
unsigned checksumFlag;
|
||||
} ZSTD_frameHeader;
|
||||
|
||||
/*= 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
|
||||
* Frame 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. */
|
||||
* @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) */
|
||||
* `src` should point to the start of a ZSTD encoded frame.
|
||||
* `srcSize` must be at least as large as the frame header.
|
||||
* A value >= `ZSTD_frameHeaderSize_max` is guaranteed to be large enough.
|
||||
* @return : - decompressed size of the frame pointed to be `src` if known
|
||||
* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
|
||||
* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
|
||||
#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
|
||||
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
|
||||
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. */
|
||||
* `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 : - decompressed size of all data in all successive frames
|
||||
* - 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);
|
||||
|
||||
|
||||
/***************************************
|
||||
* Context memory usage
|
||||
***************************************/
|
||||
|
||||
/*! ZSTD_sizeof_*() :
|
||||
* These functions give the current memory usage of selected object.
|
||||
* Object memory usage can evolve if it's re-used multiple times. */
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
|
||||
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_estimate*() :
|
||||
* These functions make it possible to estimate memory usage
|
||||
* of a future target object, before its allocation,
|
||||
* given a set of parameters, which vary depending on target object.
|
||||
* The objective is to guide decision before allocation. */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
|
||||
|
||||
/*! ZSTD_estimate?StreamSize() :
|
||||
* Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
|
||||
* an internal ?Dict will be created, which size is not estimated.
|
||||
* In this case, get additional size by using ZSTD_estimate?DictSize */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader);
|
||||
|
||||
/*! ZSTD_estimate?DictSize() :
|
||||
* Note : if dictionary is created "byReference", reduce estimation by dictSize */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize);
|
||||
|
||||
|
||||
/***************************************
|
||||
* 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) */
|
||||
@@ -479,11 +519,7 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, siz
|
||||
/*! 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_compressionParameters cParams, ZSTD_customMem customMem);
|
||||
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
@@ -505,12 +541,19 @@ ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
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);
|
||||
* Same as ZSTD_compress_usingDict(), with fine-tune control over each compression parameter */
|
||||
ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
ZSTD_parameters params);
|
||||
|
||||
/*! ZSTD_compress_usingCDict_advanced() :
|
||||
* Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const ZSTD_CDict* cdict, ZSTD_frameParameters fParams);
|
||||
|
||||
|
||||
/*--- Advanced decompression functions ---*/
|
||||
@@ -522,31 +565,21 @@ ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
||||
* 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.
|
||||
@@ -568,7 +601,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
* 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. */
|
||||
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameParams(), which will provide a more precise error code. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
@@ -579,22 +612,29 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
/*===== 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_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. This result in the creation of an internal CDict */
|
||||
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);
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
|
||||
|
||||
/*! ZSTD_resetCStream() :
|
||||
* start a new compression job, using same parameters from previous job.
|
||||
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place..
|
||||
* Note that zcs must be init at least once before using ZSTD_resetCStream().
|
||||
* pledgedSrcSize==0 means "srcSize unknown".
|
||||
* If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
|
||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||
|
||||
|
||||
/*===== 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_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_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);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
@@ -640,8 +680,10 @@ ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
|
||||
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_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize=0 means null-size */
|
||||
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);
|
||||
|
||||
@@ -707,15 +749,8 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
|
||||
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_getFrameHeader(ZSTD_frameHeader* zfhPtr, 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);
|
||||
@@ -735,19 +770,20 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
- 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.
|
||||
+ compression : any ZSTD_compressBegin*() variant, including with dictionary
|
||||
+ decompression : any ZSTD_decompressBegin*() variant, including with dictionary
|
||||
+ copyCCtx() and copyDCtx() can be used too
|
||||
- Block size is limited, it must be <= ZSTD_getBlockSizeMax() <= ZSTD_BLOCKSIZE_ABSOLUTEMAX
|
||||
+ If input is larger than a block size, it's necessary to split input data into multiple blocks
|
||||
+ For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
|
||||
Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
|
||||
- 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.
|
||||
+ In case of multiple successive blocks, should some of them be uncompressed,
|
||||
decoder must be informed of their existence in order to follow proper history.
|
||||
Use ZSTD_insertBlock() for such a case.
|
||||
*/
|
||||
|
||||
#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */
|
||||
|
||||
Reference in New Issue
Block a user