/src/draco/src/draco/core/decoder_buffer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2016 The Draco Authors. |
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 | | #ifndef DRACO_CORE_DECODER_BUFFER_H_ |
16 | | #define DRACO_CORE_DECODER_BUFFER_H_ |
17 | | |
18 | | #include <stdint.h> |
19 | | |
20 | | #include <cstring> |
21 | | #include <memory> |
22 | | |
23 | | #include "draco/core/macros.h" |
24 | | #include "draco/draco_features.h" |
25 | | |
26 | | namespace draco { |
27 | | |
28 | | // Class is a wrapper around input data used by MeshDecoder. It provides a |
29 | | // basic interface for decoding either typed or variable-bit sized data. |
30 | | class DecoderBuffer { |
31 | | public: |
32 | | DecoderBuffer(); |
33 | | DecoderBuffer(const DecoderBuffer &buf) = default; |
34 | | |
35 | | DecoderBuffer &operator=(const DecoderBuffer &buf) = default; |
36 | | |
37 | | // Sets the buffer's internal data. Note that no copy of the input data is |
38 | | // made so the data owner needs to keep the data valid and unchanged for |
39 | | // runtime of the decoder. |
40 | | void Init(const char *data, size_t data_size); |
41 | | |
42 | | // Sets the buffer's internal data. |version| is the Draco bitstream version. |
43 | | void Init(const char *data, size_t data_size, uint16_t version); |
44 | | |
45 | | // Starts decoding a bit sequence. |
46 | | // decode_size must be true if the size of the encoded bit data was included, |
47 | | // during encoding. The size is then returned to out_size. |
48 | | // Returns false on error. |
49 | | bool StartBitDecoding(bool decode_size, uint64_t *out_size); |
50 | | |
51 | | // Ends the decoding of the bit sequence and return to the default |
52 | | // byte-aligned decoding. |
53 | | void EndBitDecoding(); |
54 | | |
55 | | // Decodes up to 32 bits into out_val. Can be called only in between |
56 | | // StartBitDecoding and EndBitDecoding. Otherwise returns false. |
57 | 23.2M | bool DecodeLeastSignificantBits32(uint32_t nbits, uint32_t *out_value) { |
58 | 23.2M | if (!bit_decoder_active()) { |
59 | 0 | return false; |
60 | 0 | } |
61 | 23.2M | return bit_decoder_.GetBits(nbits, out_value); |
62 | 23.2M | } |
63 | | |
64 | | // Decodes an arbitrary data type. |
65 | | // Can be used only when we are not decoding a bit-sequence. |
66 | | // Returns false on error. |
67 | | template <typename T> |
68 | 5.23M | bool Decode(T *out_val) { |
69 | 5.23M | if (!Peek(out_val)) { |
70 | 176 | return false; |
71 | 176 | } |
72 | 5.23M | pos_ += sizeof(T); |
73 | 5.23M | return true; |
74 | 5.23M | } bool draco::DecoderBuffer::Decode<unsigned char>(unsigned char*) Line | Count | Source | 68 | 4.31M | bool Decode(T *out_val) { | 69 | 4.31M | if (!Peek(out_val)) { | 70 | 118 | return false; | 71 | 118 | } | 72 | 4.31M | pos_ += sizeof(T); | 73 | 4.31M | return true; | 74 | 4.31M | } |
bool draco::DecoderBuffer::Decode<int>(int*) Line | Count | Source | 68 | 876 | bool Decode(T *out_val) { | 69 | 876 | if (!Peek(out_val)) { | 70 | 4 | return false; | 71 | 4 | } | 72 | 872 | pos_ += sizeof(T); | 73 | 872 | return true; | 74 | 876 | } |
bool draco::DecoderBuffer::Decode<unsigned int>(unsigned int*) Line | Count | Source | 68 | 220k | bool Decode(T *out_val) { | 69 | 220k | if (!Peek(out_val)) { | 70 | 19 | return false; | 71 | 19 | } | 72 | 220k | pos_ += sizeof(T); | 73 | 220k | return true; | 74 | 220k | } |
bool draco::DecoderBuffer::Decode<signed char>(signed char*) Line | Count | Source | 68 | 1.56k | bool Decode(T *out_val) { | 69 | 1.56k | if (!Peek(out_val)) { | 70 | 1 | return false; | 71 | 1 | } | 72 | 1.56k | pos_ += sizeof(T); | 73 | 1.56k | return true; | 74 | 1.56k | } |
bool draco::DecoderBuffer::Decode<draco::HoleEventData>(draco::HoleEventData*) Line | Count | Source | 68 | 472k | bool Decode(T *out_val) { | 69 | 472k | if (!Peek(out_val)) { | 70 | 30 | return false; | 71 | 30 | } | 72 | 472k | pos_ += sizeof(T); | 73 | 472k | return true; | 74 | 472k | } |
bool draco::DecoderBuffer::Decode<unsigned short>(unsigned short*) Line | Count | Source | 68 | 216k | bool Decode(T *out_val) { | 69 | 216k | if (!Peek(out_val)) { | 70 | 4 | return false; | 71 | 4 | } | 72 | 216k | pos_ += sizeof(T); | 73 | 216k | return true; | 74 | 216k | } |
bool draco::DecoderBuffer::Decode<unsigned long>(unsigned long*) Line | Count | Source | 68 | 190 | bool Decode(T *out_val) { | 69 | 190 | if (!Peek(out_val)) { | 70 | 0 | return false; | 71 | 0 | } | 72 | 190 | pos_ += sizeof(T); | 73 | 190 | return true; | 74 | 190 | } |
bool draco::DecoderBuffer::Decode<float>(float*) Line | Count | Source | 68 | 63 | bool Decode(T *out_val) { | 69 | 63 | if (!Peek(out_val)) { | 70 | 0 | return false; | 71 | 0 | } | 72 | 63 | pos_ += sizeof(T); | 73 | 63 | return true; | 74 | 63 | } |
|
75 | | |
76 | 1.39M | bool Decode(void *out_data, size_t size_to_decode) { |
77 | 1.39M | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { |
78 | 16 | return false; // Buffer overflow. |
79 | 16 | } |
80 | 1.39M | memcpy(out_data, (data_ + pos_), size_to_decode); |
81 | 1.39M | pos_ += size_to_decode; |
82 | 1.39M | return true; |
83 | 1.39M | } |
84 | | |
85 | | // Decodes an arbitrary data, but does not advance the reading position. |
86 | | template <typename T> |
87 | 5.23M | bool Peek(T *out_val) { |
88 | 5.23M | const size_t size_to_decode = sizeof(T); |
89 | 5.23M | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { |
90 | 176 | return false; // Buffer overflow. |
91 | 176 | } |
92 | 5.23M | memcpy(out_val, (data_ + pos_), size_to_decode); |
93 | 5.23M | return true; |
94 | 5.23M | } bool draco::DecoderBuffer::Peek<unsigned char>(unsigned char*) Line | Count | Source | 87 | 4.31M | bool Peek(T *out_val) { | 88 | 4.31M | const size_t size_to_decode = sizeof(T); | 89 | 4.31M | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 118 | return false; // Buffer overflow. | 91 | 118 | } | 92 | 4.31M | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 4.31M | return true; | 94 | 4.31M | } |
bool draco::DecoderBuffer::Peek<int>(int*) Line | Count | Source | 87 | 876 | bool Peek(T *out_val) { | 88 | 876 | const size_t size_to_decode = sizeof(T); | 89 | 876 | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 4 | return false; // Buffer overflow. | 91 | 4 | } | 92 | 872 | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 872 | return true; | 94 | 876 | } |
bool draco::DecoderBuffer::Peek<unsigned int>(unsigned int*) Line | Count | Source | 87 | 220k | bool Peek(T *out_val) { | 88 | 220k | const size_t size_to_decode = sizeof(T); | 89 | 220k | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 19 | return false; // Buffer overflow. | 91 | 19 | } | 92 | 220k | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 220k | return true; | 94 | 220k | } |
bool draco::DecoderBuffer::Peek<signed char>(signed char*) Line | Count | Source | 87 | 1.56k | bool Peek(T *out_val) { | 88 | 1.56k | const size_t size_to_decode = sizeof(T); | 89 | 1.56k | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 1 | return false; // Buffer overflow. | 91 | 1 | } | 92 | 1.56k | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 1.56k | return true; | 94 | 1.56k | } |
bool draco::DecoderBuffer::Peek<draco::HoleEventData>(draco::HoleEventData*) Line | Count | Source | 87 | 472k | bool Peek(T *out_val) { | 88 | 472k | const size_t size_to_decode = sizeof(T); | 89 | 472k | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 30 | return false; // Buffer overflow. | 91 | 30 | } | 92 | 472k | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 472k | return true; | 94 | 472k | } |
bool draco::DecoderBuffer::Peek<unsigned short>(unsigned short*) Line | Count | Source | 87 | 216k | bool Peek(T *out_val) { | 88 | 216k | const size_t size_to_decode = sizeof(T); | 89 | 216k | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 4 | return false; // Buffer overflow. | 91 | 4 | } | 92 | 216k | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 216k | return true; | 94 | 216k | } |
bool draco::DecoderBuffer::Peek<unsigned long>(unsigned long*) Line | Count | Source | 87 | 190 | bool Peek(T *out_val) { | 88 | 190 | const size_t size_to_decode = sizeof(T); | 89 | 190 | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 0 | return false; // Buffer overflow. | 91 | 0 | } | 92 | 190 | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 190 | return true; | 94 | 190 | } |
bool draco::DecoderBuffer::Peek<float>(float*) Line | Count | Source | 87 | 63 | bool Peek(T *out_val) { | 88 | 63 | const size_t size_to_decode = sizeof(T); | 89 | 63 | if (data_size_ < static_cast<int64_t>(pos_ + size_to_decode)) { | 90 | 0 | return false; // Buffer overflow. | 91 | 0 | } | 92 | 63 | memcpy(out_val, (data_ + pos_), size_to_decode); | 93 | 63 | return true; | 94 | 63 | } |
|
95 | | |
96 | 0 | bool Peek(void *out_data, size_t size_to_peek) { |
97 | 0 | if (data_size_ < static_cast<int64_t>(pos_ + size_to_peek)) { |
98 | 0 | return false; // Buffer overflow. |
99 | 0 | } |
100 | 0 | memcpy(out_data, (data_ + pos_), size_to_peek); |
101 | 0 | return true; |
102 | 0 | } |
103 | | |
104 | | // Discards #bytes from the input buffer. |
105 | 5.93k | void Advance(int64_t bytes) { pos_ += bytes; } |
106 | | |
107 | | // Moves the parsing position to a specific offset from the beginning of the |
108 | | // input data. |
109 | 0 | void StartDecodingFrom(int64_t offset) { pos_ = offset; } |
110 | | |
111 | 801 | void set_bitstream_version(uint16_t version) { bitstream_version_ = version; } |
112 | | |
113 | | // Returns the data array at the current decoder position. |
114 | 6.61k | const char *data_head() const { return data_ + pos_; } |
115 | 78.9k | int64_t remaining_size() const { return data_size_ - pos_; } |
116 | 286 | int64_t decoded_size() const { return pos_; } |
117 | 23.2M | bool bit_decoder_active() const { return bit_mode_; } |
118 | | |
119 | | // Returns the bitstream associated with the data. Returns 0 if unknown. |
120 | 2.12M | uint16_t bitstream_version() const { return bitstream_version_; } |
121 | | |
122 | | private: |
123 | | // Internal helper class to decode bits from a bit buffer. |
124 | | class BitDecoder { |
125 | | public: |
126 | | BitDecoder(); |
127 | | ~BitDecoder(); |
128 | | |
129 | | // Sets the bit buffer to |b|. |s| is the size of |b| in bytes. |
130 | 426 | inline void reset(const void *b, size_t s) { |
131 | 426 | bit_offset_ = 0; |
132 | 426 | bit_buffer_ = static_cast<const uint8_t *>(b); |
133 | 426 | bit_buffer_end_ = bit_buffer_ + s; |
134 | 426 | } |
135 | | |
136 | | // Returns number of bits decoded so far. |
137 | 332 | inline uint64_t BitsDecoded() const { |
138 | 332 | return static_cast<uint64_t>(bit_offset_); |
139 | 332 | } |
140 | | |
141 | | // Return number of bits available for decoding |
142 | 0 | inline uint64_t AvailBits() const { |
143 | 0 | return ((bit_buffer_end_ - bit_buffer_) * 8) - bit_offset_; |
144 | 0 | } |
145 | | |
146 | 0 | inline uint32_t EnsureBits(int k) { |
147 | 0 | DRACO_DCHECK_LE(k, 24); |
148 | 0 | DRACO_DCHECK_LE(static_cast<uint64_t>(k), AvailBits()); |
149 | 0 |
|
150 | 0 | uint32_t buf = 0; |
151 | 0 | for (int i = 0; i < k; ++i) { |
152 | 0 | buf |= PeekBit(i) << i; |
153 | 0 | } |
154 | 0 | return buf; // Okay to return extra bits |
155 | 0 | } |
156 | | |
157 | 0 | inline void ConsumeBits(int k) { bit_offset_ += k; } |
158 | | |
159 | | // Returns |nbits| bits in |x|. |
160 | 23.2M | inline bool GetBits(uint32_t nbits, uint32_t *x) { |
161 | 23.2M | if (nbits > 32) { |
162 | 0 | return false; |
163 | 0 | } |
164 | 23.2M | uint32_t value = 0; |
165 | 54.9M | for (uint32_t bit = 0; bit < nbits; ++bit) { |
166 | 31.6M | value |= GetBit() << bit; |
167 | 31.6M | } |
168 | 23.2M | *x = value; |
169 | 23.2M | return true; |
170 | 23.2M | } |
171 | | |
172 | | private: |
173 | | // TODO(fgalligan): Add support for error reporting on range check. |
174 | | // Returns one bit from the bit buffer. |
175 | 31.6M | inline int GetBit() { |
176 | 31.6M | const size_t off = bit_offset_; |
177 | 31.6M | const size_t byte_offset = off >> 3; |
178 | 31.6M | const int bit_shift = static_cast<int>(off & 0x7); |
179 | 31.6M | if (bit_buffer_ + byte_offset < bit_buffer_end_) { |
180 | 27.0M | const int bit = (bit_buffer_[byte_offset] >> bit_shift) & 1; |
181 | 27.0M | bit_offset_ = off + 1; |
182 | 27.0M | return bit; |
183 | 27.0M | } |
184 | 4.62M | return 0; |
185 | 31.6M | } |
186 | | |
187 | 0 | inline int PeekBit(int offset) { |
188 | 0 | const size_t off = bit_offset_ + offset; |
189 | 0 | const size_t byte_offset = off >> 3; |
190 | 0 | const int bit_shift = static_cast<int>(off & 0x7); |
191 | 0 | if (bit_buffer_ + byte_offset < bit_buffer_end_) { |
192 | 0 | const int bit = (bit_buffer_[byte_offset] >> bit_shift) & 1; |
193 | 0 | return bit; |
194 | 0 | } |
195 | 0 | return 0; |
196 | 0 | } |
197 | | |
198 | | const uint8_t *bit_buffer_; |
199 | | const uint8_t *bit_buffer_end_; |
200 | | size_t bit_offset_; |
201 | | }; |
202 | | friend class BufferBitCodingTest; |
203 | | |
204 | | const char *data_; |
205 | | int64_t data_size_; |
206 | | |
207 | | // Current parsing position of the decoder. |
208 | | int64_t pos_; |
209 | | BitDecoder bit_decoder_; |
210 | | bool bit_mode_; |
211 | | uint16_t bitstream_version_; |
212 | | }; |
213 | | |
214 | | } // namespace draco |
215 | | |
216 | | #endif // DRACO_CORE_DECODER_BUFFER_H_ |