1// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "puffin/src/bit_writer.h"
6
7#include <algorithm>
8
9#include "puffin/src/set_errors.h"
10
11namespace puffin {
12
13bool BufferBitWriter::WriteBits(size_t nbits, uint32_t bits) {
14  TEST_AND_RETURN_FALSE(((out_size_ - index_) * 8) - out_holder_bits_ >= nbits);
15  TEST_AND_RETURN_FALSE(nbits <= sizeof(bits) * 8);
16  while (nbits > 0) {
17    while (out_holder_bits_ >= 8) {
18      out_buf_[index_++] = out_holder_ & 0x000000FF;
19      out_holder_ >>= 8;
20      out_holder_bits_ -= 8;
21    }
22    while (out_holder_bits_ < 24 && nbits > 0) {
23      out_holder_ |= (bits & 0x000000FF) << out_holder_bits_;
24      auto min = std::min(nbits, static_cast<size_t>(8));
25      out_holder_bits_ += min;
26      bits >>= min;
27      nbits -= min;
28    }
29  }
30  return true;
31}
32
33bool BufferBitWriter::WriteBytes(
34    size_t nbytes,
35    const std::function<bool(uint8_t* buffer, size_t count)>& read_fn) {
36  TEST_AND_RETURN_FALSE(((out_size_ - index_) * 8) - out_holder_bits_ >=
37                        (nbytes * 8));
38  TEST_AND_RETURN_FALSE(out_holder_bits_ % 8 == 0);
39  TEST_AND_RETURN_FALSE(Flush());
40  TEST_AND_RETURN_FALSE(read_fn(&out_buf_[index_], nbytes));
41  index_ += nbytes;
42  return true;
43}
44
45bool BufferBitWriter::WriteBoundaryBits(uint8_t bits) {
46  return WriteBits((8 - (out_holder_bits_ & 7)) & 7, bits);
47}
48
49bool BufferBitWriter::Flush() {
50  TEST_AND_RETURN_FALSE(WriteBoundaryBits(0));
51  while (out_holder_bits_ > 0) {
52    out_buf_[index_++] = out_holder_ & 0x000000FF;
53    out_holder_ >>= 8;
54    out_holder_bits_ -= 8;
55  }
56  return true;
57}
58
59size_t BufferBitWriter::Size() const {
60  return index_;
61}
62
63}  // namespace puffin
64