22 bitstream
33 Part of FSE library
44 header file (to include)
5- Copyright (C) 2013-2016 , Yann Collet.
5+ Copyright (C) 2013-2017 , Yann Collet.
66
77 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
88
@@ -53,6 +53,16 @@ extern "C" {
5353#include "error_private.h" /* error codes and messages */
5454
5555
56+ /*-*************************************
57+ * Debug
58+ ***************************************/
59+ #if defined(BIT_DEBUG ) && (BIT_DEBUG >=1 )
60+ # include <assert.h>
61+ #else
62+ # define assert (condition ) ((void)0)
63+ #endif
64+
65+
5666/*=========================================
5767* Target specific
5868=========================================*/
@@ -74,7 +84,7 @@ extern "C" {
7484typedef struct
7585{
7686 size_t bitContainer ;
77- int bitPos ;
87+ unsigned bitPos ;
7888 char * startPtr ;
7989 char * ptr ;
8090 char * endPtr ;
@@ -112,6 +122,7 @@ typedef struct
112122 unsigned bitsConsumed ;
113123 const char * ptr ;
114124 const char * start ;
125+ const char * limitPtr ;
115126} BIT_DStream_t ;
116127
117128typedef enum { BIT_DStream_unfinished = 0 ,
@@ -163,7 +174,10 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
163174# elif defined(__GNUC__ ) && (__GNUC__ >= 3 ) /* Use GCC Intrinsic */
164175 return 31 - __builtin_clz (val );
165176# else /* Software version */
166- 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 };
177+ static const unsigned DeBruijnClz [32 ] = { 0 , 9 , 1 , 10 , 13 , 21 , 2 , 29 ,
178+ 11 , 14 , 16 , 18 , 22 , 25 , 3 , 30 ,
179+ 8 , 12 , 20 , 28 , 15 , 17 , 24 , 7 ,
180+ 19 , 27 , 23 , 6 , 26 , 5 , 4 , 31 };
167181 U32 v = val ;
168182 v |= v >> 1 ;
169183 v |= v >> 2 ;
@@ -175,66 +189,79 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
175189}
176190
177191/*===== Local Constants =====*/
178- 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 */
192+ static const unsigned BIT_mask [] = { 0 , 1 , 3 , 7 , 0xF , 0x1F , 0x3F , 0x7F ,
193+ 0xFF , 0x1FF , 0x3FF , 0x7FF , 0xFFF , 0x1FFF , 0x3FFF , 0x7FFF ,
194+ 0xFFFF , 0x1FFFF , 0x3FFFF , 0x7FFFF , 0xFFFFF , 0x1FFFFF , 0x3FFFFF , 0x7FFFFF ,
195+ 0xFFFFFF , 0x1FFFFFF , 0x3FFFFFF }; /* up to 26 bits */
179196
180197
181198/*-**************************************************************
182199* bitStream encoding
183200****************************************************************/
184201/*! BIT_initCStream() :
185- * `dstCapacity` must be > sizeof(void* )
202+ * `dstCapacity` must be > sizeof(size_t )
186203 * @return : 0 if success,
187204 otherwise an error code (can be tested using ERR_isError() ) */
188- MEM_STATIC size_t BIT_initCStream (BIT_CStream_t * bitC , void * startPtr , size_t dstCapacity )
205+ MEM_STATIC size_t BIT_initCStream (BIT_CStream_t * bitC ,
206+ void * startPtr , size_t dstCapacity )
189207{
190208 bitC -> bitContainer = 0 ;
191209 bitC -> bitPos = 0 ;
192210 bitC -> startPtr = (char * )startPtr ;
193211 bitC -> ptr = bitC -> startPtr ;
194- bitC -> endPtr = bitC -> startPtr + dstCapacity - sizeof (bitC -> ptr );
195- if (dstCapacity <= sizeof (bitC -> ptr )) return ERROR (dstSize_tooSmall );
212+ bitC -> endPtr = bitC -> startPtr + dstCapacity - sizeof (bitC -> bitContainer );
213+ if (dstCapacity <= sizeof (bitC -> bitContainer )) return ERROR (dstSize_tooSmall );
196214 return 0 ;
197215}
198216
199217/*! BIT_addBits() :
200218 can add up to 26 bits into `bitC`.
201219 Does not check for register overflow ! */
202- MEM_STATIC void BIT_addBits (BIT_CStream_t * bitC , size_t value , unsigned nbBits )
220+ MEM_STATIC void BIT_addBits (BIT_CStream_t * bitC ,
221+ size_t value , unsigned nbBits )
203222{
204223 bitC -> bitContainer |= (value & BIT_mask [nbBits ]) << bitC -> bitPos ;
205224 bitC -> bitPos += nbBits ;
206225}
207226
208227/*! BIT_addBitsFast() :
209228 * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
210- MEM_STATIC void BIT_addBitsFast (BIT_CStream_t * bitC , size_t value , unsigned nbBits )
229+ MEM_STATIC void BIT_addBitsFast (BIT_CStream_t * bitC ,
230+ size_t value , unsigned nbBits )
211231{
232+ assert ((value >>nbBits ) == 0 );
212233 bitC -> bitContainer |= value << bitC -> bitPos ;
213234 bitC -> bitPos += nbBits ;
214235}
215236
216237/*! BIT_flushBitsFast() :
238+ * assumption : bitContainer has not overflowed
217239 * unsafe version; does not check buffer overflow */
218240MEM_STATIC void BIT_flushBitsFast (BIT_CStream_t * bitC )
219241{
220242 size_t const nbBytes = bitC -> bitPos >> 3 ;
243+ assert ( bitC -> bitPos <= (sizeof (bitC -> bitContainer )* 8 ) );
221244 MEM_writeLEST (bitC -> ptr , bitC -> bitContainer );
222245 bitC -> ptr += nbBytes ;
246+ assert (bitC -> ptr <= bitC -> endPtr );
223247 bitC -> bitPos &= 7 ;
224- bitC -> bitContainer >>= nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
248+ bitC -> bitContainer >>= nbBytes * 8 ;
225249}
226250
227251/*! BIT_flushBits() :
252+ * assumption : bitContainer has not overflowed
228253 * safe version; check for buffer overflow, and prevents it.
229- * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
254+ * note : does not signal buffer overflow.
255+ * overflow will be revealed later on using BIT_closeCStream() */
230256MEM_STATIC void BIT_flushBits (BIT_CStream_t * bitC )
231257{
232258 size_t const nbBytes = bitC -> bitPos >> 3 ;
259+ assert ( bitC -> bitPos <= (sizeof (bitC -> bitContainer )* 8 ) );
233260 MEM_writeLEST (bitC -> ptr , bitC -> bitContainer );
234261 bitC -> ptr += nbBytes ;
235262 if (bitC -> ptr > bitC -> endPtr ) bitC -> ptr = bitC -> endPtr ;
236263 bitC -> bitPos &= 7 ;
237- bitC -> bitContainer >>= nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
264+ bitC -> bitContainer >>= nbBytes * 8 ;
238265}
239266
240267/*! BIT_closeCStream() :
@@ -244,9 +271,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
244271{
245272 BIT_addBitsFast (bitC , 1 , 1 ); /* endMark */
246273 BIT_flushBits (bitC );
247-
248- if (bitC -> ptr >= bitC -> endPtr ) return 0 ; /* doesn't fit within authorized budget : cancel */
249-
274+ if (bitC -> ptr >= bitC -> endPtr ) return 0 ; /* overflow detected */
250275 return (bitC -> ptr - bitC -> startPtr ) + (bitC -> bitPos > 0 );
251276}
252277
@@ -264,15 +289,16 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
264289{
265290 if (srcSize < 1 ) { memset (bitD , 0 , sizeof (* bitD )); return ERROR (srcSize_wrong ); }
266291
292+ bitD -> start = (const char * )srcBuffer ;
293+ bitD -> limitPtr = bitD -> start + sizeof (bitD -> bitContainer );
294+
267295 if (srcSize >= sizeof (bitD -> bitContainer )) { /* normal case */
268- bitD -> start = (const char * )srcBuffer ;
269296 bitD -> ptr = (const char * )srcBuffer + srcSize - sizeof (bitD -> bitContainer );
270297 bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
271298 { BYTE const lastByte = ((const BYTE * )srcBuffer )[srcSize - 1 ];
272299 bitD -> bitsConsumed = lastByte ? 8 - BIT_highbit32 (lastByte ) : 0 ; /* ensures bitsConsumed is always set */
273300 if (lastByte == 0 ) return ERROR (GENERIC ); /* endMark not present */ }
274301 } else {
275- bitD -> start = (const char * )srcBuffer ;
276302 bitD -> ptr = bitD -> start ;
277303 bitD -> bitContainer = * (const BYTE * )(bitD -> start );
278304 switch (srcSize )
@@ -330,17 +356,18 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
330356#if defined(__BMI__ ) && defined(__GNUC__ ) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
331357 return BIT_getMiddleBits (bitD -> bitContainer , (sizeof (bitD -> bitContainer )* 8 ) - bitD -> bitsConsumed - nbBits , nbBits );
332358#else
333- U32 const bitMask = sizeof (bitD -> bitContainer )* 8 - 1 ;
334- return ((bitD -> bitContainer << (bitD -> bitsConsumed & bitMask )) >> 1 ) >> ((bitMask - nbBits ) & bitMask );
359+ U32 const regMask = sizeof (bitD -> bitContainer )* 8 - 1 ;
360+ return ((bitD -> bitContainer << (bitD -> bitsConsumed & regMask )) >> 1 ) >> ((regMask - nbBits ) & regMask );
335361#endif
336362}
337363
338364/*! BIT_lookBitsFast() :
339- * unsafe version; only works only if nbBits >= 1 */
365+ * unsafe version; only works if nbBits >= 1 */
340366MEM_STATIC size_t BIT_lookBitsFast (const BIT_DStream_t * bitD , U32 nbBits )
341367{
342- U32 const bitMask = sizeof (bitD -> bitContainer )* 8 - 1 ;
343- return (bitD -> bitContainer << (bitD -> bitsConsumed & bitMask )) >> (((bitMask + 1 )- nbBits ) & bitMask );
368+ U32 const regMask = sizeof (bitD -> bitContainer )* 8 - 1 ;
369+ assert (nbBits >= 1 );
370+ return (bitD -> bitContainer << (bitD -> bitsConsumed & regMask )) >> (((regMask + 1 )- nbBits ) & regMask );
344371}
345372
346373MEM_STATIC void BIT_skipBits (BIT_DStream_t * bitD , U32 nbBits )
@@ -365,6 +392,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
365392MEM_STATIC size_t BIT_readBitsFast (BIT_DStream_t * bitD , U32 nbBits )
366393{
367394 size_t const value = BIT_lookBitsFast (bitD , nbBits );
395+ assert (nbBits >= 1 );
368396 BIT_skipBits (bitD , nbBits );
369397 return value ;
370398}
@@ -376,10 +404,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
376404 if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
377405MEM_STATIC BIT_DStream_status BIT_reloadDStream (BIT_DStream_t * bitD )
378406{
379- if (bitD -> bitsConsumed > (sizeof (bitD -> bitContainer )* 8 )) /* should not happen => corruption detected */
380- return BIT_DStream_overflow ;
407+ if (bitD -> bitsConsumed > (sizeof (bitD -> bitContainer )* 8 )) /* overflow detected, like end of stream */
408+ return BIT_DStream_overflow ;
381409
382- if (bitD -> ptr >= bitD -> start + sizeof ( bitD -> bitContainer ) ) {
410+ if (bitD -> ptr >= bitD -> limitPtr ) {
383411 bitD -> ptr -= bitD -> bitsConsumed >> 3 ;
384412 bitD -> bitsConsumed &= 7 ;
385413 bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
@@ -389,6 +417,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
389417 if (bitD -> bitsConsumed < sizeof (bitD -> bitContainer )* 8 ) return BIT_DStream_endOfBuffer ;
390418 return BIT_DStream_completed ;
391419 }
420+ /* start < ptr < limitPtr */
392421 { U32 nbBytes = bitD -> bitsConsumed >> 3 ;
393422 BIT_DStream_status result = BIT_DStream_unfinished ;
394423 if (bitD -> ptr - nbBytes < bitD -> start ) {
@@ -397,7 +426,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
397426 }
398427 bitD -> ptr -= nbBytes ;
399428 bitD -> bitsConsumed -= nbBytes * 8 ;
400- bitD -> bitContainer = MEM_readLEST (bitD -> ptr ); /* reminder : srcSize > sizeof(bitD) */
429+ bitD -> bitContainer = MEM_readLEST (bitD -> ptr ); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
401430 return result ;
402431 }
403432}
0 commit comments