sync bitstream.h from fse library
This commit is contained in:
+36
-19
@@ -84,7 +84,7 @@ extern "C" {
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
size_t bitContainer;
|
size_t bitContainer;
|
||||||
int bitPos;
|
unsigned bitPos;
|
||||||
char* startPtr;
|
char* startPtr;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
char* endPtr;
|
char* endPtr;
|
||||||
@@ -122,6 +122,7 @@ typedef struct
|
|||||||
unsigned bitsConsumed;
|
unsigned bitsConsumed;
|
||||||
const char* ptr;
|
const char* ptr;
|
||||||
const char* start;
|
const char* start;
|
||||||
|
const char* limitPtr;
|
||||||
} BIT_DStream_t;
|
} BIT_DStream_t;
|
||||||
|
|
||||||
typedef enum { BIT_DStream_unfinished = 0,
|
typedef enum { BIT_DStream_unfinished = 0,
|
||||||
@@ -173,7 +174,10 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
|
|||||||
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
|
||||||
return 31 - __builtin_clz (val);
|
return 31 - __builtin_clz (val);
|
||||||
# else /* Software version */
|
# else /* Software version */
|
||||||
static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
|
static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
|
||||||
|
11, 14, 16, 18, 22, 25, 3, 30,
|
||||||
|
8, 12, 20, 28, 15, 17, 24, 7,
|
||||||
|
19, 27, 23, 6, 26, 5, 4, 31 };
|
||||||
U32 v = val;
|
U32 v = val;
|
||||||
v |= v >> 1;
|
v |= v >> 1;
|
||||||
v |= v >> 2;
|
v |= v >> 2;
|
||||||
@@ -185,31 +189,36 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 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
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
/*! BIT_initCStream() :
|
/*! BIT_initCStream() :
|
||||||
* `dstCapacity` must be > sizeof(void*)
|
* `dstCapacity` must be > sizeof(size_t)
|
||||||
* @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() ) */
|
||||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
|
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
||||||
|
void* const startPtr, size_t const 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->bitContainer);
|
||||||
if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
|
if (dstCapacity <= sizeof(bitC->bitContainer)) 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 ! */
|
||||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
|
||||||
|
size_t const value, unsigned const nbBits)
|
||||||
{
|
{
|
||||||
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
|
bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
|
||||||
bitC->bitPos += nbBits;
|
bitC->bitPos += nbBits;
|
||||||
@@ -217,7 +226,8 @@ MEM_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 */
|
||||||
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
|
MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
|
||||||
|
size_t const value, unsigned const nbBits)
|
||||||
{
|
{
|
||||||
assert((value>>nbBits) == 0);
|
assert((value>>nbBits) == 0);
|
||||||
bitC->bitContainer |= value << bitC->bitPos;
|
bitC->bitContainer |= value << bitC->bitPos;
|
||||||
@@ -225,22 +235,27 @@ MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*! BIT_flushBitsFast() :
|
/*! BIT_flushBitsFast() :
|
||||||
|
* assumption : bitContainer has not overflowed
|
||||||
* unsafe version; does not check buffer overflow */
|
* unsafe version; does not check buffer overflow */
|
||||||
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
|
||||||
{
|
{
|
||||||
size_t const nbBytes = bitC->bitPos >> 3;
|
size_t const nbBytes = bitC->bitPos >> 3;
|
||||||
|
assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
|
||||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
||||||
bitC->ptr += nbBytes;
|
bitC->ptr += nbBytes;
|
||||||
|
assert(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! BIT_flushBits() :
|
/*! BIT_flushBits() :
|
||||||
|
* assumption : bitContainer has not overflowed
|
||||||
* 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() */
|
||||||
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||||
{
|
{
|
||||||
size_t const nbBytes = bitC->bitPos >> 3;
|
size_t const nbBytes = bitC->bitPos >> 3;
|
||||||
|
assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
|
||||||
MEM_writeLEST(bitC->ptr, bitC->bitContainer);
|
MEM_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;
|
||||||
@@ -275,15 +290,16 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
|
|||||||
{
|
{
|
||||||
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||||
|
|
||||||
|
bitD->start = (const char*)srcBuffer;
|
||||||
|
bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
|
||||||
|
|
||||||
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
|
||||||
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 = MEM_readLEST(bitD->ptr);
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||||
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
|
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
|
||||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
||||||
} else {
|
} else {
|
||||||
bitD->start = (const char*)srcBuffer;
|
|
||||||
bitD->ptr = bitD->start;
|
bitD->ptr = bitD->start;
|
||||||
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
||||||
switch(srcSize)
|
switch(srcSize)
|
||||||
@@ -341,8 +357,8 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
|||||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
|
#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
|
||||||
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
||||||
#else
|
#else
|
||||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||||
return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
|
return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,9 +366,9 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
|||||||
* unsafe version; only works if nbBits >= 1 */
|
* unsafe version; only works if nbBits >= 1 */
|
||||||
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
|
||||||
{
|
{
|
||||||
U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
|
U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
|
||||||
assert(nbBits >= 1);
|
assert(nbBits >= 1);
|
||||||
return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
|
return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||||
@@ -389,10 +405,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
|||||||
if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
|
if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
|
||||||
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||||
{
|
{
|
||||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should not happen => corruption detected */
|
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
|
||||||
return BIT_DStream_overflow;
|
return BIT_DStream_overflow;
|
||||||
|
|
||||||
if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
|
if (bitD->ptr >= bitD->limitPtr) {
|
||||||
bitD->ptr -= bitD->bitsConsumed >> 3;
|
bitD->ptr -= bitD->bitsConsumed >> 3;
|
||||||
bitD->bitsConsumed &= 7;
|
bitD->bitsConsumed &= 7;
|
||||||
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
bitD->bitContainer = MEM_readLEST(bitD->ptr);
|
||||||
@@ -402,6 +418,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
/* start < ptr < limitPtr */
|
||||||
{ 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) {
|
||||||
@@ -410,7 +427,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
|||||||
}
|
}
|
||||||
bitD->ptr -= nbBytes;
|
bitD->ptr -= nbBytes;
|
||||||
bitD->bitsConsumed -= nbBytes*8;
|
bitD->bitsConsumed -= nbBytes*8;
|
||||||
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
|
bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user