[linux-kernel] clang-format lib/zstd/

dev
Nick Terrell 2017-05-17 14:40:46 -07:00
parent 588579f3a1
commit 67101c6c77
15 changed files with 5241 additions and 4655 deletions

View File

@ -50,16 +50,15 @@
/*-**************************************** /*-****************************************
* Dependencies * Dependencies
******************************************/ ******************************************/
#include "mem.h" /* unaligned access routines */ #include "error_private.h" /* error codes and messages */
#include "error_private.h" /* error codes and messages */ #include "mem.h" /* unaligned access routines */
/*========================================= /*=========================================
* Target specific * Target specific
=========================================*/ =========================================*/
#define STREAM_ACCUMULATOR_MIN_32 25 #define STREAM_ACCUMULATOR_MIN_32 25
#define STREAM_ACCUMULATOR_MIN_64 57 #define STREAM_ACCUMULATOR_MIN_64 57
#define STREAM_ACCUMULATOR_MIN ((U32)(ZSTD_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64)) #define STREAM_ACCUMULATOR_MIN ((U32)(ZSTD_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
/*-****************************************** /*-******************************************
* bitStream encoding API (write forward) * bitStream encoding API (write forward)
@ -68,19 +67,18 @@
* A critical property of these streams is that they encode and decode in **reverse** direction. * 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. * So the first bit sequence you add will be the last to be read, like a LIFO stack.
*/ */
typedef struct typedef struct {
{
size_t bitContainer; size_t bitContainer;
int bitPos; int bitPos;
char* startPtr; char *startPtr;
char* ptr; char *ptr;
char* endPtr; char *endPtr;
} BIT_CStream_t; } BIT_CStream_t;
ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity); ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *dstBuffer, size_t dstCapacity);
ZSTD_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits); ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
ZSTD_STATIC void BIT_flushBits(BIT_CStream_t* bitC); ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC);
ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC); ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC);
/* Start with initCStream, providing the size of buffer to write into. /* Start with initCStream, providing the size of buffer to write into.
* bitStream will never write outside of this buffer. * bitStream will never write outside of this buffer.
@ -99,29 +97,28 @@ ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable) * If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
*/ */
/*-******************************************** /*-********************************************
* bitStream decoding API (read backward) * bitStream decoding API (read backward)
**********************************************/ **********************************************/
typedef struct typedef struct {
{ size_t bitContainer;
size_t bitContainer;
unsigned bitsConsumed; unsigned bitsConsumed;
const char* ptr; const char *ptr;
const char* start; const char *start;
} BIT_DStream_t; } BIT_DStream_t;
typedef enum { BIT_DStream_unfinished = 0, typedef enum {
BIT_DStream_endOfBuffer = 1, BIT_DStream_unfinished = 0,
BIT_DStream_completed = 2, BIT_DStream_endOfBuffer = 1,
BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */ BIT_DStream_completed = 2,
/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */ BIT_DStream_overflow = 3
} BIT_DStream_status; /* result of BIT_reloadDStream() */
ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize); /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize);
ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, unsigned nbBits);
ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD);
ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *bitD);
/* Start by invoking BIT_initDStream(). /* Start by invoking BIT_initDStream().
* A chunk of the bitStream is then stored into a local register. * A chunk of the bitStream is then stored into a local register.
@ -133,32 +130,27 @@ ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
* Checking if DStream has reached its end can be performed with BIT_endOfDStream(). * Checking if DStream has reached its end can be performed with BIT_endOfDStream().
*/ */
/*-**************************************** /*-****************************************
* unsafe API * unsafe API
******************************************/ ******************************************/
ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits); ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */ /* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC); ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC);
/* unsafe version; does not check buffer overflow */ /* unsafe version; does not check buffer overflow */
ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits); ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits);
/* faster, but works only if nbBits >= 1 */ /* faster, but works only if nbBits >= 1 */
/*-************************************************************** /*-**************************************************************
* Internal functions * Internal functions
****************************************************************/ ****************************************************************/
ZSTD_STATIC unsigned BIT_highbit32 (register U32 val) ZSTD_STATIC unsigned BIT_highbit32(register U32 val) { return 31 - __builtin_clz(val); }
{
return 31 - __builtin_clz(val);
}
/*===== Local Constants =====*/ /*===== Local Constants =====*/
static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */ static const unsigned BIT_mask[] = {0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF}; /* up to 26 bits */
/*-************************************************************** /*-**************************************************************
* bitStream encoding * bitStream encoding
@ -167,21 +159,22 @@ static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x
* `dstCapacity` must be > sizeof(void*) * `dstCapacity` must be > sizeof(void*)
* @return : 0 if success, * @return : 0 if success,
otherwise an error code (can be tested using ERR_isError() ) */ otherwise an error code (can be tested using ERR_isError() ) */
ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity) ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *startPtr, size_t dstCapacity)
{ {
bitC->bitContainer = 0; bitC->bitContainer = 0;
bitC->bitPos = 0; bitC->bitPos = 0;
bitC->startPtr = (char*)startPtr; bitC->startPtr = (char *)startPtr;
bitC->ptr = bitC->startPtr; bitC->ptr = bitC->startPtr;
bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr); bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall); if (dstCapacity <= sizeof(bitC->ptr))
return ERROR(dstSize_tooSmall);
return 0; return 0;
} }
/*! BIT_addBits() : /*! BIT_addBits() :
can add up to 26 bits into `bitC`. can add up to 26 bits into `bitC`.
Does not check for register overflow ! */ Does not check for register overflow ! */
ZSTD_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits) ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
{ {
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
bitC->bitPos += nbBits; bitC->bitPos += nbBits;
@ -189,7 +182,7 @@ ZSTD_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
/*! BIT_addBitsFast() : /*! BIT_addBitsFast() :
* works only if `value` is _clean_, meaning all high bits above nbBits are 0 */ * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits) ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
{ {
bitC->bitContainer |= value << bitC->bitPos; bitC->bitContainer |= value << bitC->bitPos;
bitC->bitPos += nbBits; bitC->bitPos += nbBits;
@ -197,42 +190,43 @@ ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbB
/*! BIT_flushBitsFast() : /*! BIT_flushBitsFast() :
* unsafe version; does not check buffer overflow */ * unsafe version; does not check buffer overflow */
ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC) ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC)
{ {
size_t const nbBytes = bitC->bitPos >> 3; size_t const nbBytes = bitC->bitPos >> 3;
ZSTD_writeLEST(bitC->ptr, bitC->bitContainer); ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
bitC->ptr += nbBytes; bitC->ptr += nbBytes;
bitC->bitPos &= 7; bitC->bitPos &= 7;
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
} }
/*! BIT_flushBits() : /*! BIT_flushBits() :
* safe version; check for buffer overflow, and prevents it. * safe version; check for buffer overflow, and prevents it.
* note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */ * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
ZSTD_STATIC void BIT_flushBits(BIT_CStream_t* bitC) ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC)
{ {
size_t const nbBytes = bitC->bitPos >> 3; size_t const nbBytes = bitC->bitPos >> 3;
ZSTD_writeLEST(bitC->ptr, bitC->bitContainer); ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
bitC->ptr += nbBytes; bitC->ptr += nbBytes;
if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr; if (bitC->ptr > bitC->endPtr)
bitC->ptr = bitC->endPtr;
bitC->bitPos &= 7; bitC->bitPos &= 7;
bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */ bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
} }
/*! BIT_closeCStream() : /*! BIT_closeCStream() :
* @return : size of CStream, in bytes, * @return : size of CStream, in bytes,
or 0 if it could not fit into dstBuffer */ or 0 if it could not fit into dstBuffer */
ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC)
{ {
BIT_addBitsFast(bitC, 1, 1); /* endMark */ BIT_addBitsFast(bitC, 1, 1); /* endMark */
BIT_flushBits(bitC); BIT_flushBits(bitC);
if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */ if (bitC->ptr >= bitC->endPtr)
return 0; /* doesn't fit within authorized budget : cancel */
return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0); return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
} }
/*-******************************************************** /*-********************************************************
* bitStream decoding * bitStream decoding
**********************************************************/ **********************************************************/
@ -242,54 +236,53 @@ ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
* `srcSize` must be the *exact* size of the bitStream, in bytes. * `srcSize` must be the *exact* size of the bitStream, in bytes.
* @return : size of stream (== srcSize) or an errorCode if a problem is detected * @return : size of stream (== srcSize) or an errorCode if a problem is detected
*/ */
ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) ZSTD_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 < 1) {
memset(bitD, 0, sizeof(*bitD));
return ERROR(srcSize_wrong);
}
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */ if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
bitD->start = (const char*)srcBuffer; bitD->start = (const char *)srcBuffer;
bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer); bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(bitD->bitContainer);
bitD->bitContainer = ZSTD_readLEST(bitD->ptr); bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
} else {
bitD->start = (const char*)srcBuffer;
bitD->ptr = bitD->start;
bitD->bitContainer = *(const BYTE*)(bitD->start);
switch(srcSize)
{ {
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16); BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24); bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32); if (lastByte == 0)
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; return ERROR(GENERIC); /* endMark not present */
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
default:;
} }
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1]; } else {
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; bitD->start = (const char *)srcBuffer;
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ } bitD->ptr = bitD->start;
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8; bitD->bitContainer = *(const BYTE *)(bitD->start);
switch (srcSize) {
case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16);
case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24);
case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32);
case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24;
case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16;
case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8;
default:;
}
{
BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
if (lastByte == 0)
return ERROR(GENERIC); /* endMark not present */
}
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize) * 8;
} }
return srcSize; return srcSize;
} }
ZSTD_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) ZSTD_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; }
{
return bitContainer >> start;
}
ZSTD_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) ZSTD_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { return (bitContainer >> start) & BIT_mask[nbBits]; }
{
return (bitContainer >> start) & BIT_mask[nbBits];
}
ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { return bitContainer & BIT_mask[nbBits]; }
{
return bitContainer & BIT_mask[nbBits];
}
/*! BIT_lookBits() : /*! BIT_lookBits() :
* Provides next n bits from local register. * Provides next n bits from local register.
@ -298,31 +291,28 @@ ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
* On 64-bits, maxNbBits==56. * On 64-bits, maxNbBits==56.
* @return : value extracted * @return : value extracted
*/ */
ZSTD_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) ZSTD_STATIC size_t BIT_lookBits(const BIT_DStream_t *bitD, U32 nbBits)
{ {
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1; U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask); return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask);
} }
/*! BIT_lookBitsFast() : /*! BIT_lookBitsFast() :
* unsafe version; only works only if nbBits >= 1 */ * unsafe version; only works only if nbBits >= 1 */
ZSTD_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) ZSTD_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t *bitD, U32 nbBits)
{ {
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1; U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask); return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask);
} }
ZSTD_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) ZSTD_STATIC void BIT_skipBits(BIT_DStream_t *bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; }
{
bitD->bitsConsumed += nbBits;
}
/*! BIT_readBits() : /*! BIT_readBits() :
* Read (consume) next n bits from local register and update. * Read (consume) next n bits from local register and update.
* Pay attention to not read more than nbBits contained into local register. * Pay attention to not read more than nbBits contained into local register.
* @return : extracted value. * @return : extracted value.
*/ */
ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits) ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, U32 nbBits)
{ {
size_t const value = BIT_lookBits(bitD, nbBits); size_t const value = BIT_lookBits(bitD, nbBits);
BIT_skipBits(bitD, nbBits); BIT_skipBits(bitD, nbBits);
@ -331,7 +321,7 @@ ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
/*! BIT_readBitsFast() : /*! BIT_readBitsFast() :
* unsafe version; only works only if nbBits >= 1 */ * unsafe version; only works only if nbBits >= 1 */
ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits) ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, U32 nbBits)
{ {
size_t const value = BIT_lookBitsFast(bitD, nbBits); size_t const value = BIT_lookBitsFast(bitD, nbBits);
BIT_skipBits(bitD, nbBits); BIT_skipBits(bitD, nbBits);
@ -343,9 +333,9 @@ ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
* This function is safe, it guarantees it will not read beyond src buffer. * This function is safe, it guarantees it will not read beyond src buffer.
* @return : status of `BIT_DStream_t` internal register. * @return : status of `BIT_DStream_t` internal register.
if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */ if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD) ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD)
{ {
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */ if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should not happen => corruption detected */
return BIT_DStream_overflow; return BIT_DStream_overflow;
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) { if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
@ -355,18 +345,20 @@ ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
return BIT_DStream_unfinished; return BIT_DStream_unfinished;
} }
if (bitD->ptr == bitD->start) { if (bitD->ptr == bitD->start) {
if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer; if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8)
return BIT_DStream_endOfBuffer;
return BIT_DStream_completed; return BIT_DStream_completed;
} }
{ U32 nbBytes = bitD->bitsConsumed >> 3; {
U32 nbBytes = bitD->bitsConsumed >> 3;
BIT_DStream_status result = BIT_DStream_unfinished; BIT_DStream_status result = BIT_DStream_unfinished;
if (bitD->ptr - nbBytes < bitD->start) { if (bitD->ptr - nbBytes < bitD->start) {
nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */ nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
result = BIT_DStream_endOfBuffer; result = BIT_DStream_endOfBuffer;
} }
bitD->ptr -= nbBytes; bitD->ptr -= nbBytes;
bitD->bitsConsumed -= nbBytes*8; bitD->bitsConsumed -= nbBytes * 8;
bitD->bitContainer = ZSTD_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */ bitD->bitContainer = ZSTD_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
return result; return result;
} }
} }
@ -374,9 +366,9 @@ ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
/*! BIT_endOfDStream() : /*! BIT_endOfDStream() :
* @return Tells if DStream has exactly reached its end (all bits consumed). * @return Tells if DStream has exactly reached its end (all bits consumed).
*/ */
ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream) ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *DStream)
{ {
return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8)); return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer) * 8));
} }
#endif /* BITSTREAM_H_MODULE */ #endif /* BITSTREAM_H_MODULE */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -40,31 +40,27 @@
/* ************************************* /* *************************************
* Dependencies * Dependencies
***************************************/ ***************************************/
#include "mem.h" #include "error_private.h" /* ERR_*, ERROR */
#include "error_private.h" /* ERR_*, ERROR */
#include "fse.h" #include "fse.h"
#include "huf.h" #include "huf.h"
#include "mem.h"
/*=== Version ===*/ /*=== Version ===*/
unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; } unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
/*=== Error Management ===*/ /*=== Error Management ===*/
unsigned FSE_isError(size_t code) { return ERR_isError(code); } unsigned FSE_isError(size_t code) { return ERR_isError(code); }
unsigned HUF_isError(size_t code) { return ERR_isError(code); } unsigned HUF_isError(size_t code) { return ERR_isError(code); }
/*-************************************************************** /*-**************************************************************
* FSE NCount encoding-decoding * FSE NCount encoding-decoding
****************************************************************/ ****************************************************************/
size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSVPtr, unsigned *tableLogPtr, const void *headerBuffer, size_t hbSize)
const void* headerBuffer, size_t hbSize)
{ {
const BYTE* const istart = (const BYTE*) headerBuffer; const BYTE *const istart = (const BYTE *)headerBuffer;
const BYTE* const iend = istart + hbSize; const BYTE *const iend = istart + hbSize;
const BYTE* ip = istart; const BYTE *ip = istart;
int nbBits; int nbBits;
int remaining; int remaining;
int threshold; int threshold;
@ -73,29 +69,32 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
unsigned charnum = 0; unsigned charnum = 0;
int previous0 = 0; int previous0 = 0;
if (hbSize < 4) return ERROR(srcSize_wrong); if (hbSize < 4)
return ERROR(srcSize_wrong);
bitStream = ZSTD_readLE32(ip); bitStream = ZSTD_readLE32(ip);
nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX)
return ERROR(tableLog_tooLarge);
bitStream >>= 4; bitStream >>= 4;
bitCount = 4; bitCount = 4;
*tableLogPtr = nbBits; *tableLogPtr = nbBits;
remaining = (1<<nbBits)+1; remaining = (1 << nbBits) + 1;
threshold = 1<<nbBits; threshold = 1 << nbBits;
nbBits++; nbBits++;
while ((remaining>1) & (charnum<=*maxSVPtr)) { while ((remaining > 1) & (charnum <= *maxSVPtr)) {
if (previous0) { if (previous0) {
unsigned n0 = charnum; unsigned n0 = charnum;
while ((bitStream & 0xFFFF) == 0xFFFF) { while ((bitStream & 0xFFFF) == 0xFFFF) {
n0 += 24; n0 += 24;
if (ip < iend-5) { if (ip < iend - 5) {
ip += 2; ip += 2;
bitStream = ZSTD_readLE32(ip) >> bitCount; bitStream = ZSTD_readLE32(ip) >> bitCount;
} else { } else {
bitStream >>= 16; bitStream >>= 16;
bitCount += 16; bitCount += 16;
} } }
}
while ((bitStream & 3) == 3) { while ((bitStream & 3) == 3) {
n0 += 3; n0 += 3;
bitStream >>= 2; bitStream >>= 2;
@ -103,29 +102,34 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
} }
n0 += bitStream & 3; n0 += bitStream & 3;
bitCount += 2; bitCount += 2;
if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); if (n0 > *maxSVPtr)
while (charnum < n0) normalizedCounter[charnum++] = 0; return ERROR(maxSymbolValue_tooSmall);
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { while (charnum < n0)
ip += bitCount>>3; normalizedCounter[charnum++] = 0;
if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
ip += bitCount >> 3;
bitCount &= 7; bitCount &= 7;
bitStream = ZSTD_readLE32(ip) >> bitCount; bitStream = ZSTD_readLE32(ip) >> bitCount;
} else { } else {
bitStream >>= 2; bitStream >>= 2;
} } }
{ int const max = (2*threshold-1) - remaining; }
{
int const max = (2 * threshold - 1) - remaining;
int count; int count;
if ((bitStream & (threshold-1)) < (U32)max) { if ((bitStream & (threshold - 1)) < (U32)max) {
count = bitStream & (threshold-1); count = bitStream & (threshold - 1);
bitCount += nbBits-1; bitCount += nbBits - 1;
} else { } else {
count = bitStream & (2*threshold-1); count = bitStream & (2 * threshold - 1);
if (count >= threshold) count -= max; if (count >= threshold)
count -= max;
bitCount += nbBits; bitCount += nbBits;
} }
count--; /* extra accuracy */ count--; /* extra accuracy */
remaining -= count < 0 ? -count : count; /* -1 means +1 */ remaining -= count < 0 ? -count : count; /* -1 means +1 */
normalizedCounter[charnum++] = (short)count; normalizedCounter[charnum++] = (short)count;
previous0 = !count; previous0 = !count;
while (remaining < threshold) { while (remaining < threshold) {
@ -133,24 +137,26 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
threshold >>= 1; threshold >>= 1;
} }
if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
ip += bitCount>>3; ip += bitCount >> 3;
bitCount &= 7; bitCount &= 7;
} else { } else {
bitCount -= (int)(8 * (iend - 4 - ip)); bitCount -= (int)(8 * (iend - 4 - ip));
ip = iend - 4; ip = iend - 4;
} }
bitStream = ZSTD_readLE32(ip) >> (bitCount & 31); bitStream = ZSTD_readLE32(ip) >> (bitCount & 31);
} } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ }
if (remaining != 1) return ERROR(corruption_detected); } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
if (bitCount > 32) return ERROR(corruption_detected); if (remaining != 1)
*maxSVPtr = charnum-1; return ERROR(corruption_detected);
if (bitCount > 32)
return ERROR(corruption_detected);
*maxSVPtr = charnum - 1;
ip += (bitCount+7)>>3; ip += (bitCount + 7) >> 3;
return ip-istart; return ip - istart;
} }
/*! HUF_readStats() : /*! HUF_readStats() :
Read compact Huffman tree, saved by HUF_writeCTable(). Read compact Huffman tree, saved by HUF_writeCTable().
`huffWeight` is destination buffer. `huffWeight` is destination buffer.
@ -158,65 +164,81 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
@return : size read from `src` , or an error Code . @return : size read from `src` , or an error Code .
Note : Needed by HUF_readCTable() and HUF_readDTableX?() . Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
*/ */
size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, size_t HUF_readStats(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize)
U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize)
{ {
U32 weightTotal; U32 weightTotal;
const BYTE* ip = (const BYTE*) src; const BYTE *ip = (const BYTE *)src;
size_t iSize; size_t iSize;
size_t oSize; size_t oSize;
if (!srcSize) return ERROR(srcSize_wrong); if (!srcSize)
return ERROR(srcSize_wrong);
iSize = ip[0]; iSize = ip[0];
/* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
if (iSize >= 128) { /* special header */ if (iSize >= 128) { /* special header */
oSize = iSize - 127; oSize = iSize - 127;
iSize = ((oSize+1)/2); iSize = ((oSize + 1) / 2);
if (iSize+1 > srcSize) return ERROR(srcSize_wrong); if (iSize + 1 > srcSize)
if (oSize >= hwSize) return ERROR(corruption_detected); return ERROR(srcSize_wrong);
if (oSize >= hwSize)
return ERROR(corruption_detected);
ip += 1; ip += 1;
{ U32 n; {
for (n=0; n<oSize; n+=2) { U32 n;
huffWeight[n] = ip[n/2] >> 4; for (n = 0; n < oSize; n += 2) {
huffWeight[n+1] = ip[n/2] & 15; huffWeight[n] = ip[n / 2] >> 4;
} } } huffWeight[n + 1] = ip[n / 2] & 15;
else { /* header compressed with FSE (normal case) */ }
FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ }
if (iSize+1 > srcSize) return ERROR(srcSize_wrong); } else { /* header compressed with FSE (normal case) */
oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */
if (FSE_isError(oSize)) return oSize; if (iSize + 1 > srcSize)
return ERROR(srcSize_wrong);
oSize = FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */
if (FSE_isError(oSize))
return oSize;
} }
/* collect weight stats */ /* collect weight stats */
memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
weightTotal = 0; weightTotal = 0;
{ U32 n; for (n=0; n<oSize; n++) { {
if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); U32 n;
for (n = 0; n < oSize; n++) {
if (huffWeight[n] >= HUF_TABLELOG_MAX)
return ERROR(corruption_detected);
rankStats[huffWeight[n]]++; rankStats[huffWeight[n]]++;
weightTotal += (1 << huffWeight[n]) >> 1; weightTotal += (1 << huffWeight[n]) >> 1;
} } }
if (weightTotal == 0) return ERROR(corruption_detected); }
if (weightTotal == 0)
return ERROR(corruption_detected);
/* get last non-null symbol weight (implied, total must be 2^n) */ /* get last non-null symbol weight (implied, total must be 2^n) */
{ U32 const tableLog = BIT_highbit32(weightTotal) + 1; {
if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected); U32 const tableLog = BIT_highbit32(weightTotal) + 1;
if (tableLog > HUF_TABLELOG_MAX)
return ERROR(corruption_detected);
*tableLogPtr = tableLog; *tableLogPtr = tableLog;
/* determine last weight */ /* determine last weight */
{ U32 const total = 1 << tableLog; {
U32 const total = 1 << tableLog;
U32 const rest = total - weightTotal; U32 const rest = total - weightTotal;
U32 const verif = 1 << BIT_highbit32(rest); U32 const verif = 1 << BIT_highbit32(rest);
U32 const lastWeight = BIT_highbit32(rest) + 1; U32 const lastWeight = BIT_highbit32(rest) + 1;
if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */ if (verif != rest)
return ERROR(corruption_detected); /* last value must be a clean power of 2 */
huffWeight[oSize] = (BYTE)lastWeight; huffWeight[oSize] = (BYTE)lastWeight;
rankStats[lastWeight]++; rankStats[lastWeight]++;
} } }
}
/* check tree construction validity */ /* check tree construction validity */
if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */ if ((rankStats[1] < 2) || (rankStats[1] & 1))
return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
/* results */ /* results */
*nbSymbolsPtr = (U32)(oSize+1); *nbSymbolsPtr = (U32)(oSize + 1);
return iSize+1; return iSize + 1;
} }

