blob: fe3148eebd0ee5150aa15e9ebdcbf3585712c5fb [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 Colletfa41bcc2018-06-13 14:59:26 -04004 Copyright (C) 2013-present, Yann Collet.
Yann Colletb1f3f4b2015-10-18 22:18:32 +01005
6 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11
12 * Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above
15 copyright notice, this list of conditions and the following disclaimer
16 in the documentation and/or other materials provided with the
17 distribution.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 You can contact the author at :
32 - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
Yann Colletb1f3f4b2015-10-18 22:18:32 +010033****************************************************************** */
34#ifndef BITSTREAM_H_MODULE
35#define BITSTREAM_H_MODULE
36
37#if defined (__cplusplus)
38extern "C" {
39#endif
40
Yann Colletb1f3f4b2015-10-18 22:18:32 +010041/*
Yann Collet01e5b952016-03-19 14:14:31 +010042* This API consists of small unitary functions, which must be inlined for best performance.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010043* Since link-time-optimization is not available for all compilers,
44* these functions are defined into a .h to be included.
45*/
46
Yann Colletae7aa062016-02-03 02:46:46 +010047/*-****************************************
48* Dependencies
Yann Colletb1f3f4b2015-10-18 22:18:32 +010049******************************************/
Yann Collet977f1f32016-01-21 15:38:47 +010050#include "mem.h" /* unaligned access routines */
Nick Terrell718f00f2019-11-25 18:26:19 -080051#include "compiler.h" /* UNLIKELY() */
Yann Colletfa41bcc2018-06-13 14:59:26 -040052#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */
Yann Collet977f1f32016-01-21 15:38:47 +010053#include "error_private.h" /* error codes and messages */
Yann Colletb1f3f4b2015-10-18 22:18:32 +010054
55
Yann Collet74bd1192016-03-26 17:50:26 +010056/*=========================================
57* Target specific
58=========================================*/
59#if defined(__BMI__) && defined(__GNUC__)
60# include <immintrin.h> /* support for bextr (experimental) */
Joseph Chen3855bc42019-07-29 15:20:37 +080061#elif defined(__ICCARM__)
62# include <intrinsics.h>
Yann Collet74bd1192016-03-26 17:50:26 +010063#endif
64
Sean Purcelld44703d2017-03-01 14:36:25 -080065#define STREAM_ACCUMULATOR_MIN_32 25
66#define STREAM_ACCUMULATOR_MIN_64 57
67#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
Yann Collet74bd1192016-03-26 17:50:26 +010068
Yann Collet8c910d22017-06-03 01:15:02 -070069
Yann Colletae7aa062016-02-03 02:46:46 +010070/*-******************************************
71* bitStream encoding API (write forward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010072********************************************/
Yann Colletd1d210f2016-03-19 12:12:07 +010073/* bitStream can mix input from multiple sources.
Yann Colletb71363b2017-07-19 01:05:40 -070074 * A critical property of these streams is that they encode and decode in **reverse** direction.
75 * So the first bit sequence you add will be the last to be read, like a LIFO stack.
76 */
Yann Colletfa41bcc2018-06-13 14:59:26 -040077typedef struct {
Yann Colletb1f3f4b2015-10-18 22:18:32 +010078 size_t bitContainer;
Yann Colletf39a6732017-05-01 09:56:03 -070079 unsigned bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +010080 char* startPtr;
81 char* ptr;
82 char* endPtr;
83} BIT_CStream_t;
84
Yann Colletae7aa062016-02-03 02:46:46 +010085MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
Yann Colletb1f3f4b2015-10-18 22:18:32 +010086MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
87MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
88MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
89
Yann Collet01e5b952016-03-19 14:14:31 +010090/* Start with initCStream, providing the size of buffer to write into.
91* bitStream will never write outside of this buffer.
Yann Collet1032fbe2016-05-11 18:30:24 +020092* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010093*
Yann Collet01e5b952016-03-19 14:14:31 +010094* bits are first added to a local register.
95* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
96* Writing data into memory is an explicit operation, performed by the flushBits function.
97* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
98* After a flushBits, a maximum of 7 bits might still be stored into local register.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010099*
Yann Collet01e5b952016-03-19 14:14:31 +0100100* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100101*
Yann Collet01e5b952016-03-19 14:14:31 +0100102* Last operation is to close the bitStream.
103* The function returns the final size of CStream in bytes.
104* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100105*/
106
107
Yann Colletae7aa062016-02-03 02:46:46 +0100108/*-********************************************
109* bitStream decoding API (read backward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100110**********************************************/
Yann Colletfa41bcc2018-06-13 14:59:26 -0400111typedef struct {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100112 size_t bitContainer;
113 unsigned bitsConsumed;
114 const char* ptr;
115 const char* start;
Yann Colletf39a6732017-05-01 09:56:03 -0700116 const char* limitPtr;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100117} BIT_DStream_t;
118
119typedef enum { BIT_DStream_unfinished = 0,
120 BIT_DStream_endOfBuffer = 1,
121 BIT_DStream_completed = 2,
122 BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
123 /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
124
125MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
126MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
127MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
128MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
129
130
Yann Collet01e5b952016-03-19 14:14:31 +0100131/* Start by invoking BIT_initDStream().
132* A chunk of the bitStream is then stored into a local register.
133* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
134* You can then retrieve bitFields stored into the local register, **in reverse order**.
135* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
Yann Collet1032fbe2016-05-11 18:30:24 +0200136* 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 +0100137* Otherwise, it can be less than that, so proceed accordingly.
Yann Colletb21ce152016-03-24 01:27:55 +0100138* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100139*/
140
141
Yann Colletae7aa062016-02-03 02:46:46 +0100142/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100143* unsafe API
144******************************************/
145MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
146/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
147
148MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
149/* unsafe version; does not check buffer overflow */
150
151MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
152/* faster, but works only if nbBits >= 1 */
153
154
155
Yann Colletae7aa062016-02-03 02:46:46 +0100156/*-**************************************************************
Yann Collet6cf45da2016-03-23 14:18:37 +0100157* Internal functions
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100158****************************************************************/
Yann Colletc173dbd2017-12-04 17:57:42 -0800159MEM_STATIC unsigned BIT_highbit32 (U32 val)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100160{
Stella Laue50ed1f2017-08-22 11:55:42 -0700161 assert(val != 0);
162 {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100163# if defined(_MSC_VER) /* Visual */
Stella Laue50ed1f2017-08-22 11:55:42 -0700164 unsigned long r=0;
165 _BitScanReverse ( &r, val );
166 return (unsigned) r;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100167# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
Dávid Bolvanský1f7228c2019-09-23 21:23:09 +0200168 return __builtin_clz (val) ^ 31;
Joseph Chen3855bc42019-07-29 15:20:37 +0800169# elif defined(__ICCARM__) /* IAR Intrinsic */
170 return 31 - __CLZ(val);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100171# else /* Software version */
Stella Laue50ed1f2017-08-22 11:55:42 -0700172 static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
173 11, 14, 16, 18, 22, 25, 3, 30,
174 8, 12, 20, 28, 15, 17, 24, 7,
175 19, 27, 23, 6, 26, 5, 4, 31 };
176 U32 v = val;
177 v |= v >> 1;
178 v |= v >> 2;
179 v |= v >> 4;
180 v |= v >> 8;
181 v |= v >> 16;
182 return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100183# endif
Stella Laue50ed1f2017-08-22 11:55:42 -0700184 }
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100185}
186
Yann Collet6cf45da2016-03-23 14:18:37 +0100187/*===== Local Constants =====*/
Nick Terrell74718d72017-09-15 17:44:09 -0700188static const unsigned BIT_mask[] = {
189 0, 1, 3, 7, 0xF, 0x1F,
190 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
191 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
192 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
193 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
194 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
195#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100196
Yann Colletae7aa062016-02-03 02:46:46 +0100197/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100198* bitStream encoding
199****************************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100200/*! BIT_initCStream() :
Yann Colletf39a6732017-05-01 09:56:03 -0700201 * `dstCapacity` must be > sizeof(size_t)
Yann Collet01e5b952016-03-19 14:14:31 +0100202 * @return : 0 if success,
Yann Colletb71363b2017-07-19 01:05:40 -0700203 * otherwise an error code (can be tested using ERR_isError()) */
Yann Colletf39a6732017-05-01 09:56:03 -0700204MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700205 void* startPtr, size_t dstCapacity)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100206{
207 bitC->bitContainer = 0;
208 bitC->bitPos = 0;
209 bitC->startPtr = (char*)startPtr;
210 bitC->ptr = bitC->startPtr;
Yann Colletf39a6732017-05-01 09:56:03 -0700211 bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
212 if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100213 return 0;
214}
215
Yann Collet01e5b952016-03-19 14:14:31 +0100216/*! BIT_addBits() :
Nick Terrell74718d72017-09-15 17:44:09 -0700217 * can add up to 31 bits into `bitC`.
Yann Colletb71363b2017-07-19 01:05:40 -0700218 * Note : does not check for register overflow ! */
Yann Colletf39a6732017-05-01 09:56:03 -0700219MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700220 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100221{
Nick Terrell74718d72017-09-15 17:44:09 -0700222 MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32);
223 assert(nbBits < BIT_MASK_SIZE);
224 assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Collet6cf45da2016-03-23 14:18:37 +0100225 bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100226 bitC->bitPos += nbBits;
227}
228
Yann Colletd1d210f2016-03-19 12:12:07 +0100229/*! BIT_addBitsFast() :
Yann Colletfa41bcc2018-06-13 14:59:26 -0400230 * works only if `value` is _clean_,
231 * meaning all high bits above nbBits are 0 */
Yann Colletf39a6732017-05-01 09:56:03 -0700232MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
Yann Collet33c38b02017-05-01 11:12:30 -0700233 size_t value, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100234{
Yann Collet202082f2017-04-28 16:56:39 -0700235 assert((value>>nbBits) == 0);
Nick Terrell74718d72017-09-15 17:44:09 -0700236 assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100237 bitC->bitContainer |= value << bitC->bitPos;
238 bitC->bitPos += nbBits;
239}
240
Yann Colletd1d210f2016-03-19 12:12:07 +0100241/*! BIT_flushBitsFast() :
Yann Colletf39a6732017-05-01 09:56:03 -0700242 * assumption : bitContainer has not overflowed
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100243 * unsafe version; does not check buffer overflow */
244MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
245{
Yann Colletd64f4352016-03-21 00:07:42 +0100246 size_t const nbBytes = bitC->bitPos >> 3;
Nick Terrell74718d72017-09-15 17:44:09 -0700247 assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Bimba Shrestha43da5bf2019-09-12 14:43:50 -0700248 assert(bitC->ptr <= bitC->endPtr);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100249 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
250 bitC->ptr += nbBytes;
251 bitC->bitPos &= 7;
Yann Colletf39a6732017-05-01 09:56:03 -0700252 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100253}
254
Yann Collet01e5b952016-03-19 14:14:31 +0100255/*! BIT_flushBits() :
Yann Colletf39a6732017-05-01 09:56:03 -0700256 * assumption : bitContainer has not overflowed
Yann Collet01e5b952016-03-19 14:14:31 +0100257 * safe version; check for buffer overflow, and prevents it.
Yann Collet33c38b02017-05-01 11:12:30 -0700258 * note : does not signal buffer overflow.
259 * overflow will be revealed later on using BIT_closeCStream() */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100260MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
261{
Yann Colletd64f4352016-03-21 00:07:42 +0100262 size_t const nbBytes = bitC->bitPos >> 3;
Nick Terrell74718d72017-09-15 17:44:09 -0700263 assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
Bimba Shresthafe9af332019-09-12 15:35:27 -0700264 assert(bitC->ptr <= bitC->endPtr);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100265 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
266 bitC->ptr += nbBytes;
267 if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
268 bitC->bitPos &= 7;
Yann Collet33c38b02017-05-01 11:12:30 -0700269 bitC->bitContainer >>= nbBytes*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100270}
271
Yann Colletd1d210f2016-03-19 12:12:07 +0100272/*! BIT_closeCStream() :
Yann Collet01e5b952016-03-19 14:14:31 +0100273 * @return : size of CStream, in bytes,
Yann Colletb71363b2017-07-19 01:05:40 -0700274 * or 0 if it could not fit into dstBuffer */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100275MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
276{
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100277 BIT_addBitsFast(bitC, 1, 1); /* endMark */
278 BIT_flushBits(bitC);
Yann Collet33c38b02017-05-01 11:12:30 -0700279 if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
Yann Collet01e5b952016-03-19 14:14:31 +0100280 return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100281}
282
283
Yann Colletae7aa062016-02-03 02:46:46 +0100284/*-********************************************************
Yann Colletb71363b2017-07-19 01:05:40 -0700285* bitStream decoding
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100286**********************************************************/
Yann Collet01e5b952016-03-19 14:14:31 +0100287/*! BIT_initDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700288 * Initialize a BIT_DStream_t.
289 * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
290 * `srcSize` must be the *exact* size of the bitStream, in bytes.
291 * @return : size of stream (== srcSize), or an errorCode if a problem is detected
292 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100293MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
294{
295 if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
296
Yann Colletf39a6732017-05-01 09:56:03 -0700297 bitD->start = (const char*)srcBuffer;
298 bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
299
Yann Collet1032fbe2016-05-11 18:30:24 +0200300 if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
Yann Collet1032fbe2016-05-11 18:30:24 +0200301 bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100302 bitD->bitContainer = MEM_readLEST(bitD->ptr);
Yann Colletb21ce152016-03-24 01:27:55 +0100303 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
Yann Collet5397a662016-12-13 15:21:06 +0100304 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
Yann Collet18c8f792016-06-12 22:51:52 +0200305 if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
Yann Colletae7aa062016-02-03 02:46:46 +0100306 } else {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100307 bitD->ptr = bitD->start;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200308 bitD->bitContainer = *(const BYTE*)(bitD->start);
309 switch(srcSize)
310 {
Yann Colletb71363b2017-07-19 01:05:40 -0700311 case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
312 /* fall-through */
Jos Collin05286fd2017-05-09 08:36:05 +0530313
Yann Colletb71363b2017-07-19 01:05:40 -0700314 case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
315 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700316
Yann Colletb71363b2017-07-19 01:05:40 -0700317 case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
318 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700319
Yann Colletb71363b2017-07-19 01:05:40 -0700320 case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
321 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700322
Yann Colletb71363b2017-07-19 01:05:40 -0700323 case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
324 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700325
Yann Colletb71363b2017-07-19 01:05:40 -0700326 case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
327 /* fall-through */
Yann Collet58e8d792017-06-02 18:20:48 -0700328
Yann Colletb71363b2017-07-19 01:05:40 -0700329 default: break;
Yann Collet1ceb5a92016-05-12 13:50:13 +0200330 }
Yann Colletb71363b2017-07-19 01:05:40 -0700331 { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
332 bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
333 if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
334 }
Yann Collet1032fbe2016-05-11 18:30:24 +0200335 bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100336 }
337
338 return srcSize;
339}
340
Yann Collet1032fbe2016-05-11 18:30:24 +0200341MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
Yann Collet3c017862016-03-23 14:09:51 +0100342{
Yann Collet1032fbe2016-05-11 18:30:24 +0200343 return bitContainer >> start;
Yann Collet3c017862016-03-23 14:09:51 +0100344}
345
Yann Collet1032fbe2016-05-11 18:30:24 +0200346MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
Yann Collet3c017862016-03-23 14:09:51 +0100347{
Yann Collet6ed3b522018-10-10 18:26:44 -0700348 U32 const regMask = sizeof(bitContainer)*8 - 1;
349 /* if start > regMask, bitstream is corrupted, and result is undefined */
Nick Terrell74718d72017-09-15 17:44:09 -0700350 assert(nbBits < BIT_MASK_SIZE);
Yann Collet6ed3b522018-10-10 18:26:44 -0700351 return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
Yann Collet3c017862016-03-23 14:09:51 +0100352}
353
Yann Collet1032fbe2016-05-11 18:30:24 +0200354MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
Yann Colletafab0202016-03-23 13:57:49 +0100355{
Nick Terrell74718d72017-09-15 17:44:09 -0700356 assert(nbBits < BIT_MASK_SIZE);
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.
Yann Colletb71363b2017-07-19 01:05:40 -0700365 * @return : value extracted */
366MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100367{
Yann Collet7791f192018-10-10 16:36:11 -0700368 /* arbitrate between double-shift and shift+mask */
Yann Colletd3ec2332018-10-10 15:48:43 -0700369#if 1
Yann Collet7791f192018-10-10 16:36:11 -0700370 /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
371 * bitstream is likely corrupted, and result is undefined */
Yann Collet1032fbe2016-05-11 18:30:24 +0200372 return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
Yann Collet862a8592016-03-23 18:45:23 +0100373#else
Yann Collet7791f192018-10-10 16:36:11 -0700374 /* this code path is slower on my os-x laptop */
Yann Colletf39a6732017-05-01 09:56:03 -0700375 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
376 return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
Yann Collet862a8592016-03-23 18:45:23 +0100377#endif
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100378}
379
Yann Collet01e5b952016-03-19 14:14:31 +0100380/*! BIT_lookBitsFast() :
Yann Collet202082f2017-04-28 16:56:39 -0700381 * unsafe version; only works if nbBits >= 1 */
Yann Colletadd08d62016-03-23 01:32:41 +0100382MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100383{
Yann Colletf39a6732017-05-01 09:56:03 -0700384 U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
Yann Collet202082f2017-04-28 16:56:39 -0700385 assert(nbBits >= 1);
Yann Colletf39a6732017-05-01 09:56:03 -0700386 return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100387}
388
389MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
390{
391 bitD->bitsConsumed += nbBits;
392}
393
Yann Collet01e5b952016-03-19 14:14:31 +0100394/*! BIT_readBits() :
Yann Colletb21ce152016-03-24 01:27:55 +0100395 * Read (consume) next n bits from local register and update.
396 * Pay attention to not read more than nbBits contained into local register.
Yann Colletb71363b2017-07-19 01:05:40 -0700397 * @return : extracted value. */
Yann Colletededcfc2018-12-21 16:19:44 -0800398MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100399{
Yann Colletafab0202016-03-23 13:57:49 +0100400 size_t const value = BIT_lookBits(bitD, nbBits);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100401 BIT_skipBits(bitD, nbBits);
402 return value;
403}
404
Yann Collet01e5b952016-03-19 14:14:31 +0100405/*! BIT_readBitsFast() :
Yann Colletb71363b2017-07-19 01:05:40 -0700406 * unsafe version; only works only if nbBits >= 1 */
Yann Colletededcfc2018-12-21 16:19:44 -0800407MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100408{
Yann Colletafab0202016-03-23 13:57:49 +0100409 size_t const value = BIT_lookBitsFast(bitD, nbBits);
Yann Collet202082f2017-04-28 16:56:39 -0700410 assert(nbBits >= 1);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100411 BIT_skipBits(bitD, nbBits);
412 return value;
413}
414
Nick Terrell718f00f2019-11-25 18:26:19 -0800415/*! BIT_reloadDStreamFast() :
416 * Similar to BIT_reloadDStream(), but with two differences:
417 * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
418 * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
419 * point you must use BIT_reloadDStream() to reload.
420 */
421MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
422{
423 if (UNLIKELY(bitD->ptr < bitD->limitPtr))
424 return BIT_DStream_overflow;
425 assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
426 bitD->ptr -= bitD->bitsConsumed >> 3;
427 bitD->bitsConsumed &= 7;
428 bitD->bitContainer = MEM_readLEST(bitD->ptr);
429 return BIT_DStream_unfinished;
430}
431
Yann Collet01e5b952016-03-19 14:14:31 +0100432/*! BIT_reloadDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700433 * Refill `bitD` from buffer previously set in BIT_initDStream() .
434 * This function is safe, it guarantees it will not read beyond src buffer.
435 * @return : status of `BIT_DStream_t` internal register.
Baldur Karlsson430a2fe2018-03-13 20:02:21 +0000436 * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100437MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
438{
Yann Colletf39a6732017-05-01 09:56:03 -0700439 if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
Nick Terrell5152fb22017-03-29 18:51:58 -0700440 return BIT_DStream_overflow;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100441
Yann Colletf39a6732017-05-01 09:56:03 -0700442 if (bitD->ptr >= bitD->limitPtr) {
Nick Terrell718f00f2019-11-25 18:26:19 -0800443 return BIT_reloadDStreamFast(bitD);
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100444 }
Yann Colletae7aa062016-02-03 02:46:46 +0100445 if (bitD->ptr == bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100446 if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
447 return BIT_DStream_completed;
448 }
Yann Colletf39a6732017-05-01 09:56:03 -0700449 /* start < ptr < limitPtr */
Yann Collet01e5b952016-03-19 14:14:31 +0100450 { U32 nbBytes = bitD->bitsConsumed >> 3;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100451 BIT_DStream_status result = BIT_DStream_unfinished;
Yann Colletae7aa062016-02-03 02:46:46 +0100452 if (bitD->ptr - nbBytes < bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100453 nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
454 result = BIT_DStream_endOfBuffer;
455 }
456 bitD->ptr -= nbBytes;
457 bitD->bitsConsumed -= nbBytes*8;
Yann Colletf39a6732017-05-01 09:56:03 -0700458 bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100459 return result;
460 }
461}
462
Yann Colletd1d210f2016-03-19 12:12:07 +0100463/*! BIT_endOfDStream() :
Yann Colletb71363b2017-07-19 01:05:40 -0700464 * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
465 */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100466MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
467{
468 return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
469}
470
471#if defined (__cplusplus)
472}
473#endif
474
475#endif /* BITSTREAM_H_MODULE */