OLD | NEW |
(Empty) | |
| 1 /* Copyright 2013 Google Inc. All Rights Reserved. |
| 2 |
| 3 Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 you may not use this file except in compliance with the License. |
| 5 You may obtain a copy of the License at |
| 6 |
| 7 http://www.apache.org/licenses/LICENSE-2.0 |
| 8 |
| 9 Unless required by applicable law or agreed to in writing, software |
| 10 distributed under the License is distributed on an "AS IS" BASIS, |
| 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 See the License for the specific language governing permissions and |
| 13 limitations under the License. |
| 14 |
| 15 Bit reading helpers |
| 16 */ |
| 17 |
| 18 #ifndef BROTLI_DEC_BIT_READER_H_ |
| 19 #define BROTLI_DEC_BIT_READER_H_ |
| 20 |
| 21 #include <string.h> |
| 22 #include "./streams.h" |
| 23 #include "./types.h" |
| 24 |
| 25 #if defined(__cplusplus) || defined(c_plusplus) |
| 26 extern "C" { |
| 27 #endif |
| 28 |
| 29 #define BROTLI_MAX_NUM_BIT_READ 25 |
| 30 #define BROTLI_READ_SIZE 4096 |
| 31 #define BROTLI_IBUF_SIZE (2 * BROTLI_READ_SIZE + 32) |
| 32 #define BROTLI_IBUF_MASK (2 * BROTLI_READ_SIZE - 1) |
| 33 |
| 34 #define UNALIGNED_COPY64(dst, src) memcpy(dst, src, 8) |
| 35 #define UNALIGNED_MOVE64(dst, src) memmove(dst, src, 8) |
| 36 |
| 37 static const uint32_t kBitMask[BROTLI_MAX_NUM_BIT_READ] = { |
| 38 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, |
| 39 65535, 131071, 262143, 524287, 1048575, 2097151, 4194303, 8388607, 16777215 |
| 40 }; |
| 41 |
| 42 typedef struct { |
| 43 /* Input byte buffer, consist of a ringbuffer and a "slack" region where */ |
| 44 /* bytes from the start of the ringbuffer are copied. */ |
| 45 uint8_t buf_[BROTLI_IBUF_SIZE]; |
| 46 uint8_t* buf_ptr_; /* next input will write here */ |
| 47 BrotliInput input_; /* input callback */ |
| 48 uint64_t val_; /* pre-fetched bits */ |
| 49 uint32_t pos_; /* byte position in stream */ |
| 50 uint32_t bit_pos_; /* current bit-reading position in val_ */ |
| 51 uint32_t bit_end_pos_; /* bit-reading end position from LSB of val_ */ |
| 52 int eos_; /* input stream is finished */ |
| 53 } BrotliBitReader; |
| 54 |
| 55 int BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input); |
| 56 |
| 57 /* Return the prefetched bits, so they can be looked up. */ |
| 58 static BROTLI_INLINE uint32_t BrotliPrefetchBits(BrotliBitReader* const br) { |
| 59 return (uint32_t)(br->val_ >> br->bit_pos_); |
| 60 } |
| 61 |
| 62 /* For jumping over a number of bits in the bit stream when accessed with */ |
| 63 /* BrotliPrefetchBits and BrotliFillBitWindow. */ |
| 64 static BROTLI_INLINE void BrotliSetBitPos(BrotliBitReader* const br, |
| 65 uint32_t val) { |
| 66 #ifdef BROTLI_DECODE_DEBUG |
| 67 uint32_t n_bits = val - br->bit_pos_; |
| 68 const uint32_t bval = (uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits]; |
| 69 printf("[BrotliReadBits] %010d %2d val: %6x\n", |
| 70 (br->pos_ << 3) + br->bit_pos_ - 64, n_bits, bval); |
| 71 #endif |
| 72 br->bit_pos_ = val; |
| 73 } |
| 74 |
| 75 /* Reload up to 64 bits byte-by-byte */ |
| 76 static BROTLI_INLINE void ShiftBytes(BrotliBitReader* const br) { |
| 77 while (br->bit_pos_ >= 8) { |
| 78 br->val_ >>= 8; |
| 79 br->val_ |= ((uint64_t)br->buf_[br->pos_ & BROTLI_IBUF_MASK]) << 56; |
| 80 ++br->pos_; |
| 81 br->bit_pos_ -= 8; |
| 82 br->bit_end_pos_ -= 8; |
| 83 } |
| 84 } |
| 85 |
| 86 /* Fills up the input ringbuffer by calling the input callback. |
| 87 |
| 88 Does nothing if there are at least 32 bytes present after current position. |
| 89 |
| 90 Returns 0 if either: |
| 91 - the input callback returned an error, or |
| 92 - there is no more input and the position is past the end of the stream. |
| 93 |
| 94 After encountering the end of the input stream, 32 additional zero bytes are |
| 95 copied to the ringbuffer, therefore it is safe to call this function after |
| 96 every 32 bytes of input is read. |
| 97 */ |
| 98 static BROTLI_INLINE int BrotliReadMoreInput(BrotliBitReader* const br) { |
| 99 if (br->bit_end_pos_ > 256) { |
| 100 return 1; |
| 101 } else if (br->eos_) { |
| 102 return br->bit_pos_ <= br->bit_end_pos_; |
| 103 } else { |
| 104 uint8_t* dst = br->buf_ptr_; |
| 105 int bytes_read = BrotliRead(br->input_, dst, BROTLI_READ_SIZE); |
| 106 if (bytes_read < 0) { |
| 107 return 0; |
| 108 } |
| 109 if (bytes_read < BROTLI_READ_SIZE) { |
| 110 br->eos_ = 1; |
| 111 /* Store 32 bytes of zero after the stream end. */ |
| 112 #if (defined(__x86_64__) || defined(_M_X64)) |
| 113 *(uint64_t*)(dst + bytes_read) = 0; |
| 114 *(uint64_t*)(dst + bytes_read + 8) = 0; |
| 115 *(uint64_t*)(dst + bytes_read + 16) = 0; |
| 116 *(uint64_t*)(dst + bytes_read + 24) = 0; |
| 117 #else |
| 118 memset(dst + bytes_read, 0, 32); |
| 119 #endif |
| 120 } |
| 121 if (dst == br->buf_) { |
| 122 /* Copy the head of the ringbuffer to the slack region. */ |
| 123 #if (defined(__x86_64__) || defined(_M_X64)) |
| 124 UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 32, br->buf_); |
| 125 UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 24, br->buf_ + 8); |
| 126 UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 16, br->buf_ + 16); |
| 127 UNALIGNED_COPY64(br->buf_ + BROTLI_IBUF_SIZE - 8, br->buf_ + 24); |
| 128 #else |
| 129 memcpy(br->buf_ + (BROTLI_READ_SIZE << 1), br->buf_, 32); |
| 130 #endif |
| 131 br->buf_ptr_ = br->buf_ + BROTLI_READ_SIZE; |
| 132 } else { |
| 133 br->buf_ptr_ = br->buf_; |
| 134 } |
| 135 br->bit_end_pos_ += ((uint32_t)bytes_read << 3); |
| 136 return 1; |
| 137 } |
| 138 } |
| 139 |
| 140 /* Advances the Read buffer by 5 bytes to make room for reading next 24 bits. */ |
| 141 static BROTLI_INLINE void BrotliFillBitWindow(BrotliBitReader* const br) { |
| 142 if (br->bit_pos_ >= 40) { |
| 143 #if (defined(__x86_64__) || defined(_M_X64)) |
| 144 br->val_ >>= 40; |
| 145 /* The expression below needs a little-endian arch to work correctly. */ |
| 146 /* This gives a large speedup for decoding speed. */ |
| 147 br->val_ |= *(const uint64_t*)( |
| 148 br->buf_ + (br->pos_ & BROTLI_IBUF_MASK)) << 24; |
| 149 br->pos_ += 5; |
| 150 br->bit_pos_ -= 40; |
| 151 br->bit_end_pos_ -= 40; |
| 152 #else |
| 153 ShiftBytes(br); |
| 154 #endif |
| 155 } |
| 156 } |
| 157 |
| 158 /* Reads the specified number of bits from Read Buffer. */ |
| 159 static BROTLI_INLINE uint32_t BrotliReadBits( |
| 160 BrotliBitReader* const br, int n_bits) { |
| 161 uint32_t val; |
| 162 BrotliFillBitWindow(br); |
| 163 val = (uint32_t)(br->val_ >> br->bit_pos_) & kBitMask[n_bits]; |
| 164 #ifdef BROTLI_DECODE_DEBUG |
| 165 printf("[BrotliReadBits] %010d %2d val: %6x\n", |
| 166 (br->pos_ << 3) + br->bit_pos_ - 64, n_bits, val); |
| 167 #endif |
| 168 br->bit_pos_ += (uint32_t)n_bits; |
| 169 return val; |
| 170 } |
| 171 |
| 172 #if defined(__cplusplus) || defined(c_plusplus) |
| 173 } /* extern "C" */ |
| 174 #endif |
| 175 |
| 176 #endif /* BROTLI_DEC_BIT_READER_H_ */ |
OLD | NEW |