View File

@ -22,23 +22,20 @@
/* **************************************** /* ****************************************
* Dependencies * Dependencies
******************************************/ ******************************************/
#include <linux/types.h> /* size_t */ #include <linux/types.h> /* size_t */
#include <linux/zstd.h> /* enum list */ #include <linux/zstd.h> /* enum list */
/* **************************************** /* ****************************************
* Compiler-specific * Compiler-specific
******************************************/ ******************************************/
#define ERR_STATIC static __attribute__((unused)) #define ERR_STATIC static __attribute__((unused))
/*-**************************************** /*-****************************************
* Customization (error_public.h) * Customization (error_public.h)
******************************************/ ******************************************/
typedef ZSTD_ErrorCode ERR_enum; typedef ZSTD_ErrorCode ERR_enum;
#define PREFIX(name) ZSTD_error_##name #define PREFIX(name) ZSTD_error_##name
/*-**************************************** /*-****************************************
* Error codes handling * Error codes handling
******************************************/ ******************************************/
@ -46,6 +43,11 @@ typedef ZSTD_ErrorCode ERR_enum;
ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); } ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); } ERR_STATIC ERR_enum ERR_getErrorCode(size_t code)
{
if (!ERR_isError(code))
return (ERR_enum)0;
return (ERR_enum)(0 - code);
}
#endif /* ERROR_H_MODULE */ #endif /* ERROR_H_MODULE */

View File

