Coverage Report

Created: 2024-09-08 06:47

/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_