@@ -91,19 +91,20 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
91
91
/*-********************************************
92
92
* bitStream decoding API (read backward)
93
93
**********************************************/
94
+ typedef size_t BitContainerType ;
94
95
typedef struct {
95
- size_t bitContainer ;
96
+ BitContainerType bitContainer ;
96
97
unsigned bitsConsumed ;
97
98
const char * ptr ;
98
99
const char * start ;
99
100
const char * limitPtr ;
100
101
} BIT_DStream_t ;
101
102
102
- typedef enum { BIT_DStream_unfinished = 0 ,
103
- BIT_DStream_endOfBuffer = 1 ,
104
- BIT_DStream_completed = 2 ,
105
- BIT_DStream_overflow = 3 } BIT_DStream_status ; /* result of BIT_reloadDStream() */
106
- /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
103
+ typedef enum { BIT_DStream_unfinished = 0 , /* fully refilled */
104
+ BIT_DStream_endOfBuffer = 1 , /* still some bits left in bitstream */
105
+ BIT_DStream_completed = 2 , /* bitstream entirely consumed, bit-exact */
106
+ BIT_DStream_overflow = 3 /* user requested more bits than present in bitstream */
107
+ } BIT_DStream_status ; /* result of BIT_reloadDStream() */
107
108
108
109
MEM_STATIC size_t BIT_initDStream (BIT_DStream_t * bitD , const void * srcBuffer , size_t srcSize );
109
110
MEM_STATIC size_t BIT_readBits (BIT_DStream_t * bitD , unsigned nbBits );
@@ -113,7 +114,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
113
114
114
115
/* Start by invoking BIT_initDStream().
115
116
* A chunk of the bitStream is then stored into a local register.
116
- * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t ).
117
+ * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType ).
117
118
* You can then retrieve bitFields stored into the local register, **in reverse order**.
118
119
* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
119
120
* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
@@ -163,7 +164,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
163
164
return 0 ;
164
165
}
165
166
166
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits (size_t bitContainer , U32 const nbBits )
167
+ FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits (size_t bitContainer , U32 const nbBits )
167
168
{
168
169
#if defined(STATIC_BMI2 ) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS )
169
170
return _bzhi_u64 (bitContainer , nbBits );
@@ -268,22 +269,22 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
268
269
bitD -> bitContainer = * (const BYTE * )(bitD -> start );
269
270
switch (srcSize )
270
271
{
271
- case 7 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[6 ]) << (sizeof (bitD -> bitContainer )* 8 - 16 );
272
+ case 7 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[6 ]) << (sizeof (bitD -> bitContainer )* 8 - 16 );
272
273
ZSTD_FALLTHROUGH ;
273
274
274
- case 6 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[5 ]) << (sizeof (bitD -> bitContainer )* 8 - 24 );
275
+ case 6 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[5 ]) << (sizeof (bitD -> bitContainer )* 8 - 24 );
275
276
ZSTD_FALLTHROUGH ;
276
277
277
- case 5 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[4 ]) << (sizeof (bitD -> bitContainer )* 8 - 32 );
278
+ case 5 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[4 ]) << (sizeof (bitD -> bitContainer )* 8 - 32 );
278
279
ZSTD_FALLTHROUGH ;
279
280
280
- case 4 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[3 ]) << 24 ;
281
+ case 4 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[3 ]) << 24 ;
281
282
ZSTD_FALLTHROUGH ;
282
283
283
- case 3 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[2 ]) << 16 ;
284
+ case 3 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[2 ]) << 16 ;
284
285
ZSTD_FALLTHROUGH ;
285
286
286
- case 2 : bitD -> bitContainer += (size_t )(((const BYTE * )(srcBuffer ))[1 ]) << 8 ;
287
+ case 2 : bitD -> bitContainer += (BitContainerType )(((const BYTE * )(srcBuffer ))[1 ]) << 8 ;
287
288
ZSTD_FALLTHROUGH ;
288
289
289
290
default : break ;
@@ -298,12 +299,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
298
299
return srcSize ;
299
300
}
300
301
301
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits (size_t bitContainer , U32 const start )
302
+ FORCE_INLINE_TEMPLATE size_t BIT_getUpperBits (BitContainerType bitContainer , U32 const start )
302
303
{
303
304
return bitContainer >> start ;
304
305
}
305
306
306
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits (size_t bitContainer , U32 const start , U32 const nbBits )
307
+ FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits (BitContainerType bitContainer , U32 const start , U32 const nbBits )
307
308
{
308
309
U32 const regMask = sizeof (bitContainer )* 8 - 1 ;
309
310
/* if start > regMask, bitstream is corrupted, and result is undefined */
@@ -326,7 +327,7 @@ MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 c
326
327
* On 32-bits, maxNbBits==24.
327
328
* On 64-bits, maxNbBits==56.
328
329
* @return : value extracted */
329
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits (const BIT_DStream_t * bitD , U32 nbBits )
330
+ FORCE_INLINE_TEMPLATE size_t BIT_lookBits (const BIT_DStream_t * bitD , U32 nbBits )
330
331
{
331
332
/* arbitrate between double-shift and shift+mask */
332
333
#if 1
@@ -349,7 +350,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
349
350
return (bitD -> bitContainer << (bitD -> bitsConsumed & regMask )) >> (((regMask + 1 )- nbBits ) & regMask );
350
351
}
351
352
352
- MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits (BIT_DStream_t * bitD , U32 nbBits )
353
+ FORCE_INLINE_TEMPLATE void BIT_skipBits (BIT_DStream_t * bitD , U32 nbBits )
353
354
{
354
355
bitD -> bitsConsumed += nbBits ;
355
356
}
@@ -358,7 +359,7 @@ MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
358
359
* Read (consume) next n bits from local register and update.
359
360
* Pay attention to not read more than nbBits contained into local register.
360
361
* @return : extracted value. */
361
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits (BIT_DStream_t * bitD , unsigned nbBits )
362
+ FORCE_INLINE_TEMPLATE size_t BIT_readBits (BIT_DStream_t * bitD , unsigned nbBits )
362
363
{
363
364
size_t const value = BIT_lookBits (bitD , nbBits );
364
365
BIT_skipBits (bitD , nbBits );
@@ -375,6 +376,21 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
375
376
return value ;
376
377
}
377
378
379
+ /*! BIT_reloadDStream_internal() :
380
+ * Simple variant of BIT_reloadDStream(), with two conditions:
381
+ * 1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8
382
+ * 2. look window is valid after shifted down : bitD->ptr >= bitD->start
383
+ */
384
+ MEM_STATIC BIT_DStream_status BIT_reloadDStream_internal (BIT_DStream_t * bitD )
385
+ {
386
+ assert (bitD -> bitsConsumed <= sizeof (bitD -> bitContainer )* 8 );
387
+ bitD -> ptr -= bitD -> bitsConsumed >> 3 ;
388
+ assert (bitD -> ptr >= bitD -> start );
389
+ bitD -> bitsConsumed &= 7 ;
390
+ bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
391
+ return BIT_DStream_unfinished ;
392
+ }
393
+
378
394
/*! BIT_reloadDStreamFast() :
379
395
* Similar to BIT_reloadDStream(), but with two differences:
380
396
* 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
@@ -385,31 +401,35 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
385
401
{
386
402
if (UNLIKELY (bitD -> ptr < bitD -> limitPtr ))
387
403
return BIT_DStream_overflow ;
388
- assert (bitD -> bitsConsumed <= sizeof (bitD -> bitContainer )* 8 );
389
- bitD -> ptr -= bitD -> bitsConsumed >> 3 ;
390
- bitD -> bitsConsumed &= 7 ;
391
- bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
392
- return BIT_DStream_unfinished ;
404
+ return BIT_reloadDStream_internal (bitD );
393
405
}
394
406
395
407
/*! BIT_reloadDStream() :
396
408
* Refill `bitD` from buffer previously set in BIT_initDStream() .
397
- * This function is safe, it guarantees it will not read beyond src buffer.
409
+ * This function is safe, it guarantees it will not never beyond src buffer.
398
410
* @return : status of `BIT_DStream_t` internal register.
399
411
* when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
400
- MEM_STATIC FORCE_INLINE_ATTR BIT_DStream_status BIT_reloadDStream (BIT_DStream_t * bitD )
412
+ FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream (BIT_DStream_t * bitD )
401
413
{
402
- if (bitD -> bitsConsumed > (sizeof (bitD -> bitContainer )* 8 )) /* overflow detected, like end of stream */
414
+ /* note : once in overflow mode, a bitstream remains in this mode until it's reset */
415
+ if (UNLIKELY (bitD -> bitsConsumed > (sizeof (bitD -> bitContainer )* 8 ))) {
416
+ static const BitContainerType zeroFilled = 0 ;
417
+ bitD -> ptr = (const char * )& zeroFilled ; /* aliasing is allowed for char */
418
+ /* overflow detected, erroneous scenario or end of stream: no update */
403
419
return BIT_DStream_overflow ;
420
+ }
421
+
422
+ assert (bitD -> ptr >= bitD -> start );
404
423
405
424
if (bitD -> ptr >= bitD -> limitPtr ) {
406
- return BIT_reloadDStreamFast (bitD );
425
+ return BIT_reloadDStream_internal (bitD );
407
426
}
408
427
if (bitD -> ptr == bitD -> start ) {
428
+ /* reached end of bitStream => no update */
409
429
if (bitD -> bitsConsumed < sizeof (bitD -> bitContainer )* 8 ) return BIT_DStream_endOfBuffer ;
410
430
return BIT_DStream_completed ;
411
431
}
412
- /* start < ptr < limitPtr */
432
+ /* start < ptr < limitPtr => cautious update */
413
433
{ U32 nbBytes = bitD -> bitsConsumed >> 3 ;
414
434
BIT_DStream_status result = BIT_DStream_unfinished ;
415
435
if (bitD -> ptr - nbBytes < bitD -> start ) {
0 commit comments