@ -40,12 +40,10 @@
#ifndef FSE_H #ifndef FSE_H
#define FSE_H #define FSE_H
/*-***************************************** /*-*****************************************
* Dependencies * Dependencies
******************************************/ ******************************************/
#include <linux/types.h> /* size_t, ptrdiff_t */ #include <linux/types.h> /* size_t, ptrdiff_t */
/*-***************************************** /*-*****************************************
* FSE_PUBLIC_API : control library symbols visibility * FSE_PUBLIC_API : control library symbols visibility
@ -53,26 +51,25 @@
#define FSE_PUBLIC_API #define FSE_PUBLIC_API
/*------ Version ------*/ /*------ Version ------*/
#define FSE_VERSION_MAJOR 0 #define FSE_VERSION_MAJOR 0
#define FSE_VERSION_MINOR 9 #define FSE_VERSION_MINOR 9
#define FSE_VERSION_RELEASE 0 #define FSE_VERSION_RELEASE 0
#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE #define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
#define FSE_QUOTE(str) #str #define FSE_QUOTE(str) #str
#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str) #define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION) #define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE) #define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR * 100 * 100 + FSE_VERSION_MINOR * 100 + FSE_VERSION_RELEASE)
FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */ FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
/*-***************************************** /*-*****************************************
* Tool functions * Tool functions
******************************************/ ******************************************/
FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */ FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
/* Error Management */ /* Error Management */
FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */ FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
/*-***************************************** /*-*****************************************
* FSE detailed API * FSE detailed API
@ -107,7 +104,7 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize
'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
@return : tableLog, @return : tableLog,
or an errorCode, which can be tested using FSE_isError() */ or an errorCode, which can be tested using FSE_isError() */
FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t srcSize, unsigned maxSymbolValue); FSE_PUBLIC_API size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t srcSize, unsigned maxSymbolValue);
/*! FSE_NCountWriteBound(): /*! FSE_NCountWriteBound():
Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
@ -118,19 +115,18 @@ FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tab
Compactly save 'normalizedCounter' into 'buffer'. Compactly save 'normalizedCounter' into 'buffer'.
@return : size of the compressed table, @return : size of the compressed table,
or an errorCode, which can be tested using FSE_isError(). */ or an errorCode, which can be tested using FSE_isError(). */
FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); FSE_PUBLIC_API size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
/*! Constructor and Destructor of FSE_CTable. /*! Constructor and Destructor of FSE_CTable.
Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */ Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */ typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
/*! FSE_compress_usingCTable(): /*! FSE_compress_usingCTable():
Compress `src` using `ct` into `dst` which must be already allocated. Compress `src` using `ct` into `dst` which must be already allocated.
@return : size of compressed data (<= `dstCapacity`), @return : size of compressed data (<= `dstCapacity`),
or 0 if compressed data could not fit into `dst`, or 0 if compressed data could not fit into `dst`,
or an errorCode, which can be tested using FSE_isError() */ or an errorCode, which can be tested using FSE_isError() */
FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct); FSE_PUBLIC_API size_t FSE_compress_usingCTable(void *dst, size_t dstCapacity, const void *src, size_t srcSize, const FSE_CTable *ct);
/*! /*!
Tutorial : Tutorial :
@ -175,7 +171,6 @@ If it returns '0', compressed data could not fit into 'dst'.
If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()). If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
*/ */
/* *** DECOMPRESSION *** */ /* *** DECOMPRESSION *** */
/*! FSE_readNCount(): /*! FSE_readNCount():
@ -183,23 +178,23 @@ If there is an error, the function will return an ErrorCode (which can be tested
@return : size read from 'rBuffer', @return : size read from 'rBuffer',
or an errorCode, which can be tested using FSE_isError(). or an errorCode, which can be tested using FSE_isError().
maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */ maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); FSE_PUBLIC_API size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize);
/*! Constructor and Destructor of FSE_DTable. /*! Constructor and Destructor of FSE_DTable.
Note that its size depends on 'tableLog' */ Note that its size depends on 'tableLog' */
typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
/*! FSE_buildDTable(): /*! FSE_buildDTable():
Builds 'dt', which must be already allocated, using FSE_createDTable(). Builds 'dt', which must be already allocated, using FSE_createDTable().
return : 0, or an errorCode, which can be tested using FSE_isError() */ return : 0, or an errorCode, which can be tested using FSE_isError() */
FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog); FSE_PUBLIC_API size_t FSE_buildDTable(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
/*! FSE_decompress_usingDTable(): /*! FSE_decompress_usingDTable():
Decompress compressed source `cSrc` of size `cSrcSize` using `dt` Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
into `dst` which must be already allocated. into `dst` which must be already allocated.
@return : size of regenerated data (necessarily <= `dstCapacity`), @return : size of regenerated data (necessarily <= `dstCapacity`),
or an errorCode, which can be tested using FSE_isError() */ or an errorCode, which can be tested using FSE_isError() */
FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt); FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt);
/*! /*!
Tutorial : Tutorial :
@ -229,23 +224,20 @@ FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<
If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small) If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
*/ */
/* *** Dependency *** */ /* *** Dependency *** */
#include "bitstream.h" #include "bitstream.h"
/* ***************************************** /* *****************************************
* Static allocation * Static allocation
*******************************************/ *******************************************/
/* FSE buffer bounds */ /* FSE buffer bounds */
#define FSE_NCOUNTBOUND 512 #define FSE_NCOUNTBOUND 512
#define FSE_BLOCKBOUND(size) (size + (size>>7)) #define FSE_BLOCKBOUND(size) (size + (size >> 7))
#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) #define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1 << (maxTableLog - 1)) + ((maxSymbolValue + 1) * 2))
#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) #define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog))
/* ***************************************** /* *****************************************
* FSE advanced API * FSE advanced API
@ -254,22 +246,19 @@ If there is an error, the function will return an error code, which can be teste
* Same as FSE_count(), but using an externally provided scratch buffer. * Same as FSE_count(), but using an externally provided scratch buffer.
* `workSpace` size must be table of >= `1024` unsigned * `workSpace` size must be table of >= `1024` unsigned
*/ */
size_t FSE_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace);
const void* source, size_t sourceSize, unsigned* workSpace);
/* FSE_countFast_wksp() : /* FSE_countFast_wksp() :
* Same as FSE_countFast(), but using an externally provided scratch buffer. * Same as FSE_countFast(), but using an externally provided scratch buffer.
* `workSpace` must be a table of minimum `1024` unsigned * `workSpace` must be a table of minimum `1024` unsigned
*/ */
size_t FSE_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* workSpace); size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize, unsigned *workSpace);
/*! FSE_count_simple /*! FSE_count_simple
* Same as FSE_countFast(), but does not use any additional memory (not even on stack). * Same as FSE_countFast(), but does not use any additional memory (not even on stack).
* This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`). * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
*/ */
size_t FSE_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize); size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize);
unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus); unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
/**< same as FSE_optimalTableLog(), which used `minus==2` */ /**< same as FSE_optimalTableLog(), which used `minus==2` */
@ -278,31 +267,32 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
* FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
*/ */
#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) #define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) \
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024))
size_t FSE_compress_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
size_t wkspSize);
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); size_t FSE_buildCTable_raw(FSE_CTable *ct, unsigned nbBits);
/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */ /**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); size_t FSE_buildCTable_rle(FSE_CTable *ct, unsigned char symbolValue);
/**< build a fake FSE_CTable, designed to compress always the same symbolValue */ /**< build a fake FSE_CTable, designed to compress always the same symbolValue */
/* FSE_buildCTable_wksp() : /* FSE_buildCTable_wksp() :
* Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
* `wkspSize` must be >= `(1<<tableLog)`. * `wkspSize` must be >= `(1<<tableLog)`.
*/ */
size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize);
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits);
/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ /**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); size_t FSE_buildDTable_rle(FSE_DTable *dt, unsigned char symbolValue);
/**< build a fake FSE_DTable, designed to always generate the same symbolValue */ /**< build a fake FSE_DTable, designed to always generate the same symbolValue */
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog); size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, FSE_DTable *workSpace, unsigned maxLog);
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */ /**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
/* ***************************************** /* *****************************************
* FSE symbol compression API * FSE symbol compression API
*******************************************/ *******************************************/
@ -311,17 +301,17 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
Hence their body are included in next section. Hence their body are included in next section.
*/ */
typedef struct { typedef struct {
ptrdiff_t value; ptrdiff_t value;
const void* stateTable; const void *stateTable;
const void* symbolTT; const void *symbolTT;
unsigned stateLog; unsigned stateLog;
} FSE_CState_t; } FSE_CState_t;
static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct); static void FSE_initCState(FSE_CState_t *CStatePtr, const FSE_CTable *ct);
static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol); static void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *CStatePtr, unsigned symbol);
static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr); static void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *CStatePtr);
/**< /**<
These functions are inner components of FSE_compress_usingCTable(). These functions are inner components of FSE_compress_usingCTable().
@ -366,21 +356,19 @@ If there is an error, it returns an errorCode (which can be tested using FSE_isE
size_t size = BIT_closeCStream(&bitStream); size_t size = BIT_closeCStream(&bitStream);
*/ */
/* ***************************************** /* *****************************************
* FSE symbol decompression API * FSE symbol decompression API
*******************************************/ *******************************************/
typedef struct { typedef struct {
size_t state; size_t state;
const void* table; /* precise table may vary, depending on U16 */ const void *table; /* precise table may vary, depending on U16 */
} FSE_DState_t; } FSE_DState_t;
static void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt);
static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt); static unsigned char FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); static unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr);
static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
/**< /**<
Let's now decompose FSE_decompress_usingDTable() into its unitary components. Let's now decompose FSE_decompress_usingDTable() into its unitary components.
@ -431,14 +419,12 @@ Check also the states. There might be some symbols left there, if some high prob
FSE_endOfDState(&DState); FSE_endOfDState(&DState);
*/ */
/* ***************************************** /* *****************************************
* FSE unsafe API * FSE unsafe API
*******************************************/ *******************************************/
static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD); static unsigned char FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */ /* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
/* ***************************************** /* *****************************************
* Implementation of inlined functions * Implementation of inlined functions
*******************************************/ *******************************************/
@ -447,88 +433,86 @@ typedef struct {
U32 deltaNbBits; U32 deltaNbBits;
} FSE_symbolCompressionTransform; /* total 8 bytes */ } FSE_symbolCompressionTransform; /* total 8 bytes */
ZSTD_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct) ZSTD_STATIC void FSE_initCState(FSE_CState_t *statePtr, const FSE_CTable *ct)
{ {
const void* ptr = ct; const void *ptr = ct;
const U16* u16ptr = (const U16*) ptr; const U16 *u16ptr = (const U16 *)ptr;
const U32 tableLog = ZSTD_read16(ptr); const U32 tableLog = ZSTD_read16(ptr);
statePtr->value = (ptrdiff_t)1<<tableLog; statePtr->value = (ptrdiff_t)1 << tableLog;
statePtr->stateTable = u16ptr+2; statePtr->stateTable = u16ptr + 2;
statePtr->symbolTT = ((const U32*)ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1)); statePtr->symbolTT = ((const U32 *)ct + 1 + (tableLog ? (1 << (tableLog - 1)) : 1));
statePtr->stateLog = tableLog; statePtr->stateLog = tableLog;
} }
/*! FSE_initCState2() : /*! FSE_initCState2() :
* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read) * Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
* uses the smallest state value possible, saving the cost of this symbol */ * uses the smallest state value possible, saving the cost of this symbol */
ZSTD_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol) ZSTD_STATIC void FSE_initCState2(FSE_CState_t *statePtr, const FSE_CTable *ct, U32 symbol)
{ {
FSE_initCState(statePtr, ct); FSE_initCState(statePtr, ct);
{ const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; {
const U16* stateTable = (const U16*)(statePtr->stateTable); const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16); const U16 *stateTable = (const U16 *)(statePtr->stateTable);
U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1 << 15)) >> 16);
statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits; statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
} }
} }
ZSTD_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, U32 symbol) ZSTD_STATIC void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *statePtr, U32 symbol)
{ {
const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol]; const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
const U16* const stateTable = (const U16*)(statePtr->stateTable); const U16 *const stateTable = (const U16 *)(statePtr->stateTable);
U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16); U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
BIT_addBits(bitC, statePtr->value, nbBitsOut); BIT_addBits(bitC, statePtr->value, nbBitsOut);
statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState]; statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
} }
ZSTD_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr) ZSTD_STATIC void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *statePtr)
{ {
BIT_addBits(bitC, statePtr->value, statePtr->stateLog); BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
BIT_flushBits(bitC); BIT_flushBits(bitC);
} }
/* ====== Decompression ====== */ /* ====== Decompression ====== */
typedef struct { typedef struct {
U16 tableLog; U16 tableLog;
U16 fastMode; U16 fastMode;
} FSE_DTableHeader; /* sizeof U32 */ } FSE_DTableHeader; /* sizeof U32 */
typedef struct typedef struct {
{
unsigned short newState; unsigned short newState;
unsigned char symbol; unsigned char symbol;
unsigned char nbBits; unsigned char nbBits;
} FSE_decode_t; /* size == U32 */ } FSE_decode_t; /* size == U32 */
ZSTD_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt) ZSTD_STATIC void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt)
{ {
const void* ptr = dt; const void *ptr = dt;
const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr; const FSE_DTableHeader *const DTableH = (const FSE_DTableHeader *)ptr;
DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog); DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
BIT_reloadDStream(bitD); BIT_reloadDStream(bitD);
DStatePtr->table = dt + 1; DStatePtr->table = dt + 1;
} }
ZSTD_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr) ZSTD_STATIC BYTE FSE_peekSymbol(const FSE_DState_t *DStatePtr)
{ {
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
return DInfo.symbol; return DInfo.symbol;
} }
ZSTD_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) ZSTD_STATIC void FSE_updateState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
{ {
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
U32 const nbBits = DInfo.nbBits; U32 const nbBits = DInfo.nbBits;
size_t const lowBits = BIT_readBits(bitD, nbBits); size_t const lowBits = BIT_readBits(bitD, nbBits);
DStatePtr->state = DInfo.newState + lowBits; DStatePtr->state = DInfo.newState + lowBits;
} }
ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
{ {
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
U32 const nbBits = DInfo.nbBits; U32 const nbBits = DInfo.nbBits;
BYTE const symbol = DInfo.symbol; BYTE const symbol = DInfo.symbol;
size_t const lowBits = BIT_readBits(bitD, nbBits); size_t const lowBits = BIT_readBits(bitD, nbBits);
@ -539,9 +523,9 @@ ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
/*! FSE_decodeSymbolFast() : /*! FSE_decodeSymbolFast() :
unsafe, only works if no symbol has a probability > 50% */ unsafe, only works if no symbol has a probability > 50% */
ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD) ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
{ {
FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state]; FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
U32 const nbBits = DInfo.nbBits; U32 const nbBits = DInfo.nbBits;
BYTE const symbol = DInfo.symbol; BYTE const symbol = DInfo.symbol;
size_t const lowBits = BIT_readBitsFast(bitD, nbBits); size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
@ -550,12 +534,7 @@ ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bi
return symbol; return symbol;
} }
ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr) { return DStatePtr->state == 0; }
{
return DStatePtr->state == 0;
}
#ifndef FSE_COMMONDEFS_ONLY #ifndef FSE_COMMONDEFS_ONLY
@ -568,17 +547,17 @@ ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
* Reduced memory usage can improve speed, due to cache effect * Reduced memory usage can improve speed, due to cache effect
* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
#ifndef FSE_MAX_MEMORY_USAGE #ifndef FSE_MAX_MEMORY_USAGE
# define FSE_MAX_MEMORY_USAGE 14 #define FSE_MAX_MEMORY_USAGE 14
#endif #endif
#ifndef FSE_DEFAULT_MEMORY_USAGE #ifndef FSE_DEFAULT_MEMORY_USAGE
# define FSE_DEFAULT_MEMORY_USAGE 13 #define FSE_DEFAULT_MEMORY_USAGE 13
#endif #endif
/*!FSE_MAX_SYMBOL_VALUE : /*!FSE_MAX_SYMBOL_VALUE :
* Maximum symbol value authorized. * Maximum symbol value authorized.
* Required for proper stack allocation */ * Required for proper stack allocation */
#ifndef FSE_MAX_SYMBOL_VALUE #ifndef FSE_MAX_SYMBOL_VALUE
# define FSE_MAX_SYMBOL_VALUE 255 #define FSE_MAX_SYMBOL_VALUE 255
#endif #endif
/* ************************************************************** /* **************************************************************
@ -588,25 +567,22 @@ ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
#define FSE_FUNCTION_EXTENSION #define FSE_FUNCTION_EXTENSION
#define FSE_DECODE_TYPE FSE_decode_t #define FSE_DECODE_TYPE FSE_decode_t
#endif /* !FSE_COMMONDEFS_ONLY */
#endif /* !FSE_COMMONDEFS_ONLY */
/* *************************************************************** /* ***************************************************************
* Constants * Constants
*****************************************************************/ *****************************************************************/
#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2) #define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE - 2)
#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG) #define FSE_MAX_TABLESIZE (1U << FSE_MAX_TABLELOG)
#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1) #define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE - 1)
#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2) #define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE - 2)
#define FSE_MIN_TABLELOG 5 #define FSE_MIN_TABLELOG 5
#define FSE_TABLELOG_ABSOLUTE_MAX 15 #define FSE_TABLELOG_ABSOLUTE_MAX 15
#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX #if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" #error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
#endif #endif
#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3) #define FSE_TABLESTEP(tableSize) ((tableSize >> 1) + (tableSize >> 3) + 3)
#endif /* FSE_H */
#endif /* FSE_H */

File diff suppressed because it is too large Load Diff

View File

