xref: /dflybsd-src/contrib/zstd/lib/common/bitstream.h (revision a28cd43d19e8b720a6c852a4bbc5ae147a26165a)
1a28cd43dSSascha Wildner /* ******************************************************************
2a28cd43dSSascha Wildner  * bitstream
3a28cd43dSSascha Wildner  * Part of FSE library
4a28cd43dSSascha Wildner  * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
5a28cd43dSSascha Wildner  *
6a28cd43dSSascha Wildner  * You can contact the author at :
7a28cd43dSSascha Wildner  * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
8a28cd43dSSascha Wildner  *
9a28cd43dSSascha Wildner  * This source code is licensed under both the BSD-style license (found in the
10a28cd43dSSascha Wildner  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11a28cd43dSSascha Wildner  * in the COPYING file in the root directory of this source tree).
12a28cd43dSSascha Wildner  * You may select, at your option, one of the above-listed licenses.
13a28cd43dSSascha Wildner ****************************************************************** */
14a28cd43dSSascha Wildner #ifndef BITSTREAM_H_MODULE
15a28cd43dSSascha Wildner #define BITSTREAM_H_MODULE
16a28cd43dSSascha Wildner 
17a28cd43dSSascha Wildner #if defined (__cplusplus)
18a28cd43dSSascha Wildner extern "C" {
19a28cd43dSSascha Wildner #endif
20a28cd43dSSascha Wildner /*
21a28cd43dSSascha Wildner *  This API consists of small unitary functions, which must be inlined for best performance.
22a28cd43dSSascha Wildner *  Since link-time-optimization is not available for all compilers,
23a28cd43dSSascha Wildner *  these functions are defined into a .h to be included.
24a28cd43dSSascha Wildner */
25a28cd43dSSascha Wildner 
26a28cd43dSSascha Wildner /*-****************************************
27a28cd43dSSascha Wildner *  Dependencies
28a28cd43dSSascha Wildner ******************************************/
29a28cd43dSSascha Wildner #include "mem.h"            /* unaligned access routines */
30a28cd43dSSascha Wildner #include "compiler.h"       /* UNLIKELY() */
31a28cd43dSSascha Wildner #include "debug.h"          /* assert(), DEBUGLOG(), RAWLOG() */
32a28cd43dSSascha Wildner #include "error_private.h"  /* error codes and messages */
33a28cd43dSSascha Wildner 
34a28cd43dSSascha Wildner 
35a28cd43dSSascha Wildner /*=========================================
36a28cd43dSSascha Wildner *  Target specific
37a28cd43dSSascha Wildner =========================================*/
38a28cd43dSSascha Wildner #ifndef ZSTD_NO_INTRINSICS
39a28cd43dSSascha Wildner #  if defined(__BMI__) && defined(__GNUC__)
40a28cd43dSSascha Wildner #    include <immintrin.h>   /* support for bextr (experimental) */
41a28cd43dSSascha Wildner #  elif defined(__ICCARM__)
42a28cd43dSSascha Wildner #    include <intrinsics.h>
43a28cd43dSSascha Wildner #  endif
44a28cd43dSSascha Wildner #endif
45a28cd43dSSascha Wildner 
46a28cd43dSSascha Wildner #define STREAM_ACCUMULATOR_MIN_32  25
47a28cd43dSSascha Wildner #define STREAM_ACCUMULATOR_MIN_64  57
48a28cd43dSSascha Wildner #define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
49a28cd43dSSascha Wildner 
50a28cd43dSSascha Wildner 
51a28cd43dSSascha Wildner /*-******************************************
52a28cd43dSSascha Wildner *  bitStream encoding API (write forward)
53a28cd43dSSascha Wildner ********************************************/
54a28cd43dSSascha Wildner /* bitStream can mix input from multiple sources.
55a28cd43dSSascha Wildner  * A critical property of these streams is that they encode and decode in **reverse** direction.
56a28cd43dSSascha Wildner  * So the first bit sequence you add will be the last to be read, like a LIFO stack.
57a28cd43dSSascha Wildner  */
58a28cd43dSSascha Wildner typedef struct {
59a28cd43dSSascha Wildner     size_t bitContainer;
60a28cd43dSSascha Wildner     unsigned bitPos;
61a28cd43dSSascha Wildner     char*  startPtr;
62a28cd43dSSascha Wildner     char*  ptr;
63a28cd43dSSascha Wildner     char*  endPtr;
64a28cd43dSSascha Wildner } BIT_CStream_t;
65a28cd43dSSascha Wildner 
66a28cd43dSSascha Wildner MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
67a28cd43dSSascha Wildner MEM_STATIC void   BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
68a28cd43dSSascha Wildner MEM_STATIC void   BIT_flushBits(BIT_CStream_t* bitC);
69a28cd43dSSascha Wildner MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
70a28cd43dSSascha Wildner 
71a28cd43dSSascha Wildner /* Start with initCStream, providing the size of buffer to write into.
72a28cd43dSSascha Wildner *  bitStream will never write outside of this buffer.
73a28cd43dSSascha Wildner *  `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
74a28cd43dSSascha Wildner *
75a28cd43dSSascha Wildner *  bits are first added to a local register.
76a28cd43dSSascha Wildner *  Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
77a28cd43dSSascha Wildner *  Writing data into memory is an explicit operation, performed by the flushBits function.
78a28cd43dSSascha Wildner *  Hence keep track how many bits are potentially stored into local register to avoid register overflow.
79a28cd43dSSascha Wildner *  After a flushBits, a maximum of 7 bits might still be stored into local register.
80a28cd43dSSascha Wildner *
81a28cd43dSSascha Wildner *  Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
82a28cd43dSSascha Wildner *
83a28cd43dSSascha Wildner *  Last operation is to close the bitStream.
84a28cd43dSSascha Wildner *  The function returns the final size of CStream in bytes.
85a28cd43dSSascha Wildner *  If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
86a28cd43dSSascha Wildner */
87a28cd43dSSascha Wildner 
88a28cd43dSSascha Wildner 
89a28cd43dSSascha Wildner /*-********************************************
90a28cd43dSSascha Wildner *  bitStream decoding API (read backward)
91a28cd43dSSascha Wildner **********************************************/
92a28cd43dSSascha Wildner typedef struct {
93a28cd43dSSascha Wildner     size_t   bitContainer;
94a28cd43dSSascha Wildner     unsigned bitsConsumed;
95a28cd43dSSascha Wildner     const char* ptr;
96a28cd43dSSascha Wildner     const char* start;
97a28cd43dSSascha Wildner     const char* limitPtr;
98a28cd43dSSascha Wildner } BIT_DStream_t;
99a28cd43dSSascha Wildner 
100a28cd43dSSascha Wildner typedef enum { BIT_DStream_unfinished = 0,
101a28cd43dSSascha Wildner                BIT_DStream_endOfBuffer = 1,
102a28cd43dSSascha Wildner                BIT_DStream_completed = 2,
103a28cd43dSSascha Wildner                BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */
104a28cd43dSSascha Wildner                /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
105a28cd43dSSascha Wildner 
106a28cd43dSSascha Wildner MEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
107a28cd43dSSascha Wildner MEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
108a28cd43dSSascha Wildner MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
109a28cd43dSSascha Wildner MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
110a28cd43dSSascha Wildner 
111a28cd43dSSascha Wildner 
112a28cd43dSSascha Wildner /* Start by invoking BIT_initDStream().
113a28cd43dSSascha Wildner *  A chunk of the bitStream is then stored into a local register.
114a28cd43dSSascha Wildner *  Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
115a28cd43dSSascha Wildner *  You can then retrieve bitFields stored into the local register, **in reverse order**.
116a28cd43dSSascha Wildner *  Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
117a28cd43dSSascha Wildner *  A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
118a28cd43dSSascha Wildner *  Otherwise, it can be less than that, so proceed accordingly.
119a28cd43dSSascha Wildner *  Checking if DStream has reached its end can be performed with BIT_endOfDStream().
120a28cd43dSSascha Wildner */
121a28cd43dSSascha Wildner 
122a28cd43dSSascha Wildner 
123a28cd43dSSascha Wildner /*-****************************************
124a28cd43dSSascha Wildner *  unsafe API
125a28cd43dSSascha Wildner ******************************************/
126a28cd43dSSascha Wildner MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
127a28cd43dSSascha Wildner /* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
128a28cd43dSSascha Wildner 
129a28cd43dSSascha Wildner MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
130a28cd43dSSascha Wildner /* unsafe version; does not check buffer overflow */
131a28cd43dSSascha Wildner 
132a28cd43dSSascha Wildner MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
133a28cd43dSSascha Wildner /* faster, but works only if nbBits >= 1 */
134a28cd43dSSascha Wildner 
135a28cd43dSSascha Wildner 
136a28cd43dSSascha Wildner 
137a28cd43dSSascha Wildner /*-**************************************************************
138a28cd43dSSascha Wildner *  Internal functions
139a28cd43dSSascha Wildner ****************************************************************/
BIT_highbit32(U32 val)140a28cd43dSSascha Wildner MEM_STATIC unsigned BIT_highbit32 (U32 val)
141a28cd43dSSascha Wildner {
142a28cd43dSSascha Wildner     assert(val != 0);
143a28cd43dSSascha Wildner     {
144a28cd43dSSascha Wildner #   if defined(_MSC_VER)   /* Visual */
145a28cd43dSSascha Wildner #       if STATIC_BMI2 == 1
146a28cd43dSSascha Wildner 		return _lzcnt_u32(val) ^ 31;
147a28cd43dSSascha Wildner #       else
148a28cd43dSSascha Wildner 		unsigned long r = 0;
149a28cd43dSSascha Wildner 		return _BitScanReverse(&r, val) ? (unsigned)r : 0;
150a28cd43dSSascha Wildner #       endif
151a28cd43dSSascha Wildner #   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */
152a28cd43dSSascha Wildner         return __builtin_clz (val) ^ 31;
153a28cd43dSSascha Wildner #   elif defined(__ICCARM__)    /* IAR Intrinsic */
154a28cd43dSSascha Wildner         return 31 - __CLZ(val);
155a28cd43dSSascha Wildner #   else   /* Software version */
156a28cd43dSSascha Wildner         static const unsigned DeBruijnClz[32] = { 0,  9,  1, 10, 13, 21,  2, 29,
157a28cd43dSSascha Wildner                                                  11, 14, 16, 18, 22, 25,  3, 30,
158a28cd43dSSascha Wildner                                                   8, 12, 20, 28, 15, 17, 24,  7,
159a28cd43dSSascha Wildner                                                  19, 27, 23,  6, 26,  5,  4, 31 };
160a28cd43dSSascha Wildner         U32 v = val;
161a28cd43dSSascha Wildner         v |= v >> 1;
162a28cd43dSSascha Wildner         v |= v >> 2;
163a28cd43dSSascha Wildner         v |= v >> 4;
164a28cd43dSSascha Wildner         v |= v >> 8;
165a28cd43dSSascha Wildner         v |= v >> 16;
166a28cd43dSSascha Wildner         return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
167a28cd43dSSascha Wildner #   endif
168a28cd43dSSascha Wildner     }
169a28cd43dSSascha Wildner }
170a28cd43dSSascha Wildner 
171a28cd43dSSascha Wildner /*=====    Local Constants   =====*/
172a28cd43dSSascha Wildner static const unsigned BIT_mask[] = {
173a28cd43dSSascha Wildner     0,          1,         3,         7,         0xF,       0x1F,
174a28cd43dSSascha Wildner     0x3F,       0x7F,      0xFF,      0x1FF,     0x3FF,     0x7FF,
175a28cd43dSSascha Wildner     0xFFF,      0x1FFF,    0x3FFF,    0x7FFF,    0xFFFF,    0x1FFFF,
176a28cd43dSSascha Wildner     0x3FFFF,    0x7FFFF,   0xFFFFF,   0x1FFFFF,  0x3FFFFF,  0x7FFFFF,
177a28cd43dSSascha Wildner     0xFFFFFF,   0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
178a28cd43dSSascha Wildner     0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
179a28cd43dSSascha Wildner #define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
180a28cd43dSSascha Wildner 
181a28cd43dSSascha Wildner /*-**************************************************************
182a28cd43dSSascha Wildner *  bitStream encoding
183a28cd43dSSascha Wildner ****************************************************************/
184a28cd43dSSascha Wildner /*! BIT_initCStream() :
185a28cd43dSSascha Wildner  *  `dstCapacity` must be > sizeof(size_t)
186a28cd43dSSascha Wildner  *  @return : 0 if success,
187a28cd43dSSascha Wildner  *            otherwise an error code (can be tested using ERR_isError()) */
BIT_initCStream(BIT_CStream_t * bitC,void * startPtr,size_t dstCapacity)188a28cd43dSSascha Wildner MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
189a28cd43dSSascha Wildner                                   void* startPtr, size_t dstCapacity)
190a28cd43dSSascha Wildner {
191a28cd43dSSascha Wildner     bitC->bitContainer = 0;
192a28cd43dSSascha Wildner     bitC->bitPos = 0;
193a28cd43dSSascha Wildner     bitC->startPtr = (char*)startPtr;
194a28cd43dSSascha Wildner     bitC->ptr = bitC->startPtr;
195a28cd43dSSascha Wildner     bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
196a28cd43dSSascha Wildner     if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
197a28cd43dSSascha Wildner     return 0;
198a28cd43dSSascha Wildner }
199a28cd43dSSascha Wildner 
200a28cd43dSSascha Wildner /*! BIT_addBits() :
201a28cd43dSSascha Wildner  *  can add up to 31 bits into `bitC`.
202a28cd43dSSascha Wildner  *  Note : does not check for register overflow ! */
BIT_addBits(BIT_CStream_t * bitC,size_t value,unsigned nbBits)203a28cd43dSSascha Wildner MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
204a28cd43dSSascha Wildner                             size_t value, unsigned nbBits)
205a28cd43dSSascha Wildner {
206a28cd43dSSascha Wildner     DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);
207a28cd43dSSascha Wildner     assert(nbBits < BIT_MASK_SIZE);
208a28cd43dSSascha Wildner     assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
209a28cd43dSSascha Wildner     bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
210a28cd43dSSascha Wildner     bitC->bitPos += nbBits;
211a28cd43dSSascha Wildner }
212a28cd43dSSascha Wildner 
213a28cd43dSSascha Wildner /*! BIT_addBitsFast() :
214a28cd43dSSascha Wildner  *  works only if `value` is _clean_,
215a28cd43dSSascha Wildner  *  meaning all high bits above nbBits are 0 */
BIT_addBitsFast(BIT_CStream_t * bitC,size_t value,unsigned nbBits)216a28cd43dSSascha Wildner MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
217a28cd43dSSascha Wildner                                 size_t value, unsigned nbBits)
218a28cd43dSSascha Wildner {
219a28cd43dSSascha Wildner     assert((value>>nbBits) == 0);
220a28cd43dSSascha Wildner     assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
221a28cd43dSSascha Wildner     bitC->bitContainer |= value << bitC->bitPos;
222a28cd43dSSascha Wildner     bitC->bitPos += nbBits;
223a28cd43dSSascha Wildner }
224a28cd43dSSascha Wildner 
225a28cd43dSSascha Wildner /*! BIT_flushBitsFast() :
226a28cd43dSSascha Wildner  *  assumption : bitContainer has not overflowed
227a28cd43dSSascha Wildner  *  unsafe version; does not check buffer overflow */
BIT_flushBitsFast(BIT_CStream_t * bitC)228a28cd43dSSascha Wildner MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
229a28cd43dSSascha Wildner {
230a28cd43dSSascha Wildner     size_t const nbBytes = bitC->bitPos >> 3;
231a28cd43dSSascha Wildner     assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
232a28cd43dSSascha Wildner     assert(bitC->ptr <= bitC->endPtr);
233a28cd43dSSascha Wildner     MEM_writeLEST(bitC->ptr, bitC->bitContainer);
234a28cd43dSSascha Wildner     bitC->ptr += nbBytes;
235a28cd43dSSascha Wildner     bitC->bitPos &= 7;
236a28cd43dSSascha Wildner     bitC->bitContainer >>= nbBytes*8;
237a28cd43dSSascha Wildner }
238a28cd43dSSascha Wildner 
239a28cd43dSSascha Wildner /*! BIT_flushBits() :
240a28cd43dSSascha Wildner  *  assumption : bitContainer has not overflowed
241a28cd43dSSascha Wildner  *  safe version; check for buffer overflow, and prevents it.
242a28cd43dSSascha Wildner  *  note : does not signal buffer overflow.
243a28cd43dSSascha Wildner  *  overflow will be revealed later on using BIT_closeCStream() */
BIT_flushBits(BIT_CStream_t * bitC)244a28cd43dSSascha Wildner MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
245a28cd43dSSascha Wildner {
246a28cd43dSSascha Wildner     size_t const nbBytes = bitC->bitPos >> 3;
247a28cd43dSSascha Wildner     assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
248a28cd43dSSascha Wildner     assert(bitC->ptr <= bitC->endPtr);
249a28cd43dSSascha Wildner     MEM_writeLEST(bitC->ptr, bitC->bitContainer);
250a28cd43dSSascha Wildner     bitC->ptr += nbBytes;
251a28cd43dSSascha Wildner     if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
252a28cd43dSSascha Wildner     bitC->bitPos &= 7;
253a28cd43dSSascha Wildner     bitC->bitContainer >>= nbBytes*8;
254a28cd43dSSascha Wildner }
255a28cd43dSSascha Wildner 
256a28cd43dSSascha Wildner /*! BIT_closeCStream() :
257a28cd43dSSascha Wildner  *  @return : size of CStream, in bytes,
258a28cd43dSSascha Wildner  *            or 0 if it could not fit into dstBuffer */
BIT_closeCStream(BIT_CStream_t * bitC)259a28cd43dSSascha Wildner MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
260a28cd43dSSascha Wildner {
261a28cd43dSSascha Wildner     BIT_addBitsFast(bitC, 1, 1);   /* endMark */
262a28cd43dSSascha Wildner     BIT_flushBits(bitC);
263a28cd43dSSascha Wildner     if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
264a28cd43dSSascha Wildner     return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
265a28cd43dSSascha Wildner }
266a28cd43dSSascha Wildner 
267a28cd43dSSascha Wildner 
268a28cd43dSSascha Wildner /*-********************************************************
269a28cd43dSSascha Wildner *  bitStream decoding
270a28cd43dSSascha Wildner **********************************************************/
271a28cd43dSSascha Wildner /*! BIT_initDStream() :
272a28cd43dSSascha Wildner  *  Initialize a BIT_DStream_t.
273a28cd43dSSascha Wildner  * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
274a28cd43dSSascha Wildner  * `srcSize` must be the *exact* size of the bitStream, in bytes.
275a28cd43dSSascha Wildner  * @return : size of stream (== srcSize), or an errorCode if a problem is detected
276a28cd43dSSascha Wildner  */
BIT_initDStream(BIT_DStream_t * bitD,const void * srcBuffer,size_t srcSize)277a28cd43dSSascha Wildner MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
278a28cd43dSSascha Wildner {
279a28cd43dSSascha Wildner     if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
280a28cd43dSSascha Wildner 
281a28cd43dSSascha Wildner     bitD->start = (const char*)srcBuffer;
282a28cd43dSSascha Wildner     bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
283a28cd43dSSascha Wildner 
284a28cd43dSSascha Wildner     if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */
285a28cd43dSSascha Wildner         bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
286a28cd43dSSascha Wildner         bitD->bitContainer = MEM_readLEST(bitD->ptr);
287a28cd43dSSascha Wildner         { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
288a28cd43dSSascha Wildner           bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;  /* ensures bitsConsumed is always set */
289a28cd43dSSascha Wildner           if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
290a28cd43dSSascha Wildner     } else {
291a28cd43dSSascha Wildner         bitD->ptr   = bitD->start;
292a28cd43dSSascha Wildner         bitD->bitContainer = *(const BYTE*)(bitD->start);
293a28cd43dSSascha Wildner         switch(srcSize)
294a28cd43dSSascha Wildner         {
295a28cd43dSSascha Wildner         case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
296a28cd43dSSascha Wildner                 /* fall-through */
297a28cd43dSSascha Wildner 
298a28cd43dSSascha Wildner         case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
299a28cd43dSSascha Wildner                 /* fall-through */
300a28cd43dSSascha Wildner 
301a28cd43dSSascha Wildner         case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
302a28cd43dSSascha Wildner                 /* fall-through */
303a28cd43dSSascha Wildner 
304a28cd43dSSascha Wildner         case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
305a28cd43dSSascha Wildner                 /* fall-through */
306a28cd43dSSascha Wildner 
307a28cd43dSSascha Wildner         case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
308a28cd43dSSascha Wildner                 /* fall-through */
309a28cd43dSSascha Wildner 
310a28cd43dSSascha Wildner         case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8;
311a28cd43dSSascha Wildner                 /* fall-through */
312a28cd43dSSascha Wildner 
313a28cd43dSSascha Wildner         default: break;
314a28cd43dSSascha Wildner         }
315a28cd43dSSascha Wildner         {   BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
316a28cd43dSSascha Wildner             bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
317a28cd43dSSascha Wildner             if (lastByte == 0) return ERROR(corruption_detected);  /* endMark not present */
318a28cd43dSSascha Wildner         }
319a28cd43dSSascha Wildner         bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
320a28cd43dSSascha Wildner     }
321a28cd43dSSascha Wildner 
322a28cd43dSSascha Wildner     return srcSize;
323a28cd43dSSascha Wildner }
324a28cd43dSSascha Wildner 
BIT_getUpperBits(size_t bitContainer,U32 const start)325a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
326a28cd43dSSascha Wildner {
327a28cd43dSSascha Wildner     return bitContainer >> start;
328a28cd43dSSascha Wildner }
329a28cd43dSSascha Wildner 
BIT_getMiddleBits(size_t bitContainer,U32 const start,U32 const nbBits)330a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
331a28cd43dSSascha Wildner {
332a28cd43dSSascha Wildner     U32 const regMask = sizeof(bitContainer)*8 - 1;
333a28cd43dSSascha Wildner     /* if start > regMask, bitstream is corrupted, and result is undefined */
334a28cd43dSSascha Wildner     assert(nbBits < BIT_MASK_SIZE);
335a28cd43dSSascha Wildner     return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
336a28cd43dSSascha Wildner }
337a28cd43dSSascha Wildner 
BIT_getLowerBits(size_t bitContainer,U32 const nbBits)338a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
339a28cd43dSSascha Wildner {
340a28cd43dSSascha Wildner #if defined(STATIC_BMI2) && STATIC_BMI2 == 1
341a28cd43dSSascha Wildner 	return  _bzhi_u64(bitContainer, nbBits);
342a28cd43dSSascha Wildner #else
343a28cd43dSSascha Wildner     assert(nbBits < BIT_MASK_SIZE);
344a28cd43dSSascha Wildner     return bitContainer & BIT_mask[nbBits];
345a28cd43dSSascha Wildner #endif
346a28cd43dSSascha Wildner }
347a28cd43dSSascha Wildner 
348a28cd43dSSascha Wildner /*! BIT_lookBits() :
349a28cd43dSSascha Wildner  *  Provides next n bits from local register.
350a28cd43dSSascha Wildner  *  local register is not modified.
351a28cd43dSSascha Wildner  *  On 32-bits, maxNbBits==24.
352a28cd43dSSascha Wildner  *  On 64-bits, maxNbBits==56.
353a28cd43dSSascha Wildner  * @return : value extracted */
BIT_lookBits(const BIT_DStream_t * bitD,U32 nbBits)354a28cd43dSSascha Wildner MEM_STATIC  FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t*  bitD, U32 nbBits)
355a28cd43dSSascha Wildner {
356a28cd43dSSascha Wildner     /* arbitrate between double-shift and shift+mask */
357a28cd43dSSascha Wildner #if 1
358a28cd43dSSascha Wildner     /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
359a28cd43dSSascha Wildner      * bitstream is likely corrupted, and result is undefined */
360a28cd43dSSascha Wildner     return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
361a28cd43dSSascha Wildner #else
362a28cd43dSSascha Wildner     /* this code path is slower on my os-x laptop */
363a28cd43dSSascha Wildner     U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
364a28cd43dSSascha Wildner     return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
365a28cd43dSSascha Wildner #endif
366a28cd43dSSascha Wildner }
367a28cd43dSSascha Wildner 
368a28cd43dSSascha Wildner /*! BIT_lookBitsFast() :
369a28cd43dSSascha Wildner  *  unsafe version; only works if nbBits >= 1 */
BIT_lookBitsFast(const BIT_DStream_t * bitD,U32 nbBits)370a28cd43dSSascha Wildner MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
371a28cd43dSSascha Wildner {
372a28cd43dSSascha Wildner     U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
373a28cd43dSSascha Wildner     assert(nbBits >= 1);
374a28cd43dSSascha Wildner     return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
375a28cd43dSSascha Wildner }
376a28cd43dSSascha Wildner 
BIT_skipBits(BIT_DStream_t * bitD,U32 nbBits)377a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
378a28cd43dSSascha Wildner {
379a28cd43dSSascha Wildner     bitD->bitsConsumed += nbBits;
380a28cd43dSSascha Wildner }
381a28cd43dSSascha Wildner 
382a28cd43dSSascha Wildner /*! BIT_readBits() :
383a28cd43dSSascha Wildner  *  Read (consume) next n bits from local register and update.
384a28cd43dSSascha Wildner  *  Pay attention to not read more than nbBits contained into local register.
385a28cd43dSSascha Wildner  * @return : extracted value. */
BIT_readBits(BIT_DStream_t * bitD,unsigned nbBits)386a28cd43dSSascha Wildner MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
387a28cd43dSSascha Wildner {
388a28cd43dSSascha Wildner     size_t const value = BIT_lookBits(bitD, nbBits);
389a28cd43dSSascha Wildner     BIT_skipBits(bitD, nbBits);
390a28cd43dSSascha Wildner     return value;
391a28cd43dSSascha Wildner }
392a28cd43dSSascha Wildner 
393a28cd43dSSascha Wildner /*! BIT_readBitsFast() :
394a28cd43dSSascha Wildner  *  unsafe version; only works only if nbBits >= 1 */
BIT_readBitsFast(BIT_DStream_t * bitD,unsigned nbBits)395a28cd43dSSascha Wildner MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
396a28cd43dSSascha Wildner {
397a28cd43dSSascha Wildner     size_t const value = BIT_lookBitsFast(bitD, nbBits);
398a28cd43dSSascha Wildner     assert(nbBits >= 1);
399a28cd43dSSascha Wildner     BIT_skipBits(bitD, nbBits);
400a28cd43dSSascha Wildner     return value;
401a28cd43dSSascha Wildner }
402a28cd43dSSascha Wildner 
403a28cd43dSSascha Wildner /*! BIT_reloadDStreamFast() :
404a28cd43dSSascha Wildner  *  Similar to BIT_reloadDStream(), but with two differences:
405a28cd43dSSascha Wildner  *  1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
406a28cd43dSSascha Wildner  *  2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
407a28cd43dSSascha Wildner  *     point you must use BIT_reloadDStream() to reload.
408a28cd43dSSascha Wildner  */
BIT_reloadDStreamFast(BIT_DStream_t * bitD)409a28cd43dSSascha Wildner MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
410a28cd43dSSascha Wildner {
411a28cd43dSSascha Wildner     if (UNLIKELY(bitD->ptr < bitD->limitPtr))
412a28cd43dSSascha Wildner         return BIT_DStream_overflow;
413a28cd43dSSascha Wildner     assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
414a28cd43dSSascha Wildner     bitD->ptr -= bitD->bitsConsumed >> 3;
415a28cd43dSSascha Wildner     bitD->bitsConsumed &= 7;
416a28cd43dSSascha Wildner     bitD->bitContainer = MEM_readLEST(bitD->ptr);
417a28cd43dSSascha Wildner     return BIT_DStream_unfinished;
418a28cd43dSSascha Wildner }
419a28cd43dSSascha Wildner 
420a28cd43dSSascha Wildner /*! BIT_reloadDStream() :
421a28cd43dSSascha Wildner  *  Refill `bitD` from buffer previously set in BIT_initDStream() .
422a28cd43dSSascha Wildner  *  This function is safe, it guarantees it will not read beyond src buffer.
423a28cd43dSSascha Wildner  * @return : status of `BIT_DStream_t` internal register.
424a28cd43dSSascha Wildner  *           when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
BIT_reloadDStream(BIT_DStream_t * bitD)425a28cd43dSSascha Wildner MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
426a28cd43dSSascha Wildner {
427a28cd43dSSascha Wildner     if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* overflow detected, like end of stream */
428a28cd43dSSascha Wildner         return BIT_DStream_overflow;
429a28cd43dSSascha Wildner 
430a28cd43dSSascha Wildner     if (bitD->ptr >= bitD->limitPtr) {
431a28cd43dSSascha Wildner         return BIT_reloadDStreamFast(bitD);
432a28cd43dSSascha Wildner     }
433a28cd43dSSascha Wildner     if (bitD->ptr == bitD->start) {
434a28cd43dSSascha Wildner         if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
435a28cd43dSSascha Wildner         return BIT_DStream_completed;
436a28cd43dSSascha Wildner     }
437a28cd43dSSascha Wildner     /* start < ptr < limitPtr */
438a28cd43dSSascha Wildner     {   U32 nbBytes = bitD->bitsConsumed >> 3;
439a28cd43dSSascha Wildner         BIT_DStream_status result = BIT_DStream_unfinished;
440a28cd43dSSascha Wildner         if (bitD->ptr - nbBytes < bitD->start) {
441a28cd43dSSascha Wildner             nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */
442a28cd43dSSascha Wildner             result = BIT_DStream_endOfBuffer;
443a28cd43dSSascha Wildner         }
444a28cd43dSSascha Wildner         bitD->ptr -= nbBytes;
445a28cd43dSSascha Wildner         bitD->bitsConsumed -= nbBytes*8;
446a28cd43dSSascha Wildner         bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
447a28cd43dSSascha Wildner         return result;
448a28cd43dSSascha Wildner     }
449a28cd43dSSascha Wildner }
450a28cd43dSSascha Wildner 
451a28cd43dSSascha Wildner /*! BIT_endOfDStream() :
452a28cd43dSSascha Wildner  * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
453a28cd43dSSascha Wildner  */
BIT_endOfDStream(const BIT_DStream_t * DStream)454a28cd43dSSascha Wildner MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
455a28cd43dSSascha Wildner {
456a28cd43dSSascha Wildner     return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
457a28cd43dSSascha Wildner }
458a28cd43dSSascha Wildner 
459a28cd43dSSascha Wildner #if defined (__cplusplus)
460a28cd43dSSascha Wildner }
461a28cd43dSSascha Wildner #endif
462a28cd43dSSascha Wildner 
463a28cd43dSSascha Wildner #endif /* BITSTREAM_H_MODULE */
464