blob: f3c9064bb239c52db1481f2097b840690a2f3785 [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 Collet202082f2017-04-28 16:56:39 -07005 Copyright (C) 2013-2017, 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
Yann Colletb1f3f4b2015-10-18 22:18:32 +010042/*
Yann Collet01e5b952016-03-19 14:14:31 +010043* This API consists of small unitary functions, which must be inlined for best performance.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010044* Since link-time-optimization is not available for all compilers,
45* these functions are defined into a .h to be included.
46*/
47
Yann Colletae7aa062016-02-03 02:46:46 +010048/*-****************************************
49* Dependencies
Yann Colletb1f3f4b2015-10-18 22:18:32 +010050******************************************/
Yann Collet977f1f32016-01-21 15:38:47 +010051#include "mem.h" /* unaligned access routines */
52#include "error_private.h" /* error codes and messages */
Yann Colletb1f3f4b2015-10-18 22:18:32 +010053
54
Yann Collet202082f2017-04-28 16:56:39 -070055/*-*************************************
56* Debug
57***************************************/
58#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
59# include <assert.h>
60#else
Yann Collet58e8d792017-06-02 18:20:48 -070061# ifndef assert
62# define assert(condition) ((void)0)
63# endif
Yann Collet202082f2017-04-28 16:56:39 -070064#endif
65
66
Yann Collet74bd1192016-03-26 17:50:26 +010067/*=========================================
68* Target specific
69=========================================*/
70#if defined(__BMI__) && defined(__GNUC__)
71# include <immintrin.h> /* support for bextr (experimental) */
72#endif
73
Sean Purcelld44703d2017-03-01 14:36:25 -080074#define STREAM_ACCUMULATOR_MIN_32 25
75#define STREAM_ACCUMULATOR_MIN_64 57
76#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
Yann Collet74bd1192016-03-26 17:50:26 +010077
Yann Colletae7aa062016-02-03 02:46:46 +010078/*-******************************************
79* bitStream encoding API (write forward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010080********************************************/
Yann Colletd1d210f2016-03-19 12:12:07 +010081/* bitStream can mix input from multiple sources.
82* A critical property of these streams is that they encode and decode in **reverse** direction.
83* 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 +010084*/
85typedef struct
86{
87 size_t bitContainer;
Yann Colletf39a6732017-05-01 09:56:03 -070088 unsigned bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +010089 char* startPtr;
90 char* ptr;
91 char* endPtr;
92} BIT_CStream_t;
93
Yann Colletae7aa062016-02-03 02:46:46 +010094MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
Yann Colletb1f3f4b2015-10-18 22:18:32 +010095MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
96MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
97MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
98
Yann Collet01e5b952016-03-19 14:14:31 +010099/* Start with initCStream, providing the size of buffer to write into.
100* bitStream will never write outside of this buffer.
Yann Collet1032fbe2016-05-11 18:30:24 +0200101* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100102*
Yann Collet01e5b952016-03-19 14:14:31 +0100103* bits are first added to a local register.
104* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
105* Writing data into memory is an explicit operation, performed by the flushBits function.
106* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
107* After a flushBits, a maximum of 7 bits might still be stored into local register.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100108*
Yann Collet01e5b952016-03-19 14:14:31 +0100109* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100110*
Yann Collet01e5b952016-03-19 14:14:31 +0100111* Last operation is to close the bitStream.
112* The function returns the final size of CStream in bytes.
113* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100114*/
115
116
Yann Colletae7aa062016-02-03 02:46:46 +0100117/*-********************************************
118* bitStream decoding API (read backward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100119**********************************************/
120typedef struct
121{
122 size_t bitContainer;
123 unsigned bitsConsumed;
124 const char* ptr;
125 const char* start;
Yann Colletf39a6732017-05-01 09:56:03 -0700126 const char* limitPtr;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100127} BIT_DStream_t;
128
129typedef enum { BIT_DStream_unfinished = 0,
130 BIT_DStream_endOfBuffer = 1,
131 BIT_DStream_completed = 2,
132 BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
133 /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
134
135MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
136MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
137MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
138MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
139
140
Yann Collet01e5b952016-03-19 14:14:31 +0100141/* Start by invoking BIT_initDStream().
142* A chunk of the bitStream is then stored into a local register.
143* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
144* You can then retrieve bitFields stored into the local register, **in reverse order**.
145* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
Yann Collet1032fbe2016-05-11 18:30:24 +0200146* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
Yann Collet01e5b952016-03-19 14:14:31 +0100147* Otherwise, it can be less than that, so proceed accordingly.
Yann Colletb21ce152016-03-24 01:27:55 +0100148* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100149*/
150
151
Yann Colletae7aa062016-02-03 02:46:46 +0100152/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100153* unsafe API
154******************************************/
155MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
156/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
157
158MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
159/* unsafe version; does not check buffer overflow */
160
161MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
162/* faster, but works only if nbBits >= 1 */
163
164
165
Yann Colletae7aa062016-02-03 02:46:46 +0100166/*-**************************************************************
Yann Collet6cf45da2016-03-23 14:18:37 +0100167* Internal functions
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100168****************************************************************/
169MEM_STATIC unsigned BIT_highbit32 (register U32 val)
170{
171# if defined(_MSC_VER) /* Visual */
Yann Collet4114f952015-10-30 06:40:22 +0100172 unsigned long r=0;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100173 _BitScanReverse ( &r, val );
174 return (unsigned) r;
175# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
176 return 31 - __builtin_clz (val);
177# else /* Software version */
Yann Colletf39a6732017-05-01 09:56:03 -0700178 static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
179 11, 14, 16, 18, 22, 25, 3, 30,
180 8, 12, 20, 28, 15, 17, 24, 7,
181 19, 27, 23, 6, 26, 5, 4, 31 };
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100182 U32 v = val;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100183 v |= v >> 1;
184 v |= v >> 2;
185 v |= v >> 4;
186 v |= v >> 8;
187 v |= v >> 16;
Yann Colletf22a0d62016-05-20 14:36:36 +0200188 return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100189# endif
190}
191
Yann Collet6cf45da2016-03-23 14:18:37 +0100192/*===== Local Constants =====*/
Yann Colletf39a6732017-05-01 09:56:03 -0700193static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F,
194 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF,
195 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
196 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF }; /* up to 26 bits */
Yann Collet6cf45da2016-03-23 14:18:37 +0100197
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100198
Yann Colletae7aa062016-02-03 02:46:46 +0100199/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100200* bitStream encoding
201****************************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100202/*! BIT_initCStream() :
Yann Colletf39a6732017-05-01 09:56:03 -0700203 * `dstCapacity` must be > sizeof(size_t)
Yann Collet01e5b952016-03-19 14:14:31 +0100204 * @return : 0 if success,
205 otherwise an error code (can be tested using ERR_isError() ) */
Yann Colletf39a6732017-05-01 09:56:03 -0700206MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700207 void* startPtr, size_t dstCapacity)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100208{
209 bitC->bitContainer = 0;
210 bitC->bitPos = 0;
211 bitC->startPtr = (char*)startPtr;
212 bitC->ptr = bitC->startPtr;
Yann Colletf39a6732017-05-01 09:56:03 -0700213 bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
214 if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100215 return 0;
216}
217
Yann Collet01e5b952016-03-19 14:14:31 +0100218/*! BIT_addBits() :
219 can add up to 26 bits into `bitC`.
220 Does not check for register overflow ! */
Yann Colletf39a6732017-05-01 09:56:03 -0700221MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700222 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100223{
Yann Collet6cf45da2016-03-23 14:18:37 +0100224 bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100225 bitC->bitPos += nbBits;
226}
227
Yann Colletd1d210f2016-03-19 12:12:07 +0100228/*! BIT_addBitsFast() :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100229 * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
Yann Colletf39a6732017-05-01 09:56:03 -0700230MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700231 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100232{
Yann Collet202082f2017-04-28 16:56:39 -0700233 assert((value>>nbBits) == 0);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100234 bitC->bitContainer |= value << bitC->bitPos;
235 bitC->bitPos += nbBits;
236}
237
Yann Colletd1d210f2016-03-19 12:12:07 +0100238/*! BIT_flushBitsFast() :
Yann Colletf39a6732017-05-01 09:56:03 -0700239 * assumption : bitContainer has not overflowed
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100240 * unsafe version; does not check buffer overflow */
241MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
242{
Yann Colletd64f4352016-03-21 00:07:42 +0100243 size_t const nbBytes = bitC->bitPos >> 3;
Yann Colletf39a6732017-05-01 09:56:03 -0700244 assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100245 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
246 bitC->ptr += nbBytes;
Yann Colletf39a6732017-05-01 09:56:03 -0700247 assert(bitC->ptr <= bitC->endPtr);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100248 bitC->bitPos &= 7;
Yann Colletf39a6732017-05-01 09:56:03 -0700249 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100250}
251
Yann Collet01e5b952016-03-19 14:14:31 +0100252/*! BIT_flushBits() :
Yann Colletf39a6732017-05-01 09:56:03 -0700253 * assumption : bitContainer has not overflowed
Yann Collet01e5b952016-03-19 14:14:31 +0100254 * safe version; check for buffer overflow, and prevents it.
Yann Collet33c38b02017-05-01 11:12:30 -0700255 * note : does not signal buffer overflow.
256 * overflow will be revealed later on using BIT_closeCStream() */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100257MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
258{
Yann Colletd64f4352016-03-21 00:07:42 +0100259 size_t const nbBytes = bitC->bitPos >> 3;
Yann Colletf39a6732017-05-01 09:56:03 -0700260 assert( bitC->bitPos <= (sizeof(bitC->bitContainer)*8) );
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100261 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
262 bitC->ptr += nbBytes;
263 if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
264 bitC->bitPos &= 7;
Yann Collet33c38b02017-05-01 11:12:30 -0700265 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100266}
267
Yann Colletd1d210f2016-03-19 12:12:07 +0100268/*! BIT_closeCStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100269 * @return : size of CStream, in bytes,
270 or 0 if it could not fit into dstBuffer */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100271MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
272{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100273 BIT_addBitsFast(bitC, 1, 1); /* endMark */
274 BIT_flushBits(bitC);
Yann Collet33c38b02017-05-01 11:12:30 -0700275 if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
Yann Collet01e5b952016-03-19 14:14:31 +0100276 return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100277}
278
279
Yann Colletae7aa062016-02-03 02:46:46 +0100280/*-********************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100281* bitStream decoding
282**********************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100283/*! BIT_initDStream() :
284* Initialize a BIT_DStream_t.
285* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
Yann Colletadd08d62016-03-23 01:32:41 +0100286* `srcSize` must be the *exact* size of the bitStream, in bytes.
Yann Collet01e5b952016-03-19 14:14:31 +0100287* @return : size of stream (== srcSize) or an errorCode if a problem is detected
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100288*/
289MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
290{
291 if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
292
Yann Colletf39a6732017-05-01 09:56:03 -0700293 bitD->start = (const char*)srcBuffer;
294 bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
295
Yann Collet1032fbe2016-05-11 18:30:24 +0200296 if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
Yann Collet1032fbe2016-05-11 18:30:24 +0200297 bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100298 bitD->bitContainer = MEM_readLEST(bitD->ptr);
Yann Colletb21ce152016-03-24 01:27:55 +0100299 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
Yann Collet5397a662016-12-13 15:21:06 +0100300 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
Yann Collet18c8f792016-06-12 22:51:52 +0200301 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
Yann Colletae7aa062016-02-03 02:46:46 +0100302 } else {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100303 bitD->ptr = bitD->start;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200304 bitD->bitContainer = *(const BYTE*)(bitD->start);
305 switch(srcSize)
306 {
Jos Collin05286fd2017-05-09 08:36:05 +0530307 case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
308 /* fall-through */
309
310 case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
311 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700312
Jos Collin05286fd2017-05-09 08:36:05 +0530313 case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
314 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700315
Jos Collin05286fd2017-05-09 08:36:05 +0530316 case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
317 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700318
Jos Collin05286fd2017-05-09 08:36:05 +0530319 case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
320 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700321
Jos Collin05286fd2017-05-09 08:36:05 +0530322 case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
323 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700324
Jos Collin05286fd2017-05-09 08:36:05 +0530325 default: break;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200326 }
Yann Colletb21ce152016-03-24 01:27:55 +0100327 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
Yann Collet18c8f792016-06-12 22:51:52 +0200328 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
329 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
Yann Collet1032fbe2016-05-11 18:30:24 +0200330 bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100331 }
332
333 return srcSize;
334}
335
Yann Collet1032fbe2016-05-11 18:30:24 +0200336MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
Yann Collet3c017862016-03-23 14:09:51 +0100337{
Yann Collet1032fbe2016-05-11 18:30:24 +0200338 return bitContainer >> start;
Yann Collet3c017862016-03-23 14:09:51 +0100339}
340
Yann Collet1032fbe2016-05-11 18:30:24 +0200341MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
Yann Collet3c017862016-03-23 14:09:51 +0100342{
Yann Collet5397a662016-12-13 15:21:06 +0100343#if defined(__BMI__) && defined(__GNUC__) && __GNUC__*1000+__GNUC_MINOR__ >= 4008 /* experimental */
Yann Collet6f9c0562016-05-01 10:26:30 +0200344# if defined(__x86_64__)
Yann Collet1032fbe2016-05-11 18:30:24 +0200345 if (sizeof(bitContainer)==8)
346 return _bextr_u64(bitContainer, start, nbBits);
Yann Collet6f9c0562016-05-01 10:26:30 +0200347 else
348# endif
Yann Collet1032fbe2016-05-11 18:30:24 +0200349 return _bextr_u32(bitContainer, start, nbBits);
Yann Collet862a8592016-03-23 18:45:23 +0100350#else
Yann Collet1032fbe2016-05-11 18:30:24 +0200351 return (bitContainer >> start) & BIT_mask[nbBits];
Yann Collet862a8592016-03-23 18:45:23 +0100352#endif
Yann Collet3c017862016-03-23 14:09:51 +0100353}
354
Yann Collet1032fbe2016-05-11 18:30:24 +0200355MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
Yann Colletafab0202016-03-23 13:57:49 +0100356{
Yann Collet1032fbe2016-05-11 18:30:24 +0200357 return bitContainer & BIT_mask[nbBits];
Yann Colletafab0202016-03-23 13:57:49 +0100358}
359
Yann Collet01e5b952016-03-19 14:14:31 +0100360/*! BIT_lookBits() :
361 * Provides next n bits from local register.
Yann Collet1032fbe2016-05-11 18:30:24 +0200362 * local register is not modified.
Yann Collet01e5b952016-03-19 14:14:31 +0100363 * On 32-bits, maxNbBits==24.
364 * On 64-bits, maxNbBits==56.
365 * @return : value extracted
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100366 */
Yann Collet862a8592016-03-23 18:45:23 +0100367 MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100368{
Yann Collet1032fbe2016-05-11 18:30:24 +0200369#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
370 return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
Yann Collet862a8592016-03-23 18:45:23 +0100371#else
Yann Colletf39a6732017-05-01 09:56:03 -0700372 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
373 return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
Yann Collet862a8592016-03-23 18:45:23 +0100374#endif
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100375}
376
Yann Collet01e5b952016-03-19 14:14:31 +0100377/*! BIT_lookBitsFast() :
Yann Collet202082f2017-04-28 16:56:39 -0700378 * unsafe version; only works if nbBits >= 1 */
Yann Colletadd08d62016-03-23 01:32:41 +0100379MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100380{
Yann Colletf39a6732017-05-01 09:56:03 -0700381 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
Yann Collet202082f2017-04-28 16:56:39 -0700382 assert(nbBits >= 1);
Yann Colletf39a6732017-05-01 09:56:03 -0700383 return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100384}
385
386MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
387{
388 bitD->bitsConsumed += nbBits;
389}
390
Yann Collet01e5b952016-03-19 14:14:31 +0100391/*! BIT_readBits() :
Yann Colletb21ce152016-03-24 01:27:55 +0100392 * Read (consume) next n bits from local register and update.
393 * Pay attention to not read more than nbBits contained into local register.
Yann Collet01e5b952016-03-19 14:14:31 +0100394 * @return : extracted value.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100395 */
396MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
397{
Yann Colletafab0202016-03-23 13:57:49 +0100398 size_t const value = BIT_lookBits(bitD, nbBits);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100399 BIT_skipBits(bitD, nbBits);
400 return value;
401}
402
Yann Collet01e5b952016-03-19 14:14:31 +0100403/*! BIT_readBitsFast() :
404* unsafe version; only works only if nbBits >= 1 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100405MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
406{
Yann Colletafab0202016-03-23 13:57:49 +0100407 size_t const value = BIT_lookBitsFast(bitD, nbBits);
Yann Collet202082f2017-04-28 16:56:39 -0700408 assert(nbBits >= 1);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100409 BIT_skipBits(bitD, nbBits);
410 return value;
411}
412
Yann Collet01e5b952016-03-19 14:14:31 +0100413/*! BIT_reloadDStream() :
Yann Collet5397a662016-12-13 15:21:06 +0100414* Refill `bitD` from buffer previously set in BIT_initDStream() .
Yann Collet01e5b952016-03-19 14:14:31 +0100415* This function is safe, it guarantees it will not read beyond src buffer.
416* @return : status of `BIT_DStream_t` internal register.
Yann Collet5397a662016-12-13 15:21:06 +0100417 if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100418MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
419{
Yann Colletf39a6732017-05-01 09:56:03 -0700420 if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
Nick Terrell5152fb22017-03-29 18:51:58 -0700421 return BIT_DStream_overflow;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100422
Yann Colletf39a6732017-05-01 09:56:03 -0700423 if (bitD->ptr >= bitD->limitPtr) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100424 bitD->ptr -= bitD->bitsConsumed >> 3;
425 bitD->bitsConsumed &= 7;
426 bitD->bitContainer = MEM_readLEST(bitD->ptr);
427 return BIT_DStream_unfinished;
428 }
Yann Colletae7aa062016-02-03 02:46:46 +0100429 if (bitD->ptr == bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100430 if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
431 return BIT_DStream_completed;
432 }
Yann Colletf39a6732017-05-01 09:56:03 -0700433 /* start < ptr < limitPtr */
Yann Collet01e5b952016-03-19 14:14:31 +0100434 { U32 nbBytes = bitD->bitsConsumed >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100435 BIT_DStream_status result = BIT_DStream_unfinished;
Yann Colletae7aa062016-02-03 02:46:46 +0100436 if (bitD->ptr - nbBytes < bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100437 nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
438 result = BIT_DStream_endOfBuffer;
439 }
440 bitD->ptr -= nbBytes;
441 bitD->bitsConsumed -= nbBytes*8;
Yann Colletf39a6732017-05-01 09:56:03 -0700442 bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100443 return result;
444 }
445}
446
Yann Colletd1d210f2016-03-19 12:12:07 +0100447/*! BIT_endOfDStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100448* @return Tells if DStream has exactly reached its end (all bits consumed).
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100449*/
450MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
451{
452 return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
453}
454
455#if defined (__cplusplus)
456}
457#endif
458
459#endif /* BITSTREAM_H_MODULE */