@ -37,31 +37,35 @@
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
*/ */
/* ************************************************************** /* **************************************************************
* Compiler specifics * Compiler specifics
****************************************************************/ ****************************************************************/
#define FORCE_INLINE static __always_inline #define FORCE_INLINE static __always_inline
/* ************************************************************** /* **************************************************************
* Includes * Includes
****************************************************************/ ****************************************************************/
#include <linux/compiler.h>
#include <linux/string.h> /* memcpy, memset */
#include "bitstream.h" #include "bitstream.h"
#include "fse.h" #include "fse.h"
#include <linux/compiler.h>
#include <linux/string.h> /* memcpy, memset */
/* ************************************************************** /* **************************************************************
* Error Management * Error Management
****************************************************************/ ****************************************************************/
#define FSE_isError ERR_isError #define FSE_isError ERR_isError
#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ #define FSE_STATIC_ASSERT(c) \
{ \
enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
} /* use only *after* variable declarations */
/* check and forward error code */ /* check and forward error code */
#define CHECK_F(f) { size_t const e = f; if (FSE_isError(e)) return e; } #define CHECK_F(f) \
{ \
size_t const e = f; \
if (FSE_isError(e)) \
return e; \
}
/* ************************************************************** /* **************************************************************
* Templates * Templates
@ -74,89 +78,100 @@
/* safety checks */ /* safety checks */
#ifndef FSE_FUNCTION_EXTENSION #ifndef FSE_FUNCTION_EXTENSION
# error "FSE_FUNCTION_EXTENSION must be defined" #error "FSE_FUNCTION_EXTENSION must be defined"
#endif #endif
#ifndef FSE_FUNCTION_TYPE #ifndef FSE_FUNCTION_TYPE
# error "FSE_FUNCTION_TYPE must be defined" #error "FSE_FUNCTION_TYPE must be defined"
#endif #endif
/* Function names */ /* Function names */
#define FSE_CAT(X,Y) X##Y #define FSE_CAT(X, Y) X##Y
#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y) #define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y) #define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
/* Function templates */ /* Function templates */
size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) size_t FSE_buildDTable(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
{ {
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr);
U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; U16 symbolNext[FSE_MAX_SYMBOL_VALUE + 1];
U32 const maxSV1 = maxSymbolValue + 1; U32 const maxSV1 = maxSymbolValue + 1;
U32 const tableSize = 1 << tableLog; U32 const tableSize = 1 << tableLog;
U32 highThreshold = tableSize-1; U32 highThreshold = tableSize - 1;
/* Sanity Checks */ /* Sanity Checks */
if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE)
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); return ERROR(maxSymbolValue_tooLarge);
if (tableLog > FSE_MAX_TABLELOG)
return ERROR(tableLog_tooLarge);
/* Init, lay down lowprob symbols */ /* Init, lay down lowprob symbols */
{ FSE_DTableHeader DTableH; {
FSE_DTableHeader DTableH;
DTableH.tableLog = (U16)tableLog; DTableH.tableLog = (U16)tableLog;
DTableH.fastMode = 1; DTableH.fastMode = 1;
{ S16 const largeLimit= (S16)(1 << (tableLog-1)); {
S16 const largeLimit = (S16)(1 << (tableLog - 1));
U32 s; U32 s;
for (s=0; s<maxSV1; s++) { for (s = 0; s < maxSV1; s++) {
if (normalizedCounter[s]==-1) { if (normalizedCounter[s] == -1) {
tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s; tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
symbolNext[s] = 1; symbolNext[s] = 1;
} else { } else {
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0; if (normalizedCounter[s] >= largeLimit)
DTableH.fastMode = 0;
symbolNext[s] = normalizedCounter[s]; symbolNext[s] = normalizedCounter[s];
} } } }
}
}
memcpy(dt, &DTableH, sizeof(DTableH)); memcpy(dt, &DTableH, sizeof(DTableH));
} }
/* Spread symbols */ /* Spread symbols */
{ U32 const tableMask = tableSize-1; {
U32 const tableMask = tableSize - 1;
U32 const step = FSE_TABLESTEP(tableSize); U32 const step = FSE_TABLESTEP(tableSize);
U32 s, position = 0; U32 s, position = 0;
for (s=0; s<maxSV1; s++) { for (s = 0; s < maxSV1; s++) {
int i; int i;
for (i=0; i<normalizedCounter[s]; i++) { for (i = 0; i < normalizedCounter[s]; i++) {
tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s; tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
position = (position + step) & tableMask; position = (position + step) & tableMask;
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ 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 */ }
}
if (position != 0)
return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
} }
/* Build Decoding table */ /* Build Decoding table */
{ U32 u; {
for (u=0; u<tableSize; u++) { U32 u;
for (u = 0; u < tableSize; u++) {
FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol); FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
U16 nextState = symbolNext[symbol]++; U16 nextState = symbolNext[symbol]++;
tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) ); tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState));
tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize); tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
} } }
}
return 0; return 0;
} }
#ifndef FSE_COMMONDEFS_ONLY #ifndef FSE_COMMONDEFS_ONLY
/*-******************************************************* /*-*******************************************************
* Decompression (Byte symbols) * Decompression (Byte symbols)
*********************************************************/ *********************************************************/
size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue) size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue)
{ {
void* ptr = dt; void *ptr = dt;
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
void* dPtr = dt + 1; void *dPtr = dt + 1;
FSE_decode_t* const cell = (FSE_decode_t*)dPtr; FSE_decode_t *const cell = (FSE_decode_t *)dPtr;
DTableH->tableLog = 0; DTableH->tableLog = 0;
DTableH->fastMode = 0; DTableH->fastMode = 0;
@ -168,25 +183,25 @@ size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
return 0; return 0;
} }
size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits)
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
{ {
void* ptr = dt; void *ptr = dt;
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr; FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
void* dPtr = dt + 1; void *dPtr = dt + 1;
FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr; FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr;
const unsigned tableSize = 1 << nbBits; const unsigned tableSize = 1 << nbBits;
const unsigned tableMask = tableSize - 1; const unsigned tableMask = tableSize - 1;
const unsigned maxSV1 = tableMask+1; const unsigned maxSV1 = tableMask + 1;
unsigned s; unsigned s;
/* Sanity checks */ /* Sanity checks */
if (nbBits < 1) return ERROR(GENERIC); /* min size */ if (nbBits < 1)
return ERROR(GENERIC); /* min size */
/* Build Decoding Table */ /* Build Decoding Table */
DTableH->tableLog = (U16)nbBits; DTableH->tableLog = (U16)nbBits;
DTableH->fastMode = 1; DTableH->fastMode = 1;
for (s=0; s<maxSV1; s++) { for (s = 0; s < maxSV1; s++) {
dinfo[s].newState = 0; dinfo[s].newState = 0;
dinfo[s].symbol = (BYTE)s; dinfo[s].symbol = (BYTE)s;
dinfo[s].nbBits = (BYTE)nbBits; dinfo[s].nbBits = (BYTE)nbBits;
@ -195,15 +210,13 @@ size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
return 0; return 0;
} }
FORCE_INLINE size_t FSE_decompress_usingDTable_generic( FORCE_INLINE size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt,
void* dst, size_t maxDstSize, const unsigned fast)
const void* cSrc, size_t cSrcSize,
const FSE_DTable* dt, const unsigned fast)
{ {
BYTE* const ostart = (BYTE*) dst; BYTE *const ostart = (BYTE *)dst;
BYTE* op = ostart; BYTE *op = ostart;
BYTE* const omax = op + maxDstSize; BYTE *const omax = op + maxDstSize;
BYTE* const olimit = omax-3; BYTE *const olimit = omax - 3;
BIT_DStream_t bitD; BIT_DStream_t bitD;
FSE_DState_t state1; FSE_DState_t state1;
@ -218,20 +231,25 @@ FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD) #define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
/* 4 symbols per loop */ /* 4 symbols per loop */
for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) { for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) {
op[0] = FSE_GETSYMBOL(&state1); op[0] = FSE_GETSYMBOL(&state1);
if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
BIT_reloadDStream(&bitD); BIT_reloadDStream(&bitD);
op[1] = FSE_GETSYMBOL(&state2); op[1] = FSE_GETSYMBOL(&state2);
if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
{ if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } } {
if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) {
op += 2;
break;
}
}
op[2] = FSE_GETSYMBOL(&state1); op[2] = FSE_GETSYMBOL(&state1);
if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */ if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
BIT_reloadDStream(&bitD); BIT_reloadDStream(&bitD);
op[3] = FSE_GETSYMBOL(&state2); op[3] = FSE_GETSYMBOL(&state2);
@ -240,58 +258,60 @@ FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
/* tail */ /* tail */
/* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */ /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
while (1) { while (1) {
if (op>(omax-2)) return ERROR(dstSize_tooSmall); if (op > (omax - 2))
return ERROR(dstSize_tooSmall);
*op++ = FSE_GETSYMBOL(&state1); *op++ = FSE_GETSYMBOL(&state1);
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
*op++ = FSE_GETSYMBOL(&state2); *op++ = FSE_GETSYMBOL(&state2);
break; break;
} }
if (op>(omax-2)) return ERROR(dstSize_tooSmall); if (op > (omax - 2))
return ERROR(dstSize_tooSmall);
*op++ = FSE_GETSYMBOL(&state2); *op++ = FSE_GETSYMBOL(&state2);
if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) { if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
*op++ = FSE_GETSYMBOL(&state1); *op++ = FSE_GETSYMBOL(&state1);
break; break;
} } }
}
return op-ostart; return op - ostart;
} }
size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt)
size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
const void* cSrc, size_t cSrcSize,
const FSE_DTable* dt)
{ {
const void* ptr = dt; const void *ptr = dt;
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr;
const U32 fastMode = DTableH->fastMode; const U32 fastMode = DTableH->fastMode;
/* select fast mode (static) */ /* select fast mode (static) */
if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1); if (fastMode)
return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0); return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
} }
size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, FSE_DTable *workSpace, unsigned maxLog)
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog)
{ {
const BYTE* const istart = (const BYTE*)cSrc; const BYTE *const istart = (const BYTE *)cSrc;
const BYTE* ip = istart; const BYTE *ip = istart;
short counting[FSE_MAX_SYMBOL_VALUE+1]; short counting[FSE_MAX_SYMBOL_VALUE + 1];
unsigned tableLog; unsigned tableLog;
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
/* normal FSE decoding mode */ /* normal FSE decoding mode */
size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); size_t const NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
if (FSE_isError(NCountLength)) return NCountLength; if (FSE_isError(NCountLength))
//if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ return NCountLength;
if (tableLog > maxLog) return ERROR(tableLog_tooLarge); // if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining
// case : NCountLength==cSrcSize */
if (tableLog > maxLog)
return ERROR(tableLog_tooLarge);
ip += NCountLength; ip += NCountLength;
cSrcSize -= NCountLength; cSrcSize -= NCountLength;
CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); CHECK_F(FSE_buildDTable(workSpace, counting, maxSymbolValue, tableLog));
return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */
} }
#endif /* FSE_COMMONDEFS_ONLY */
#endif /* FSE_COMMONDEFS_ONLY */

View File

@ -40,77 +40,68 @@
#ifndef HUF_H_298734234 #ifndef HUF_H_298734234
#define HUF_H_298734234 #define HUF_H_298734234
/* *** Dependencies *** */ /* *** Dependencies *** */
#include <linux/types.h> /* size_t */ #include <linux/types.h> /* size_t */
/* *** Tool functions *** */ /* *** Tool functions *** */
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */ #define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */ size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
/* Error Management */ /* Error Management */
unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */ unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
/* *** Advanced function *** */ /* *** Advanced function *** */
/** HUF_compress4X_wksp() : /** HUF_compress4X_wksp() :
* Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */ * Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */
size_t HUF_compress4X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ size_t HUF_compress4X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
/* *** Dependencies *** */ /* *** Dependencies *** */
#include "mem.h" /* U32 */ #include "mem.h" /* U32 */
/* *** Constants *** */ /* *** Constants *** */
#define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */ #define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */ #define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
#define HUF_SYMBOLVALUE_MAX 255 #define HUF_SYMBOLVALUE_MAX 255
#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */ #define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX) #if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
# error "HUF_TABLELOG_MAX is too large !" #error "HUF_TABLELOG_MAX is too large !"
#endif #endif
/* **************************************** /* ****************************************
* Static allocation * Static allocation
******************************************/ ******************************************/
/* HUF buffer bounds */ /* HUF buffer bounds */
#define HUF_CTABLEBOUND 129 #define HUF_CTABLEBOUND 129
#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true if incompressible pre-filtered with fast heuristic */ #define HUF_BLOCKBOUND(size) (size + (size >> 8) + 8) /* only true if incompressible pre-filtered with fast heuristic */
#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
/* static allocation of HUF's Compression Table */ /* static allocation of HUF's Compression Table */
#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ #define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
U32 name##hb[maxSymbolValue+1]; \ U32 name##hb[maxSymbolValue + 1]; \
void* name##hv = &(name##hb); \ void *name##hv = &(name##hb); \
HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */ HUF_CElt *name = (HUF_CElt *)(name##hv) /* no final ; */
/* static allocation of HUF's DTable */ /* static allocation of HUF's DTable */
typedef U32 HUF_DTable; typedef U32 HUF_DTable;
#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog))) #define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << (maxTableLog)))
#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \ #define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = {((U32)((maxTableLog)-1) * 0x01000001)}
HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) } #define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = {((U32)(maxTableLog)*0x01000001)}
#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \
HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
/* The workspace must have alignment at least 4 and be at least this large */ /* The workspace must have alignment at least 4 and be at least this large */
#define HUF_WORKSPACE_SIZE (6 << 10) #define HUF_WORKSPACE_SIZE (6 << 10)
#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32)) #define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
/* **************************************** /* ****************************************
* Advanced decompression functions * Advanced decompression functions
******************************************/ ******************************************/
size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */ size_t HUF_decompress4X_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */ size_t HUF_decompress4X_hufOnly(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc,
size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ size_t cSrcSize); /**< considers RLE and uncompressed as errors */
size_t HUF_decompress4X4_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ size_t HUF_decompress4X2_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< single-symbol decoder */
size_t HUF_decompress4X4_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< double-symbols decoder */
/* **************************************** /* ****************************************
* HUF detailed API * HUF detailed API
@ -129,41 +120,41 @@ or to save and regenerate 'CTable' using external methods.
*/ */
/* FSE_count() : find it within "fse.h" */ /* FSE_count() : find it within "fse.h" */
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); size_t HUF_writeCTable(void *dst, size_t maxDstSize, const HUF_CElt *CTable, unsigned maxSymbolValue, unsigned huffLog);
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
typedef enum { typedef enum {
HUF_repeat_none, /**< Cannot use the previous table */ HUF_repeat_none, /**< Cannot use the previous table */
HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */ HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */ 4}X_repeat */
} HUF_repeat; HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
} HUF_repeat;
/** HUF_compress4X_repeat() : /** HUF_compress4X_repeat() :
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
* If it uses hufTable it does not modify hufTable or repeat. * If it uses hufTable it does not modify hufTable or repeat.
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
* If preferRepeat then the old table will always be used if valid. */ * If preferRepeat then the old table will always be used if valid. */
size_t HUF_compress4X_repeat(void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ size_t HUF_compress4X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
/** HUF_buildCTable_wksp() : /** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer. * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned. * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
*/ */
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize); size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize);
/*! HUF_readStats() : /*! HUF_readStats() :
Read compact Huffman tree, saved by HUF_writeCTable(). Read compact Huffman tree, saved by HUF_writeCTable().
`huffWeight` is destination buffer. `huffWeight` is destination buffer.
@return : size read from `src` , or an error Code . @return : size read from `src` , or an error Code .
Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */ Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, size_t HUF_readStats(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize);
U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize);
/** HUF_readCTable() : /** HUF_readCTable() :
* Loading a CTable saved with HUF_writeCTable() */ * Loading a CTable saved with HUF_writeCTable() */
size_t HUF_readCTable (HUF_CElt* CTable, unsigned maxSymbolValue, const void* src, size_t srcSize); size_t HUF_readCTable(HUF_CElt *CTable, unsigned maxSymbolValue, const void *src, size_t srcSize);
/* /*
HUF_decompress() does the following: HUF_decompress() does the following:
@ -177,33 +168,36 @@ HUF_decompress() does the following:
* based on a set of pre-determined metrics. * based on a set of pre-determined metrics.
* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 . * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
* Assumption : 0 < cSrcSize < dstSize <= 128 KB */ * Assumption : 0 < cSrcSize < dstSize <= 128 KB */
U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize); U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize);
size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize); size_t HUF_readDTableX2(HUF_DTable *DTable, const void *src, size_t srcSize);
size_t HUF_readDTableX4 (HUF_DTable* DTable, const void* src, size_t srcSize); size_t HUF_readDTableX4(HUF_DTable *DTable, const void *src, size_t srcSize);
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
size_t HUF_decompress4X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
size_t HUF_decompress4X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
/* single stream variants */ /* single stream variants */
size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ size_t HUF_compress1X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
/** HUF_compress1X_repeat() : /** HUF_compress1X_repeat() :
* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none. * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
* If it uses hufTable it does not modify hufTable or repeat. * If it uses hufTable it does not modify hufTable or repeat.
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used. * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
* If preferRepeat then the old table will always be used if valid. */ * If preferRepeat then the old table will always be used if valid. */
size_t HUF_compress1X_repeat(void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize, HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ size_t HUF_compress1X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
int preferRepeat); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); size_t HUF_decompress1X_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize);
size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */ size_t HUF_decompress1X2_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< single-symbol decoder */
size_t HUF_decompress1X4_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */ size_t HUF_decompress1X4_DCtx(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize); /**< double-symbols decoder */
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */ size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize,
size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); const HUF_DTable *DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
size_t HUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); size_t HUF_decompress1X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
size_t HUF_decompress1X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
#endif /* HUF_H_298734234 */ #endif /* HUF_H_298734234 */

View File

