// Copyright 2016 The Draco Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef DRACO_CORE_ENCODER_BUFFER_H_ #define DRACO_CORE_ENCODER_BUFFER_H_ #include #include #include "core/bit_coder.h" namespace draco { // Class representing a buffer that can be used for either for byte-aligned // encoding of arbitrary data structures or for encoding of varialble-length // bit data. class EncoderBuffer { public: EncoderBuffer(); void Clear(); void Resize(int64_t nbytes); // Start encoding a bit sequence. A maximum size of the sequence needs to // be known upfront. // If encode_size is true, the size of encoded bit sequence is stored before // the sequence. Decoder can then use this size to skip over the bit sequence // if needed. // Returns false on error. bool StartBitEncoding(int64_t required_bits, bool encode_size); // End the encoding of the bit sequence and return to the default byte-aligned // encoding. void EndBitEncoding(); // Encode up to 32 bits into the buffer. Can be called only in between // StartBitEncoding and EndBitEncoding. Otherwise returns false. // TODO(hemmer): Swap arguments to make it consistent with DecoderBuffer. bool EncodeBits32(uint32_t value, int nbits) { if (!bit_encoder_active()) return false; bit_encoder_->PutBits(value, nbits); return true; } // Encode an arbitrary data type. // Can be used only when we are not encoding a bit-sequence. // Returns false when the value couldn't be encoded. template bool Encode(const T &data) { if (bit_encoder_active()) return false; const uint8_t *src_data = reinterpret_cast(&data); buffer_.insert(buffer_.end(), src_data, src_data + sizeof(T)); return true; } bool Encode(const void *data, size_t data_size) { if (bit_encoder_active()) return false; const uint8_t *src_data = reinterpret_cast(data); buffer_.insert(buffer_.end(), src_data, src_data + data_size); return true; } bool bit_encoder_active() const { return bit_encoder_reserved_bytes_ > 0; } const char *data() const { return buffer_.data(); } size_t size() const { return buffer_.size(); } std::vector *buffer() { return &buffer_; } BitEncoder *bit_encoder() { return bit_encoder_.get(); } private: // All data is stored in this vector. std::vector buffer_; // Bit encoder is used when encoding variable-length bit data. // TODO(ostava): Currently encoder needs to be recreated each time // StartBitEncoding method is called. This is not necessary if BitEncoder // supported reset function which can easily added but let's leave that for // later. std::unique_ptr bit_encoder_; // The number of bytes reserved for bit encoder. // Values > 0 indicate we are in the bit encoding mode. int64_t bit_encoder_reserved_bytes_; // Flag used indicating that we need to store the length of the currently // processed bit sequence. bool encode_bit_sequence_size_; }; } // namespace draco #endif // DRACO_CORE_ENCODER_BUFFER_H_