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