@ -37,23 +37,29 @@
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
*/ */
/* ************************************************************** /* **************************************************************
* Includes * Includes
****************************************************************/ ****************************************************************/
#include <linux/string.h> /* memcpy, memset */
#include "bitstream.h" #include "bitstream.h"
#include "fse.h" /* header compression */ #include "fse.h" /* header compression */
#include "huf.h" #include "huf.h"
#include <linux/string.h> /* memcpy, memset */
/* ************************************************************** /* **************************************************************
* Error Management * Error Management
****************************************************************/ ****************************************************************/
#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ #define HUF_STATIC_ASSERT(c) \
#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return f { \
#define CHECK_F(f) { CHECK_V_F(_var_err__, f); } enum { HUF_static_assert = 1 / (int)(!!(c)) }; \
} /* use only *after* variable declarations */
#define CHECK_V_F(e, f) \
size_t const e = f; \
if (ERR_isError(e)) \
return f
#define CHECK_F(f) \
{ \
CHECK_V_F(_var_err__, f); \
}
/* ************************************************************** /* **************************************************************
* Utils * Utils
@ -63,7 +69,6 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1); return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);
} }
/* ******************************************************* /* *******************************************************
* HUF : Huffman block compression * HUF : Huffman block compression
*********************************************************/ *********************************************************/
@ -73,141 +78,168 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX. * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
*/ */
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6 #define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize) size_t HUF_compressWeights(void *dst, size_t dstSize, const void *weightTable, size_t wtSize)
{ {
BYTE* const ostart = (BYTE*) dst; BYTE *const ostart = (BYTE *)dst;
BYTE* op = ostart; BYTE *op = ostart;
BYTE* const oend = ostart + dstSize; BYTE *const oend = ostart + dstSize;
U32 maxSymbolValue = HUF_TABLELOG_MAX; U32 maxSymbolValue = HUF_TABLELOG_MAX;
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER]; BYTE scratchBuffer[1 << MAX_FSE_TABLELOG_FOR_HUFF_HEADER];
U32 count[HUF_TABLELOG_MAX+1]; U32 count[HUF_TABLELOG_MAX + 1];
S16 norm[HUF_TABLELOG_MAX+1]; S16 norm[HUF_TABLELOG_MAX + 1];
/* init conditions */ /* init conditions */
if (wtSize <= 1) return 0; /* Not compressible */ if (wtSize <= 1)
return 0; /* Not compressible */
/* Scan input and build symbol stats */ /* Scan input and build symbol stats */
{ CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize) ); {
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */ CHECK_V_F(maxCount, FSE_count_simple(count, &maxSymbolValue, weightTable, wtSize));
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */ if (maxCount == wtSize)
return 1; /* only a single symbol in src : rle */
if (maxCount == 1)
return 0; /* each symbol present maximum once => not compressible */
} }
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); CHECK_F(FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue));
/* Write table description header */ /* Write table description header */
{ CHECK_V_F(hSize, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); {
CHECK_V_F(hSize, FSE_writeNCount(op, oend - op, norm, maxSymbolValue, tableLog));
op += hSize; op += hSize;
} }
/* Compress */ /* Compress */
CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) ); CHECK_F(FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)));
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable) ); {
if (cSize == 0) return 0; /* not enough space for compressed data */ CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, weightTable, wtSize, CTable));
if (cSize == 0)
return 0; /* not enough space for compressed data */
op += cSize; op += cSize;
} }
return op-ostart; return op - ostart;
} }
struct HUF_CElt_s { struct HUF_CElt_s {
U16 val; U16 val;
BYTE nbBits; BYTE nbBits;
}; /* typedef'd to HUF_CElt within "huf.h" */ }; /* typedef'd to HUF_CElt within "huf.h" */
/*! HUF_writeCTable() : /*! HUF_writeCTable() :
`CTable` : Huffman tree to save, using huf representation. `CTable` : Huffman tree to save, using huf representation.
@return : size of saved CTable */ @return : size of saved CTable */
size_t HUF_writeCTable (void* dst, size_t maxDstSize, size_t HUF_writeCTable(void *dst, size_t maxDstSize, const HUF_CElt *CTable, U32 maxSymbolValue, U32 huffLog)
const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
{ {
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */ BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
BYTE huffWeight[HUF_SYMBOLVALUE_MAX]; BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
BYTE* op = (BYTE*)dst; BYTE *op = (BYTE *)dst;
U32 n; U32 n;
/* check conditions */ /* check conditions */
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge); if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)
return ERROR(maxSymbolValue_tooLarge);
/* convert to weight */ /* convert to weight */
bitsToWeight[0] = 0; bitsToWeight[0] = 0;
for (n=1; n<huffLog+1; n++) for (n = 1; n < huffLog + 1; n++)
bitsToWeight[n] = (BYTE)(huffLog + 1 - n); bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
for (n=0; n<maxSymbolValue; n++) for (n = 0; n < maxSymbolValue; n++)
huffWeight[n] = bitsToWeight[CTable[n].nbBits]; huffWeight[n] = bitsToWeight[CTable[n].nbBits];
/* attempt weights compression by FSE */ /* attempt weights compression by FSE */
{ CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) ); {
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */ CHECK_V_F(hSize, HUF_compressWeights(op + 1, maxDstSize - 1, huffWeight, maxSymbolValue));
if ((hSize > 1) & (hSize < maxSymbolValue / 2)) { /* FSE compressed */
op[0] = (BYTE)hSize; op[0] = (BYTE)hSize;
return hSize+1; return hSize + 1;
} } }
}
/* write raw values as 4-bits (max : 15) */ /* write raw values as 4-bits (max : 15) */
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */ if (maxSymbolValue > (256 - 128))
if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */ return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1)); if (((maxSymbolValue + 1) / 2) + 1 > maxDstSize)
huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */ return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
for (n=0; n<maxSymbolValue; n+=2) op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue - 1));
op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]); huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
return ((maxSymbolValue+1)/2) + 1; for (n = 0; n < maxSymbolValue; n += 2)
op[(n / 2) + 1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n + 1]);
return ((maxSymbolValue + 1) / 2) + 1;
} }
size_t HUF_readCTable(HUF_CElt *CTable, U32 maxSymbolValue, const void *src, size_t srcSize)
size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
{ {
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */ BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; /* init not required, even though some static analyzer may complain */
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */ U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
U32 tableLog = 0; U32 tableLog = 0;
U32 nbSymbols = 0; U32 nbSymbols = 0;
/* get symbol weights */ /* get symbol weights */
CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize)); CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize));
/* check result */ /* check result */
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); if (tableLog > HUF_TABLELOG_MAX)
if (nbSymbols > maxSymbolValue+1) return ERROR(maxSymbolValue_tooSmall); return ERROR(tableLog_tooLarge);
if (nbSymbols > maxSymbolValue + 1)
return ERROR(maxSymbolValue_tooSmall);
/* Prepare base value per rank */ /* Prepare base value per rank */
{ U32 n, nextRankStart = 0; {
for (n=1; n<=tableLog; n++) { U32 n, nextRankStart = 0;
for (n = 1; n <= tableLog; n++) {
U32 curr = nextRankStart; U32 curr = nextRankStart;
nextRankStart += (rankVal[n] << (n-1)); nextRankStart += (rankVal[n] << (n - 1));
rankVal[n] = curr; rankVal[n] = curr;
} } }
}
/* fill nbBits */ /* fill nbBits */
{ U32 n; for (n=0; n<nbSymbols; n++) { {
U32 n;
for (n = 0; n < nbSymbols; n++) {
const U32 w = huffWeight[n]; const U32 w = huffWeight[n];
CTable[n].nbBits = (BYTE)(tableLog + 1 - w); CTable[n].nbBits = (BYTE)(tableLog + 1 - w);
} } }
}
/* fill val */ /* fill val */
{ U16 nbPerRank[HUF_TABLELOG_MAX+2] = {0}; /* support w=0=>n=tableLog+1 */ {
U16 valPerRank[HUF_TABLELOG_MAX+2] = {0}; U16 nbPerRank[HUF_TABLELOG_MAX + 2] = {0}; /* support w=0=>n=tableLog+1 */
{ U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; } U16 valPerRank[HUF_TABLELOG_MAX + 2] = {0};
{
U32 n;
for (n = 0; n < nbSymbols; n++)
nbPerRank[CTable[n].nbBits]++;
}
/* determine stating value per rank */ /* determine stating value per rank */
valPerRank[tableLog+1] = 0; /* for w==0 */ valPerRank[tableLog + 1] = 0; /* for w==0 */
{ U16 min = 0; {
U32 n; for (n=tableLog; n>0; n--) { /* start at n=tablelog <-> w=1 */ U16 min = 0;
U32 n;
for (n = tableLog; n > 0; n--) { /* start at n=tablelog <-> w=1 */
valPerRank[n] = min; /* get starting value within each rank */ valPerRank[n] = min; /* get starting value within each rank */
min += nbPerRank[n]; min += nbPerRank[n];
min >>= 1; min >>= 1;
} } }
}
/* 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]++; } {
U32 n;
for (n = 0; n <= maxSymbolValue; n++)
CTable[n].val = valPerRank[CTable[n].nbBits]++;
}
} }
return readSize; return readSize;
} }
typedef struct nodeElt_s { typedef struct nodeElt_s {
U32 count; U32 count;
U16 parent; U16 parent;
@ -215,130 +247,153 @@ typedef struct nodeElt_s {
BYTE nbBits; BYTE nbBits;
} nodeElt; } nodeElt;
static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) static U32 HUF_setMaxHeight(nodeElt *huffNode, U32 lastNonNull, U32 maxNbBits)
{ {
const U32 largestBits = huffNode[lastNonNull].nbBits; const U32 largestBits = huffNode[lastNonNull].nbBits;
if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */ if (largestBits <= maxNbBits)
return largestBits; /* early exit : no elt > maxNbBits */
/* there are several too large elements (at least >= 2) */ /* there are several too large elements (at least >= 2) */
{ int totalCost = 0; {
int totalCost = 0;
const U32 baseCost = 1 << (largestBits - maxNbBits); const U32 baseCost = 1 << (largestBits - maxNbBits);
U32 n = lastNonNull; U32 n = lastNonNull;
while (huffNode[n].nbBits > maxNbBits) { while (huffNode[n].nbBits > maxNbBits) {
totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));
huffNode[n].nbBits = (BYTE)maxNbBits; huffNode[n].nbBits = (BYTE)maxNbBits;
n --; n--;
} /* n stops at huffNode[n].nbBits <= maxNbBits */ } /* n stops at huffNode[n].nbBits <= maxNbBits */
while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */ while (huffNode[n].nbBits == maxNbBits)
n--; /* n end at index of smallest symbol using < maxNbBits */
/* renorm totalCost */ /* renorm totalCost */
totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */
/* repay normalized cost */ /* repay normalized cost */
{ U32 const noSymbol = 0xF0F0F0F0; {
U32 rankLast[HUF_TABLELOG_MAX+2]; U32 const noSymbol = 0xF0F0F0F0;
U32 rankLast[HUF_TABLELOG_MAX + 2];
int pos; int pos;
/* Get pos of last (smallest) symbol per rank */ /* Get pos of last (smallest) symbol per rank */
memset(rankLast, 0xF0, sizeof(rankLast)); memset(rankLast, 0xF0, sizeof(rankLast));
{ U32 currNbBits = maxNbBits; {
for (pos=n ; pos >= 0; pos--) { U32 currNbBits = maxNbBits;
if (huffNode[pos].nbBits >= currNbBits) continue; for (pos = n; pos >= 0; pos--) {
currNbBits = huffNode[pos].nbBits; /* < maxNbBits */ if (huffNode[pos].nbBits >= currNbBits)
rankLast[maxNbBits-currNbBits] = pos; continue;
} } currNbBits = huffNode[pos].nbBits; /* < maxNbBits */
rankLast[maxNbBits - currNbBits] = pos;
}
}
while (totalCost > 0) { while (totalCost > 0) {
U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1; U32 nBitsToDecrease = BIT_highbit32(totalCost) + 1;
for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { for (; nBitsToDecrease > 1; nBitsToDecrease--) {
U32 highPos = rankLast[nBitsToDecrease]; U32 highPos = rankLast[nBitsToDecrease];
U32 lowPos = rankLast[nBitsToDecrease-1]; U32 lowPos = rankLast[nBitsToDecrease - 1];
if (highPos == noSymbol) continue; if (highPos == noSymbol)
if (lowPos == noSymbol) break; continue;
{ U32 const highTotal = huffNode[highPos].count; if (lowPos == noSymbol)
break;
{
U32 const highTotal = huffNode[highPos].count;
U32 const lowTotal = 2 * huffNode[lowPos].count; U32 const lowTotal = 2 * huffNode[lowPos].count;
if (highTotal <= lowTotal) break; if (highTotal <= lowTotal)
} } break;
}
}
/* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */
while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ while (
nBitsToDecrease ++; (nBitsToDecrease <= HUF_TABLELOG_MAX) &&
totalCost -= 1 << (nBitsToDecrease-1); (rankLast[nBitsToDecrease] == noSymbol)) /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */
if (rankLast[nBitsToDecrease-1] == noSymbol) nBitsToDecrease++;
rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ totalCost -= 1 << (nBitsToDecrease - 1);
huffNode[rankLast[nBitsToDecrease]].nbBits ++; if (rankLast[nBitsToDecrease - 1] == noSymbol)
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ rankLast[nBitsToDecrease - 1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */
huffNode[rankLast[nBitsToDecrease]].nbBits++;
if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */
rankLast[nBitsToDecrease] = noSymbol; rankLast[nBitsToDecrease] = noSymbol;
else { else {
rankLast[nBitsToDecrease]--; rankLast[nBitsToDecrease]--;
if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease) if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits - nBitsToDecrease)
rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */
} } /* while (totalCost > 0) */ }
} /* while (totalCost > 0) */
while (totalCost < 0) { /* Sometimes, cost correction overshoot */ 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) */ if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0
while (huffNode[n].nbBits == maxNbBits) n--; (using maxNbBits) */
huffNode[n+1].nbBits--; while (huffNode[n].nbBits == maxNbBits)
rankLast[1] = n+1; n--;
huffNode[n + 1].nbBits--;
rankLast[1] = n + 1;
totalCost++; totalCost++;
continue; continue;
} }
huffNode[ rankLast[1] + 1 ].nbBits--; huffNode[rankLast[1] + 1].nbBits--;
rankLast[1]++; rankLast[1]++;
totalCost ++; totalCost++;
} } } /* there are several too large elements (at least >= 2) */ }
}
} /* there are several too large elements (at least >= 2) */
return maxNbBits; return maxNbBits;
} }
typedef struct { typedef struct {
U32 base; U32 base;
U32 curr; U32 curr;
} rankPos; } rankPos;
static void HUF_sort(nodeElt* huffNode, const U32* count, U32 maxSymbolValue) static void HUF_sort(nodeElt *huffNode, const U32 *count, U32 maxSymbolValue)
{ {
rankPos rank[32]; rankPos rank[32];
U32 n; U32 n;
memset(rank, 0, sizeof(rank)); memset(rank, 0, sizeof(rank));
for (n=0; n<=maxSymbolValue; n++) { for (n = 0; n <= maxSymbolValue; n++) {
U32 r = BIT_highbit32(count[n] + 1); U32 r = BIT_highbit32(count[n] + 1);
rank[r].base ++; rank[r].base++;
} }
for (n=30; n>0; n--) rank[n-1].base += rank[n].base; for (n = 30; n > 0; n--)
for (n=0; n<32; n++) rank[n].curr = rank[n].base; rank[n - 1].base += rank[n].base;
for (n=0; n<=maxSymbolValue; n++) { for (n = 0; n < 32; n++)
rank[n].curr = rank[n].base;
for (n = 0; n <= maxSymbolValue; n++) {
U32 const c = count[n]; U32 const c = count[n];
U32 const r = BIT_highbit32(c+1) + 1; U32 const r = BIT_highbit32(c + 1) + 1;
U32 pos = rank[r].curr++; U32 pos = rank[r].curr++;
while ((pos > rank[r].base) && (c > huffNode[pos-1].count)) huffNode[pos]=huffNode[pos-1], pos--; while ((pos > rank[r].base) && (c > huffNode[pos - 1].count))
huffNode[pos] = huffNode[pos - 1], pos--;
huffNode[pos].count = c; huffNode[pos].count = c;
huffNode[pos].byte = (BYTE)n; huffNode[pos].byte = (BYTE)n;
} }
} }
/** HUF_buildCTable_wksp() : /** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer. * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
* `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned. * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
*/ */
#define STARTNODE (HUF_SYMBOLVALUE_MAX+1) #define STARTNODE (HUF_SYMBOLVALUE_MAX + 1)
typedef nodeElt huffNodeTable[2*HUF_SYMBOLVALUE_MAX+1 +1]; typedef nodeElt huffNodeTable[2 * HUF_SYMBOLVALUE_MAX + 1 + 1];
size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize)
{ {
nodeElt* const huffNode0 = (nodeElt*)workSpace; nodeElt *const huffNode0 = (nodeElt *)workSpace;
nodeElt* const huffNode = huffNode0+1; nodeElt *const huffNode = huffNode0 + 1;
U32 n, nonNullRank; U32 n, nonNullRank;
int lowS, lowN; int lowS, lowN;
U16 nodeNb = STARTNODE; U16 nodeNb = STARTNODE;
U32 nodeRoot; U32 nodeRoot;
/* safety checks */ /* safety checks */
if (wkspSize < sizeof(huffNodeTable)) return ERROR(GENERIC); /* workSpace is not large enough */ if (wkspSize < sizeof(huffNodeTable))
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; return ERROR(GENERIC); /* workSpace is not large enough */
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC); if (maxNbBits == 0)
maxNbBits = HUF_TABLELOG_DEFAULT;
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)
return ERROR(GENERIC);
memset(huffNode0, 0, sizeof(huffNodeTable)); memset(huffNode0, 0, sizeof(huffNodeTable));
/* sort, decreasing order */ /* sort, decreasing order */
@ -346,13 +401,18 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
/* init for parents */ /* init for parents */
nonNullRank = maxSymbolValue; nonNullRank = maxSymbolValue;
while(huffNode[nonNullRank].count == 0) nonNullRank--; while (huffNode[nonNullRank].count == 0)
lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb; nonNullRank--;
huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count; lowS = nonNullRank;
huffNode[lowS].parent = huffNode[lowS-1].parent = nodeNb; nodeRoot = nodeNb + lowS - 1;
nodeNb++; lowS-=2; lowN = nodeNb;
for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30); huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS - 1].count;
huffNode0[0].count = (U32)(1U<<31); /* fake entry, strong barrier */ huffNode[lowS].parent = huffNode[lowS - 1].parent = nodeNb;
nodeNb++;
lowS -= 2;
for (n = nodeNb; n <= nodeRoot; n++)
huffNode[n].count = (U32)(1U << 30);
huffNode0[0].count = (U32)(1U << 31); /* fake entry, strong barrier */
/* create parents */ /* create parents */
while (nodeNb <= nodeRoot) { while (nodeNb <= nodeRoot) {
@ -365,37 +425,41 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const U32* count, U32 maxSymbolValu
/* distribute weights (unlimited tree height) */ /* distribute weights (unlimited tree height) */
huffNode[nodeRoot].nbBits = 0; huffNode[nodeRoot].nbBits = 0;
for (n=nodeRoot-1; n>=STARTNODE; n--) for (n = nodeRoot - 1; n >= STARTNODE; n--)
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1;
for (n=0; n<=nonNullRank; n++) for (n = 0; n <= nonNullRank; n++)
huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; huffNode[n].nbBits = huffNode[huffNode[n].parent].nbBits + 1;
/* enforce maxTableLog */ /* enforce maxTableLog */
maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits); maxNbBits = HUF_setMaxHeight(huffNode, nonNullRank, maxNbBits);
/* fill result into tree (val, nbBits) */ /* fill result into tree (val, nbBits) */
{ U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; {
U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; U16 nbPerRank[HUF_TABLELOG_MAX + 1] = {0};
if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ U16 valPerRank[HUF_TABLELOG_MAX + 1] = {0};
for (n=0; n<=nonNullRank; n++) if (maxNbBits > HUF_TABLELOG_MAX)
return ERROR(GENERIC); /* check fit into table */
for (n = 0; n <= nonNullRank; n++)
nbPerRank[huffNode[n].nbBits]++; nbPerRank[huffNode[n].nbBits]++;
/* determine stating value per rank */ /* determine stating value per rank */
{ U16 min = 0; {
for (n=maxNbBits; n>0; n--) { U16 min = 0;
valPerRank[n] = min; /* get starting value within each rank */ for (n = maxNbBits; n > 0; n--) {
valPerRank[n] = min; /* get starting value within each rank */
min += nbPerRank[n]; min += nbPerRank[n];
min >>= 1; 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++)
for (n=0; n<=maxSymbolValue; n++) tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ for (n = 0; n <= maxSymbolValue; n++)
tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */
} }
return maxNbBits; return maxNbBits;
} }
static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) static size_t HUF_estimateCompressedSize(HUF_CElt *CTable, const unsigned *count, unsigned maxSymbolValue)
{ {
size_t nbBits = 0; size_t nbBits = 0;
int s; int s;
@ -405,165 +469,180 @@ static size_t HUF_estimateCompressedSize(HUF_CElt* CTable, const unsigned* count
return nbBits >> 3; return nbBits >> 3;
} }
static int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { static int HUF_validateCTable(const HUF_CElt *CTable, const unsigned *count, unsigned maxSymbolValue)
int bad = 0; {
int s; int bad = 0;
for (s = 0; s <= (int)maxSymbolValue; ++s) { int s;
bad |= (count[s] != 0) & (CTable[s].nbBits == 0); for (s = 0; s <= (int)maxSymbolValue; ++s) {
} bad |= (count[s] != 0) & (CTable[s].nbBits == 0);
return !bad; }
return !bad;
} }
static void HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable) static void HUF_encodeSymbol(BIT_CStream_t *bitCPtr, U32 symbol, const HUF_CElt *CTable)
{ {
BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits); BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
} }
size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); } size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
#define HUF_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s)) #define HUF_FLUSHBITS(s) (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))
#define HUF_FLUSHBITS_1(stream) \ #define HUF_FLUSHBITS_1(stream) \
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*2+7) HUF_FLUSHBITS(stream) if (sizeof((stream)->bitContainer) * 8 < HUF_TABLELOG_MAX * 2 + 7) \
HUF_FLUSHBITS(stream)
#define HUF_FLUSHBITS_2(stream) \ #define HUF_FLUSHBITS_2(stream) \
if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream) if (sizeof((stream)->bitContainer) * 8 < HUF_TABLELOG_MAX * 4 + 7) \
HUF_FLUSHBITS(stream)
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable) size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable)
{ {
const BYTE* ip = (const BYTE*) src; const BYTE *ip = (const BYTE *)src;
BYTE* const ostart = (BYTE*)dst; BYTE *const ostart = (BYTE *)dst;
BYTE* const oend = ostart + dstSize; BYTE *const oend = ostart + dstSize;
BYTE* op = ostart; BYTE *op = ostart;
size_t n; size_t n;
const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize)); const unsigned fast = (dstSize >= HUF_BLOCKBOUND(srcSize));
BIT_CStream_t bitC; BIT_CStream_t bitC;
/* init */ /* init */
if (dstSize < 8) return 0; /* not enough space to compress */ if (dstSize < 8)
{ size_t const initErr = BIT_initCStream(&bitC, op, oend-op); return 0; /* not enough space to compress */
if (HUF_isError(initErr)) return 0; }
n = srcSize & ~3; /* join to mod 4 */
switch (srcSize & 3)
{ {
case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable); size_t const initErr = BIT_initCStream(&bitC, op, oend - op);
HUF_FLUSHBITS_2(&bitC); if (HUF_isError(initErr))
case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable); return 0;
HUF_FLUSHBITS_1(&bitC);
case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable);
HUF_FLUSHBITS(&bitC);
case 0 :
default: ;
} }
for (; n>0; n-=4) { /* note : n&3==0 at this stage */ n = srcSize & ~3; /* join to mod 4 */
HUF_encodeSymbol(&bitC, ip[n- 1], CTable); switch (srcSize & 3) {
case 3: HUF_encodeSymbol(&bitC, ip[n + 2], CTable); HUF_FLUSHBITS_2(&bitC);
case 2: HUF_encodeSymbol(&bitC, ip[n + 1], CTable); HUF_FLUSHBITS_1(&bitC);
case 1: HUF_encodeSymbol(&bitC, ip[n + 0], CTable); HUF_FLUSHBITS(&bitC);
case 0:
default:;
}
for (; n > 0; n -= 4) { /* note : n&3==0 at this stage */
HUF_encodeSymbol(&bitC, ip[n - 1], CTable);
HUF_FLUSHBITS_1(&bitC); HUF_FLUSHBITS_1(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 2], CTable); HUF_encodeSymbol(&bitC, ip[n - 2], CTable);
HUF_FLUSHBITS_2(&bitC); HUF_FLUSHBITS_2(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 3], CTable); HUF_encodeSymbol(&bitC, ip[n - 3], CTable);
HUF_FLUSHBITS_1(&bitC); HUF_FLUSHBITS_1(&bitC);
HUF_encodeSymbol(&bitC, ip[n- 4], CTable); HUF_encodeSymbol(&bitC, ip[n - 4], CTable);
HUF_FLUSHBITS(&bitC); HUF_FLUSHBITS(&bitC);
} }
return BIT_closeCStream(&bitC); return BIT_closeCStream(&bitC);
} }
size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable)
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
{ {
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */ size_t const segmentSize = (srcSize + 3) / 4; /* first 3 segments */
const BYTE* ip = (const BYTE*) src; const BYTE *ip = (const BYTE *)src;
const BYTE* const iend = ip + srcSize; const BYTE *const iend = ip + srcSize;
BYTE* const ostart = (BYTE*) dst; BYTE *const ostart = (BYTE *)dst;
BYTE* const oend = ostart + dstSize; BYTE *const oend = ostart + dstSize;
BYTE* op = ostart; BYTE *op = ostart;
if (dstSize < 6 + 1 + 1 + 1 + 8) return 0; /* minimum space to compress successfully */ if (dstSize < 6 + 1 + 1 + 1 + 8)
if (srcSize < 12) return 0; /* no saving possible : too small input */ return 0; /* minimum space to compress successfully */
op += 6; /* jumpTable */ if (srcSize < 12)
return 0; /* no saving possible : too small input */
op += 6; /* jumpTable */
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) ); {
if (cSize==0) return 0; CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable));
if (cSize == 0)
return 0;
ZSTD_writeLE16(ostart, (U16)cSize); ZSTD_writeLE16(ostart, (U16)cSize);
op += cSize; op += cSize;
} }
ip += segmentSize; ip += segmentSize;
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) ); {
if (cSize==0) return 0; CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable));
ZSTD_writeLE16(ostart+2, (U16)cSize); if (cSize == 0)
return 0;
ZSTD_writeLE16(ostart + 2, (U16)cSize);
op += cSize; op += cSize;
} }
ip += segmentSize; ip += segmentSize;
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, segmentSize, CTable) ); {
if (cSize==0) return 0; CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, segmentSize, CTable));
ZSTD_writeLE16(ostart+4, (U16)cSize); if (cSize == 0)
return 0;
ZSTD_writeLE16(ostart + 4, (U16)cSize);
op += cSize; op += cSize;
} }
ip += segmentSize; ip += segmentSize;
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend-op, ip, iend-ip, CTable) ); {
if (cSize==0) return 0; CHECK_V_F(cSize, HUF_compress1X_usingCTable(op, oend - op, ip, iend - ip, CTable));
if (cSize == 0)
return 0;
op += cSize; op += cSize;
} }
return op-ostart; return op - ostart;
} }
static size_t HUF_compressCTable_internal(BYTE *const ostart, BYTE *op, BYTE *const oend, const void *src, size_t srcSize, unsigned singleStream,
static size_t HUF_compressCTable_internal( const HUF_CElt *CTable)
BYTE* const ostart, BYTE* op, BYTE* const oend,
const void* src, size_t srcSize,
unsigned singleStream, const HUF_CElt* CTable)
{ {
size_t const cSize = singleStream ? size_t const cSize =
HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) : singleStream ? HUF_compress1X_usingCTable(op, oend - op, src, srcSize, CTable) : HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable);
HUF_compress4X_usingCTable(op, oend - op, src, srcSize, CTable); if (HUF_isError(cSize)) {
if (HUF_isError(cSize)) { return cSize; } return cSize;
if (cSize==0) { return 0; } /* uncompressible */ }
if (cSize == 0) {
return 0;
} /* uncompressible */
op += cSize; op += cSize;
/* check compressibility */ /* check compressibility */
if ((size_t)(op-ostart) >= srcSize-1) { return 0; } if ((size_t)(op - ostart) >= srcSize - 1) {
return op-ostart; return 0;
}
return op - ostart;
} }
/* `workSpace` must a table of at least 1024 unsigned */ /* `workSpace` must a table of at least 1024 unsigned */
static size_t HUF_compress_internal ( static size_t HUF_compress_internal(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog,
void* dst, size_t dstSize, unsigned singleStream, void *workSpace, size_t wkspSize, HUF_CElt *oldHufTable, HUF_repeat *repeat, int preferRepeat)
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
unsigned singleStream,
void* workSpace, size_t wkspSize,
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat)
{ {
BYTE* const ostart = (BYTE*)dst; BYTE *const ostart = (BYTE *)dst;
BYTE* const oend = ostart + dstSize; BYTE *const oend = ostart + dstSize;
BYTE* op = ostart; BYTE *op = ostart;
U32* count; U32 *count;
size_t const countSize = sizeof(U32) * (HUF_SYMBOLVALUE_MAX + 1); size_t const countSize = sizeof(U32) * (HUF_SYMBOLVALUE_MAX + 1);
HUF_CElt* CTable; HUF_CElt *CTable;
size_t const CTableSize = sizeof(HUF_CElt) * (HUF_SYMBOLVALUE_MAX + 1); size_t const CTableSize = sizeof(HUF_CElt) * (HUF_SYMBOLVALUE_MAX + 1);
/* checks & inits */ /* checks & inits */
if (wkspSize < sizeof(huffNodeTable) + countSize + CTableSize) return ERROR(GENERIC); if (wkspSize < sizeof(huffNodeTable) + countSize + CTableSize)
if (!srcSize) return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */ return ERROR(GENERIC);
if (!dstSize) return 0; /* cannot fit within dst budget */ if (!srcSize)
if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* curr block size limit */ return 0; /* Uncompressed (note : 1 means rle, so first byte must be correct) */
if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); if (!dstSize)
if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX; return 0; /* cannot fit within dst budget */
if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT; if (srcSize > HUF_BLOCKSIZE_MAX)
return ERROR(srcSize_wrong); /* curr block size limit */
if (huffLog > HUF_TABLELOG_MAX)
return ERROR(tableLog_tooLarge);
if (!maxSymbolValue)
maxSymbolValue = HUF_SYMBOLVALUE_MAX;
if (!huffLog)
huffLog = HUF_TABLELOG_DEFAULT;
count = (U32*)workSpace; count = (U32 *)workSpace;
workSpace = (BYTE*)workSpace + countSize; workSpace = (BYTE *)workSpace + countSize;
wkspSize -= countSize; wkspSize -= countSize;
CTable = (HUF_CElt*)workSpace; CTable = (HUF_CElt *)workSpace;
workSpace = (BYTE*)workSpace + CTableSize; workSpace = (BYTE *)workSpace + CTableSize;
wkspSize -= CTableSize; wkspSize -= CTableSize;
/* Heuristic : If we don't need to check the validity of the old table use the old table for small inputs */ /* Heuristic : If we don't need to check the validity of the old table use the old table for small inputs */
@ -572,9 +651,14 @@ static size_t HUF_compress_internal (
} }
/* Scan input and build symbol stats */ /* Scan input and build symbol stats */
{ CHECK_V_F(largest, FSE_count_wksp (count, &maxSymbolValue, (const BYTE*)src, srcSize, (U32*)workSpace) ); {
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ CHECK_V_F(largest, FSE_count_wksp(count, &maxSymbolValue, (const BYTE *)src, srcSize, (U32 *)workSpace));
if (largest <= (srcSize >> 7)+1) return 0; /* Fast heuristic : not compressible enough */ if (largest == srcSize) {
*ostart = ((const BYTE *)src)[0];
return 1;
} /* single symbol, rle */
if (largest <= (srcSize >> 7) + 1)
return 0; /* Fast heuristic : not compressible enough */
} }
/* Check validity of previous table */ /* Check validity of previous table */
@ -588,14 +672,16 @@ static size_t HUF_compress_internal (
/* Build Huffman Tree */ /* Build Huffman Tree */
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
{ CHECK_V_F(maxBits, HUF_buildCTable_wksp (CTable, count, maxSymbolValue, huffLog, workSpace, wkspSize) ); {
CHECK_V_F(maxBits, HUF_buildCTable_wksp(CTable, count, maxSymbolValue, huffLog, workSpace, wkspSize));
huffLog = (U32)maxBits; huffLog = (U32)maxBits;
/* Zero the unused symbols so we can check it for validity */ /* Zero the unused symbols so we can check it for validity */
memset(CTable + maxSymbolValue + 1, 0, CTableSize - (maxSymbolValue + 1) * sizeof(HUF_CElt)); memset(CTable + maxSymbolValue + 1, 0, CTableSize - (maxSymbolValue + 1) * sizeof(HUF_CElt));
} }
/* Write table description header */ /* Write table description header */
{ CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, CTable, maxSymbolValue, huffLog) ); {
CHECK_V_F(hSize, HUF_writeCTable(op, dstSize, CTable, maxSymbolValue, huffLog));
/* Check if using the previous table will be beneficial */ /* Check if using the previous table will be beneficial */
if (repeat && *repeat != HUF_repeat_none) { if (repeat && *repeat != HUF_repeat_none) {
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, count, maxSymbolValue); size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, count, maxSymbolValue);
@ -605,45 +691,42 @@ static size_t HUF_compress_internal (
} }
} }
/* Use the new table */ /* Use the new table */
if (hSize + 12ul >= srcSize) { return 0; } if (hSize + 12ul >= srcSize) {
return 0;
}
op += hSize; op += hSize;
if (repeat) { *repeat = HUF_repeat_none; } if (repeat) {
if (oldHufTable) { memcpy(oldHufTable, CTable, CTableSize); } /* Save the new table */ *repeat = HUF_repeat_none;
}
if (oldHufTable) {
memcpy(oldHufTable, CTable, CTableSize);
} /* Save the new table */
} }
return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, CTable); return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, singleStream, CTable);
} }
size_t HUF_compress1X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, void *workSpace,
size_t HUF_compress1X_wksp (void* dst, size_t dstSize, size_t wkspSize)
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{ {
return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, NULL, NULL, 0); return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, NULL, NULL, 0);
} }
size_t HUF_compress1X_repeat (void* dst, size_t dstSize, size_t HUF_compress1X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, void *workSpace,
const void* src, size_t srcSize, size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat)
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
{ {
return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, hufTable, repeat, preferRepeat); return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 1 /* single stream */, workSpace, wkspSize, hufTable, repeat,
preferRepeat);
} }
size_t HUF_compress4X_wksp (void* dst, size_t dstSize, size_t HUF_compress4X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, void *workSpace,
const void* src, size_t srcSize, size_t wkspSize)
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize)
{ {
return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, NULL, NULL, 0); return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, NULL, NULL, 0);
} }
size_t HUF_compress4X_repeat (void* dst, size_t dstSize, size_t HUF_compress4X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, void *workSpace,
const void* src, size_t srcSize, size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat, int preferRepeat)
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat)
{ {
return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, hufTable, repeat, preferRepeat); return HUF_compress_internal(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, 0 /* 4 streams */, workSpace, wkspSize, hufTable, repeat,
preferRepeat);
} }

