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 #ifndef SRC_BIT_WRITER_H_
6 #define SRC_BIT_WRITER_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 
11 #include "puffin/src/include/puffin/common.h"
12 
13 namespace puffin {
14 // An abstract class for writing bits into a deflate stream. For more
15 // information on the pattern of writing, refer to RFC1951 at
16 // https://www.ietf.org/rfc/rfc1951.txt
17 class BitWriterInterface {
18  public:
19   virtual ~BitWriterInterface() = default;
20 
21   // Puts least significant |nbits| bits of |bits| into the cache and flush it
22   // if necessary. If it returns false (e.g. not enough output buffer), then it
23   // may write part of |bits| into the output which will be unknown.
24   //
25   // |nbits| IN  The number of bits to write in the output.
26   // |bits|  IN  The bit values to write into the output.
27   virtual bool WriteBits(size_t nbits, uint32_t bits) = 0;
28 
29   // It first flushes the cache and then puts the |nbytes| bytes from |buffer|
30   // into the output buffer. User should make sure there that the number of bits
31   // written into the |BitWriter| before this call is a multiplication of
32   // eight. Otherwise it is errornous. This can be achieved by calling
33   // |WriteBoundaryBits| or |WriteBits| (if the user is tracking the number of
34   // bits written).
35   //
36   // |nbytes|  IN  The number of bytes to read using |read_fn| and write into
37   //               the output.
38   // |read_fn| IN  A function to read bytes from.
39   virtual bool WriteBytes(
40       size_t nbytes,
41       const std::function<bool(uint8_t* buffer, size_t count)>& read_fn) = 0;
42 
43   // Puts enough least-significant bits from |bits| into output until the
44   // beginning of the next Byte is reached. The number of bits to write into
45   // output will be determined by how many bits are needed to reach the
46   // boundary.
47   //
48   // |bits| IN  The value of boundary bits.
49   virtual bool WriteBoundaryBits(uint8_t bits) = 0;
50 
51   // Flushes the cache into the output buffer. It writes 0 for extra bits that
52   // comes without data at the end.
53   //
54   // Returns false if it fails to flush.
55   virtual bool Flush() = 0;
56 
57   // Returns the number of bytes written to the ouput including the cached
58   // bytes.
59   virtual size_t Size() const = 0;
60 };
61 
62 // A raw buffer implementation of |BitWriterInterface|.
63 class BufferBitWriter : public BitWriterInterface {
64  public:
65   // Sets the beginning of the buffer that the users wants to write into.
66   //
67   // |out_buf|  IN  The output buffer
68   // |out_size| IN  The size of the output buffer
BufferBitWriter(uint8_t * out_buf,size_t out_size)69   BufferBitWriter(uint8_t* out_buf, size_t out_size)
70       : out_buf_(out_buf),
71         out_size_(out_size),
72         index_(0),
73         out_holder_(0),
74         out_holder_bits_(0) {}
75 
76   ~BufferBitWriter() override = default;
77 
78   bool WriteBits(size_t nbits, uint32_t bits) override;
79   bool WriteBytes(size_t nbytes,
80                   const std::function<bool(uint8_t* buffer, size_t count)>&
81                       read_fn) override;
82   bool WriteBoundaryBits(uint8_t bits) override;
83   bool Flush() override;
84   size_t Size() const override;
85 
86  private:
87   // The output buffer.
88   uint8_t* out_buf_;
89 
90   // The number of bytes in |out_buf_|.
91   uint64_t out_size_;
92 
93   // The index to the next byte to write into.
94   uint64_t index_;
95 
96   // A temporary buffer to keep the bits going out.
97   uint32_t out_holder_;
98 
99   // The number of bits in |out_holder_|.
100   uint8_t out_holder_bits_;
101 
102   DISALLOW_COPY_AND_ASSIGN(BufferBitWriter);
103 };
104 
105 }  // namespace puffin
106 
107 #endif  // SRC_BIT_WRITER_H_
108