libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
bit_stream_writer.hpp
1 #pragma once
2 
3 #include "fly/types/bit_stream/detail/bit_stream.hpp"
4 #include "fly/types/bit_stream/detail/concepts.hpp"
5 #include "fly/types/bit_stream/types.hpp"
6 #include "fly/types/numeric/endian.hpp"
7 
8 #include <bit>
9 #include <ostream>
10 
11 namespace fly {
12 
24 {
25 public:
31  explicit BitStreamWriter(std::ostream &stream) noexcept;
32 
40  void write_word(word_type word);
41 
49  void write_byte(byte_type byte);
50 
62  template <detail::BitStreamInteger DataType>
63  void write_bits(DataType bits, byte_type size);
64 
70  bool finish();
71 
72 private:
78  void flush_header(byte_type remainder);
79 
83  void flush_buffer();
84 
93  template <detail::BitStreamInteger DataType>
94  void flush(const DataType &buffer, byte_type bytes);
95 
96  std::ostream &m_stream;
97 };
98 
99 //==================================================================================================
100 template <detail::BitStreamInteger DataType>
101 void BitStreamWriter::write_bits(DataType bits, byte_type size)
102 {
103  // If there are more bits to write than are available in the byte buffer, break the bits into
104  // two chunks.
105  if (size > m_position)
106  {
107  const byte_type rshift = size - m_position;
108 
109  // Fill the remainder of the byte buffer with as many bits as are available, and flush it
110  // onto the stream.
111  m_buffer |= static_cast<buffer_type>(bits) >> rshift;
112  flush_buffer();
113 
114  // Then update the input bits to retain only those bits that have not been written yet.
115  bits &= bit_mask<DataType>(rshift);
116  size = rshift;
117  }
118 
119  const byte_type lshift = m_position - size;
120 
121  m_buffer |= static_cast<buffer_type>(bits) << lshift;
122  m_position = lshift;
123 }
124 
125 //==================================================================================================
126 template <detail::BitStreamInteger DataType>
127 void BitStreamWriter::flush(const DataType &buffer, byte_type bytes)
128 {
129  if (m_stream)
130  {
131  const DataType data = endian_swap_if_non_native<std::endian::big>(buffer);
132 
133  m_stream_buffer->sputn(
134  reinterpret_cast<const std::ios::char_type *>(&data),
135  static_cast<std::streamsize>(bytes));
136  }
137 }
138 
139 } // namespace fly
Definition: bit_stream_writer.hpp:24
bool finish()
Definition: bit_stream_writer.cpp:29
void write_byte(byte_type byte)
Definition: bit_stream_writer.cpp:23
void write_bits(DataType bits, byte_type size)
Definition: bit_stream_writer.hpp:101
void write_word(word_type word)
Definition: bit_stream_writer.cpp:17
BitStreamWriter(std::ostream &stream) noexcept
Definition: bit_stream_writer.cpp:9
Definition: bit_stream.hpp:34