File diff suppressed because it is too large Load Diff

View File

@ -21,126 +21,78 @@
* Dependencies * Dependencies
******************************************/ ******************************************/
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/types.h> /* size_t, ptrdiff_t */ #include <linux/string.h> /* memcpy */
#include <linux/string.h> /* memcpy */ #include <linux/types.h> /* size_t, ptrdiff_t */
/*-**************************************** /*-****************************************
* Compiler specifics * Compiler specifics
******************************************/ ******************************************/
#define ZSTD_STATIC static __inline __attribute__((unused)) #define ZSTD_STATIC static __inline __attribute__((unused))
/*-************************************************************** /*-**************************************************************
* Basic Types * Basic Types
*****************************************************************/ *****************************************************************/
typedef uint8_t BYTE; typedef uint8_t BYTE;
typedef uint16_t U16; typedef uint16_t U16;
typedef int16_t S16; typedef int16_t S16;
typedef uint32_t U32; typedef uint32_t U32;
typedef int32_t S32; typedef int32_t S32;
typedef uint64_t U64; typedef uint64_t U64;
typedef int64_t S64; typedef int64_t S64;
typedef ptrdiff_t iPtrDiff; typedef ptrdiff_t iPtrDiff;
typedef uintptr_t uPtrDiff; typedef uintptr_t uPtrDiff;
/*-************************************************************** /*-**************************************************************
* Memory I/O * Memory I/O
*****************************************************************/ *****************************************************************/
ZSTD_STATIC unsigned ZSTD_32bits(void) { return sizeof(size_t)==4; } ZSTD_STATIC unsigned ZSTD_32bits(void) { return sizeof(size_t) == 4; }
ZSTD_STATIC unsigned ZSTD_64bits(void) { return sizeof(size_t)==8; } ZSTD_STATIC unsigned ZSTD_64bits(void) { return sizeof(size_t) == 8; }
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
# define ZSTD_LITTLE_ENDIAN 1 #define ZSTD_LITTLE_ENDIAN 1
#else #else
# define ZSTD_LITTLE_ENDIAN 0 #define ZSTD_LITTLE_ENDIAN 0
#endif #endif
ZSTD_STATIC unsigned ZSTD_isLittleEndian(void) ZSTD_STATIC unsigned ZSTD_isLittleEndian(void) { return ZSTD_LITTLE_ENDIAN; }
{
return ZSTD_LITTLE_ENDIAN;
}
ZSTD_STATIC U16 ZSTD_read16(const void* memPtr) ZSTD_STATIC U16 ZSTD_read16(const void *memPtr) { return get_unaligned((const U16 *)memPtr); }
{
return get_unaligned((const U16*)memPtr);
}
ZSTD_STATIC U32 ZSTD_read32(const void* memPtr) ZSTD_STATIC U32 ZSTD_read32(const void *memPtr) { return get_unaligned((const U32 *)memPtr); }
{
return get_unaligned((const U32*)memPtr);
}
ZSTD_STATIC U64 ZSTD_read64(const void* memPtr) ZSTD_STATIC U64 ZSTD_read64(const void *memPtr) { return get_unaligned((const U64 *)memPtr); }
{
return get_unaligned((const U64*)memPtr);
}
ZSTD_STATIC size_t ZSTD_readST(const void* memPtr) ZSTD_STATIC size_t ZSTD_readST(const void *memPtr) { return get_unaligned((const size_t *)memPtr); }
{
return get_unaligned((const size_t*)memPtr);
}
ZSTD_STATIC void ZSTD_write16(void* memPtr, U16 value) ZSTD_STATIC void ZSTD_write16(void *memPtr, U16 value) { put_unaligned(value, (U16 *)memPtr); }
{
put_unaligned(value, (U16*)memPtr);
}
ZSTD_STATIC void ZSTD_write32(void* memPtr, U32 value) ZSTD_STATIC void ZSTD_write32(void *memPtr, U32 value) { put_unaligned(value, (U32 *)memPtr); }
{
put_unaligned(value, (U32*)memPtr);
}
ZSTD_STATIC void ZSTD_write64(void* memPtr, U64 value) ZSTD_STATIC void ZSTD_write64(void *memPtr, U64 value) { put_unaligned(value, (U64 *)memPtr); }
{
put_unaligned(value, (U64*)memPtr);
}
/*=== Little endian r/w ===*/ /*=== Little endian r/w ===*/
ZSTD_STATIC U16 ZSTD_readLE16(const void* memPtr) ZSTD_STATIC U16 ZSTD_readLE16(const void *memPtr) { return get_unaligned_le16(memPtr); }
{
return get_unaligned_le16(memPtr);
}
ZSTD_STATIC void ZSTD_writeLE16(void* memPtr, U16 val) ZSTD_STATIC void ZSTD_writeLE16(void *memPtr, U16 val) { put_unaligned_le16(val, memPtr); }
{
put_unaligned_le16(val, memPtr);
}
ZSTD_STATIC U32 ZSTD_readLE24(const void* memPtr) ZSTD_STATIC U32 ZSTD_readLE24(const void *memPtr) { return ZSTD_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); }
{
return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
}
ZSTD_STATIC void ZSTD_writeLE24(void* memPtr, U32 val) ZSTD_STATIC void ZSTD_writeLE24(void *memPtr, U32 val)
{ {
ZSTD_writeLE16(memPtr, (U16)val); ZSTD_writeLE16(memPtr, (U16)val);
((BYTE*)memPtr)[2] = (BYTE)(val>>16); ((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
} }
ZSTD_STATIC U32 ZSTD_readLE32(const void* memPtr) ZSTD_STATIC U32 ZSTD_readLE32(const void *memPtr) { return get_unaligned_le32(memPtr); }
{
return get_unaligned_le32(memPtr);
}
ZSTD_STATIC void ZSTD_writeLE32(void* memPtr, U32 val32) ZSTD_STATIC void ZSTD_writeLE32(void *memPtr, U32 val32) { put_unaligned_le32(val32, memPtr); }
{
put_unaligned_le32(val32, memPtr);
}
ZSTD_STATIC U64 ZSTD_readLE64(const void* memPtr) ZSTD_STATIC U64 ZSTD_readLE64(const void *memPtr) { return get_unaligned_le64(memPtr); }
{
return get_unaligned_le64(memPtr);
}
ZSTD_STATIC void ZSTD_writeLE64(void* memPtr, U64 val64) ZSTD_STATIC void ZSTD_writeLE64(void *memPtr, U64 val64) { put_unaligned_le64(val64, memPtr); }
{
put_unaligned_le64(val64, memPtr);
}
ZSTD_STATIC size_t ZSTD_readLEST(const void* memPtr) ZSTD_STATIC size_t ZSTD_readLEST(const void *memPtr)
{ {
if (ZSTD_32bits()) if (ZSTD_32bits())
return (size_t)ZSTD_readLE32(memPtr); return (size_t)ZSTD_readLE32(memPtr);
@ -148,7 +100,7 @@ ZSTD_STATIC size_t ZSTD_readLEST(const void* memPtr)
return (size_t)ZSTD_readLE64(memPtr); return (size_t)ZSTD_readLE64(memPtr);
} }
ZSTD_STATIC void ZSTD_writeLEST(void* memPtr, size_t val) ZSTD_STATIC void ZSTD_writeLEST(void *memPtr, size_t val)
{ {
if (ZSTD_32bits()) if (ZSTD_32bits())
ZSTD_writeLE32(memPtr, (U32)val); ZSTD_writeLE32(memPtr, (U32)val);
@ -158,27 +110,15 @@ ZSTD_STATIC void ZSTD_writeLEST(void* memPtr, size_t val)
/*=== Big endian r/w ===*/ /*=== Big endian r/w ===*/
ZSTD_STATIC U32 ZSTD_readBE32(const void* memPtr) ZSTD_STATIC U32 ZSTD_readBE32(const void *memPtr) { return get_unaligned_be32(memPtr); }
{
return get_unaligned_be32(memPtr);
}
ZSTD_STATIC void ZSTD_writeBE32(void* memPtr, U32 val32) ZSTD_STATIC void ZSTD_writeBE32(void *memPtr, U32 val32) { put_unaligned_be32(val32, memPtr); }
{
put_unaligned_be32(val32, memPtr);
}
ZSTD_STATIC U64 ZSTD_readBE64(const void* memPtr) ZSTD_STATIC U64 ZSTD_readBE64(const void *memPtr) { return get_unaligned_be64(memPtr); }
{
return get_unaligned_be64(memPtr);
}
ZSTD_STATIC void ZSTD_writeBE64(void* memPtr, U64 val64) ZSTD_STATIC void ZSTD_writeBE64(void *memPtr, U64 val64) { put_unaligned_be64(val64, memPtr); }
{
put_unaligned_be64(val64, memPtr);
}
ZSTD_STATIC size_t ZSTD_readBEST(const void* memPtr) ZSTD_STATIC size_t ZSTD_readBEST(const void *memPtr)
{ {
if (ZSTD_32bits()) if (ZSTD_32bits())
return (size_t)ZSTD_readBE32(memPtr); return (size_t)ZSTD_readBE32(memPtr);
@ -186,7 +126,7 @@ ZSTD_STATIC size_t ZSTD_readBEST(const void* memPtr)
return (size_t)ZSTD_readBE64(memPtr); return (size_t)ZSTD_readBE64(memPtr);
} }
ZSTD_STATIC void ZSTD_writeBEST(void* memPtr, size_t val) ZSTD_STATIC void ZSTD_writeBEST(void *memPtr, size_t val)
{ {
if (ZSTD_32bits()) if (ZSTD_32bits())
ZSTD_writeBE32(memPtr, (U32)val); ZSTD_writeBE32(memPtr, (U32)val);
@ -194,18 +134,17 @@ ZSTD_STATIC void ZSTD_writeBEST(void* memPtr, size_t val)
ZSTD_writeBE64(memPtr, (U64)val); ZSTD_writeBE64(memPtr, (U64)val);
} }
/* function safe only for comparisons */ /* function safe only for comparisons */
ZSTD_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length) ZSTD_STATIC U32 ZSTD_readMINMATCH(const void *memPtr, U32 length)
{ {
switch (length) switch (length) {
{ default:
default : case 4: return ZSTD_read32(memPtr);
case 4 : return ZSTD_read32(memPtr); case 3:
case 3 : if (ZSTD_isLittleEndian()) if (ZSTD_isLittleEndian())
return ZSTD_read32(memPtr)<<8; return ZSTD_read32(memPtr) << 8;
else else
return ZSTD_read32(memPtr)>>8; return ZSTD_read32(memPtr) >> 8;
} }
} }

View File

@ -14,29 +14,28 @@
* ("BSD"). * ("BSD").
*/ */
/*-************************************* /*-*************************************
* Dependencies * Dependencies
***************************************/ ***************************************/
#include "error_private.h" #include "error_private.h"
#include "zstd_internal.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */ #include "zstd_internal.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */
#include <linux/kernel.h> #include <linux/kernel.h>
/*=************************************************************** /*=**************************************************************
* Custom allocator * Custom allocator
****************************************************************/ ****************************************************************/
#define stack_push(stack, size) ({ \ #define stack_push(stack, size) \
void* const ptr = ZSTD_PTR_ALIGN((stack)->ptr); \ ({ \
(stack)->ptr = (char*)ptr + (size); \ void *const ptr = ZSTD_PTR_ALIGN((stack)->ptr); \
(stack)->ptr <= (stack)->end ? ptr : NULL; \ (stack)->ptr = (char *)ptr + (size); \
(stack)->ptr <= (stack)->end ? ptr : NULL; \
}) })
ZSTD_customMem ZSTD_initStack(void* workspace, size_t workspaceSize) { ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize)
ZSTD_customMem stackMem = { ZSTD_stackAlloc, ZSTD_stackFree, workspace }; {
ZSTD_stack* stack = (ZSTD_stack*) workspace; ZSTD_customMem stackMem = {ZSTD_stackAlloc, ZSTD_stackFree, workspace};
ZSTD_stack *stack = (ZSTD_stack *)workspace;
/* Verify preconditions */ /* Verify preconditions */
if (!workspace || workspaceSize < sizeof(ZSTD_stack) || workspace != ZSTD_PTR_ALIGN(workspace)) { if (!workspace || workspaceSize < sizeof(ZSTD_stack) || workspace != ZSTD_PTR_ALIGN(workspace)) {
ZSTD_customMem error = {NULL, NULL, NULL}; ZSTD_customMem error = {NULL, NULL, NULL};
@ -44,33 +43,33 @@ ZSTD_customMem ZSTD_initStack(void* workspace, size_t workspaceSize) {
} }
/* Initialize the stack */ /* Initialize the stack */
stack->ptr = workspace; stack->ptr = workspace;
stack->end = (char*)workspace + workspaceSize; stack->end = (char *)workspace + workspaceSize;
stack_push(stack, sizeof(ZSTD_stack)); stack_push(stack, sizeof(ZSTD_stack));
return stackMem; return stackMem;
} }
void* ZSTD_stackAllocAll(void* opaque, size_t* size) { void *ZSTD_stackAllocAll(void *opaque, size_t *size)
ZSTD_stack* stack = (ZSTD_stack*)opaque; {
ZSTD_stack *stack = (ZSTD_stack *)opaque;
*size = stack->end - ZSTD_PTR_ALIGN(stack->ptr); *size = stack->end - ZSTD_PTR_ALIGN(stack->ptr);
return stack_push(stack, *size); return stack_push(stack, *size);
} }
void* ZSTD_stackAlloc(void* opaque, size_t size) { void *ZSTD_stackAlloc(void *opaque, size_t size)
ZSTD_stack* stack = (ZSTD_stack*)opaque; {
ZSTD_stack *stack = (ZSTD_stack *)opaque;
return stack_push(stack, size); return stack_push(stack, size);
} }
void ZSTD_stackFree(void* opaque, void* address) { void ZSTD_stackFree(void *opaque, void *address)
{
(void)opaque; (void)opaque;
(void)address; (void)address;
} }
void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) void *ZSTD_malloc(size_t size, ZSTD_customMem customMem) { return customMem.customAlloc(customMem.opaque, size); }
{
return customMem.customAlloc(customMem.opaque, size);
}
void ZSTD_free(void* ptr, ZSTD_customMem customMem) void ZSTD_free(void *ptr, ZSTD_customMem customMem)
{ {
if (ptr!=NULL) if (ptr != NULL)
customMem.customFree(customMem.opaque, ptr); customMem.customFree(customMem.opaque, ptr);
} }

