blob: 404006808bea8921f2f7f22c826183630cf56ffe [file] [log] [blame]
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001/* ******************************************************************
2 bitstream
Yann Colletae7aa062016-02-03 02:46:46 +01003 Part of FSE library
Yann Colletb1f3f4b2015-10-18 22:18:32 +01004 header file (to include)
Yann Colletae7aa062016-02-03 02:46:46 +01005 Copyright (C) 2013-2016, Yann Collet.
Yann Colletb1f3f4b2015-10-18 22:18:32 +01006
7 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are
11 met:
12
13 * Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above
16 copyright notice, this list of conditions and the following disclaimer
17 in the documentation and/or other materials provided with the
18 distribution.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 You can contact the author at :
33 - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
Yann Colletb1f3f4b2015-10-18 22:18:32 +010034****************************************************************** */
35#ifndef BITSTREAM_H_MODULE
36#define BITSTREAM_H_MODULE
37
38#if defined (__cplusplus)
39extern "C" {
40#endif
41
42
43/*
Yann Collet01e5b952016-03-19 14:14:31 +010044* This API consists of small unitary functions, which must be inlined for best performance.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010045* Since link-time-optimization is not available for all compilers,
46* these functions are defined into a .h to be included.
47*/
48
Yann Colletae7aa062016-02-03 02:46:46 +010049/*-****************************************
50* Dependencies
Yann Colletb1f3f4b2015-10-18 22:18:32 +010051******************************************/
Yann Collet977f1f32016-01-21 15:38:47 +010052#include "mem.h" /* unaligned access routines */
53#include "error_private.h" /* error codes and messages */
Yann Colletb1f3f4b2015-10-18 22:18:32 +010054
55
Yann Colletae7aa062016-02-03 02:46:46 +010056/*-******************************************
57* bitStream encoding API (write forward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010058********************************************/
Yann Colletd1d210f2016-03-19 12:12:07 +010059/* bitStream can mix input from multiple sources.
60* A critical property of these streams is that they encode and decode in **reverse** direction.
61* So the first bit sequence you add will be the last to be read, like a LIFO stack.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010062*/
63typedef struct
64{
65 size_t bitContainer;
66 int bitPos;
67 char* startPtr;
68 char* ptr;
69 char* endPtr;
70} BIT_CStream_t;
71
Yann Colletae7aa062016-02-03 02:46:46 +010072MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
Yann Colletb1f3f4b2015-10-18 22:18:32 +010073MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
74MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
75MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
76
Yann Collet01e5b952016-03-19 14:14:31 +010077/* Start with initCStream, providing the size of buffer to write into.
78* bitStream will never write outside of this buffer.
79* `dstCapacity` must be >= sizeof(size_t), otherwise @return will be an error code.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010080*
Yann Collet01e5b952016-03-19 14:14:31 +010081* bits are first added to a local register.
82* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
83* Writing data into memory is an explicit operation, performed by the flushBits function.
84* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
85* After a flushBits, a maximum of 7 bits might still be stored into local register.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010086*
Yann Collet01e5b952016-03-19 14:14:31 +010087* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010088*
Yann Collet01e5b952016-03-19 14:14:31 +010089* Last operation is to close the bitStream.
90* The function returns the final size of CStream in bytes.
91* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010092*/
93
94
Yann Colletae7aa062016-02-03 02:46:46 +010095/*-********************************************
96* bitStream decoding API (read backward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010097**********************************************/
98typedef struct
99{
100 size_t bitContainer;
101 unsigned bitsConsumed;
102 const char* ptr;
103 const char* start;
104} BIT_DStream_t;
105
106typedef enum { BIT_DStream_unfinished = 0,
107 BIT_DStream_endOfBuffer = 1,
108 BIT_DStream_completed = 2,
109 BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
110 /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
111
112MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
113MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
114MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
115MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
116
117
Yann Collet01e5b952016-03-19 14:14:31 +0100118/* Start by invoking BIT_initDStream().
119* A chunk of the bitStream is then stored into a local register.
120* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
121* You can then retrieve bitFields stored into the local register, **in reverse order**.
122* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
123* A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished.
124* Otherwise, it can be less than that, so proceed accordingly.
Yann Colletb21ce152016-03-24 01:27:55 +0100125* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100126*/
127
128
Yann Colletae7aa062016-02-03 02:46:46 +0100129/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100130* unsafe API
131******************************************/
132MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
133/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
134
135MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
136/* unsafe version; does not check buffer overflow */
137
138MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
139/* faster, but works only if nbBits >= 1 */
140
141
142
Yann Colletae7aa062016-02-03 02:46:46 +0100143/*-**************************************************************
Yann Collet6cf45da2016-03-23 14:18:37 +0100144* Internal functions
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100145****************************************************************/
146MEM_STATIC unsigned BIT_highbit32 (register U32 val)
147{
148# if defined(_MSC_VER) /* Visual */
Yann Collet4114f952015-10-30 06:40:22 +0100149 unsigned long r=0;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100150 _BitScanReverse ( &r, val );
151 return (unsigned) r;
152# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
153 return 31 - __builtin_clz (val);
154# else /* Software version */
155 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 };
156 U32 v = val;
157 unsigned r;
158 v |= v >> 1;
159 v |= v >> 2;
160 v |= v >> 4;
161 v |= v >> 8;
162 v |= v >> 16;
163 r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
164 return r;
165# endif
166}
167
Yann Collet6cf45da2016-03-23 14:18:37 +0100168/*===== Local Constants =====*/
169static 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 */
170
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100171
Yann Colletae7aa062016-02-03 02:46:46 +0100172/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100173* bitStream encoding
174****************************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100175/*! BIT_initCStream() :
176 * `dstCapacity` must be > sizeof(void*)
177 * @return : 0 if success,
178 otherwise an error code (can be tested using ERR_isError() ) */
179MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t dstCapacity)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100180{
181 bitC->bitContainer = 0;
182 bitC->bitPos = 0;
183 bitC->startPtr = (char*)startPtr;
184 bitC->ptr = bitC->startPtr;
Yann Collet01e5b952016-03-19 14:14:31 +0100185 bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
186 if (dstCapacity <= sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100187 return 0;
188}
189
Yann Collet01e5b952016-03-19 14:14:31 +0100190/*! BIT_addBits() :
191 can add up to 26 bits into `bitC`.
192 Does not check for register overflow ! */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100193MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
194{
Yann Collet6cf45da2016-03-23 14:18:37 +0100195 bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100196 bitC->bitPos += nbBits;
197}
198
Yann Colletd1d210f2016-03-19 12:12:07 +0100199/*! BIT_addBitsFast() :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100200 * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
201MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
202{
203 bitC->bitContainer |= value << bitC->bitPos;
204 bitC->bitPos += nbBits;
205}
206
Yann Colletd1d210f2016-03-19 12:12:07 +0100207/*! BIT_flushBitsFast() :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100208 * unsafe version; does not check buffer overflow */
209MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
210{
Yann Colletd64f4352016-03-21 00:07:42 +0100211 size_t const nbBytes = bitC->bitPos >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100212 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
213 bitC->ptr += nbBytes;
214 bitC->bitPos &= 7;
Yann Collet00fd7a22015-11-28 16:03:22 +0100215 bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100216}
217
Yann Collet01e5b952016-03-19 14:14:31 +0100218/*! BIT_flushBits() :
219 * safe version; check for buffer overflow, and prevents it.
220 * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100221MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
222{
Yann Colletd64f4352016-03-21 00:07:42 +0100223 size_t const nbBytes = bitC->bitPos >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100224 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
225 bitC->ptr += nbBytes;
226 if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
227 bitC->bitPos &= 7;
Yann Collet00fd7a22015-11-28 16:03:22 +0100228 bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100229}
230
Yann Colletd1d210f2016-03-19 12:12:07 +0100231/*! BIT_closeCStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100232 * @return : size of CStream, in bytes,
233 or 0 if it could not fit into dstBuffer */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100234MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
235{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100236 BIT_addBitsFast(bitC, 1, 1); /* endMark */
237 BIT_flushBits(bitC);
238
Yann Collet01e5b952016-03-19 14:14:31 +0100239 if (bitC->ptr >= bitC->endPtr) return 0; /* doesn't fit within authorized budget : cancel */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100240
Yann Collet01e5b952016-03-19 14:14:31 +0100241 return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100242}
243
244
Yann Colletae7aa062016-02-03 02:46:46 +0100245/*-********************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100246* bitStream decoding
247**********************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100248/*! BIT_initDStream() :
249* Initialize a BIT_DStream_t.
250* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
Yann Colletadd08d62016-03-23 01:32:41 +0100251* `srcSize` must be the *exact* size of the bitStream, in bytes.
Yann Collet01e5b952016-03-19 14:14:31 +0100252* @return : size of stream (== srcSize) or an errorCode if a problem is detected
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100253*/
254MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
255{
256 if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
257
Yann Colletae7aa062016-02-03 02:46:46 +0100258 if (srcSize >= sizeof(size_t)) { /* normal case */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100259 bitD->start = (const char*)srcBuffer;
260 bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t);
261 bitD->bitContainer = MEM_readLEST(bitD->ptr);
Yann Colletb21ce152016-03-24 01:27:55 +0100262 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
263 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */
264 bitD->bitsConsumed = 8 - BIT_highbit32(lastByte); }
Yann Colletae7aa062016-02-03 02:46:46 +0100265 } else {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100266 bitD->start = (const char*)srcBuffer;
267 bitD->ptr = bitD->start;
268 bitD->bitContainer = *(const BYTE*)(bitD->start);
269 switch(srcSize)
270 {
271 case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);
272 case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);
273 case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);
274 case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;
275 case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;
276 case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8;
277 default:;
278 }
Yann Colletb21ce152016-03-24 01:27:55 +0100279 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
280 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */
281 bitD->bitsConsumed = 8 - BIT_highbit32(lastByte); }
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100282 bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
283 }
284
285 return srcSize;
286}
287
Yann Collet3c017862016-03-23 14:09:51 +0100288MEM_STATIC size_t BIT_getUpperBits(size_t bitD, U32 const start)
289{
290 return bitD >> start;
291}
292
Yann Collet862a8592016-03-23 18:45:23 +0100293#include <immintrin.h>
Yann Collet6cf45da2016-03-23 14:18:37 +0100294MEM_STATIC size_t BIT_getMiddleBits(size_t bitD, U32 const nbBits, U32 const start)
Yann Collet3c017862016-03-23 14:09:51 +0100295{
Yann Colletb21ce152016-03-24 01:27:55 +0100296#if defined(__BMI__) && defined(__GNUC__) /* experimental */
Yann Collet862a8592016-03-23 18:45:23 +0100297 return __builtin_ia32_bextr_u64(bitD, (nbBits<<8) | start );
298#else
Yann Collet6cf45da2016-03-23 14:18:37 +0100299 return (bitD >> start) & BIT_mask[nbBits];
Yann Collet862a8592016-03-23 18:45:23 +0100300#endif
Yann Collet3c017862016-03-23 14:09:51 +0100301}
302
Yann Collet6cf45da2016-03-23 14:18:37 +0100303MEM_STATIC size_t BIT_getLowerBits(size_t bitD, U32 const nbBits)
Yann Colletafab0202016-03-23 13:57:49 +0100304{
Yann Collet6cf45da2016-03-23 14:18:37 +0100305 return bitD & BIT_mask[nbBits];
Yann Colletafab0202016-03-23 13:57:49 +0100306}
307
Yann Collet01e5b952016-03-19 14:14:31 +0100308/*! BIT_lookBits() :
309 * Provides next n bits from local register.
310 * local register is not modified (bits are still present for next read/look).
311 * On 32-bits, maxNbBits==24.
312 * On 64-bits, maxNbBits==56.
313 * @return : value extracted
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100314 */
Yann Collet862a8592016-03-23 18:45:23 +0100315 MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100316{
Yann Colletb21ce152016-03-24 01:27:55 +0100317#if defined(__BMI__) && defined(__GNUC__) /* experimental */
Yann Collet862a8592016-03-23 18:45:23 +0100318 return __builtin_ia32_bextr_u64(bitD->bitContainer, (nbBits<<8) | (64 - bitD->bitsConsumed - nbBits) );
319#else
Yann Colletd1d210f2016-03-19 12:12:07 +0100320 U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100321 return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
Yann Collet862a8592016-03-23 18:45:23 +0100322#endif
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100323}
324
Yann Collet01e5b952016-03-19 14:14:31 +0100325/*! BIT_lookBitsFast() :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100326* unsafe version; only works only if nbBits >= 1 */
Yann Colletadd08d62016-03-23 01:32:41 +0100327MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100328{
Yann Colletd1d210f2016-03-19 12:12:07 +0100329 U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100330 return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
331}
332
333MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
334{
335 bitD->bitsConsumed += nbBits;
336}
337
Yann Collet01e5b952016-03-19 14:14:31 +0100338/*! BIT_readBits() :
Yann Colletb21ce152016-03-24 01:27:55 +0100339 * Read (consume) next n bits from local register and update.
340 * Pay attention to not read more than nbBits contained into local register.
Yann Collet01e5b952016-03-19 14:14:31 +0100341 * @return : extracted value.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100342 */
343MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
344{
Yann Colletafab0202016-03-23 13:57:49 +0100345 size_t const value = BIT_lookBits(bitD, nbBits);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100346 BIT_skipBits(bitD, nbBits);
347 return value;
348}
349
Yann Collet01e5b952016-03-19 14:14:31 +0100350/*! BIT_readBitsFast() :
351* unsafe version; only works only if nbBits >= 1 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100352MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
353{
Yann Colletafab0202016-03-23 13:57:49 +0100354 size_t const value = BIT_lookBitsFast(bitD, nbBits);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100355 BIT_skipBits(bitD, nbBits);
356 return value;
357}
358
Yann Collet01e5b952016-03-19 14:14:31 +0100359/*! BIT_reloadDStream() :
360* Refill `BIT_DStream_t` from src buffer previously defined (see BIT_initDStream() ).
361* This function is safe, it guarantees it will not read beyond src buffer.
362* @return : status of `BIT_DStream_t` internal register.
363 if status == unfinished, internal register is filled with >= (sizeof(size_t)*8 - 7) bits */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100364MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
365{
366 if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
367 return BIT_DStream_overflow;
368
Yann Colletae7aa062016-02-03 02:46:46 +0100369 if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100370 bitD->ptr -= bitD->bitsConsumed >> 3;
371 bitD->bitsConsumed &= 7;
372 bitD->bitContainer = MEM_readLEST(bitD->ptr);
373 return BIT_DStream_unfinished;
374 }
Yann Colletae7aa062016-02-03 02:46:46 +0100375 if (bitD->ptr == bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100376 if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
377 return BIT_DStream_completed;
378 }
Yann Collet01e5b952016-03-19 14:14:31 +0100379 { U32 nbBytes = bitD->bitsConsumed >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100380 BIT_DStream_status result = BIT_DStream_unfinished;
Yann Colletae7aa062016-02-03 02:46:46 +0100381 if (bitD->ptr - nbBytes < bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100382 nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
383 result = BIT_DStream_endOfBuffer;
384 }
385 bitD->ptr -= nbBytes;
386 bitD->bitsConsumed -= nbBytes*8;
387 bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
388 return result;
389 }
390}
391
Yann Colletd1d210f2016-03-19 12:12:07 +0100392/*! BIT_endOfDStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100393* @return Tells if DStream has exactly reached its end (all bits consumed).
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100394*/
395MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
396{
397 return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
398}
399
400#if defined (__cplusplus)
401}
402#endif
403
404#endif /* BITSTREAM_H_MODULE */