framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bit_stream.hpp
Go to the documentation of this file.
1 // Copyright (C) 2012 iwg molw5
2 // For conditions of distribution and use, see copyright notice in COPYING
3 
13 #pragma once
14 
15 #include <cstdint>
16 #include <cassert>
17 #include <type_traits>
18 #include <climits>
19 
23 
24 namespace framework
25 {
26  namespace serializable
27  {
59  template <typename Stream, typename Block>
60  class bit_stream : private std::reference_wrapper <Stream>
61  {
62  private:
63  using buffer_type = typename std::make_unsigned <type_extractor <Block>>::type;
64  enum{ block_bytes = sizeof(buffer_type) };
65  enum{ block_bits = CHAR_BIT*block_bytes };
66  enum{ block_mask = static_cast <buffer_type> (~static_cast <buffer_type> (0)) };
67  enum{ byte_mask = static_cast <unsigned char> (~static_cast <unsigned char> (0)) };
69 
70  template <std::size_t N>
71  struct read_handler_fixed;
72 
73  template <std::size_t N, std::size_t Buffer, typename Enabler = void>
74  struct read_bits_impl;
75 
76  template <std::size_t>
77  struct write_handler_fixed;
78 
79  template <std::size_t N, std::size_t Buffer, typename Enabler = void>
80  struct write_bits_impl;
81 
82  struct read_handler_dynamic;
83  struct write_handler_dynamic;
84 
85  public:
92  bit_stream (Stream& s)
93  : std::reference_wrapper <Stream> (s)
94  {
95  }
96 
100  template <std::size_t N>
101  bool read (char* s)
102  {
103  for (std::size_t i=0; i < N; ++i, ++s)
104  if (!read_bits <8> (*s))
105  return false;
106 
107  return true;
108  }
109 
113  bool read (char* s, std::size_t n)
114  {
115  for (std::size_t i=0; i < n; ++i, ++s)
116  if (!read_bits <8> (*s))
117  return false;
118 
119  return true;
120  }
121 
125  template <std::size_t N>
126  bool write (char const* s)
127  {
128  for (std::size_t i=0; i < N; ++i, ++s)
129  if (!write_bits <8> (*s))
130  return false;
131 
132  return true;
133  }
134 
138  bool write (char const* s, std::size_t n)
139  {
140  for (std::size_t i=0; i < n; ++i, ++s)
141  if (!write_bits <8> (*s))
142  return false;
143 
144  return true;
145  }
146 
156  template <std::size_t N, typename T>
157  bool read_bits (T& t)
158  {
159  auto& value = reinterpret_cast <typename std::make_unsigned <T>::type&> (t);
160  return variadic_switch_return <case_list> (read_handler_fixed <N> {}, p_iInputBlockBits, *this, value);
161  }
162 
172  template <typename T>
173  bool read_bits (T& t, std::size_t n)
174  {
175  auto& value = reinterpret_cast <typename std::make_unsigned <T>::type&> (t);
176  return variadic_switch_return <case_list> (read_handler_dynamic{}, p_iInputBlockBits, *this, value, n);
177  }
178 
188  template <std::size_t N, typename T>
189  bool write_bits (T const& t)
190  {
191  auto const& value = reinterpret_cast <typename std::make_unsigned <T>::type const&> (t);
192  return variadic_switch_return <case_list> (write_handler_fixed <N> (), p_iOutputBlockBits, *this, value);
193  }
194 
204  template <typename T>
205  bool write_bits (T const& t, std::size_t n)
206  {
207  auto const& value = reinterpret_cast <typename std::make_unsigned <T>::type const&> (t);
208  return variadic_switch_return <case_list> (write_handler_dynamic{}, p_iOutputBlockBits, *this, value, n);
209  }
210 
218  bool flush ()
219  {
220  if (p_iOutputBlockBits < block_bits)
221  {
222  auto const value = static_cast <type_extractor <Block>> (p_iOutputBlock);
223  if (!dispatch_write <Block> (value, this->get()))
224  return false;
225 
226  p_iOutputBlock = 0;
227  p_iOutputBlockBits = block_bits;
228  }
229 
230  return true;
231  }
232 
233  private:
234  buffer_type p_iInputBlock {0};
235  std::size_t p_iInputBlockBits {0};
236 
237  buffer_type p_iOutputBlock {0};
238  std::size_t p_iOutputBlockBits {block_bits};
239  };
240  }
241 }
242 
243 #include <framework/serializable/streams/bit_stream.inl>