View File

@ -23,60 +23,67 @@
#define FORCE_INLINE static __always_inline #define FORCE_INLINE static __always_inline
#define FORCE_NOINLINE static noinline #define FORCE_NOINLINE static noinline
/*-************************************* /*-*************************************
* Dependencies * Dependencies
***************************************/ ***************************************/
#include "error_private.h"
#include "mem.h"
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/xxhash.h> #include <linux/xxhash.h>
#include <linux/zstd.h> #include <linux/zstd.h>
#include "mem.h"
#include "error_private.h"
/*-************************************* /*-*************************************
* shared macros * shared macros
***************************************/ ***************************************/
#define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b))
#define CHECK_F(f) { size_t const errcod = f; if (ERR_isError(errcod)) return errcod; } /* check and Forward error code */ #define CHECK_F(f) \
#define CHECK_E(f, e) { size_t const errcod = f; if (ERR_isError(errcod)) return ERROR(e); } /* check and send Error code */ { \
size_t const errcod = f; \
if (ERR_isError(errcod)) \
return errcod; \
} /* check and Forward error code */
#define CHECK_E(f, e) \
{ \
size_t const errcod = f; \
if (ERR_isError(errcod)) \
return ERROR(e); \
} /* check and send Error code */
/*-************************************* /*-*************************************
* Common constants * Common constants
***************************************/ ***************************************/
#define ZSTD_OPT_NUM (1<<12) #define ZSTD_OPT_NUM (1 << 12)
#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */ #define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */
#define ZSTD_REP_NUM 3 /* number of repcodes */ #define ZSTD_REP_NUM 3 /* number of repcodes */
#define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */ #define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) #define ZSTD_REP_MOVE (ZSTD_REP_NUM - 1)
#define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM) #define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM)
static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; static const U32 repStartValue[ZSTD_REP_NUM] = {1, 4, 8};
#define KB *(1 <<10) #define KB *(1 << 10)
#define MB *(1 <<20) #define MB *(1 << 20)
#define GB *(1U<<30) #define GB *(1U << 30)
#define BIT7 128 #define BIT7 128
#define BIT6 64 #define BIT6 64
#define BIT5 32 #define BIT5 32
#define BIT4 16 #define BIT4 16
#define BIT1 2 #define BIT1 2
#define BIT0 1 #define BIT0 1
#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; static const size_t ZSTD_fcs_fieldSize[4] = {0, 2, 4, 8};
static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; static const size_t ZSTD_did_fieldSize[4] = {0, 1, 2, 4};
#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */ #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 MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
#define HufLog 12 #define HufLog 12
typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e; typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
@ -86,72 +93,66 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
#define MINMATCH 3 #define MINMATCH 3
#define EQUAL_READ32 4 #define EQUAL_READ32 4
#define Litbits 8 #define Litbits 8
#define MaxLit ((1<<Litbits) - 1) #define MaxLit ((1 << Litbits) - 1)
#define MaxML 52 #define MaxML 52
#define MaxLL 35 #define MaxLL 35
#define MaxOff 28 #define MaxOff 28
#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */ #define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
#define MLFSELog 9 #define MLFSELog 9
#define LLFSELog 9 #define LLFSELog 9
#define OffFSELog 8 #define OffFSELog 8
static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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};
1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, static const S16 LL_defaultNorm[MaxLL + 1] = {4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};
13,14,15,16 }; #define LL_DEFAULTNORMLOG 6 /* for static allocation */
static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
-1,-1,-1,-1 };
#define LL_DEFAULTNORMLOG 6 /* for static allocation */
static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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};
1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11, static const S16 ML_defaultNorm[MaxML + 1] = {1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
12,13,14,15,16 }; 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 S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, #define ML_DEFAULTNORMLOG 6 /* for static allocation */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,
-1,-1,-1,-1,-1 };
#define ML_DEFAULTNORMLOG 6 /* for static allocation */
static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
static const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, static const S16 OF_defaultNorm[MaxOff + 1] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};
1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 }; #define OF_DEFAULTNORMLOG 5 /* for static allocation */
#define OF_DEFAULTNORMLOG 5 /* for static allocation */
static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
/*-******************************************* /*-*******************************************
* Shared functions to include for inlining * Shared functions to include for inlining
*********************************************/ *********************************************/
static void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); } 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; } #define COPY8(d, s) \
{ \
ZSTD_copy8(d, s); \
d += 8; \
s += 8; \
}
/*! ZSTD_wildcopy() : /*! ZSTD_wildcopy() :
* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */ * custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
#define WILDCOPY_OVERLENGTH 8 #define WILDCOPY_OVERLENGTH 8
ZSTD_STATIC void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length) ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE *ip = (const BYTE *)src;
BYTE* op = (BYTE*)dst; BYTE *op = (BYTE *)dst;
BYTE* const oend = op + length; BYTE *const oend = op + length;
do do
COPY8(op, ip) COPY8(op, ip)
while (op < oend); while (op < oend);
} }
ZSTD_STATIC void ZSTD_wildcopy_e(void* dst, const void* src, void* dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */ ZSTD_STATIC void ZSTD_wildcopy_e(void *dst, const void *src, void *dstEnd) /* should be faster for decoding, but strangely, not verified on all platform */
{ {
const BYTE* ip = (const BYTE*)src; const BYTE *ip = (const BYTE *)src;
BYTE* op = (BYTE*)dst; BYTE *op = (BYTE *)dst;
BYTE* const oend = (BYTE*)dstEnd; BYTE *const oend = (BYTE *)dstEnd;
do do
COPY8(op, ip) COPY8(op, ip)
while (op < oend); while (op < oend);
} }
/*-******************************************* /*-*******************************************
* Private interfaces * Private interfaces
*********************************************/ *********************************************/
@ -170,84 +171,81 @@ typedef struct {
U32 rep[ZSTD_REP_NUM]; U32 rep[ZSTD_REP_NUM];
} ZSTD_optimal_t; } ZSTD_optimal_t;
typedef struct seqDef_s { typedef struct seqDef_s {
U32 offset; U32 offset;
U16 litLength; U16 litLength;
U16 matchLength; U16 matchLength;
} seqDef; } seqDef;
typedef struct { typedef struct {
seqDef* sequencesStart; seqDef *sequencesStart;
seqDef* sequences; seqDef *sequences;
BYTE* litStart; BYTE *litStart;
BYTE* lit; BYTE *lit;
BYTE* llCode; BYTE *llCode;
BYTE* mlCode; BYTE *mlCode;
BYTE* ofCode; BYTE *ofCode;
U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
U32 longLengthPos; U32 longLengthPos;
/* opt */ /* opt */
ZSTD_optimal_t* priceTable; ZSTD_optimal_t *priceTable;
ZSTD_match_t* matchTable; ZSTD_match_t *matchTable;
U32* matchLengthFreq; U32 *matchLengthFreq;
U32* litLengthFreq; U32 *litLengthFreq;
U32* litFreq; U32 *litFreq;
U32* offCodeFreq; U32 *offCodeFreq;
U32 matchLengthSum; U32 matchLengthSum;
U32 matchSum; U32 matchSum;
U32 litLengthSum; U32 litLengthSum;
U32 litSum; U32 litSum;
U32 offCodeSum; U32 offCodeSum;
U32 log2matchLengthSum; U32 log2matchLengthSum;
U32 log2matchSum; U32 log2matchSum;
U32 log2litLengthSum; U32 log2litLengthSum;
U32 log2litSum; U32 log2litSum;
U32 log2offCodeSum; U32 log2offCodeSum;
U32 factor; U32 factor;
U32 staticPrices; U32 staticPrices;
U32 cachedPrice; U32 cachedPrice;
U32 cachedLitLength; U32 cachedLitLength;
const BYTE* cachedLiterals; const BYTE *cachedLiterals;
} seqStore_t; } seqStore_t;
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx);
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); void ZSTD_seqToCodes(const seqStore_t *seqStorePtr);
int ZSTD_isSkipFrame(ZSTD_DCtx* dctx); int ZSTD_isSkipFrame(ZSTD_DCtx *dctx);
/*= Custom memory allocation functions */ /*= Custom memory allocation functions */
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); typedef void *(*ZSTD_allocFunction)(void *opaque, size_t size);
typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef void (*ZSTD_freeFunction)(void *opaque, void *address);
typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; typedef struct {
ZSTD_allocFunction customAlloc;
ZSTD_freeFunction customFree;
void *opaque;
} ZSTD_customMem;
void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); void *ZSTD_malloc(size_t size, ZSTD_customMem customMem);
void ZSTD_free(void* ptr, ZSTD_customMem customMem); void ZSTD_free(void *ptr, ZSTD_customMem customMem);
/*====== stack allocation ======*/ /*====== stack allocation ======*/
typedef struct { typedef struct {
void* ptr; void *ptr;
const void* end; const void *end;
} ZSTD_stack; } ZSTD_stack;
#define ZSTD_ALIGN(x) ALIGN(x, sizeof(size_t)) #define ZSTD_ALIGN(x) ALIGN(x, sizeof(size_t))
#define ZSTD_PTR_ALIGN(p) PTR_ALIGN(p, sizeof(size_t)) #define ZSTD_PTR_ALIGN(p) PTR_ALIGN(p, sizeof(size_t))
ZSTD_customMem ZSTD_initStack(void* workspace, size_t workspaceSize); ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize);
void* ZSTD_stackAllocAll(void* opaque, size_t* size);
void* ZSTD_stackAlloc(void* opaque, size_t size);
void ZSTD_stackFree(void* opaque, void* address);
void *ZSTD_stackAllocAll(void *opaque, size_t *size);
void *ZSTD_stackAlloc(void *opaque, size_t size);
void ZSTD_stackFree(void *opaque, void *address);
/*====== common function ======*/ /*====== common function ======*/
ZSTD_STATIC U32 ZSTD_highbit32(U32 val) ZSTD_STATIC U32 ZSTD_highbit32(U32 val) { return 31 - __builtin_clz(val); }
{
return 31 - __builtin_clz(val);
}
/* hidden functions */ /* hidden functions */
@ -255,14 +253,13 @@ ZSTD_STATIC U32 ZSTD_highbit32(U32 val)
* ensures next compression will not use repcodes from previous block. * ensures next compression will not use repcodes from previous block.
* Note : only works with regular variant; * Note : only works with regular variant;
* do not use with extDict variant ! */ * do not use with extDict variant ! */
void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx); void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx);
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx);
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx);
size_t ZSTD_freeCDict(ZSTD_CDict* cdict); size_t ZSTD_freeCDict(ZSTD_CDict *cdict);
size_t ZSTD_freeDDict(ZSTD_DDict* cdict); size_t ZSTD_freeDDict(ZSTD_DDict *cdict);
size_t ZSTD_freeCStream(ZSTD_CStream* zcs); size_t ZSTD_freeCStream(ZSTD_CStream *zcs);
size_t ZSTD_freeDStream(ZSTD_DStream* zds); size_t ZSTD_freeDStream(ZSTD_DStream *zds);
#endif /* ZSTD_CCOMMON_H_MODULE */
#endif /* ZSTD_CCOMMON_H_MODULE */

File diff suppressed because it is too large Load Diff