2015-10-18 14:18:32 -07:00
/* ******************************************************************
bitstream
2016-02-02 17:46:46 -08:00
Part of FSE library
2015-10-18 14:18:32 -07:00
header file ( to include )
2016-02-02 17:46:46 -08:00
Copyright ( C ) 2013 - 2016 , Yann Collet .
2015-10-18 14:18:32 -07:00
BSD 2 - Clause License ( http : //www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
* Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the following disclaimer
in the documentation and / or other materials provided with the
distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
You can contact the author at :
- Source repository : https : //github.com/Cyan4973/FiniteStateEntropy
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef BITSTREAM_H_MODULE
# define BITSTREAM_H_MODULE
# if defined (__cplusplus)
extern " C " {
# endif
/*
2016-03-19 06:14:31 -07:00
* This API consists of small unitary functions , which must be inlined for best performance .
2015-10-18 14:18:32 -07:00
* Since link - time - optimization is not available for all compilers ,
* these functions are defined into a . h to be included .
*/
2016-02-02 17:46:46 -08:00
/*-****************************************
* Dependencies
2015-10-18 14:18:32 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-21 06:38:47 -08:00
# include "mem.h" /* unaligned access routines */
# include "error_private.h" /* error codes and messages */
2015-10-18 14:18:32 -07:00
2016-03-26 09:50:26 -07:00
/*=========================================
* Target specific
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# if defined(__BMI__) && defined(__GNUC__)
# include <immintrin.h> /* support for bextr (experimental) */
# endif
2016-02-02 17:46:46 -08:00
/*-******************************************
* bitStream encoding API ( write forward )
2015-10-18 14:18:32 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-19 04:12:07 -07:00
/* bitStream can mix input from multiple sources.
* 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 .
2015-10-18 14:18:32 -07:00
*/
typedef struct
{
size_t bitContainer ;
int bitPos ;
char * startPtr ;
char * ptr ;
char * endPtr ;
} BIT_CStream_t ;
2016-02-02 17:46:46 -08:00
MEM_STATIC size_t BIT_initCStream ( BIT_CStream_t * bitC , void * dstBuffer , size_t dstCapacity ) ;
2015-10-18 14:18:32 -07:00
MEM_STATIC void BIT_addBits ( BIT_CStream_t * bitC , size_t value , unsigned nbBits ) ;
MEM_STATIC void BIT_flushBits ( BIT_CStream_t * bitC ) ;
MEM_STATIC size_t BIT_closeCStream ( BIT_CStream_t * bitC ) ;
2016-03-19 06:14:31 -07:00
/* Start with initCStream, providing the size of buffer to write into.
* bitStream will never write outside of this buffer .
2016-05-11 09:30:24 -07:00
* ` dstCapacity ` must be > = sizeof ( bitD - > bitContainer ) , otherwise @ return will be an error code .
2015-10-18 14:18:32 -07:00
*
2016-03-19 06:14:31 -07:00
* bits are first added to a local register .
* Local register is size_t , hence 64 - bits on 64 - bits systems , or 32 - bits on 32 - bits systems .
* Writing data into memory is an explicit operation , performed by the flushBits function .
* Hence keep track how many bits are potentially stored into local register to avoid register overflow .
* After a flushBits , a maximum of 7 bits might still be stored into local register .
2015-10-18 14:18:32 -07:00
*
2016-03-19 06:14:31 -07:00
* Avoid storing elements of more than 24 bits if you want compatibility with 32 - bits bitstream readers .
2015-10-18 14:18:32 -07:00
*
2016-03-19 06:14:31 -07:00
* Last operation is to close the bitStream .
* The function returns the final size of CStream in bytes .
* If data couldn ' t fit into ` dstBuffer ` , it will return a 0 ( = = not storable )
2015-10-18 14:18:32 -07:00
*/
2016-02-02 17:46:46 -08:00
/*-********************************************
* bitStream decoding API ( read backward )
2015-10-18 14:18:32 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef struct
{
size_t bitContainer ;
unsigned bitsConsumed ;
const char * ptr ;
const char * start ;
} BIT_DStream_t ;
typedef enum { BIT_DStream_unfinished = 0 ,
BIT_DStream_endOfBuffer = 1 ,
BIT_DStream_completed = 2 ,
BIT_DStream_overflow = 3 } BIT_DStream_status ; /* result of BIT_reloadDStream() */
/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
MEM_STATIC size_t BIT_initDStream ( BIT_DStream_t * bitD , const void * srcBuffer , size_t srcSize ) ;
MEM_STATIC size_t BIT_readBits ( BIT_DStream_t * bitD , unsigned nbBits ) ;
MEM_STATIC BIT_DStream_status BIT_reloadDStream ( BIT_DStream_t * bitD ) ;
MEM_STATIC unsigned BIT_endOfDStream ( const BIT_DStream_t * bitD ) ;
2016-03-19 06:14:31 -07:00
/* Start by invoking BIT_initDStream().
* A chunk of the bitStream is then stored into a local register .
* Local register size is 64 - bits on 64 - bits systems , 32 - bits on 32 - bits systems ( size_t ) .
* You can then retrieve bitFields stored into the local register , * * in reverse order * * .
* Local register is explicitly reloaded from memory by the BIT_reloadDStream ( ) method .
2016-05-11 09:30:24 -07:00
* A reload guarantee a minimum of ( ( 8 * sizeof ( bitD - > bitContainer ) ) - 7 ) bits when its result is BIT_DStream_unfinished .
2016-03-19 06:14:31 -07:00
* Otherwise , it can be less than that , so proceed accordingly .
2016-03-23 17:27:55 -07:00
* Checking if DStream has reached its end can be performed with BIT_endOfDStream ( ) .
2015-10-18 14:18:32 -07:00
*/
2016-02-02 17:46:46 -08:00
/*-****************************************
2015-10-18 14:18:32 -07:00
* unsafe API
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
MEM_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 */
MEM_STATIC void BIT_flushBitsFast ( BIT_CStream_t * bitC ) ;
/* unsafe version; does not check buffer overflow */
MEM_STATIC size_t BIT_readBitsFast ( BIT_DStream_t * bitD , unsigned nbBits ) ;
/* faster, but works only if nbBits >= 1 */
2016-02-02 17:46:46 -08:00
/*-**************************************************************
2016-03-23 06:18:37 -07:00
* Internal functions
2015-10-18 14:18:32 -07:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
MEM_STATIC unsigned BIT_highbit32 ( register U32 val )
{
# if defined(_MSC_VER) /* Visual */
2015-10-29 22:40:22 -07:00
unsigned long r = 0 ;
2015-10-18 14:18:32 -07:00
_BitScanReverse ( & r , val ) ;
return ( unsigned ) r ;
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
return 31 - __builtin_clz ( val ) ;
# 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 } ;
U32 v = val ;
v | = v > > 1 ;
v | = v > > 2 ;
v | = v > > 4 ;
v | = v > > 8 ;
v | = v > > 16 ;
2016-05-20 05:36:36 -07:00
return DeBruijnClz [ ( U32 ) ( v * 0x07C4ACDDU ) > > 27 ] ;
2015-10-18 14:18:32 -07:00
# endif
}
2016-03-23 06:18:37 -07:00
/*===== 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 */
2015-10-18 14:18:32 -07:00
2016-02-02 17:46:46 -08:00
/*-**************************************************************
2015-10-18 14:18:32 -07:00
* bitStream encoding
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-19 06:14:31 -07:00
/*! BIT_initCStream() :
* ` dstCapacity ` must be > sizeof ( void * )
* @ return : 0 if success ,
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 )
2015-10-18 14:18:32 -07:00
{
bitC - > bitContainer = 0 ;
bitC - > bitPos = 0 ;
bitC - > startPtr = ( char * ) startPtr ;
bitC - > ptr = bitC - > startPtr ;
2016-03-19 06:14:31 -07:00
bitC - > endPtr = bitC - > startPtr + dstCapacity - sizeof ( bitC - > ptr ) ;
if ( dstCapacity < = sizeof ( bitC - > ptr ) ) return ERROR ( dstSize_tooSmall ) ;
2015-10-18 14:18:32 -07:00
return 0 ;
}
2016-03-19 06:14:31 -07:00
/*! BIT_addBits() :
can add up to 26 bits into ` bitC ` .
Does not check for register overflow ! */
2015-10-18 14:18:32 -07:00
MEM_STATIC void BIT_addBits ( BIT_CStream_t * bitC , size_t value , unsigned nbBits )
{
2016-03-23 06:18:37 -07:00
bitC - > bitContainer | = ( value & BIT_mask [ nbBits ] ) < < bitC - > bitPos ;
2015-10-18 14:18:32 -07:00
bitC - > bitPos + = nbBits ;
}
2016-03-19 04:12:07 -07:00
/*! BIT_addBitsFast() :
2015-10-18 14:18:32 -07:00
* 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 )
{
bitC - > bitContainer | = value < < bitC - > bitPos ;
bitC - > bitPos + = nbBits ;
}
2016-03-19 04:12:07 -07:00
/*! BIT_flushBitsFast() :
2015-10-18 14:18:32 -07:00
* unsafe version ; does not check buffer overflow */
MEM_STATIC void BIT_flushBitsFast ( BIT_CStream_t * bitC )
{
2016-03-20 16:07:42 -07:00
size_t const nbBytes = bitC - > bitPos > > 3 ;
2015-10-18 14:18:32 -07:00
MEM_writeLEST ( bitC - > ptr , bitC - > bitContainer ) ;
bitC - > ptr + = nbBytes ;
bitC - > bitPos & = 7 ;
2015-11-28 07:03:22 -08:00
bitC - > bitContainer > > = nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
2015-10-18 14:18:32 -07:00
}
2016-03-19 06:14:31 -07:00
/*! BIT_flushBits() :
* safe version ; check for buffer overflow , and prevents it .
* note : does not signal buffer overflow . This will be revealed later on using BIT_closeCStream ( ) */
2015-10-18 14:18:32 -07:00
MEM_STATIC void BIT_flushBits ( BIT_CStream_t * bitC )
{
2016-03-20 16:07:42 -07:00
size_t const nbBytes = bitC - > bitPos > > 3 ;
2015-10-18 14:18:32 -07:00
MEM_writeLEST ( bitC - > ptr , bitC - > bitContainer ) ;
bitC - > ptr + = nbBytes ;
if ( bitC - > ptr > bitC - > endPtr ) bitC - > ptr = bitC - > endPtr ;
bitC - > bitPos & = 7 ;
2015-11-28 07:03:22 -08:00
bitC - > bitContainer > > = nbBytes * 8 ; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
2015-10-18 14:18:32 -07:00
}
2016-03-19 04:12:07 -07:00
/*! BIT_closeCStream() :
2016-03-19 06:14:31 -07:00
* @ return : size of CStream , in bytes ,
or 0 if it could not fit into dstBuffer */
2015-10-18 14:18:32 -07:00
MEM_STATIC size_t BIT_closeCStream ( BIT_CStream_t * bitC )
{
BIT_addBitsFast ( bitC , 1 , 1 ) ; /* endMark */
BIT_flushBits ( bitC ) ;
2016-03-19 06:14:31 -07:00
if ( bitC - > ptr > = bitC - > endPtr ) return 0 ; /* doesn't fit within authorized budget : cancel */
2015-10-18 14:18:32 -07:00
2016-03-19 06:14:31 -07:00
return ( bitC - > ptr - bitC - > startPtr ) + ( bitC - > bitPos > 0 ) ;
2015-10-18 14:18:32 -07:00
}
2016-02-02 17:46:46 -08:00
/*-********************************************************
2015-10-18 14:18:32 -07:00
* bitStream decoding
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-03-19 06:14:31 -07:00
/*! BIT_initDStream() :
* Initialize a BIT_DStream_t .
* ` bitD ` : a pointer to an already allocated BIT_DStream_t structure .
2016-03-22 17:32:41 -07:00
* ` srcSize ` must be the * exact * size of the bitStream , in bytes .
2016-03-19 06:14:31 -07:00
* @ return : size of stream ( = = srcSize ) or an errorCode if a problem is detected
2015-10-18 14:18:32 -07:00
*/
MEM_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 ) ; }
2016-05-11 09:30:24 -07:00
if ( srcSize > = sizeof ( bitD - > bitContainer ) ) { /* normal case */
2015-10-18 14:18:32 -07:00
bitD - > start = ( const char * ) srcBuffer ;
2016-05-11 09:30:24 -07:00
bitD - > ptr = ( const char * ) srcBuffer + srcSize - sizeof ( bitD - > bitContainer ) ;
2015-10-18 14:18:32 -07:00
bitD - > bitContainer = MEM_readLEST ( bitD - > ptr ) ;
2016-03-23 17:27:55 -07:00
{ BYTE const lastByte = ( ( const BYTE * ) srcBuffer ) [ srcSize - 1 ] ;
2016-06-12 13:51:52 -07:00
bitD - > bitsConsumed = lastByte ? 8 - BIT_highbit32 ( lastByte ) : 0 ;
if ( lastByte = = 0 ) return ERROR ( GENERIC ) ; /* endMark not present */ }
2016-02-02 17:46:46 -08:00
} else {
2015-10-18 14:18:32 -07:00
bitD - > start = ( const char * ) srcBuffer ;
bitD - > ptr = bitD - > start ;
2016-05-12 04:50:13 -07:00
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 : ;
}
2016-03-23 17:27:55 -07:00
{ BYTE const lastByte = ( ( const BYTE * ) srcBuffer ) [ srcSize - 1 ] ;
2016-06-12 13:51:52 -07:00
bitD - > bitsConsumed = lastByte ? 8 - BIT_highbit32 ( lastByte ) : 0 ;
if ( lastByte = = 0 ) return ERROR ( GENERIC ) ; /* endMark not present */ }
2016-05-11 09:30:24 -07:00
bitD - > bitsConsumed + = ( U32 ) ( sizeof ( bitD - > bitContainer ) - srcSize ) * 8 ;
2015-10-18 14:18:32 -07:00
}
return srcSize ;
}
2016-05-11 09:30:24 -07:00
MEM_STATIC size_t BIT_getUpperBits ( size_t bitContainer , U32 const start )
2016-03-23 06:09:51 -07:00
{
2016-05-11 09:30:24 -07:00
return bitContainer > > start ;
2016-03-23 06:09:51 -07:00
}
2016-05-11 09:30:24 -07:00
MEM_STATIC size_t BIT_getMiddleBits ( size_t bitContainer , U32 const start , U32 const nbBits )
2016-03-23 06:09:51 -07:00
{
2016-03-23 17:27:55 -07:00
# if defined(__BMI__) && defined(__GNUC__) /* experimental */
2016-05-01 01:26:30 -07:00
# if defined(__x86_64__)
2016-05-11 09:30:24 -07:00
if ( sizeof ( bitContainer ) = = 8 )
return _bextr_u64 ( bitContainer , start , nbBits ) ;
2016-05-01 01:26:30 -07:00
else
# endif
2016-05-11 09:30:24 -07:00
return _bextr_u32 ( bitContainer , start , nbBits ) ;
2016-03-23 10:45:23 -07:00
# else
2016-05-11 09:30:24 -07:00
return ( bitContainer > > start ) & BIT_mask [ nbBits ] ;
2016-03-23 10:45:23 -07:00
# endif
2016-03-23 06:09:51 -07:00
}
2016-05-11 09:30:24 -07:00
MEM_STATIC size_t BIT_getLowerBits ( size_t bitContainer , U32 const nbBits )
2016-03-23 05:57:49 -07:00
{
2016-05-11 09:30:24 -07:00
return bitContainer & BIT_mask [ nbBits ] ;
2016-03-23 05:57:49 -07:00
}
2016-03-19 06:14:31 -07:00
/*! BIT_lookBits() :
* Provides next n bits from local register .
2016-05-11 09:30:24 -07:00
* local register is not modified .
2016-03-19 06:14:31 -07:00
* On 32 - bits , maxNbBits = = 24.
* On 64 - bits , maxNbBits = = 56.
* @ return : value extracted
2015-10-18 14:18:32 -07:00
*/
2016-03-23 10:45:23 -07:00
MEM_STATIC size_t BIT_lookBits ( const BIT_DStream_t * bitD , U32 nbBits )
2015-10-18 14:18:32 -07:00
{
2016-05-11 09:30:24 -07:00
# 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 ) ;
2016-03-23 10:45:23 -07:00
# else
2016-03-19 04:12:07 -07:00
U32 const bitMask = sizeof ( bitD - > bitContainer ) * 8 - 1 ;
2015-10-18 14:18:32 -07:00
return ( ( bitD - > bitContainer < < ( bitD - > bitsConsumed & bitMask ) ) > > 1 ) > > ( ( bitMask - nbBits ) & bitMask ) ;
2016-03-23 10:45:23 -07:00
# endif
2015-10-18 14:18:32 -07:00
}
2016-03-19 06:14:31 -07:00
/*! BIT_lookBitsFast() :
2015-10-18 14:18:32 -07:00
* unsafe version ; only works only if nbBits > = 1 */
2016-03-22 17:32:41 -07:00
MEM_STATIC size_t BIT_lookBitsFast ( const BIT_DStream_t * bitD , U32 nbBits )
2015-10-18 14:18:32 -07:00
{
2016-03-19 04:12:07 -07:00
U32 const bitMask = sizeof ( bitD - > bitContainer ) * 8 - 1 ;
2015-10-18 14:18:32 -07:00
return ( bitD - > bitContainer < < ( bitD - > bitsConsumed & bitMask ) ) > > ( ( ( bitMask + 1 ) - nbBits ) & bitMask ) ;
}
MEM_STATIC void BIT_skipBits ( BIT_DStream_t * bitD , U32 nbBits )
{
bitD - > bitsConsumed + = nbBits ;
}
2016-03-19 06:14:31 -07:00
/*! BIT_readBits() :
2016-03-23 17:27:55 -07:00
* Read ( consume ) next n bits from local register and update .
* Pay attention to not read more than nbBits contained into local register .
2016-03-19 06:14:31 -07:00
* @ return : extracted value .
2015-10-18 14:18:32 -07:00
*/
MEM_STATIC size_t BIT_readBits ( BIT_DStream_t * bitD , U32 nbBits )
{
2016-03-23 05:57:49 -07:00
size_t const value = BIT_lookBits ( bitD , nbBits ) ;
2015-10-18 14:18:32 -07:00
BIT_skipBits ( bitD , nbBits ) ;
return value ;
}
2016-03-19 06:14:31 -07:00
/*! BIT_readBitsFast() :
* unsafe version ; only works only if nbBits > = 1 */
2015-10-18 14:18:32 -07:00
MEM_STATIC size_t BIT_readBitsFast ( BIT_DStream_t * bitD , U32 nbBits )
{
2016-03-23 05:57:49 -07:00
size_t const value = BIT_lookBitsFast ( bitD , nbBits ) ;
2015-10-18 14:18:32 -07:00
BIT_skipBits ( bitD , nbBits ) ;
return value ;
}
2016-03-19 06:14:31 -07:00
/*! BIT_reloadDStream() :
* Refill ` BIT_DStream_t ` from src buffer previously defined ( see BIT_initDStream ( ) ) .
* This function is safe , it guarantees it will not read beyond src buffer .
* @ return : status of ` BIT_DStream_t ` internal register .
2016-05-11 09:30:24 -07:00
if status = = unfinished , internal register is filled with > = ( sizeof ( bitD - > bitContainer ) * 8 - 7 ) bits */
2015-10-18 14:18:32 -07:00
MEM_STATIC BIT_DStream_status BIT_reloadDStream ( BIT_DStream_t * bitD )
{
2016-05-20 05:36:36 -07:00
if ( bitD - > bitsConsumed > ( sizeof ( bitD - > bitContainer ) * 8 ) ) /* should not happen => corruption detected */
2015-10-18 14:18:32 -07:00
return BIT_DStream_overflow ;
2016-02-02 17:46:46 -08:00
if ( bitD - > ptr > = bitD - > start + sizeof ( bitD - > bitContainer ) ) {
2015-10-18 14:18:32 -07:00
bitD - > ptr - = bitD - > bitsConsumed > > 3 ;
bitD - > bitsConsumed & = 7 ;
bitD - > bitContainer = MEM_readLEST ( bitD - > ptr ) ;
return BIT_DStream_unfinished ;
}
2016-02-02 17:46:46 -08:00
if ( bitD - > ptr = = bitD - > start ) {
2015-10-18 14:18:32 -07:00
if ( bitD - > bitsConsumed < sizeof ( bitD - > bitContainer ) * 8 ) return BIT_DStream_endOfBuffer ;
return BIT_DStream_completed ;
}
2016-03-19 06:14:31 -07:00
{ U32 nbBytes = bitD - > bitsConsumed > > 3 ;
2015-10-18 14:18:32 -07:00
BIT_DStream_status result = BIT_DStream_unfinished ;
2016-02-02 17:46:46 -08:00
if ( bitD - > ptr - nbBytes < bitD - > start ) {
2015-10-18 14:18:32 -07:00
nbBytes = ( U32 ) ( bitD - > ptr - bitD - > start ) ; /* ptr > start */
result = BIT_DStream_endOfBuffer ;
}
bitD - > ptr - = nbBytes ;
bitD - > bitsConsumed - = nbBytes * 8 ;
bitD - > bitContainer = MEM_readLEST ( bitD - > ptr ) ; /* reminder : srcSize > sizeof(bitD) */
return result ;
}
}
2016-03-19 04:12:07 -07:00
/*! BIT_endOfDStream() :
2016-03-19 06:14:31 -07:00
* @ return Tells if DStream has exactly reached its end ( all bits consumed ) .
2015-10-18 14:18:32 -07:00
*/
MEM_STATIC unsigned BIT_endOfDStream ( const BIT_DStream_t * DStream )
{
return ( ( DStream - > ptr = = DStream - > start ) & & ( DStream - > bitsConsumed = = sizeof ( DStream - > bitContainer ) * 8 ) ) ;
}
# if defined (__cplusplus)
}
# endif
# endif /* BITSTREAM_H_MODULE */