2
2
bitstream
3
3
Part of FSE library
4
4
header file (to include)
5
- Copyright (C) 2013-2016 , Yann Collet.
5
+ Copyright (C) 2013-2017 , Yann Collet.
6
6
7
7
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8
8
@@ -53,6 +53,16 @@ extern "C" {
53
53
#include "error_private.h" /* error codes and messages */
54
54
55
55
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
+
56
66
/*=========================================
57
67
* Target specific
58
68
=========================================*/
@@ -74,7 +84,7 @@ extern "C" {
74
84
typedef struct
75
85
{
76
86
size_t bitContainer ;
77
- int bitPos ;
87
+ unsigned bitPos ;
78
88
char * startPtr ;
79
89
char * ptr ;
80
90
char * endPtr ;
@@ -112,6 +122,7 @@ typedef struct
112
122
unsigned bitsConsumed ;
113
123
const char * ptr ;
114
124
const char * start ;
125
+ const char * limitPtr ;
115
126
} BIT_DStream_t ;
116
127
117
128
typedef enum { BIT_DStream_unfinished = 0 ,
@@ -163,7 +174,10 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
163
174
# elif defined(__GNUC__ ) && (__GNUC__ >= 3 ) /* Use GCC Intrinsic */
164
175
return 31 - __builtin_clz (val );
165
176
# 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 };
167
181
U32 v = val ;
168
182
v |= v >> 1 ;
169
183
v |= v >> 2 ;
@@ -175,66 +189,79 @@ MEM_STATIC unsigned BIT_highbit32 (register U32 val)
175
189
}
176
190
177
191
/*===== 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 */
179
196
180
197
181
198
/*-**************************************************************
182
199
* bitStream encoding
183
200
****************************************************************/
184
201
/*! BIT_initCStream() :
185
- * `dstCapacity` must be > sizeof(void* )
202
+ * `dstCapacity` must be > sizeof(size_t )
186
203
* @return : 0 if success,
187
204
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 )
189
207
{
190
208
bitC -> bitContainer = 0 ;
191
209
bitC -> bitPos = 0 ;
192
210
bitC -> startPtr = (char * )startPtr ;
193
211
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 );
196
214
return 0 ;
197
215
}
198
216
199
217
/*! BIT_addBits() :
200
218
can add up to 26 bits into `bitC`.
201
219
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 )
203
222
{
204
223
bitC -> bitContainer |= (value & BIT_mask [nbBits ]) << bitC -> bitPos ;
205
224
bitC -> bitPos += nbBits ;
206
225
}
207
226
208
227
/*! BIT_addBitsFast() :
209
228
* 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 )
211
231
{
232
+ assert ((value >>nbBits ) == 0 );
212
233
bitC -> bitContainer |= value << bitC -> bitPos ;
213
234
bitC -> bitPos += nbBits ;
214
235
}
215
236
216
237
/*! BIT_flushBitsFast() :
238
+ * assumption : bitContainer has not overflowed
217
239
* unsafe version; does not check buffer overflow */
218
240
MEM_STATIC void BIT_flushBitsFast (BIT_CStream_t * bitC )
219
241
{
220
242
size_t const nbBytes = bitC -> bitPos >> 3 ;
243
+ assert ( bitC -> bitPos <= (sizeof (bitC -> bitContainer )* 8 ) );
221
244
MEM_writeLEST (bitC -> ptr , bitC -> bitContainer );
222
245
bitC -> ptr += nbBytes ;
246
+ assert (bitC -> ptr <= bitC -> endPtr );
223
247
bitC -> bitPos &= 7 ;
224
- bitC -> bitContainer >>= nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
248
+ bitC -> bitContainer >>= nbBytes * 8 ;
225
249
}
226
250
227
251
/*! BIT_flushBits() :
252
+ * assumption : bitContainer has not overflowed
228
253
* 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() */
230
256
MEM_STATIC void BIT_flushBits (BIT_CStream_t * bitC )
231
257
{
232
258
size_t const nbBytes = bitC -> bitPos >> 3 ;
259
+ assert ( bitC -> bitPos <= (sizeof (bitC -> bitContainer )* 8 ) );
233
260
MEM_writeLEST (bitC -> ptr , bitC -> bitContainer );
234
261
bitC -> ptr += nbBytes ;
235
262
if (bitC -> ptr > bitC -> endPtr ) bitC -> ptr = bitC -> endPtr ;
236
263
bitC -> bitPos &= 7 ;
237
- bitC -> bitContainer >>= nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
264
+ bitC -> bitContainer >>= nbBytes * 8 ;
238
265
}
239
266
240
267
/*! BIT_closeCStream() :
@@ -244,9 +271,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
244
271
{
245
272
BIT_addBitsFast (bitC , 1 , 1 ); /* endMark */
246
273
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 */
250
275
return (bitC -> ptr - bitC -> startPtr ) + (bitC -> bitPos > 0 );
251
276
}
252
277
@@ -264,15 +289,16 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
264
289
{
265
290
if (srcSize < 1 ) { memset (bitD , 0 , sizeof (* bitD )); return ERROR (srcSize_wrong ); }
266
291
292
+ bitD -> start = (const char * )srcBuffer ;
293
+ bitD -> limitPtr = bitD -> start + sizeof (bitD -> bitContainer );
294
+
267
295
if (srcSize >= sizeof (bitD -> bitContainer )) { /* normal case */
268
- bitD -> start = (const char * )srcBuffer ;
269
296
bitD -> ptr = (const char * )srcBuffer + srcSize - sizeof (bitD -> bitContainer );
270
297
bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
271
298
{ BYTE const lastByte = ((const BYTE * )srcBuffer )[srcSize - 1 ];
272
299
bitD -> bitsConsumed = lastByte ? 8 - BIT_highbit32 (lastByte ) : 0 ; /* ensures bitsConsumed is always set */
273
300
if (lastByte == 0 ) return ERROR (GENERIC ); /* endMark not present */ }
274
301
} else {
275
- bitD -> start = (const char * )srcBuffer ;
276
302
bitD -> ptr = bitD -> start ;
277
303
bitD -> bitContainer = * (const BYTE * )(bitD -> start );
278
304
switch (srcSize )
@@ -330,17 +356,18 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
330
356
#if defined(__BMI__ ) && defined(__GNUC__ ) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
331
357
return BIT_getMiddleBits (bitD -> bitContainer , (sizeof (bitD -> bitContainer )* 8 ) - bitD -> bitsConsumed - nbBits , nbBits );
332
358
#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 );
335
361
#endif
336
362
}
337
363
338
364
/*! BIT_lookBitsFast() :
339
- * unsafe version; only works only if nbBits >= 1 */
365
+ * unsafe version; only works if nbBits >= 1 */
340
366
MEM_STATIC size_t BIT_lookBitsFast (const BIT_DStream_t * bitD , U32 nbBits )
341
367
{
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 );
344
371
}
345
372
346
373
MEM_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)
365
392
MEM_STATIC size_t BIT_readBitsFast (BIT_DStream_t * bitD , U32 nbBits )
366
393
{
367
394
size_t const value = BIT_lookBitsFast (bitD , nbBits );
395
+ assert (nbBits >= 1 );
368
396
BIT_skipBits (bitD , nbBits );
369
397
return value ;
370
398
}
@@ -376,10 +404,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
376
404
if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
377
405
MEM_STATIC BIT_DStream_status BIT_reloadDStream (BIT_DStream_t * bitD )
378
406
{
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 ;
381
409
382
- if (bitD -> ptr >= bitD -> start + sizeof ( bitD -> bitContainer ) ) {
410
+ if (bitD -> ptr >= bitD -> limitPtr ) {
383
411
bitD -> ptr -= bitD -> bitsConsumed >> 3 ;
384
412
bitD -> bitsConsumed &= 7 ;
385
413
bitD -> bitContainer = MEM_readLEST (bitD -> ptr );
@@ -389,6 +417,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
389
417
if (bitD -> bitsConsumed < sizeof (bitD -> bitContainer )* 8 ) return BIT_DStream_endOfBuffer ;
390
418
return BIT_DStream_completed ;
391
419
}
420
+ /* start < ptr < limitPtr */
392
421
{ U32 nbBytes = bitD -> bitsConsumed >> 3 ;
393
422
BIT_DStream_status result = BIT_DStream_unfinished ;
394
423
if (bitD -> ptr - nbBytes < bitD -> start ) {
@@ -397,7 +426,7 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
397
426
}
398
427
bitD -> ptr -= nbBytes ;
399
428
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 */
401
430
return result ;
402
431
}
403
432
}
0 commit comments