]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/BrotliCustomDecompressLib/dec/bit_reader.h
MdeModulePkg: Copy Brotli algorithm 3rd party source code for library
[mirror_edk2.git] / MdeModulePkg / Library / BrotliCustomDecompressLib / dec / bit_reader.h
CommitLineData
36ff6d80
SB
1/* Copyright 2013 Google Inc. All Rights Reserved.\r
2\r
3 Distributed under MIT license.\r
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\r
5*/\r
6\r
7/* Bit reading helpers */\r
8\r
9#ifndef BROTLI_DEC_BIT_READER_H_\r
10#define BROTLI_DEC_BIT_READER_H_\r
11\r
12#include <string.h> /* memcpy */\r
13\r
14#include "../common/types.h"\r
15#include "./port.h"\r
16\r
17#if defined(__cplusplus) || defined(c_plusplus)\r
18extern "C" {\r
19#endif\r
20\r
21#if (BROTLI_64_BITS)\r
22#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 4\r
23typedef uint64_t reg_t;\r
24#else\r
25#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 2\r
26typedef uint32_t reg_t;\r
27#endif\r
28\r
29static const uint32_t kBitMask[33] = { 0x0000,\r
30 0x00000001, 0x00000003, 0x00000007, 0x0000000F,\r
31 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,\r
32 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,\r
33 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,\r
34 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,\r
35 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,\r
36 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,\r
37 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF\r
38};\r
39\r
40static BROTLI_INLINE uint32_t BitMask(uint32_t n) {\r
41 if (IS_CONSTANT(n) || BROTLI_HAS_UBFX) {\r
42 /* Masking with this expression turns to a single\r
43 "Unsigned Bit Field Extract" UBFX instruction on ARM. */\r
44 return ~((0xffffffffU) << n);\r
45 } else {\r
46 return kBitMask[n];\r
47 }\r
48}\r
49\r
50typedef struct {\r
51 reg_t val_; /* pre-fetched bits */\r
52 uint32_t bit_pos_; /* current bit-reading position in val_ */\r
53 const uint8_t* next_in; /* the byte we're reading from */\r
54 size_t avail_in;\r
55} BrotliBitReader;\r
56\r
57typedef struct {\r
58 reg_t val_;\r
59 uint32_t bit_pos_;\r
60 const uint8_t* next_in;\r
61 size_t avail_in;\r
62} BrotliBitReaderState;\r
63\r
64/* Initializes the bitreader fields. */\r
65BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);\r
66\r
67/* Ensures that accumulator is not empty. May consume one byte of input.\r
68 Returns 0 if data is required but there is no input available.\r
69 For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned\r
70 reading. */\r
71BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);\r
72\r
73static BROTLI_INLINE void BrotliBitReaderSaveState(\r
74 BrotliBitReader* const from, BrotliBitReaderState* to) {\r
75 to->val_ = from->val_;\r
76 to->bit_pos_ = from->bit_pos_;\r
77 to->next_in = from->next_in;\r
78 to->avail_in = from->avail_in;\r
79}\r
80\r
81static BROTLI_INLINE void BrotliBitReaderRestoreState(\r
82 BrotliBitReader* const to, BrotliBitReaderState* from) {\r
83 to->val_ = from->val_;\r
84 to->bit_pos_ = from->bit_pos_;\r
85 to->next_in = from->next_in;\r
86 to->avail_in = from->avail_in;\r
87}\r
88\r
89static BROTLI_INLINE uint32_t BrotliGetAvailableBits(\r
90 const BrotliBitReader* br) {\r
91 return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_;\r
92}\r
93\r
94/* Returns amount of unread bytes the bit reader still has buffered from the\r
95 BrotliInput, including whole bytes in br->val_. */\r
96static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {\r
97 return br->avail_in + (BrotliGetAvailableBits(br) >> 3);\r
98}\r
99\r
100/* Checks if there is at least num bytes left in the input ringbuffer (excluding\r
101 the bits remaining in br->val_). */\r
102static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(\r
103 BrotliBitReader* const br, size_t num) {\r
104 return TO_BROTLI_BOOL(br->avail_in >= num);\r
105}\r
106\r
107static BROTLI_INLINE uint16_t BrotliLoad16LE(const uint8_t* in) {\r
108 if (BROTLI_LITTLE_ENDIAN) {\r
109 return *((const uint16_t*)in);\r
110 } else if (BROTLI_BIG_ENDIAN) {\r
111 uint16_t value = *((const uint16_t*)in);\r
112 return (uint16_t)(((value & 0xFFU) << 8) | ((value & 0xFF00U) >> 8));\r
113 } else {\r
114 return (uint16_t)(in[0] | (in[1] << 8));\r
115 }\r
116}\r
117\r
118static BROTLI_INLINE uint32_t BrotliLoad32LE(const uint8_t* in) {\r
119 if (BROTLI_LITTLE_ENDIAN) {\r
120 return *((const uint32_t*)in);\r
121 } else if (BROTLI_BIG_ENDIAN) {\r
122 uint32_t value = *((const uint32_t*)in);\r
123 return ((value & 0xFFU) << 24) | ((value & 0xFF00U) << 8) |\r
124 ((value & 0xFF0000U) >> 8) | ((value & 0xFF000000U) >> 24);\r
125 } else {\r
126 uint32_t value = (uint32_t)(*(in++));\r
127 value |= (uint32_t)(*(in++)) << 8;\r
128 value |= (uint32_t)(*(in++)) << 16;\r
129 value |= (uint32_t)(*(in++)) << 24;\r
130 return value;\r
131 }\r
132}\r
133\r
134#if (BROTLI_64_BITS)\r
135static BROTLI_INLINE uint64_t BrotliLoad64LE(const uint8_t* in) {\r
136 if (BROTLI_LITTLE_ENDIAN) {\r
137 return *((const uint64_t*)in);\r
138 } else if (BROTLI_BIG_ENDIAN) {\r
139 uint64_t value = *((const uint64_t*)in);\r
140 return\r
141 ((value & 0xFFU) << 56) |\r
142 ((value & 0xFF00U) << 40) |\r
143 ((value & 0xFF0000U) << 24) |\r
144 ((value & 0xFF000000U) << 8) |\r
145 ((value & 0xFF00000000U) >> 8) |\r
146 ((value & 0xFF0000000000U) >> 24) |\r
147 ((value & 0xFF000000000000U) >> 40) |\r
148 ((value & 0xFF00000000000000U) >> 56);\r
149 } else {\r
150 uint64_t value = (uint64_t)(*(in++));\r
151 value |= (uint64_t)(*(in++)) << 8;\r
152 value |= (uint64_t)(*(in++)) << 16;\r
153 value |= (uint64_t)(*(in++)) << 24;\r
154 value |= (uint64_t)(*(in++)) << 32;\r
155 value |= (uint64_t)(*(in++)) << 40;\r
156 value |= (uint64_t)(*(in++)) << 48;\r
157 value |= (uint64_t)(*(in++)) << 56;\r
158 return value;\r
159 }\r
160}\r
161#endif\r
162\r
163/* Guarantees that there are at least n_bits + 1 bits in accumulator.\r
164 Precondition: accumulator contains at least 1 bit.\r
165 n_bits should be in the range [1..24] for regular build. For portable\r
166 non-64-bit little endian build only 16 bits are safe to request. */\r
167static BROTLI_INLINE void BrotliFillBitWindow(\r
168 BrotliBitReader* const br, uint32_t n_bits) {\r
169#if (BROTLI_64_BITS)\r
170 if (!BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {\r
171 if (br->bit_pos_ >= 56) {\r
172 br->val_ >>= 56;\r
173 br->bit_pos_ ^= 56; /* here same as -= 56 because of the if condition */\r
174 br->val_ |= BrotliLoad64LE(br->next_in) << 8;\r
175 br->avail_in -= 7;\r
176 br->next_in += 7;\r
177 }\r
178 } else if (!BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 16)) {\r
179 if (br->bit_pos_ >= 48) {\r
180 br->val_ >>= 48;\r
181 br->bit_pos_ ^= 48; /* here same as -= 48 because of the if condition */\r
182 br->val_ |= BrotliLoad64LE(br->next_in) << 16;\r
183 br->avail_in -= 6;\r
184 br->next_in += 6;\r
185 }\r
186 } else {\r
187 if (br->bit_pos_ >= 32) {\r
188 br->val_ >>= 32;\r
189 br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */\r
190 br->val_ |= ((uint64_t)BrotliLoad32LE(br->next_in)) << 32;\r
191 br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;\r
192 br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\r
193 }\r
194 }\r
195#else\r
196 if (!BROTLI_ALIGNED_READ && IS_CONSTANT(n_bits) && (n_bits <= 8)) {\r
197 if (br->bit_pos_ >= 24) {\r
198 br->val_ >>= 24;\r
199 br->bit_pos_ ^= 24; /* here same as -= 24 because of the if condition */\r
200 br->val_ |= BrotliLoad32LE(br->next_in) << 8;\r
201 br->avail_in -= 3;\r
202 br->next_in += 3;\r
203 }\r
204 } else {\r
205 if (br->bit_pos_ >= 16) {\r
206 br->val_ >>= 16;\r
207 br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */\r
208 br->val_ |= ((uint32_t)BrotliLoad16LE(br->next_in)) << 16;\r
209 br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;\r
210 br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\r
211 }\r
212 }\r
213#endif\r
214}\r
215\r
216/* Mosltly like BrotliFillBitWindow, but guarantees only 16 bits and reads no\r
217 more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */\r
218static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {\r
219 BrotliFillBitWindow(br, 17);\r
220}\r
221\r
222/* Pulls one byte of input to accumulator. */\r
223static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {\r
224 if (br->avail_in == 0) {\r
225 return BROTLI_FALSE;\r
226 }\r
227 br->val_ >>= 8;\r
228#if (BROTLI_64_BITS)\r
229 br->val_ |= ((uint64_t)*br->next_in) << 56;\r
230#else\r
231 br->val_ |= ((uint32_t)*br->next_in) << 24;\r
232#endif\r
233 br->bit_pos_ -= 8;\r
234 --br->avail_in;\r
235 ++br->next_in;\r
236 return BROTLI_TRUE;\r
237}\r
238\r
239/* Returns currently available bits.\r
240 The number of valid bits could be calclulated by BrotliGetAvailableBits. */\r
241static BROTLI_INLINE reg_t BrotliGetBitsUnmasked(BrotliBitReader* const br) {\r
242 return br->val_ >> br->bit_pos_;\r
243}\r
244\r
245/* Like BrotliGetBits, but does not mask the result.\r
246 The result contains at least 16 valid bits. */\r
247static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked(\r
248 BrotliBitReader* const br) {\r
249 BrotliFillBitWindow(br, 16);\r
250 return (uint32_t)BrotliGetBitsUnmasked(br);\r
251}\r
252\r
253/* Returns the specified number of bits from br without advancing bit pos. */\r
254static BROTLI_INLINE uint32_t BrotliGetBits(\r
255 BrotliBitReader* const br, uint32_t n_bits) {\r
256 BrotliFillBitWindow(br, n_bits);\r
257 return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);\r
258}\r
259\r
260/* Tries to peek the specified amount of bits. Returns 0, if there is not\r
261 enough input. */\r
262static BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(\r
263 BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {\r
264 while (BrotliGetAvailableBits(br) < n_bits) {\r
265 if (!BrotliPullByte(br)) {\r
266 return BROTLI_FALSE;\r
267 }\r
268 }\r
269 *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);\r
270 return BROTLI_TRUE;\r
271}\r
272\r
273/* Advances the bit pos by n_bits. */\r
274static BROTLI_INLINE void BrotliDropBits(\r
275 BrotliBitReader* const br, uint32_t n_bits) {\r
276 br->bit_pos_ += n_bits;\r
277}\r
278\r
279static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {\r
280 uint32_t unused_bytes = BrotliGetAvailableBits(br) >> 3;\r
281 uint32_t unused_bits = unused_bytes << 3;\r
282 br->avail_in += unused_bytes;\r
283 br->next_in -= unused_bytes;\r
284 if (unused_bits == sizeof(br->val_) << 3) {\r
285 br->val_ = 0;\r
286 } else {\r
287 br->val_ <<= unused_bits;\r
288 }\r
289 br->bit_pos_ += unused_bits;\r
290}\r
291\r
292/* Reads the specified number of bits from br and advances the bit pos.\r
293 Precondition: accumulator MUST contain at least n_bits. */\r
294static BROTLI_INLINE void BrotliTakeBits(\r
295 BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {\r
296 *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);\r
297 BROTLI_LOG(("[BrotliReadBits] %d %d %d val: %6x\n",\r
298 (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val));\r
299 BrotliDropBits(br, n_bits);\r
300}\r
301\r
302/* Reads the specified number of bits from br and advances the bit pos.\r
303 Assumes that there is enough input to perform BrotliFillBitWindow. */\r
304static BROTLI_INLINE uint32_t BrotliReadBits(\r
305 BrotliBitReader* const br, uint32_t n_bits) {\r
306 if (BROTLI_64_BITS || (n_bits <= 16)) {\r
307 uint32_t val;\r
308 BrotliFillBitWindow(br, n_bits);\r
309 BrotliTakeBits(br, n_bits, &val);\r
310 return val;\r
311 } else {\r
312 uint32_t low_val;\r
313 uint32_t high_val;\r
314 BrotliFillBitWindow(br, 16);\r
315 BrotliTakeBits(br, 16, &low_val);\r
316 BrotliFillBitWindow(br, 8);\r
317 BrotliTakeBits(br, n_bits - 16, &high_val);\r
318 return low_val | (high_val << 16);\r
319 }\r
320}\r
321\r
322/* Tries to read the specified amount of bits. Returns 0, if there is not\r
323 enough input. n_bits MUST be positive. */\r
324static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(\r
325 BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {\r
326 while (BrotliGetAvailableBits(br) < n_bits) {\r
327 if (!BrotliPullByte(br)) {\r
328 return BROTLI_FALSE;\r
329 }\r
330 }\r
331 BrotliTakeBits(br, n_bits, val);\r
332 return BROTLI_TRUE;\r
333}\r
334\r
335/* Advances the bit reader position to the next byte boundary and verifies\r
336 that any skipped bits are set to zero. */\r
337static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {\r
338 uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;\r
339 uint32_t pad_bits = 0;\r
340 if (pad_bits_count != 0) {\r
341 BrotliTakeBits(br, pad_bits_count, &pad_bits);\r
342 }\r
343 return TO_BROTLI_BOOL(pad_bits == 0);\r
344}\r
345\r
346/* Peeks a byte at specified offset.\r
347 Precondition: bit reader is parked to a byte boundary.\r
348 Returns -1 if operation is not feasible. */\r
349static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, size_t offset) {\r
350 uint32_t available_bits = BrotliGetAvailableBits(br);\r
351 size_t bytes_left = available_bits >> 3;\r
352 BROTLI_DCHECK((available_bits & 7) == 0);\r
353 if (offset < bytes_left) {\r
354 return (BrotliGetBitsUnmasked(br) >> (unsigned)(offset << 3)) & 0xFF;\r
355 }\r
356 offset -= bytes_left;\r
357 if (offset < br->avail_in) {\r
358 return br->next_in[offset];\r
359 }\r
360 return -1;\r
361}\r
362\r
363/* Copies remaining input bytes stored in the bit reader to the output. Value\r
364 num may not be larger than BrotliGetRemainingBytes. The bit reader must be\r
365 warmed up again after this. */\r
366static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,\r
367 BrotliBitReader* br, size_t num) {\r
368 while (BrotliGetAvailableBits(br) >= 8 && num > 0) {\r
369 *dest = (uint8_t)BrotliGetBitsUnmasked(br);\r
370 BrotliDropBits(br, 8);\r
371 ++dest;\r
372 --num;\r
373 }\r
374 memcpy(dest, br->next_in, num);\r
375 br->avail_in -= num;\r
376 br->next_in += num;\r
377}\r
378\r
379#if defined(__cplusplus) || defined(c_plusplus)\r
380} /* extern "C" */\r
381#endif\r
382\r
383#endif /* BROTLI_DEC_BIT_READER_H_ */\r