Merge remote-tracking branch 'refs/remotes/origin/dev' into repcodes
# Conflicts: # lib/zstd_compress.c # lib/zstd_decompress.c # lib/zstd_internal.h # lib/zstd_opt.h # programs/bench.c
This commit is contained in:
@@ -89,9 +89,8 @@ gpptest: clean
|
||||
$(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror"
|
||||
|
||||
armtest: clean
|
||||
# $(MAKE) -C $(ZSTDDIR) all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror"
|
||||
$(MAKE) -C $(PRGDIR) datagen # use native, faster
|
||||
$(MAKE) -C $(PRGDIR) test CC=arm-linux-gnueabi-gcc ZSTDRTTEST= MOREFLAGS=-static # MOREFLAGS="-Werror -static"
|
||||
$(MAKE) -C $(PRGDIR) test CC=arm-linux-gnueabi-gcc ZSTDRTTEST= MOREFLAGS="-Werror -static"
|
||||
|
||||
# for Travis CI
|
||||
arminstall: clean
|
||||
@@ -105,7 +104,7 @@ armtest-w-install: clean arminstall armtest
|
||||
|
||||
ppctest: clean
|
||||
$(MAKE) -C $(PRGDIR) datagen # use native, faster
|
||||
$(MAKE) -C $(PRGDIR) test CC=powerpc-linux-gnu-gcc ZSTDRTTEST= MOREFLAGS=-static # MOREFLAGS="-Werror -static"
|
||||
$(MAKE) -C $(PRGDIR) test CC=powerpc-linux-gnu-gcc ZSTDRTTEST= MOREFLAGS="-Werror -static"
|
||||
|
||||
# for Travis CI
|
||||
ppcinstall: clean
|
||||
|
||||
+123
-87
@@ -41,7 +41,7 @@ extern "C" {
|
||||
|
||||
|
||||
/*
|
||||
* This API consists of small unitary functions, which highly benefit from being inlined.
|
||||
* This API consists of small unitary functions, which must be inlined for best performance.
|
||||
* Since link-time-optimization is not available for all compilers,
|
||||
* these functions are defined into a .h to be included.
|
||||
*/
|
||||
@@ -53,13 +53,20 @@ extern "C" {
|
||||
#include "error_private.h" /* error codes and messages */
|
||||
|
||||
|
||||
/*=========================================
|
||||
* Target specific
|
||||
=========================================*/
|
||||
#if defined(__BMI__) && defined(__GNUC__)
|
||||
# include <immintrin.h> /* support for bextr (experimental) */
|
||||
#endif
|
||||
|
||||
|
||||
/*-******************************************
|
||||
* bitStream encoding API (write forward)
|
||||
********************************************/
|
||||
/*!
|
||||
* bitStream can mix input from multiple sources.
|
||||
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||
/* bitStream can mix input from multiple sources.
|
||||
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -75,22 +82,21 @@ MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits
|
||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
|
||||
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
|
||||
|
||||
/*!
|
||||
* Start by initCStream, providing the size of buffer to write into.
|
||||
* bitStream will never write outside of this buffer.
|
||||
* @dstCapacity must be >= sizeof(size_t), otherwise @return will be an error code.
|
||||
/* Start with initCStream, providing the size of buffer to write into.
|
||||
* bitStream will never write outside of this buffer.
|
||||
* `dstCapacity` must be >= sizeof(size_t), otherwise @return will be an error code.
|
||||
*
|
||||
* bits are first added to a local register.
|
||||
* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
|
||||
* Writing data into memory is an explicit operation, performed by the flushBits function.
|
||||
* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
|
||||
* After a flushBits, a maximum of 7 bits might still be stored into local register.
|
||||
* bits are first added to a local register.
|
||||
* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
|
||||
* Writing data into memory is an explicit operation, performed by the flushBits function.
|
||||
* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
|
||||
* After a flushBits, a maximum of 7 bits might still be stored into local register.
|
||||
*
|
||||
* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
|
||||
* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
|
||||
*
|
||||
* Last operation is to close the bitStream.
|
||||
* The function returns the final size of CStream in bytes.
|
||||
* If data couldn't fit into @dstBuffer, it will return a 0 ( == not storable)
|
||||
* Last operation is to close the bitStream.
|
||||
* The function returns the final size of CStream in bytes.
|
||||
* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
|
||||
*/
|
||||
|
||||
|
||||
@@ -117,15 +123,14 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
|
||||
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
|
||||
|
||||
|
||||
/*!
|
||||
* Start by invoking BIT_initDStream().
|
||||
* A chunk of the bitStream is then stored into a local register.
|
||||
* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||
* You can then retrieve bitFields stored into the local register, **in reverse order**.
|
||||
* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
|
||||
* A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished.
|
||||
* Otherwise, it can be less than that, so proceed accordingly.
|
||||
* Checking if DStream has reached its end can be performed with BIT_endOfDStream()
|
||||
/* Start by invoking BIT_initDStream().
|
||||
* A chunk of the bitStream is then stored into a local register.
|
||||
* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
|
||||
* You can then retrieve bitFields stored into the local register, **in reverse order**.
|
||||
* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
|
||||
* A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished.
|
||||
* Otherwise, it can be less than that, so proceed accordingly.
|
||||
* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
|
||||
*/
|
||||
|
||||
|
||||
@@ -144,7 +149,7 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* Helper functions
|
||||
* Internal functions
|
||||
****************************************************************/
|
||||
MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
||||
{
|
||||
@@ -168,29 +173,38 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
||||
# endif
|
||||
}
|
||||
|
||||
/*===== Local Constants =====*/
|
||||
static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */
|
||||
|
||||
|
||||
/*-**************************************************************
|
||||
* bitStream encoding
|
||||
****************************************************************/
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t maxSize)
|
||||
/*! BIT_initCStream() :
|
||||
* `dstCapacity` must be > sizeof(void*)
|
||||
* @return : 0 if success,
|
||||
otherwise an error code (can be tested using ERR_isError() ) */
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
|
||||
{
|
||||
bitC->bitContainer = 0;
|
||||
bitC->bitPos = 0;
|
||||
bitC->startPtr = (char*)startPtr;
|
||||
bitC->ptr = bitC->startPtr;
|
||||
bitC->endPtr = bitC->startPtr + maxSize - sizeof(bitC->ptr);
|
||||
if (maxSize < sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
|
||||
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
|
||||
if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! BIT_addBits() :
|
||||
can add up to 26 bits into `bitC`.
|
||||
Does not check for register overflow ! */
|
||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
||||
{
|
||||
static const unsigned 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 */
|
||||
bitC->bitContainer |= (value & mask[nbBits]) << bitC->bitPos;
|
||||
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
|
||||
bitC->bitPos += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_addBitsFast
|
||||
/*! 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)
|
||||
{
|
||||
@@ -198,20 +212,23 @@ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBi
|
||||
bitC->bitPos += nbBits;
|
||||
}
|
||||
|
||||
/*! BIT_flushBitsFast
|
||||
/*! BIT_flushBitsFast() :
|
||||
* unsafe version; does not check buffer overflow */
|
||||
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t nbBytes = bitC->bitPos >> 3;
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||
bitC->ptr += nbBytes;
|
||||
bitC->bitPos &= 7;
|
||||
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
|
||||
}
|
||||
|
||||
/*! BIT_flushBits() :
|
||||
* safe version; check for buffer overflow, and prevents it.
|
||||
* note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
|
||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||
{
|
||||
size_t nbBytes = bitC->bitPos >> 3;
|
||||
size_t const nbBytes = bitC->bitPos >> 3;
|
||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||
bitC->ptr += nbBytes;
|
||||
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
|
||||
@@ -219,49 +236,41 @@ MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
|
||||
}
|
||||
|
||||
/*! BIT_closeCStream
|
||||
* @result : size of CStream, in bytes, or 0 if it cannot fit into dstBuffer */
|
||||
/*! BIT_closeCStream() :
|
||||
* @return : size of CStream, in bytes,
|
||||
or 0 if it could not fit into dstBuffer */
|
||||
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
||||
{
|
||||
char* endPtr;
|
||||
|
||||
BIT_addBitsFast(bitC, 1, 1); /* endMark */
|
||||
BIT_flushBits(bitC);
|
||||
|
||||
if (bitC->ptr >= bitC->endPtr) /* too close to buffer's end */
|
||||
return 0; /* not storable */
|
||||
if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */
|
||||
|
||||
endPtr = bitC->ptr;
|
||||
endPtr += bitC->bitPos > 0; /* remaining bits (incomplete byte) */
|
||||
|
||||
return (endPtr - bitC->startPtr);
|
||||
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
|
||||
}
|
||||
|
||||
|
||||
/*-********************************************************
|
||||
* bitStream decoding
|
||||
**********************************************************/
|
||||
/*!BIT_initDStream
|
||||
* Initialize a BIT_DStream_t.
|
||||
* @bitD : a pointer to an already allocated BIT_DStream_t structure
|
||||
* @srcBuffer must point at the beginning of a bitStream
|
||||
* @srcSize must be the exact size of the bitStream
|
||||
* @result : size of stream (== srcSize) or an errorCode if a problem is detected
|
||||
/*! BIT_initDStream() :
|
||||
* Initialize a BIT_DStream_t.
|
||||
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
||||
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
||||
* @return : size of stream (== srcSize) or an errorCode if a problem is detected
|
||||
*/
|
||||
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
|
||||
{
|
||||
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||
|
||||
if (srcSize >= sizeof(size_t)) { /* normal case */
|
||||
U32 contain32;
|
||||
bitD->start = (const char*)srcBuffer;
|
||||
bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t);
|
||||
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||
contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
|
||||
bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */
|
||||
bitD->bitsConsumed = 8 - BIT_highbit32(lastByte); }
|
||||
} else {
|
||||
U32 contain32;
|
||||
bitD->start = (const char*)srcBuffer;
|
||||
bitD->ptr = bitD->start;
|
||||
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
||||
@@ -275,33 +284,56 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
|
||||
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8;
|
||||
default:;
|
||||
}
|
||||
contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
|
||||
bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */
|
||||
bitD->bitsConsumed = 8 - BIT_highbit32(lastByte); }
|
||||
bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
|
||||
}
|
||||
|
||||
return srcSize;
|
||||
}
|
||||
|
||||
/*!BIT_lookBits
|
||||
* Provides next n bits from local register
|
||||
* local register is not modified (bits are still present for next read/look)
|
||||
* On 32-bits, maxNbBits==25
|
||||
* On 64-bits, maxNbBits==57
|
||||
* @return : value extracted
|
||||
*/
|
||||
MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
MEM_STATIC size_t BIT_getUpperBits(size_t bitD, U32 const start)
|
||||
{
|
||||
const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
|
||||
return bitD >> start;
|
||||
}
|
||||
|
||||
/*! BIT_lookBitsFast :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
MEM_STATIC size_t BIT_getMiddleBits(size_t bitD, U32 const nbBits, U32 const start)
|
||||
{
|
||||
const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental */
|
||||
return __builtin_ia32_bextr_u64(bitD, (nbBits<<8) | start );
|
||||
#else
|
||||
return (bitD >> start) & BIT_mask[nbBits];
|
||||
#endif
|
||||
}
|
||||
|
||||
MEM_STATIC size_t BIT_getLowerBits(size_t bitD, U32 const nbBits)
|
||||
{
|
||||
return bitD & BIT_mask[nbBits];
|
||||
}
|
||||
|
||||
/*! BIT_lookBits() :
|
||||
* Provides next n bits from local register.
|
||||
* local register is not modified (bits are still present for next read/look).
|
||||
* On 32-bits, maxNbBits==24.
|
||||
* On 64-bits, maxNbBits==56.
|
||||
* @return : value extracted
|
||||
*/
|
||||
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental */
|
||||
return __builtin_ia32_bextr_u64(bitD->bitContainer, (nbBits<<8) | (64 - bitD->bitsConsumed - nbBits) );
|
||||
#else
|
||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! BIT_lookBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||
return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
|
||||
}
|
||||
|
||||
@@ -310,27 +342,32 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
bitD->bitsConsumed += nbBits;
|
||||
}
|
||||
|
||||
/*!BIT_readBits
|
||||
* Read next n bits from local register.
|
||||
* pay attention to not read more than nbBits contained into local register.
|
||||
* @return : extracted value.
|
||||
/*! BIT_readBits() :
|
||||
* Read (consume) next n bits from local register and update.
|
||||
* Pay attention to not read more than nbBits contained into local register.
|
||||
* @return : extracted value.
|
||||
*/
|
||||
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t value = BIT_lookBits(bitD, nbBits);
|
||||
size_t const value = BIT_lookBits(bitD, nbBits);
|
||||
BIT_skipBits(bitD, nbBits);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*!BIT_readBitsFast :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
/*! BIT_readBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t value = BIT_lookBitsFast(bitD, nbBits);
|
||||
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
||||
BIT_skipBits(bitD, nbBits);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*! BIT_reloadDStream() :
|
||||
* Refill `BIT_DStream_t` from src buffer previously defined (see BIT_initDStream() ).
|
||||
* This function is safe, it guarantees it will not read beyond src buffer.
|
||||
* @return : status of `BIT_DStream_t` internal register.
|
||||
if status == unfinished, internal register is filled with >= (sizeof(size_t)*8 - 7) bits */
|
||||
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
{
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
|
||||
@@ -346,8 +383,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;
|
||||
}
|
||||
{
|
||||
U32 nbBytes = bitD->bitsConsumed >> 3;
|
||||
{ U32 nbBytes = bitD->bitsConsumed >> 3;
|
||||
BIT_DStream_status result = BIT_DStream_unfinished;
|
||||
if (bitD->ptr - nbBytes < bitD->start) {
|
||||
nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
|
||||
@@ -360,8 +396,8 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
}
|
||||
}
|
||||
|
||||
/*! BIT_endOfDStream
|
||||
* @return Tells if DStream has reached its exact end
|
||||
/*! BIT_endOfDStream() :
|
||||
* @return Tells if DStream has exactly reached its end (all bits consumed).
|
||||
*/
|
||||
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
{
|
||||
|
||||
+7
-6
@@ -28,7 +28,7 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- Source repository : https://github.com/Cyan4973/zstd
|
||||
- Homepage : http://www.zstd.net
|
||||
****************************************************************** */
|
||||
/* Note : this module is expected to remain private, do not expose it */
|
||||
|
||||
@@ -62,7 +62,7 @@ extern "C" {
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* Customization
|
||||
* Customization (error_public.h)
|
||||
******************************************/
|
||||
typedef ZSTD_ErrorCode ERR_enum;
|
||||
#define PREFIX(name) ZSTD_error_##name
|
||||
@@ -74,7 +74,7 @@ typedef ZSTD_ErrorCode ERR_enum;
|
||||
#ifdef ERROR
|
||||
# undef ERROR /* reported already defined on VS 2015 (Rich Geldreich) */
|
||||
#endif
|
||||
#define ERROR(name) (size_t)-PREFIX(name)
|
||||
#define ERROR(name) ((size_t)-PREFIX(name))
|
||||
|
||||
ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
|
||||
|
||||
@@ -95,18 +95,19 @@ ERR_STATIC const char* ERR_getErrorName(size_t code)
|
||||
case PREFIX(prefix_unknown): return "Unknown frame descriptor";
|
||||
case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
|
||||
case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
|
||||
case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
|
||||
case PREFIX(init_missing): return "Context should be init first";
|
||||
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
|
||||
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
|
||||
case PREFIX(srcSize_wrong): return "Src size incorrect";
|
||||
case PREFIX(corruption_detected): return "Corrupted block detected";
|
||||
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory";
|
||||
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max possible Symbol Value : too large";
|
||||
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
|
||||
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
|
||||
case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
|
||||
case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
|
||||
case PREFIX(maxCode):
|
||||
default: return notErrorCode; /* should be impossible, due to ERR_getError() */
|
||||
default: return notErrorCode; /* impossible, due to ERR_getError() */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- Source repository : https://github.com/Cyan4973/zstd
|
||||
- Homepage : http://www.zstd.net
|
||||
****************************************************************** */
|
||||
#ifndef ERROR_PUBLIC_H_MODULE
|
||||
#define ERROR_PUBLIC_H_MODULE
|
||||
@@ -47,6 +47,7 @@ typedef enum {
|
||||
ZSTD_error_prefix_unknown,
|
||||
ZSTD_error_frameParameter_unsupported,
|
||||
ZSTD_error_frameParameter_unsupportedBy32bits,
|
||||
ZSTD_error_compressionParameter_unsupported,
|
||||
ZSTD_error_init_missing,
|
||||
ZSTD_error_memory_allocation,
|
||||
ZSTD_error_stage_wrong,
|
||||
@@ -60,8 +61,7 @@ typedef enum {
|
||||
ZSTD_error_maxCode
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
/* note : functions provide error codes in reverse negative order,
|
||||
so compare with (size_t)(0-enum) */
|
||||
/* note : compare with size_t function results using ZSTD_getError() */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
||||
@@ -145,21 +145,18 @@ static U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3)
|
||||
|
||||
size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
const unsigned tableSize = 1 << tableLog;
|
||||
const unsigned tableMask = tableSize - 1;
|
||||
U32 const tableSize = 1 << tableLog;
|
||||
U32 const tableMask = tableSize - 1;
|
||||
void* const ptr = ct;
|
||||
U16* const tableU16 = ( (U16*) ptr) + 2;
|
||||
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
|
||||
FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
|
||||
const unsigned step = FSE_tableStep(tableSize);
|
||||
unsigned cumul[FSE_MAX_SYMBOL_VALUE+2];
|
||||
U32 position = 0;
|
||||
U32 const step = FSE_tableStep(tableSize);
|
||||
U32 cumul[FSE_MAX_SYMBOL_VALUE+2];
|
||||
FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */
|
||||
U32 highThreshold = tableSize-1;
|
||||
unsigned symbol;
|
||||
unsigned i;
|
||||
|
||||
/* header */
|
||||
/* CTable header */
|
||||
tableU16[-2] = (U16) tableLog;
|
||||
tableU16[-1] = (U16) maxSymbolValue;
|
||||
|
||||
@@ -167,42 +164,44 @@ size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned
|
||||
* http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
|
||||
|
||||
/* symbol start positions */
|
||||
cumul[0] = 0;
|
||||
for (i=1; i<=maxSymbolValue+1; i++) {
|
||||
if (normalizedCounter[i-1]==-1) { /* Low proba symbol */
|
||||
cumul[i] = cumul[i-1] + 1;
|
||||
tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(i-1);
|
||||
} else {
|
||||
cumul[i] = cumul[i-1] + normalizedCounter[i-1];
|
||||
} }
|
||||
cumul[maxSymbolValue+1] = tableSize+1;
|
||||
|
||||
/* Spread symbols */
|
||||
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
||||
int nbOccurences;
|
||||
for (nbOccurences=0; nbOccurences<normalizedCounter[symbol]; nbOccurences++) {
|
||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* Low proba area */
|
||||
} }
|
||||
|
||||
if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */
|
||||
|
||||
/* Build table */
|
||||
for (i=0; i<tableSize; i++) {
|
||||
FSE_FUNCTION_TYPE s = tableSymbol[i]; /* note : static analyzer may not understand tableSymbol is properly initialized */
|
||||
tableU16[cumul[s]++] = (U16) (tableSize+i); /* TableU16 : sorted by symbol order; gives next state value */
|
||||
{ U32 u;
|
||||
cumul[0] = 0;
|
||||
for (u=1; u<=maxSymbolValue+1; u++) {
|
||||
if (normalizedCounter[u-1]==-1) { /* Low proba symbol */
|
||||
cumul[u] = cumul[u-1] + 1;
|
||||
tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);
|
||||
} else {
|
||||
cumul[u] = cumul[u-1] + normalizedCounter[u-1];
|
||||
} }
|
||||
cumul[maxSymbolValue+1] = tableSize+1;
|
||||
}
|
||||
|
||||
/* Spread symbols */
|
||||
{ U32 position = 0;
|
||||
U32 symbol;
|
||||
for (symbol=0; symbol<=maxSymbolValue; symbol++) {
|
||||
int nbOccurences;
|
||||
for (nbOccurences=0; nbOccurences<normalizedCounter[symbol]; nbOccurences++) {
|
||||
tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* Low proba area */
|
||||
} }
|
||||
if (position!=0) return ERROR(GENERIC); /* Must have gone through all positions */
|
||||
}
|
||||
|
||||
/* Build table */
|
||||
{ U32 u; for (u=0; u<tableSize; u++) {
|
||||
FSE_FUNCTION_TYPE s = tableSymbol[u]; /* note : static analyzer may not understand tableSymbol is properly initialized */
|
||||
tableU16[cumul[s]++] = (U16) (tableSize+u); /* TableU16 : sorted by symbol order; gives next state value */
|
||||
}}
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
{
|
||||
{ unsigned total = 0;
|
||||
unsigned s;
|
||||
unsigned total = 0;
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
switch (normalizedCounter[s])
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 0: break;
|
||||
case -1:
|
||||
case 1:
|
||||
symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);
|
||||
@@ -211,8 +210,8 @@ size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned
|
||||
break;
|
||||
default :
|
||||
{
|
||||
U32 maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
|
||||
U32 minStatePlus = normalizedCounter[s] << maxBitsOut;
|
||||
U32 const maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
|
||||
U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;
|
||||
symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
|
||||
symbolTT[s].deltaFindState = total - normalizedCounter[s];
|
||||
total += normalizedCounter[s];
|
||||
@@ -242,9 +241,8 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned
|
||||
const U32 tableMask = tableSize-1;
|
||||
const U32 step = FSE_tableStep(tableSize);
|
||||
U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];
|
||||
U32 position = 0;
|
||||
U32 highThreshold = tableSize-1;
|
||||
const S16 largeLimit= (S16)(1 << (tableLog-1));
|
||||
S16 const largeLimit= (S16)(1 << (tableLog-1));
|
||||
U32 noLarge = 1;
|
||||
U32 s;
|
||||
|
||||
@@ -264,24 +262,24 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned
|
||||
} }
|
||||
|
||||
/* Spread symbols */
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
int i;
|
||||
for (i=0; i<normalizedCounter[s]; i++) {
|
||||
tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
|
||||
} }
|
||||
|
||||
if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
|
||||
{ U32 position = 0;
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
int i;
|
||||
for (i=0; i<normalizedCounter[s]; i++) {
|
||||
tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
|
||||
position = (position + step) & tableMask;
|
||||
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
|
||||
} }
|
||||
if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
|
||||
}
|
||||
|
||||
/* Build Decoding table */
|
||||
{
|
||||
U32 i;
|
||||
for (i=0; i<tableSize; i++) {
|
||||
FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);
|
||||
{ U32 u;
|
||||
for (u=0; u<tableSize; u++) {
|
||||
FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
|
||||
U16 nextState = symbolNext[symbol]++;
|
||||
tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
|
||||
tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);
|
||||
tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );
|
||||
tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
|
||||
} }
|
||||
|
||||
DTableH.fastMode = (U16)noLarge;
|
||||
@@ -365,8 +363,7 @@ static size_t FSE_writeNCount_generic (void* header, size_t headerBufferSize,
|
||||
bitStream >>= 16;
|
||||
bitCount -= 16;
|
||||
} }
|
||||
{
|
||||
short count = normalizedCounter[charnum++];
|
||||
{ short count = normalizedCounter[charnum++];
|
||||
const short max = (short)((2*threshold-1)-remaining);
|
||||
remaining -= FSE_abs(count);
|
||||
if (remaining<1) return ERROR(GENERIC);
|
||||
@@ -465,8 +462,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
|
||||
else
|
||||
bitStream >>= 2;
|
||||
}
|
||||
{
|
||||
const short max = (short)((2*threshold-1)-remaining);
|
||||
{ short const max = (short)((2*threshold-1)-remaining);
|
||||
short count;
|
||||
|
||||
if ((bitStream & (threshold-1)) < (U32)max) {
|
||||
@@ -509,11 +505,11 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
|
||||
* Counting histogram
|
||||
****************************************************************/
|
||||
/*! FSE_count_simple
|
||||
This function just counts byte values within @src,
|
||||
and store the histogram into @count.
|
||||
This function is unsafe : it doesn't check that all values within @src can fit into @count.
|
||||
For this reason, prefer using a table @count with 256 elements.
|
||||
@return : highest count for a single element
|
||||
This function just counts byte values within `src`,
|
||||
and store the histogram into table `count`.
|
||||
This function is unsafe : it doesn't check that all values within `src` can fit into `count`.
|
||||
For this reason, prefer using a table `count` with 256 elements.
|
||||
@return : count of most numerous element
|
||||
*/
|
||||
static size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const void* src, size_t srcSize)
|
||||
@@ -522,7 +518,6 @@ static size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const BYTE* const end = ip + srcSize;
|
||||
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
||||
unsigned max=0;
|
||||
U32 s;
|
||||
|
||||
memset(count, 0, (maxSymbolValue+1)*sizeof(*count));
|
||||
if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }
|
||||
@@ -532,7 +527,7 @@ static size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
while (!count[maxSymbolValue]) maxSymbolValue--;
|
||||
*maxSymbolValuePtr = maxSymbolValue;
|
||||
|
||||
for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s];
|
||||
{ U32 s; for (s=0; s<=maxSymbolValue; s++) if (count[s] > max) max = count[s]; }
|
||||
|
||||
return (size_t)max;
|
||||
}
|
||||
@@ -546,7 +541,6 @@ static size_t FSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
const BYTE* const iend = ip+sourceSize;
|
||||
unsigned maxSymbolValue = *maxSymbolValuePtr;
|
||||
unsigned max=0;
|
||||
U32 s;
|
||||
|
||||
U32 Counting1[256] = { 0 };
|
||||
U32 Counting2[256] = { 0 };
|
||||
@@ -561,8 +555,8 @@ static size_t FSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
}
|
||||
if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */
|
||||
|
||||
{ /* by stripes of 16 bytes */
|
||||
U32 cached = MEM_read32(ip); ip += 4;
|
||||
/* by stripes of 16 bytes */
|
||||
{ U32 cached = MEM_read32(ip); ip += 4;
|
||||
while (ip < iend-15) {
|
||||
U32 c = cached; cached = MEM_read32(ip); ip += 4;
|
||||
Counting1[(BYTE) c ]++;
|
||||
@@ -592,15 +586,15 @@ static size_t FSE_count_parallel(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
while (ip<iend) Counting1[*ip++]++;
|
||||
|
||||
if (checkMax) { /* verify stats will fit into destination table */
|
||||
for (s=255; s>maxSymbolValue; s--) {
|
||||
U32 s; for (s=255; s>maxSymbolValue; s--) {
|
||||
Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];
|
||||
if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall);
|
||||
} }
|
||||
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
{ U32 s; for (s=0; s<=maxSymbolValue; s++) {
|
||||
count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s];
|
||||
if (count[s] > max) max = count[s];
|
||||
}
|
||||
}}
|
||||
|
||||
while (!count[maxSymbolValue]) maxSymbolValue--;
|
||||
*maxSymbolValuePtr = maxSymbolValue;
|
||||
@@ -634,7 +628,7 @@ size_t FSE_count(unsigned* count, unsigned* maxSymbolValuePtr,
|
||||
`U16 maxSymbolValue;`
|
||||
`U16 nextStateNumber[1 << tableLog];` // This size is variable
|
||||
`FSE_symbolCompressionTransform symbolTT[maxSymbolValue+1];` // This size is variable
|
||||
Allocation is manual, since C standard does not support variable-size structures.
|
||||
Allocation is manual (C standard does not support variable-size structures).
|
||||
*/
|
||||
|
||||
size_t FSE_sizeof_CTable (unsigned maxSymbolValue, unsigned tableLog)
|
||||
@@ -730,7 +724,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count,
|
||||
/* all values are pretty poor;
|
||||
probably incompressible data (should have already been detected);
|
||||
find max, then give all remaining points to max */
|
||||
U32 maxV = 0, maxC =0;
|
||||
U32 maxV = 0, maxC = 0;
|
||||
for (s=0; s<=maxSymbolValue; s++)
|
||||
if (count[s] > maxC) maxV=s, maxC=count[s];
|
||||
norm[maxV] += (short)ToDistribute;
|
||||
@@ -768,8 +762,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
|
||||
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); /* Unsupported size */
|
||||
if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */
|
||||
|
||||
{
|
||||
U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
|
||||
{ U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };
|
||||
U64 const scale = 62 - tableLog;
|
||||
U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */
|
||||
U64 const vStep = 1ULL<<(scale-20);
|
||||
@@ -845,13 +838,11 @@ size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits)
|
||||
tableU16[s] = (U16)(tableSize + s);
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
{
|
||||
const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);
|
||||
{ const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
symbolTT[s].deltaNbBits = deltaNbBits;
|
||||
symbolTT[s].deltaFindState = s-1;
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -887,15 +878,13 @@ static size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,
|
||||
const BYTE* const istart = (const BYTE*) src;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* ip=iend;
|
||||
|
||||
size_t errorCode;
|
||||
BIT_CStream_t bitC;
|
||||
FSE_CState_t CState1, CState2;
|
||||
|
||||
/* init */
|
||||
if (srcSize <= 2) return 0;
|
||||
errorCode = BIT_initCStream(&bitC, dst, dstSize);
|
||||
if (FSE_isError(errorCode)) return 0;
|
||||
{ size_t const errorCode = BIT_initCStream(&bitC, dst, dstSize);
|
||||
if (FSE_isError(errorCode)) return 0; }
|
||||
|
||||
#define FSE_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
|
||||
|
||||
@@ -918,8 +907,7 @@ static size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,
|
||||
}
|
||||
|
||||
/* 2 or 4 encoding per loop */
|
||||
for ( ; ip>istart ; )
|
||||
{
|
||||
for ( ; ip>istart ; ) {
|
||||
FSE_encodeSymbol(&bitC, &CState2, *--ip);
|
||||
|
||||
if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 ) /* this test must be static */
|
||||
|
||||
+19
-14
@@ -267,7 +267,7 @@ MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePt
|
||||
BIT_flushBits(bitC);
|
||||
}
|
||||
|
||||
/* decompression */
|
||||
/*<===== Decompression =====>*/
|
||||
|
||||
typedef struct {
|
||||
U16 tableLog;
|
||||
@@ -290,34 +290,39 @@ MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, con
|
||||
DStatePtr->table = dt + 1;
|
||||
}
|
||||
|
||||
MEM_STATIC size_t FSE_getStateValue(FSE_DState_t* DStatePtr)
|
||||
MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
|
||||
{
|
||||
return DStatePtr->state;
|
||||
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
return DInfo.symbol;
|
||||
}
|
||||
|
||||
MEM_STATIC BYTE FSE_peakSymbol(FSE_DState_t* DStatePtr)
|
||||
MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
return DInfo.symbol;
|
||||
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
}
|
||||
|
||||
MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
const U32 nbBits = DInfo.nbBits;
|
||||
BYTE symbol = DInfo.symbol;
|
||||
size_t lowBits = BIT_readBits(bitD, nbBits);
|
||||
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
BYTE const symbol = DInfo.symbol;
|
||||
size_t const lowBits = BIT_readBits(bitD, nbBits);
|
||||
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/*! FSE_decodeSymbolFast() :
|
||||
unsafe, only works if no symbol has a probability > 50% */
|
||||
MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
|
||||
{
|
||||
const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
const U32 nbBits = DInfo.nbBits;
|
||||
BYTE symbol = DInfo.symbol;
|
||||
size_t lowBits = BIT_readBitsFast(bitD, nbBits);
|
||||
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
|
||||
U32 const nbBits = DInfo.nbBits;
|
||||
BYTE const symbol = DInfo.symbol;
|
||||
size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
|
||||
|
||||
DStatePtr->state = DInfo.newState + lowBits;
|
||||
return symbol;
|
||||
|
||||
+101
-130
@@ -1,6 +1,6 @@
|
||||
/* ******************************************************************
|
||||
Huff0 : Huffman coder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
@@ -103,8 +103,7 @@ typedef struct nodeElt_s {
|
||||
} nodeElt;
|
||||
|
||||
/*! HUF_writeCTable() :
|
||||
@dst : destination buffer
|
||||
@CTable : huffman tree to save, using huff0 representation
|
||||
`CTable` : huffman tree to save, using huff0 representation.
|
||||
@return : size of saved CTable */
|
||||
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
||||
const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
|
||||
@@ -181,66 +180,58 @@ size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, si
|
||||
BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];
|
||||
U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1]; /* large enough for values from 0 to 16 */
|
||||
U32 tableLog = 0;
|
||||
size_t iSize;
|
||||
size_t readSize;
|
||||
U32 nbSymbols = 0;
|
||||
U32 n;
|
||||
U32 nextRankStart;
|
||||
//memset(huffWeight, 0, sizeof(huffWeight)); /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
/* get symbol weights */
|
||||
iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE+1, rankVal, &nbSymbols, &tableLog, src, srcSize);
|
||||
if (HUF_isError(iSize)) return iSize;
|
||||
readSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE+1, rankVal, &nbSymbols, &tableLog, src, srcSize);
|
||||
if (HUF_isError(readSize)) return readSize;
|
||||
|
||||
/* check result */
|
||||
if (tableLog > HUF_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
|
||||
if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall);
|
||||
|
||||
/* Prepare base value per rank */
|
||||
nextRankStart = 0;
|
||||
for (n=1; n<=tableLog; n++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += (rankVal[n] << (n-1));
|
||||
rankVal[n] = current;
|
||||
}
|
||||
{ U32 n, nextRankStart = 0;
|
||||
for (n=1; n<=tableLog; n++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += (rankVal[n] << (n-1));
|
||||
rankVal[n] = current;
|
||||
} }
|
||||
|
||||
/* fill nbBits */
|
||||
for (n=0; n<nbSymbols; n++) {
|
||||
{ U32 n; for (n=0; n<nbSymbols; n++) {
|
||||
const U32 w = huffWeight[n];
|
||||
CTable[n].nbBits = (BYTE)(tableLog + 1 - w);
|
||||
}
|
||||
}}
|
||||
|
||||
/* fill val */
|
||||
{
|
||||
U16 nbPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
{ U16 nbPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
U16 valPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
for (n=0; n<nbSymbols; n++)
|
||||
nbPerRank[CTable[n].nbBits]++;
|
||||
{
|
||||
/* determine stating value per rank */
|
||||
U16 min = 0;
|
||||
for (n=HUF_MAX_TABLELOG; n>0; n--) {
|
||||
{ U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; }
|
||||
/* determine stating value per rank */
|
||||
{ U16 min = 0;
|
||||
U32 n; for (n=HUF_MAX_TABLELOG; n>0; n--) {
|
||||
valPerRank[n] = min; /* get starting value within each rank */
|
||||
min += nbPerRank[n];
|
||||
min >>= 1;
|
||||
} }
|
||||
for (n=0; n<=maxSymbolValue; n++)
|
||||
CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */
|
||||
/* assign value within rank, symbol order */
|
||||
{ U32 n; for (n=0; n<=maxSymbolValue; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
|
||||
}
|
||||
|
||||
return iSize;
|
||||
return readSize;
|
||||
}
|
||||
|
||||
|
||||
static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
{
|
||||
int totalCost = 0;
|
||||
const U32 largestBits = huffNode[lastNonNull].nbBits;
|
||||
|
||||
/* early exit : all is fine */
|
||||
if (largestBits <= maxNbBits) return largestBits;
|
||||
if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */
|
||||
|
||||
/* there are several too large elements (at least >= 2) */
|
||||
{
|
||||
{ int totalCost = 0;
|
||||
const U32 baseCost = 1 << (largestBits - maxNbBits);
|
||||
U32 n = lastNonNull;
|
||||
|
||||
@@ -248,26 +239,25 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
|
||||
huffNode[n].nbBits = (BYTE)maxNbBits;
|
||||
n --;
|
||||
} /* n stops at huffNode[n].nbBits <= maxNbBits */
|
||||
while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using (maxNbBits-1) */
|
||||
} /* n stops at huffNode[n].nbBits <= maxNbBits */
|
||||
while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */
|
||||
|
||||
/* renorm totalCost */
|
||||
totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */
|
||||
|
||||
/* repay normalized cost */
|
||||
{
|
||||
const U32 noSymbol = 0xF0F0F0F0;
|
||||
{ U32 const noSymbol = 0xF0F0F0F0;
|
||||
U32 rankLast[HUF_MAX_TABLELOG+1];
|
||||
U32 currentNbBits = maxNbBits;
|
||||
int pos;
|
||||
|
||||
/* Get pos of last (smallest) symbol per rank */
|
||||
memset(rankLast, 0xF0, sizeof(rankLast));
|
||||
for (pos=n ; pos >= 0; pos--) {
|
||||
if (huffNode[pos].nbBits >= currentNbBits) continue;
|
||||
currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */
|
||||
rankLast[maxNbBits-currentNbBits] = pos;
|
||||
}
|
||||
{ U32 currentNbBits = maxNbBits;
|
||||
for (pos=n ; pos >= 0; pos--) {
|
||||
if (huffNode[pos].nbBits >= currentNbBits) continue;
|
||||
currentNbBits = huffNode[pos].nbBits; /* < maxNbBits */
|
||||
rankLast[maxNbBits-currentNbBits] = pos;
|
||||
} }
|
||||
|
||||
while (totalCost > 0) {
|
||||
U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1;
|
||||
@@ -276,9 +266,8 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
U32 lowPos = rankLast[nBitsToDecrease-1];
|
||||
if (highPos == noSymbol) continue;
|
||||
if (lowPos == noSymbol) break;
|
||||
{
|
||||
U32 highTotal = huffNode[highPos].count;
|
||||
U32 lowTotal = 2 * huffNode[lowPos].count;
|
||||
{ U32 const highTotal = huffNode[highPos].count;
|
||||
U32 const lowTotal = 2 * huffNode[lowPos].count;
|
||||
if (highTotal <= lowTotal) break;
|
||||
} }
|
||||
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
|
||||
@@ -294,7 +283,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
rankLast[nBitsToDecrease]--;
|
||||
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)
|
||||
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
|
||||
} }
|
||||
} } /* while (totalCost > 0) */
|
||||
|
||||
while (totalCost < 0) { /* Sometimes, cost correction overshoot */
|
||||
if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */
|
||||
@@ -307,7 +296,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
|
||||
huffNode[ rankLast[1] + 1 ].nbBits--;
|
||||
rankLast[1]++;
|
||||
totalCost ++;
|
||||
} } }
|
||||
} } } /* there are several too large elements (at least >= 2) */
|
||||
|
||||
return maxNbBits;
|
||||
}
|
||||
@@ -331,8 +320,8 @@ static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue)
|
||||
for (n=30; n>0; n--) rank[n-1].base += rank[n].base;
|
||||
for (n=0; n<32; n++) rank[n].current = rank[n].base;
|
||||
for (n=0; n<=maxSymbolValue; n++) {
|
||||
U32 c = count[n];
|
||||
U32 r = BIT_highbit32(c+1) + 1;
|
||||
U32 const c = count[n];
|
||||
U32 const r = BIT_highbit32(c+1) + 1;
|
||||
U32 pos = rank[r].current++;
|
||||
while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) huffNode[pos]=huffNode[pos-1], pos--;
|
||||
huffNode[pos].count = c;
|
||||
@@ -389,21 +378,18 @@ size_t HUF_buildCTable (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U3
|
||||
maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits);
|
||||
|
||||
/* fill result into tree (val, nbBits) */
|
||||
{
|
||||
U16 nbPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
{ U16 nbPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
U16 valPerRank[HUF_MAX_TABLELOG+1] = {0};
|
||||
if (maxNbBits > HUF_MAX_TABLELOG) return ERROR(GENERIC); /* check fit into table */
|
||||
for (n=0; n<=nonNullRank; n++)
|
||||
nbPerRank[huffNode[n].nbBits]++;
|
||||
{
|
||||
/* determine stating value per rank */
|
||||
U16 min = 0;
|
||||
/* determine stating value per rank */
|
||||
{ U16 min = 0;
|
||||
for (n=maxNbBits; n>0; n--) {
|
||||
valPerRank[n] = min; /* get starting value within each rank */
|
||||
min += nbPerRank[n];
|
||||
min >>= 1;
|
||||
}
|
||||
}
|
||||
} }
|
||||
for (n=0; n<=maxSymbolValue; n++)
|
||||
tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
|
||||
for (n=0; n<=maxSymbolValue; n++)
|
||||
@@ -432,17 +418,16 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
size_t n;
|
||||
const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize));
|
||||
size_t errorCode;
|
||||
BIT_CStream_t bitC;
|
||||
|
||||
/* init */
|
||||
if (dstSize < 8) return 0; /* not enough space to compress */
|
||||
errorCode = BIT_initCStream(&bitC, op, oend-op);
|
||||
if (HUF_isError(errorCode)) return 0;
|
||||
{ size_t const errorCode = BIT_initCStream(&bitC, op, oend-op);
|
||||
if (HUF_isError(errorCode)) return 0; }
|
||||
|
||||
n = srcSize & ~3; /* join to mod 4 */
|
||||
switch (srcSize & 3)
|
||||
@@ -475,12 +460,12 @@ size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, si
|
||||
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
|
||||
{
|
||||
size_t segmentSize = (srcSize+3)/4; /* first 3 segments */
|
||||
size_t errorCode;
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
const BYTE* const iend = ip + srcSize;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
size_t errorCode;
|
||||
|
||||
if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */
|
||||
if (srcSize < 12) return 0; /* no saving possible : too small input */
|
||||
@@ -523,8 +508,8 @@ static size_t HUF_compress_internal (
|
||||
unsigned singleStream)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
BYTE* op = ostart;
|
||||
|
||||
U32 count[HUF_MAX_SYMBOL_VALUE+1];
|
||||
HUF_CElt CTable[HUF_MAX_SYMBOL_VALUE+1];
|
||||
@@ -573,8 +558,8 @@ static size_t HUF_compress_internal (
|
||||
|
||||
|
||||
size_t HUF_compress1X (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
{
|
||||
return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1);
|
||||
}
|
||||
@@ -602,9 +587,9 @@ typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4; /* doubl
|
||||
|
||||
typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
|
||||
|
||||
/*! HUF_readStats
|
||||
Read compact Huffman tree, saved by HUF_writeCTable
|
||||
@huffWeight : destination buffer
|
||||
/*! HUF_readStats() :
|
||||
Read compact Huffman tree, saved by HUF_writeCTable().
|
||||
`huffWeight` is destination buffer.
|
||||
@return : size read from `src`
|
||||
*/
|
||||
static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
@@ -616,13 +601,12 @@ static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
size_t iSize = ip[0];
|
||||
size_t oSize;
|
||||
U32 n;
|
||||
|
||||
//memset(huffWeight, 0, hwSize); /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
if (iSize >= 128) { /* special header */
|
||||
if (iSize >= (242)) { /* RLE */
|
||||
static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
|
||||
static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
|
||||
oSize = l[iSize-242];
|
||||
memset(huffWeight, 1, hwSize);
|
||||
iSize = 0;
|
||||
@@ -633,10 +617,11 @@ static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||
if (oSize >= hwSize) return ERROR(corruption_detected);
|
||||
ip += 1;
|
||||
for (n=0; n<oSize; n+=2) {
|
||||
huffWeight[n] = ip[n/2] >> 4;
|
||||
huffWeight[n+1] = ip[n/2] & 15;
|
||||
} } }
|
||||
{ U32 n;
|
||||
for (n=0; n<oSize; n+=2) {
|
||||
huffWeight[n] = ip[n/2] >> 4;
|
||||
huffWeight[n+1] = ip[n/2] & 15;
|
||||
} } } }
|
||||
else { /* header compressed with FSE (normal case) */
|
||||
if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
|
||||
oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize); /* max (hwSize-1) values decoded, as last one is implied */
|
||||
@@ -646,20 +631,20 @@ static size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
/* collect weight stats */
|
||||
memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));
|
||||
weightTotal = 0;
|
||||
for (n=0; n<oSize; n++) {
|
||||
{ U32 n; for (n=0; n<oSize; n++) {
|
||||
if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
|
||||
rankStats[huffWeight[n]]++;
|
||||
weightTotal += (1 << huffWeight[n]) >> 1;
|
||||
}
|
||||
}}
|
||||
|
||||
/* get last non-null symbol weight (implied, total must be 2^n) */
|
||||
tableLog = BIT_highbit32(weightTotal) + 1;
|
||||
if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);
|
||||
{ /* determine last weight */
|
||||
U32 total = 1 << tableLog;
|
||||
U32 rest = total - weightTotal;
|
||||
U32 verif = 1 << BIT_highbit32(rest);
|
||||
U32 lastWeight = BIT_highbit32(rest) + 1;
|
||||
/* determine last weight */
|
||||
{ U32 const total = 1 << tableLog;
|
||||
U32 const rest = total - weightTotal;
|
||||
U32 const verif = 1 << BIT_highbit32(rest);
|
||||
U32 const lastWeight = BIT_highbit32(rest) + 1;
|
||||
if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
|
||||
huffWeight[oSize] = (BYTE)lastWeight;
|
||||
rankStats[lastWeight]++;
|
||||
@@ -724,12 +709,13 @@ size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)
|
||||
return iSize;
|
||||
}
|
||||
|
||||
|
||||
static BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)
|
||||
{
|
||||
const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
|
||||
const BYTE c = dt[val].byte;
|
||||
BIT_skipBits(Dstream, dt[val].nbBits);
|
||||
return c;
|
||||
const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
|
||||
const BYTE c = dt[val].byte;
|
||||
BIT_skipBits(Dstream, dt[val].nbBits);
|
||||
return c;
|
||||
}
|
||||
|
||||
#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
|
||||
@@ -773,13 +759,13 @@ size_t HUF_decompress1X2_usingDTable(
|
||||
{
|
||||
BYTE* op = (BYTE*)dst;
|
||||
BYTE* const oend = op + dstSize;
|
||||
size_t errorCode;
|
||||
const U32 dtLog = DTable[0];
|
||||
const void* dtPtr = DTable;
|
||||
const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr)+1;
|
||||
BIT_DStream_t bitD;
|
||||
errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode;
|
||||
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode; }
|
||||
|
||||
HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
|
||||
|
||||
@@ -793,9 +779,8 @@ size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
size_t errorCode;
|
||||
|
||||
errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);
|
||||
size_t const errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode;
|
||||
if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += errorCode;
|
||||
@@ -812,8 +797,8 @@ size_t HUF_decompress4X2_usingDTable(
|
||||
{
|
||||
/* Check */
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) cSrc;
|
||||
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable;
|
||||
@@ -903,9 +888,8 @@ size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
size_t errorCode;
|
||||
|
||||
errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);
|
||||
size_t const errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode;
|
||||
if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += errorCode;
|
||||
@@ -926,7 +910,6 @@ static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 co
|
||||
{
|
||||
HUF_DEltX4 DElt;
|
||||
U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];
|
||||
U32 s;
|
||||
|
||||
/* get pre-calculated rankVal */
|
||||
memcpy(rankVal, rankValOrigin, sizeof(rankVal));
|
||||
@@ -942,7 +925,7 @@ static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 co
|
||||
}
|
||||
|
||||
/* fill DTable */
|
||||
for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
|
||||
{ U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
|
||||
const U32 symbol = sortedSymbols[s].symbol;
|
||||
const U32 weight = sortedSymbols[s].weight;
|
||||
const U32 nbBits = nbBitsBaseline - weight;
|
||||
@@ -957,7 +940,7 @@ static void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 co
|
||||
do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */
|
||||
|
||||
rankVal[weight] += length;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
typedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];
|
||||
@@ -992,16 +975,14 @@ static void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,
|
||||
sortedList+sortedRank, sortedListSize-sortedRank,
|
||||
nbBitsBaseline, symbol);
|
||||
} else {
|
||||
U32 i;
|
||||
const U32 end = start + length;
|
||||
HUF_DEltX4 DElt;
|
||||
|
||||
MEM_writeLE16(&(DElt.sequence), symbol);
|
||||
DElt.nbBits = (BYTE)(nbBits);
|
||||
DElt.length = 1;
|
||||
for (i = start; i < end; i++)
|
||||
DTable[i] = DElt;
|
||||
}
|
||||
DElt.nbBits = (BYTE)(nbBits);
|
||||
DElt.length = 1;
|
||||
{ U32 u;
|
||||
const U32 end = start + length;
|
||||
for (u = start; u < end; u++) DTable[u] = DElt;
|
||||
} }
|
||||
rankVal[weight] += length;
|
||||
}
|
||||
}
|
||||
@@ -1034,8 +1015,7 @@ size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
|
||||
for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
|
||||
|
||||
/* Get start index of each weight */
|
||||
{
|
||||
U32 w, nextRankStart = 0;
|
||||
{ U32 w, nextRankStart = 0;
|
||||
for (w=1; w<=maxW; w++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += rankStats[w];
|
||||
@@ -1046,8 +1026,7 @@ size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
|
||||
}
|
||||
|
||||
/* sort symbols by weight */
|
||||
{
|
||||
U32 s;
|
||||
{ U32 s;
|
||||
for (s=0; s<nbSymbols; s++) {
|
||||
U32 w = weightList[s];
|
||||
U32 r = rankStart[w]++;
|
||||
@@ -1058,8 +1037,7 @@ size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
{
|
||||
const U32 minBits = tableLog+1 - maxW;
|
||||
{ const U32 minBits = tableLog+1 - maxW;
|
||||
U32 nextRankVal = 0;
|
||||
U32 w, consumed;
|
||||
const int rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */
|
||||
@@ -1156,15 +1134,14 @@ size_t HUF_decompress1X4_usingDTable(
|
||||
const U32 dtLog = DTable[0];
|
||||
const void* const dtPtr = DTable;
|
||||
const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1;
|
||||
size_t errorCode;
|
||||
|
||||
/* Init */
|
||||
BIT_DStream_t bitD;
|
||||
errorCode = BIT_initDStream(&bitD, istart, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode;
|
||||
{ size_t const errorCode = BIT_initDStream(&bitD, istart, cSrcSize);
|
||||
if (HUF_isError(errorCode)) return errorCode; }
|
||||
|
||||
/* finish bitStreams one by one */
|
||||
HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);
|
||||
/* decode */
|
||||
HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);
|
||||
|
||||
/* check */
|
||||
if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
|
||||
@@ -1178,7 +1155,7 @@ size_t HUF_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);
|
||||
size_t const hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize;
|
||||
@@ -1194,8 +1171,7 @@ size_t HUF_decompress4X4_usingDTable(
|
||||
{
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) cSrc;
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
const void* const dtPtr = DTable;
|
||||
@@ -1385,8 +1361,7 @@ size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
|
||||
for (maxW = tableLog; maxW && rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
|
||||
|
||||
/* Get start index of each weight */
|
||||
{
|
||||
U32 w, nextRankStart = 0;
|
||||
{ U32 w, nextRankStart = 0;
|
||||
for (w=1; w<=maxW; w++) {
|
||||
U32 current = nextRankStart;
|
||||
nextRankStart += rankStats[w];
|
||||
@@ -1397,8 +1372,7 @@ size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
|
||||
}
|
||||
|
||||
/* sort symbols by weight */
|
||||
{
|
||||
U32 s;
|
||||
{ U32 s;
|
||||
for (s=0; s<nbSymbols; s++) {
|
||||
U32 w = weightList[s];
|
||||
U32 r = rankStart[w]++;
|
||||
@@ -1409,8 +1383,7 @@ size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
|
||||
}
|
||||
|
||||
/* Build rankVal */
|
||||
{
|
||||
const U32 minBits = tableLog+1 - maxW;
|
||||
{ const U32 minBits = tableLog+1 - maxW;
|
||||
U32 nextRankVal = 0;
|
||||
U32 w, consumed;
|
||||
const int rescale = (memLog-tableLog) - 1; /* tableLog <= memLog */
|
||||
@@ -1427,8 +1400,7 @@ size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)
|
||||
} } }
|
||||
|
||||
/* fill tables */
|
||||
{
|
||||
void* ddPtr = DTable+1;
|
||||
{ void* ddPtr = DTable+1;
|
||||
HUF_DDescX6* DDescription = (HUF_DDescX6*)ddPtr;
|
||||
void* dsPtr = DTable + 1 + ((size_t)1<<(memLog-1));
|
||||
HUF_DSeqX6* DSequence = (HUF_DSeqX6*)dsPtr;
|
||||
@@ -1563,8 +1535,7 @@ size_t HUF_decompress4X6_usingDTable(
|
||||
/* Check */
|
||||
if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
|
||||
|
||||
{
|
||||
const BYTE* const istart = (const BYTE*) cSrc;
|
||||
{ const BYTE* const istart = (const BYTE*) cSrc;
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
|
||||
@@ -1659,7 +1630,7 @@ size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG);
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize);
|
||||
size_t const hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize;
|
||||
|
||||
+11
-11
@@ -48,24 +48,24 @@ extern "C" {
|
||||
/* ****************************************
|
||||
* Huff0 simple functions
|
||||
******************************************/
|
||||
size_t HUF_compress(void* dst, size_t maxDstSize,
|
||||
size_t HUF_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
size_t HUF_decompress(void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
/*!
|
||||
HUF_compress():
|
||||
/*
|
||||
HUF_compress() :
|
||||
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
||||
'dst' buffer must be already allocated. Compression runs faster if maxDstSize >= HUF_compressBound(srcSize).
|
||||
'dst' buffer must be already allocated. Compression runs faster if dstCapacity >= HUF_compressBound(srcSize).
|
||||
Note : srcSize must be <= 128 KB
|
||||
@return : size of compressed data (<= maxDstSize)
|
||||
@return : size of compressed data (<= dstCapacity)
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||
if return == 1, srcData is a single repeated byte symbol (RLE compression)
|
||||
if return == 1, srcData is a single repeated byte symbol (RLE compression).
|
||||
if HUF_isError(return), compression failed (more details using HUF_getErrorName())
|
||||
|
||||
HUF_decompress():
|
||||
HUF_decompress() :
|
||||
Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',
|
||||
into already allocated destination buffer 'dst', of size 'dstSize'.
|
||||
@dstSize : must be the **exact** size of original (uncompressed) data.
|
||||
`dstSize` : must be the **exact** size of original (uncompressed) data.
|
||||
Note : in contrast with FSE, HUF_decompress can regenerate
|
||||
RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
|
||||
because it knows size to regenerate.
|
||||
@@ -77,11 +77,11 @@ HUF_decompress():
|
||||
/* ****************************************
|
||||
* Tool functions
|
||||
******************************************/
|
||||
size_t HUF_compressBound(size_t size); /* maximum compressed size */
|
||||
size_t HUF_compressBound(size_t size); /**< maximum compressed size */
|
||||
|
||||
/* 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) */
|
||||
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) */
|
||||
|
||||
|
||||
/* ****************************************
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ HUF_compress() does the following:
|
||||
1. count symbol occurrence from source[] into table count[] using FSE_count()
|
||||
2. build Huffman table from count using HUF_buildCTable()
|
||||
3. save Huffman table to memory buffer using HUF_writeCTable()
|
||||
4. encode the data stream using HUF_compress_usingCTable()
|
||||
4. encode the data stream using HUF_compress4X_usingCTable()
|
||||
|
||||
The following API allows targeting specific sub-functions for advanced tasks.
|
||||
For example, it's possible to compress several blocks using the same 'CTable',
|
||||
@@ -95,7 +95,7 @@ or to save and regenerate 'CTable' using external methods.
|
||||
typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
|
||||
size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);
|
||||
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
|
||||
size_t HUF_compress4X_into4Segments(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||
|
||||
|
||||
/*!
|
||||
|
||||
+66
-75
@@ -26,14 +26,9 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd source repository : https://github.com/Cyan4973/zstd
|
||||
- ztsd public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
- zstd homepage : http://www.zstd.net/
|
||||
*/
|
||||
|
||||
/* The objects defined into this file should be considered experimental.
|
||||
* They are not labelled stable, as their prototype may change in the future.
|
||||
* You can use them for tests, provide feedback, or if you can endure risk of future changes.
|
||||
*/
|
||||
|
||||
/* *************************************
|
||||
* Dependencies
|
||||
@@ -124,21 +119,20 @@ size_t ZBUFF_freeCCtx(ZBUFF_CCtx* zbc)
|
||||
|
||||
/* *** Initialization *** */
|
||||
|
||||
size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, ZSTD_parameters params)
|
||||
size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
{
|
||||
size_t neededInBuffSize;
|
||||
|
||||
ZSTD_validateParams(¶ms);
|
||||
neededInBuffSize = (size_t)1 << params.windowLog;
|
||||
|
||||
/* allocate buffers */
|
||||
if (zbc->inBuffSize < neededInBuffSize) {
|
||||
zbc->inBuffSize = neededInBuffSize;
|
||||
free(zbc->inBuff); /* should not be necessary */
|
||||
zbc->inBuff = (char*)malloc(neededInBuffSize);
|
||||
if (zbc->inBuff == NULL) return ERROR(memory_allocation);
|
||||
{ size_t const neededInBuffSize = (size_t)1 << params.cParams.windowLog;
|
||||
if (zbc->inBuffSize < neededInBuffSize) {
|
||||
zbc->inBuffSize = neededInBuffSize;
|
||||
free(zbc->inBuff); /* should not be necessary */
|
||||
zbc->inBuff = (char*)malloc(neededInBuffSize);
|
||||
if (zbc->inBuff == NULL) return ERROR(memory_allocation);
|
||||
}
|
||||
zbc->blockSize = MIN(ZSTD_BLOCKSIZE_MAX, neededInBuffSize/2);
|
||||
}
|
||||
zbc->blockSize = MIN(ZSTD_BLOCKSIZE_MAX, zbc->inBuffSize);
|
||||
if (zbc->outBuffSize < ZSTD_compressBound(zbc->blockSize)+1) {
|
||||
zbc->outBuffSize = ZSTD_compressBound(zbc->blockSize)+1;
|
||||
free(zbc->outBuff); /* should not be necessary */
|
||||
@@ -146,26 +140,30 @@ size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* zbc, const void* dict, size_t dic
|
||||
if (zbc->outBuff == NULL) return ERROR(memory_allocation);
|
||||
}
|
||||
|
||||
zbc->outBuffContentSize = ZSTD_compressBegin_advanced(zbc->zc, dict, dictSize, params);
|
||||
if (ZSTD_isError(zbc->outBuffContentSize)) return zbc->outBuffContentSize;
|
||||
{ size_t const errorCode = ZSTD_compressBegin_advanced(zbc->zc, dict, dictSize, params, pledgedSrcSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode; }
|
||||
|
||||
zbc->inToCompress = 0;
|
||||
zbc->inBuffPos = 0;
|
||||
zbc->inBuffTarget = zbc->blockSize;
|
||||
zbc->outBuffFlushedSize = 0;
|
||||
zbc->stage = ZBUFFcs_flush; /* starts by flushing the header */
|
||||
zbc->stage = ZBUFFcs_load;
|
||||
return 0; /* ready to go */
|
||||
}
|
||||
|
||||
|
||||
size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters params;
|
||||
params.cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
params.fParams.contentSizeFlag = 0;
|
||||
ZSTD_adjustCParams(¶ms.cParams, 0, dictSize);
|
||||
return ZBUFF_compressInit_advanced(zbc, dict, dictSize, params, 0);
|
||||
}
|
||||
|
||||
size_t ZBUFF_compressInit(ZBUFF_CCtx* zbc, int compressionLevel)
|
||||
{
|
||||
return ZBUFF_compressInit_advanced(zbc, NULL, 0, ZSTD_getParams(compressionLevel, 0));
|
||||
}
|
||||
|
||||
|
||||
ZSTDLIB_API size_t ZBUFF_compressInitDictionary(ZBUFF_CCtx* zbc, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
return ZBUFF_compressInit_advanced(zbc, dict, dictSize, ZSTD_getParams(compressionLevel, 0));
|
||||
return ZBUFF_compressInitDictionary(zbc, NULL, 0, compressionLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -185,11 +183,11 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
||||
{
|
||||
U32 notDone = 1;
|
||||
const char* const istart = (const char*)src;
|
||||
const char* ip = istart;
|
||||
const char* const iend = istart + *srcSizePtr;
|
||||
const char* ip = istart;
|
||||
char* const ostart = (char*)dst;
|
||||
char* op = ostart;
|
||||
char* const oend = ostart + *dstCapacityPtr;
|
||||
char* op = ostart;
|
||||
|
||||
while (notDone) {
|
||||
switch(zbc->stage)
|
||||
@@ -198,19 +196,17 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
||||
|
||||
case ZBUFFcs_load:
|
||||
/* complete inBuffer */
|
||||
{
|
||||
size_t toLoad = zbc->inBuffTarget - zbc->inBuffPos;
|
||||
size_t loaded = ZBUFF_limitCopy(zbc->inBuff + zbc->inBuffPos, toLoad, ip, iend-ip);
|
||||
{ size_t const toLoad = zbc->inBuffTarget - zbc->inBuffPos;
|
||||
size_t const loaded = ZBUFF_limitCopy(zbc->inBuff + zbc->inBuffPos, toLoad, ip, iend-ip);
|
||||
zbc->inBuffPos += loaded;
|
||||
ip += loaded;
|
||||
if ( (zbc->inBuffPos==zbc->inToCompress) || (!flush && (toLoad != loaded)) ) {
|
||||
notDone = 0; break; /* not enough input to get a full block : stop there, wait for more */
|
||||
} }
|
||||
/* compress current block (note : this stage cannot be stopped in the middle) */
|
||||
{
|
||||
void* cDst;
|
||||
{ void* cDst;
|
||||
size_t cSize;
|
||||
size_t iSize = zbc->inBuffPos - zbc->inToCompress;
|
||||
size_t const iSize = zbc->inBuffPos - zbc->inToCompress;
|
||||
size_t oSize = oend-op;
|
||||
if (oSize >= ZSTD_compressBound(iSize))
|
||||
cDst = op; /* compress directly into output buffer (avoid flush stage) */
|
||||
@@ -221,20 +217,18 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
||||
/* prepare next block */
|
||||
zbc->inBuffTarget = zbc->inBuffPos + zbc->blockSize;
|
||||
if (zbc->inBuffTarget > zbc->inBuffSize)
|
||||
{ zbc->inBuffPos = 0; zbc->inBuffTarget = zbc->blockSize; } /* note : inBuffSize >= blockSize */
|
||||
zbc->inBuffPos = 0, zbc->inBuffTarget = zbc->blockSize; /* note : inBuffSize >= blockSize */
|
||||
zbc->inToCompress = zbc->inBuffPos;
|
||||
if (cDst == op) { op += cSize; break; } /* no need to flush */
|
||||
zbc->outBuffContentSize = cSize;
|
||||
zbc->outBuffFlushedSize = 0;
|
||||
zbc->stage = ZBUFFcs_flush;
|
||||
// break; /* flush stage follows */
|
||||
zbc->stage = ZBUFFcs_flush; /* continue to flush stage */
|
||||
}
|
||||
|
||||
case ZBUFFcs_flush:
|
||||
/* flush into dst */
|
||||
{
|
||||
size_t toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
|
||||
size_t flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
|
||||
{ size_t const toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
|
||||
size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
|
||||
op += flushed;
|
||||
zbc->outBuffFlushedSize += flushed;
|
||||
if (toFlush!=flushed) { notDone = 0; break; } /* not enough space within dst to store compressed block : stop there */
|
||||
@@ -250,8 +244,7 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
||||
|
||||
*srcSizePtr = ip - istart;
|
||||
*dstCapacityPtr = op - ostart;
|
||||
{
|
||||
size_t hintInSize = zbc->inBuffTarget - zbc->inBuffPos;
|
||||
{ size_t hintInSize = zbc->inBuffTarget - zbc->inBuffPos;
|
||||
if (hintInSize==0) hintInSize = zbc->blockSize;
|
||||
return hintInSize;
|
||||
}
|
||||
@@ -271,7 +264,7 @@ size_t ZBUFF_compressContinue(ZBUFF_CCtx* zbc,
|
||||
size_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
|
||||
{
|
||||
size_t srcSize = 0;
|
||||
ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, &srcSize, &srcSize, 1); /* use a valid src address instead of NULL, as some sanitizer don't like it */
|
||||
ZBUFF_compressContinue_generic(zbc, dst, dstCapacityPtr, &srcSize, &srcSize, 1); /* use a valid src address instead of NULL */
|
||||
return zbc->outBuffContentSize - zbc->outBuffFlushedSize;
|
||||
}
|
||||
|
||||
@@ -279,11 +272,11 @@ size_t ZBUFF_compressFlush(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
|
||||
size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + *dstCapacityPtr;
|
||||
BYTE* op = ostart;
|
||||
size_t outSize = *dstCapacityPtr;
|
||||
size_t epilogueSize, remaining;
|
||||
ZBUFF_compressFlush(zbc, dst, &outSize); /* flush any remaining inBuff */
|
||||
ZBUFF_compressFlush(zbc, dst, &outSize); /* flush any remaining inBuff */
|
||||
op += outSize;
|
||||
epilogueSize = ZSTD_compressEnd(zbc->zc, zbc->outBuff + zbc->outBuffContentSize, zbc->outBuffSize - zbc->outBuffContentSize); /* epilogue into outBuff */
|
||||
zbc->outBuffContentSize += epilogueSize;
|
||||
@@ -291,7 +284,7 @@ size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
|
||||
zbc->stage = ZBUFFcs_flush;
|
||||
remaining = ZBUFF_compressFlush(zbc, op, &outSize); /* attempt to flush epilogue into dst */
|
||||
op += outSize;
|
||||
if (!remaining) zbc->stage = ZBUFFcs_init; /* close only if nothing left to flush */
|
||||
if (!remaining) zbc->stage = ZBUFFcs_init; /* close only if nothing left to flush */
|
||||
*dstCapacityPtr = op-ostart; /* tells how many bytes were written */
|
||||
return remaining;
|
||||
}
|
||||
@@ -328,10 +321,11 @@ typedef enum { ZBUFFds_init, ZBUFFds_readHeader,
|
||||
struct ZBUFF_DCtx_s {
|
||||
ZSTD_DCtx* zc;
|
||||
ZSTD_frameParams fParams;
|
||||
char* inBuff;
|
||||
size_t blockSize;
|
||||
char* inBuff;
|
||||
size_t inBuffSize;
|
||||
size_t inPos;
|
||||
char* outBuff;
|
||||
char* outBuff;
|
||||
size_t outBuffSize;
|
||||
size_t outStart;
|
||||
size_t outEnd;
|
||||
@@ -406,27 +400,26 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc,
|
||||
return headerSize;
|
||||
} }
|
||||
|
||||
/* Frame header provides buffer sizes */
|
||||
{ size_t const neededInSize = ZSTD_BLOCKSIZE_MAX; /* a block is never > ZSTD_BLOCKSIZE_MAX */
|
||||
if (zbc->inBuffSize < neededInSize) {
|
||||
/* Frame header instruct buffer sizes */
|
||||
{ size_t const blockSize = MIN(1 << zbc->fParams.windowLog, ZSTD_BLOCKSIZE_MAX);
|
||||
zbc->blockSize = blockSize;
|
||||
if (zbc->inBuffSize < blockSize) {
|
||||
free(zbc->inBuff);
|
||||
zbc->inBuffSize = neededInSize;
|
||||
zbc->inBuff = (char*)malloc(neededInSize);
|
||||
zbc->inBuffSize = blockSize;
|
||||
zbc->inBuff = (char*)malloc(blockSize);
|
||||
if (zbc->inBuff == NULL) return ERROR(memory_allocation);
|
||||
} }
|
||||
{
|
||||
size_t const neededOutSize = (size_t)1 << zbc->fParams.windowLog;
|
||||
if (zbc->outBuffSize < neededOutSize) {
|
||||
free(zbc->outBuff);
|
||||
zbc->outBuffSize = neededOutSize;
|
||||
zbc->outBuff = (char*)malloc(neededOutSize);
|
||||
if (zbc->outBuff == NULL) return ERROR(memory_allocation);
|
||||
} }
|
||||
}
|
||||
{ size_t const neededOutSize = ((size_t)1 << zbc->fParams.windowLog) + blockSize;
|
||||
if (zbc->outBuffSize < neededOutSize) {
|
||||
free(zbc->outBuff);
|
||||
zbc->outBuffSize = neededOutSize;
|
||||
zbc->outBuff = (char*)malloc(neededOutSize);
|
||||
if (zbc->outBuff == NULL) return ERROR(memory_allocation);
|
||||
} } }
|
||||
zbc->stage = ZBUFFds_read;
|
||||
|
||||
case ZBUFFds_read:
|
||||
{
|
||||
size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
if (neededInSize==0) { /* end of frame */
|
||||
zbc->stage = ZBUFFds_init;
|
||||
notDone = 0;
|
||||
@@ -449,8 +442,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc,
|
||||
}
|
||||
|
||||
case ZBUFFds_load:
|
||||
{
|
||||
size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
size_t const toLoad = neededInSize - zbc->inPos; /* should always be <= remaining space within inBuff */
|
||||
size_t loadedSize;
|
||||
if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected); /* should never happen */
|
||||
@@ -458,8 +450,8 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc,
|
||||
ip += loadedSize;
|
||||
zbc->inPos += loadedSize;
|
||||
if (loadedSize < toLoad) { notDone = 0; break; } /* not enough input, wait for more */
|
||||
{
|
||||
size_t const decodedSize = ZSTD_decompressContinue(zbc->zc,
|
||||
/* decode loaded input */
|
||||
{ size_t const decodedSize = ZSTD_decompressContinue(zbc->zc,
|
||||
zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,
|
||||
zbc->inBuff, neededInSize);
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
@@ -469,15 +461,15 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc,
|
||||
zbc->stage = ZBUFFds_flush;
|
||||
// break; /* ZBUFFds_flush follows */
|
||||
} }
|
||||
|
||||
case ZBUFFds_flush:
|
||||
{
|
||||
size_t const toFlushSize = zbc->outEnd - zbc->outStart;
|
||||
{ size_t const toFlushSize = zbc->outEnd - zbc->outStart;
|
||||
size_t const flushedSize = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);
|
||||
op += flushedSize;
|
||||
zbc->outStart += flushedSize;
|
||||
if (flushedSize == toFlushSize) {
|
||||
zbc->stage = ZBUFFds_read;
|
||||
if (zbc->outStart + ZSTD_BLOCKSIZE_MAX > zbc->outBuffSize)
|
||||
if (zbc->outStart + zbc->blockSize > zbc->outBuffSize)
|
||||
zbc->outStart = zbc->outEnd = 0;
|
||||
break;
|
||||
}
|
||||
@@ -491,8 +483,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc,
|
||||
/* result */
|
||||
*srcSizePtr = ip-istart;
|
||||
*dstCapacityPtr = op-ostart;
|
||||
{
|
||||
size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbc->zc);
|
||||
if (nextSrcSizeHint > ZSTD_blockHeaderSize) nextSrcSizeHint+= ZSTD_blockHeaderSize; /* get following block header too */
|
||||
nextSrcSizeHint -= zbc->inPos; /* already loaded*/
|
||||
return nextSrcSizeHint;
|
||||
|
||||
+4
-9
@@ -31,11 +31,6 @@
|
||||
#ifndef ZSTD_BUFFERED_H
|
||||
#define ZSTD_BUFFERED_H
|
||||
|
||||
/* The objects defined into this file should be considered experimental.
|
||||
* They are not considered stable, as their prototype may change in the future.
|
||||
* You can use them for tests, provide feedback, or if you can endure risk of future changes.
|
||||
*/
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -89,12 +84,12 @@ ZSTDLIB_API size_t ZBUFF_compressEnd(ZBUFF_CCtx* cctx, void* dst, size_t* dstCap
|
||||
* *srcSizePtr and *dstCapacityPtr can be any size.
|
||||
* The function will report how many bytes were read or written within *srcSizePtr and *dstCapacityPtr.
|
||||
* Note that it may not consume the entire input, in which case it's up to the caller to present again remaining data.
|
||||
* The content of @dst will be overwritten (up to *dstCapacityPtr) at each call, so save its content if it matters or change @dst .
|
||||
* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each call, so save its content if it matters or change @dst .
|
||||
* @return : a hint to preferred nb of bytes to use as input for next function call (it's just a hint, to improve latency)
|
||||
* or an error code, which can be tested using ZBUFF_isError().
|
||||
*
|
||||
* At any moment, it's possible to flush whatever data remains within buffer, using ZBUFF_compressFlush().
|
||||
* The nb of bytes written into @dst will be reported into *dstCapacityPtr.
|
||||
* The nb of bytes written into `dst` will be reported into *dstCapacityPtr.
|
||||
* Note that the function cannot output more than *dstCapacityPtr,
|
||||
* therefore, some content might still be left into internal buffer if *dstCapacityPtr is too small.
|
||||
* @return : nb of bytes still present into internal buffer (0 if it's empty)
|
||||
@@ -139,13 +134,13 @@ ZSTDLIB_API size_t ZBUFF_decompressContinue(ZBUFF_DCtx* dctx,
|
||||
* *srcSizePtr and *dstCapacityPtr can be any size.
|
||||
* The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.
|
||||
* Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.
|
||||
* The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.
|
||||
* The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.
|
||||
* @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),
|
||||
* or 0 when a frame is completely decoded,
|
||||
* or an error code, which can be tested using ZBUFF_isError().
|
||||
*
|
||||
* Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize() and ZBUFF_recommendedDOutSize()
|
||||
* output : ZBUFF_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.
|
||||
* output : ZBUFF_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.
|
||||
* input : ZBUFF_recommendedDInSize == 128KB + 3;
|
||||
* just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .
|
||||
* *******************************************************************************/
|
||||
|
||||
+3
-1
@@ -51,7 +51,9 @@ extern "C" {
|
||||
/* *************************************
|
||||
* Advanced Streaming functions
|
||||
***************************************/
|
||||
ZSTDLIB_API size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params);
|
||||
ZSTDLIB_API size_t ZBUFF_compressInit_advanced(ZBUFF_CCtx* cctx,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
||||
+71
-44
@@ -284,8 +284,7 @@ static dictItem ZDICT_analyzePos(
|
||||
return solution;
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
{ int i;
|
||||
U32 searchLength;
|
||||
U32 refinedStart = start;
|
||||
U32 refinedEnd = end;
|
||||
@@ -575,7 +574,6 @@ static void ZDICT_fillNoise(void* buffer, size_t length)
|
||||
{
|
||||
unsigned acc = PRIME1;
|
||||
size_t p=0;;
|
||||
|
||||
for (p=0; p<length; p++) {
|
||||
acc *= PRIME2;
|
||||
((unsigned char*)buffer)[p] = (unsigned char)(acc >> 21);
|
||||
@@ -595,29 +593,40 @@ static void ZDICT_countEStats(EStats_ress_t esr,
|
||||
U32* countLit, U32* offsetcodeCount, U32* matchlengthCount, U32* litlengthCount,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const BYTE* bytePtr;
|
||||
const U32* u32Ptr;
|
||||
seqStore_t seqStore;
|
||||
const seqStore_t* seqStorePtr;
|
||||
|
||||
if (srcSize > ZSTD_BLOCKSIZE_MAX) srcSize = ZSTD_BLOCKSIZE_MAX; /* protection vs large samples */
|
||||
ZSTD_copyCCtx(esr.zc, esr.ref);
|
||||
ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_MAX, src, srcSize);
|
||||
seqStore = ZSTD_copySeqStore(esr.zc);
|
||||
seqStorePtr = ZSTD_getSeqStore(esr.zc);
|
||||
|
||||
/* count stats */
|
||||
for(bytePtr = seqStore.litStart; bytePtr < seqStore.lit; bytePtr++)
|
||||
countLit[*bytePtr]++;
|
||||
for(u32Ptr = seqStore.offsetStart; u32Ptr < seqStore.offset; u32Ptr++) {
|
||||
BYTE offcode = (BYTE)ZSTD_highbit(*u32Ptr) + 1;
|
||||
if (*u32Ptr==0) offcode=0;
|
||||
offsetcodeCount[offcode]++;
|
||||
/* literals stats */
|
||||
{ const BYTE* bytePtr;
|
||||
for(bytePtr = seqStorePtr->litStart; bytePtr < seqStorePtr->lit; bytePtr++)
|
||||
countLit[*bytePtr]++;
|
||||
}
|
||||
for(bytePtr = seqStore.matchLengthStart; bytePtr < seqStore.matchLength; bytePtr++)
|
||||
matchlengthCount[*bytePtr]++;
|
||||
for(bytePtr = seqStore.litLengthStart; bytePtr < seqStore.litLength; bytePtr++)
|
||||
litlengthCount[*bytePtr]++;
|
||||
|
||||
/* seqStats */
|
||||
{ size_t const nbSeq = (size_t)(seqStorePtr->offset - seqStorePtr->offsetStart);
|
||||
ZSTD_seqToCodes(seqStorePtr, nbSeq);
|
||||
|
||||
{ const BYTE* codePtr = seqStorePtr->offCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) offsetcodeCount[codePtr[u]]++;
|
||||
}
|
||||
|
||||
{ const BYTE* codePtr = seqStorePtr->mlCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) matchlengthCount[codePtr[u]]++;
|
||||
}
|
||||
|
||||
{ const BYTE* codePtr = seqStorePtr->llCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) litlengthCount[codePtr[u]]++;
|
||||
} }
|
||||
}
|
||||
|
||||
/*
|
||||
static size_t ZDICT_maxSampleSize(const size_t* fileSizes, unsigned nbFiles)
|
||||
{
|
||||
unsigned u;
|
||||
@@ -626,6 +635,15 @@ static size_t ZDICT_maxSampleSize(const size_t* fileSizes, unsigned nbFiles)
|
||||
if (max < fileSizes[u]) max = fileSizes[u];
|
||||
return max;
|
||||
}
|
||||
*/
|
||||
|
||||
static size_t ZDICT_totalSampleSize(const size_t* fileSizes, unsigned nbFiles)
|
||||
{
|
||||
size_t total;
|
||||
unsigned u;
|
||||
for (u=0, total=0; u<nbFiles; u++) total += fileSizes[u];
|
||||
return total;
|
||||
}
|
||||
|
||||
#define OFFCODE_MAX 18 /* only applicable to first block */
|
||||
static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
@@ -634,24 +652,26 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
const void* dictBuffer, size_t dictBufferSize)
|
||||
{
|
||||
U32 countLit[256];
|
||||
U32 offcodeCount[MaxOff+1];
|
||||
HUF_CREATE_STATIC_CTABLE(hufTable, 255);
|
||||
short offcodeNCount[MaxOff+1];
|
||||
U32 offcodeCount[OFFCODE_MAX+1];
|
||||
short offcodeNCount[OFFCODE_MAX+1];
|
||||
U32 matchLengthCount[MaxML+1];
|
||||
short matchLengthNCount[MaxML+1];
|
||||
U32 litlengthCount[MaxLL+1];
|
||||
short litlengthNCount[MaxLL+1];
|
||||
U32 litLengthCount[MaxLL+1];
|
||||
short litLengthNCount[MaxLL+1];
|
||||
EStats_ress_t esr;
|
||||
ZSTD_parameters params;
|
||||
U32 u, huffLog = 12, Offlog = OffFSELog, mlLog = MLFSELog, llLog = LLFSELog, total;
|
||||
size_t pos = 0, errorCode;
|
||||
size_t eSize = 0;
|
||||
size_t const totalSrcSize = ZDICT_totalSampleSize(fileSizes, nbFiles);
|
||||
size_t const averageSampleSize = totalSrcSize / nbFiles;
|
||||
|
||||
/* init */
|
||||
for (u=0; u<256; u++) countLit[u]=1; /* any character must be described */
|
||||
for (u=0; u<=OFFCODE_MAX; 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<=MaxLL; u++) litLengthCount[u]=1;
|
||||
esr.ref = ZSTD_createCCtx();
|
||||
esr.zc = ZSTD_createCCtx();
|
||||
esr.workPlace = malloc(ZSTD_BLOCKSIZE_MAX);
|
||||
@@ -661,14 +681,15 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
goto _cleanup;
|
||||
}
|
||||
if (compressionLevel==0) compressionLevel=g_compressionLevel_default;
|
||||
params = ZSTD_getParams(compressionLevel, MAX(dictBufferSize, ZDICT_maxSampleSize(fileSizes, nbFiles)));
|
||||
params.strategy = ZSTD_greedy;
|
||||
ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params);
|
||||
params.cParams = ZSTD_getCParams(compressionLevel, averageSampleSize, dictBufferSize);
|
||||
params.cParams.strategy = ZSTD_greedy;
|
||||
params.fParams.contentSizeFlag = 0;
|
||||
ZSTD_compressBegin_advanced(esr.ref, dictBuffer, dictBufferSize, params, 0);
|
||||
|
||||
/* collect stats on all files */
|
||||
for (u=0; u<nbFiles; u++) {
|
||||
ZDICT_countEStats(esr,
|
||||
countLit, offcodeCount, matchLengthCount, litlengthCount,
|
||||
countLit, offcodeCount, matchLengthCount, litLengthCount,
|
||||
(const char*)srcBuffer + pos, fileSizes[u]);
|
||||
pos += fileSizes[u];
|
||||
}
|
||||
@@ -700,11 +721,11 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
}
|
||||
mlLog = (U32)errorCode;
|
||||
|
||||
total=0; for (u=0; u<=MaxLL; u++) total+=litlengthCount[u];
|
||||
errorCode = FSE_normalizeCount(litlengthNCount, llLog, litlengthCount, total, MaxLL);
|
||||
total=0; for (u=0; u<=MaxLL; u++) total+=litLengthCount[u];
|
||||
errorCode = FSE_normalizeCount(litLengthNCount, llLog, litLengthCount, total, MaxLL);
|
||||
if (FSE_isError(errorCode)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
DISPLAYLEVEL(1, "FSE_normalizeCount error with litlengthCount");
|
||||
DISPLAYLEVEL(1, "FSE_normalizeCount error with litLengthCount");
|
||||
goto _cleanup;
|
||||
}
|
||||
llLog = (U32)errorCode;
|
||||
@@ -740,7 +761,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
maxDstSize -= errorCode;
|
||||
eSize += errorCode;
|
||||
|
||||
errorCode = FSE_writeNCount(dstBuffer, maxDstSize, litlengthNCount, MaxLL, llLog);
|
||||
errorCode = FSE_writeNCount(dstBuffer, maxDstSize, litLengthNCount, MaxLL, llLog);
|
||||
if (FSE_isError(errorCode)) {
|
||||
eSize = ERROR(GENERIC);
|
||||
DISPLAYLEVEL(1, "FSE_writeNCount error with litlengthNCount");
|
||||
@@ -799,12 +820,17 @@ static size_t ZDICT_fastSampling(void* dictBuffer, size_t dictSize,
|
||||
}
|
||||
|
||||
|
||||
#define DIB_MINSAMPLESSIZE (DIB_FASTSEGMENTSIZE*3)
|
||||
/*! ZDICT_trainFromBuffer_unsafe() :
|
||||
* `samplesBuffer` must be followed by noisy guard band.
|
||||
* @return : size of dictionary.
|
||||
*/
|
||||
size_t ZDICT_trainFromBuffer_unsafe(
|
||||
void* dictBuffer, size_t maxDictSize,
|
||||
const void* samplesBuffer, const size_t* sampleSizes, unsigned nbSamples,
|
||||
ZDICT_params_t params)
|
||||
{
|
||||
const U32 dictListSize = MAX( MAX(DICTLISTSIZE, nbSamples), (U32)(maxDictSize/16));
|
||||
U32 const dictListSize = MAX( MAX(DICTLISTSIZE, nbSamples), (U32)(maxDictSize/16));
|
||||
dictItem* dictList = (dictItem*)malloc(dictListSize * sizeof(*dictList));
|
||||
unsigned selectivity = params.selectivityLevel;
|
||||
unsigned compressionLevel = params.compressionLevel;
|
||||
@@ -814,10 +840,11 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
|
||||
/* checks */
|
||||
if (maxDictSize <= g_provision_entropySize + g_min_fast_dictContent) return ERROR(dstSize_tooSmall);
|
||||
if (!dictList) return ERROR(memory_allocation);
|
||||
|
||||
/* init */
|
||||
{ unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += sampleSizes[u]; }
|
||||
if (!dictList) return ERROR(memory_allocation);
|
||||
if (sBuffSize < DIB_MINSAMPLESSIZE) return 0; /* not enough source to create dictionary */
|
||||
ZDICT_initDictItem(dictList);
|
||||
g_displayLevel = params.notificationLevel;
|
||||
if (selectivity==0) selectivity = g_selectivity_default;
|
||||
@@ -832,9 +859,9 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
|
||||
/* display best matches */
|
||||
if (g_displayLevel>= 3) {
|
||||
const U32 nb = 25;
|
||||
U32 const nb = 25;
|
||||
U32 const dictContentSize = ZDICT_dictSize(dictList);
|
||||
U32 u;
|
||||
U32 dictContentSize = ZDICT_dictSize(dictList);
|
||||
DISPLAYLEVEL(3, "\n %u segments found, of total size %u \n", dictList[0].pos, dictContentSize);
|
||||
DISPLAYLEVEL(3, "list %u best segments \n", nb);
|
||||
for (u=1; u<=nb; u++) {
|
||||
@@ -848,8 +875,7 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
} } }
|
||||
|
||||
/* create dictionary */
|
||||
{
|
||||
U32 dictContentSize = ZDICT_dictSize(dictList);
|
||||
{ U32 dictContentSize = ZDICT_dictSize(dictList);
|
||||
size_t hSize;
|
||||
BYTE* ptr;
|
||||
U32 u;
|
||||
@@ -894,31 +920,32 @@ size_t ZDICT_trainFromBuffer_unsafe(
|
||||
}
|
||||
|
||||
|
||||
/* issue : samplesBuffer need to be followed by a noisy guard band.
|
||||
* work around : duplicate the buffer, and add the noise */
|
||||
size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||
ZDICT_params_t params)
|
||||
{
|
||||
size_t sBuffSize;
|
||||
void* newBuff;
|
||||
size_t result;
|
||||
size_t sBuffSize;
|
||||
|
||||
{ unsigned u; for (u=0, sBuffSize=0; u<nbSamples; u++) sBuffSize += samplesSizes[u]; }
|
||||
if (sBuffSize==0) return 0; /* empty content => no dictionary */
|
||||
newBuff = malloc(sBuffSize + NOISELENGTH);
|
||||
if (!newBuff) return ERROR(memory_allocation);
|
||||
|
||||
memcpy(newBuff, samplesBuffer, sBuffSize);
|
||||
ZDICT_fillNoise((char*)newBuff + sBuffSize, NOISELENGTH); /* guard band, for end of buffer condition */
|
||||
|
||||
result = ZDICT_trainFromBuffer_unsafe(dictBuffer, dictBufferCapacity,
|
||||
{ size_t const result = ZDICT_trainFromBuffer_unsafe(
|
||||
dictBuffer, dictBufferCapacity,
|
||||
newBuff, samplesSizes, nbSamples,
|
||||
params);
|
||||
free(newBuff);
|
||||
return result;
|
||||
free(newBuff);
|
||||
return result; }
|
||||
}
|
||||
|
||||
|
||||
/* issue : samplesBuffer need to be followed by a noisy guard band.
|
||||
* work around : duplicate the buffer, and add the noise ? */
|
||||
size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples)
|
||||
{
|
||||
|
||||
+659
-580
@@ -62,7 +62,7 @@
|
||||
/*-*************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
static const U32 g_searchStrength = 8;
|
||||
static const U32 g_searchStrength = 8; /* control skip over incompressible data */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -80,7 +80,6 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
||||
ssPtr->lit = ssPtr->litStart;
|
||||
ssPtr->litLength = ssPtr->litLengthStart;
|
||||
ssPtr->matchLength = ssPtr->matchLengthStart;
|
||||
ssPtr->dumps = ssPtr->dumpsStart;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +95,9 @@ struct ZSTD_CCtx_s
|
||||
U32 lowLimit; /* below that point, no more data */
|
||||
U32 nextToUpdate; /* index from which to continue dictionary update */
|
||||
U32 nextToUpdate3; /* index from which to continue dictionary update */
|
||||
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
||||
U32 loadedDictEnd;
|
||||
U32 stage;
|
||||
U32 additionalParam;
|
||||
ZSTD_parameters params;
|
||||
void* workSpace;
|
||||
size_t workSpaceSize;
|
||||
@@ -109,7 +108,7 @@ struct ZSTD_CCtx_s
|
||||
seqStore_t seqStore; /* sequences storage ptrs */
|
||||
U32* hashTable;
|
||||
U32* hashTable3;
|
||||
U32* contentTable;
|
||||
U32* chainTable;
|
||||
HUF_CElt* hufTable;
|
||||
U32 flagStaticTables;
|
||||
FSE_CTable offcodeCTable [FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
|
||||
@@ -129,88 +128,121 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
return 0; /* reserved as a potential error code in the future */
|
||||
}
|
||||
|
||||
seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
|
||||
{
|
||||
return ctx->seqStore;
|
||||
return &(ctx->seqStore);
|
||||
}
|
||||
|
||||
|
||||
#define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
|
||||
#define CLAMPCHECK(val,min,max) { if ((val<min) || (val>max)) return ERROR(compressionParameter_unsupported); }
|
||||
|
||||
/** ZSTD_checkParams() :
|
||||
ensure param values remain within authorized range.
|
||||
@return : 0, or an error code if one value is beyond authorized range */
|
||||
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
||||
CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
|
||||
CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
||||
CLAMPCHECK(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
|
||||
{ U32 const searchLengthMin = (cParams.strategy == ZSTD_btopt) ? ZSTD_SEARCHLENGTH_MIN : ZSTD_SEARCHLENGTH_MIN+1;
|
||||
U32 const searchLengthMax = (cParams.strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
|
||||
CLAMPCHECK(cParams.searchLength, searchLengthMin, searchLengthMax); }
|
||||
CLAMPCHECK(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
||||
if ((U32)(cParams.strategy) > (U32)ZSTD_btopt) return ERROR(compressionParameter_unsupported);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned ZSTD_highbit(U32 val);
|
||||
|
||||
#define CLAMP(val,min,max) { if (val<min) val=min; else if (val>max) val=max; }
|
||||
|
||||
/** ZSTD_validateParams() :
|
||||
correct params value to remain within authorized range,
|
||||
optimize for `srcSize` if srcSize > 0 */
|
||||
void ZSTD_validateParams(ZSTD_parameters* params)
|
||||
/** ZSTD_checkCParams_advanced() :
|
||||
temporary work-around, while the compressor compatibility remains limited regarding windowLog < 18 */
|
||||
size_t ZSTD_checkCParams_advanced(ZSTD_compressionParameters cParams, U64 srcSize)
|
||||
{
|
||||
const U32 btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_btopt);
|
||||
const U32 searchLengthMax = (params->strategy == ZSTD_fast) ? ZSTD_SEARCHLENGTH_MAX : ZSTD_SEARCHLENGTH_MAX-1;
|
||||
const U32 searchLengthMin = (params->strategy == ZSTD_btopt) ? ZSTD_SEARCHLENGTH_MIN : ZSTD_SEARCHLENGTH_MIN+1;
|
||||
if (srcSize > (1ULL << ZSTD_WINDOWLOG_MIN)) return ZSTD_checkCParams(cParams);
|
||||
if (cParams.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) return ERROR(compressionParameter_unsupported);
|
||||
if (srcSize <= (1ULL << cParams.windowLog)) cParams.windowLog = ZSTD_WINDOWLOG_MIN; /* fake value - temporary work around */
|
||||
if (srcSize <= (1ULL << cParams.chainLog)) cParams.chainLog = ZSTD_CHAINLOG_MIN; /* fake value - temporary work around */
|
||||
if ((srcSize <= (1ULL << cParams.hashLog)) && ((U32)cParams.strategy < (U32)ZSTD_btlazy2)) cParams.hashLog = ZSTD_HASHLOG_MIN; /* fake value - temporary work around */
|
||||
return ZSTD_checkCParams(cParams);
|
||||
}
|
||||
|
||||
/* validate params */
|
||||
if (MEM_32bits()) if (params->windowLog > 25) params->windowLog = 25; /* 32 bits mode cannot flush > 24 bits */
|
||||
CLAMP(params->windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
||||
CLAMP(params->contentLog, ZSTD_CONTENTLOG_MIN, ZSTD_CONTENTLOG_MAX);
|
||||
CLAMP(params->hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
||||
CLAMP(params->searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
|
||||
CLAMP(params->searchLength, searchLengthMin, searchLengthMax);
|
||||
CLAMP(params->targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
||||
if ((U32)params->strategy>(U32)ZSTD_btopt) params->strategy = ZSTD_btopt;
|
||||
|
||||
/* correct params, to use less memory */
|
||||
if ((params->srcSize > 0) && (params->srcSize < (1<<ZSTD_WINDOWLOG_MAX))) {
|
||||
U32 srcLog = ZSTD_highbit((U32)(params->srcSize)-1) + 1;
|
||||
if (params->windowLog > srcLog) params->windowLog = srcLog;
|
||||
}
|
||||
/** ZSTD_adjustParams() :
|
||||
optimize params for q given input (`srcSize` and `dictSize`).
|
||||
mostly downsizing to reduce memory consumption and initialization.
|
||||
Both `srcSize` and `dictSize` are optional (use 0 if unknown),
|
||||
but if both are 0, no optimization can be done.
|
||||
Note : params is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
|
||||
void ZSTD_adjustCParams(ZSTD_compressionParameters* params, U64 srcSize, size_t dictSize)
|
||||
{
|
||||
if (srcSize+dictSize == 0) return; /* no size information available : no adjustment */
|
||||
|
||||
/* resize params, to use less memory when necessary */
|
||||
{ U32 const minSrcSize = (srcSize==0) ? 500 : 0;
|
||||
U64 const rSize = srcSize + dictSize + minSrcSize;
|
||||
if (rSize < (1<<ZSTD_WINDOWLOG_MAX)) {
|
||||
U32 const srcLog = ZSTD_highbit((U32)(rSize)-1) + 1;
|
||||
if (params->windowLog > srcLog) params->windowLog = srcLog;
|
||||
} }
|
||||
if (params->hashLog > params->windowLog) params->hashLog = params->windowLog;
|
||||
{ U32 const btPlus = (params->strategy == ZSTD_btlazy2) || (params->strategy == ZSTD_btopt);
|
||||
U32 const maxChainLog = params->windowLog+btPlus;
|
||||
if (params->chainLog > maxChainLog) params->chainLog = maxChainLog; } /* <= ZSTD_CHAINLOG_MAX */
|
||||
|
||||
if (params->windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) params->windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* required for frame header */
|
||||
if (params->contentLog > params->windowLog+btPlus) params->contentLog = params->windowLog+btPlus; /* <= ZSTD_CONTENTLOG_MAX */
|
||||
if ((params->hashLog < ZSTD_HASHLOG_MIN) && ((U32)params->strategy >= (U32)ZSTD_btlazy2)) params->hashLog = ZSTD_HASHLOG_MIN; /* required to ensure collision resistance in bt */
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_sizeofCCtx(ZSTD_parameters params) /* hidden interface, for paramagrill */
|
||||
{ /* copy / pasted from ZSTD_resetCCtx_advanced */
|
||||
const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.windowLog);
|
||||
const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog;
|
||||
const U32 divider = (params.searchLength==3) ? 3 : 4;
|
||||
const size_t maxNbSeq = blockSize / divider;
|
||||
const size_t tokenSpace = blockSize + 8*maxNbSeq;
|
||||
const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog) + (1 << HASHLOG3)) * sizeof(U32);
|
||||
const size_t optSpace = ((1<<MLbits) + (1<<LLbits) + (1<<Offbits) + (1<<Litbits))*sizeof(U32) + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
|
||||
const size_t neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
|
||||
+ ((params.strategy == ZSTD_btopt) ? optSpace : 0);
|
||||
|
||||
return sizeof(ZSTD_CCtx) + neededSpace;
|
||||
size_t ZSTD_sizeofCCtx(ZSTD_compressionParameters cParams) /* hidden interface, for paramagrill */
|
||||
{
|
||||
ZSTD_CCtx* zc = ZSTD_createCCtx();
|
||||
ZSTD_parameters params;
|
||||
params.cParams = cParams;
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
ZSTD_compressBegin_advanced(zc, NULL, 0, params, 0);
|
||||
{ size_t const ccsize = sizeof(*zc) + zc->workSpaceSize;
|
||||
ZSTD_freeCCtx(zc);
|
||||
return ccsize; }
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_resetCCtx_advanced() :
|
||||
note : 'params' is expected to be validated */
|
||||
static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
ZSTD_parameters params)
|
||||
{ /* note : params considered validated here */
|
||||
const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.windowLog);
|
||||
const U32 contentLog = (params.strategy == ZSTD_fast) ? 1 : params.contentLog;
|
||||
const U32 divider = (params.searchLength==3) ? 3 : 4;
|
||||
const size_t blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
|
||||
const U32 divider = (params.cParams.searchLength==3) ? 3 : 4;
|
||||
const size_t maxNbSeq = blockSize / divider;
|
||||
const size_t tokenSpace = blockSize + 8*maxNbSeq;
|
||||
const size_t tableSpace = ((1 << contentLog) + (1 << params.hashLog) + (1 << HASHLOG3)) * sizeof(U32);
|
||||
const size_t optSpace = ((1<<MLbits) + (1<<LLbits) + (1<<Offbits) + (1<<Litbits))*sizeof(U32) + (ZSTD_OPT_NUM+1)*(sizeof(ZSTD_match_t) + sizeof(ZSTD_optimal_t));
|
||||
const size_t neededSpace = tableSpace + (256*sizeof(U32)) /* huffTable */ + tokenSpace
|
||||
+ ((params.strategy == ZSTD_btopt) ? optSpace : 0);
|
||||
const size_t tokenSpace = blockSize + 11*maxNbSeq;
|
||||
const size_t chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
|
||||
const size_t hSize = 1 << params.cParams.hashLog;
|
||||
const size_t h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
|
||||
const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
|
||||
/* Check if workSpace is large enough, alloc a new one if needed */
|
||||
{ size_t const optSpace = ((MaxML+1) + (MaxLL+1) + (1<<Offbits) + (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) ? optSpace : 0);
|
||||
if (zc->workSpaceSize < neededSpace) {
|
||||
free(zc->workSpace);
|
||||
zc->workSpace = malloc(neededSpace);
|
||||
if (zc->workSpace == NULL) return ERROR(memory_allocation);
|
||||
zc->workSpaceSize = neededSpace;
|
||||
} }
|
||||
|
||||
if (zc->workSpaceSize < neededSpace) {
|
||||
free(zc->workSpace);
|
||||
zc->workSpace = malloc(neededSpace);
|
||||
if (zc->workSpace == NULL) return ERROR(memory_allocation);
|
||||
zc->workSpaceSize = neededSpace;
|
||||
}
|
||||
memset(zc->workSpace, 0, tableSpace ); /* reset only tables */
|
||||
zc->hashTable3 = (U32*)(zc->workSpace);
|
||||
zc->hashTable = zc->hashTable3 + ((size_t)1 << HASHLOG3);
|
||||
zc->contentTable = zc->hashTable + ((size_t)1 << params.hashLog);
|
||||
zc->seqStore.buffer = zc->contentTable + ((size_t)1 << contentLog);
|
||||
zc->hashTable = zc->hashTable3 + h3Size;
|
||||
zc->chainTable = zc->hashTable + hSize;
|
||||
zc->seqStore.buffer = zc->chainTable + chainSize;
|
||||
zc->hufTable = (HUF_CElt*)zc->seqStore.buffer;
|
||||
zc->flagStaticTables = 0;
|
||||
zc->seqStore.buffer = (U32*)(zc->seqStore.buffer) + 256;
|
||||
zc->seqStore.buffer = ((U32*)(zc->seqStore.buffer)) + 256;
|
||||
|
||||
zc->nextToUpdate = 1;
|
||||
zc->nextSrc = NULL;
|
||||
@@ -221,21 +253,23 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
zc->params = params;
|
||||
zc->blockSize = blockSize;
|
||||
|
||||
zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
|
||||
zc->seqStore.offCodeStart = (BYTE*) (zc->seqStore.offsetStart + maxNbSeq);
|
||||
zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
|
||||
zc->seqStore.litLengthStart = zc->seqStore.litStart + blockSize;
|
||||
zc->seqStore.matchLengthStart = zc->seqStore.litLengthStart + maxNbSeq;
|
||||
zc->seqStore.dumpsStart = zc->seqStore.matchLengthStart + maxNbSeq;
|
||||
if (params.strategy == ZSTD_btopt) {
|
||||
zc->seqStore.litFreq = (U32*)((void*)(zc->seqStore.dumpsStart + maxNbSeq));
|
||||
if (params.cParams.strategy == ZSTD_btopt) {
|
||||
zc->seqStore.litFreq = (U32*)(zc->seqStore.buffer);
|
||||
zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
|
||||
zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (1<<LLbits);
|
||||
zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (1<<MLbits);
|
||||
zc->seqStore.matchLengthFreq = zc->seqStore.litLengthFreq + (MaxLL+1);
|
||||
zc->seqStore.offCodeFreq = zc->seqStore.matchLengthFreq + (MaxML+1);
|
||||
zc->seqStore.matchTable = (ZSTD_match_t*)((void*)(zc->seqStore.offCodeFreq + (1<<Offbits)));
|
||||
zc->seqStore.priceTable = (ZSTD_optimal_t*)((void*)(zc->seqStore.matchTable + ZSTD_OPT_NUM+1));
|
||||
zc->seqStore.buffer = zc->seqStore.priceTable + ZSTD_OPT_NUM+1;
|
||||
zc->seqStore.litLengthSum = 0;
|
||||
}
|
||||
zc->seqStore.offsetStart = (U32*) (zc->seqStore.buffer);
|
||||
zc->seqStore.litLengthStart = (U16*) (void*)(zc->seqStore.offsetStart + maxNbSeq);
|
||||
zc->seqStore.matchLengthStart = (U16*) (void*)(zc->seqStore.litLengthStart + maxNbSeq);
|
||||
zc->seqStore.llCodeStart = (BYTE*) (zc->seqStore.matchLengthStart + maxNbSeq);
|
||||
zc->seqStore.mlCodeStart = zc->seqStore.llCodeStart + maxNbSeq;
|
||||
zc->seqStore.offCodeStart = zc->seqStore.mlCodeStart + maxNbSeq;
|
||||
zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
|
||||
|
||||
zc->hbSize = 0;
|
||||
zc->stage = 0;
|
||||
@@ -251,30 +285,32 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
|
||||
{
|
||||
const U32 contentLog = (srcCCtx->params.strategy == ZSTD_fast) ? 1 : srcCCtx->params.contentLog;
|
||||
const size_t tableSpace = ((1 << contentLog) + (1 << srcCCtx->params.hashLog) + (1 << HASHLOG3)) * sizeof(U32);
|
||||
|
||||
if (srcCCtx->stage!=0) return ERROR(stage_wrong);
|
||||
|
||||
dstCCtx->hashLog3 = srcCCtx->hashLog3; /* must be before ZSTD_resetCCtx_advanced */
|
||||
ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params);
|
||||
|
||||
/* copy tables */
|
||||
memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
|
||||
{ const size_t chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
|
||||
const size_t hSize = 1 << srcCCtx->params.cParams.hashLog;
|
||||
const size_t h3Size = (srcCCtx->hashLog3) ? 1 << srcCCtx->hashLog3 : 0;
|
||||
const size_t tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
memcpy(dstCCtx->workSpace, srcCCtx->workSpace, tableSpace);
|
||||
}
|
||||
|
||||
/* copy frame header */
|
||||
dstCCtx->hbSize = srcCCtx->hbSize;
|
||||
memcpy(dstCCtx->headerBuffer , srcCCtx->headerBuffer, srcCCtx->hbSize);
|
||||
|
||||
/* copy dictionary pointers */
|
||||
dstCCtx->nextToUpdate= srcCCtx->nextToUpdate;
|
||||
dstCCtx->nextToUpdate3 = srcCCtx->nextToUpdate3;
|
||||
dstCCtx->nextSrc = srcCCtx->nextSrc;
|
||||
dstCCtx->base = srcCCtx->base;
|
||||
dstCCtx->dictBase = srcCCtx->dictBase;
|
||||
dstCCtx->dictLimit = srcCCtx->dictLimit;
|
||||
dstCCtx->lowLimit = srcCCtx->lowLimit;
|
||||
dstCCtx->loadedDictEnd = srcCCtx->loadedDictEnd;
|
||||
dstCCtx->additionalParam = srcCCtx->additionalParam;
|
||||
dstCCtx->nextToUpdate = srcCCtx->nextToUpdate;
|
||||
dstCCtx->nextToUpdate3= srcCCtx->nextToUpdate3;
|
||||
dstCCtx->nextSrc = srcCCtx->nextSrc;
|
||||
dstCCtx->base = srcCCtx->base;
|
||||
dstCCtx->dictBase = srcCCtx->dictBase;
|
||||
dstCCtx->dictLimit = srcCCtx->dictLimit;
|
||||
dstCCtx->lowLimit = srcCCtx->lowLimit;
|
||||
dstCCtx->loadedDictEnd= srcCCtx->loadedDictEnd;
|
||||
|
||||
/* copy entropy tables */
|
||||
dstCCtx->flagStaticTables = srcCCtx->flagStaticTables;
|
||||
@@ -289,22 +325,31 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_reduceIndex() :
|
||||
* rescale indexes to avoid future overflow (indexes are U32) */
|
||||
static void ZSTD_reduceIndex (ZSTD_CCtx* zc,
|
||||
const U32 reducerValue)
|
||||
/*! ZSTD_reduceTable() :
|
||||
* reduce table indexes by `reducerValue` */
|
||||
static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reducerValue)
|
||||
{
|
||||
const U32 contentLog = (zc->params.strategy == ZSTD_fast) ? 1 : zc->params.contentLog;
|
||||
const U32 tableSpaceU32 = (1 << contentLog) + (1 << zc->params.hashLog);
|
||||
U32* table32 = zc->hashTable;
|
||||
U32 index;
|
||||
|
||||
for (index=0 ; index < tableSpaceU32 ; index++) {
|
||||
if (table32[index] < reducerValue) table32[index] = 0;
|
||||
else table32[index] -= reducerValue;
|
||||
U32 u;
|
||||
for (u=0 ; u < size ; u++) {
|
||||
if (table[u] < reducerValue) table[u] = 0;
|
||||
else table[u] -= reducerValue;
|
||||
}
|
||||
}
|
||||
|
||||
/*! ZSTD_reduceIndex() :
|
||||
* rescale all indexes to avoid future overflow (indexes are U32) */
|
||||
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
||||
{
|
||||
{ const U32 hSize = 1 << zc->params.cParams.hashLog;
|
||||
ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
|
||||
|
||||
{ const U32 chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog);
|
||||
ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
|
||||
|
||||
{ const U32 h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
|
||||
ZSTD_reduceTable(zc->hashTable3, h3Size, reducerValue); }
|
||||
}
|
||||
|
||||
|
||||
/*-*******************************************************
|
||||
* Block entropic compression
|
||||
@@ -447,7 +492,7 @@ size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const void* src, siz
|
||||
static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE* const ostart = (BYTE* const)dst;
|
||||
const U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
|
||||
if (srcSize + flSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
|
||||
@@ -475,7 +520,7 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void
|
||||
static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE* const ostart = (BYTE* const)dst;
|
||||
U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
|
||||
(void)dstCapacity; /* dstCapacity guaranteed to be >=4, hence large enough */
|
||||
|
||||
@@ -488,7 +533,7 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
|
||||
ostart[0] = (BYTE)((IS_RLE<<6) + (2<<4) + (srcSize >> 8));
|
||||
ostart[1] = (BYTE)srcSize;
|
||||
break;
|
||||
default: /*note : should not be necessary : flSize is necessary within {1,2,3} */
|
||||
default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
|
||||
case 3: /* 2 - 2 - 20 */
|
||||
ostart[0] = (BYTE)((IS_RLE<<6) + (3<<4) + (srcSize >> 16));
|
||||
ostart[1] = (BYTE)(srcSize>>8);
|
||||
@@ -501,62 +546,116 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
|
||||
static size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 2; }
|
||||
|
||||
static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const size_t minGain = ZSTD_minGain(srcSize);
|
||||
size_t const minGain = ZSTD_minGain(srcSize);
|
||||
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
const size_t lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
|
||||
U32 singleStream = srcSize < 256;
|
||||
U32 hType = IS_HUF;
|
||||
size_t clitSize;
|
||||
size_t cLitSize;
|
||||
|
||||
|
||||
/* small ? don't even attempt compression (speed opt) */
|
||||
# define LITERAL_NOENTROPY 63
|
||||
{ size_t const minLitSize = zc->flagStaticTables ? 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 */
|
||||
|
||||
if (zc->flagStaticTables && (lhSize==3)) {
|
||||
hType = IS_PCH;
|
||||
singleStream = 1;
|
||||
clitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable);
|
||||
cLitSize = HUF_compress1X_usingCTable(ostart+lhSize, dstCapacity-lhSize, src, srcSize, zc->hufTable);
|
||||
} else {
|
||||
clitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12)
|
||||
cLitSize = singleStream ? HUF_compress1X(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12)
|
||||
: HUF_compress2 (ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 12);
|
||||
}
|
||||
|
||||
if ((clitSize==0) || (clitSize >= srcSize - minGain)) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
if (clitSize==1) return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
||||
if ((cLitSize==0) || (cLitSize >= srcSize - minGain))
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
if (cLitSize==1)
|
||||
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
||||
|
||||
/* Build header */
|
||||
switch(lhSize)
|
||||
{
|
||||
case 3: /* 2 - 2 - 10 - 10 */
|
||||
ostart[0] = (BYTE)((srcSize>>6) + (singleStream << 4) + (hType<<6));
|
||||
ostart[1] = (BYTE)((srcSize<<2) + (clitSize>>8));
|
||||
ostart[2] = (BYTE)(clitSize);
|
||||
ostart[1] = (BYTE)((srcSize<<2) + (cLitSize>>8));
|
||||
ostart[2] = (BYTE)(cLitSize);
|
||||
break;
|
||||
case 4: /* 2 - 2 - 14 - 14 */
|
||||
ostart[0] = (BYTE)((srcSize>>10) + (2<<4) + (hType<<6));
|
||||
ostart[1] = (BYTE)(srcSize>> 2);
|
||||
ostart[2] = (BYTE)((srcSize<<6) + (clitSize>>8));
|
||||
ostart[3] = (BYTE)(clitSize);
|
||||
ostart[2] = (BYTE)((srcSize<<6) + (cLitSize>>8));
|
||||
ostart[3] = (BYTE)(cLitSize);
|
||||
break;
|
||||
default: /* should not be necessary, lhSize is {3,4,5} */
|
||||
default: /* should not be necessary, lhSize is only {3,4,5} */
|
||||
case 5: /* 2 - 2 - 18 - 18 */
|
||||
ostart[0] = (BYTE)((srcSize>>14) + (3<<4) + (hType<<6));
|
||||
ostart[1] = (BYTE)(srcSize>>6);
|
||||
ostart[2] = (BYTE)((srcSize<<2) + (clitSize>>16));
|
||||
ostart[3] = (BYTE)(clitSize>>8);
|
||||
ostart[4] = (BYTE)(clitSize);
|
||||
ostart[2] = (BYTE)((srcSize<<2) + (cLitSize>>16));
|
||||
ostart[3] = (BYTE)(cLitSize>>8);
|
||||
ostart[4] = (BYTE)(cLitSize);
|
||||
break;
|
||||
}
|
||||
|
||||
return lhSize+clitSize;
|
||||
return lhSize+cLitSize;
|
||||
}
|
||||
|
||||
|
||||
#define LITERAL_NOENTROPY 63 /* don't even attempt to compress literals below this threshold (cheap heuristic) */
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq)
|
||||
{
|
||||
/* LL codes */
|
||||
{ static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 16, 17, 17, 18, 18, 19, 19,
|
||||
20, 20, 20, 20, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24 };
|
||||
const BYTE LL_deltaCode = 19;
|
||||
U16* const llTable = seqStorePtr->litLengthStart;
|
||||
BYTE* const llCodeTable = seqStorePtr->llCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) {
|
||||
U32 ll = llTable[u];
|
||||
if (llTable[u] == 65535) { ll = seqStorePtr->longLength; llTable[u] = (U16)ll; }
|
||||
llCodeTable[u] = (ll>63) ? (BYTE)ZSTD_highbit(ll) + LL_deltaCode : LL_Code[ll];
|
||||
} }
|
||||
|
||||
/* Offset codes */
|
||||
{ const U32* const offsetTable = seqStorePtr->offsetStart;
|
||||
BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) ofCodeTable[u] = (BYTE)ZSTD_highbit(offsetTable[u]);
|
||||
}
|
||||
|
||||
/* ML codes */
|
||||
{ static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
|
||||
38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
||||
41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
|
||||
const BYTE ML_deltaCode = 36;
|
||||
U16* const mlTable = seqStorePtr->matchLengthStart;
|
||||
BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
|
||||
size_t u;
|
||||
for (u=0; u<nbSeq; u++) {
|
||||
U32 ml = mlTable[u];
|
||||
if (mlTable[u] == 65535) { ml = seqStorePtr->longLength; mlTable[u] = (U16)ml; }
|
||||
mlCodeTable[u] = (ml>127) ? (BYTE)ZSTD_highbit(ml) + ML_deltaCode : ML_Code[ml];
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
@@ -565,199 +664,179 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
||||
const seqStore_t* seqStorePtr = &(zc->seqStore);
|
||||
U32 count[MaxSeq+1];
|
||||
S16 norm[MaxSeq+1];
|
||||
size_t mostFrequent;
|
||||
U32 max;
|
||||
FSE_CTable* CTable_LitLength = zc->litlengthCTable;
|
||||
FSE_CTable* CTable_OffsetBits = zc->offcodeCTable;
|
||||
FSE_CTable* CTable_MatchLength = zc->matchlengthCTable;
|
||||
U32 LLtype, Offtype, MLtype; /* compressed, raw or rle */
|
||||
const BYTE* const op_lit_start = seqStorePtr->litStart;
|
||||
const BYTE* const llTable = seqStorePtr->litLengthStart;
|
||||
const BYTE* const llPtr = seqStorePtr->litLength;
|
||||
const BYTE* const mlTable = seqStorePtr->matchLengthStart;
|
||||
U16* const llTable = seqStorePtr->litLengthStart;
|
||||
U16* const mlTable = seqStorePtr->matchLengthStart;
|
||||
const U32* const offsetTable = seqStorePtr->offsetStart;
|
||||
BYTE* const offCodeTable = seqStorePtr->offCodeStart;
|
||||
const U32* const offsetTableEnd = seqStorePtr->offset;
|
||||
BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
|
||||
BYTE* const llCodeTable = seqStorePtr->llCodeStart;
|
||||
BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstCapacity;
|
||||
const size_t nbSeq = llPtr - llTable;
|
||||
const size_t minGain = ZSTD_minGain(srcSize);
|
||||
const size_t maxCSize = srcSize - minGain;
|
||||
BYTE* op = ostart;
|
||||
size_t const nbSeq = offsetTableEnd - offsetTable;
|
||||
BYTE* seqHead;
|
||||
|
||||
/* Compress literals */
|
||||
{
|
||||
size_t cSize;
|
||||
size_t litSize = seqStorePtr->lit - op_lit_start;
|
||||
const size_t minLitSize = zc->flagStaticTables ? 6 : LITERAL_NOENTROPY;
|
||||
|
||||
if (litSize <= minLitSize)
|
||||
cSize = ZSTD_noCompressLiterals(op, dstCapacity, op_lit_start, litSize);
|
||||
else
|
||||
cSize = ZSTD_compressLiterals(zc, op, dstCapacity, op_lit_start, litSize);
|
||||
{ const BYTE* const literals = seqStorePtr->litStart;
|
||||
size_t const litSize = seqStorePtr->lit - literals;
|
||||
size_t const cSize = ZSTD_compressLiterals(zc, op, dstCapacity, literals, litSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
/* Sequences Header */
|
||||
if ((oend-op) < MIN_SEQUENCES_SIZE) return ERROR(dstSize_tooSmall);
|
||||
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
|
||||
if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
|
||||
else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
|
||||
else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
|
||||
if (nbSeq==0) goto _check_compressibility;
|
||||
|
||||
/* dumps : contains rests of large lengths */
|
||||
if ((oend-op) < 3 /* dumps */ + 1 /*seqHead*/)
|
||||
return ERROR(dstSize_tooSmall);
|
||||
seqHead = op;
|
||||
{
|
||||
size_t dumpsLength = seqStorePtr->dumps - seqStorePtr->dumpsStart;
|
||||
if (dumpsLength < 512) {
|
||||
op[0] = (BYTE)(dumpsLength >> 8);
|
||||
op[1] = (BYTE)(dumpsLength);
|
||||
op += 2;
|
||||
} else {
|
||||
op[0] = 2;
|
||||
op[1] = (BYTE)(dumpsLength>>8);
|
||||
op[2] = (BYTE)(dumpsLength);
|
||||
op += 3;
|
||||
}
|
||||
if ((size_t)(oend-op) < dumpsLength+6) return ERROR(dstSize_tooSmall);
|
||||
memcpy(op, seqStorePtr->dumpsStart, dumpsLength);
|
||||
op += dumpsLength;
|
||||
}
|
||||
/* seqHead : flags for FSE encoding type */
|
||||
seqHead = op++;
|
||||
|
||||
#define MIN_SEQ_FOR_DYNAMIC_FSE 64
|
||||
#define MAX_SEQ_FOR_STATIC_FSE 1000
|
||||
|
||||
/* CTable for Literal Lengths */
|
||||
max = MaxLL;
|
||||
mostFrequent = FSE_countFast(count, &max, llTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = llTable[0];
|
||||
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
|
||||
LLtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
LLtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LLbits-1)))) {
|
||||
FSE_buildCTable_raw(CTable_LitLength, LLbits);
|
||||
LLtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t NCountSize;
|
||||
size_t nbSeq_1 = nbSeq;
|
||||
U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
|
||||
if (count[llTable[nbSeq-1]]>1) { count[llTable[nbSeq-1]]--; nbSeq_1--; }
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize;
|
||||
FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
|
||||
LLtype = FSE_ENCODING_DYNAMIC;
|
||||
}
|
||||
/* convert length/distances into codes */
|
||||
ZSTD_seqToCodes(seqStorePtr, nbSeq);
|
||||
|
||||
/* CTable for Offset codes */
|
||||
{ /* create Offset codes */
|
||||
size_t i; for (i=0; i<nbSeq; i++) {
|
||||
offCodeTable[i] = (BYTE)ZSTD_highbit(offsetTable[i]) + 1;
|
||||
if (offsetTable[i]==0) offCodeTable[i]=0;;
|
||||
}
|
||||
}
|
||||
max = MaxOff;
|
||||
mostFrequent = FSE_countFast(count, &max, offCodeTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = offCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
||||
Offtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
Offtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
|
||||
FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
|
||||
Offtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t NCountSize;
|
||||
size_t nbSeq_1 = nbSeq;
|
||||
U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
|
||||
if (count[offCodeTable[nbSeq-1]]>1) { count[offCodeTable[nbSeq-1]]--; nbSeq_1--; }
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize;
|
||||
FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
|
||||
Offtype = FSE_ENCODING_DYNAMIC;
|
||||
}
|
||||
/* CTable for Literal Lengths */
|
||||
{ U32 max = MaxLL;
|
||||
size_t const mostFrequent = FSE_countFast(count, &max, llCodeTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = llCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_LitLength, (BYTE)max);
|
||||
LLtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
LLtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (LL_defaultNormLog-1)))) {
|
||||
FSE_buildCTable(CTable_LitLength, LL_defaultNorm, MaxLL, LL_defaultNormLog);
|
||||
LLtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t nbSeq_1 = nbSeq;
|
||||
const U32 tableLog = FSE_optimalTableLog(LLFSELog, nbSeq, max);
|
||||
if (count[llCodeTable[nbSeq-1]]>1) { count[llCodeTable[nbSeq-1]]--; nbSeq_1--; }
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize; }
|
||||
FSE_buildCTable(CTable_LitLength, norm, max, tableLog);
|
||||
LLtype = FSE_ENCODING_DYNAMIC;
|
||||
} }
|
||||
|
||||
/* CTable for Offsets */
|
||||
{ U32 max = MaxOff;
|
||||
size_t const mostFrequent = FSE_countFast(count, &max, ofCodeTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = ofCodeTable[0];
|
||||
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
||||
Offtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
Offtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (Offbits-1)))) {
|
||||
FSE_buildCTable_raw(CTable_OffsetBits, Offbits);
|
||||
Offtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t nbSeq_1 = nbSeq;
|
||||
const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
|
||||
if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize; }
|
||||
FSE_buildCTable(CTable_OffsetBits, norm, max, tableLog);
|
||||
Offtype = FSE_ENCODING_DYNAMIC;
|
||||
} }
|
||||
|
||||
/* CTable for MatchLengths */
|
||||
max = MaxML;
|
||||
mostFrequent = FSE_countFast(count, &max, mlTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = *mlTable;
|
||||
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
|
||||
MLtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
MLtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (MLbits-1)))) {
|
||||
FSE_buildCTable_raw(CTable_MatchLength, MLbits);
|
||||
MLtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t NCountSize;
|
||||
U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq, max);
|
||||
NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize;
|
||||
FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
|
||||
MLtype = FSE_ENCODING_DYNAMIC;
|
||||
}
|
||||
{ U32 max = MaxML;
|
||||
size_t const mostFrequent = FSE_countFast(count, &max, mlCodeTable, nbSeq);
|
||||
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||
*op++ = *mlCodeTable;
|
||||
FSE_buildCTable_rle(CTable_MatchLength, (BYTE)max);
|
||||
MLtype = FSE_ENCODING_RLE;
|
||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||
MLtype = FSE_ENCODING_STATIC;
|
||||
} else if ((nbSeq < MIN_SEQ_FOR_DYNAMIC_FSE) || (mostFrequent < (nbSeq >> (ML_defaultNormLog-1)))) {
|
||||
FSE_buildCTable(CTable_MatchLength, ML_defaultNorm, MaxML, ML_defaultNormLog);
|
||||
MLtype = FSE_ENCODING_RAW;
|
||||
} else {
|
||||
size_t nbSeq_1 = nbSeq;
|
||||
const U32 tableLog = FSE_optimalTableLog(MLFSELog, nbSeq, max);
|
||||
if (count[mlCodeTable[nbSeq-1]]>1) { count[mlCodeTable[nbSeq-1]]--; nbSeq_1--; }
|
||||
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||
op += NCountSize; }
|
||||
FSE_buildCTable(CTable_MatchLength, norm, max, tableLog);
|
||||
MLtype = FSE_ENCODING_DYNAMIC;
|
||||
} }
|
||||
|
||||
seqHead[0] += (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
||||
*seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));
|
||||
zc->flagStaticTables = 0;
|
||||
|
||||
/* Encoding Sequences */
|
||||
{
|
||||
size_t streamSize, errorCode;
|
||||
BIT_CStream_t blockStream;
|
||||
FSE_CState_t stateMatchLength;
|
||||
FSE_CState_t stateOffsetBits;
|
||||
FSE_CState_t stateLitLength;
|
||||
int i;
|
||||
{ BIT_CStream_t blockStream;
|
||||
FSE_CState_t stateMatchLength;
|
||||
FSE_CState_t stateOffsetBits;
|
||||
FSE_CState_t stateLitLength;
|
||||
|
||||
errorCode = BIT_initCStream(&blockStream, op, oend-op);
|
||||
if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); /* not enough space remaining */
|
||||
{ size_t const errorCode = BIT_initCStream(&blockStream, op, oend-op);
|
||||
if (ERR_isError(errorCode)) return ERROR(dstSize_tooSmall); } /* not enough space remaining */
|
||||
|
||||
/* first symbols */
|
||||
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlTable[nbSeq-1]);
|
||||
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, offCodeTable[nbSeq-1]);
|
||||
FSE_initCState2(&stateLitLength, CTable_LitLength, llTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, offsetTable[nbSeq-1], offCodeTable[nbSeq-1] ? (offCodeTable[nbSeq-1]-1) : 0);
|
||||
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
||||
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
|
||||
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
||||
BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1]);
|
||||
BIT_flushBits(&blockStream);
|
||||
|
||||
for (i=(int)nbSeq-2; i>=0; i--) {
|
||||
BYTE mlCode = mlTable[i];
|
||||
U32 offset = offsetTable[i];
|
||||
BYTE offCode = offCodeTable[i]; /* 32b*/ /* 64b*/
|
||||
U32 nbBits = (offCode-1) + (!offCode);
|
||||
BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/
|
||||
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 17 */ /* 17 */
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
|
||||
FSE_encodeSymbol(&blockStream, &stateLitLength, litLength); /* 17 */ /* 27 */
|
||||
FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 26 */ /* 36 */
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */
|
||||
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 62 */ /* 24 bits max in 32-bits mode */
|
||||
BIT_flushBits(&blockStream); /* 7 */ /* 7 */
|
||||
}
|
||||
{ size_t n;
|
||||
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
||||
const BYTE ofCode = ofCodeTable[n];
|
||||
const BYTE mlCode = mlCodeTable[n];
|
||||
const BYTE llCode = llCodeTable[n];
|
||||
const U32 llBits = LL_bits[llCode];
|
||||
const U32 mlBits = ML_bits[mlCode];
|
||||
const U32 ofBits = ofCode; /* 32b*/ /* 64b*/
|
||||
/* (7)*/ /* (7)*/
|
||||
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
|
||||
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 24 */ /* 24 */
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
||||
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 33 */
|
||||
if (MEM_32bits() || (ofBits+mlBits+llBits > 64-7-(LLFSELog+MLFSELog+OffFSELog)))
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
BIT_addBits(&blockStream, llTable[n], llBits);
|
||||
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
|
||||
BIT_addBits(&blockStream, mlTable[n], mlBits);
|
||||
if (MEM_32bits()) BIT_flushBits(&blockStream); /* (7)*/
|
||||
BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */
|
||||
BIT_flushBits(&blockStream); /* (7)*/
|
||||
} }
|
||||
|
||||
FSE_flushCState(&blockStream, &stateMatchLength);
|
||||
FSE_flushCState(&blockStream, &stateOffsetBits);
|
||||
FSE_flushCState(&blockStream, &stateLitLength);
|
||||
|
||||
streamSize = BIT_closeCStream(&blockStream);
|
||||
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
||||
op += streamSize;
|
||||
}
|
||||
{ size_t const streamSize = BIT_closeCStream(&blockStream);
|
||||
if (streamSize==0) return ERROR(dstSize_tooSmall); /* not enough space */
|
||||
op += streamSize;
|
||||
} }
|
||||
|
||||
/* check compressibility */
|
||||
_check_compressibility:
|
||||
if ((size_t)(op-ostart) >= maxCSize) return 0;
|
||||
{ size_t const minGain = ZSTD_minGain(srcSize);
|
||||
size_t const maxCSize = srcSize - minGain;
|
||||
if ((size_t)(op-ostart) >= maxCSize) return 0; }
|
||||
|
||||
return op - ostart;
|
||||
}
|
||||
@@ -772,56 +851,28 @@ MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const B
|
||||
{
|
||||
#if 0 /* for debug */
|
||||
static const BYTE* g_start = NULL;
|
||||
const U32 pos = (U32)(literals - g_start);
|
||||
if (g_start==NULL) g_start = literals;
|
||||
//if (literals - g_start == 8695)
|
||||
printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
|
||||
(U32)(literals - g_start), (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||
#endif
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
if (offsetCode == 0) seqStorePtr->realRepSum++;
|
||||
seqStorePtr->realSeqSum++;
|
||||
seqStorePtr->realMatchSum += matchCode;
|
||||
seqStorePtr->realLitSum += litLength;
|
||||
if ((pos > 200000000) && (pos < 200900000))
|
||||
printf("Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
||||
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||
#endif
|
||||
ZSTD_statsUpdatePrices(&seqStorePtr->stats, litLength, literals, offsetCode, matchCode);
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
||||
seqStorePtr->lit += litLength;
|
||||
|
||||
/* literal Length */
|
||||
if (litLength >= MaxLL) {
|
||||
*(seqStorePtr->litLength++) = MaxLL;
|
||||
if (litLength<255 + MaxLL) {
|
||||
*(seqStorePtr->dumps++) = (BYTE)(litLength - MaxLL);
|
||||
} else {
|
||||
*(seqStorePtr->dumps++) = 255;
|
||||
if (litLength < (1<<15)) {
|
||||
MEM_writeLE16(seqStorePtr->dumps, (U16)(litLength<<1));
|
||||
seqStorePtr->dumps += 2;
|
||||
} else {
|
||||
MEM_writeLE32(seqStorePtr->dumps, (U32)((litLength<<1)+1));
|
||||
seqStorePtr->dumps += 3;
|
||||
} } }
|
||||
else *(seqStorePtr->litLength++) = (BYTE)litLength;
|
||||
if (litLength>=65535) { *(seqStorePtr->litLength++) = 65535; seqStorePtr->longLength = (U32)litLength; }
|
||||
else *seqStorePtr->litLength++ = (U16)litLength;
|
||||
|
||||
/* match offset */
|
||||
*(seqStorePtr->offset++) = (U32)offsetCode;
|
||||
*(seqStorePtr->offset++) = (U32)offsetCode + 1;
|
||||
|
||||
/* match Length */
|
||||
if (matchCode >= MaxML) {
|
||||
*(seqStorePtr->matchLength++) = MaxML;
|
||||
if (matchCode < 255+MaxML) {
|
||||
*(seqStorePtr->dumps++) = (BYTE)(matchCode - MaxML);
|
||||
} else {
|
||||
*(seqStorePtr->dumps++) = 255;
|
||||
if (matchCode < (1<<15)) {
|
||||
MEM_writeLE16(seqStorePtr->dumps, (U16)(matchCode<<1));
|
||||
seqStorePtr->dumps += 2;
|
||||
} else {
|
||||
MEM_writeLE32(seqStorePtr->dumps, (U32)((matchCode<<1)+1));
|
||||
seqStorePtr->dumps += 3;
|
||||
} } }
|
||||
else *(seqStorePtr->matchLength++) = (BYTE)matchCode;
|
||||
if (matchCode>=65535) { *(seqStorePtr->matchLength++) = 65535; seqStorePtr->longLength = (U32)matchCode; }
|
||||
else *seqStorePtr->matchLength++ = (U16)matchCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -958,18 +1009,18 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
|
||||
/*-*************************************
|
||||
* Fast Scan
|
||||
***************************************/
|
||||
#define FILLHASHSTEP 3
|
||||
static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hBits = zc->params.hashLog;
|
||||
const U32 hBits = zc->params.cParams.hashLog;
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* ip = base + zc->nextToUpdate;
|
||||
const BYTE* const iend = ((const BYTE*)end) - 8;
|
||||
const size_t fastHashFillStep = 3;
|
||||
|
||||
while(ip <= iend) {
|
||||
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base);
|
||||
ip += FILLHASHSTEP;
|
||||
ip += fastHashFillStep;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -980,7 +1031,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hBits = zc->params.hashLog;
|
||||
const U32 hBits = zc->params.cParams.hashLog;
|
||||
seqStore_t* seqStorePtr = &(zc->seqStore);
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
@@ -990,10 +1041,8 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
|
||||
const BYTE* const lowest = base + lowIndex;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
|
||||
size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE;
|
||||
|
||||
|
||||
/* init */
|
||||
ZSTD_resetSeqStore(seqStorePtr);
|
||||
if (ip < lowest+REPCODE_STARTVALUE) ip = lowest+REPCODE_STARTVALUE;
|
||||
@@ -1039,8 +1088,8 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
|
||||
while ( (ip <= ilimit)
|
||||
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
|
||||
/* store sequence */
|
||||
size_t rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
|
||||
size_t tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
|
||||
size_t const rlCode = ZSTD_count(ip+MINMATCH, ip+MINMATCH-offset_2, iend);
|
||||
{ size_t const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
|
||||
hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip-base);
|
||||
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, rlCode);
|
||||
ip += rlCode+MINMATCH;
|
||||
@@ -1048,8 +1097,8 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
|
||||
continue; /* faster when present ... (?) */
|
||||
} } }
|
||||
|
||||
{ /* Last Literals */
|
||||
size_t lastLLSize = iend - anchor;
|
||||
/* Last Literals */
|
||||
{ size_t const lastLLSize = iend - anchor;
|
||||
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
||||
seqStorePtr->lit += lastLLSize;
|
||||
}
|
||||
@@ -1059,7 +1108,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
|
||||
static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const U32 mls = ctx->params.searchLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
@@ -1080,7 +1129,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* hashTable = ctx->hashTable;
|
||||
const U32 hBits = ctx->params.hashLog;
|
||||
const U32 hBits = ctx->params.cParams.hashLog;
|
||||
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
||||
const BYTE* const base = ctx->base;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
@@ -1118,7 +1167,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
U32 offset;
|
||||
hashTable[h] = current; /* update hash table */
|
||||
|
||||
if ( ((repIndex <= dictLimit-4) || (repIndex >= dictLimit))
|
||||
if ( ((repIndex >= dictLimit) || (repIndex <= dictLimit-4))
|
||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||
const BYTE* repMatchEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlCode = ZSTD_count_2segments(ip+1+MINMATCH, repMatch+MINMATCH, iend, repMatchEnd, lowPrefixPtr);
|
||||
@@ -1126,10 +1175,11 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
ZSTD_storeSeq(seqStorePtr, ip-anchor, anchor, 0, mlCode);
|
||||
} else {
|
||||
if ( (matchIndex < lowLimit) ||
|
||||
(MEM_read32(match) != MEM_read32(ip)) )
|
||||
{ ip += ((ip-anchor) >> g_searchStrength) + 1; continue; }
|
||||
{
|
||||
const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
|
||||
(MEM_read32(match) != MEM_read32(ip)) ) {
|
||||
ip += ((ip-anchor) >> g_searchStrength) + 1;
|
||||
continue;
|
||||
}
|
||||
{ const BYTE* matchEnd = matchIndex < dictLimit ? dictEnd : iend;
|
||||
const BYTE* lowMatchPtr = matchIndex < dictLimit ? dictStart : lowPrefixPtr;
|
||||
mlCode = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iend, matchEnd, lowPrefixPtr);
|
||||
while ((ip>anchor) && (match>lowMatchPtr) && (ip[-1] == match[-1])) { ip--; match--; mlCode++; } /* catch up */
|
||||
@@ -1149,8 +1199,8 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
hashTable[ZSTD_hashPtr(ip-2, hBits, mls)] = (U32)(ip-2-base);
|
||||
/* check immediate repcode */
|
||||
while (ip <= ilimit) {
|
||||
U32 current2 = (U32)(ip-base);
|
||||
const U32 repIndex2 = current2 - offset_2;
|
||||
U32 const current2 = (U32)(ip-base);
|
||||
U32 const repIndex2 = current2 - offset_2;
|
||||
const BYTE* repMatch2 = repIndex2 < dictLimit ? dictBase + repIndex2 : base + repIndex2;
|
||||
if ( ((repIndex2 <= dictLimit-4) || (repIndex2 >= dictLimit))
|
||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||
@@ -1167,8 +1217,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
} } }
|
||||
|
||||
/* Last Literals */
|
||||
{
|
||||
size_t lastLLSize = iend - anchor;
|
||||
{ size_t const lastLLSize = iend - anchor;
|
||||
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
||||
seqStorePtr->lit += lastLLSize;
|
||||
}
|
||||
@@ -1178,7 +1227,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const U32 mls = ctx->params.searchLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default:
|
||||
@@ -1204,10 +1253,10 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
|
||||
U32 extDict)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hashLog = zc->params.hashLog;
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const bt = zc->contentTable;
|
||||
const U32 btLog = zc->params.contentLog - 1;
|
||||
U32* const bt = zc->chainTable;
|
||||
const U32 btLog = zc->params.cParams.chainLog - 1;
|
||||
const U32 btMask= (1 << btLog) - 1;
|
||||
U32 matchIndex = hashTable[h];
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
@@ -1306,10 +1355,10 @@ static size_t ZSTD_insertBtAndFindBestMatch (
|
||||
U32 extDict)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hashLog = zc->params.hashLog;
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const bt = zc->contentTable;
|
||||
const U32 btLog = zc->params.contentLog - 1;
|
||||
U32* const bt = zc->chainTable;
|
||||
const U32 btLog = zc->params.cParams.chainLog - 1;
|
||||
const U32 btMask= (1 << btLog) - 1;
|
||||
U32 matchIndex = hashTable[h];
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
@@ -1387,7 +1436,7 @@ static void ZSTD_updateTree(ZSTD_CCtx* zc, const BYTE* const ip, const BYTE* con
|
||||
idx += ZSTD_insertBt1(zc, base+idx, mls, iend, nbCompares, 0);
|
||||
}
|
||||
|
||||
/** Tree updater, providing best match */
|
||||
/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */
|
||||
static size_t ZSTD_BtFindBestMatch (
|
||||
ZSTD_CCtx* zc,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
@@ -1468,15 +1517,15 @@ FORCE_INLINE
|
||||
U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hashLog = zc->params.hashLog;
|
||||
U32* const chainTable = zc->contentTable;
|
||||
const U32 chainMask = (1 << zc->params.contentLog) - 1;
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
U32* const chainTable = zc->chainTable;
|
||||
const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1;
|
||||
const BYTE* const base = zc->base;
|
||||
const U32 target = (U32)(ip - base);
|
||||
U32 idx = zc->nextToUpdate;
|
||||
|
||||
while(idx < target) {
|
||||
size_t h = ZSTD_hashPtr(base+idx, hashLog, mls);
|
||||
size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);
|
||||
NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];
|
||||
hashTable[h] = idx;
|
||||
idx++;
|
||||
@@ -1494,8 +1543,8 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
size_t* offsetPtr,
|
||||
const U32 maxNbAttempts, const U32 mls, const U32 extDict)
|
||||
{
|
||||
U32* const chainTable = zc->contentTable;
|
||||
const U32 chainSize = (1 << zc->params.contentLog);
|
||||
U32* const chainTable = zc->chainTable;
|
||||
const U32 chainSize = (1 << zc->params.cParams.chainLog);
|
||||
const U32 chainMask = chainSize-1;
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* const dictBase = zc->dictBase;
|
||||
@@ -1513,9 +1562,8 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
/* HC4 match finder */
|
||||
matchIndex = ZSTD_insertAndFindFirstIndex (zc, ip, mls);
|
||||
|
||||
while ((matchIndex>lowLimit) && (nbAttempts)) {
|
||||
for ( ; (matchIndex>lowLimit) && (nbAttempts) ; nbAttempts--) {
|
||||
size_t currentMl=0;
|
||||
nbAttempts--;
|
||||
if ((!extDict) || matchIndex >= dictLimit) {
|
||||
match = base + matchIndex;
|
||||
if (match[ml] == ip[ml]) /* potentially better */
|
||||
@@ -1585,8 +1633,8 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
const BYTE* const base = ctx->base + ctx->dictLimit;
|
||||
|
||||
const U32 maxSearches = 1 << ctx->params.searchLog;
|
||||
const U32 mls = ctx->params.searchLength;
|
||||
const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
|
||||
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -1624,10 +1672,9 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* first search (depth 0) */
|
||||
size_t offsetFound = 99999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
||||
/* first search (depth 0) */
|
||||
{ size_t offsetFound = 99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
||||
if (ml2 > matchLength)
|
||||
matchLength = ml2, start = ip, offset=offsetFound + ZSTD_REP_MOVE;
|
||||
}
|
||||
@@ -1643,17 +1690,16 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
ip ++;
|
||||
for (int i=0; i<ZSTD_REP_NUM; i++)
|
||||
if (MEM_read32(ip) == MEM_read32(ip - rep[i])) {
|
||||
size_t mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-rep[i], iend) + MINMATCH;
|
||||
int gain2 = (int)(mlRep * 3);
|
||||
int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1 + (offset<ZSTD_REP_NUM));
|
||||
size_t const mlRep = ZSTD_count(ip+MINMATCH, ip+MINMATCH-rep[i], iend) + MINMATCH;
|
||||
int const gain2 = (int)(mlRep * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1 + (offset<ZSTD_REP_NUM));
|
||||
if ((mlRep >= MINMATCH) && (gain2 > gain1))
|
||||
matchLength = mlRep, offset = i, start = ip;
|
||||
}
|
||||
{
|
||||
size_t offset2=999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
|
||||
{ size_t offset2=99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
|
||||
if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2 + ZSTD_REP_MOVE, start = ip;
|
||||
continue; /* search a better one */
|
||||
@@ -1664,17 +1710,16 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
ip ++;
|
||||
for (int i=0; i<ZSTD_REP_NUM; i++)
|
||||
if (MEM_read32(ip) == MEM_read32(ip - rep[i])) {
|
||||
size_t ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-rep[i], iend) + MINMATCH;
|
||||
int gain2 = (int)(ml2 * 4);
|
||||
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1 + (offset<ZSTD_REP_NUM));
|
||||
size_t const ml2 = ZSTD_count(ip+MINMATCH, ip+MINMATCH-rep[i], iend) + MINMATCH;
|
||||
int const gain2 = (int)(ml2 * 4);
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 1 + (offset<ZSTD_REP_NUM));
|
||||
if ((ml2 >= MINMATCH) && (gain2 > gain1))
|
||||
matchLength = ml2, offset = i, start = ip;
|
||||
}
|
||||
{
|
||||
size_t offset2=999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
|
||||
{ size_t offset2=99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
|
||||
if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2 + ZSTD_REP_MOVE, start = ip;
|
||||
continue;
|
||||
@@ -1720,17 +1765,18 @@ _storeSequence:
|
||||
rep[1] = rep[0]; rep[0] = offset - ZSTD_REP_MOVE;
|
||||
}
|
||||
#endif
|
||||
size_t litLength = start - anchor;
|
||||
size_t const litLength = start - anchor;
|
||||
|
||||
ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
|
||||
anchor = ip = start + matchLength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last Literals */
|
||||
{
|
||||
size_t lastLLSize = iend - anchor;
|
||||
{ size_t const lastLLSize = iend - anchor;
|
||||
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
||||
seqStorePtr->lit += lastLLSize;
|
||||
ZSTD_statsUpdatePrices(&seqStorePtr->stats, lastLLSize, anchor, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1779,8 +1825,8 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const dictStart = dictBase + ctx->lowLimit;
|
||||
|
||||
const U32 maxSearches = 1 << ctx->params.searchLog;
|
||||
const U32 mls = ctx->params.searchLength;
|
||||
const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
|
||||
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -1816,10 +1862,9 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
if (depth==0) goto _storeSequence;
|
||||
} }
|
||||
|
||||
{
|
||||
/* first search (depth 0) */
|
||||
size_t offsetFound = 99999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
||||
/* first search (depth 0) */
|
||||
{ size_t offsetFound = 99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offsetFound, maxSearches, mls);
|
||||
if (ml2 > matchLength)
|
||||
matchLength = ml2, start = ip, offset=offsetFound + ZSTD_REP_MOVE;
|
||||
}
|
||||
@@ -1843,19 +1888,18 @@ 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+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
|
||||
int gain2 = (int)(repLength * 3);
|
||||
int gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
|
||||
size_t const repLength = ZSTD_count_2segments(ip+MINMATCH, repMatch+MINMATCH, iend, repEnd, prefixStart) + MINMATCH;
|
||||
int const gain2 = (int)(repLength * 3);
|
||||
int const gain1 = (int)(matchLength*3 - ZSTD_highbit((U32)offset+1) + 1);
|
||||
if ((repLength >= MINMATCH) && (gain2 > gain1))
|
||||
matchLength = repLength, offset = 0, start = ip;
|
||||
} }
|
||||
|
||||
/* search match, depth 1 */
|
||||
{
|
||||
size_t offset2=999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
|
||||
{ size_t offset2=99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 4);
|
||||
if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2 + ZSTD_REP_MOVE, start = ip;
|
||||
continue; /* search a better one */
|
||||
@@ -1882,11 +1926,10 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
} }
|
||||
|
||||
/* search match, depth 2 */
|
||||
{
|
||||
size_t offset2=999999;
|
||||
size_t ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
|
||||
{ size_t offset2=99999999;
|
||||
size_t const ml2 = searchMax(ctx, ip, iend, &offset2, maxSearches, mls);
|
||||
int const gain2 = (int)(ml2*4 - ZSTD_highbit((U32)offset2+1)); /* raw approx */
|
||||
int const gain1 = (int)(matchLength*4 - ZSTD_highbit((U32)offset+1) + 7);
|
||||
if ((ml2 >= MINMATCH) && (gain2 > gain1)) {
|
||||
matchLength = ml2, offset = offset2 + ZSTD_REP_MOVE, start = ip;
|
||||
continue;
|
||||
@@ -1905,8 +1948,7 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
|
||||
/* store sequence */
|
||||
_storeSequence:
|
||||
{
|
||||
size_t litLength = start - anchor;
|
||||
{ size_t const litLength = start - anchor;
|
||||
ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, matchLength-MINMATCH);
|
||||
anchor = ip = start + matchLength;
|
||||
}
|
||||
@@ -1931,8 +1973,7 @@ _storeSequence:
|
||||
} }
|
||||
|
||||
/* Last Literals */
|
||||
{
|
||||
size_t lastLLSize = iend - anchor;
|
||||
{ size_t const lastLLSize = iend - anchor;
|
||||
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
||||
seqStorePtr->lit += lastLLSize;
|
||||
}
|
||||
@@ -1979,13 +2020,15 @@ static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int
|
||||
|
||||
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.strategy, zc->lowLimit < zc->dictLimit);
|
||||
ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
|
||||
if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) return 0; /* don't even attempt compression below a certain srcSize */
|
||||
blockCompressor(zc, src, srcSize);
|
||||
return ZSTD_compressSequences(zc, dst, dstCapacity, srcSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
@@ -1995,22 +2038,21 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
const U32 maxDist = 1 << zc->params.windowLog;
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
seqStore_t* ssPtr = &zc->seqStore;
|
||||
static U32 priceFunc = 0;
|
||||
ssPtr->realMatchSum = ssPtr->realLitSum = ssPtr->realSeqSum = ssPtr->realRepSum = 1;
|
||||
ssPtr->priceFunc = priceFunc;
|
||||
#endif
|
||||
const U32 maxDist = 1 << zc->params.cParams.windowLog;
|
||||
ZSTD_stats_t* stats = &zc->seqStore.stats;
|
||||
|
||||
ZSTD_statsInit(stats);
|
||||
|
||||
while (remaining) {
|
||||
size_t cSize;
|
||||
ZSTD_statsResetFreqs(stats);
|
||||
|
||||
if (dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE) return ERROR(dstSize_tooSmall); /* not enough space to store compressed block */
|
||||
if (remaining < blockSize) blockSize = remaining;
|
||||
|
||||
if ((U32)(ip+blockSize - zc->base) > zc->loadedDictEnd + maxDist) { /* enforce maxDist */
|
||||
U32 newLowLimit = (U32)(ip+blockSize - zc->base) - maxDist;
|
||||
if ((U32)(ip+blockSize - zc->base) > zc->loadedDictEnd + maxDist) {
|
||||
/* enforce maxDist */
|
||||
U32 const newLowLimit = (U32)(ip+blockSize - zc->base) - maxDist;
|
||||
if (zc->lowLimit < newLowLimit) zc->lowLimit = newLowLimit;
|
||||
if (zc->dictLimit < zc->lowLimit) zc->dictLimit = zc->lowLimit;
|
||||
}
|
||||
@@ -2035,18 +2077,13 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
ssPtr->realMatchSum += ssPtr->realSeqSum * ((zc->params.searchLength == 3) ? 3 : 4);
|
||||
printf("avgMatchL=%.2f avgLitL=%.2f match=%.1f%% lit=%.1f%% reps=%d seq=%d priceFunc=%d\n", (float)ssPtr->realMatchSum/ssPtr->realSeqSum, (float)ssPtr->realLitSum/ssPtr->realSeqSum, 100.0*ssPtr->realMatchSum/(ssPtr->realMatchSum+ssPtr->realLitSum), 100.0*ssPtr->realLitSum/(ssPtr->realMatchSum+ssPtr->realLitSum), ssPtr->realRepSum, ssPtr->realSeqSum, ssPtr->priceFunc);
|
||||
priceFunc++;
|
||||
#endif
|
||||
|
||||
ZSTD_statsPrint(stats, zc->params.cParams.searchLength);
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
U32 frame)
|
||||
{
|
||||
@@ -2055,17 +2092,17 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
||||
|
||||
if (frame && (zc->stage==0)) {
|
||||
hbSize = zc->hbSize;
|
||||
if (dstSize <= hbSize) return ERROR(dstSize_tooSmall);
|
||||
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
|
||||
zc->stage = 1;
|
||||
memcpy(dst, zc->headerBuffer, hbSize);
|
||||
dstSize -= hbSize;
|
||||
dstCapacity -= hbSize;
|
||||
dst = (char*)dst + hbSize;
|
||||
}
|
||||
|
||||
/* Check if blocks follow each other */
|
||||
if (src != zc->nextSrc) {
|
||||
/* not contiguous */
|
||||
size_t delta = zc->nextSrc - ip;
|
||||
size_t const delta = zc->nextSrc - ip;
|
||||
zc->lowLimit = zc->dictLimit;
|
||||
zc->dictLimit = (U32)(zc->nextSrc - zc->base);
|
||||
zc->dictBase = zc->base;
|
||||
@@ -2076,10 +2113,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
||||
|
||||
/* preemptive overflow correction */
|
||||
if (zc->lowLimit > (1<<30)) {
|
||||
U32 btplus = (zc->params.strategy == ZSTD_btlazy2) || (zc->params.strategy == ZSTD_btopt);
|
||||
U32 contentMask = (1 << (zc->params.contentLog - btplus)) - 1;
|
||||
U32 newLowLimit = zc->lowLimit & contentMask; /* preserve position % contentSize */
|
||||
U32 correction = zc->lowLimit - newLowLimit;
|
||||
U32 const btplus = (zc->params.cParams.strategy == ZSTD_btlazy2) || (zc->params.cParams.strategy == ZSTD_btopt);
|
||||
U32 const chainMask = (1 << (zc->params.cParams.chainLog - btplus)) - 1;
|
||||
U32 const newLowLimit = zc->lowLimit & chainMask; /* preserve position % chainSize */
|
||||
U32 const correction = zc->lowLimit - newLowLimit;
|
||||
ZSTD_reduceIndex(zc, correction);
|
||||
zc->base += correction;
|
||||
zc->dictBase += correction;
|
||||
@@ -2096,10 +2133,9 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
||||
}
|
||||
|
||||
zc->nextSrc = ip + srcSize;
|
||||
{
|
||||
size_t cSize;
|
||||
if (frame) cSize = ZSTD_compress_generic (zc, dst, dstSize, src, srcSize);
|
||||
else cSize = ZSTD_compressBlock_internal (zc, dst, dstSize, src, srcSize);
|
||||
{ size_t const cSize = frame ?
|
||||
ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
|
||||
ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
return cSize + hbSize;
|
||||
}
|
||||
@@ -2107,17 +2143,17 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
||||
|
||||
|
||||
size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_compressContinue_internal(zc, dst, dstSize, src, srcSize, 1);
|
||||
return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBlock(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
if (srcSize > ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
||||
zc->params.searchLength = MINMATCH; /* force ZSTD_btopt to MINMATCH in block mode */
|
||||
zc->params.cParams.searchLength = MINMATCH; /* force ZSTD_btopt to MINMATCH in block mode */
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compressBlock searchLength=%d\n", zc->base, zc->params.searchLength);
|
||||
return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 0);
|
||||
}
|
||||
@@ -2139,21 +2175,21 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
||||
zc->nextSrc = iend;
|
||||
if (srcSize <= 8) return 0;
|
||||
|
||||
switch(zc->params.strategy)
|
||||
switch(zc->params.cParams.strategy)
|
||||
{
|
||||
case ZSTD_fast:
|
||||
ZSTD_fillHashTable (zc, iend, zc->params.searchLength);
|
||||
ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_greedy:
|
||||
case ZSTD_lazy:
|
||||
case ZSTD_lazy2:
|
||||
ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength);
|
||||
ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_btlazy2:
|
||||
case ZSTD_btopt:
|
||||
ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.searchLog, zc->params.searchLength);
|
||||
ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2183,7 +2219,7 @@ static size_t ZSTD_loadDictEntropyStats(ZSTD_CCtx* zc, const void* dict, size_t
|
||||
short litlengthNCount[MaxLL+1];
|
||||
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
|
||||
|
||||
const size_t hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
|
||||
size_t const hufHeaderSize = HUF_readCTable(zc->hufTable, 255, dict, dictSize);
|
||||
if (HUF_isError(hufHeaderSize)) return ERROR(dictionary_corrupted);
|
||||
zc->flagStaticTables = 1;
|
||||
dict = (const char*)dict + hufHeaderSize;
|
||||
@@ -2221,43 +2257,42 @@ static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* dict, si
|
||||
if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) return ZSTD_loadDictionaryContent(zc, dict, dictSize);
|
||||
|
||||
/* known magic number : dict is parsed for entropy stats and content */
|
||||
{ size_t const eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+4 /* skip magic */, dictSize-4) + 4;
|
||||
if (ZSTD_isError(eSize)) return eSize;
|
||||
return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
|
||||
{ size_t const eSize = ZSTD_loadDictEntropyStats(zc, (const char*)dict+4 /* skip magic */, dictSize-4) + 4;
|
||||
if (ZSTD_isError(eSize)) return eSize;
|
||||
return ZSTD_loadDictionaryContent(zc, (const char*)dict+eSize, dictSize-eSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_compressBegin_advanced() :
|
||||
/*! ZSTD_compressBegin_internal() :
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
|
||||
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* zc,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params)
|
||||
ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
{
|
||||
ZSTD_validateParams(¶ms);
|
||||
U32 hashLog3 = (pledgedSrcSize || pledgedSrcSize >= 8192) ? ZSTD_HASHLOG3_MAX : ((pledgedSrcSize >= 2048) ? ZSTD_HASHLOG3_MIN + 1 : ZSTD_HASHLOG3_MIN);
|
||||
zc->hashLog3 = (params.cParams.searchLength==3) ? hashLog3 : 0;
|
||||
// printf("windowLog=%d hashLog=%d hashLog3=%d \n", params.windowLog, params.hashLog, zc->hashLog3);
|
||||
|
||||
{ size_t const errorCode = ZSTD_resetCCtx_advanced(zc, params);
|
||||
if (ZSTD_isError(errorCode)) return errorCode; }
|
||||
if (ZSTD_isError(errorCode)) return errorCode; }
|
||||
|
||||
/* Write Frame Header into ctx headerBuffer */
|
||||
MEM_writeLE32(zc->headerBuffer, ZSTD_MAGICNUMBER);
|
||||
{
|
||||
BYTE* const op = (BYTE*)zc->headerBuffer;
|
||||
U32 const fcsSize[4] = { 0, 1, 2, 8 };
|
||||
U32 const fcsId = (params.srcSize>0) + (params.srcSize>=256) + (params.srcSize>=65536+256); /* 0-3 */
|
||||
BYTE fdescriptor = (BYTE)(params.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN); /* windowLog : 4 KB - 128 MB */
|
||||
fdescriptor |= (BYTE)((params.searchLength==3)<<4); /* mml : 3-4 */
|
||||
{ BYTE* const op = (BYTE*)zc->headerBuffer;
|
||||
U32 const fcsId = (pledgedSrcSize>0) + (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256); /* 0-3 */
|
||||
BYTE fdescriptor = (BYTE)(params.cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN); /* windowLog : 4 KB - 128 MB */
|
||||
fdescriptor |= (BYTE)((params.cParams.searchLength==3)<<4); /* mml : 3-4 */
|
||||
fdescriptor |= (BYTE)(fcsId << 6);
|
||||
op[4] = fdescriptor;
|
||||
switch(fcsId)
|
||||
{
|
||||
default: /* impossible */
|
||||
case 0 : break;
|
||||
case 1 : op[5] = (BYTE)(params.srcSize); break;
|
||||
case 2 : MEM_writeLE16(op+5, (U16)(params.srcSize-256)); break;
|
||||
case 3 : MEM_writeLE64(op+5, (U64)(params.srcSize)); break;
|
||||
case 1 : op[5] = (BYTE)(pledgedSrcSize); break;
|
||||
case 2 : MEM_writeLE16(op+5, (U16)(pledgedSrcSize-256)); break;
|
||||
case 3 : MEM_writeLE64(op+5, (U64)(pledgedSrcSize)); break;
|
||||
}
|
||||
zc->hbSize = ZSTD_frameHeaderSize_min + fcsSize[fcsId];
|
||||
zc->hbSize = ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
|
||||
}
|
||||
|
||||
zc->stage = 0;
|
||||
@@ -2265,18 +2300,46 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_compressBegin_advanced() :
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* zc,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
{
|
||||
/* compression parameters verification and optimization */
|
||||
{ size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, pledgedSrcSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode; }
|
||||
|
||||
return ZSTD_compressBegin_internal(zc, dict, dictSize, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* zc, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, dictSize);
|
||||
params.srcSize = 0;
|
||||
ZSTD_parameters params;
|
||||
params.cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
params.fParams.contentSizeFlag = 0;
|
||||
ZSTD_adjustCParams(¶ms.cParams, 0, dictSize);
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_usingDict compressionLevel=%d\n", zc->base, compressionLevel);
|
||||
return ZSTD_compressBegin_advanced(zc, dict, dictSize, params);
|
||||
return ZSTD_compressBegin_internal(zc, dict, dictSize, params, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBegin_targetSrcSize(ZSTD_CCtx* zc, const void* dict, size_t dictSize, size_t targetSrcSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters params;
|
||||
params.cParams = ZSTD_getCParams(compressionLevel, targetSrcSize, dictSize);
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
ZSTD_adjustCParams(¶ms.cParams, targetSrcSize, dictSize);
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin_targetSrcSize compressionLevel=%d\n", zc->base, compressionLevel);
|
||||
return ZSTD_compressBegin_internal(zc, dict, dictSize, params, targetSrcSize);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBegin(ZSTD_CCtx* zc, int compressionLevel)
|
||||
{
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compressBegin compressionLevel=%d\n", zc->base, compressionLevel);
|
||||
return ZSTD_compressBegin_advanced(zc, NULL, 0, ZSTD_getParams(compressionLevel, 0));
|
||||
return ZSTD_compressBegin_usingDict(zc, NULL, 0, compressionLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -2288,7 +2351,7 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t dstCapacity)
|
||||
BYTE* op = (BYTE*)dst;
|
||||
size_t hbSize = 0;
|
||||
|
||||
/* empty frame */
|
||||
/* special case : empty frame : header still within internal buffer */
|
||||
if (zc->stage==0) {
|
||||
hbSize = zc->hbSize;
|
||||
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
|
||||
@@ -2312,20 +2375,19 @@ size_t ZSTD_compress_usingPreparedCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* prepare
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t outSize;
|
||||
size_t errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
errorCode = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
outSize = errorCode;
|
||||
errorCode = ZSTD_compressEnd(cctx, (char*)dst+outSize, dstCapacity-outSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
outSize += errorCode;
|
||||
return outSize;
|
||||
{ size_t const errorCode = ZSTD_copyCCtx(cctx, preparedCCtx);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
}
|
||||
{ size_t const cSize = ZSTD_compressContinue(cctx, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
{ size_t const endSize = ZSTD_compressEnd(cctx, (char*)dst+cSize, dstCapacity-cSize);
|
||||
if (ZSTD_isError(endSize)) return endSize;
|
||||
return cSize + endSize;
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
||||
static size_t ZSTD_compress_internal (ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
@@ -2335,33 +2397,48 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
|
||||
BYTE* op = ostart;
|
||||
|
||||
/* Init */
|
||||
{ size_t const errorCode = ZSTD_compressBegin_advanced(ctx, dict, dictSize, params);
|
||||
if(ZSTD_isError(errorCode)) return errorCode; }
|
||||
{ size_t const errorCode = ZSTD_compressBegin_internal(ctx, dict, dictSize, params, srcSize);
|
||||
if(ZSTD_isError(errorCode)) return errorCode; }
|
||||
|
||||
/* body (compression) */
|
||||
{ size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
|
||||
if(ZSTD_isError(oSize)) return oSize;
|
||||
op += oSize;
|
||||
dstCapacity -= oSize; }
|
||||
if(ZSTD_isError(oSize)) return oSize;
|
||||
op += oSize;
|
||||
dstCapacity -= oSize; }
|
||||
|
||||
/* Close frame */
|
||||
{ size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
|
||||
if(ZSTD_isError(oSize)) return oSize;
|
||||
op += oSize; }
|
||||
if(ZSTD_isError(oSize)) return oSize;
|
||||
op += oSize; }
|
||||
|
||||
return (op - ostart);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size_t const errorCode = ZSTD_checkCParams_advanced(params.cParams, srcSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
|
||||
}
|
||||
|
||||
size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters params;
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compress_usingDict srcSize=%d dictSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, (int)dictSize, compressionLevel);
|
||||
return ZSTD_compress_advanced(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, ZSTD_getParams(compressionLevel, srcSize));
|
||||
params.cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
ZSTD_adjustCParams(¶ms.cParams, srcSize, dictSize);
|
||||
return ZSTD_compress_internal(ctx, dst, dstCapacity, src, srcSize, dict, dictSize, params);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressCCtx (ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_compressCCtx srcSize=%d compressionLevel=%d\n", ctx->base, (int)srcSize, compressionLevel);
|
||||
return ZSTD_compress_advanced(ctx, dst, dstCapacity, src, srcSize, NULL, 0, ZSTD_getParams(compressionLevel, srcSize));
|
||||
return ZSTD_compress_usingDict(ctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);
|
||||
}
|
||||
|
||||
size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel)
|
||||
@@ -2380,127 +2457,129 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
|
||||
#define ZSTD_MAX_CLEVEL 22
|
||||
unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
|
||||
|
||||
|
||||
static const ZSTD_parameters ZSTD_defaultParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
||||
static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
|
||||
{ /* "default" */
|
||||
/* l, W, C, H, S, L, SL, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
|
||||
{ 0, 19, 13, 14, 1, 7, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 0, 19, 15, 16, 1, 6, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 0, 20, 18, 20, 1, 6, 4, ZSTD_fast }, /* level 3 */
|
||||
{ 0, 20, 13, 17, 2, 5, 4, ZSTD_greedy }, /* level 4.*/
|
||||
{ 0, 20, 15, 18, 3, 5, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 0, 21, 16, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 0, 21, 17, 20, 3, 5, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 0, 21, 18, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 0, 21, 20, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 0, 21, 19, 21, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 0, 22, 20, 22, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 0, 22, 20, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 0, 22, 21, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */
|
||||
{ 0, 22, 21, 22, 6, 5, 4, ZSTD_lazy2 }, /* level 14 */
|
||||
{ 0, 22, 21, 21, 5, 5, 4, ZSTD_btlazy2 }, /* level 15 */
|
||||
{ 0, 23, 22, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */
|
||||
{ 0, 23, 22, 22, 6, 5, 22, ZSTD_btopt }, /* level 17 */
|
||||
{ 0, 22, 22, 22, 5, 3, 44, ZSTD_btopt }, /* level 18 */
|
||||
{ 0, 23, 24, 22, 7, 3, 44, ZSTD_btopt }, /* level 19 */
|
||||
{ 0, 25, 26, 22, 7, 3, 71, ZSTD_btopt }, /* level 20 */
|
||||
{ 0, 26, 26, 24, 7, 3,256, ZSTD_btopt }, /* level 21 */
|
||||
{ 0, 27, 28, 26, 9, 3,256, ZSTD_btopt }, /* level 22 */
|
||||
/* W, C, H, S, L, SL, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
|
||||
{ 19, 13, 14, 1, 7, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 19, 15, 16, 1, 6, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 20, 18, 20, 1, 6, 4, ZSTD_fast }, /* level 3 */
|
||||
{ 20, 13, 17, 2, 5, 4, ZSTD_greedy }, /* level 4.*/
|
||||
{ 20, 15, 18, 3, 5, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 21, 16, 19, 2, 5, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 21, 17, 20, 3, 5, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 21, 18, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 21, 20, 20, 3, 5, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 21, 19, 21, 4, 5, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 22, 20, 22, 4, 5, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 22, 20, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 22, 21, 22, 5, 5, 4, ZSTD_lazy2 }, /* level 13 */
|
||||
{ 22, 21, 22, 6, 5, 4, ZSTD_lazy2 }, /* level 14 */
|
||||
{ 22, 21, 21, 5, 5, 4, ZSTD_btlazy2 }, /* level 15 */
|
||||
{ 23, 22, 22, 5, 5, 4, ZSTD_btlazy2 }, /* level 16 */
|
||||
{ 23, 22, 22, 6, 5, 22, ZSTD_btopt }, /* level 17 */
|
||||
{ 22, 22, 22, 5, 3, 44, ZSTD_btopt }, /* level 18 */
|
||||
{ 23, 24, 22, 7, 3, 44, ZSTD_btopt }, /* level 19 */
|
||||
{ 25, 26, 22, 7, 3, 71, ZSTD_btopt }, /* level 20 */
|
||||
{ 26, 26, 24, 7, 3,256, ZSTD_btopt }, /* level 21 */
|
||||
{ 27, 28, 26, 9, 3,256, ZSTD_btopt }, /* level 22 */
|
||||
},
|
||||
{ /* for srcSize <= 256 KB */
|
||||
/* l, W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */
|
||||
{ 0, 18, 14, 15, 1, 6, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 0, 18, 14, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 0, 18, 14, 17, 1, 5, 4, ZSTD_fast }, /* level 3.*/
|
||||
{ 0, 18, 14, 15, 4, 4, 4, ZSTD_greedy }, /* level 4 */
|
||||
{ 0, 18, 16, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 0, 18, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 0, 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 0, 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 0, 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 0, 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 0, 18, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 0, 18, 18, 17, 4, 4, 4, ZSTD_btlazy2 }, /* level 12 */
|
||||
{ 0, 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
|
||||
{ 0, 18, 17, 19, 8, 4, 24, ZSTD_btopt }, /* level 14.*/
|
||||
{ 0, 18, 19, 19, 8, 4, 48, ZSTD_btopt }, /* level 15.*/
|
||||
{ 0, 18, 19, 18, 9, 4,128, ZSTD_btopt }, /* level 16.*/
|
||||
{ 0, 18, 19, 18, 9, 4,192, ZSTD_btopt }, /* level 17.*/
|
||||
{ 0, 18, 19, 18, 9, 4,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 0, 18, 19, 18, 10, 4,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 0, 18, 19, 18, 11, 4,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 0, 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 0, 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 22*/
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 */
|
||||
{ 18, 14, 15, 1, 6, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 18, 14, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 18, 14, 17, 1, 5, 4, ZSTD_fast }, /* level 3.*/
|
||||
{ 18, 14, 15, 4, 4, 4, ZSTD_greedy }, /* level 4 */
|
||||
{ 18, 16, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 18, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 18, 17, 17, 4, 4, 4, ZSTD_lazy }, /* level 7 */
|
||||
{ 18, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 18, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 18, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 18, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 18, 18, 17, 4, 4, 4, ZSTD_btlazy2 }, /* level 12 */
|
||||
{ 18, 19, 17, 7, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
|
||||
{ 18, 17, 19, 8, 4, 24, ZSTD_btopt }, /* level 14.*/
|
||||
{ 18, 19, 19, 8, 4, 48, ZSTD_btopt }, /* level 15.*/
|
||||
{ 18, 19, 18, 9, 4,128, ZSTD_btopt }, /* level 16.*/
|
||||
{ 18, 19, 18, 9, 4,192, ZSTD_btopt }, /* level 17.*/
|
||||
{ 18, 19, 18, 9, 4,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 18, 19, 18, 10, 4,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 18, 19, 18, 11, 4,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 18, 19, 18, 12, 4,256, ZSTD_btopt }, /* level 22*/
|
||||
},
|
||||
{ /* for srcSize <= 128 KB */
|
||||
/* l, W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
|
||||
{ 0, 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 0, 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 0, 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */
|
||||
{ 0, 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */
|
||||
{ 0, 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 0, 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 0, 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 0, 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 0, 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 0, 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 0, 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 0, 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 0, 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
|
||||
{ 0, 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
|
||||
{ 0, 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
|
||||
{ 0, 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
|
||||
{ 0, 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
|
||||
{ 0, 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 0, 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 0, 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 0, 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 0, 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 - never used */
|
||||
{ 17, 12, 13, 1, 6, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 17, 13, 16, 1, 5, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 17, 13, 14, 2, 5, 4, ZSTD_greedy }, /* level 3 */
|
||||
{ 17, 13, 15, 3, 4, 4, ZSTD_greedy }, /* level 4 */
|
||||
{ 17, 15, 17, 4, 4, 4, ZSTD_greedy }, /* level 5 */
|
||||
{ 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
|
||||
{ 17, 15, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 7 */
|
||||
{ 17, 17, 17, 4, 4, 4, ZSTD_lazy2 }, /* level 8 */
|
||||
{ 17, 17, 17, 5, 4, 4, ZSTD_lazy2 }, /* level 9 */
|
||||
{ 17, 17, 17, 6, 4, 4, ZSTD_lazy2 }, /* level 10 */
|
||||
{ 17, 17, 17, 7, 4, 4, ZSTD_lazy2 }, /* level 11 */
|
||||
{ 17, 17, 17, 8, 4, 4, ZSTD_lazy2 }, /* level 12 */
|
||||
{ 17, 18, 17, 6, 4, 4, ZSTD_btlazy2 }, /* level 13.*/
|
||||
{ 17, 17, 17, 7, 3, 8, ZSTD_btopt }, /* level 14.*/
|
||||
{ 17, 17, 17, 7, 3, 16, ZSTD_btopt }, /* level 15.*/
|
||||
{ 17, 18, 17, 7, 3, 32, ZSTD_btopt }, /* level 16.*/
|
||||
{ 17, 18, 17, 7, 3, 64, ZSTD_btopt }, /* level 17.*/
|
||||
{ 17, 18, 17, 7, 3,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 17, 18, 17, 8, 3,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 17, 18, 17, 9, 3,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 17, 18, 17, 10, 3,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 17, 18, 17, 11, 3,256, ZSTD_btopt }, /* level 22.*/
|
||||
},
|
||||
{ /* for srcSize <= 16 KB */
|
||||
/* l, W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */
|
||||
{ 0, 14, 14, 14, 1, 4, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 0, 14, 14, 15, 1, 4, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 0, 14, 14, 14, 4, 4, 4, ZSTD_greedy }, /* level 3.*/
|
||||
{ 0, 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 4.*/
|
||||
{ 0, 14, 14, 14, 4, 4, 4, ZSTD_lazy2 }, /* level 5 */
|
||||
{ 0, 14, 14, 14, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */
|
||||
{ 0, 14, 14, 14, 6, 4, 4, ZSTD_lazy2 }, /* level 7.*/
|
||||
{ 0, 14, 14, 14, 7, 4, 4, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 0, 14, 15, 14, 6, 4, 4, ZSTD_btlazy2 }, /* level 9.*/
|
||||
{ 0, 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
|
||||
{ 0, 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
|
||||
{ 0, 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
|
||||
{ 0, 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
|
||||
{ 0, 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
|
||||
{ 0, 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
|
||||
{ 0, 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
|
||||
{ 0, 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
|
||||
{ 0, 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 0, 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 0, 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 0, 14, 15, 15, 9, 3,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 0, 14, 15, 15, 10, 3,256, ZSTD_btopt }, /* level 22.*/
|
||||
/* W, C, H, S, L, T, strat */
|
||||
{ 0, 0, 0, 0, 0, 0, ZSTD_fast }, /* level 0 -- never used */
|
||||
{ 14, 14, 14, 1, 4, 4, ZSTD_fast }, /* level 1 */
|
||||
{ 14, 14, 15, 1, 4, 4, ZSTD_fast }, /* level 2 */
|
||||
{ 14, 14, 14, 4, 4, 4, ZSTD_greedy }, /* level 3.*/
|
||||
{ 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 4.*/
|
||||
{ 14, 14, 14, 4, 4, 4, ZSTD_lazy2 }, /* level 5 */
|
||||
{ 14, 14, 14, 5, 4, 4, ZSTD_lazy2 }, /* level 6 */
|
||||
{ 14, 14, 14, 6, 4, 4, ZSTD_lazy2 }, /* level 7.*/
|
||||
{ 14, 14, 14, 7, 4, 4, ZSTD_lazy2 }, /* level 8.*/
|
||||
{ 14, 15, 14, 6, 4, 4, ZSTD_btlazy2 }, /* level 9.*/
|
||||
{ 14, 15, 14, 3, 3, 6, ZSTD_btopt }, /* level 10.*/
|
||||
{ 14, 15, 14, 6, 3, 8, ZSTD_btopt }, /* level 11.*/
|
||||
{ 14, 15, 14, 6, 3, 16, ZSTD_btopt }, /* level 12.*/
|
||||
{ 14, 15, 14, 6, 3, 24, ZSTD_btopt }, /* level 13.*/
|
||||
{ 14, 15, 15, 6, 3, 48, ZSTD_btopt }, /* level 14.*/
|
||||
{ 14, 15, 15, 6, 3, 64, ZSTD_btopt }, /* level 15.*/
|
||||
{ 14, 15, 15, 6, 3, 96, ZSTD_btopt }, /* level 16.*/
|
||||
{ 14, 15, 15, 6, 3,128, ZSTD_btopt }, /* level 17.*/
|
||||
{ 14, 15, 15, 6, 3,256, ZSTD_btopt }, /* level 18.*/
|
||||
{ 14, 15, 15, 7, 3,256, ZSTD_btopt }, /* level 19.*/
|
||||
{ 14, 15, 15, 8, 3,256, ZSTD_btopt }, /* level 20.*/
|
||||
{ 14, 15, 15, 9, 3,256, ZSTD_btopt }, /* level 21.*/
|
||||
{ 14, 15, 15, 10, 3,256, ZSTD_btopt }, /* level 22.*/
|
||||
},
|
||||
};
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* @return ZSTD_parameters structure for a selected compression level and srcSize.
|
||||
* `srcSizeHint` value is optional, select 0 if not known */
|
||||
ZSTD_parameters ZSTD_getParams(int compressionLevel, U64 srcSizeHint)
|
||||
* `srcSize` value is optional, select 0 if not known */
|
||||
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, U64 srcSize, size_t dictSize)
|
||||
{
|
||||
ZSTD_parameters result;
|
||||
int tableID = ((srcSizeHint-1) <= 256 KB) + ((srcSizeHint-1) <= 128 KB) + ((srcSizeHint-1) <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
|
||||
ZSTD_compressionParameters cp;
|
||||
size_t const addedSize = srcSize ? 0 : 500;
|
||||
U64 const rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
|
||||
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
|
||||
if (compressionLevel<=0) compressionLevel = 1;
|
||||
if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
|
||||
#if ZSTD_OPT_DEBUG >= 1
|
||||
tableID=0;
|
||||
#endif
|
||||
result = ZSTD_defaultParameters[tableID][compressionLevel];
|
||||
result.srcSize = srcSizeHint;
|
||||
return result;
|
||||
cp = ZSTD_defaultCParameters[tableID][compressionLevel];
|
||||
if (MEM_32bits()) { /* auto-correction, for 32-bits mode */
|
||||
if (cp.windowLog > ZSTD_WINDOWLOG_MAX) cp.windowLog = ZSTD_WINDOWLOG_MAX;
|
||||
if (cp.chainLog > ZSTD_CHAINLOG_MAX) cp.chainLog = ZSTD_CHAINLOG_MAX;
|
||||
if (cp.hashLog > ZSTD_HASHLOG_MAX) cp.hashLog = ZSTD_HASHLOG_MAX;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
+214
-265
@@ -26,7 +26,7 @@
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd source repository : https://github.com/Cyan4973/zstd
|
||||
- zstd homepage : http://www.zstd.net
|
||||
*/
|
||||
|
||||
/* ***************************************************************
|
||||
@@ -75,7 +75,6 @@
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
||||
#else
|
||||
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
@@ -84,16 +83,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Local types
|
||||
***************************************/
|
||||
typedef struct
|
||||
{
|
||||
blockType_t blockType;
|
||||
U32 origSize;
|
||||
} blockProperties_t;
|
||||
|
||||
|
||||
/*_*******************************************************
|
||||
* Memory operations
|
||||
**********************************************************/
|
||||
@@ -286,8 +275,6 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
||||
TO DO
|
||||
*/
|
||||
|
||||
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
|
||||
|
||||
/** ZSTD_frameHeaderSize() :
|
||||
* srcSize must be >= ZSTD_frameHeaderSize_min.
|
||||
* @return : size of the Frame Header */
|
||||
@@ -335,28 +322,32 @@ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t
|
||||
|
||||
/** ZSTD_decodeFrameHeader() :
|
||||
* `srcSize` must be the size provided by ZSTD_frameHeaderSize().
|
||||
* @return : 0, or an error code, which can be tested using ZSTD_isError() */
|
||||
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
||||
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* zc, const void* src, size_t srcSize)
|
||||
{
|
||||
size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
|
||||
size_t const result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
|
||||
if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
blockType_t blockType;
|
||||
U32 origSize;
|
||||
} blockProperties_t;
|
||||
|
||||
/*! ZSTD_getcBlockSize() :
|
||||
* Provides the size of compressed block from block header `src` */
|
||||
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
|
||||
{
|
||||
const BYTE* const in = (const BYTE* const)src;
|
||||
BYTE headerFlags;
|
||||
U32 cSize;
|
||||
|
||||
if (srcSize < 3)
|
||||
return ERROR(srcSize_wrong);
|
||||
if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
|
||||
headerFlags = *in;
|
||||
bpPtr->blockType = (blockType_t)((*in) >> 6);
|
||||
cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
|
||||
|
||||
bpPtr->blockType = (blockType_t)(headerFlags >> 6);
|
||||
bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
|
||||
|
||||
if (bpPtr->blockType == bt_end) return 0;
|
||||
@@ -365,9 +356,9 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bp
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
|
||||
if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
|
||||
memcpy(dst, src, srcSize);
|
||||
return srcSize;
|
||||
}
|
||||
@@ -508,126 +499,111 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
|
||||
FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
|
||||
const void* src, size_t srcSize)
|
||||
/*! ZSTD_buildSeqTable() :
|
||||
@return : nb bytes read from src,
|
||||
or an error code if it fails, testable with ZSTD_isError()
|
||||
*/
|
||||
FORCE_INLINE size_t ZSTD_buildSeqTableOff(FSE_DTable* DTable, U32 type, U32 rawBits, U32 maxLog,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 max = (1<<rawBits)-1;
|
||||
switch(type)
|
||||
{
|
||||
case FSE_ENCODING_RLE :
|
||||
if (!srcSize) return ERROR(srcSize_wrong);
|
||||
FSE_buildDTable_rle(DTable, (*(const BYTE*)src) & max); /* if *src > max, data is corrupted */
|
||||
return 1;
|
||||
case FSE_ENCODING_RAW :
|
||||
FSE_buildDTable_raw(DTable, rawBits);
|
||||
return 0;
|
||||
case FSE_ENCODING_STATIC:
|
||||
return 0;
|
||||
default : /* impossible */
|
||||
case FSE_ENCODING_DYNAMIC :
|
||||
{ U32 tableLog;
|
||||
S16 norm[MaxSeq+1];
|
||||
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
||||
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
|
||||
if (tableLog > maxLog) return ERROR(corruption_detected);
|
||||
FSE_buildDTable(DTable, norm, max, tableLog);
|
||||
return headerSize;
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE size_t ZSTD_buildSeqTable(FSE_DTable* DTable, U32 type, U32 max, U32 maxLog,
|
||||
const void* src, size_t srcSize,
|
||||
const S16* defaultNorm, U32 defaultLog)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case FSE_ENCODING_RLE :
|
||||
if (!srcSize) return ERROR(srcSize_wrong);
|
||||
if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);
|
||||
FSE_buildDTable_rle(DTable, *(const BYTE*)src); /* if *src > max, data is corrupted */
|
||||
return 1;
|
||||
case FSE_ENCODING_RAW :
|
||||
FSE_buildDTable(DTable, defaultNorm, max, defaultLog);
|
||||
return 0;
|
||||
case FSE_ENCODING_STATIC:
|
||||
return 0;
|
||||
default : /* impossible */
|
||||
case FSE_ENCODING_DYNAMIC :
|
||||
{ U32 tableLog;
|
||||
S16 norm[MaxSeq+1];
|
||||
size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
|
||||
if (FSE_isError(headerSize)) return ERROR(corruption_detected);
|
||||
if (tableLog > maxLog) return ERROR(corruption_detected);
|
||||
FSE_buildDTable(DTable, norm, max, tableLog);
|
||||
return headerSize;
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_decodeSeqHeaders(int* nbSeqPtr,
|
||||
FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const BYTE* const istart = (const BYTE* const)src;
|
||||
const BYTE* ip = istart;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
U32 LLtype, Offtype, MLtype;
|
||||
U32 LLlog, Offlog, MLlog;
|
||||
size_t dumpsLength;
|
||||
const BYTE* ip = istart;
|
||||
|
||||
/* check */
|
||||
if (srcSize < MIN_SEQUENCES_SIZE)
|
||||
return ERROR(srcSize_wrong);
|
||||
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
||||
|
||||
/* SeqHead */
|
||||
*nbSeq = *ip++;
|
||||
if (*nbSeq==0) return 1;
|
||||
if (*nbSeq >= 0x7F) {
|
||||
if (*nbSeq == 0xFF)
|
||||
*nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||
else
|
||||
*nbSeq = ((nbSeq[0]-0x80)<<8) + *ip++;
|
||||
{ int nbSeq = *ip++;
|
||||
if (!nbSeq) { *nbSeqPtr=0; return 1; }
|
||||
if (nbSeq > 0x7F) {
|
||||
if (nbSeq == 0xFF)
|
||||
nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
|
||||
else
|
||||
nbSeq = ((nbSeq-0x80)<<8) + *ip++;
|
||||
}
|
||||
*nbSeqPtr = nbSeq;
|
||||
}
|
||||
|
||||
/* FSE table descriptors */
|
||||
LLtype = *ip >> 6;
|
||||
Offtype = (*ip >> 4) & 3;
|
||||
MLtype = (*ip >> 2) & 3;
|
||||
if (*ip & 2) {
|
||||
dumpsLength = ip[2];
|
||||
dumpsLength += ip[1] << 8;
|
||||
ip += 3;
|
||||
} else {
|
||||
dumpsLength = ip[1];
|
||||
dumpsLength += (ip[0] & 1) << 8;
|
||||
ip += 2;
|
||||
}
|
||||
*dumpsPtr = ip;
|
||||
ip += dumpsLength;
|
||||
*dumpsLengthPtr = dumpsLength;
|
||||
{ U32 const LLtype = *ip >> 6;
|
||||
U32 const Offtype = (*ip >> 4) & 3;
|
||||
U32 const MLtype = (*ip >> 2) & 3;
|
||||
ip++;
|
||||
|
||||
/* check */
|
||||
if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
|
||||
/* sequences */
|
||||
{
|
||||
S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */
|
||||
size_t headerSize;
|
||||
/* check */
|
||||
if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
|
||||
|
||||
/* Build DTables */
|
||||
switch(LLtype)
|
||||
{
|
||||
U32 max;
|
||||
case FSE_ENCODING_RLE :
|
||||
LLlog = 0;
|
||||
FSE_buildDTable_rle(DTableLL, *ip++);
|
||||
break;
|
||||
case FSE_ENCODING_RAW :
|
||||
LLlog = LLbits;
|
||||
FSE_buildDTable_raw(DTableLL, LLbits);
|
||||
break;
|
||||
case FSE_ENCODING_STATIC:
|
||||
break;
|
||||
case FSE_ENCODING_DYNAMIC :
|
||||
default : /* impossible */
|
||||
max = MaxLL;
|
||||
headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
|
||||
if (FSE_isError(headerSize)) return ERROR(GENERIC);
|
||||
if (LLlog > LLFSELog) return ERROR(corruption_detected);
|
||||
ip += headerSize;
|
||||
FSE_buildDTable(DTableLL, norm, max, LLlog);
|
||||
{ size_t const bhSize = ZSTD_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog);
|
||||
if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
|
||||
ip += bhSize;
|
||||
}
|
||||
|
||||
switch(Offtype)
|
||||
{
|
||||
U32 max;
|
||||
case FSE_ENCODING_RLE :
|
||||
Offlog = 0;
|
||||
if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
|
||||
FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
|
||||
break;
|
||||
case FSE_ENCODING_RAW :
|
||||
Offlog = Offbits;
|
||||
FSE_buildDTable_raw(DTableOffb, Offbits);
|
||||
break;
|
||||
case FSE_ENCODING_STATIC:
|
||||
break;
|
||||
case FSE_ENCODING_DYNAMIC :
|
||||
default : /* impossible */
|
||||
max = MaxOff;
|
||||
headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
|
||||
if (FSE_isError(headerSize)) return ERROR(GENERIC);
|
||||
if (Offlog > OffFSELog) return ERROR(corruption_detected);
|
||||
ip += headerSize;
|
||||
FSE_buildDTable(DTableOffb, norm, max, Offlog);
|
||||
{ size_t const bhSize = ZSTD_buildSeqTableOff(DTableOffb, Offtype, Offbits, OffFSELog, ip, iend-ip);
|
||||
if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
|
||||
ip += bhSize;
|
||||
}
|
||||
|
||||
switch(MLtype)
|
||||
{
|
||||
U32 max;
|
||||
case FSE_ENCODING_RLE :
|
||||
MLlog = 0;
|
||||
if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
|
||||
FSE_buildDTable_rle(DTableML, *ip++);
|
||||
break;
|
||||
case FSE_ENCODING_RAW :
|
||||
MLlog = MLbits;
|
||||
FSE_buildDTable_raw(DTableML, MLbits);
|
||||
break;
|
||||
case FSE_ENCODING_STATIC:
|
||||
break;
|
||||
case FSE_ENCODING_DYNAMIC :
|
||||
default : /* impossible */
|
||||
max = MaxML;
|
||||
headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
|
||||
if (FSE_isError(headerSize)) return ERROR(GENERIC);
|
||||
if (MLlog > MLFSELog) return ERROR(corruption_detected);
|
||||
ip += headerSize;
|
||||
FSE_buildDTable(DTableML, norm, max, MLlog);
|
||||
{ size_t const bhSize = ZSTD_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog);
|
||||
if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
|
||||
ip += bhSize;
|
||||
} }
|
||||
|
||||
return ip-istart;
|
||||
@@ -646,41 +622,48 @@ typedef struct {
|
||||
FSE_DState_t stateOffb;
|
||||
FSE_DState_t stateML;
|
||||
size_t prevOffset[ZSTD_REP_INIT];
|
||||
const BYTE* dumps;
|
||||
const BYTE* dumpsEnd;
|
||||
} seqState_t;
|
||||
|
||||
|
||||
|
||||
static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
|
||||
{
|
||||
const BYTE* dumps = seqState->dumps;
|
||||
const BYTE* const de = seqState->dumpsEnd;
|
||||
size_t litLength, offset;
|
||||
|
||||
/* Literal length */
|
||||
litLength = FSE_peakSymbol(&(seqState->stateLL));
|
||||
if (litLength == MaxLL) {
|
||||
const U32 add = *dumps++;
|
||||
if (add < 255) litLength += add;
|
||||
else {
|
||||
litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
|
||||
if (litLength&1) litLength>>=1, dumps += 3;
|
||||
else litLength = (U16)(litLength)>>1, dumps += 2;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
U32 const llCode = FSE_peekSymbol(&(seqState->stateLL));
|
||||
U32 const mlCode = FSE_peekSymbol(&(seqState->stateML));
|
||||
U32 const ofCode = FSE_peekSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
|
||||
|
||||
/* Offset */
|
||||
{
|
||||
static const U32 offsetPrefix[MaxOff+1] = {
|
||||
1 /*fake*/, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100,
|
||||
0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
|
||||
0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, /*fake*/ 1, 1, 1, 1 };
|
||||
const U32 offsetCode = FSE_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
|
||||
const U32 nbBits = offsetCode ? offsetCode-1 : 0;
|
||||
offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
|
||||
U32 const llBits = LL_bits[llCode];
|
||||
U32 const mlBits = ML_bits[mlCode];
|
||||
U32 const ofBits = ofCode;
|
||||
U32 const totalBits = llBits+mlBits+ofBits;
|
||||
|
||||
static const U32 LL_base[MaxLL+1] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
|
||||
0x2000, 0x4000, 0x8000, 0x10000 };
|
||||
|
||||
static const U32 ML_base[MaxML+1] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 34, 36, 38, 40, 44, 48, 56, 64, 80, 96, 0x80, 0x100, 0x200, 0x400, 0x800,
|
||||
0x1000, 0x2000, 0x4000, 0x8000, 0x10000 };
|
||||
|
||||
static const U32 OF_base[MaxOff+1] = {
|
||||
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, /*fake*/ 1, 1, 1, 1, 1 };
|
||||
|
||||
/* sequence */
|
||||
{ size_t const offset = ofCode ? OF_base[ofCode] + BIT_readBits(&(seqState->DStream), ofBits) : /* <= 26 bits */
|
||||
llCode ? seq->offset : seqState->prevOffset[0];
|
||||
if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
|
||||
if (ofCode | !llCode) seqState->prevOffset[0] = seq->offset; /* cmove */
|
||||
seq->offset = offset;
|
||||
|
||||
#if ZSTD_REP_NUM == 4
|
||||
if (offsetCode==0) offset = 0;
|
||||
if (ofCode==0) offset = 0;
|
||||
|
||||
if (offset < ZSTD_REP_NUM) {
|
||||
if (litLength == 0 && offset <= 1) offset = 1-offset;
|
||||
@@ -713,12 +696,12 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
|
||||
#endif
|
||||
}
|
||||
#else // ZSTD_REP_NUM == 1
|
||||
#if 0
|
||||
if (offsetCode==0) offset = litLength ? seq->offset : seqState->prevOffset[0]; /* repcode, cmove */
|
||||
#if 1
|
||||
/* if (ofCode==0) offset = litLength ? seq->offset : seqState->prevOffset[0];
|
||||
else offset -= ZSTD_REP_MOVE;
|
||||
if (offsetCode | !litLength) seqState->prevOffset[0] = seq->offset; /* cmove */
|
||||
if (ofCode | !litLength) seqState->prevOffset[0] = seq->offset; */
|
||||
#else
|
||||
if (offsetCode==0) {
|
||||
if (ofCode==0) {
|
||||
if (!litLength) {
|
||||
offset = seqState->prevOffset[0]; /* repcode, cmove */
|
||||
seqState->prevOffset[0] = seq->offset; /* cmove */
|
||||
@@ -730,44 +713,20 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
|
||||
// printf("offsetCode=%d nbBits=%d offset=%d\n", offsetCode, nbBits, (int)offset); fflush(stdout);
|
||||
}
|
||||
|
||||
/* Literal length update */
|
||||
FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
|
||||
if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
|
||||
seq->matchLength = ML_base[mlCode] + mls + ((mlCode>31) ? BIT_readBits(&(seqState->DStream), mlBits) : 0); /* <= 16 bits */
|
||||
if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&(seqState->DStream));
|
||||
|
||||
/* MatchLength */
|
||||
{
|
||||
size_t matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
|
||||
if (matchLength == MaxML) {
|
||||
const U32 add = *dumps++;
|
||||
if (add < 255) matchLength += add;
|
||||
else {
|
||||
matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
|
||||
if (matchLength&1) matchLength>>=1, dumps += 3;
|
||||
else matchLength = (U16)(matchLength)>>1, dumps += 2;
|
||||
}
|
||||
if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
|
||||
}
|
||||
matchLength += mls;
|
||||
seq->matchLength = matchLength;
|
||||
}
|
||||
seq->litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBits(&(seqState->DStream), llBits) : 0); /* <= 16 bits */
|
||||
if (MEM_32bits() ||
|
||||
(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&(seqState->DStream));
|
||||
|
||||
/* save result */
|
||||
seq->litLength = litLength;
|
||||
seq->offset = offset;
|
||||
seqState->dumps = dumps;
|
||||
|
||||
#if 0 /* debug */
|
||||
{
|
||||
static U64 totalDecoded = 0;
|
||||
printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
|
||||
(U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
|
||||
totalDecoded += litLength + matchLength;
|
||||
}
|
||||
#endif
|
||||
/* ANS state update */
|
||||
FSE_updateState(&(seqState->stateLL), &(seqState->DStream)); /* <= 9 bits */
|
||||
FSE_updateState(&(seqState->stateML), &(seqState->DStream)); /* <= 9 bits */
|
||||
if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream)); /* <= 18 bits */
|
||||
FSE_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <= 8 bits */
|
||||
}
|
||||
|
||||
|
||||
@@ -776,38 +735,34 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE** litPtr, const BYTE* const litLimit_8,
|
||||
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||
{
|
||||
static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
const size_t sequenceLength = sequence.litLength + sequence.matchLength;
|
||||
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
||||
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||
BYTE* const oend_8 = oend-8;
|
||||
const BYTE* const litEnd = *litPtr + sequence.litLength;
|
||||
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit_8) return ERROR(corruption_detected); /* risk read beyond lit buffer */
|
||||
if (iLitEnd > litLimit_8) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
*litPtr = iLitEnd; /* update for next sequence */
|
||||
|
||||
/* copy Match */
|
||||
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||
/* offset beyond prefix */
|
||||
if (sequence.offset > (size_t)(oLitEnd - vBase))
|
||||
return ERROR(corruption_detected);
|
||||
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
||||
match = dictEnd - (base-match);
|
||||
if (match + sequence.matchLength <= dictEnd) {
|
||||
memmove(oLitEnd, match, sequence.matchLength);
|
||||
return sequenceLength;
|
||||
}
|
||||
/* span extDict & currentPrefixSegment */
|
||||
{
|
||||
size_t length1 = dictEnd - match;
|
||||
{ size_t const length1 = dictEnd - match;
|
||||
memmove(oLitEnd, match, length1);
|
||||
op = oLitEnd + length1;
|
||||
sequence.matchLength -= length1;
|
||||
@@ -817,7 +772,9 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
|
||||
/* match within prefix */
|
||||
if (sequence.offset < 8) {
|
||||
/* close range match, overlap */
|
||||
const int sub2 = dec64table[sequence.offset];
|
||||
static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
|
||||
static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
|
||||
int const sub2 = dec64table[sequence.offset];
|
||||
op[0] = match[0];
|
||||
op[1] = match[1];
|
||||
op[2] = match[2];
|
||||
@@ -836,8 +793,7 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
|
||||
match += oend_8 - op;
|
||||
op = oend_8;
|
||||
}
|
||||
while (op < oMatchEnd)
|
||||
*op++ = *match++;
|
||||
while (op < oMatchEnd) *op++ = *match++;
|
||||
} else {
|
||||
ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
|
||||
}
|
||||
@@ -855,12 +811,9 @@ static size_t ZSTD_decompressSequences(
|
||||
BYTE* const ostart = (BYTE* const)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + maxDstSize;
|
||||
size_t errorCode, dumpsLength;
|
||||
const BYTE* litPtr = dctx->litPtr;
|
||||
const BYTE* const litLimit_8 = litPtr + dctx->litBufSize - 8;
|
||||
const BYTE* const litEnd = litPtr + dctx->litSize;
|
||||
int nbSeq;
|
||||
const BYTE* dumps;
|
||||
U32* DTableLL = dctx->LLTable;
|
||||
U32* DTableML = dctx->MLTable;
|
||||
U32* DTableOffb = dctx->OffTable;
|
||||
@@ -868,13 +821,15 @@ static size_t ZSTD_decompressSequences(
|
||||
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
||||
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
||||
const U32 mls = dctx->fParams.mml;
|
||||
int nbSeq;
|
||||
|
||||
/* Build Decoding Tables */
|
||||
errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
|
||||
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(&nbSeq,
|
||||
DTableLL, DTableML, DTableOffb,
|
||||
ip, seqSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
ip += errorCode;
|
||||
if (ZSTD_isError(seqHSize)) return seqHSize;
|
||||
ip += seqHSize;
|
||||
}
|
||||
|
||||
/* Regen sequences */
|
||||
if (nbSeq) {
|
||||
@@ -883,12 +838,10 @@ static size_t ZSTD_decompressSequences(
|
||||
|
||||
memset(&sequence, 0, sizeof(sequence));
|
||||
sequence.offset = REPCODE_STARTVALUE;
|
||||
seqState.dumps = dumps;
|
||||
seqState.dumpsEnd = dumps + dumpsLength;
|
||||
for (int i=0; i<ZSTD_REP_INIT; i++)
|
||||
seqState.prevOffset[i] = REPCODE_STARTVALUE;
|
||||
errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
|
||||
if (ERR_isError(errorCode)) return ERROR(corruption_detected);
|
||||
{ size_t const errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
|
||||
if (ERR_isError(errorCode)) return ERROR(corruption_detected); }
|
||||
FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
|
||||
FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
|
||||
FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
|
||||
@@ -897,9 +850,15 @@ static size_t ZSTD_decompressSequences(
|
||||
size_t oneSeqSize;
|
||||
nbSeq--;
|
||||
ZSTD_decodeSequence(&sequence, &seqState, mls);
|
||||
#if 0 /* for debug */
|
||||
{ U32 pos = (U32)(op-base);
|
||||
if ((pos > 200802300) && (pos < 200802400))
|
||||
printf("Dpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
||||
pos, (U32)sequence.litLength, (U32)sequence.matchLength, (U32)sequence.offset);
|
||||
}
|
||||
#endif
|
||||
oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
|
||||
if (ZSTD_isError(oneSeqSize))
|
||||
return oneSeqSize;
|
||||
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
||||
op += oneSeqSize;
|
||||
}
|
||||
|
||||
@@ -908,8 +867,7 @@ static size_t ZSTD_decompressSequences(
|
||||
}
|
||||
|
||||
/* last literal segment */
|
||||
{
|
||||
size_t lastLLSize = litEnd - litPtr;
|
||||
{ size_t const lastLLSize = litEnd - litPtr;
|
||||
if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
|
||||
if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
|
||||
memcpy(op, litPtr, lastLLSize);
|
||||
@@ -936,17 +894,16 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
const void* src, size_t srcSize)
|
||||
{ /* blockType == blockCompressed */
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
size_t litCSize;
|
||||
|
||||
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
||||
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->fParams.mml);
|
||||
|
||||
/* Decode literals sub-block */
|
||||
litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||
if (ZSTD_isError(litCSize)) return litCSize;
|
||||
ip += litCSize;
|
||||
srcSize -= litCSize;
|
||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||
if (ZSTD_isError(litCSize)) return litCSize;
|
||||
ip += litCSize;
|
||||
srcSize -= litCSize; }
|
||||
|
||||
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
|
||||
}
|
||||
@@ -964,41 +921,38 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
|
||||
/*! ZSTD_decompress_continueDCtx() :
|
||||
* `dctx` must have been properly initialized */
|
||||
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t maxDstSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
const BYTE* iend = ip + srcSize;
|
||||
BYTE* const ostart = (BYTE* const)dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + maxDstSize;
|
||||
BYTE* const oend = ostart + dstCapacity;
|
||||
size_t remainingSize = srcSize;
|
||||
blockProperties_t blockProperties;
|
||||
|
||||
/* Frame Header */
|
||||
{
|
||||
size_t frameHeaderSize, errorCode;
|
||||
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
/* check */
|
||||
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
|
||||
{
|
||||
const U32 magicNumber = MEM_readLE32(src);
|
||||
if (ZSTD_isLegacy(magicNumber))
|
||||
return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
|
||||
}
|
||||
{ const U32 magicNumber = MEM_readLE32(src);
|
||||
if (ZSTD_isLegacy(magicNumber))
|
||||
return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, magicNumber);
|
||||
}
|
||||
#endif
|
||||
frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
|
||||
|
||||
/* Frame Header */
|
||||
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
|
||||
if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
|
||||
if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
|
||||
errorCode = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
if (ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);
|
||||
ip += frameHeaderSize; remainingSize -= frameHeaderSize;
|
||||
}
|
||||
|
||||
/* Loop on each block */
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
size_t decodedSize=0;
|
||||
size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
|
||||
size_t const cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
|
||||
ip += ZSTD_blockHeaderSize;
|
||||
@@ -1036,45 +990,45 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
|
||||
|
||||
size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
|
||||
void* dst, size_t maxDstSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_copyDCtx(dctx, refDCtx);
|
||||
ZSTD_checkContinuity(dctx, dst);
|
||||
return ZSTD_decompressFrame(dctx, dst, maxDstSize, src, srcSize);
|
||||
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t maxDstSize,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict, size_t dictSize)
|
||||
{
|
||||
ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
|
||||
ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->fParams.mml);
|
||||
ZSTD_checkContinuity(dctx, dst);
|
||||
return ZSTD_decompressFrame(dctx, dst, maxDstSize, src, srcSize);
|
||||
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);
|
||||
return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
|
||||
size_t regenSize;
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
if (dctx==NULL) return ERROR(memory_allocation);
|
||||
regenSize = ZSTD_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);
|
||||
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
|
||||
ZSTD_freeDCtx(dctx);
|
||||
return regenSize;
|
||||
#else
|
||||
ZSTD_DCtx dctx;
|
||||
return ZSTD_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);
|
||||
return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1098,7 +1052,6 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
|
||||
{
|
||||
case ZSTDds_getFrameHeaderSize :
|
||||
{
|
||||
/* get frame header size */
|
||||
if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
|
||||
dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
|
||||
if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
|
||||
@@ -1112,7 +1065,6 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
|
||||
}
|
||||
case ZSTDds_decodeFrameHeader:
|
||||
{
|
||||
/* get frame header */
|
||||
size_t result;
|
||||
memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
|
||||
result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
|
||||
@@ -1123,16 +1075,14 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co
|
||||
}
|
||||
case ZSTDds_decodeBlockHeader:
|
||||
{
|
||||
/* Decode block header */
|
||||
blockProperties_t bp;
|
||||
size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
|
||||
if (ZSTD_isError(blockSize)) return blockSize;
|
||||
size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
|
||||
if (ZSTD_isError(cBlockSize)) return cBlockSize;
|
||||
if (bp.blockType == bt_end) {
|
||||
dctx->expected = 0;
|
||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||
}
|
||||
else {
|
||||
dctx->expected = blockSize;
|
||||
} else {
|
||||
dctx->expected = cBlockSize;
|
||||
dctx->bType = bp.blockType;
|
||||
dctx->stage = ZSTDds_decompressBlock;
|
||||
}
|
||||
@@ -1219,7 +1169,7 @@ static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSiz
|
||||
static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
size_t eSize;
|
||||
U32 magic = MEM_readLE32(dict);
|
||||
U32 const magic = MEM_readLE32(dict);
|
||||
if (magic != ZSTD_DICT_MAGIC) {
|
||||
/* pure content mode */
|
||||
ZSTD_refDictContent(dctx, dict, dictSize);
|
||||
@@ -1242,12 +1192,11 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
||||
|
||||
size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
size_t errorCode;
|
||||
errorCode = ZSTD_decompressBegin(dctx);
|
||||
if (ZSTD_isError(errorCode)) return errorCode;
|
||||
{ size_t const errorCode = ZSTD_decompressBegin(dctx);
|
||||
if (ZSTD_isError(errorCode)) return errorCode; }
|
||||
|
||||
if (dict && dictSize) {
|
||||
errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
|
||||
size_t const errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
|
||||
if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
|
||||
}
|
||||
|
||||
|
||||
+61
-41
@@ -50,7 +50,7 @@
|
||||
/*-*************************************
|
||||
* Common constants
|
||||
***************************************/
|
||||
#define ZSTD_OPT_DEBUG 0 // 1 = tableID=0; 3 = price func tests; 5 = check encoded sequences; 9 = full logs
|
||||
#define ZSTD_OPT_DEBUG 0 // 3 = compression stats; 5 = check encoded sequences; 9 = full logs
|
||||
#include <stdio.h>
|
||||
#if defined(ZSTD_OPT_DEBUG) && ZSTD_OPT_DEBUG>=9
|
||||
#define ZSTD_LOG_PARSER(...) printf(__VA_ARGS__)
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
#define ZSTD_OPT_NUM (1<<12)
|
||||
#define ZSTD_DICT_MAGIC 0xEC30A435
|
||||
#if 1
|
||||
#if 0
|
||||
#define ZSTD_REP_NUM 4
|
||||
#define ZSTD_REP_INIT 4
|
||||
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
|
||||
@@ -78,9 +78,6 @@
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define ZSTD_BLOCKHEADERSIZE 3 /* because C standard does not allow a static const value to be defined using another static const value .... :( */
|
||||
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
|
||||
|
||||
#define BIT7 128
|
||||
#define BIT6 64
|
||||
#define BIT5 32
|
||||
@@ -88,55 +85,72 @@ static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
|
||||
#define BIT1 2
|
||||
#define BIT0 1
|
||||
|
||||
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 12
|
||||
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
|
||||
|
||||
#define ZSTD_BLOCKHEADERSIZE 3 /* because C standard does not allow a static const value to be defined using another static const value .... :( */
|
||||
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
|
||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||
|
||||
#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
|
||||
#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
|
||||
|
||||
#define HufLog 12
|
||||
|
||||
#define IS_HUF 0
|
||||
#define IS_PCH 1
|
||||
#define IS_RAW 2
|
||||
#define IS_RLE 3
|
||||
|
||||
#define LONGNBSEQ 0x7F00
|
||||
|
||||
#define MINMATCH 4
|
||||
#define REPCODE_STARTVALUE 1
|
||||
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 12
|
||||
|
||||
#define Litbits 8
|
||||
#define MLbits 7
|
||||
#define LLbits 6
|
||||
#define Offbits 5
|
||||
#define MaxLit ((1<<Litbits) - 1)
|
||||
#define MaxML ((1<<MLbits) - 1)
|
||||
#define MaxLL ((1<<LLbits) - 1)
|
||||
#define MaxML 52
|
||||
#define MaxLL 35
|
||||
#define MaxOff ((1<<Offbits)- 1)
|
||||
#define MLFSELog 10
|
||||
#define LLFSELog 10
|
||||
#define OffFSELog 9
|
||||
#define MaxSeq MAX(MaxLL, MaxML)
|
||||
|
||||
#define LONGNBSEQ 0x7F00
|
||||
#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
|
||||
#define MLFSELog 9
|
||||
#define LLFSELog 9
|
||||
#define OffFSELog 8
|
||||
|
||||
#define FSE_ENCODING_RAW 0
|
||||
#define FSE_ENCODING_RLE 1
|
||||
#define FSE_ENCODING_STATIC 2
|
||||
#define FSE_ENCODING_DYNAMIC 3
|
||||
|
||||
#define HufLog 12
|
||||
#define HASHLOG3 17
|
||||
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,
|
||||
13,14,15,16 };
|
||||
static const S16 LL_defaultNorm[MaxLL+1] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
|
||||
1, 1, 1, 1 };
|
||||
static const U32 LL_defaultNormLog = 6;
|
||||
|
||||
#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
|
||||
#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
|
||||
|
||||
#define WILDCOPY_OVERLENGTH 8
|
||||
|
||||
typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;
|
||||
static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,
|
||||
12,13,14,15,16 };
|
||||
static const S16 ML_defaultNorm[MaxML+1] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, };
|
||||
static const U32 ML_defaultNormLog = 6;
|
||||
|
||||
|
||||
/*-*******************************************
|
||||
* Shared functions to include for inlining
|
||||
*********************************************/
|
||||
static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }
|
||||
|
||||
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
|
||||
|
||||
/*! ZSTD_wildcopy() :
|
||||
* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
|
||||
#define WILDCOPY_OVERLENGTH 8
|
||||
MEM_STATIC void ZSTD_wildcopy(void* dst, const void* src, size_t length)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
@@ -186,20 +200,30 @@ typedef struct {
|
||||
U32 rep[ZSTD_REP_INIT];
|
||||
} ZSTD_optimal_t;
|
||||
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
#include "zstd_stats.h"
|
||||
#else
|
||||
typedef struct { U32 unused; } ZSTD_stats_t;
|
||||
MEM_STATIC void ZSTD_statsPrint(ZSTD_stats_t* stats, U32 searchLength) { (void)stats; (void)searchLength; };
|
||||
MEM_STATIC void ZSTD_statsInit(ZSTD_stats_t* stats) { (void)stats; };
|
||||
MEM_STATIC void ZSTD_statsResetFreqs(ZSTD_stats_t* stats) { (void)stats; };
|
||||
MEM_STATIC void ZSTD_statsUpdatePrices(ZSTD_stats_t* stats, size_t litLength, const BYTE* literals, size_t offset, size_t matchLength) { (void)stats; (void)litLength; (void)literals; (void)offset; (void)matchLength; };
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void* buffer;
|
||||
U32* offsetStart;
|
||||
U32* offset;
|
||||
BYTE* offCodeStart;
|
||||
BYTE* offCode;
|
||||
BYTE* litStart;
|
||||
BYTE* lit;
|
||||
BYTE* litLengthStart;
|
||||
BYTE* litLength;
|
||||
BYTE* matchLengthStart;
|
||||
BYTE* matchLength;
|
||||
BYTE* dumpsStart;
|
||||
BYTE* dumps;
|
||||
U16* litLengthStart;
|
||||
U16* litLength;
|
||||
BYTE* llCodeStart;
|
||||
U16* matchLengthStart;
|
||||
U16* matchLength;
|
||||
BYTE* mlCodeStart;
|
||||
U32 longLength;
|
||||
/* opt */
|
||||
ZSTD_optimal_t* priceTable;
|
||||
ZSTD_match_t* matchTable;
|
||||
@@ -218,17 +242,13 @@ typedef struct {
|
||||
U32 log2litSum;
|
||||
U32 log2offCodeSum;
|
||||
U32 factor;
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
U32 realMatchSum;
|
||||
U32 realLitSum;
|
||||
U32 realSeqSum;
|
||||
U32 realRepSum;
|
||||
U32 priceFunc;
|
||||
#endif
|
||||
ZSTD_stats_t stats;
|
||||
} seqStore_t;
|
||||
|
||||
seqStore_t ZSTD_copySeqStore(const ZSTD_CCtx* ctx);
|
||||
|
||||
extern int kSlotNew;
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);
|
||||
size_t ZSTD_compressBegin_targetSrcSize(ZSTD_CCtx* zc, const void* dict, size_t dictSize, size_t targetSrcSize, int compressionLevel);
|
||||
|
||||
|
||||
#endif /* ZSTD_CCOMMON_H_MODULE */
|
||||
|
||||
+444
-48
@@ -31,7 +31,7 @@
|
||||
- Zstd source repository : https://www.zstd.net
|
||||
*/
|
||||
|
||||
/* Note : this file is intended to be included within zstd_compress.c */
|
||||
/* Note : this file is intended to be included within zstd_compress.c */
|
||||
|
||||
|
||||
#define ZSTD_FREQ_DIV 5
|
||||
@@ -55,8 +55,8 @@ MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr)
|
||||
|
||||
if (ssPtr->litLengthSum == 0) {
|
||||
ssPtr->litSum = (2<<Litbits);
|
||||
ssPtr->litLengthSum = (1<<LLbits);
|
||||
ssPtr->matchLengthSum = (1<<MLbits);
|
||||
ssPtr->litLengthSum = MaxLL+1;
|
||||
ssPtr->matchLengthSum = MaxML+1;
|
||||
ssPtr->offCodeSum = (1<<Offbits);
|
||||
ssPtr->matchSum = (2<<Litbits);
|
||||
|
||||
@@ -93,7 +93,7 @@ MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr)
|
||||
ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZSTD_setLog2Prices(ssPtr);
|
||||
}
|
||||
|
||||
@@ -111,9 +111,18 @@ FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* seqStorePtr, U32 litLength, co
|
||||
price -= ZSTD_highbit(seqStorePtr->litFreq[literals[u]]+1);
|
||||
|
||||
/* literal Length */
|
||||
price += ((litLength >= MaxLL)<<3) + ((litLength >= 255+MaxLL)<<4) + ((litLength>=(1<<15))<<3);
|
||||
if (litLength >= MaxLL) litLength = MaxLL;
|
||||
price += seqStorePtr->log2litLengthSum - ZSTD_highbit(seqStorePtr->litLengthFreq[litLength]+1);
|
||||
{ static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 16, 17, 17, 18, 18, 19, 19,
|
||||
20, 20, 20, 20, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24 };
|
||||
const BYTE LL_deltaCode = 19;
|
||||
const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit(litLength) + LL_deltaCode : LL_Code[litLength];
|
||||
price += LL_bits[llCode] + seqStorePtr->log2litLengthSum - ZSTD_highbit(seqStorePtr->litLengthFreq[llCode]+1);
|
||||
}
|
||||
|
||||
return price;
|
||||
}
|
||||
@@ -122,25 +131,24 @@ FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t* seqStorePtr, U32 litLength, co
|
||||
FORCE_INLINE U32 ZSTD_getPrice(seqStore_t* seqStorePtr, U32 litLength, const BYTE* literals, U32 offset, U32 matchLength)
|
||||
{
|
||||
/* offset */
|
||||
BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset+1) + 1 : 0;
|
||||
U32 price = (offCode-1) + (!offCode) + seqStorePtr->log2offCodeSum - ZSTD_highbit(seqStorePtr->offCodeFreq[offCode]+1);
|
||||
BYTE offCode = (BYTE)ZSTD_highbit(offset+1);
|
||||
U32 price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit(seqStorePtr->offCodeFreq[offCode]+1);
|
||||
|
||||
/* match Length */
|
||||
price += ((matchLength >= MaxML)<<3) + ((matchLength >= 255+MaxML)<<4) + ((matchLength>=(1<<15))<<3);
|
||||
if (matchLength >= MaxML) matchLength = MaxML;
|
||||
price += ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->log2matchLengthSum - ZSTD_highbit(seqStorePtr->matchLengthFreq[matchLength]+1);
|
||||
|
||||
#if ZSTD_OPT_DEBUG == 3
|
||||
switch (seqStorePtr->priceFunc) {
|
||||
default:
|
||||
case 0:
|
||||
return 1 + price + ((seqStorePtr->litSum>>5) / seqStorePtr->litLengthSum) + ((seqStorePtr->litSum<<1) / (seqStorePtr->litSum + seqStorePtr->matchSum));
|
||||
case 1:
|
||||
return 1 + price;
|
||||
{ static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
|
||||
38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
||||
41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
|
||||
const BYTE ML_deltaCode = 36;
|
||||
const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit(matchLength) + ML_deltaCode : ML_Code[matchLength];
|
||||
price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit(seqStorePtr->matchLengthFreq[mlCode]+1);
|
||||
}
|
||||
#else
|
||||
return price + seqStorePtr->factor;
|
||||
#endif
|
||||
|
||||
return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,23 +162,39 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B
|
||||
seqStorePtr->litFreq[literals[u]]++;
|
||||
|
||||
/* literal Length */
|
||||
seqStorePtr->litLengthSum++;
|
||||
if (litLength >= MaxLL)
|
||||
seqStorePtr->litLengthFreq[MaxLL]++;
|
||||
else
|
||||
seqStorePtr->litLengthFreq[litLength]++;
|
||||
{ static const BYTE LL_Code[64] = { 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 16, 17, 17, 18, 18, 19, 19,
|
||||
20, 20, 20, 20, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24 };
|
||||
const BYTE LL_deltaCode = 19;
|
||||
const BYTE llCode = (litLength>63) ? (BYTE)ZSTD_highbit(litLength) + LL_deltaCode : LL_Code[litLength];
|
||||
seqStorePtr->litLengthFreq[llCode]++;
|
||||
seqStorePtr->litLengthSum++;
|
||||
}
|
||||
|
||||
/* match offset */
|
||||
seqStorePtr->offCodeSum++;
|
||||
BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset+1) + 1 : 0;
|
||||
BYTE offCode = (BYTE)ZSTD_highbit(offset+1);
|
||||
seqStorePtr->offCodeFreq[offCode]++;
|
||||
|
||||
/* match Length */
|
||||
seqStorePtr->matchLengthSum++;
|
||||
if (matchLength >= MaxML)
|
||||
seqStorePtr->matchLengthFreq[MaxML]++;
|
||||
else
|
||||
seqStorePtr->matchLengthFreq[matchLength]++;
|
||||
{ static const BYTE ML_Code[128] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,
|
||||
38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,
|
||||
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
|
||||
41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
|
||||
42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
|
||||
const BYTE ML_deltaCode = 36;
|
||||
const BYTE mlCode = (matchLength>127) ? (BYTE)ZSTD_highbit(matchLength) + ML_deltaCode : ML_Code[matchLength];
|
||||
seqStorePtr->matchLengthFreq[mlCode]++;
|
||||
seqStorePtr->matchLengthSum++;
|
||||
}
|
||||
|
||||
ZSTD_setLog2Prices(seqStorePtr);
|
||||
}
|
||||
@@ -196,17 +220,18 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B
|
||||
static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_CCtx* zc, const BYTE* ip)
|
||||
{
|
||||
U32* const hashTable3 = zc->hashTable3;
|
||||
U32 const hashLog3 = zc->hashLog3;
|
||||
const BYTE* const base = zc->base;
|
||||
const U32 target = (U32)(ip - base);
|
||||
U32 idx = zc->nextToUpdate3;
|
||||
|
||||
while(idx < target) {
|
||||
hashTable3[ZSTD_hash3Ptr(base+idx, HASHLOG3)] = idx;
|
||||
hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;
|
||||
idx++;
|
||||
}
|
||||
|
||||
zc->nextToUpdate3 = target;
|
||||
return hashTable3[ZSTD_hash3Ptr(ip, HASHLOG3)];
|
||||
return hashTable3[ZSTD_hash3Ptr(ip, hashLog3)];
|
||||
}
|
||||
|
||||
|
||||
@@ -218,12 +243,12 @@ static U32 ZSTD_insertBtAndGetAllMatches (
|
||||
{
|
||||
const BYTE* const base = zc->base;
|
||||
const U32 current = (U32)(ip-base);
|
||||
const U32 hashLog = zc->params.hashLog;
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const hashTable = zc->hashTable;
|
||||
U32 matchIndex = hashTable[h];
|
||||
U32* const bt = zc->contentTable;
|
||||
const U32 btLog = zc->params.contentLog - 1;
|
||||
U32* const bt = zc->chainTable;
|
||||
const U32 btLog = zc->params.cParams.chainLog - 1;
|
||||
const U32 btMask= (1U << btLog) - 1;
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
const BYTE* const dictBase = zc->dictBase;
|
||||
@@ -243,7 +268,7 @@ static U32 ZSTD_insertBtAndGetAllMatches (
|
||||
|
||||
if (minMatch == 3) { /* HC3 match finder */
|
||||
U32 matchIndex3 = ZSTD_insertAndFindFirstIndexHash3 (zc, ip);
|
||||
|
||||
|
||||
if (matchIndex3>windowLow && (current - matchIndex3 < (1<<18))) {
|
||||
const BYTE* match;
|
||||
size_t currentMl=0;
|
||||
@@ -408,11 +433,11 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
const BYTE* const base = ctx->base;
|
||||
const BYTE* const prefixStart = base + ctx->dictLimit;
|
||||
|
||||
const U32 maxSearches = 1U << ctx->params.searchLog;
|
||||
const U32 sufficient_len = ctx->params.targetLength;
|
||||
const U32 mls = ctx->params.searchLength;
|
||||
const U32 minMatch = (ctx->params.searchLength == 3) ? 3 : 4;
|
||||
|
||||
const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->params.cParams.targetLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
|
||||
|
||||
ZSTD_optimal_t* opt = seqStorePtr->priceTable;
|
||||
ZSTD_match_t* matches = seqStorePtr->matchTable;
|
||||
@@ -713,7 +738,378 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize,
|
||||
const U32 depth)
|
||||
{
|
||||
(void)ctx; (void)src; (void)srcSize; (void)depth;
|
||||
(void)ZSTD_BtGetAllMatches_selectMLS_extDict;
|
||||
printf("ZSTD_compressBlock_opt_extDict_generic\n"), exit(0);
|
||||
printf("NOT IMPLEMENTED: ZSTD_compressBlock_opt_extDict_generic\n"), exit(0);
|
||||
(void)ctx; (void)src; (void)srcSize; (void)depth; (void)ZSTD_BtGetAllMatches_selectMLS_extDict;
|
||||
#if 0
|
||||
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const BYTE* ip = istart;
|
||||
const BYTE* anchor = istart;
|
||||
const BYTE* litstart;
|
||||
const BYTE* const iend = istart + srcSize;
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
const BYTE* const base = ctx->base;
|
||||
const U32 dictLimit = ctx->dictLimit;
|
||||
const BYTE* const prefixStart = base + dictLimit;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const U32 lowLimit = ctx->lowLimit;
|
||||
|
||||
const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->params.cParams.targetLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
|
||||
|
||||
ZSTD_optimal_t* opt = seqStorePtr->priceTable;
|
||||
ZSTD_match_t* matches = seqStorePtr->matchTable;
|
||||
const BYTE* inr;
|
||||
U32 cur, match_num, last_pos, litlen, price;
|
||||
|
||||
/* init */
|
||||
U32 rep[ZSTD_REP_INIT];
|
||||
for (int i=0; i<ZSTD_REP_INIT; i++)
|
||||
rep[i]=REPCODE_STARTVALUE;
|
||||
|
||||
ctx->nextToUpdate3 = ctx->nextToUpdate;
|
||||
ZSTD_resetSeqStore(seqStorePtr);
|
||||
ZSTD_rescaleFreqs(seqStorePtr);
|
||||
if ((ip - prefixStart) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE;
|
||||
|
||||
ZSTD_LOG_BLOCK("%d: COMPBLOCK_OPT_EXTDICT srcSz=%d maxSrch=%d mls=%d sufLen=%d\n", (int)(ip-base), (int)srcSize, maxSearches, mls, sufficient_len);
|
||||
|
||||
/* Match Loop */
|
||||
while (ip < ilimit) {
|
||||
U32 u, offset, best_off=0;
|
||||
U32 mlen=0, best_mlen=0;
|
||||
U32 current = (U32)(ip-base);
|
||||
memset(opt, 0, sizeof(ZSTD_optimal_t));
|
||||
last_pos = 0;
|
||||
inr = ip;
|
||||
litstart = ((U32)(ip - anchor) > 128) ? ip - 128 : anchor;
|
||||
opt[0].litlen = (U32)(ip - litstart);
|
||||
|
||||
/* check repCode */
|
||||
{
|
||||
const U32 repIndex = (U32)(current+1 - rep_1);
|
||||
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
||||
const BYTE* const repMatch = repBase + repIndex;
|
||||
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
|
||||
&& (MEM_readMINMATCH(ip+1, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
|
||||
/* repcode detected we should take it */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlen = (U32)ZSTD_count_2segments(ip+1+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
|
||||
|
||||
ZSTD_LOG_PARSER("%d: start try REP rep=%d mlen=%d\n", (int)(ip-base), (int)rep_1, (int)mlen);
|
||||
if (depth==0 || mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
|
||||
ip+=1; best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;
|
||||
goto _storeSequence;
|
||||
}
|
||||
|
||||
litlen = opt[0].litlen + 1;
|
||||
do {
|
||||
price = ZSTD_getPrice(seqStorePtr, litlen, litstart, 0, mlen - minMatch);
|
||||
if (mlen + 1 > last_pos || price < opt[mlen + 1].price)
|
||||
SET_PRICE(mlen + 1, mlen, 0, litlen, price);
|
||||
mlen--;
|
||||
} while (mlen >= minMatch);
|
||||
} }
|
||||
|
||||
best_mlen = (last_pos) ? last_pos : minMatch;
|
||||
|
||||
match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches); /* first search (depth 0) */
|
||||
|
||||
ZSTD_LOG_PARSER("%d: match_num=%d last_pos=%d\n", (int)(ip-base), match_num, last_pos);
|
||||
if (!last_pos && !match_num) { ip++; continue; }
|
||||
|
||||
opt[0].rep = rep_1;
|
||||
opt[0].rep2 = rep_2;
|
||||
opt[0].mlen = 1;
|
||||
|
||||
if (match_num && matches[match_num-1].len > sufficient_len) {
|
||||
best_mlen = matches[match_num-1].len;
|
||||
best_off = matches[match_num-1].off;
|
||||
cur = 0;
|
||||
last_pos = 1;
|
||||
goto _storeSequence;
|
||||
}
|
||||
|
||||
// set prices using matches at position = 0
|
||||
for (u = 0; u < match_num; u++) {
|
||||
mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
|
||||
best_mlen = (matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM;
|
||||
ZSTD_LOG_PARSER("%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(ip-base), matches[u].len, matches[u].off, (int)best_mlen, (int)last_pos);
|
||||
litlen = opt[0].litlen;
|
||||
while (mlen <= best_mlen) {
|
||||
price = ZSTD_getPrice(seqStorePtr, litlen, litstart, matches[u].off, mlen - minMatch);
|
||||
if (mlen > last_pos || price < opt[mlen].price)
|
||||
SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
|
||||
mlen++;
|
||||
} }
|
||||
|
||||
if (last_pos < minMatch) {
|
||||
// ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */
|
||||
ip++; continue;
|
||||
}
|
||||
|
||||
/* check further positions */
|
||||
for (cur = 1; cur <= last_pos; cur++) {
|
||||
size_t cur_rep;
|
||||
inr = ip + cur;
|
||||
|
||||
if (opt[cur-1].mlen == 1) {
|
||||
litlen = opt[cur-1].litlen + 1;
|
||||
if (cur > litlen) {
|
||||
price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-litlen);
|
||||
} else
|
||||
price = ZSTD_getLiteralPrice(seqStorePtr, litlen, litstart);
|
||||
} else {
|
||||
litlen = 1;
|
||||
price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr-1);
|
||||
}
|
||||
|
||||
if (cur > last_pos || price <= opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))
|
||||
SET_PRICE(cur, 1, 0, litlen, price);
|
||||
|
||||
if (cur == last_pos) break;
|
||||
|
||||
if (inr > ilimit) // last match must start at a minimum distance of 8 from oend
|
||||
continue;
|
||||
|
||||
mlen = opt[cur].mlen;
|
||||
|
||||
if (opt[cur].off) {
|
||||
opt[cur].rep2 = opt[cur-mlen].rep;
|
||||
opt[cur].rep = opt[cur].off;
|
||||
ZSTD_LOG_ENCODE("%d: COPYREP_OFF cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
|
||||
} else {
|
||||
if (cur!=mlen && opt[cur].litlen == 0) {
|
||||
opt[cur].rep2 = opt[cur-mlen].rep;
|
||||
opt[cur].rep = opt[cur-mlen].rep2;
|
||||
ZSTD_LOG_ENCODE("%d: COPYREP_SWI cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
|
||||
} else {
|
||||
opt[cur].rep2 = opt[cur-mlen].rep2;
|
||||
opt[cur].rep = opt[cur-mlen].rep;
|
||||
ZSTD_LOG_ENCODE("%d: COPYREP_NOR cur=%d mlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, mlen, opt[cur].rep, opt[cur].rep2);
|
||||
} }
|
||||
|
||||
ZSTD_LOG_PARSER("%d: CURRENT_Ext price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(inr-base), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
|
||||
|
||||
best_mlen = 0;
|
||||
|
||||
if (opt[cur].mlen != 1) {
|
||||
cur_rep = opt[cur].rep2;
|
||||
ZSTD_LOG_PARSER("%d: tryExt REP2 rep2=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
|
||||
} else {
|
||||
cur_rep = opt[cur].rep;
|
||||
ZSTD_LOG_PARSER("%d: tryExt REP1 rep=%u mlen=%u\n", (int)(inr-base), (U32)cur_rep, mlen);
|
||||
}
|
||||
|
||||
const U32 repIndex = (U32)(current+cur - cur_rep);
|
||||
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
||||
const BYTE* const repMatch = repBase + repIndex;
|
||||
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
|
||||
&& (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
|
||||
/* repcode detected */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
|
||||
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\n", (int)(inr-base), mlen, 0, opt[cur].rep, cur, opt[cur].off);
|
||||
|
||||
if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
|
||||
best_mlen = mlen;
|
||||
best_off = 0;
|
||||
ZSTD_LOG_PARSER("%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\n", (int)(inr-base), sufficient_len, best_mlen, best_off, last_pos);
|
||||
last_pos = cur + 1;
|
||||
goto _storeSequence;
|
||||
}
|
||||
|
||||
if (opt[cur].mlen == 1) {
|
||||
litlen = opt[cur].litlen;
|
||||
if (cur > litlen) {
|
||||
price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr-litlen, 0, mlen - minMatch);
|
||||
} else
|
||||
price = ZSTD_getPrice(seqStorePtr, litlen, litstart, 0, mlen - minMatch);
|
||||
} else {
|
||||
litlen = 0;
|
||||
price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, 0, mlen - minMatch);
|
||||
}
|
||||
|
||||
best_mlen = mlen;
|
||||
|
||||
ZSTD_LOG_PARSER("%d: Found REP mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, 0, price, litlen);
|
||||
|
||||
do {
|
||||
if (cur + mlen > last_pos || price <= opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH
|
||||
SET_PRICE(cur + mlen, mlen, 0, litlen, price);
|
||||
mlen--;
|
||||
} while (mlen >= minMatch);
|
||||
}
|
||||
|
||||
best_mlen = (best_mlen > minMatch) ? best_mlen : minMatch;
|
||||
|
||||
match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches);
|
||||
ZSTD_LOG_PARSER("%d: ZSTD_GetAllMatches match_num=%d\n", (int)(inr-base), match_num);
|
||||
|
||||
if (match_num > 0 && matches[match_num-1].len > sufficient_len) {
|
||||
best_mlen = matches[match_num-1].len;
|
||||
best_off = matches[match_num-1].off;
|
||||
last_pos = cur + 1;
|
||||
goto _storeSequence;
|
||||
}
|
||||
|
||||
// set prices using matches at position = cur
|
||||
for (u = 0; u < match_num; u++) {
|
||||
mlen = (u>0) ? matches[u-1].len+1 : best_mlen;
|
||||
best_mlen = (cur + matches[u].len < ZSTD_OPT_NUM) ? matches[u].len : ZSTD_OPT_NUM - cur;
|
||||
|
||||
// ZSTD_LOG_PARSER("%d: Found1 cur=%d mlen=%d off=%d best_mlen=%d last_pos=%d\n", (int)(inr-base), cur, matches[u].len, matches[u].off, best_mlen, last_pos);
|
||||
|
||||
while (mlen <= best_mlen) {
|
||||
if (opt[cur].mlen == 1) {
|
||||
litlen = opt[cur].litlen;
|
||||
if (cur > litlen)
|
||||
price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip+cur-litlen, matches[u].off, mlen - minMatch);
|
||||
else
|
||||
price = ZSTD_getPrice(seqStorePtr, litlen, litstart, matches[u].off, mlen - minMatch);
|
||||
} else {
|
||||
litlen = 0;
|
||||
price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off, mlen - minMatch);
|
||||
}
|
||||
|
||||
// ZSTD_LOG_PARSER("%d: Found2 mlen=%d best_mlen=%d off=%d price=%d litlen=%d\n", (int)(inr-base), mlen, best_mlen, matches[u].off, price, litlen);
|
||||
|
||||
if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
|
||||
SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
|
||||
|
||||
mlen++;
|
||||
} } } // for (cur = 1; cur <= last_pos; cur++)
|
||||
|
||||
best_mlen = opt[last_pos].mlen;
|
||||
best_off = opt[last_pos].off;
|
||||
cur = last_pos - best_mlen;
|
||||
|
||||
/* store sequence */
|
||||
_storeSequence: // cur, last_pos, best_mlen, best_off have to be set
|
||||
for (u = 1; u <= last_pos; u++)
|
||||
ZSTD_LOG_PARSER("%d: price[%u/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
|
||||
ZSTD_LOG_PARSER("%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\n", (int)(ip-base+cur), (int)cur, (int)last_pos, (int)best_mlen, (int)best_off, opt[cur].rep);
|
||||
|
||||
opt[0].mlen = 1;
|
||||
|
||||
while (1) {
|
||||
mlen = opt[cur].mlen;
|
||||
offset = opt[cur].off;
|
||||
opt[cur].mlen = best_mlen;
|
||||
opt[cur].off = best_off;
|
||||
best_mlen = mlen;
|
||||
best_off = offset;
|
||||
if (mlen > cur) break;
|
||||
cur -= mlen;
|
||||
}
|
||||
|
||||
for (u = 0; u <= last_pos; ) {
|
||||
ZSTD_LOG_PARSER("%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+u), u, last_pos, opt[u].price, opt[u].off, opt[u].mlen, opt[u].litlen, opt[u].rep, opt[u].rep2);
|
||||
u += opt[u].mlen;
|
||||
}
|
||||
|
||||
for (cur=0; cur < last_pos; ) {
|
||||
U32 litLength;
|
||||
ZSTD_LOG_PARSER("%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d rep2=%d\n", (int)(ip-base+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep, opt[cur].rep2);
|
||||
mlen = opt[cur].mlen;
|
||||
if (mlen == 1) { ip++; cur++; continue; }
|
||||
offset = opt[cur].off;
|
||||
cur += mlen;
|
||||
|
||||
litLength = (U32)(ip - anchor);
|
||||
ZSTD_LOG_ENCODE("%d/%d: ENCODE1 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
|
||||
|
||||
if (offset) {
|
||||
rep_2 = rep_1;
|
||||
rep_1 = offset;
|
||||
} else {
|
||||
if (litLength == 0) {
|
||||
best_off = rep_2;
|
||||
rep_2 = rep_1;
|
||||
rep_1 = best_off;
|
||||
} }
|
||||
|
||||
ZSTD_LOG_ENCODE("%d/%d: ENCODE2 literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(ip-base), (int)(iend-base), (int)(litLength), (int)mlen, (int)(offset), (int)rep_1, (int)rep_2);
|
||||
|
||||
#if ZSTD_OPT_DEBUG >= 5
|
||||
U32 ml2;
|
||||
if (offset) {
|
||||
if (offset > (size_t)(ip - prefixStart)) {
|
||||
const BYTE* match = dictEnd - (offset - (ip - prefixStart));
|
||||
ml2 = ZSTD_count_2segments(ip, match, iend, dictEnd, prefixStart);
|
||||
ZSTD_LOG_PARSER("%d: ZSTD_count_2segments=%d offset=%d dictBase=%p dictEnd=%p prefixStart=%p ip=%p match=%p\n", (int)current, (int)ml2, (int)offset, dictBase, dictEnd, prefixStart, ip, match);
|
||||
}
|
||||
else ml2 = (U32)ZSTD_count(ip, ip-offset, iend);
|
||||
}
|
||||
else ml2 = (U32)ZSTD_count(ip, ip-rep_1, iend);
|
||||
if ((offset >= 8) && (ml2 < mlen || ml2 < minMatch)) {
|
||||
printf("%d: ERROR_Ext iend=%d mlen=%d offset=%d ml2=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset, (int)ml2); exit(0); }
|
||||
if (ip < anchor) {
|
||||
printf("%d: ERROR_Ext ip < anchor iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
|
||||
if (ip + mlen > iend) {
|
||||
printf("%d: ERROR_Ext ip + mlen >= iend iend=%d mlen=%d offset=%d\n", (int)(ip - base), (int)(iend - ip), (int)mlen, (int)offset); exit(0); }
|
||||
#endif
|
||||
|
||||
ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen-minMatch);
|
||||
ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen-minMatch);
|
||||
anchor = ip = ip + mlen;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* check immediate repcode */
|
||||
while ((anchor >= base + lowLimit + rep_2) && (anchor <= ilimit)) {
|
||||
if ((anchor - rep_2) >= prefixStart) {
|
||||
if (MEM_readMINMATCH(anchor, minMatch) == MEM_readMINMATCH(anchor - rep_2, minMatch))
|
||||
mlen = (U32)ZSTD_count(anchor+minMatch, anchor - rep_2 + minMatch, iend) + minMatch;
|
||||
else
|
||||
break;
|
||||
} else {
|
||||
const BYTE* repMatch = dictBase + ((anchor-base) - rep_2);
|
||||
if ((repMatch + minMatch <= dictEnd) && (MEM_readMINMATCH(anchor, minMatch) == MEM_readMINMATCH(repMatch, minMatch)))
|
||||
mlen = (U32)ZSTD_count_2segments(anchor+minMatch, repMatch+minMatch, iend, dictEnd, prefixStart) + minMatch;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
offset = rep_2; rep_2 = rep_1; rep_1 = offset; /* swap offset history */
|
||||
ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
|
||||
ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, mlen-minMatch);
|
||||
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, mlen-minMatch);
|
||||
anchor += mlen;
|
||||
}
|
||||
#else
|
||||
/* check immediate repcode */
|
||||
/* minimal correctness condition = while ((anchor >= prefixStart + REPCODE_STARTVALUE) && (anchor <= ilimit)) { */
|
||||
while ((anchor >= base + lowLimit + rep_2) && (anchor <= ilimit)) {
|
||||
const U32 repIndex = (U32)((anchor-base) - rep_2);
|
||||
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
|
||||
const BYTE* const repMatch = repBase + repIndex;
|
||||
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
|
||||
&& (MEM_readMINMATCH(anchor, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
|
||||
/* repcode detected, let's take it */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlen = (U32)ZSTD_count_2segments(anchor+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
|
||||
offset = rep_2; rep_2 = rep_1; rep_1 = offset; /* swap offset history */
|
||||
ZSTD_LOG_ENCODE("%d/%d: ENCODE REP literals=%d mlen=%d off=%d rep1=%d rep2=%d\n", (int)(anchor-base), (int)(iend-base), (int)(0), (int)best_mlen, (int)(0), (int)rep_1, (int)rep_2);
|
||||
ZSTD_updatePrice(seqStorePtr, 0, anchor, 0, mlen-minMatch);
|
||||
ZSTD_storeSeq(seqStorePtr, 0, anchor, 0, mlen-minMatch);
|
||||
anchor += mlen;
|
||||
continue; /* faster when present ... (?) */
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (anchor > ip) ip = anchor;
|
||||
}
|
||||
|
||||
{ /* Last Literals */
|
||||
size_t lastLLSize = iend - anchor;
|
||||
ZSTD_LOG_ENCODE("%d: lastLLSize literals=%u\n", (int)(ip-base), (U32)(lastLLSize));
|
||||
memcpy(seqStorePtr->lit, anchor, lastLLSize);
|
||||
seqStorePtr->lit += lastLLSize;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+31
-17
@@ -57,13 +57,15 @@ extern "C" {
|
||||
/*-*************************************
|
||||
* Types
|
||||
***************************************/
|
||||
#define ZSTD_WINDOWLOG_MAX 27
|
||||
#define ZSTD_WINDOWLOG_MAX (MEM_32bits() ? 25 : 27)
|
||||
#define ZSTD_WINDOWLOG_MIN 18
|
||||
#define ZSTD_CONTENTLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
|
||||
#define ZSTD_CONTENTLOG_MIN 4
|
||||
#define ZSTD_HASHLOG_MAX 28
|
||||
#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
|
||||
#define ZSTD_CHAINLOG_MIN 4
|
||||
#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
|
||||
#define ZSTD_HASHLOG_MIN 12
|
||||
#define ZSTD_SEARCHLOG_MAX (ZSTD_CONTENTLOG_MAX-1)
|
||||
#define ZSTD_HASHLOG3_MAX 17
|
||||
#define ZSTD_HASHLOG3_MIN 15
|
||||
#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
|
||||
#define ZSTD_SEARCHLOG_MIN 1
|
||||
#define ZSTD_SEARCHLENGTH_MAX 7
|
||||
#define ZSTD_SEARCHLENGTH_MIN 3
|
||||
@@ -73,16 +75,23 @@ extern "C" {
|
||||
/* from faster to stronger */
|
||||
typedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2, ZSTD_btopt } ZSTD_strategy;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 srcSize; /* optional : tells how much bytes are present in the frame. Use 0 if not known. */
|
||||
typedef struct {
|
||||
U32 windowLog; /* largest match distance : larger == more compression, more memory needed during decompression */
|
||||
U32 contentLog; /* full search segment : larger == more compression, slower, more memory (useless for fast) */
|
||||
U32 chainLog; /* fully searched segment : larger == more compression, slower, more memory (useless for fast) */
|
||||
U32 hashLog; /* dispatch table : larger == faster, more memory */
|
||||
U32 searchLog; /* nb of searches : larger == more compression, slower */
|
||||
U32 searchLength; /* match length searched : larger == faster decompression, sometimes less compression */
|
||||
U32 targetLength; /* acceptable match size for optimal parser (only) : larger == more compression, slower */
|
||||
ZSTD_strategy strategy;
|
||||
} ZSTD_compressionParameters;
|
||||
|
||||
typedef struct {
|
||||
U32 contentSizeFlag; /* 1: content size will be in frame header (if known). */
|
||||
} ZSTD_frameParameters;
|
||||
|
||||
typedef struct {
|
||||
ZSTD_compressionParameters cParams;
|
||||
ZSTD_frameParameters fParams;
|
||||
} ZSTD_parameters;
|
||||
|
||||
|
||||
@@ -91,14 +100,19 @@ typedef struct
|
||||
***************************************/
|
||||
ZSTDLIB_API unsigned ZSTD_maxCLevel (void);
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* @return ZSTD_parameters structure for a selected compression level and srcSize.
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and srcSize.
|
||||
* `srcSize` value is optional, select 0 if not known */
|
||||
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, U64 srcSize);
|
||||
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, U64 srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_validateParams() :
|
||||
* correct params value to remain within authorized range */
|
||||
ZSTDLIB_API void ZSTD_validateParams(ZSTD_parameters* params);
|
||||
/*! ZSTD_checkParams() :
|
||||
* Ensure param values remain within authorized range */
|
||||
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
|
||||
/*! ZSTD_adjustParams() :
|
||||
* optimize params for a given `srcSize` and `dictSize`.
|
||||
* both values are optional, select `0` if unknown. */
|
||||
ZSTDLIB_API void ZSTD_adjustCParams(ZSTD_compressionParameters* params, U64 srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_compress_advanced() :
|
||||
* Same as ZSTD_compress_usingDict(), with fine-tune control of each compression parameter */
|
||||
@@ -136,7 +150,7 @@ ZSTDLIB_API size_t ZSTD_decompress_usingPreparedDCtx(
|
||||
****************************************/
|
||||
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);
|
||||
ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, U64 pledgedSrcSize);
|
||||
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx);
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
@@ -245,7 +259,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, cons
|
||||
***************************************/
|
||||
#include "error_public.h"
|
||||
/*! ZSTD_getErrorCode() :
|
||||
convert a `size_t` function result into a `ZSTD_error_code` enum type,
|
||||
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
||||
which can be used to compare directly with enum list published into "error_public.h" */
|
||||
ZSTD_ErrorCode ZSTD_getError(size_t code);
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
zstd - standard compression library
|
||||
Header File for static linking only
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net
|
||||
*/
|
||||
#ifndef ZSTD_STATS_H
|
||||
#define ZSTD_STATS_H
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-*************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
//#include "zstd.h"
|
||||
//#include "mem.h"
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
//#define ZSTD_MAGICNUMBER 0xFD2FB526 /* v0.6 */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Types
|
||||
***************************************/
|
||||
typedef struct {
|
||||
U32 priceOffset, priceOffCode, priceMatchLength, priceLiteral, priceLitLength, priceDumpsLength;
|
||||
U32 totalMatchSum, totalLitSum, totalSeqSum, totalRepSum;
|
||||
U32 litSum, matchLengthSum, litLengthSum, offCodeSum;
|
||||
U32 matchLengthFreq[1<<MLbits];
|
||||
U32 litLengthFreq[1<<LLbits];
|
||||
U32 litFreq[1<<Litbits];
|
||||
U32 offCodeFreq[1<<Offbits];
|
||||
} ZSTD_stats_t;
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Advanced functions
|
||||
***************************************/
|
||||
MEM_STATIC void ZSTD_statsPrint(ZSTD_stats_t* stats, U32 searchLength)
|
||||
{
|
||||
stats->totalMatchSum += stats->totalSeqSum * ((searchLength == 3) ? 3 : 4);
|
||||
printf("avgMatchL=%.2f avgLitL=%.2f match=%.1f%% lit=%.1f%% reps=%d seq=%d\n", (float)stats->totalMatchSum/stats->totalSeqSum, (float)stats->totalLitSum/stats->totalSeqSum, 100.0*stats->totalMatchSum/(stats->totalMatchSum+stats->totalLitSum), 100.0*stats->totalLitSum/(stats->totalMatchSum+stats->totalLitSum), stats->totalRepSum, stats->totalSeqSum);
|
||||
printf("SumBytes=%d Offset=%d OffCode=%d Match=%d Literal=%d LitLength=%d DumpsLength=%d\n", (stats->priceOffset+stats->priceOffCode+stats->priceMatchLength+stats->priceLiteral+stats->priceLitLength+stats->priceDumpsLength)/8, stats->priceOffset/8, stats->priceOffCode/8, stats->priceMatchLength/8, stats->priceLiteral/8, stats->priceLitLength/8, stats->priceDumpsLength/8);
|
||||
}
|
||||
|
||||
MEM_STATIC void ZSTD_statsInit(ZSTD_stats_t* stats)
|
||||
{
|
||||
stats->totalLitSum = stats->totalMatchSum = stats->totalSeqSum = stats->totalRepSum = 1;
|
||||
stats->priceOffset = stats->priceOffCode = stats->priceMatchLength = stats->priceLiteral = stats->priceLitLength = stats->priceDumpsLength = 0;
|
||||
}
|
||||
|
||||
MEM_STATIC void ZSTD_statsResetFreqs(ZSTD_stats_t* stats)
|
||||
{
|
||||
unsigned u;
|
||||
|
||||
stats->litSum = (1<<Litbits);
|
||||
stats->litLengthSum = (1<<LLbits);
|
||||
stats->matchLengthSum = (1<<MLbits);
|
||||
stats->offCodeSum = (1<<Offbits);
|
||||
|
||||
for (u=0; u<=MaxLit; u++)
|
||||
stats->litFreq[u] = 1;
|
||||
for (u=0; u<=MaxLL; u++)
|
||||
stats->litLengthFreq[u] = 1;
|
||||
for (u=0; u<=MaxML; u++)
|
||||
stats->matchLengthFreq[u] = 1;
|
||||
for (u=0; u<=MaxOff; u++)
|
||||
stats->offCodeFreq[u] = 1;
|
||||
}
|
||||
|
||||
MEM_STATIC void ZSTD_statsUpdatePrices(ZSTD_stats_t* stats, size_t litLength, const BYTE* literals, size_t offset, size_t matchLength)
|
||||
{
|
||||
/* offset */
|
||||
BYTE offCode = offset ? (BYTE)ZSTD_highbit(offset+1) + 1 : 0;
|
||||
stats->priceOffCode += ZSTD_highbit(stats->offCodeSum+1) - ZSTD_highbit(stats->offCodeFreq[offCode]+1);
|
||||
stats->priceOffset += (offCode-1) + (!offCode);
|
||||
|
||||
/* match Length */
|
||||
stats->priceDumpsLength += ((matchLength >= MaxML)<<3) + ((matchLength >= 255+MaxML)<<4) + ((matchLength>=(1<<15))<<3);
|
||||
stats->priceMatchLength += ZSTD_highbit(stats->matchLengthSum+1) - ZSTD_highbit(stats->matchLengthFreq[(matchLength >= MaxML) ? MaxML : matchLength]+1);
|
||||
|
||||
if (litLength) {
|
||||
/* literals */
|
||||
U32 u;
|
||||
stats->priceLiteral += litLength * ZSTD_highbit(stats->litSum+1);
|
||||
for (u=0; u < litLength; u++)
|
||||
stats->priceLiteral -= ZSTD_highbit(stats->litFreq[literals[u]]+1);
|
||||
|
||||
/* literal Length */
|
||||
stats->priceDumpsLength += ((litLength >= MaxLL)<<3) + ((litLength >= 255+MaxLL)<<4) + ((litLength>=(1<<15))<<3);
|
||||
stats->priceLitLength += ZSTD_highbit(stats->litLengthSum+1) - ZSTD_highbit(stats->litLengthFreq[(litLength >= MaxLL) ? MaxLL : litLength]+1);
|
||||
} else {
|
||||
stats->priceLitLength += ZSTD_highbit(stats->litLengthSum+1) - ZSTD_highbit(stats->litLengthFreq[0]+1);
|
||||
}
|
||||
|
||||
|
||||
if (offset == 0) stats->totalRepSum++;
|
||||
stats->totalSeqSum++;
|
||||
stats->totalMatchSum += matchLength;
|
||||
stats->totalLitSum += litLength;
|
||||
|
||||
U32 u;
|
||||
/* literals */
|
||||
stats->litSum += litLength;
|
||||
for (u=0; u < litLength; u++)
|
||||
stats->litFreq[literals[u]]++;
|
||||
|
||||
/* literal Length */
|
||||
stats->litLengthSum++;
|
||||
if (litLength >= MaxLL)
|
||||
stats->litLengthFreq[MaxLL]++;
|
||||
else
|
||||
stats->litLengthFreq[litLength]++;
|
||||
|
||||
/* match offset */
|
||||
stats->offCodeSum++;
|
||||
stats->offCodeFreq[offCode]++;
|
||||
|
||||
/* match Length */
|
||||
stats->matchLengthSum++;
|
||||
if (matchLength >= MaxML)
|
||||
stats->matchLengthFreq[MaxML]++;
|
||||
else
|
||||
stats->matchLengthFreq[matchLength]++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZSTD_STATIC_H */
|
||||
@@ -5,6 +5,8 @@ fullbench
|
||||
fullbench32
|
||||
fuzzer
|
||||
fuzzer32
|
||||
zbufftest
|
||||
zbufftest32
|
||||
datagen
|
||||
paramgrill
|
||||
|
||||
|
||||
+11
-11
@@ -215,19 +215,19 @@ test-zbuff: zbufftest
|
||||
test-zbuff32: zbufftest32
|
||||
./zbufftest32 $(ZBUFFTEST)
|
||||
|
||||
valgrindTest: VALGRIND = valgrind --leak-check=full --error-exitcode=1
|
||||
valgrindTest: zstd datagen fuzzer fullbench zbufftest
|
||||
@echo "\n ---- valgrind tests : memory analyzer ----"
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./datagen -g50M > $(VOID)
|
||||
./datagen -g16KB > tmp
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./zstd -vf tmp -o $(VOID)
|
||||
./datagen -g2930KB > tmp
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./zstd -5 -vf tmp -o tmp2
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./zstd -vdf tmp2 -o $(VOID)
|
||||
./datagen -g64MB > tmp
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./zstd -vf tmp -o $(VOID)
|
||||
$(VALGRIND) ./datagen -g50M > $(VOID)
|
||||
$(VALGRIND) ./zstd ; if [ $$? -eq 0 ] ; then echo "zstd without argument should have failed"; false; fi
|
||||
./datagen -g80 | $(VALGRIND) ./zstd - -c > $(VOID)
|
||||
./datagen -g16KB | $(VALGRIND) ./zstd -vf - -o $(VOID)
|
||||
./datagen -g2930KB | $(VALGRIND) ./zstd -5 -vf - -o tmp
|
||||
$(VALGRIND) ./zstd -vdf tmp -o $(VOID)
|
||||
./datagen -g64MB | $(VALGRIND) ./zstd -vf - -o $(VOID)
|
||||
@rm tmp
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./fuzzer -T1mn -t1
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./fullbench -i1
|
||||
valgrind --leak-check=yes --error-exitcode=1 ./zbufftest -T1mn
|
||||
$(VALGRIND) ./fuzzer -T1mn -t1
|
||||
$(VALGRIND) ./fullbench -i1
|
||||
$(VALGRIND) ./zbufftest -T1mn
|
||||
|
||||
endif
|
||||
|
||||
+177
-143
@@ -44,35 +44,58 @@
|
||||
/* *************************************
|
||||
* Includes
|
||||
***************************************/
|
||||
#define _POSIX_C_SOURCE 199309L /* before time.h */
|
||||
#define _POSIX_C_SOURCE 199309L /* before <time.h> - needed for nanosleep() */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* memset */
|
||||
#include <stdio.h> /* fprintf, fopen, ftello64 */
|
||||
#include <sys/types.h> /* stat64 */
|
||||
#include <sys/stat.h> /* stat64 */
|
||||
#include <time.h> /* clock_t, clock, nanosleep, CLOCKS_PER_SEC */
|
||||
#include <time.h> /* clock_t, nanosleep, clock, CLOCKS_PER_SEC */
|
||||
|
||||
/* sleep : posix - windows - others */
|
||||
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
|
||||
# include <unistd.h>
|
||||
# include <sys/resource.h> /* setpriority */
|
||||
# define BMK_sleep(s) sleep(s)
|
||||
# define mili_sleep(mili) { struct timespec t; t.tv_sec=0; t.tv_nsec=mili*1000000L; nanosleep(&t, NULL); }
|
||||
# define mili_sleep(mili) { struct timespec t; t.tv_sec=0; t.tv_nsec=mili*1000000ULL; nanosleep(&t, NULL); }
|
||||
# define SET_HIGH_PRIORITY setpriority(PRIO_PROCESS, 0, -20)
|
||||
#elif defined(_WIN32)
|
||||
# include <windows.h>
|
||||
# define BMK_sleep(s) Sleep(1000*s)
|
||||
# define mili_sleep(mili) Sleep(mili)
|
||||
# define SET_HIGH_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)
|
||||
#else
|
||||
# define BMK_sleep(s) /* disabled */
|
||||
# define mili_sleep(mili) /* disabled */
|
||||
#error "disabled"
|
||||
# define SET_HIGH_PRIORITY /* disabled */
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
|
||||
typedef clock_t BMK_time_t;
|
||||
# define BMK_initTimer(ticksPerSecond) ticksPerSecond=0
|
||||
# define BMK_getTime(x) x = clock()
|
||||
# define BMK_getSpanTimeMicro(ticksPerSecond, clockStart, clockEnd) (1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC)
|
||||
# define BMK_getSpanTimeNano(ticksPerSecond, clockStart, clockEnd) (1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC)
|
||||
#elif defined(_WIN32)
|
||||
typedef LARGE_INTEGER BMK_time_t;
|
||||
# define BMK_initTimer(x) if (!QueryPerformanceFrequency(&x)) { fprintf(stderr, "ERROR: QueryPerformance not present\n"); }
|
||||
# define BMK_getTime(x) QueryPerformanceCounter(&x)
|
||||
# define BMK_getSpanTimeMicro(ticksPerSecond, clockStart, clockEnd) (1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart)
|
||||
# define BMK_getSpanTimeNano(ticksPerSecond, clockStart, clockEnd) (1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart)
|
||||
#else
|
||||
typedef int BMK_time_t;
|
||||
# define BMK_initTimer(ticksPerSecond) ticksPerSecond=0
|
||||
# define BMK_getTimeMicro(clockStart) clockStart=1
|
||||
# define BMK_getSpanTimeMicro(ticksPerSecond, clockStart, clockEnd) (TIMELOOP_S*1000000ULL+clockEnd-clockStart)
|
||||
# define BMK_getSpanTimeNano(ticksPerSecond, clockStart, clockEnd) (TIMELOOP_S*1000000000ULL+clockEnd-clockStart)
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "zstd_static.h"
|
||||
#include "zstd_internal.h" /* ZSTD_setAdditionalParam */
|
||||
#include "zstd_internal.h" /* ZSTD_compressBegin_targetSrcSize */
|
||||
#include "datagen.h" /* RDG_genBuffer */
|
||||
#include "xxhash.h"
|
||||
#include "datagen.h" /* RDG_genBuffer */
|
||||
|
||||
|
||||
|
||||
/* *************************************
|
||||
@@ -138,9 +161,12 @@ static U32 g_displayLevel = 2; /* 0 : no display; 1: errors; 2 : + result
|
||||
***************************************/
|
||||
static U32 g_nbIterations = NBLOOPS;
|
||||
static size_t g_blockSize = 0;
|
||||
int g_additionalParam = 0;
|
||||
|
||||
void BMK_setNotificationLevel(unsigned level) { g_displayLevel=level; }
|
||||
|
||||
void BMK_setAdditionalParam(int additionalParam) { g_additionalParam=additionalParam; }
|
||||
|
||||
void BMK_SetNbIterations(unsigned nbLoops)
|
||||
{
|
||||
g_nbIterations = nbLoops;
|
||||
@@ -157,12 +183,16 @@ void BMK_SetBlockSize(size_t blockSize)
|
||||
/* ********************************************************
|
||||
* Private functions
|
||||
**********************************************************/
|
||||
static clock_t BMK_clockSpan( clock_t clockStart )
|
||||
/* returns time span in microseconds */
|
||||
static U64 BMK_clockSpan( BMK_time_t clockStart, BMK_time_t ticksPerSecond )
|
||||
{
|
||||
return clock() - clockStart; /* works even if overflow, span limited to <= ~30mn */
|
||||
BMK_time_t clockEnd;
|
||||
|
||||
(void)ticksPerSecond;
|
||||
BMK_getTime(clockEnd);
|
||||
return BMK_getSpanTimeMicro(ticksPerSecond, clockStart, clockEnd);
|
||||
}
|
||||
|
||||
|
||||
static U64 BMK_getFileSize(const char* infilename)
|
||||
{
|
||||
int r;
|
||||
@@ -207,44 +237,42 @@ typedef struct
|
||||
int kSlotNew = 0;
|
||||
|
||||
static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
||||
const char* displayName, int cLevel, int additionalParam,
|
||||
const char* displayName, int cLevel,
|
||||
const size_t* fileSizes, U32 nbFiles,
|
||||
const void* dictBuffer, size_t dictBufferSize, benchResult_t *result)
|
||||
{
|
||||
const size_t blockSize = (g_blockSize ? g_blockSize : srcSize) + (!srcSize); /* avoid div by 0 */
|
||||
const U32 maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles;
|
||||
size_t largestBlockSize = 0;
|
||||
size_t const blockSize = (g_blockSize ? g_blockSize : srcSize) + (!srcSize); /* avoid div by 0 */
|
||||
U32 const maxNbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize) + nbFiles;
|
||||
blockParam_t* const blockTable = (blockParam_t*) malloc(maxNbBlocks * sizeof(blockParam_t));
|
||||
const size_t maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); /* add some room for safety */
|
||||
size_t const maxCompressedSize = ZSTD_compressBound(srcSize) + (maxNbBlocks * 1024); /* add some room for safety */
|
||||
void* const compressedBuffer = malloc(maxCompressedSize);
|
||||
void* const resultBuffer = malloc(srcSize);
|
||||
ZSTD_CCtx* refCtx = ZSTD_createCCtx();
|
||||
ZSTD_CCtx* ctx = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* refDCtx = ZSTD_createDCtx();
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
U64 crcOrig = XXH64(srcBuffer, srcSize, 0);
|
||||
U32 nbBlocks = 0;
|
||||
size_t cSize = 0;
|
||||
|
||||
/* init */
|
||||
if (strlen(displayName)>17) displayName += strlen(displayName)-17; /* can only display 17 characters */
|
||||
U32 nbBlocks;
|
||||
BMK_time_t ticksPerSecond;
|
||||
|
||||
/* Memory allocation & restrictions */
|
||||
/* checks */
|
||||
if (!compressedBuffer || !resultBuffer || !blockTable || !refCtx || !ctx || !refDCtx || !dctx)
|
||||
EXM_THROW(31, "not enough memory");
|
||||
|
||||
/* init */
|
||||
if (strlen(displayName)>17) displayName += strlen(displayName)-17; /* can only display 17 characters */
|
||||
BMK_initTimer(ticksPerSecond);
|
||||
|
||||
/* Init blockTable data */
|
||||
{
|
||||
const char* srcPtr = (const char*)srcBuffer;
|
||||
{ const char* srcPtr = (const char*)srcBuffer;
|
||||
char* cPtr = (char*)compressedBuffer;
|
||||
char* resPtr = (char*)resultBuffer;
|
||||
U32 fileNb;
|
||||
for (fileNb=0; fileNb<nbFiles; fileNb++) {
|
||||
for (nbBlocks=0, fileNb=0; fileNb<nbFiles; fileNb++) {
|
||||
size_t remaining = fileSizes[fileNb];
|
||||
U32 const nbBlocksforThisFile = (U32)((remaining + (blockSize-1)) / blockSize);
|
||||
U32 const blockEnd = nbBlocks + nbBlocksforThisFile;
|
||||
for ( ; nbBlocks<blockEnd; nbBlocks++) {
|
||||
size_t thisBlockSize = MIN(remaining, blockSize);
|
||||
size_t const thisBlockSize = MIN(remaining, blockSize);
|
||||
blockTable[nbBlocks].srcPtr = srcPtr;
|
||||
blockTable[nbBlocks].cPtr = cPtr;
|
||||
blockTable[nbBlocks].resPtr = resPtr;
|
||||
@@ -254,137 +282,137 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
|
||||
cPtr += blockTable[nbBlocks].cRoom;
|
||||
resPtr += thisBlockSize;
|
||||
remaining -= thisBlockSize;
|
||||
if (thisBlockSize > largestBlockSize) largestBlockSize = thisBlockSize;
|
||||
} } }
|
||||
|
||||
/* warmimg up memory */
|
||||
// int timeloop = additionalParam ? additionalParam : 2500;
|
||||
kSlotNew = additionalParam;
|
||||
RDG_genBuffer(compressedBuffer, maxCompressedSize, 0.10, 0.50, 1);
|
||||
|
||||
/* Bench */
|
||||
{
|
||||
U32 loopNb;
|
||||
double fastestC = 100000000., fastestD = 100000000.;
|
||||
double ratio = 0.;
|
||||
{ double fastestC = 100000000., fastestD = 100000000.;
|
||||
U64 const crcOrig = XXH64(srcBuffer, srcSize, 0);
|
||||
U64 crcCheck = 0;
|
||||
clock_t coolTime = clock();
|
||||
BMK_time_t coolTime;
|
||||
U32 testNb;
|
||||
size_t cSize = 0;
|
||||
double ratio = 0.;
|
||||
|
||||
BMK_getTime(coolTime);
|
||||
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||
for (loopNb = 1; loopNb <= (g_nbIterations + !g_nbIterations); loopNb++) {
|
||||
int nbLoops;
|
||||
U32 blockNb;
|
||||
clock_t clockStart, clockSpan;
|
||||
clock_t const clockLoop = g_nbIterations ? TIMELOOP_S * CLOCKS_PER_SEC : 10;
|
||||
for (testNb = 1; testNb <= (g_nbIterations + !g_nbIterations); testNb++) {
|
||||
BMK_time_t clockStart, clockEnd;
|
||||
U64 clockLoop = g_nbIterations ? TIMELOOP_S*1000000ULL : 10;
|
||||
|
||||
/* overheat protection */
|
||||
if (BMK_clockSpan(coolTime) > ACTIVEPERIOD_S * CLOCKS_PER_SEC) {
|
||||
if (BMK_clockSpan(coolTime, ticksPerSecond) > ACTIVEPERIOD_S*1000000ULL) {
|
||||
DISPLAY("\rcooling down ... \r");
|
||||
BMK_sleep(COOLPERIOD_S);
|
||||
coolTime = clock();
|
||||
BMK_getTime(coolTime);
|
||||
}
|
||||
|
||||
/* Compression */
|
||||
DISPLAYLEVEL(2, "%2i-%-17.17s :%10u ->\r", loopNb, displayName, (U32)srcSize);
|
||||
DISPLAYLEVEL(2, "%2i-%-17.17s :%10u ->\r", testNb, displayName, (U32)srcSize);
|
||||
memset(compressedBuffer, 0xE5, maxCompressedSize); /* warm up and erase result buffer */
|
||||
|
||||
nbLoops = 0;
|
||||
mili_sleep(1); // give processor to other processes
|
||||
clockStart = clock();
|
||||
while (clock() == clockStart);
|
||||
clockStart = clock();
|
||||
while (BMK_clockSpan(clockStart) < clockLoop) {
|
||||
ZSTD_compressBegin_advanced(refCtx, dictBuffer, dictBufferSize, ZSTD_getParams(cLevel, MAX(dictBufferSize, largestBlockSize)));
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||
size_t rSize = ZSTD_compress_usingPreparedCCtx(ctx, refCtx,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize);
|
||||
if (ZSTD_isError(rSize)) EXM_THROW(1, "ZSTD_compress_usingPreparedCCtx() failed : %s", ZSTD_getErrorName(rSize));
|
||||
blockTable[blockNb].cSize = rSize;
|
||||
}
|
||||
nbLoops++;
|
||||
}
|
||||
clockSpan = BMK_clockSpan(clockStart);
|
||||
mili_sleep(1); /* give processor time to other processes */
|
||||
BMK_getTime(clockStart);
|
||||
do { BMK_getTime(clockEnd); }
|
||||
while (BMK_getSpanTimeNano(ticksPerSecond, clockStart, clockEnd) == 0);
|
||||
BMK_getTime(clockStart);
|
||||
|
||||
{ U32 nbLoops;
|
||||
for (nbLoops = 0 ; BMK_clockSpan(clockStart, ticksPerSecond) < clockLoop ; nbLoops++) {
|
||||
U32 blockNb;
|
||||
ZSTD_compressBegin_targetSrcSize(refCtx, dictBuffer, dictBufferSize, blockSize, cLevel);
|
||||
// ZSTD_compressBegin_usingDict(refCtx, dictBuffer, dictBufferSize, cLevel);
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||
size_t const rSize = ZSTD_compress_usingPreparedCCtx(ctx, refCtx,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cRoom,
|
||||
blockTable[blockNb].srcPtr,blockTable[blockNb].srcSize);
|
||||
if (ZSTD_isError(rSize)) EXM_THROW(1, "ZSTD_compress_usingPreparedCCtx() failed : %s", ZSTD_getErrorName(rSize));
|
||||
blockTable[blockNb].cSize = rSize;
|
||||
} }
|
||||
{ U64 const clockSpan = BMK_clockSpan(clockStart, ticksPerSecond);
|
||||
if ((double)clockSpan < fastestC*nbLoops) fastestC = (double)clockSpan / nbLoops;
|
||||
} }
|
||||
|
||||
cSize = 0;
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++)
|
||||
cSize += blockTable[blockNb].cSize;
|
||||
if ((double)clockSpan < fastestC*nbLoops) fastestC = (double)clockSpan / nbLoops;
|
||||
{ U32 blockNb; for (blockNb=0; blockNb<nbBlocks; blockNb++) cSize += blockTable[blockNb].cSize; }
|
||||
ratio = (double)srcSize / (double)cSize;
|
||||
DISPLAYLEVEL(2, "%2i-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s\r",
|
||||
loopNb, displayName, (U32)srcSize, (U32)cSize, ratio,
|
||||
(double)srcSize / 1000000. / (fastestC / CLOCKS_PER_SEC) );
|
||||
testNb, displayName, (U32)srcSize, (U32)cSize, ratio,
|
||||
(double)srcSize / fastestC );
|
||||
|
||||
(void)fastestD; (void)crcOrig; /* unused when decompression disabled */
|
||||
#if 1
|
||||
/* Decompression */
|
||||
memset(resultBuffer, 0xD6, srcSize); /* warm result buffer */
|
||||
|
||||
nbLoops = 0;
|
||||
mili_sleep(1); // give processor to other processes
|
||||
clockStart = clock();
|
||||
while (clock() == clockStart);
|
||||
clockStart = clock();
|
||||
mili_sleep(1); /* give processor time to other processes */
|
||||
BMK_getTime(clockStart);
|
||||
do { BMK_getTime(clockEnd); }
|
||||
while (BMK_getSpanTimeNano(ticksPerSecond, clockStart, clockEnd) == 0);
|
||||
BMK_getTime(clockStart);
|
||||
|
||||
for ( ; BMK_clockSpan(clockStart) < clockLoop; nbLoops++) {
|
||||
ZSTD_decompressBegin_usingDict(refDCtx, dictBuffer, dictBufferSize);
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||
size_t regenSize = ZSTD_decompress_usingPreparedDCtx(dctx, refDCtx,
|
||||
blockTable[blockNb].resPtr, blockTable[blockNb].srcSize,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cSize);
|
||||
if (ZSTD_isError(regenSize)) {
|
||||
DISPLAY("ZSTD_decompress_usingPreparedDCtx() failed on block %u : %s",
|
||||
blockNb, ZSTD_getErrorName(regenSize));
|
||||
goto _findError;
|
||||
}
|
||||
blockTable[blockNb].resSize = regenSize;
|
||||
{ U32 nbLoops;
|
||||
for (nbLoops = 0 ; BMK_clockSpan(clockStart, ticksPerSecond) < clockLoop ; nbLoops++) {
|
||||
U32 blockNb;
|
||||
ZSTD_decompressBegin_usingDict(refDCtx, dictBuffer, dictBufferSize);
|
||||
for (blockNb=0; blockNb<nbBlocks; blockNb++) {
|
||||
size_t const regenSize = ZSTD_decompress_usingPreparedDCtx(dctx, refDCtx,
|
||||
blockTable[blockNb].resPtr, blockTable[blockNb].srcSize,
|
||||
blockTable[blockNb].cPtr, blockTable[blockNb].cSize);
|
||||
if (ZSTD_isError(regenSize)) {
|
||||
DISPLAY("ZSTD_decompress_usingPreparedDCtx() failed on block %u : %s \n",
|
||||
blockNb, ZSTD_getErrorName(regenSize));
|
||||
clockLoop = 0; /* force immediate test end */
|
||||
break;
|
||||
}
|
||||
blockTable[blockNb].resSize = regenSize;
|
||||
} }
|
||||
{ U64 const clockSpan = BMK_clockSpan(clockStart, ticksPerSecond);
|
||||
if ((double)clockSpan < fastestD*nbLoops) fastestD = (double)clockSpan / nbLoops;
|
||||
} }
|
||||
|
||||
clockSpan = BMK_clockSpan(clockStart);
|
||||
if ((double)clockSpan < fastestD*nbLoops) fastestD = (double)clockSpan / nbLoops;
|
||||
DISPLAYLEVEL(2, "%2i-%-17.17s :%10u ->%10u (%5.3f),%6.1f MB/s ,%6.1f MB/s\r",
|
||||
loopNb, displayName, (U32)srcSize, (U32)cSize, ratio,
|
||||
(double)srcSize / 1000000. / (fastestC / CLOCKS_PER_SEC),
|
||||
(double)srcSize / 1000000. / (fastestD / CLOCKS_PER_SEC) );
|
||||
testNb, displayName, (U32)srcSize, (U32)cSize, ratio,
|
||||
(double)srcSize / fastestC,
|
||||
(double)srcSize / fastestD );
|
||||
|
||||
/* CRC Checking */
|
||||
_findError:
|
||||
crcCheck = XXH64(resultBuffer, srcSize, 0);
|
||||
if (crcOrig!=crcCheck) {
|
||||
size_t u;
|
||||
DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", displayName, (unsigned)crcOrig, (unsigned)crcCheck);
|
||||
for (u=0; u<srcSize; u++) {
|
||||
if (((const BYTE*)srcBuffer)[u] != ((const BYTE*)resultBuffer)[u]) {
|
||||
U32 segNb, bNb, pos;
|
||||
size_t bacc = 0;
|
||||
printf("Decoding error at pos %u ", (U32)u);
|
||||
for (segNb = 0; segNb < nbBlocks; segNb++) {
|
||||
if (bacc + blockTable[segNb].srcSize > u) break;
|
||||
bacc += blockTable[segNb].srcSize;
|
||||
{ crcCheck = XXH64(resultBuffer, srcSize, 0);
|
||||
if (crcOrig!=crcCheck) {
|
||||
size_t u;
|
||||
DISPLAY("!!! WARNING !!! %14s : Invalid Checksum : %x != %x \n", displayName, (unsigned)crcOrig, (unsigned)crcCheck);
|
||||
for (u=0; u<srcSize; u++) {
|
||||
if (((const BYTE*)srcBuffer)[u] != ((const BYTE*)resultBuffer)[u]) {
|
||||
U32 segNb, bNb, pos;
|
||||
size_t bacc = 0;
|
||||
DISPLAY("Decoding error at pos %u ", (U32)u);
|
||||
for (segNb = 0; segNb < nbBlocks; segNb++) {
|
||||
if (bacc + blockTable[segNb].srcSize > u) break;
|
||||
bacc += blockTable[segNb].srcSize;
|
||||
}
|
||||
pos = (U32)(u - bacc);
|
||||
bNb = pos / (128 KB);
|
||||
DISPLAY("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
|
||||
break;
|
||||
}
|
||||
pos = (U32)(u - bacc);
|
||||
bNb = pos / (128 KB);
|
||||
printf("(block %u, sub %u, pos %u) \n", segNb, bNb, pos);
|
||||
break;
|
||||
}
|
||||
if (u==srcSize-1) { /* should never happen */
|
||||
printf("no difference detected\n");
|
||||
} }
|
||||
break;
|
||||
}
|
||||
if (u==srcSize-1) { /* should never happen */
|
||||
DISPLAY("no difference detected\n");
|
||||
} }
|
||||
break;
|
||||
} } /* CRC Checking */
|
||||
#endif
|
||||
}
|
||||
} /* for (testNb = 1; testNb <= (g_nbIterations + !g_nbIterations); testNb++) */
|
||||
|
||||
if (crcOrig == crcCheck)
|
||||
{
|
||||
if (crcOrig == crcCheck) {
|
||||
result->ratio = ratio;
|
||||
result->cSize = cSize;
|
||||
result->cSpeed = (double)srcSize / 1000000. / (fastestC / CLOCKS_PER_SEC);
|
||||
result->dSpeed = (double)srcSize / 1000000. / (fastestD / CLOCKS_PER_SEC);
|
||||
DISPLAYLEVEL(2, "%2i-%-17.17s :%10i ->%10i (%5.3f),%6.1f MB/s ,%6.1f MB/s \n", cLevel, displayName, (int)srcSize, (int)cSize, ratio, result->cSpeed, result->dSpeed);
|
||||
result->cSpeed = (double)srcSize / fastestC;
|
||||
result->dSpeed = (double)srcSize / fastestD;
|
||||
}
|
||||
else
|
||||
DISPLAYLEVEL(2, "%2i-\n", cLevel);
|
||||
}
|
||||
DISPLAYLEVEL(2, "%2i#\n", cLevel);
|
||||
} /* Bench */
|
||||
|
||||
/* clean up */
|
||||
free(compressedBuffer);
|
||||
@@ -399,23 +427,24 @@ _findError:
|
||||
|
||||
static size_t BMK_findMaxMem(U64 requiredMem)
|
||||
{
|
||||
size_t step = 64 MB;
|
||||
size_t const step = 64 MB;
|
||||
BYTE* testmem = NULL;
|
||||
|
||||
requiredMem = (((requiredMem >> 26) + 1) << 26);
|
||||
requiredMem += 2 * step;
|
||||
requiredMem += step;
|
||||
if (requiredMem > maxMemory) requiredMem = maxMemory;
|
||||
|
||||
while (!testmem) {
|
||||
requiredMem -= step;
|
||||
do {
|
||||
testmem = (BYTE*)malloc((size_t)requiredMem);
|
||||
}
|
||||
requiredMem -= step;
|
||||
} while (!testmem);
|
||||
|
||||
free(testmem);
|
||||
return (size_t)(requiredMem - step);
|
||||
return (size_t)(requiredMem);
|
||||
}
|
||||
|
||||
static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
||||
const char* displayName, int cLevel, int cLevelLast, int additionalParam,
|
||||
const char* displayName, int cLevel, int cLevelLast,
|
||||
const size_t* fileSizes, unsigned nbFiles,
|
||||
const void* dictBuffer, size_t dictBufferSize)
|
||||
{
|
||||
@@ -427,6 +456,8 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
||||
setpriority(PRIO_PROCESS, 0, -20);
|
||||
#endif
|
||||
|
||||
SET_HIGH_PRIORITY;
|
||||
|
||||
const char* pch = strrchr(displayName, '\\'); /* Windows */
|
||||
if (!pch) pch = strrchr(displayName, '/'); /* Linux */
|
||||
if (pch) displayName = pch+1;
|
||||
@@ -434,19 +465,20 @@ static void BMK_benchCLevel(void* srcBuffer, size_t benchedSize,
|
||||
memset(&result, 0, sizeof(result));
|
||||
memset(&total, 0, sizeof(total));
|
||||
|
||||
// if (g_displayLevel == 1 && !additionalParam)
|
||||
// DISPLAY("bench %s: input %u bytes, %i iterations, %u KB blocks\n", ZSTD_VERSION, (U32)benchedSize, g_nbIterations, (U32)(g_blockSize>>10));
|
||||
kSlotNew = g_additionalParam;
|
||||
if (g_displayLevel == 1 && !g_additionalParam)
|
||||
DISPLAY("bench %s: input %u bytes, %i iterations, %u KB blocks\n", ZSTD_VERSION, (U32)benchedSize, g_nbIterations, (U32)(g_blockSize>>10));
|
||||
|
||||
if (cLevelLast < cLevel) cLevelLast = cLevel;
|
||||
|
||||
for (l=cLevel; l <= cLevelLast; l++) {
|
||||
BMK_benchMem(srcBuffer, benchedSize,
|
||||
displayName, l, additionalParam,
|
||||
displayName, l,
|
||||
fileSizes, nbFiles,
|
||||
dictBuffer, dictBufferSize, &result);
|
||||
if (g_displayLevel == 1) {
|
||||
if (1)// && additionalParam)
|
||||
DISPLAY("%-3i%11i (%5.3f) %6.1f MB/s %6.1f MB/s %s (kSlotNew=%d)\n", -l, (int)result.cSize, result.ratio, result.cSpeed, result.dSpeed, displayName, additionalParam);
|
||||
if (g_additionalParam)
|
||||
DISPLAY("%-3i%11i (%5.3f) %6.1f MB/s %6.1f MB/s %s (param=%d)\n", -l, (int)result.cSize, result.ratio, result.cSpeed, result.dSpeed, displayName, g_additionalParam);
|
||||
else
|
||||
DISPLAY("%-3i%11i (%5.3f) %6.1f MB/s %6.1f MB/s %s\n", -l, (int)result.cSize, result.ratio, result.cSpeed, result.dSpeed, displayName);
|
||||
total.cSize += result.cSize;
|
||||
@@ -474,30 +506,32 @@ static U64 BMK_getTotalFileSize(const char** fileNamesTable, unsigned nbFiles)
|
||||
return total;
|
||||
}
|
||||
|
||||
/*! BMK_loadFiles() :
|
||||
Loads `buffer` with content of files listed within `fileNamesTable`.
|
||||
At most, fills `buffer` entirely */
|
||||
static void BMK_loadFiles(void* buffer, size_t bufferSize,
|
||||
size_t* fileSizes,
|
||||
const char** fileNamesTable, unsigned const nbFiles)
|
||||
const char** fileNamesTable, unsigned nbFiles)
|
||||
{
|
||||
size_t pos = 0;
|
||||
|
||||
unsigned n;
|
||||
for (n=0; n<nbFiles; n++) {
|
||||
size_t readSize;
|
||||
U64 fileSize = BMK_getFileSize(fileNamesTable[n]);
|
||||
FILE* f = fopen(fileNamesTable[n], "rb");
|
||||
FILE* const f = fopen(fileNamesTable[n], "rb");
|
||||
if (f==NULL) EXM_THROW(10, "impossible to open file %s", fileNamesTable[n]);
|
||||
DISPLAYLEVEL(2, "Loading %s... \r", fileNamesTable[n]);
|
||||
if (fileSize > bufferSize-pos) fileSize = bufferSize-pos;
|
||||
readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);
|
||||
if (readSize != (size_t)fileSize) EXM_THROW(11, "could not read %s", fileNamesTable[n]);
|
||||
pos += readSize;
|
||||
if (fileSize > bufferSize-pos) fileSize = bufferSize-pos, nbFiles=n; /* buffer too small - stop after this file */
|
||||
{ size_t const readSize = fread(((char*)buffer)+pos, 1, (size_t)fileSize, f);
|
||||
if (readSize != (size_t)fileSize) EXM_THROW(11, "could not read %s", fileNamesTable[n]);
|
||||
pos += readSize; }
|
||||
fileSizes[n] = (size_t)fileSize;
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
||||
const char* dictFileName, int cLevel, int cLevelLast, int additionalParam)
|
||||
const char* dictFileName, int cLevel, int cLevelLast)
|
||||
{
|
||||
void* srcBuffer;
|
||||
size_t benchedSize;
|
||||
@@ -537,7 +571,7 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
||||
else displayName = fileNamesTable[0];
|
||||
|
||||
BMK_benchCLevel(srcBuffer, benchedSize,
|
||||
displayName, cLevel, cLevelLast, additionalParam,
|
||||
displayName, cLevel, cLevelLast,
|
||||
fileSizes, nbFiles,
|
||||
dictBuffer, dictBufferSize);
|
||||
|
||||
@@ -548,7 +582,7 @@ static void BMK_benchFileTable(const char** fileNamesTable, unsigned nbFiles,
|
||||
}
|
||||
|
||||
|
||||
static void BMK_syntheticTest(int cLevel, int cLevelLast, int additionalParam, double compressibility)
|
||||
static void BMK_syntheticTest(int cLevel, int cLevelLast, double compressibility)
|
||||
{
|
||||
char name[20] = {0};
|
||||
size_t benchedSize = 10000000;
|
||||
@@ -562,7 +596,7 @@ static void BMK_syntheticTest(int cLevel, int cLevelLast, int additionalParam, d
|
||||
|
||||
/* Bench */
|
||||
snprintf (name, sizeof(name), "Synthetic %2u%%", (unsigned)(compressibility*100));
|
||||
BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, additionalParam, &benchedSize, 1, NULL, 0);
|
||||
BMK_benchCLevel(srcBuffer, benchedSize, name, cLevel, cLevelLast, &benchedSize, 1, NULL, 0);
|
||||
|
||||
/* clean up */
|
||||
free(srcBuffer);
|
||||
@@ -570,14 +604,14 @@ static void BMK_syntheticTest(int cLevel, int cLevelLast, int additionalParam, d
|
||||
|
||||
|
||||
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
|
||||
const char* dictFileName, int cLevel, int cLevelLast, int additionalParam)
|
||||
const char* dictFileName, int cLevel, int cLevelLast)
|
||||
{
|
||||
double const compressibility = (double)g_compressibilityDefault / 100;
|
||||
|
||||
if (nbFiles == 0)
|
||||
BMK_syntheticTest(cLevel, cLevelLast, additionalParam, compressibility);
|
||||
BMK_syntheticTest(cLevel, cLevelLast, compressibility);
|
||||
else
|
||||
BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast, additionalParam);
|
||||
BMK_benchFileTable(fileNamesTable, nbFiles, dictFileName, cLevel, cLevelLast);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -27,10 +27,11 @@
|
||||
|
||||
/* Main function */
|
||||
int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles,
|
||||
const char* dictFileName, int cLevel, int cLevelLast, int additionalParam);
|
||||
const char* dictFileName, int cLevel, int cLevelLast);
|
||||
|
||||
/* Set Parameters */
|
||||
void BMK_SetNbIterations(unsigned nbLoops);
|
||||
void BMK_SetBlockSize(size_t blockSize);
|
||||
void BMK_setAdditionalParam(int additionalParam);
|
||||
void BMK_setNotificationLevel(unsigned level);
|
||||
|
||||
|
||||
+16
-17
@@ -333,28 +333,28 @@ static int FIO_compressFilename_internal(cRess_t ress,
|
||||
{
|
||||
FILE* srcFile = ress.srcFile;
|
||||
FILE* dstFile = ress.dstFile;
|
||||
U64 filesize = 0;
|
||||
U64 readsize = 0;
|
||||
U64 compressedfilesize = 0;
|
||||
size_t dictSize = ress.dictBufferSize;
|
||||
size_t sizeCheck, errorCode;
|
||||
size_t sizeCheck;
|
||||
ZSTD_parameters params;
|
||||
U64 const fileSize = FIO_getFileSize(srcFileName);
|
||||
|
||||
/* init */
|
||||
filesize = MAX(FIO_getFileSize(srcFileName),dictSize);
|
||||
params = ZSTD_getParams(cLevel, filesize);
|
||||
params.srcSize = filesize;
|
||||
if (g_maxWLog) if (params.windowLog > g_maxWLog) params.windowLog = g_maxWLog;
|
||||
errorCode = ZBUFF_compressInit_advanced(ress.ctx, ress.dictBuffer, ress.dictBufferSize, params);
|
||||
if (ZBUFF_isError(errorCode)) EXM_THROW(21, "Error initializing compression : %s", ZBUFF_getErrorName(errorCode));
|
||||
params.cParams = ZSTD_getCParams(cLevel, fileSize, dictSize);
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
if (g_maxWLog) if (params.cParams.windowLog > g_maxWLog) params.cParams.windowLog = g_maxWLog;
|
||||
{ size_t const errorCode = ZBUFF_compressInit_advanced(ress.ctx, ress.dictBuffer, ress.dictBufferSize, params, fileSize);
|
||||
if (ZBUFF_isError(errorCode)) EXM_THROW(21, "Error initializing compression : %s", ZBUFF_getErrorName(errorCode)); }
|
||||
|
||||
/* Main compression loop */
|
||||
filesize = 0;
|
||||
readsize = 0;
|
||||
while (1) {
|
||||
/* Fill input Buffer */
|
||||
size_t inSize = fread(ress.srcBuffer, (size_t)1, ress.srcBufferSize, srcFile);
|
||||
size_t const inSize = fread(ress.srcBuffer, (size_t)1, ress.srcBufferSize, srcFile);
|
||||
if (inSize==0) break;
|
||||
filesize += inSize;
|
||||
DISPLAYUPDATE(2, "\rRead : %u MB ", (U32)(filesize>>20));
|
||||
readsize += inSize;
|
||||
DISPLAYUPDATE(2, "\rRead : %u MB ", (U32)(readsize>>20));
|
||||
|
||||
{ /* Compress using buffered streaming */
|
||||
size_t usedInSize = inSize;
|
||||
@@ -371,13 +371,12 @@ static int FIO_compressFilename_internal(cRess_t ress,
|
||||
if (sizeCheck!=cSize) EXM_THROW(25, "Write error : cannot write compressed block into %s", dstFileName);
|
||||
compressedfilesize += cSize;
|
||||
}
|
||||
DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", (U32)(filesize>>20), (double)compressedfilesize/filesize*100);
|
||||
DISPLAYUPDATE(2, "\rRead : %u MB ==> %.2f%% ", (U32)(readsize>>20), (double)compressedfilesize/readsize*100);
|
||||
}
|
||||
|
||||
/* End of Frame */
|
||||
{
|
||||
size_t cSize = ress.dstBufferSize;
|
||||
size_t result = ZBUFF_compressEnd(ress.ctx, ress.dstBuffer, &cSize);
|
||||
{ size_t cSize = ress.dstBufferSize;
|
||||
size_t const result = ZBUFF_compressEnd(ress.ctx, ress.dstBuffer, &cSize);
|
||||
if (result!=0) EXM_THROW(26, "Compression error : cannot create frame end");
|
||||
|
||||
sizeCheck = fwrite(ress.dstBuffer, 1, cSize, dstFile);
|
||||
@@ -388,7 +387,7 @@ static int FIO_compressFilename_internal(cRess_t ress,
|
||||
/* Status */
|
||||
DISPLAYLEVEL(2, "\r%79s\r", "");
|
||||
DISPLAYLEVEL(2,"Compressed %llu bytes into %llu bytes ==> %.2f%%\n",
|
||||
(unsigned long long) filesize, (unsigned long long) compressedfilesize, (double)compressedfilesize/filesize*100);
|
||||
(unsigned long long)readsize, (unsigned long long) compressedfilesize, (double)compressedfilesize/readsize*100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ static clock_t BMK_clockSpan( clock_t clockStart )
|
||||
|
||||
static size_t BMK_findMaxMem(U64 requiredMem)
|
||||
{
|
||||
const size_t step = 64 MB;
|
||||
size_t const step = 64 MB;
|
||||
void* testmem = NULL;
|
||||
|
||||
requiredMem = (((requiredMem >> 26) + 1) << 26);
|
||||
@@ -182,15 +182,13 @@ size_t local_ZSTD_decodeLiteralsBlock(void* dst, size_t dstSize, void* buff2, co
|
||||
}
|
||||
|
||||
extern size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr);
|
||||
extern size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr, FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb, const void* src, size_t srcSize);
|
||||
extern size_t ZSTD_decodeSeqHeaders(int* nbSeq, FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb, const void* src, size_t srcSize);
|
||||
size_t local_ZSTD_decodeSeqHeaders(void* dst, size_t dstSize, void* buff2, const void* src, size_t srcSize)
|
||||
{
|
||||
U32 DTableML[FSE_DTABLE_SIZE_U32(10)], DTableLL[FSE_DTABLE_SIZE_U32(10)], DTableOffb[FSE_DTABLE_SIZE_U32(9)]; /* MLFSELog, LLFSELog and OffFSELog are not public values */
|
||||
const BYTE* dumps;
|
||||
size_t length;
|
||||
int nbSeq;
|
||||
(void)src; (void)srcSize; (void)dst; (void)dstSize;
|
||||
return ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &length, DTableLL, DTableML, DTableOffb, buff2, g_cSize);
|
||||
return ZSTD_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, buff2, g_cSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+134
-190
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Fuzzer test tool for zstd
|
||||
Copyright (C) Yann Collet 2014-2105
|
||||
Copyright (C) Yann Collet 2014-2016
|
||||
|
||||
GPL v2 License
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
You can contact the author at :
|
||||
- ZSTD source repository : https://github.com/Cyan4973/zstd
|
||||
- ZSTD public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
- ZSTD homepage : http://www.zstd.net
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Compiler specific
|
||||
**************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
@@ -32,14 +31,8 @@
|
||||
# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
|
||||
#endif
|
||||
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
|
||||
# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include <stdlib.h> /* free */
|
||||
@@ -52,8 +45,8 @@
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
Constants
|
||||
/*-************************************
|
||||
* Constants
|
||||
**************************************/
|
||||
#ifndef ZSTD_VERSION
|
||||
# define ZSTD_VERSION ""
|
||||
@@ -63,15 +56,12 @@
|
||||
#define MB *(1U<<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
static const size_t COMPRESSIBLE_NOISE_LENGTH = 10 MB; /* capital, used to be a macro */
|
||||
static const U32 FUZ_compressibility_default = 50;
|
||||
static const U32 nbTestsDefault = 30000;
|
||||
#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
|
||||
#define FUZ_COMPRESSIBILITY_DEFAULT 50
|
||||
static const U32 prime1 = 2654435761U;
|
||||
static const U32 prime2 = 2246822519U;
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Display Macros
|
||||
**************************************/
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
@@ -85,10 +75,8 @@ static U32 g_displayLevel = 2;
|
||||
static const U32 g_refreshRate = 150;
|
||||
static U32 g_displayTime = 0;
|
||||
|
||||
static U32 g_testTime = 0;
|
||||
|
||||
|
||||
/*********************************************************
|
||||
/*-*******************************************************
|
||||
* Fuzzer functions
|
||||
*********************************************************/
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -117,6 +105,8 @@ static U32 FUZ_GetMilliSpan(U32 nTimeStart)
|
||||
# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
unsigned int FUZ_rand(unsigned int* src)
|
||||
{
|
||||
static const U32 prime1 = 2654435761U;
|
||||
static const U32 prime2 = 2246822519U;
|
||||
U32 rand32 = *src;
|
||||
rand32 *= prime1;
|
||||
rand32 += prime2;
|
||||
@@ -130,8 +120,7 @@ static unsigned FUZ_highbit32(U32 v32)
|
||||
{
|
||||
unsigned nbBits = 0;
|
||||
if (v32==0) return 0;
|
||||
while (v32)
|
||||
{
|
||||
while (v32) {
|
||||
v32 >>= 1;
|
||||
nbBits ++;
|
||||
}
|
||||
@@ -153,8 +142,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
|
||||
compressedBuffer = malloc(ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH));
|
||||
decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
|
||||
if (!CNBuffer || !compressedBuffer || !decodedBuffer)
|
||||
{
|
||||
if (!CNBuffer || !compressedBuffer || !decodedBuffer) {
|
||||
DISPLAY("Not enough memory, aborting\n");
|
||||
testResult = 1;
|
||||
goto _end;
|
||||
@@ -162,23 +150,21 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
RDG_genBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, 0., randState);
|
||||
|
||||
/* Basic tests */
|
||||
DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||
DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, (U32)COMPRESSIBLE_NOISE_LENGTH);
|
||||
result = ZSTD_compress(compressedBuffer, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH), CNBuffer, COMPRESSIBLE_NOISE_LENGTH, 1);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
cSize = result;
|
||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
|
||||
|
||||
DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
|
||||
DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, (U32)COMPRESSIBLE_NOISE_LENGTH);
|
||||
result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
if (result != COMPRESSIBLE_NOISE_LENGTH) goto _output_error;
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
{
|
||||
size_t i;
|
||||
{ size_t i;
|
||||
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
|
||||
for (i=0; i<COMPRESSIBLE_NOISE_LENGTH; i++)
|
||||
{
|
||||
for (i=0; i<COMPRESSIBLE_NOISE_LENGTH; i++) {
|
||||
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
|
||||
}
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
@@ -197,8 +183,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
/* Dictionary and Duplication tests */
|
||||
{
|
||||
ZSTD_CCtx* ctxOrig = ZSTD_createCCtx();
|
||||
{ ZSTD_CCtx* ctxOrig = ZSTD_createCCtx();
|
||||
ZSTD_CCtx* ctxDuplicated = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
const size_t dictSize = 500;
|
||||
@@ -269,8 +254,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
/* block API tests */
|
||||
{
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
{ ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
const size_t blockSize = 100 KB;
|
||||
const size_t dictSize = 16 KB;
|
||||
@@ -312,8 +296,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
}
|
||||
|
||||
/* long rle test */
|
||||
{
|
||||
size_t sampleSize = 0;
|
||||
{ size_t sampleSize = 0;
|
||||
DISPLAYLEVEL(4, "test%3i : Long RLE test : ", testNb++);
|
||||
RDG_genBuffer(CNBuffer, sampleSize, compressibility, 0., randState);
|
||||
memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1);
|
||||
@@ -344,41 +327,40 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
/* nbSeq limit test */
|
||||
{
|
||||
#define _3BYTESTESTLENGTH 131000
|
||||
#define NB3BYTESSEQLOG 9
|
||||
#define NB3BYTESSEQ (1 << NB3BYTESSEQLOG)
|
||||
#define NB3BYTESSEQMASK (NB3BYTESSEQ-1)
|
||||
BYTE _3BytesSeqs[NB3BYTESSEQ][3];
|
||||
U32 r = 1;
|
||||
int i;
|
||||
#define _3BYTESTESTLENGTH 131000
|
||||
#define NB3BYTESSEQLOG 9
|
||||
#define NB3BYTESSEQ (1 << NB3BYTESSEQLOG)
|
||||
#define NB3BYTESSEQMASK (NB3BYTESSEQ-1)
|
||||
/* creates a buffer full of 3-bytes sequences */
|
||||
{ BYTE _3BytesSeqs[NB3BYTESSEQ][3];
|
||||
U32 rSeed = 1;
|
||||
|
||||
for (i=0; i < NB3BYTESSEQ; i++) {
|
||||
_3BytesSeqs[i][0] = (BYTE)(FUZ_rand(&r) & 255);
|
||||
_3BytesSeqs[i][1] = (BYTE)(FUZ_rand(&r) & 255);
|
||||
_3BytesSeqs[i][2] = (BYTE)(FUZ_rand(&r) & 255);
|
||||
}
|
||||
/* create batch of 3-bytes sequences */
|
||||
{ int i; for (i=0; i < NB3BYTESSEQ; i++) {
|
||||
_3BytesSeqs[i][0] = (BYTE)(FUZ_rand(&rSeed) & 255);
|
||||
_3BytesSeqs[i][1] = (BYTE)(FUZ_rand(&rSeed) & 255);
|
||||
_3BytesSeqs[i][2] = (BYTE)(FUZ_rand(&rSeed) & 255);
|
||||
}}
|
||||
|
||||
for (i=0; i < _3BYTESTESTLENGTH; ) {
|
||||
U32 id = FUZ_rand(&r) & NB3BYTESSEQMASK;
|
||||
/* randomly fills CNBuffer with prepared 3-bytes sequences */
|
||||
{ int i; for (i=0; i < _3BYTESTESTLENGTH; ) { /* note : CNBuffer size > _3BYTESTESTLENGTH+3 */
|
||||
U32 id = FUZ_rand(&rSeed) & NB3BYTESSEQMASK;
|
||||
((BYTE*)CNBuffer)[i+0] = _3BytesSeqs[id][0];
|
||||
((BYTE*)CNBuffer)[i+1] = _3BytesSeqs[id][1];
|
||||
((BYTE*)CNBuffer)[i+2] = _3BytesSeqs[id][2];
|
||||
i += 3;
|
||||
}
|
||||
} }}
|
||||
DISPLAYLEVEL(4, "test%3i : compress lots 3-bytes sequences : ", testNb++);
|
||||
result = ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH), CNBuffer, _3BYTESTESTLENGTH, 19);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
cSize = result;
|
||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/_3BYTESTESTLENGTH*100);
|
||||
|
||||
DISPLAYLEVEL(4, "test%3i : compress lots 3-bytes sequences : ", testNb++);
|
||||
result = ZSTD_compress(compressedBuffer, ZSTD_compressBound(_3BYTESTESTLENGTH), CNBuffer, _3BYTESTESTLENGTH, 19);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
cSize = result;
|
||||
DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/_3BYTESTESTLENGTH*100);
|
||||
|
||||
DISPLAYLEVEL(4, "test%3i : decompress lots 3-bytes sequence : ", testNb++);
|
||||
result = ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
if (result != _3BYTESTESTLENGTH) goto _output_error;
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
}
|
||||
DISPLAYLEVEL(4, "test%3i : decompress lots 3-bytes sequence : ", testNb++);
|
||||
result = ZSTD_decompress(decodedBuffer, _3BYTESTESTLENGTH, compressedBuffer, cSize);
|
||||
if (ZSTD_isError(result)) goto _output_error;
|
||||
if (result != _3BYTESTESTLENGTH) goto _output_error;
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
_end:
|
||||
free(CNBuffer);
|
||||
@@ -398,20 +380,19 @@ static size_t findDiff(const void* buf1, const void* buf2, size_t max)
|
||||
const BYTE* b1 = (const BYTE*)buf1;
|
||||
const BYTE* b2 = (const BYTE*)buf2;
|
||||
size_t i;
|
||||
for (i=0; i<max; i++)
|
||||
{
|
||||
for (i=0; i<max; i++) {
|
||||
if (b1[i] != b2[i]) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
|
||||
DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
|
||||
#define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
|
||||
DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
|
||||
|
||||
static const U32 maxSrcLog = 23;
|
||||
static const U32 maxSampleLog = 22;
|
||||
|
||||
int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
|
||||
int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 maxDuration, double compressibility)
|
||||
{
|
||||
BYTE* cNoiseBuffer[5];
|
||||
BYTE* srcBuffer;
|
||||
@@ -454,14 +435,12 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
srcBuffer = cNoiseBuffer[2];
|
||||
|
||||
/* catch up testNb */
|
||||
for (testNb=1; testNb < startTest; testNb++)
|
||||
FUZ_rand(&coreSeed);
|
||||
for (testNb=1; testNb < startTest; testNb++) FUZ_rand(&coreSeed);
|
||||
|
||||
/* test loop */
|
||||
for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < g_testTime); testNb++ )
|
||||
{
|
||||
/* main test loop */
|
||||
for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < maxDuration); testNb++ ) {
|
||||
size_t sampleSize, sampleStart, maxTestSize, totalTestSize;
|
||||
size_t cSize, dSize, dSupSize, errorCode, totalCSize, totalGenSize;
|
||||
size_t cSize, dSize, errorCode, totalCSize, totalGenSize;
|
||||
U32 sampleSizeLog, buffNb, cLevelMod, nbChunks, n;
|
||||
XXH64_CREATESTATE_STATIC(xxh64);
|
||||
U64 crcOrig, crcDest;
|
||||
@@ -470,29 +449,23 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
const BYTE* dict;
|
||||
size_t dictSize;
|
||||
|
||||
/* init */
|
||||
if (nbTests >= testNb)
|
||||
{ DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
|
||||
/* notification */
|
||||
if (nbTests >= testNb) { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); }
|
||||
else { DISPLAYUPDATE(2, "\r%6u ", testNb); }
|
||||
|
||||
FUZ_rand(&coreSeed);
|
||||
lseed = coreSeed ^ prime1;
|
||||
{ U32 const prime1 = 2654435761U; lseed = coreSeed ^ prime1; }
|
||||
buffNb = FUZ_rand(&lseed) & 127;
|
||||
if (buffNb & 7) buffNb=2;
|
||||
else
|
||||
{
|
||||
else {
|
||||
buffNb >>= 3;
|
||||
if (buffNb & 7)
|
||||
{
|
||||
if (buffNb & 7) {
|
||||
const U32 tnb[2] = { 1, 3 };
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
const U32 tnb[2] = { 0, 4 };
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
}
|
||||
}
|
||||
} }
|
||||
srcBuffer = cNoiseBuffer[buffNb];
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
@@ -506,7 +479,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
crcOrig = XXH64(sampleBuffer, sampleSize, 0);
|
||||
|
||||
/* compression test */
|
||||
//cLevelMod = MAX(1, 38 - (int)(MAX(9, sampleSizeLog) * 2)); /* high levels only for small samples, for manageable speed */
|
||||
cLevelMod = MIN( ZSTD_maxCLevel(), (U32)MAX(1, 55 - 3*(int)sampleSizeLog) ); /* high levels only for small samples, for manageable speed */
|
||||
cLevel = (FUZ_rand(&lseed) % cLevelMod) +1;
|
||||
cSize = ZSTD_compressCCtx(ctx, cBuffer, cBufferSize, sampleBuffer, sampleSize, cLevel);
|
||||
@@ -516,34 +488,33 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
if (cSize > 3) {
|
||||
const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
||||
const size_t tooSmallSize = cSize - missing;
|
||||
static const U32 endMark = 0x4DC2B1A9;
|
||||
U32 endCheck;
|
||||
const U32 endMark = 0x4DC2B1A9;
|
||||
memcpy(dstBuffer+tooSmallSize, &endMark, 4);
|
||||
errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);
|
||||
CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize);
|
||||
memcpy(&endCheck, dstBuffer+tooSmallSize, 4);
|
||||
CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow");
|
||||
{ U32 endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, 4);
|
||||
CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow"); }
|
||||
}
|
||||
|
||||
/* decompression header test */
|
||||
/* frame header decompression test */
|
||||
{ ZSTD_frameParams dParams;
|
||||
size_t const check = ZSTD_getFrameParams(&dParams, cBuffer, cSize);
|
||||
CHECK(ZSTD_isError(check), "Frame Parameters extraction failed");
|
||||
CHECK(dParams.frameContentSize != sampleSize, "Frame content size incorrect");
|
||||
}
|
||||
|
||||
/* successfull decompression tests*/
|
||||
dSupSize = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;
|
||||
dSize = ZSTD_decompress(dstBuffer, sampleSize + dSupSize, cBuffer, cSize);
|
||||
CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize);
|
||||
crcDest = XXH64(dstBuffer, sampleSize, 0);
|
||||
CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (U32)findDiff(sampleBuffer, dstBuffer, sampleSize), (U32)sampleSize);
|
||||
/* successful decompression test */
|
||||
{ size_t margin = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;
|
||||
dSize = ZSTD_decompress(dstBuffer, sampleSize + margin, cBuffer, cSize);
|
||||
CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s) (srcSize : %u ; cSize : %u)", ZSTD_getErrorName(dSize), (U32)sampleSize, (U32)cSize);
|
||||
crcDest = XXH64(dstBuffer, sampleSize, 0);
|
||||
CHECK(crcOrig != crcDest, "decompression result corrupted (pos %u / %u)", (U32)findDiff(sampleBuffer, dstBuffer, sampleSize), (U32)sampleSize);
|
||||
}
|
||||
|
||||
free(sampleBuffer); /* no longer useful after this point */
|
||||
|
||||
/* truncated src decompression test */
|
||||
{
|
||||
const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
||||
{ const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
||||
const size_t tooSmallSize = cSize - missing;
|
||||
void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch overflows */
|
||||
CHECK(cBufferTooSmall == NULL, "not enough memory !");
|
||||
@@ -554,8 +525,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
}
|
||||
|
||||
/* too small dst decompression test */
|
||||
if (sampleSize > 3)
|
||||
{
|
||||
if (sampleSize > 3) {
|
||||
const size_t missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
||||
const size_t tooSmallSize = sampleSize - missing;
|
||||
static const BYTE token = 0xA9;
|
||||
@@ -566,50 +536,40 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
}
|
||||
|
||||
/* noisy src decompression test */
|
||||
if (cSize > 6)
|
||||
{
|
||||
const U32 maxNbBits = FUZ_highbit32((U32)(cSize-4));
|
||||
size_t pos = 4; /* preserve magic number (too easy to detect) */
|
||||
U32 nbBits = FUZ_rand(&lseed) % maxNbBits;
|
||||
size_t mask = (1<<nbBits) - 1;
|
||||
size_t skipLength = FUZ_rand(&lseed) & mask;
|
||||
pos += skipLength;
|
||||
|
||||
while (pos < cSize)
|
||||
{
|
||||
/* add noise */
|
||||
size_t noiseStart, noiseLength;
|
||||
nbBits = FUZ_rand(&lseed) % maxNbBits;
|
||||
if (nbBits>0) nbBits--;
|
||||
mask = (1<<nbBits) - 1;
|
||||
noiseLength = (FUZ_rand(&lseed) & mask) + 1;
|
||||
if ( pos+noiseLength > cSize ) noiseLength = cSize-pos;
|
||||
noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);
|
||||
memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);
|
||||
pos += noiseLength;
|
||||
|
||||
/* keep some original src */
|
||||
nbBits = FUZ_rand(&lseed) % maxNbBits;
|
||||
mask = (1<<nbBits) - 1;
|
||||
skipLength = FUZ_rand(&lseed) & mask;
|
||||
pos += skipLength;
|
||||
}
|
||||
if (cSize > 6) {
|
||||
/* insert noise into src */
|
||||
{ U32 const maxNbBits = FUZ_highbit32((U32)(cSize-4));
|
||||
size_t pos = 4; /* preserve magic number (too easy to detect) */
|
||||
for (;;) {
|
||||
/* keep some original src */
|
||||
{ U32 const nbBits = FUZ_rand(&lseed) % maxNbBits;
|
||||
size_t const mask = (1<<nbBits) - 1;
|
||||
size_t const skipLength = FUZ_rand(&lseed) & mask;
|
||||
pos += skipLength;
|
||||
}
|
||||
if (pos <= cSize) break;
|
||||
/* add noise */
|
||||
{ U32 nbBits = FUZ_rand(&lseed) % maxNbBits;
|
||||
size_t mask, noiseStart, noiseLength;
|
||||
if (nbBits>0) nbBits--;
|
||||
mask = (1<<nbBits) - 1;
|
||||
noiseLength = (FUZ_rand(&lseed) & mask) + 1;
|
||||
if ( pos+noiseLength > cSize ) noiseLength = cSize-pos;
|
||||
noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);
|
||||
memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);
|
||||
pos += noiseLength;
|
||||
} } }
|
||||
|
||||
/* decompress noisy source */
|
||||
{
|
||||
U32 noiseSrc = FUZ_rand(&lseed) % 5;
|
||||
const U32 endMark = 0xA9B1C3D6;
|
||||
U32 endCheck;
|
||||
srcBuffer = cNoiseBuffer[noiseSrc];
|
||||
{ U32 const endMark = 0xA9B1C3D6;
|
||||
memcpy(dstBuffer+sampleSize, &endMark, 4);
|
||||
errorCode = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize);
|
||||
/* result *may* be an unlikely success, but even then, it must strictly respect dest buffer boundaries */
|
||||
/* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */
|
||||
CHECK((!ZSTD_isError(errorCode)) && (errorCode>sampleSize),
|
||||
"ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (U32)errorCode, (U32)sampleSize);
|
||||
memcpy(&endCheck, dstBuffer+sampleSize, 4);
|
||||
CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow");
|
||||
}
|
||||
}
|
||||
{ U32 endCheck; memcpy(&endCheck, dstBuffer+sampleSize, 4);
|
||||
CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow"); }
|
||||
} } /* noisy src decompression test */
|
||||
|
||||
/* Streaming compression of scattered segments test */
|
||||
XXH64_reset(xxh64, 0);
|
||||
@@ -631,8 +591,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
errorCode = ZSTD_copyCCtx(ctx, refCtx);
|
||||
CHECK (ZSTD_isError(errorCode), "ZSTD_copyCCtx error : %s", ZSTD_getErrorName(errorCode));
|
||||
totalTestSize = 0; cSize = 0;
|
||||
for (n=0; n<nbChunks; n++)
|
||||
{
|
||||
for (n=0; n<nbChunks; n++) {
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
@@ -661,8 +620,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
CHECK (ZSTD_isError(errorCode), "cannot init DCtx : %s", ZSTD_getErrorName(errorCode));
|
||||
totalCSize = 0;
|
||||
totalGenSize = 0;
|
||||
while (totalCSize < cSize)
|
||||
{
|
||||
while (totalCSize < cSize) {
|
||||
size_t inSize = ZSTD_nextSrcSizeToDecompress(dctx);
|
||||
size_t genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize);
|
||||
CHECK (ZSTD_isError(genSize), "streaming decompression error : %s", ZSTD_getErrorName(genSize));
|
||||
@@ -677,7 +635,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
errorCode = findDiff(mirrorBuffer, dstBuffer, totalTestSize);
|
||||
CHECK (crcDest!=crcOrig, "streaming decompressed data corrupted : byte %u / %u (%02X!=%02X)",
|
||||
(U32)errorCode, (U32)totalTestSize, dstBuffer[errorCode], mirrorBuffer[errorCode]);
|
||||
|
||||
}
|
||||
DISPLAY("\r%u fuzzer tests completed \n", testNb-1);
|
||||
|
||||
@@ -701,10 +658,10 @@ _output_error:
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************
|
||||
/*_*******************************************************
|
||||
* Command line
|
||||
*********************************************************/
|
||||
int FUZ_usage(char* programName)
|
||||
int FUZ_usage(const char* programName)
|
||||
{
|
||||
DISPLAY( "Usage :\n");
|
||||
DISPLAY( " %s [args]\n", programName);
|
||||
@@ -713,7 +670,7 @@ int FUZ_usage(char* programName)
|
||||
DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
|
||||
DISPLAY( " -s# : Select seed (default:prompt user)\n");
|
||||
DISPLAY( " -t# : Select starting test number (default:0)\n");
|
||||
DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
|
||||
DISPLAY( " -P# : Select compressibility in %% (default:%u%%)\n", FUZ_compressibility_default);
|
||||
DISPLAY( " -v : verbose\n");
|
||||
DISPLAY( " -p : pause at the end\n");
|
||||
DISPLAY( " -h : display help and exit\n");
|
||||
@@ -721,33 +678,29 @@ int FUZ_usage(char* programName)
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
U32 seed=0;
|
||||
int seedset=0;
|
||||
int argNb;
|
||||
int nbTests = nbTestsDefault;
|
||||
int testNb = 0;
|
||||
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
|
||||
U32 proba = FUZ_compressibility_default;
|
||||
int result=0;
|
||||
U32 mainPause = 0;
|
||||
char* programName;
|
||||
U32 maxDuration = 0;
|
||||
const char* programName;
|
||||
|
||||
/* Check command line */
|
||||
programName = argv[0];
|
||||
for(argNb=1; argNb<argc; argNb++)
|
||||
{
|
||||
char* argument = argv[argNb];
|
||||
|
||||
for (argNb=1; argNb<argc; argNb++) {
|
||||
const char* argument = argv[argNb];
|
||||
if(!argument) continue; /* Protection if argument empty */
|
||||
|
||||
/* Handle commands. Aggregated commands are allowed */
|
||||
if (argument[0]=='-')
|
||||
{
|
||||
if (argument[0]=='-') {
|
||||
argument++;
|
||||
|
||||
while (*argument!=0)
|
||||
{
|
||||
while (*argument!=0) {
|
||||
switch(*argument)
|
||||
{
|
||||
case 'h':
|
||||
@@ -766,10 +719,9 @@ int main(int argc, char** argv)
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
argument++; g_testTime=0;
|
||||
argument++; maxDuration=0;
|
||||
nbTests=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
nbTests *= 10;
|
||||
nbTests += *argument - '0';
|
||||
argument++;
|
||||
@@ -778,24 +730,22 @@ int main(int argc, char** argv)
|
||||
|
||||
case 'T':
|
||||
argument++;
|
||||
nbTests=0; g_testTime=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
g_testTime *= 10;
|
||||
g_testTime += *argument - '0';
|
||||
nbTests=0; maxDuration=0;
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
maxDuration *= 10;
|
||||
maxDuration += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
if (*argument=='m') g_testTime *=60, argument++;
|
||||
if (*argument=='m') maxDuration *=60, argument++;
|
||||
if (*argument=='n') argument++;
|
||||
g_testTime *= 1000;
|
||||
maxDuration *= 1000;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
argument++;
|
||||
seed=0;
|
||||
seedset=1;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
seed *= 10;
|
||||
seed += *argument - '0';
|
||||
argument++;
|
||||
@@ -805,8 +755,7 @@ int main(int argc, char** argv)
|
||||
case 't':
|
||||
argument++;
|
||||
testNb=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
testNb *= 10;
|
||||
testNb += *argument - '0';
|
||||
argument++;
|
||||
@@ -816,35 +765,30 @@ int main(int argc, char** argv)
|
||||
case 'P': /* compressibility % */
|
||||
argument++;
|
||||
proba=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
proba *= 10;
|
||||
proba += *argument - '0';
|
||||
argument++;
|
||||
}
|
||||
if (proba<0) proba=0;
|
||||
if (proba>100) proba=100;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FUZ_usage(programName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} } } } /* for (argNb=1; argNb<argc; argNb++) */
|
||||
|
||||
/* Get Seed */
|
||||
DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION);
|
||||
|
||||
if (!seedset) seed = FUZ_GetMilliStart() % 10000;
|
||||
DISPLAY("Seed = %u\n", seed);
|
||||
if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba);
|
||||
if (proba!=FUZ_compressibility_default) DISPLAY("Compressibility : %u%%\n", proba);
|
||||
|
||||
if (testNb==0) result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
|
||||
if (testNb==0)
|
||||
result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
|
||||
if (!result)
|
||||
result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
|
||||
if (mainPause)
|
||||
{
|
||||
result = fuzzerTests(seed, nbTests, testNb, maxDuration, ((double)proba) / 100);
|
||||
if (mainPause) {
|
||||
int unused;
|
||||
DISPLAY("Press Enter \n");
|
||||
unused = getchar();
|
||||
|
||||
+82
-74
@@ -126,7 +126,7 @@ static U32 g_rand = 1;
|
||||
static U32 g_singleRun = 0;
|
||||
static U32 g_target = 0;
|
||||
static U32 g_noSeed = 0;
|
||||
static ZSTD_parameters g_params = { 0, 0, 0, 0, 0, 0, 0, ZSTD_greedy };
|
||||
static ZSTD_compressionParameters g_params = { 0, 0, 0, 0, 0, 0, ZSTD_greedy };
|
||||
|
||||
void BMK_SetNbIterations(int nbLoops)
|
||||
{
|
||||
@@ -251,7 +251,7 @@ typedef struct
|
||||
static size_t BMK_benchParam(BMK_result_t* resultPtr,
|
||||
const void* srcBuffer, size_t srcSize,
|
||||
ZSTD_CCtx* ctx,
|
||||
const ZSTD_parameters params)
|
||||
const ZSTD_compressionParameters cParams)
|
||||
{
|
||||
const size_t blockSize = g_blockSize ? g_blockSize : srcSize;
|
||||
const U32 nbBlocks = (U32) ((srcSize + (blockSize-1)) / blockSize);
|
||||
@@ -259,13 +259,14 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
|
||||
const size_t maxCompressedSize = (size_t)nbBlocks * ZSTD_compressBound(blockSize);
|
||||
void* const compressedBuffer = malloc(maxCompressedSize);
|
||||
void* const resultBuffer = malloc(srcSize);
|
||||
U32 Wlog = params.windowLog;
|
||||
U32 Clog = params.contentLog;
|
||||
U32 Hlog = params.hashLog;
|
||||
U32 Slog = params.searchLog;
|
||||
U32 Slength = params.searchLength;
|
||||
U32 Tlength = params.targetLength;
|
||||
ZSTD_strategy strat = params.strategy;
|
||||
ZSTD_parameters params;
|
||||
U32 Wlog = cParams.windowLog;
|
||||
U32 Clog = cParams.chainLog;
|
||||
U32 Hlog = cParams.hashLog;
|
||||
U32 Slog = cParams.searchLog;
|
||||
U32 Slength = cParams.searchLength;
|
||||
U32 Tlength = cParams.targetLength;
|
||||
ZSTD_strategy strat = cParams.strategy;
|
||||
char name[30] = { 0 };
|
||||
U64 crcOrig;
|
||||
|
||||
@@ -315,6 +316,8 @@ static size_t BMK_benchParam(BMK_result_t* resultPtr,
|
||||
const int startTime =BMK_GetMilliStart();
|
||||
|
||||
DISPLAY("\r%79s\r", "");
|
||||
params.cParams = cParams;
|
||||
params.fParams.contentSizeFlag = 0;
|
||||
for (loopNb = 1; loopNb <= g_nbIterations; loopNb++) {
|
||||
int nbLoops;
|
||||
int milliTime;
|
||||
@@ -407,11 +410,11 @@ const char* g_stratName[] = { "ZSTD_fast ",
|
||||
"ZSTD_btlazy2",
|
||||
"ZSTD_btopt " };
|
||||
|
||||
static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_parameters params, size_t srcSize)
|
||||
static void BMK_printWinner(FILE* f, U32 cLevel, BMK_result_t result, ZSTD_compressionParameters params, size_t srcSize)
|
||||
{
|
||||
DISPLAY("\r%79s\r", "");
|
||||
fprintf(f," {%3u,%3u,%3u,%3u,%3u,%3u,%3u, %s }, ",
|
||||
0, params.windowLog, params.contentLog, params.hashLog, params.searchLog, params.searchLength,
|
||||
fprintf(f," {%3u,%3u,%3u,%3u,%3u,%3u, %s }, ",
|
||||
params.windowLog, params.chainLog, params.hashLog, params.searchLog, params.searchLength,
|
||||
params.targetLength, g_stratName[(U32)(params.strategy)]);
|
||||
fprintf(f,
|
||||
"/* level %2u */ /* R:%5.3f at %5.1f MB/s - %5.1f MB/s */\n",
|
||||
@@ -423,7 +426,7 @@ static U32 g_cSpeedTarget[NB_LEVELS_TRACKED] = { 0 }; /* NB_LEVELS_TRACKED : c
|
||||
|
||||
typedef struct {
|
||||
BMK_result_t result;
|
||||
ZSTD_parameters params;
|
||||
ZSTD_compressionParameters params;
|
||||
} winnerInfo_t;
|
||||
|
||||
static void BMK_printWinners2(FILE* f, const winnerInfo_t* winners, size_t srcSize)
|
||||
@@ -431,7 +434,7 @@ static void BMK_printWinners2(FILE* f, const winnerInfo_t* winners, size_t srcSi
|
||||
unsigned cLevel;
|
||||
|
||||
fprintf(f, "\n /* Proposed configurations : */ \n");
|
||||
fprintf(f, " /* l, W, C, H, S, L, T, strat */ \n");
|
||||
fprintf(f, " /* W, C, H, S, L, T, strat */ \n");
|
||||
|
||||
for (cLevel=0; cLevel <= ZSTD_maxCLevel(); cLevel++)
|
||||
BMK_printWinner(f, cLevel, winners[cLevel].result, winners[cLevel].params, srcSize);
|
||||
@@ -446,9 +449,9 @@ static void BMK_printWinners(FILE* f, const winnerInfo_t* winners, size_t srcSiz
|
||||
BMK_printWinners2(stdout, winners, srcSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeofCCtx(ZSTD_parameters params); /* hidden interface, declared here */
|
||||
size_t ZSTD_sizeofCCtx(ZSTD_compressionParameters params); /* hidden interface, declared here */
|
||||
|
||||
static int BMK_seed(winnerInfo_t* winners, const ZSTD_parameters params,
|
||||
static int BMK_seed(winnerInfo_t* winners, const ZSTD_compressionParameters params,
|
||||
const void* srcBuffer, size_t srcSize,
|
||||
ZSTD_CCtx* ctx)
|
||||
{
|
||||
@@ -541,55 +544,61 @@ static int BMK_seed(winnerInfo_t* winners, const ZSTD_parameters params,
|
||||
|
||||
|
||||
/* nullified useless params, to ensure count stats */
|
||||
static ZSTD_parameters* sanitizeParams(ZSTD_parameters params)
|
||||
static ZSTD_compressionParameters* sanitizeParams(ZSTD_compressionParameters params)
|
||||
{
|
||||
g_params = params;
|
||||
if (params.strategy == ZSTD_fast)
|
||||
g_params.contentLog = 0, g_params.searchLog = 0;
|
||||
g_params.chainLog = 0, g_params.searchLog = 0;
|
||||
if (params.strategy != ZSTD_btopt )
|
||||
g_params.targetLength = 0;
|
||||
return &g_params;
|
||||
}
|
||||
|
||||
|
||||
static void paramVariation(ZSTD_parameters* p)
|
||||
static void paramVariation(ZSTD_compressionParameters* ptr)
|
||||
{
|
||||
U32 nbChanges = (FUZ_rand(&g_rand) & 3) + 1;
|
||||
for (; nbChanges; nbChanges--) {
|
||||
const U32 changeID = FUZ_rand(&g_rand) % 14;
|
||||
switch(changeID)
|
||||
{
|
||||
case 0:
|
||||
p->contentLog++; break;
|
||||
case 1:
|
||||
p->contentLog--; break;
|
||||
case 2:
|
||||
p->hashLog++; break;
|
||||
case 3:
|
||||
p->hashLog--; break;
|
||||
case 4:
|
||||
p->searchLog++; break;
|
||||
case 5:
|
||||
p->searchLog--; break;
|
||||
case 6:
|
||||
p->windowLog++; break;
|
||||
case 7:
|
||||
p->windowLog--; break;
|
||||
case 8:
|
||||
p->searchLength++; break;
|
||||
case 9:
|
||||
p->searchLength--; break;
|
||||
case 10:
|
||||
p->strategy = (ZSTD_strategy)(((U32)p->strategy)+1); break;
|
||||
case 11:
|
||||
p->strategy = (ZSTD_strategy)(((U32)p->strategy)-1); break;
|
||||
case 12:
|
||||
p->targetLength *= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
|
||||
case 13:
|
||||
p->targetLength /= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
|
||||
ZSTD_compressionParameters p;
|
||||
U32 validated = 0;
|
||||
while (!validated) {
|
||||
U32 nbChanges = (FUZ_rand(&g_rand) & 3) + 1;
|
||||
p = *ptr;
|
||||
for ( ; nbChanges ; nbChanges--) {
|
||||
const U32 changeID = FUZ_rand(&g_rand) % 14;
|
||||
switch(changeID)
|
||||
{
|
||||
case 0:
|
||||
p.chainLog++; break;
|
||||
case 1:
|
||||
p.chainLog--; break;
|
||||
case 2:
|
||||
p.hashLog++; break;
|
||||
case 3:
|
||||
p.hashLog--; break;
|
||||
case 4:
|
||||
p.searchLog++; break;
|
||||
case 5:
|
||||
p.searchLog--; break;
|
||||
case 6:
|
||||
p.windowLog++; break;
|
||||
case 7:
|
||||
p.windowLog--; break;
|
||||
case 8:
|
||||
p.searchLength++; break;
|
||||
case 9:
|
||||
p.searchLength--; break;
|
||||
case 10:
|
||||
p.strategy = (ZSTD_strategy)(((U32)p.strategy)+1); break;
|
||||
case 11:
|
||||
p.strategy = (ZSTD_strategy)(((U32)p.strategy)-1); break;
|
||||
case 12:
|
||||
p.targetLength *= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
|
||||
case 13:
|
||||
p.targetLength /= 1 + ((double)(FUZ_rand(&g_rand)&255)) / 256.; break;
|
||||
}
|
||||
}
|
||||
validated = !ZSTD_isError(ZSTD_checkCParams(p));
|
||||
}
|
||||
ZSTD_validateParams(p);
|
||||
*ptr = p;
|
||||
}
|
||||
|
||||
|
||||
@@ -605,7 +614,7 @@ static BYTE g_alreadyTested[PARAMTABLESIZE] = {0}; /* init to zero */
|
||||
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
|
||||
|
||||
static void playAround(FILE* f, winnerInfo_t* winners,
|
||||
ZSTD_parameters params,
|
||||
ZSTD_compressionParameters params,
|
||||
const void* srcBuffer, size_t srcSize,
|
||||
ZSTD_CCtx* ctx)
|
||||
{
|
||||
@@ -613,7 +622,7 @@ static void playAround(FILE* f, winnerInfo_t* winners,
|
||||
const int startTime = BMK_GetMilliStart();
|
||||
|
||||
while (BMK_GetMilliSpan(startTime) < g_maxVariationTime) {
|
||||
ZSTD_parameters p = params;
|
||||
ZSTD_compressionParameters p = params;
|
||||
|
||||
if (nbVariations++ > g_maxNbVariations) break;
|
||||
paramVariation(&p);
|
||||
@@ -634,19 +643,21 @@ static void playAround(FILE* f, winnerInfo_t* winners,
|
||||
}
|
||||
|
||||
|
||||
static void potentialRandomParams(ZSTD_parameters* p, U32 inverseChance)
|
||||
static void potentialRandomParams(ZSTD_compressionParameters* p, U32 inverseChance)
|
||||
{
|
||||
U32 chance = (FUZ_rand(&g_rand) % (inverseChance+1));
|
||||
if (!chance) {
|
||||
U32 validated = 0;
|
||||
if (!chance)
|
||||
while (!validated) {
|
||||
/* totally random entry */
|
||||
p->contentLog = FUZ_rand(&g_rand) % (ZSTD_CONTENTLOG_MAX+1 - ZSTD_CONTENTLOG_MIN) + ZSTD_CONTENTLOG_MIN;
|
||||
p->chainLog = FUZ_rand(&g_rand) % (ZSTD_CHAINLOG_MAX+1 - ZSTD_CHAINLOG_MIN) + ZSTD_CHAINLOG_MIN;
|
||||
p->hashLog = FUZ_rand(&g_rand) % (ZSTD_HASHLOG_MAX+1 - ZSTD_HASHLOG_MIN) + ZSTD_HASHLOG_MIN;
|
||||
p->searchLog = FUZ_rand(&g_rand) % (ZSTD_SEARCHLOG_MAX+1 - ZSTD_SEARCHLOG_MIN) + ZSTD_SEARCHLOG_MIN;
|
||||
p->windowLog = FUZ_rand(&g_rand) % (ZSTD_WINDOWLOG_MAX+1 - ZSTD_WINDOWLOG_MIN) + ZSTD_WINDOWLOG_MIN;
|
||||
p->searchLength=FUZ_rand(&g_rand) % (ZSTD_SEARCHLENGTH_MAX+1 - ZSTD_SEARCHLENGTH_MIN) + ZSTD_SEARCHLENGTH_MIN;
|
||||
p->targetLength=FUZ_rand(&g_rand) % (ZSTD_TARGETLENGTH_MAX+1 - ZSTD_TARGETLENGTH_MIN) + ZSTD_TARGETLENGTH_MIN;
|
||||
p->strategy = (ZSTD_strategy) (FUZ_rand(&g_rand) % (ZSTD_btopt +1));
|
||||
ZSTD_validateParams(p);
|
||||
validated = !ZSTD_isError(ZSTD_checkCParams(*p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,10 +669,9 @@ static void BMK_selectRandomStart(
|
||||
U32 id = (FUZ_rand(&g_rand) % (ZSTD_maxCLevel()+1));
|
||||
if ((id==0) || (winners[id].params.windowLog==0)) {
|
||||
/* totally random entry */
|
||||
ZSTD_parameters p;
|
||||
ZSTD_compressionParameters p;
|
||||
potentialRandomParams(&p, 1);
|
||||
p.srcSize = srcSize;
|
||||
ZSTD_validateParams(&p);
|
||||
ZSTD_adjustCParams(&p, srcSize, 0);
|
||||
playAround(f, winners, p, srcBuffer, srcSize, ctx);
|
||||
}
|
||||
else
|
||||
@@ -672,7 +682,7 @@ static void BMK_selectRandomStart(
|
||||
static void BMK_benchMem(void* srcBuffer, size_t srcSize)
|
||||
{
|
||||
ZSTD_CCtx* ctx = ZSTD_createCCtx();
|
||||
ZSTD_parameters params;
|
||||
ZSTD_compressionParameters params;
|
||||
winnerInfo_t winners[NB_LEVELS_TRACKED];
|
||||
int i;
|
||||
unsigned u;
|
||||
@@ -682,8 +692,7 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize)
|
||||
|
||||
if (g_singleRun) {
|
||||
BMK_result_t testResult;
|
||||
g_params.srcSize = blockSize;
|
||||
ZSTD_validateParams(&g_params);
|
||||
ZSTD_adjustCParams(&g_params, srcSize, 0);
|
||||
BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, g_params);
|
||||
DISPLAY("\n");
|
||||
return;
|
||||
@@ -699,7 +708,7 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize)
|
||||
else {
|
||||
/* baseline config for level 1 */
|
||||
BMK_result_t testResult;
|
||||
params = ZSTD_getParams(1, blockSize);
|
||||
params = ZSTD_getCParams(1, blockSize, 0);
|
||||
BMK_benchParam(&testResult, srcBuffer, srcSize, ctx, params);
|
||||
g_cSpeedTarget[1] = (testResult.cSpeed * 31) >> 5;
|
||||
}
|
||||
@@ -712,8 +721,7 @@ static void BMK_benchMem(void* srcBuffer, size_t srcSize)
|
||||
{
|
||||
const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();
|
||||
for (i=1; i<=maxSeeds; i++) {
|
||||
params = ZSTD_getParams(i, blockSize);
|
||||
ZSTD_validateParams(¶ms);
|
||||
params = ZSTD_getCParams(i, blockSize, 0);
|
||||
BMK_seed(winners, params, srcBuffer, srcSize, ctx);
|
||||
}
|
||||
}
|
||||
@@ -864,7 +872,7 @@ int optimizeForSize(char* inFileName)
|
||||
|
||||
{
|
||||
ZSTD_CCtx* ctx = ZSTD_createCCtx();
|
||||
ZSTD_parameters params;
|
||||
ZSTD_compressionParameters params;
|
||||
winnerInfo_t winner;
|
||||
BMK_result_t candidate;
|
||||
const size_t blockSize = g_blockSize ? g_blockSize : benchedSize;
|
||||
@@ -878,7 +886,7 @@ int optimizeForSize(char* inFileName)
|
||||
{
|
||||
const int maxSeeds = g_noSeed ? 1 : ZSTD_maxCLevel();
|
||||
for (i=1; i<=maxSeeds; i++) {
|
||||
params = ZSTD_getParams(i, blockSize);
|
||||
params = ZSTD_getCParams(i, blockSize, 0);
|
||||
BMK_benchParam(&candidate, origBuff, benchedSize, ctx, params);
|
||||
if ( (candidate.cSize < winner.result.cSize)
|
||||
||((candidate.cSize == winner.result.cSize) && (candidate.cSpeed > winner.result.cSpeed)) )
|
||||
@@ -1028,7 +1036,7 @@ int main(int argc, char** argv)
|
||||
case 'S':
|
||||
g_singleRun = 1;
|
||||
argument++;
|
||||
g_params = ZSTD_getParams(2, g_blockSize);
|
||||
g_params = ZSTD_getCParams(2, g_blockSize, 0);
|
||||
for ( ; ; ) {
|
||||
switch(*argument)
|
||||
{
|
||||
@@ -1039,10 +1047,10 @@ int main(int argc, char** argv)
|
||||
g_params.windowLog *= 10, g_params.windowLog += *argument++ - '0';
|
||||
continue;
|
||||
case 'c':
|
||||
g_params.contentLog = 0;
|
||||
g_params.chainLog = 0;
|
||||
argument++;
|
||||
while ((*argument>= '0') && (*argument<='9'))
|
||||
g_params.contentLog *= 10, g_params.contentLog += *argument++ - '0';
|
||||
g_params.chainLog *= 10, g_params.chainLog += *argument++ - '0';
|
||||
continue;
|
||||
case 'h':
|
||||
g_params.hashLog = 0;
|
||||
@@ -1079,7 +1087,7 @@ int main(int argc, char** argv)
|
||||
argument++;
|
||||
while ((*argument>= '0') && (*argument<='9'))
|
||||
cLevel *= 10, cLevel += *argument++ - '0';
|
||||
g_params = ZSTD_getParams(cLevel, g_blockSize);
|
||||
g_params = ZSTD_getCParams(cLevel, g_blockSize, 0);
|
||||
continue;
|
||||
}
|
||||
default : ;
|
||||
|
||||
+13
-2
@@ -25,7 +25,9 @@ roundTripTest() {
|
||||
|
||||
echo "\n**** simple tests **** "
|
||||
./datagen > tmp
|
||||
$ZSTD tmp
|
||||
echo -n "trivial compression : "
|
||||
$ZSTD -f tmp
|
||||
echo "OK"
|
||||
$ZSTD -99 tmp && die "too large compression level undetected"
|
||||
$ZSTD tmp -c > tmpCompressed
|
||||
$ZSTD tmp --stdout > tmpCompressed
|
||||
@@ -71,6 +73,11 @@ echo "\n**** dictionary tests **** "
|
||||
./datagen -g1M | md5sum > tmp1
|
||||
./datagen -g1M | $ZSTD -D tmpDict | $ZSTD -D tmpDict -dvq | md5sum > tmp2
|
||||
diff -q tmp1 tmp2
|
||||
$ZSTD --train *.c *.h -o tmpDict
|
||||
$ZSTD xxhash.c -D tmpDict -of tmp
|
||||
$ZSTD -d tmp -D tmpDict -of result
|
||||
diff xxhash.c result
|
||||
|
||||
|
||||
echo "\n**** multiple files tests **** "
|
||||
|
||||
@@ -106,6 +113,10 @@ $ZSTD -t * && die "bad files not detected !"
|
||||
echo "\n**** zstd round-trip tests **** "
|
||||
|
||||
roundTripTest
|
||||
roundTripTest -g15K # TableID==3
|
||||
roundTripTest -g127K # TableID==2
|
||||
roundTripTest -g255K # TableID==1
|
||||
roundTripTest -g513K # TableID==0
|
||||
roundTripTest -g512K 6 # greedy, hash chain
|
||||
roundTripTest -g512K 16 # btlazy2
|
||||
roundTripTest -g512K 19 # btopt
|
||||
@@ -143,7 +154,7 @@ roundTripTest -g50000000 -P94 18
|
||||
roundTripTest -g50000000 -P94 19
|
||||
|
||||
roundTripTest -g99000000 -P99 20
|
||||
roundTripTest -g6000000000 -P99 q
|
||||
roundTripTest -g6000000000 -P99 1
|
||||
|
||||
rm tmp*
|
||||
|
||||
|
||||
+160
-195
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Fuzzer test tool for zstd_buffered
|
||||
Copyright (C) Yann Collet 2105
|
||||
Copyright (C) Yann Collet 2015-2016
|
||||
|
||||
GPL v2 License
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
You can contact the author at :
|
||||
- ZSTD source repository : https://github.com/Cyan4973/zstd
|
||||
- ZSTD public forum : https://groups.google.com/forum/#!forum/lz4c
|
||||
- ZSTD homepage : https://www.zstd.net/
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Compiler specific
|
||||
**************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
@@ -33,7 +32,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include <stdlib.h> /* free */
|
||||
@@ -42,13 +41,13 @@
|
||||
#include <string.h> /* strcmp */
|
||||
#include "mem.h"
|
||||
#include "zbuff.h"
|
||||
#include "zstd.h" /* ZSTD_compressBound() */
|
||||
#include "zstd_static.h" /* ZSTD_compressBound(), ZSTD_maxCLevel() */
|
||||
#include "datagen.h" /* RDG_genBuffer */
|
||||
#include "xxhash.h" /* XXH64 */
|
||||
|
||||
|
||||
/**************************************
|
||||
Constants
|
||||
/*-************************************
|
||||
* Constants
|
||||
**************************************/
|
||||
#ifndef ZSTD_VERSION
|
||||
# define ZSTD_VERSION ""
|
||||
@@ -66,7 +65,7 @@ static const U32 prime2 = 2246822519U;
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
/*-************************************
|
||||
* Display Macros
|
||||
**************************************/
|
||||
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
|
||||
@@ -83,7 +82,7 @@ static U32 g_displayTime = 0;
|
||||
static U32 g_testTime = 0;
|
||||
|
||||
|
||||
/*********************************************************
|
||||
/*-*******************************************************
|
||||
* Fuzzer functions
|
||||
*********************************************************/
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
@@ -107,15 +106,17 @@ static U32 FUZ_GetMilliSpan(U32 nTimeStart)
|
||||
return nSpan;
|
||||
}
|
||||
|
||||
|
||||
/*! FUZ_rand() :
|
||||
@return : a 27 bits random value, from a 32-bits `seed`.
|
||||
`seed` is also modified */
|
||||
# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
unsigned int FUZ_rand(unsigned int* src)
|
||||
unsigned int FUZ_rand(unsigned int* seedPtr)
|
||||
{
|
||||
U32 rand32 = *src;
|
||||
U32 rand32 = *seedPtr;
|
||||
rand32 *= prime1;
|
||||
rand32 += prime2;
|
||||
rand32 = FUZ_rotl32(rand32, 13);
|
||||
*src = rand32;
|
||||
*seedPtr = rand32;
|
||||
return rand32 >> 5;
|
||||
}
|
||||
|
||||
@@ -133,12 +134,12 @@ static unsigned FUZ_highbit32(U32 v32)
|
||||
static int basicUnitTests(U32 seed, double compressibility)
|
||||
{
|
||||
int testResult = 0;
|
||||
void* CNBuffer;
|
||||
size_t CNBufferSize = COMPRESSIBLE_NOISE_LENGTH;
|
||||
void* compressedBuffer;
|
||||
size_t compressedBufferSize = ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH);
|
||||
void* decodedBuffer;
|
||||
size_t decodedBufferSize = CNBufferSize;
|
||||
void* CNBuffer = malloc(CNBufferSize);
|
||||
size_t const compressedBufferSize = ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH);
|
||||
void* compressedBuffer = malloc(compressedBufferSize);
|
||||
size_t const decodedBufferSize = CNBufferSize;
|
||||
void* decodedBuffer = malloc(decodedBufferSize);
|
||||
U32 randState = seed;
|
||||
size_t result, cSize, readSize, genSize;
|
||||
U32 testNb=0;
|
||||
@@ -146,11 +147,7 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
ZBUFF_DCtx* zd = ZBUFF_createDCtx();
|
||||
|
||||
/* Create compressible test buffer */
|
||||
CNBuffer = malloc(CNBufferSize);
|
||||
compressedBuffer = malloc(compressedBufferSize);
|
||||
decodedBuffer = malloc(decodedBufferSize);
|
||||
if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd)
|
||||
{
|
||||
if (!CNBuffer || !compressedBuffer || !decodedBuffer || !zc || !zd) {
|
||||
DISPLAY("Not enough memory, aborting\n");
|
||||
goto _output_error;
|
||||
}
|
||||
@@ -183,11 +180,9 @@ static int basicUnitTests(U32 seed, double compressibility)
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
|
||||
/* check regenerated data is byte exact */
|
||||
{
|
||||
size_t i;
|
||||
{ size_t i;
|
||||
DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
|
||||
for (i=0; i<CNBufferSize; i++)
|
||||
{
|
||||
for (i=0; i<CNBufferSize; i++) {
|
||||
if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
|
||||
}
|
||||
DISPLAYLEVEL(4, "OK \n");
|
||||
@@ -213,8 +208,7 @@ static size_t findDiff(const void* buf1, const void* buf2, size_t max)
|
||||
const BYTE* b1 = (const BYTE*)buf1;
|
||||
const BYTE* b2 = (const BYTE*)buf2;
|
||||
size_t i;
|
||||
for (i=0; i<max; i++)
|
||||
{
|
||||
for (i=0; i<max; i++) {
|
||||
if (b1[i] != b2[i]) break;
|
||||
}
|
||||
return i;
|
||||
@@ -225,28 +219,39 @@ static size_t findDiff(const void* buf1, const void* buf2, size_t max)
|
||||
#define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
|
||||
DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
|
||||
|
||||
static const U32 maxSrcLog = 24;
|
||||
static const U32 maxSampleLog = 19;
|
||||
|
||||
int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
|
||||
static size_t FUZ_rLogLength(U32* seed, U32 logLength)
|
||||
{
|
||||
size_t const lengthMask = ((size_t)1 << logLength) - 1;
|
||||
return (lengthMask+1) + (FUZ_rand(seed) & lengthMask);
|
||||
}
|
||||
|
||||
static size_t FUZ_randomLength(U32* seed, U32 maxLog)
|
||||
{
|
||||
U32 const logLength = FUZ_rand(seed) % maxLog;
|
||||
return FUZ_rLogLength(seed, logLength);
|
||||
}
|
||||
|
||||
static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
|
||||
{
|
||||
static const U32 maxSrcLog = 24;
|
||||
static const U32 maxSampleLog = 19;
|
||||
BYTE* cNoiseBuffer[5];
|
||||
BYTE* srcBuffer;
|
||||
size_t srcBufferSize = (size_t)1<<maxSrcLog;
|
||||
BYTE* copyBuffer;
|
||||
size_t copyBufferSize = srcBufferSize + (1<<maxSampleLog);
|
||||
size_t copyBufferSize= srcBufferSize + (1<<maxSampleLog);
|
||||
BYTE* cBuffer;
|
||||
size_t cBufferSize = ZSTD_compressBound(srcBufferSize);
|
||||
BYTE* dstBuffer;
|
||||
size_t dstBufferSize = srcBufferSize;
|
||||
U32 result = 0;
|
||||
U32 testNb = 0;
|
||||
U32 coreSeed = seed, lseed = 0;
|
||||
U32 coreSeed = seed;
|
||||
ZBUFF_CCtx* zc;
|
||||
ZBUFF_DCtx* zd;
|
||||
U32 startTime = FUZ_GetMilliStart();
|
||||
|
||||
/* allocation */
|
||||
/* allocations */
|
||||
zc = ZBUFF_createCCtx();
|
||||
zd = ZBUFF_createDCtx();
|
||||
cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
|
||||
@@ -267,172 +272,144 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit
|
||||
RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
|
||||
RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
|
||||
RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
|
||||
srcBuffer = cNoiseBuffer[2];
|
||||
memset(copyBuffer, 0x65, copyBufferSize);
|
||||
memcpy(copyBuffer, srcBuffer, MIN(copyBufferSize,srcBufferSize)); /* make copyBuffer considered initialized */
|
||||
memset(copyBuffer, 0x65, copyBufferSize); /* make copyBuffer considered initialized */
|
||||
|
||||
/* catch up testNb */
|
||||
for (testNb=1; testNb < startTest; testNb++)
|
||||
FUZ_rand(&coreSeed);
|
||||
|
||||
/* test loop */
|
||||
for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < g_testTime); testNb++ )
|
||||
{
|
||||
size_t sampleSize, sampleStart;
|
||||
for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < g_testTime) ; testNb++ ) {
|
||||
U32 lseed;
|
||||
const BYTE* srcBuffer;
|
||||
const BYTE* dict;
|
||||
size_t cSize, dictSize;
|
||||
size_t maxTestSize, totalTestSize, readSize, totalCSize, genSize, totalGenSize;
|
||||
size_t maxTestSize, dictSize;
|
||||
size_t cSize, totalTestSize, totalCSize, totalGenSize;
|
||||
size_t errorCode;
|
||||
U32 sampleSizeLog, buffNb, n, nbChunks;
|
||||
U32 n, nbChunks;
|
||||
XXH64_CREATESTATE_STATIC(xxh64);
|
||||
U64 crcOrig, crcDest;
|
||||
U64 crcOrig;
|
||||
|
||||
/* init */
|
||||
DISPLAYUPDATE(2, "\r%6u", testNb);
|
||||
if (nbTests >= testNb) DISPLAYUPDATE(2, "/%6u ", nbTests);
|
||||
FUZ_rand(&coreSeed);
|
||||
lseed = coreSeed ^ prime1;
|
||||
buffNb = FUZ_rand(&lseed) & 127;
|
||||
if (buffNb & 7) buffNb=2; /* select buffer */
|
||||
else
|
||||
{
|
||||
buffNb >>= 3;
|
||||
if (buffNb & 7)
|
||||
{
|
||||
const U32 tnb[2] = { 1, 3 };
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
const U32 tnb[2] = { 0, 4 };
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
}
|
||||
}
|
||||
srcBuffer = cNoiseBuffer[buffNb];
|
||||
|
||||
/* Multi - segments compression test */
|
||||
/* state total reset */
|
||||
/* some problems only happen when states are re-used in a specific order */
|
||||
if ((FUZ_rand(&lseed) & 0xFF) == 131) { ZBUFF_freeCCtx(zc); zc = ZBUFF_createCCtx(); }
|
||||
if ((FUZ_rand(&lseed) & 0xFF) == 132) { ZBUFF_freeDCtx(zd); zd = ZBUFF_createDCtx(); }
|
||||
|
||||
/* srcBuffer selection [0-4] */
|
||||
{ U32 buffNb = FUZ_rand(&lseed) & 0x7F;
|
||||
if (buffNb & 7) buffNb=2; /* most common : compressible (P) */
|
||||
else {
|
||||
buffNb >>= 3;
|
||||
if (buffNb & 7) {
|
||||
const U32 tnb[2] = { 1, 3 }; /* barely/highly compressible */
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
} else {
|
||||
const U32 tnb[2] = { 0, 4 }; /* not compressible / sparse */
|
||||
buffNb = tnb[buffNb >> 3];
|
||||
} }
|
||||
srcBuffer = cNoiseBuffer[buffNb];
|
||||
}
|
||||
|
||||
/* compression init */
|
||||
{ U32 const testLog = FUZ_rand(&lseed) % maxSrcLog;
|
||||
U32 const cLevel = (FUZ_rand(&lseed) % (ZSTD_maxCLevel() - (testLog/3))) + 1;
|
||||
maxTestSize = FUZ_rLogLength(&lseed, testLog);
|
||||
/* random dictionary selection */
|
||||
{ size_t dictStart;
|
||||
dictSize = (FUZ_rand(&lseed)==1) ? FUZ_randomLength(&lseed, maxSampleLog) : 0;
|
||||
dictStart = FUZ_rand(&lseed) % (srcBufferSize - dictSize);
|
||||
dict = srcBuffer + dictStart;
|
||||
}
|
||||
{ size_t const initError = ZBUFF_compressInitDictionary(zc, dict, dictSize, cLevel);
|
||||
CHECK (ZBUFF_isError(initError),"init error : %s", ZBUFF_getErrorName(initError));
|
||||
} }
|
||||
|
||||
/* multi-segments compression test */
|
||||
XXH64_reset(xxh64, 0);
|
||||
nbChunks = (FUZ_rand(&lseed) & 127) + 2;
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSrcLog;
|
||||
maxTestSize = (size_t)1 << sampleSizeLog;
|
||||
maxTestSize += FUZ_rand(&lseed) & (maxTestSize-1);
|
||||
nbChunks = (FUZ_rand(&lseed) & 127) + 2;
|
||||
for (n=0, cSize=0, totalTestSize=0 ; (n<nbChunks) && (totalTestSize < maxTestSize) ; n++) {
|
||||
/* compress random chunk into random size dst buffer */
|
||||
{ size_t readChunkSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||
size_t const srcStart = FUZ_rand(&lseed) % (srcBufferSize - readChunkSize);
|
||||
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
|
||||
dict = srcBuffer + sampleStart;
|
||||
dictSize = sampleSize;
|
||||
ZBUFF_compressInitDictionary(zc, dict, dictSize, (FUZ_rand(&lseed) % (20 - (sampleSizeLog/3))) + 1);
|
||||
size_t const compressionError = ZBUFF_compressContinue(zc, cBuffer+cSize, &dstBuffSize, srcBuffer+srcStart, &readChunkSize);
|
||||
CHECK (ZBUFF_isError(compressionError), "compression error : %s", ZBUFF_getErrorName(compressionError));
|
||||
|
||||
totalTestSize = 0;
|
||||
cSize = 0;
|
||||
for (n=0; n<nbChunks; n++)
|
||||
{
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
|
||||
readSize = sampleSize;
|
||||
|
||||
/* random size output buffer */
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
genSize = MIN (cBufferSize - cSize, sampleSize);
|
||||
|
||||
errorCode = ZBUFF_compressContinue(zc, cBuffer+cSize, &genSize, srcBuffer+sampleStart, &readSize);
|
||||
CHECK (ZBUFF_isError(errorCode), "compression error : %s", ZBUFF_getErrorName(errorCode));
|
||||
|
||||
XXH64_update(xxh64, srcBuffer+sampleStart, readSize);
|
||||
memcpy(copyBuffer+totalTestSize, srcBuffer+sampleStart, readSize);
|
||||
cSize += genSize;
|
||||
totalTestSize += readSize;
|
||||
|
||||
if ((FUZ_rand(&lseed) & 15) == 0)
|
||||
{
|
||||
/* add a few random flushes operations, to mess around */
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
genSize = MIN (cBufferSize - cSize, sampleSize);
|
||||
errorCode = ZBUFF_compressFlush(zc, cBuffer+cSize, &genSize);
|
||||
CHECK (ZBUFF_isError(errorCode), "flush error : %s", ZBUFF_getErrorName(errorCode));
|
||||
cSize += genSize;
|
||||
XXH64_update(xxh64, srcBuffer+srcStart, readChunkSize);
|
||||
memcpy(copyBuffer+totalTestSize, srcBuffer+srcStart, readChunkSize);
|
||||
cSize += dstBuffSize;
|
||||
totalTestSize += readChunkSize;
|
||||
}
|
||||
|
||||
if (totalTestSize > maxTestSize) break;
|
||||
/* random flush operation, to mess around */
|
||||
if ((FUZ_rand(&lseed) & 15) == 0) {
|
||||
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||
size_t const flushError = ZBUFF_compressFlush(zc, cBuffer+cSize, &dstBuffSize);
|
||||
CHECK (ZBUFF_isError(flushError), "flush error : %s", ZBUFF_getErrorName(flushError));
|
||||
cSize += dstBuffSize;
|
||||
} }
|
||||
|
||||
/* final frame epilogue */
|
||||
{ size_t dstBuffSize = cBufferSize - cSize;
|
||||
size_t const flushError = ZBUFF_compressEnd(zc, cBuffer+cSize, &dstBuffSize);
|
||||
CHECK (ZBUFF_isError(flushError), "flush error : %s", ZBUFF_getErrorName(flushError));
|
||||
cSize += dstBuffSize;
|
||||
}
|
||||
genSize = cBufferSize - cSize;
|
||||
errorCode = ZBUFF_compressEnd(zc, cBuffer+cSize, &genSize);
|
||||
CHECK (ZBUFF_isError(errorCode), "compression error : %s", ZBUFF_getErrorName(errorCode));
|
||||
CHECK (errorCode != 0, "frame epilogue not fully consumed");
|
||||
cSize += genSize;
|
||||
crcOrig = XXH64_digest(xxh64);
|
||||
|
||||
/* multi - fragments decompression test */
|
||||
ZBUFF_decompressInitDictionary(zd, dict, dictSize);
|
||||
totalCSize = 0;
|
||||
totalGenSize = 0;
|
||||
while (totalCSize < cSize)
|
||||
{
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
readSize = sampleSize;
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
genSize = MIN(sampleSize, dstBufferSize - totalGenSize);
|
||||
errorCode = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &genSize, cBuffer+totalCSize, &readSize);
|
||||
CHECK (ZBUFF_isError(errorCode), "decompression error : %s", ZBUFF_getErrorName(errorCode));
|
||||
totalGenSize += genSize;
|
||||
totalCSize += readSize;
|
||||
for (totalCSize = 0, totalGenSize = 0 ; totalCSize < cSize ; ) {
|
||||
size_t readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
|
||||
size_t const decompressError = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &dstBuffSize, cBuffer+totalCSize, &readCSrcSize);
|
||||
CHECK (ZBUFF_isError(decompressError), "decompression error : %s", ZBUFF_getErrorName(decompressError));
|
||||
totalGenSize += dstBuffSize;
|
||||
totalCSize += readCSrcSize;
|
||||
errorCode = decompressError; /* needed for != 0 last test */
|
||||
}
|
||||
CHECK (errorCode != 0, "frame not fully decoded");
|
||||
CHECK (totalGenSize != totalTestSize, "decompressed data : wrong size")
|
||||
CHECK (totalCSize != cSize, "compressed data should be fully read")
|
||||
crcDest = XXH64(dstBuffer, totalTestSize, 0);
|
||||
if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);
|
||||
CHECK (crcDest!=crcOrig, "decompressed data corrupted");
|
||||
{ U64 const crcDest = XXH64(dstBuffer, totalTestSize, 0);
|
||||
if (crcDest!=crcOrig) findDiff(copyBuffer, dstBuffer, totalTestSize);
|
||||
CHECK (crcDest!=crcOrig, "decompressed data corrupted"); }
|
||||
|
||||
/*===== noisy/erroneous src decompression test =====*/
|
||||
|
||||
/* noisy/erroneous src decompression test */
|
||||
/* add some noise */
|
||||
nbChunks = (FUZ_rand(&lseed) & 7) + 2;
|
||||
for (n=0; n<nbChunks; n++)
|
||||
{
|
||||
size_t cStart;
|
||||
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
if (sampleSize > cSize/3) sampleSize = cSize/3;
|
||||
sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
|
||||
cStart = FUZ_rand(&lseed) % (cSize - sampleSize);
|
||||
|
||||
memcpy(cBuffer+cStart, srcBuffer+sampleStart, sampleSize);
|
||||
}
|
||||
{ U32 const nbNoiseChunks = (FUZ_rand(&lseed) & 7) + 2;
|
||||
U32 nn; for (nn=0; nn<nbNoiseChunks; nn++) {
|
||||
size_t const randomNoiseSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t const noiseSize = MIN((cSize/3) , randomNoiseSize);
|
||||
size_t const noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseSize);
|
||||
size_t const cStart = FUZ_rand(&lseed) % (cSize - noiseSize);
|
||||
memcpy(cBuffer+cStart, srcBuffer+noiseStart, noiseSize);
|
||||
} }
|
||||
|
||||
/* try decompression on noisy data */
|
||||
ZBUFF_decompressInit(zd);
|
||||
totalCSize = 0;
|
||||
totalGenSize = 0;
|
||||
while ( (totalCSize < cSize) && (totalGenSize < dstBufferSize) )
|
||||
{
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
readSize = sampleSize;
|
||||
sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
|
||||
sampleSize = (size_t)1 << sampleSizeLog;
|
||||
sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
|
||||
genSize = MIN(sampleSize, dstBufferSize - totalGenSize);
|
||||
errorCode = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &genSize, cBuffer+totalCSize, &readSize);
|
||||
if (ZBUFF_isError(errorCode)) break; /* error correctly detected */
|
||||
totalGenSize += genSize;
|
||||
totalCSize += readSize;
|
||||
}
|
||||
}
|
||||
while ( (totalCSize < cSize) && (totalGenSize < dstBufferSize) ) {
|
||||
size_t readCSrcSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t const randomDstSize = FUZ_randomLength(&lseed, maxSampleLog);
|
||||
size_t dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
|
||||
size_t const decompressError = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &dstBuffSize, cBuffer+totalCSize, &readCSrcSize);
|
||||
if (ZBUFF_isError(decompressError)) break; /* error correctly detected */
|
||||
totalGenSize += dstBuffSize;
|
||||
totalCSize += readCSrcSize;
|
||||
} }
|
||||
DISPLAY("\r%u fuzzer tests completed \n", testNb);
|
||||
|
||||
_cleanup:
|
||||
@@ -454,10 +431,10 @@ _output_error:
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************
|
||||
/*-*******************************************************
|
||||
* Command line
|
||||
*********************************************************/
|
||||
int FUZ_usage(char* programName)
|
||||
int FUZ_usage(const char* programName)
|
||||
{
|
||||
DISPLAY( "Usage :\n");
|
||||
DISPLAY( " %s [args]\n", programName);
|
||||
@@ -474,7 +451,7 @@ int FUZ_usage(char* programName)
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
U32 seed=0;
|
||||
int seedset=0;
|
||||
@@ -484,23 +461,18 @@ int main(int argc, char** argv)
|
||||
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
|
||||
int result=0;
|
||||
U32 mainPause = 0;
|
||||
char* programName;
|
||||
const char* programName = argv[0];
|
||||
|
||||
/* Check command line */
|
||||
programName = argv[0];
|
||||
for(argNb=1; argNb<argc; argNb++)
|
||||
{
|
||||
char* argument = argv[argNb];
|
||||
|
||||
for(argNb=1; argNb<argc; argNb++) {
|
||||
const char* argument = argv[argNb];
|
||||
if(!argument) continue; /* Protection if argument empty */
|
||||
|
||||
/* Handle commands. Aggregated commands are allowed */
|
||||
if (argument[0]=='-')
|
||||
{
|
||||
/* Parsing commands. Aggregated commands are allowed */
|
||||
if (argument[0]=='-') {
|
||||
argument++;
|
||||
|
||||
while (*argument!=0)
|
||||
{
|
||||
while (*argument!=0) {
|
||||
switch(*argument)
|
||||
{
|
||||
case 'h':
|
||||
@@ -521,8 +493,7 @@ int main(int argc, char** argv)
|
||||
case 'i':
|
||||
argument++;
|
||||
nbTests=0; g_testTime=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
nbTests *= 10;
|
||||
nbTests += *argument - '0';
|
||||
argument++;
|
||||
@@ -532,8 +503,7 @@ int main(int argc, char** argv)
|
||||
case 'T':
|
||||
argument++;
|
||||
nbTests=0; g_testTime=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
g_testTime *= 10;
|
||||
g_testTime += *argument - '0';
|
||||
argument++;
|
||||
@@ -547,8 +517,7 @@ int main(int argc, char** argv)
|
||||
argument++;
|
||||
seed=0;
|
||||
seedset=1;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
seed *= 10;
|
||||
seed += *argument - '0';
|
||||
argument++;
|
||||
@@ -558,8 +527,7 @@ int main(int argc, char** argv)
|
||||
case 't':
|
||||
argument++;
|
||||
testNb=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
testNb *= 10;
|
||||
testNb += *argument - '0';
|
||||
argument++;
|
||||
@@ -569,8 +537,7 @@ int main(int argc, char** argv)
|
||||
case 'P': /* compressibility % */
|
||||
argument++;
|
||||
proba=0;
|
||||
while ((*argument>='0') && (*argument<='9'))
|
||||
{
|
||||
while ((*argument>='0') && (*argument<='9')) {
|
||||
proba *= 10;
|
||||
proba += *argument - '0';
|
||||
argument++;
|
||||
@@ -582,9 +549,7 @@ int main(int argc, char** argv)
|
||||
default:
|
||||
return FUZ_usage(programName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} } } /* for(argNb=1; argNb<argc; argNb++) */
|
||||
|
||||
/* Get Seed */
|
||||
DISPLAY("Starting zstd_buffered tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION);
|
||||
@@ -598,8 +563,8 @@ int main(int argc, char** argv)
|
||||
if (testNb==0) result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
|
||||
if (!result)
|
||||
result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
|
||||
if (mainPause)
|
||||
{
|
||||
|
||||
if (mainPause) {
|
||||
int unused;
|
||||
DISPLAY("Press Enter \n");
|
||||
unused = getchar();
|
||||
|
||||
+24
-23
@@ -167,6 +167,8 @@ static void waitEnter(void)
|
||||
}
|
||||
|
||||
|
||||
#define CLEAN_RETURN(i) { operationResult = (i); goto _end; }
|
||||
|
||||
int main(int argCount, const char** argv)
|
||||
{
|
||||
int i,
|
||||
@@ -181,7 +183,6 @@ int main(int argCount, const char** argv)
|
||||
nextArgumentIsMaxDict=0;
|
||||
unsigned cLevel = 1;
|
||||
unsigned cLevelLast = 1;
|
||||
int additionalParam = 0;
|
||||
const char** filenameTable = (const char**)malloc(argCount * sizeof(const char*)); /* argCount >= 1 */
|
||||
unsigned filenameIdx = 0;
|
||||
const char* programName = argv[0];
|
||||
@@ -193,7 +194,7 @@ int main(int argCount, const char** argv)
|
||||
unsigned dictSelect = g_defaultSelectivityLevel;
|
||||
|
||||
/* init */
|
||||
(void)additionalParam; (void)cLevelLast; (void)dictCLevel; /* not used when ZSTD_NOBENCH / ZSTD_NODICT set */
|
||||
(void)cLevelLast; (void)dictCLevel; /* not used when ZSTD_NOBENCH / ZSTD_NODICT set */
|
||||
if (filenameTable==NULL) { DISPLAY("not enough memory\n"); exit(1); }
|
||||
displayOut = stderr;
|
||||
/* Pick out program name from path. Don't rely on stdlib because of conflicting behavior */
|
||||
@@ -212,8 +213,8 @@ int main(int argCount, const char** argv)
|
||||
/* long commands (--long-word) */
|
||||
if (!strcmp(argument, "--decompress")) { decode=1; continue; }
|
||||
if (!strcmp(argument, "--force")) { FIO_overwriteMode(); continue; }
|
||||
if (!strcmp(argument, "--version")) { displayOut=stdout; DISPLAY(WELCOME_MESSAGE); return 0; }
|
||||
if (!strcmp(argument, "--help")) { displayOut=stdout; return usage_advanced(programName); }
|
||||
if (!strcmp(argument, "--version")) { displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); }
|
||||
if (!strcmp(argument, "--help")) { displayOut=stdout; CLEAN_RETURN(usage_advanced(programName)); }
|
||||
if (!strcmp(argument, "--verbose")) { displayLevel=4; continue; }
|
||||
if (!strcmp(argument, "--quiet")) { displayLevel--; continue; }
|
||||
if (!strcmp(argument, "--stdout")) { forceStdout=1; outFileName=stdoutmark; displayLevel=1; continue; }
|
||||
@@ -244,16 +245,16 @@ int main(int argCount, const char** argv)
|
||||
}
|
||||
dictCLevel = cLevel;
|
||||
if (dictCLevel > ZSTD_maxCLevel())
|
||||
return badusage(programName);
|
||||
CLEAN_RETURN(badusage(programName));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(argument[0])
|
||||
{
|
||||
/* Display help */
|
||||
case 'V': displayOut=stdout; DISPLAY(WELCOME_MESSAGE); return 0; /* Version Only */
|
||||
case 'V': displayOut=stdout; DISPLAY(WELCOME_MESSAGE); CLEAN_RETURN(0); /* Version Only */
|
||||
case 'H':
|
||||
case 'h': displayOut=stdout; return usage_advanced(programName);
|
||||
case 'h': displayOut=stdout; CLEAN_RETURN(usage_advanced(programName));
|
||||
|
||||
/* Decoding */
|
||||
case 'd': decode=1; argument++; break;
|
||||
@@ -288,8 +289,7 @@ int main(int argCount, const char** argv)
|
||||
|
||||
/* Modify Nb Iterations (benchmark only) */
|
||||
case 'i':
|
||||
{
|
||||
int iters= 0;
|
||||
{ U32 iters= 0;
|
||||
argument++;
|
||||
while ((*argument >='0') && (*argument <='9'))
|
||||
iters *= 10, iters += *argument++ - '0';
|
||||
@@ -300,8 +300,7 @@ int main(int argCount, const char** argv)
|
||||
|
||||
/* cut input into blocks (benchmark only) */
|
||||
case 'B':
|
||||
{
|
||||
size_t bSize = 0;
|
||||
{ size_t bSize = 0;
|
||||
argument++;
|
||||
while ((*argument >='0') && (*argument <='9'))
|
||||
bSize *= 10, bSize += *argument++ - '0';
|
||||
@@ -321,7 +320,6 @@ int main(int argCount, const char** argv)
|
||||
cLevelLast = 0;
|
||||
while ((*argument >= '0') && (*argument <= '9'))
|
||||
cLevelLast *= 10, cLevelLast += *argument++ - '0';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif /* ZSTD_NOBENCH */
|
||||
@@ -335,19 +333,22 @@ int main(int argCount, const char** argv)
|
||||
|
||||
/* Pause at the end (-p) or set an additional param (-p#) (hidden option) */
|
||||
case 'p': argument++;
|
||||
#ifndef ZSTD_NOBENCH
|
||||
if ((*argument>='0') && (*argument<='9')) {
|
||||
additionalParam = 0;
|
||||
int additionalParam = 0;
|
||||
while ((*argument >= '0') && (*argument <= '9'))
|
||||
additionalParam *= 10, additionalParam += *argument++ - '0';
|
||||
continue;
|
||||
}
|
||||
main_pause=1; break;
|
||||
BMK_setAdditionalParam(additionalParam);
|
||||
} else
|
||||
#endif
|
||||
main_pause=1;
|
||||
break;
|
||||
/* unknown command */
|
||||
default : return badusage(programName);
|
||||
default : CLEAN_RETURN(badusage(programName));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} /* if (argument[0]=='-') */
|
||||
|
||||
if (nextEntryIsDictionary) {
|
||||
nextEntryIsDictionary = 0;
|
||||
@@ -383,7 +384,7 @@ int main(int argCount, const char** argv)
|
||||
if (bench) {
|
||||
#ifndef ZSTD_NOBENCH
|
||||
BMK_setNotificationLevel(displayLevel);
|
||||
BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast, additionalParam);
|
||||
BMK_benchFiles(filenameTable, filenameIdx, dictFileName, cLevel, cLevelLast);
|
||||
#endif
|
||||
goto _end;
|
||||
}
|
||||
@@ -404,17 +405,17 @@ int main(int argCount, const char** argv)
|
||||
if(!filenameIdx) filenameIdx=1, filenameTable[0]=stdinmark, outFileName=stdoutmark;
|
||||
|
||||
/* Check if input/output defined as console; trigger an error in this case */
|
||||
if (!strcmp(filenameTable[0], stdinmark) && IS_CONSOLE(stdin) ) return badusage(programName);
|
||||
if (outFileName && !strcmp(outFileName, stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) return badusage(programName);
|
||||
if (!strcmp(filenameTable[0], stdinmark) && IS_CONSOLE(stdin) ) CLEAN_RETURN(badusage(programName));
|
||||
if (outFileName && !strcmp(outFileName, stdoutmark) && IS_CONSOLE(stdout) && !forceStdout) CLEAN_RETURN(badusage(programName));
|
||||
|
||||
/* user-selected output filename, only possible with a single file */
|
||||
if (outFileName && strcmp(outFileName,stdoutmark) && strcmp(outFileName,nulmark) && (filenameIdx>1)) {
|
||||
DISPLAY("Too many files (%u) on the command line. \n", filenameIdx);
|
||||
return filenameIdx;
|
||||
CLEAN_RETURN(filenameIdx);
|
||||
}
|
||||
|
||||
/* No warning message in pipe mode (stdin + stdout) or multiple mode */
|
||||
if (!strcmp(filenameTable[0], stdinmark) && !strcmp(outFileName,stdoutmark) && (displayLevel==2)) displayLevel=1;
|
||||
if (!strcmp(filenameTable[0], stdinmark) && outFileName && !strcmp(outFileName,stdoutmark) && (displayLevel==2)) displayLevel=1;
|
||||
if ((filenameIdx>1) && (displayLevel==2)) displayLevel=1;
|
||||
|
||||
/* IO Stream/File */
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<ProjectGuid>{61ABD629-1CC8-4FD7-9281-6B8DBB9D3DF8}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>fullbench</RootNamespace>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<ProjectGuid>{6FD4352B-346C-4703-96EA-D4A8B9A6976E}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>fuzzer</RootNamespace>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<ProjectGuid>{4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>zstd</RootNamespace>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -127,13 +128,11 @@
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
<ClCompile Include="..\..\..\lib\zbuff.c" />
|
||||
<ClCompile Include="..\..\..\lib\zstd_compress.c" />
|
||||
<ClCompile Include="..\..\..\lib\zstd_decompress.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\lib\bitstream.h" />
|
||||
<ClInclude Include="..\..\..\lib\error_private.h" />
|
||||
<ClInclude Include="..\..\..\lib\error_public.h" />
|
||||
@@ -48,6 +46,7 @@
|
||||
<ProjectGuid>{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>zstdlib</RootNamespace>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@@ -96,7 +95,6 @@
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>zstdlib_x86</TargetName>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
@@ -104,14 +102,12 @@
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<TargetName>zstdlib_x64</TargetName>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>zstdlib_x86</TargetName>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
@@ -119,7 +115,6 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<TargetName>zstdlib_x64</TargetName>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>$(SolutionDir)..\..\programs\legacy;$(SolutionDir)..\..\lib\legacy;$(SolutionDir)..\..\lib;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
|
||||
Reference in New Issue
Block a user