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/logging.h"
10 
11 namespace puffin {
12 
WriteBits(size_t nbits,uint32_t bits)13 bool 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 
WriteBytes(size_t nbytes,const std::function<bool (uint8_t * buffer,size_t count)> & read_fn)33 bool 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 
WriteBoundaryBits(uint8_t bits)45 bool BufferBitWriter::WriteBoundaryBits(uint8_t bits) {
46   return WriteBits((8 - (out_holder_bits_ & 7)) & 7, bits);
47 }
48 
Flush()49 bool 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 
Size() const59 size_t BufferBitWriter::Size() const {
60   return index_;
61 }
62 
63 }  // namespace puffin
64