blob: 04440fde11097d6055c649dc3808db1181f2203f [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
Yann Collet4d5bd322018-05-09 12:00:12 -070066#if defined(BIT_DEBUG) && (BIT_DEBUG>=2)
67# include <stdio.h>
68extern int g_debuglog_enable;
69/* recommended values for BIT_DEBUG display levels :
70 * 1 : no display, enables assert() only
71 * 2 : reserved for currently active debug path
72 * 3 : events once per object lifetime (CCtx, CDict, etc.)
73 * 4 : events once per frame
74 * 5 : events once per block
75 * 6 : events once per sequence (*very* verbose) */
76# define RAWLOG(l, ...) { \
77 if ((g_debuglog_enable) & (l<=BIT_DEBUG)) { \
78 fprintf(stderr, __VA_ARGS__); \
79 } }
80# define DEBUGLOG(l, ...) { \
81 if ((g_debuglog_enable) & (l<=BIT_DEBUG)) { \
82 fprintf(stderr, __FILE__ ": " __VA_ARGS__); \
83 fprintf(stderr, " \n"); \
84 } }
85#else
86# define RAWLOG(l, ...) {} /* disabled */
87# define DEBUGLOG(l, ...) {} /* disabled */
88#endif
89
Yann Collet202082f2017-04-28 16:56:39 -070090
Yann Collet74bd1192016-03-26 17:50:26 +010091/*=========================================
92* Target specific
93=========================================*/
94#if defined(__BMI__) && defined(__GNUC__)
95# include <immintrin.h> /* support for bextr (experimental) */
96#endif
97
Sean Purcelld44703d2017-03-01 14:36:25 -080098#define STREAM_ACCUMULATOR_MIN_32 25
99#define STREAM_ACCUMULATOR_MIN_64 57
100#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
Yann Collet74bd1192016-03-26 17:50:26 +0100101
Yann Collet8c910d22017-06-03 01:15:02 -0700102
Yann Colletae7aa062016-02-03 02:46:46 +0100103/*-******************************************
104* bitStream encoding API (write forward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100105********************************************/
Yann Colletd1d210f2016-03-19 12:12:07 +0100106/* bitStream can mix input from multiple sources.
Yann Colletb71363b2017-07-19 01:05:40 -0700107 * A critical property of these streams is that they encode and decode in **reverse** direction.
108 * So the first bit sequence you add will be the last to be read, like a LIFO stack.
109 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100110typedef struct
111{
112 size_t bitContainer;
Yann Colletf39a6732017-05-01 09:56:03 -0700113 unsigned bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100114 char* startPtr;
115 char* ptr;
116 char* endPtr;
117} BIT_CStream_t;
118
Yann Colletae7aa062016-02-03 02:46:46 +0100119MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100120MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
121MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
122MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
123
Yann Collet01e5b952016-03-19 14:14:31 +0100124/* Start with initCStream, providing the size of buffer to write into.
125* bitStream will never write outside of this buffer.
Yann Collet1032fbe2016-05-11 18:30:24 +0200126* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100127*
Yann Collet01e5b952016-03-19 14:14:31 +0100128* bits are first added to a local register.
129* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
130* Writing data into memory is an explicit operation, performed by the flushBits function.
131* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
132* After a flushBits, a maximum of 7 bits might still be stored into local register.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100133*
Yann Collet01e5b952016-03-19 14:14:31 +0100134* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100135*
Yann Collet01e5b952016-03-19 14:14:31 +0100136* Last operation is to close the bitStream.
137* The function returns the final size of CStream in bytes.
138* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100139*/
140
141
Yann Colletae7aa062016-02-03 02:46:46 +0100142/*-********************************************
143* bitStream decoding API (read backward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100144**********************************************/
145typedef struct
146{
147 size_t bitContainer;
148 unsigned bitsConsumed;
149 const char* ptr;
150 const char* start;
Yann Colletf39a6732017-05-01 09:56:03 -0700151 const char* limitPtr;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100152} BIT_DStream_t;
153
154typedef enum { BIT_DStream_unfinished = 0,
155 BIT_DStream_endOfBuffer = 1,
156 BIT_DStream_completed = 2,
157 BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
158 /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
159
160MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
161MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
162MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
163MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
164
165
Yann Collet01e5b952016-03-19 14:14:31 +0100166/* Start by invoking BIT_initDStream().
167* A chunk of the bitStream is then stored into a local register.
168* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
169* You can then retrieve bitFields stored into the local register, **in reverse order**.
170* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
Yann Collet1032fbe2016-05-11 18:30:24 +0200171* 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 +0100172* Otherwise, it can be less than that, so proceed accordingly.
Yann Colletb21ce152016-03-24 01:27:55 +0100173* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100174*/
175
176
Yann Colletae7aa062016-02-03 02:46:46 +0100177/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100178* unsafe API
179******************************************/
180MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
181/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
182
183MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
184/* unsafe version; does not check buffer overflow */
185
186MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
187/* faster, but works only if nbBits >= 1 */
188
189
190
Yann Colletae7aa062016-02-03 02:46:46 +0100191/*-**************************************************************
Yann Collet6cf45da2016-03-23 14:18:37 +0100192* Internal functions
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100193****************************************************************/
Yann Colletc173dbd2017-12-04 17:57:42 -0800194MEM_STATIC unsigned BIT_highbit32 (U32 val)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100195{
Stella Laue50ed1f2017-08-22 11:55:42 -0700196 assert(val != 0);
197 {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100198# if defined(_MSC_VER) /* Visual */
Stella Laue50ed1f2017-08-22 11:55:42 -0700199 unsigned long r=0;
200 _BitScanReverse ( &r, val );
201 return (unsigned) r;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100202# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
Stella Laue50ed1f2017-08-22 11:55:42 -0700203 return 31 - __builtin_clz (val);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100204# else /* Software version */
Stella Laue50ed1f2017-08-22 11:55:42 -0700205 static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
206 11, 14, 16, 18, 22, 25, 3, 30,
207 8, 12, 20, 28, 15, 17, 24, 7,
208 19, 27, 23, 6, 26, 5, 4, 31 };
209 U32 v = val;
210 v |= v >> 1;
211 v |= v >> 2;
212 v |= v >> 4;
213 v |= v >> 8;
214 v |= v >> 16;
215 return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100216# endif
Stella Laue50ed1f2017-08-22 11:55:42 -0700217 }
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100218}
219
Yann Collet6cf45da2016-03-23 14:18:37 +0100220/*===== Local Constants =====*/
Nick Terrell74718d72017-09-15 17:44:09 -0700221static const unsigned BIT_mask[] = {
222 0, 1, 3, 7, 0xF, 0x1F,
223 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
224 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
225 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
226 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
227 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
228#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100229
Yann Colletae7aa062016-02-03 02:46:46 +0100230/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100231* bitStream encoding
232****************************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100233/*! BIT_initCStream() :
Yann Colletf39a6732017-05-01 09:56:03 -0700234 * `dstCapacity` must be > sizeof(size_t)
Yann Collet01e5b952016-03-19 14:14:31 +0100235 * @return : 0 if success,
Yann Colletb71363b2017-07-19 01:05:40 -0700236 * otherwise an error code (can be tested using ERR_isError()) */
Yann Colletf39a6732017-05-01 09:56:03 -0700237MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700238 void* startPtr, size_t dstCapacity)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100239{
240 bitC->bitContainer = 0;
241 bitC->bitPos = 0;
242 bitC->startPtr = (char*)startPtr;
243 bitC->ptr = bitC->startPtr;
Yann Colletf39a6732017-05-01 09:56:03 -0700244 bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
245 if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100246 return 0;
247}
248
Yann Collet01e5b952016-03-19 14:14:31 +0100249/*! BIT_addBits() :
Nick Terrell74718d72017-09-15 17:44:09 -0700250 * can add up to 31 bits into `bitC`.
Yann Colletb71363b2017-07-19 01:05:40 -0700251 * Note : does not check for register overflow ! */
Yann Colletf39a6732017-05-01 09:56:03 -0700252MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700253 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100254{
Nick Terrell74718d72017-09-15 17:44:09 -0700255 MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32);
256 assert(nbBits < BIT_MASK_SIZE);
257 assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Collet6cf45da2016-03-23 14:18:37 +0100258 bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100259 bitC->bitPos += nbBits;
260}
261
Yann Colletd1d210f2016-03-19 12:12:07 +0100262/*! BIT_addBitsFast() :
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100263 * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
Yann Colletf39a6732017-05-01 09:56:03 -0700264MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700265 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100266{
Yann Collet202082f2017-04-28 16:56:39 -0700267 assert((value>>nbBits) == 0);
Nick Terrell74718d72017-09-15 17:44:09 -0700268 assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100269 bitC->bitContainer |= value << bitC->bitPos;
270 bitC->bitPos += nbBits;
271}
272
Yann Colletd1d210f2016-03-19 12:12:07 +0100273/*! BIT_flushBitsFast() :
Yann Colletf39a6732017-05-01 09:56:03 -0700274 * assumption : bitContainer has not overflowed
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100275 * unsafe version; does not check buffer overflow */
276MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
277{
Yann Colletd64f4352016-03-21 00:07:42 +0100278 size_t const nbBytes = bitC->bitPos >> 3;
Nick Terrell74718d72017-09-15 17:44:09 -0700279 assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100280 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
281 bitC->ptr += nbBytes;
Yann Colletf39a6732017-05-01 09:56:03 -0700282 assert(bitC->ptr <= bitC->endPtr);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100283 bitC->bitPos &= 7;
Yann Colletf39a6732017-05-01 09:56:03 -0700284 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100285}
286
Yann Collet01e5b952016-03-19 14:14:31 +0100287/*! BIT_flushBits() :
Yann Colletf39a6732017-05-01 09:56:03 -0700288 * assumption : bitContainer has not overflowed
Yann Collet01e5b952016-03-19 14:14:31 +0100289 * safe version; check for buffer overflow, and prevents it.
Yann Collet33c38b02017-05-01 11:12:30 -0700290 * note : does not signal buffer overflow.
291 * overflow will be revealed later on using BIT_closeCStream() */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100292MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
293{
Yann Colletd64f4352016-03-21 00:07:42 +0100294 size_t const nbBytes = bitC->bitPos >> 3;
Nick Terrell74718d72017-09-15 17:44:09 -0700295 assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100296 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
297 bitC->ptr += nbBytes;
298 if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
299 bitC->bitPos &= 7;
Yann Collet33c38b02017-05-01 11:12:30 -0700300 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100301}
302
Yann Colletd1d210f2016-03-19 12:12:07 +0100303/*! BIT_closeCStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100304 * @return : size of CStream, in bytes,
Yann Colletb71363b2017-07-19 01:05:40 -0700305 * or 0 if it could not fit into dstBuffer */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100306MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
307{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100308 BIT_addBitsFast(bitC, 1, 1); /* endMark */
309 BIT_flushBits(bitC);
Yann Collet33c38b02017-05-01 11:12:30 -0700310 if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
Yann Collet01e5b952016-03-19 14:14:31 +0100311 return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100312}
313
314
Yann Colletae7aa062016-02-03 02:46:46 +0100315/*-********************************************************
Yann Colletb71363b2017-07-19 01:05:40 -0700316* bitStream decoding
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100317**********************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100318/*! BIT_initDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700319 * Initialize a BIT_DStream_t.
320 * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
321 * `srcSize` must be the *exact* size of the bitStream, in bytes.
322 * @return : size of stream (== srcSize), or an errorCode if a problem is detected
323 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100324MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
325{
326 if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
327
Yann Colletf39a6732017-05-01 09:56:03 -0700328 bitD->start = (const char*)srcBuffer;
329 bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
330
Yann Collet1032fbe2016-05-11 18:30:24 +0200331 if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
Yann Collet1032fbe2016-05-11 18:30:24 +0200332 bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100333 bitD->bitContainer = MEM_readLEST(bitD->ptr);
Yann Colletb21ce152016-03-24 01:27:55 +0100334 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
Yann Collet5397a662016-12-13 15:21:06 +0100335 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
Yann Collet18c8f792016-06-12 22:51:52 +0200336 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
Yann Colletae7aa062016-02-03 02:46:46 +0100337 } else {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100338 bitD->ptr = bitD->start;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200339 bitD->bitContainer = *(const BYTE*)(bitD->start);
340 switch(srcSize)
341 {
Yann Colletb71363b2017-07-19 01:05:40 -0700342 case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
343 /* fall-through */
Jos Collin05286fd2017-05-09 08:36:05 +0530344
Yann Colletb71363b2017-07-19 01:05:40 -0700345 case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
346 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700347
Yann Colletb71363b2017-07-19 01:05:40 -0700348 case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
349 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700350
Yann Colletb71363b2017-07-19 01:05:40 -0700351 case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
352 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700353
Yann Colletb71363b2017-07-19 01:05:40 -0700354 case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
355 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700356
Yann Colletb71363b2017-07-19 01:05:40 -0700357 case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
358 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700359
Yann Colletb71363b2017-07-19 01:05:40 -0700360 default: break;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200361 }
Yann Colletb71363b2017-07-19 01:05:40 -0700362 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
363 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
364 if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
365 }
Yann Collet1032fbe2016-05-11 18:30:24 +0200366 bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100367 }
368
369 return srcSize;
370}
371
Yann Collet1032fbe2016-05-11 18:30:24 +0200372MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
Yann Collet3c017862016-03-23 14:09:51 +0100373{
Yann Collet1032fbe2016-05-11 18:30:24 +0200374 return bitContainer >> start;
Yann Collet3c017862016-03-23 14:09:51 +0100375}
376
Yann Collet1032fbe2016-05-11 18:30:24 +0200377MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
Yann Collet3c017862016-03-23 14:09:51 +0100378{
Yann Collet5397a662016-12-13 15:21:06 +0100379#if defined(__BMI__) && defined(__GNUC__) && __GNUC__*1000+__GNUC_MINOR__ >= 4008 /* experimental */
Yann Collet6f9c0562016-05-01 10:26:30 +0200380# if defined(__x86_64__)
Yann Collet1032fbe2016-05-11 18:30:24 +0200381 if (sizeof(bitContainer)==8)
382 return _bextr_u64(bitContainer, start, nbBits);
Yann Collet6f9c0562016-05-01 10:26:30 +0200383 else
384# endif
Yann Collet1032fbe2016-05-11 18:30:24 +0200385 return _bextr_u32(bitContainer, start, nbBits);
Yann Collet862a8592016-03-23 18:45:23 +0100386#else
Nick Terrell74718d72017-09-15 17:44:09 -0700387 assert(nbBits < BIT_MASK_SIZE);
Yann Collet1032fbe2016-05-11 18:30:24 +0200388 return (bitContainer >> start) & BIT_mask[nbBits];
Yann Collet862a8592016-03-23 18:45:23 +0100389#endif
Yann Collet3c017862016-03-23 14:09:51 +0100390}
391
Yann Collet1032fbe2016-05-11 18:30:24 +0200392MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
Yann Colletafab0202016-03-23 13:57:49 +0100393{
Nick Terrell74718d72017-09-15 17:44:09 -0700394 assert(nbBits < BIT_MASK_SIZE);
Yann Collet1032fbe2016-05-11 18:30:24 +0200395 return bitContainer & BIT_mask[nbBits];
Yann Colletafab0202016-03-23 13:57:49 +0100396}
397
Yann Collet01e5b952016-03-19 14:14:31 +0100398/*! BIT_lookBits() :
399 * Provides next n bits from local register.
Yann Collet1032fbe2016-05-11 18:30:24 +0200400 * local register is not modified.
Yann Collet01e5b952016-03-19 14:14:31 +0100401 * On 32-bits, maxNbBits==24.
402 * On 64-bits, maxNbBits==56.
Yann Colletb71363b2017-07-19 01:05:40 -0700403 * @return : value extracted */
404MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100405{
Yann Collet1032fbe2016-05-11 18:30:24 +0200406#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
407 return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
Yann Collet862a8592016-03-23 18:45:23 +0100408#else
Yann Colletf39a6732017-05-01 09:56:03 -0700409 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
410 return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
Yann Collet862a8592016-03-23 18:45:23 +0100411#endif
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100412}
413
Yann Collet01e5b952016-03-19 14:14:31 +0100414/*! BIT_lookBitsFast() :
Yann Collet202082f2017-04-28 16:56:39 -0700415 * unsafe version; only works if nbBits >= 1 */
Yann Colletadd08d62016-03-23 01:32:41 +0100416MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100417{
Yann Colletf39a6732017-05-01 09:56:03 -0700418 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
Yann Collet202082f2017-04-28 16:56:39 -0700419 assert(nbBits >= 1);
Yann Colletf39a6732017-05-01 09:56:03 -0700420 return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100421}
422
423MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
424{
425 bitD->bitsConsumed += nbBits;
426}
427
Yann Collet01e5b952016-03-19 14:14:31 +0100428/*! BIT_readBits() :
Yann Colletb21ce152016-03-24 01:27:55 +0100429 * Read (consume) next n bits from local register and update.
430 * Pay attention to not read more than nbBits contained into local register.
Yann Colletb71363b2017-07-19 01:05:40 -0700431 * @return : extracted value. */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100432MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
433{
Yann Colletafab0202016-03-23 13:57:49 +0100434 size_t const value = BIT_lookBits(bitD, nbBits);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100435 BIT_skipBits(bitD, nbBits);
436 return value;
437}
438
Yann Collet01e5b952016-03-19 14:14:31 +0100439/*! BIT_readBitsFast() :
Yann Colletb71363b2017-07-19 01:05:40 -0700440 * unsafe version; only works only if nbBits >= 1 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100441MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
442{
Yann Colletafab0202016-03-23 13:57:49 +0100443 size_t const value = BIT_lookBitsFast(bitD, nbBits);
Yann Collet202082f2017-04-28 16:56:39 -0700444 assert(nbBits >= 1);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100445 BIT_skipBits(bitD, nbBits);
446 return value;
447}
448
Yann Collet01e5b952016-03-19 14:14:31 +0100449/*! BIT_reloadDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700450 * Refill `bitD` from buffer previously set in BIT_initDStream() .
451 * This function is safe, it guarantees it will not read beyond src buffer.
452 * @return : status of `BIT_DStream_t` internal register.
Baldur Karlsson430a2fe2018-03-13 20:02:21 +0000453 * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100454MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
455{
Yann Colletf39a6732017-05-01 09:56:03 -0700456 if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
Nick Terrell5152fb22017-03-29 18:51:58 -0700457 return BIT_DStream_overflow;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100458
Yann Colletf39a6732017-05-01 09:56:03 -0700459 if (bitD->ptr >= bitD->limitPtr) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100460 bitD->ptr -= bitD->bitsConsumed >> 3;
461 bitD->bitsConsumed &= 7;
462 bitD->bitContainer = MEM_readLEST(bitD->ptr);
463 return BIT_DStream_unfinished;
464 }
Yann Colletae7aa062016-02-03 02:46:46 +0100465 if (bitD->ptr == bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100466 if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
467 return BIT_DStream_completed;
468 }
Yann Colletf39a6732017-05-01 09:56:03 -0700469 /* start < ptr < limitPtr */
Yann Collet01e5b952016-03-19 14:14:31 +0100470 { U32 nbBytes = bitD->bitsConsumed >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100471 BIT_DStream_status result = BIT_DStream_unfinished;
Yann Colletae7aa062016-02-03 02:46:46 +0100472 if (bitD->ptr - nbBytes < bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100473 nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
474 result = BIT_DStream_endOfBuffer;
475 }
476 bitD->ptr -= nbBytes;
477 bitD->bitsConsumed -= nbBytes*8;
Yann Colletf39a6732017-05-01 09:56:03 -0700478 bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100479 return result;
480 }
481}
482
Yann Colletd1d210f2016-03-19 12:12:07 +0100483/*! BIT_endOfDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700484 * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
485 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100486MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
487{
488 return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
489}
490
491#if defined (__cplusplus)
492}
493#endif
494
495#endif /* BITSTREAM_H_MODULE */