blob: e0487e87e8c842b0ff99bc8c921770af93239fd2 [file] [log] [blame]
Yann Colletb1f3f4b2015-10-18 22:18:32 +01001/* ******************************************************************
2 bitstream
Yann Colletae7aa062016-02-03 02:46:46 +01003 Part of FSE library
Yann Colletb1f3f4b2015-10-18 22:18:32 +01004 header file (to include)
Yann Colletae7aa062016-02-03 02:46:46 +01005 Copyright (C) 2013-2016, Yann Collet.
Yann Colletb1f3f4b2015-10-18 22:18:32 +01006
7 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are
11 met:
12
13 * Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above
16 copyright notice, this list of conditions and the following disclaimer
17 in the documentation and/or other materials provided with the
18 distribution.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 You can contact the author at :
33 - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
Yann Colletb1f3f4b2015-10-18 22:18:32 +010034****************************************************************** */
35#ifndef BITSTREAM_H_MODULE
36#define BITSTREAM_H_MODULE
37
38#if defined (__cplusplus)
39extern "C" {
40#endif
41
42
43/*
44* This API consists of small unitary functions, which highly benefit from being inlined.
45* Since link-time-optimization is not available for all compilers,
46* these functions are defined into a .h to be included.
47*/
48
Yann Colletae7aa062016-02-03 02:46:46 +010049/*-****************************************
50* Dependencies
Yann Colletb1f3f4b2015-10-18 22:18:32 +010051******************************************/
Yann Collet977f1f32016-01-21 15:38:47 +010052#include "mem.h" /* unaligned access routines */
53#include "error_private.h" /* error codes and messages */
Yann Colletb1f3f4b2015-10-18 22:18:32 +010054
55
Yann Colletae7aa062016-02-03 02:46:46 +010056/*-******************************************
57* bitStream encoding API (write forward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010058********************************************/
Yann Colletae7aa062016-02-03 02:46:46 +010059/*!
Yann Colletb1f3f4b2015-10-18 22:18:32 +010060* bitStream can mix input from multiple sources.
61* A critical property of these streams is that they encode and decode in **reverse** direction.
62* So the first bit sequence you add will be the last to be read, like a LIFO stack.
63*/
64typedef struct
65{
66 size_t bitContainer;
67 int bitPos;
68 char* startPtr;
69 char* ptr;
70 char* endPtr;
71} BIT_CStream_t;
72
Yann Colletae7aa062016-02-03 02:46:46 +010073MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
Yann Colletb1f3f4b2015-10-18 22:18:32 +010074MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
75MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
76MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
77
Yann Colletae7aa062016-02-03 02:46:46 +010078/*!
79* Start by initCStream, providing the size of buffer to write into.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010080* bitStream will never write outside of this buffer.
Yann Colletae7aa062016-02-03 02:46:46 +010081* @dstCapacity must be >= sizeof(size_t), otherwise @return will be an error code.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010082*
83* bits are first added to a local register.
84* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
Yann Colletae7aa062016-02-03 02:46:46 +010085* Writing data into memory is an explicit operation, performed by the flushBits function.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010086* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
87* After a flushBits, a maximum of 7 bits might still be stored into local register.
88*
Yann Colletae7aa062016-02-03 02:46:46 +010089* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
Yann Colletb1f3f4b2015-10-18 22:18:32 +010090*
91* Last operation is to close the bitStream.
92* The function returns the final size of CStream in bytes.
Yann Colletae7aa062016-02-03 02:46:46 +010093* If data couldn't fit into @dstBuffer, it will return a 0 ( == not storable)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010094*/
95
96
Yann Colletae7aa062016-02-03 02:46:46 +010097/*-********************************************
98* bitStream decoding API (read backward)
Yann Colletb1f3f4b2015-10-18 22:18:32 +010099**********************************************/
100typedef struct
101{
102 size_t bitContainer;
103 unsigned bitsConsumed;
104 const char* ptr;
105 const char* start;
106} BIT_DStream_t;
107
108typedef enum { BIT_DStream_unfinished = 0,
109 BIT_DStream_endOfBuffer = 1,
110 BIT_DStream_completed = 2,
111 BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
112 /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
113
114MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
115MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
116MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
117MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
118
119
Yann Colletae7aa062016-02-03 02:46:46 +0100120/*!
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100121* Start by invoking BIT_initDStream().
122* A chunk of the bitStream is then stored into a local register.
123* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
124* You can then retrieve bitFields stored into the local register, **in reverse order**.
Yann Colletae7aa062016-02-03 02:46:46 +0100125* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100126* A reload guarantee a minimum of ((8*sizeof(size_t))-7) bits when its result is BIT_DStream_unfinished.
127* Otherwise, it can be less than that, so proceed accordingly.
128* Checking if DStream has reached its end can be performed with BIT_endOfDStream()
129*/
130
131
Yann Colletae7aa062016-02-03 02:46:46 +0100132/*-****************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100133* unsafe API
134******************************************/
135MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
136/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
137
138MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
139/* unsafe version; does not check buffer overflow */
140
141MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
142/* faster, but works only if nbBits >= 1 */
143
144
145
Yann Colletae7aa062016-02-03 02:46:46 +0100146/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100147* Helper functions
148****************************************************************/
149MEM_STATIC unsigned BIT_highbit32 (register U32 val)
150{
151# if defined(_MSC_VER) /* Visual */
Yann Collet4114f952015-10-30 06:40:22 +0100152 unsigned long r=0;
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100153 _BitScanReverse ( &r, val );
154 return (unsigned) r;
155# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
156 return 31 - __builtin_clz (val);
157# else /* Software version */
158 static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
159 U32 v = val;
160 unsigned r;
161 v |= v >> 1;
162 v |= v >> 2;
163 v |= v >> 4;
164 v |= v >> 8;
165 v |= v >> 16;
166 r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
167 return r;
168# endif
169}
170
171
Yann Colletae7aa062016-02-03 02:46:46 +0100172/*-**************************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100173* bitStream encoding
174****************************************************************/
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100175MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* startPtr, size_t maxSize)
176{
177 bitC->bitContainer = 0;
178 bitC->bitPos = 0;
179 bitC->startPtr = (char*)startPtr;
180 bitC->ptr = bitC->startPtr;
181 bitC->endPtr = bitC->startPtr + maxSize - sizeof(bitC->ptr);
182 if (maxSize < sizeof(bitC->ptr)) return ERROR(dstSize_tooSmall);
183 return 0;
184}
185
186MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
187{
188 static const unsigned mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF }; /* up to 25 bits */
189 bitC->bitContainer |= (value & mask[nbBits]) << bitC->bitPos;
190 bitC->bitPos += nbBits;
191}
192
193/*! BIT_addBitsFast
194 * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
195MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits)
196{
197 bitC->bitContainer |= value << bitC->bitPos;
198 bitC->bitPos += nbBits;
199}
200
201/*! BIT_flushBitsFast
202 * unsafe version; does not check buffer overflow */
203MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
204{
205 size_t nbBytes = bitC->bitPos >> 3;
206 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
207 bitC->ptr += nbBytes;
208 bitC->bitPos &= 7;
Yann Collet00fd7a22015-11-28 16:03:22 +0100209 bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100210}
211
212MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
213{
214 size_t nbBytes = bitC->bitPos >> 3;
215 MEM_writeLEST(bitC->ptr, bitC->bitContainer);
216 bitC->ptr += nbBytes;
217 if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
218 bitC->bitPos &= 7;
Yann Collet00fd7a22015-11-28 16:03:22 +0100219 bitC->bitContainer >>= nbBytes*8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100220}
221
222/*! BIT_closeCStream
223 * @result : size of CStream, in bytes, or 0 if it cannot fit into dstBuffer */
224MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
225{
226 char* endPtr;
227
228 BIT_addBitsFast(bitC, 1, 1); /* endMark */
229 BIT_flushBits(bitC);
230
231 if (bitC->ptr >= bitC->endPtr) /* too close to buffer's end */
232 return 0; /* not storable */
233
234 endPtr = bitC->ptr;
235 endPtr += bitC->bitPos > 0; /* remaining bits (incomplete byte) */
236
237 return (endPtr - bitC->startPtr);
238}
239
240
Yann Colletae7aa062016-02-03 02:46:46 +0100241/*-********************************************************
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100242* bitStream decoding
243**********************************************************/
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100244/*!BIT_initDStream
245* Initialize a BIT_DStream_t.
246* @bitD : a pointer to an already allocated BIT_DStream_t structure
247* @srcBuffer must point at the beginning of a bitStream
248* @srcSize must be the exact size of the bitStream
249* @result : size of stream (== srcSize) or an errorCode if a problem is detected
250*/
251MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
252{
253 if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
254
Yann Colletae7aa062016-02-03 02:46:46 +0100255 if (srcSize >= sizeof(size_t)) { /* normal case */
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100256 U32 contain32;
257 bitD->start = (const char*)srcBuffer;
258 bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(size_t);
259 bitD->bitContainer = MEM_readLEST(bitD->ptr);
260 contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
261 if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
262 bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
Yann Colletae7aa062016-02-03 02:46:46 +0100263 } else {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100264 U32 contain32;
265 bitD->start = (const char*)srcBuffer;
266 bitD->ptr = bitD->start;
267 bitD->bitContainer = *(const BYTE*)(bitD->start);
268 switch(srcSize)
269 {
270 case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);
271 case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);
272 case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);
273 case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;
274 case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;
275 case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) << 8;
276 default:;
277 }
278 contain32 = ((const BYTE*)srcBuffer)[srcSize-1];
279 if (contain32 == 0) return ERROR(GENERIC); /* endMark not present */
280 bitD->bitsConsumed = 8 - BIT_highbit32(contain32);
281 bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;
282 }
283
284 return srcSize;
285}
286
287/*!BIT_lookBits
288 * Provides next n bits from local register
289 * local register is not modified (bits are still present for next read/look)
290 * On 32-bits, maxNbBits==25
291 * On 64-bits, maxNbBits==57
292 * @return : value extracted
293 */
294MEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)
295{
296 const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
297 return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);
298}
299
300/*! BIT_lookBitsFast :
301* unsafe version; only works only if nbBits >= 1 */
302MEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)
303{
304 const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;
305 return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);
306}
307
308MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
309{
310 bitD->bitsConsumed += nbBits;
311}
312
313/*!BIT_readBits
314 * Read next n bits from local register.
315 * pay attention to not read more than nbBits contained into local register.
316 * @return : extracted value.
317 */
318MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
319{
320 size_t value = BIT_lookBits(bitD, nbBits);
321 BIT_skipBits(bitD, nbBits);
322 return value;
323}
324
325/*!BIT_readBitsFast :
326* unsafe version; only works only if nbBits >= 1 */
327MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
328{
329 size_t value = BIT_lookBitsFast(bitD, nbBits);
330 BIT_skipBits(bitD, nbBits);
331 return value;
332}
333
334MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
335{
336 if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* should never happen */
337 return BIT_DStream_overflow;
338
Yann Colletae7aa062016-02-03 02:46:46 +0100339 if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100340 bitD->ptr -= bitD->bitsConsumed >> 3;
341 bitD->bitsConsumed &= 7;
342 bitD->bitContainer = MEM_readLEST(bitD->ptr);
343 return BIT_DStream_unfinished;
344 }
Yann Colletae7aa062016-02-03 02:46:46 +0100345 if (bitD->ptr == bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100346 if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
347 return BIT_DStream_completed;
348 }
349 {
350 U32 nbBytes = bitD->bitsConsumed >> 3;
351 BIT_DStream_status result = BIT_DStream_unfinished;
Yann Colletae7aa062016-02-03 02:46:46 +0100352 if (bitD->ptr - nbBytes < bitD->start) {
Yann Colletb1f3f4b2015-10-18 22:18:32 +0100353 nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
354 result = BIT_DStream_endOfBuffer;
355 }
356 bitD->ptr -= nbBytes;
357 bitD->bitsConsumed -= nbBytes*8;
358 bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
359 return result;
360 }
361}
362
363/*! BIT_endOfDStream
364* @return Tells if DStream has reached its exact end
365*/
366MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
367{
368 return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
369}
370
371#if defined (__cplusplus)
372}
373#endif
374
375#endif /* BITSTREAM_H_MODULE */