BitStream
string_traits.h
Go to the documentation of this file.
1 #pragma once
2 #include "../utility/assert.h"
3 #include "../utility/bits.h"
4 #include "../utility/meta.h"
5 #include "../utility/parameter.h"
6 
7 #include "../stream/serialize_traits.h"
8 
9 #include <cstdint>
10 #include <string>
11 
12 namespace bitstream
13 {
17  template<typename T, size_t I>
19 
20 #pragma region const char*
24  template<>
25  struct serialize_traits<const char*>
26  {
34  template<typename Stream>
36  static serialize(Stream& writer, const char* value, uint32_t max_size) noexcept
37  {
38  uint32_t length = static_cast<uint32_t>(std::char_traits<char>::length(value));
39 
40  BS_ASSERT(length < max_size);
41 
42  if (length == 0)
43  return true;
44 
45  uint32_t num_bits = utility::bits_to_represent(max_size);
46 
47  BS_ASSERT(writer.serialize_bits(length, num_bits));
48 
49  return writer.serialize_bytes(reinterpret_cast<const uint8_t*>(value), length * 8);
50  }
51 
59  template<typename Stream>
61  static serialize(Stream& reader, char* value, uint32_t max_size) noexcept
62  {
63  uint32_t num_bits = utility::bits_to_represent(max_size);
64 
65  uint32_t length;
66  BS_ASSERT(reader.serialize_bits(length, num_bits));
67 
68  BS_ASSERT(length < max_size);
69 
70  if (length == 0)
71  {
72  value[0] = '\0';
73  return true;
74  }
75 
76  BS_ASSERT(reader.serialize_bytes(reinterpret_cast<uint8_t*>(value), length * 8));
77 
78  value[length] = '\0';
79 
80  return true;
81  }
82  };
83 
88  template<size_t MaxSize>
89  struct serialize_traits<bounded_string<const char*, MaxSize>>
90  {
97  template<typename Stream>
99  static serialize(Stream& writer, const char* value) noexcept
100  {
101  uint32_t length = static_cast<uint32_t>(std::char_traits<char>::length(value));
102 
103  BS_ASSERT(length < MaxSize);
104 
105  if (length == 0)
106  return true;
107 
108  constexpr uint32_t num_bits = utility::bits_to_represent(MaxSize);
109 
110  BS_ASSERT(writer.serialize_bits(length, num_bits));
111 
112  return writer.serialize_bytes(reinterpret_cast<const uint8_t*>(value), length * 8);
113  }
114 
121  template<typename Stream>
123  static serialize(Stream& reader, char* value) noexcept
124  {
125  constexpr uint32_t num_bits = utility::bits_to_represent(MaxSize);
126 
127  uint32_t length;
128  BS_ASSERT(reader.serialize_bits(length, num_bits));
129 
130  BS_ASSERT(length < MaxSize);
131 
132  if (length == 0)
133  {
134  value[0] = '\0';
135  return true;
136  }
137 
138  BS_ASSERT(reader.serialize_bytes(reinterpret_cast<uint8_t*>(value), length * 8));
139 
140  value[length] = '\0';
141 
142  return true;
143  }
144  };
145 #pragma endregion
146 
147 #ifdef __cpp_char8_t
151  template<>
152  struct serialize_traits<const char8_t*>
153  {
161  template<typename Stream>
162  typename utility::is_writing_t<Stream>
163  static serialize(Stream& writer, const char8_t* value, uint32_t max_size) noexcept
164  {
165  uint32_t length = static_cast<uint32_t>(std::char_traits<char8_t>::length(value));
166 
167  BS_ASSERT(length < max_size);
168 
169  if (length == 0)
170  return true;
171 
172  uint32_t num_bits = utility::bits_to_represent(max_size);
173 
174  BS_ASSERT(writer.serialize_bits(length, num_bits));
175 
176  return writer.serialize_bytes(reinterpret_cast<const uint8_t*>(value), length * 8);
177  }
178 
186  template<typename Stream>
187  typename utility::is_reading_t<Stream>
188  static serialize(Stream& reader, char8_t* value, uint32_t max_size) noexcept
189  {
190  uint32_t num_bits = utility::bits_to_represent(max_size);
191 
192  uint32_t length;
193  BS_ASSERT(reader.serialize_bits(length, num_bits));
194 
195  BS_ASSERT(length < max_size);
196 
197  if (length == 0)
198  {
199  value[0] = '\0';
200  return true;
201  }
202 
203  BS_ASSERT(reader.serialize_bytes(reinterpret_cast<uint8_t*>(value), length * 8));
204 
205  value[length] = '\0';
206 
207  return true;
208  }
209  };
210 #endif
211 
212 #pragma region std::basic_string
219  template<typename T, typename Traits, typename Alloc>
220  struct serialize_traits<std::basic_string<T, Traits, Alloc>>
221  {
229  template<typename Stream>
231  static serialize(Stream& writer, in<std::basic_string<T, Traits, Alloc>> value, uint32_t max_size) noexcept
232  {
233  uint32_t length = static_cast<uint32_t>(value.size());
234 
235  BS_ASSERT(length <= max_size);
236 
237  uint32_t num_bits = utility::bits_to_represent(max_size);
238 
239  BS_ASSERT(writer.serialize_bits(length, num_bits));
240 
241  if (length == 0)
242  return true;
243 
244  return writer.serialize_bytes(reinterpret_cast<const uint8_t*>(value.c_str()), length * sizeof(T) * 8);
245  }
246 
254  template<typename Stream>
256  static serialize(Stream& reader, out<std::basic_string<T, Traits, Alloc>> value, uint32_t max_size)
257  {
258  uint32_t num_bits = utility::bits_to_represent(max_size);
259 
260  uint32_t length;
261  BS_ASSERT(reader.serialize_bits(length, num_bits));
262 
263  BS_ASSERT(length <= max_size);
264 
265  if (length == 0)
266  {
267  value->clear();
268  return true;
269  }
270 
271  value->resize(length);
272 
273  BS_ASSERT(reader.serialize_bytes(reinterpret_cast<uint8_t*>(value->data()), length * sizeof(T) * 8));
274 
275  return true;
276  }
277  };
278 
286  template<typename T, typename Traits, typename Alloc, size_t MaxSize>
287  struct serialize_traits<bounded_string<std::basic_string<T, Traits, Alloc>, MaxSize>>
288  {
295  template<typename Stream>
297  static serialize(Stream& writer, in<std::basic_string<T, Traits, Alloc>> value) noexcept
298  {
299  uint32_t length = static_cast<uint32_t>(value.size());
300 
301  BS_ASSERT(length <= MaxSize);
302 
303  constexpr uint32_t num_bits = utility::bits_to_represent(MaxSize);
304 
305  BS_ASSERT(writer.serialize_bits(length, num_bits));
306 
307  if (length == 0)
308  return true;
309 
310  return writer.serialize_bytes(reinterpret_cast<const uint8_t*>(value.c_str()), length * sizeof(T) * 8);
311  }
312 
319  template<typename Stream>
321  static serialize(Stream& reader, out<std::basic_string<T, Traits, Alloc>> value)
322  {
323  constexpr uint32_t num_bits = utility::bits_to_represent(MaxSize);
324 
325  uint32_t length;
326  BS_ASSERT(reader.serialize_bits(length, num_bits));
327 
328  BS_ASSERT(length <= MaxSize);
329 
330  if (length == 0)
331  {
332  value->clear();
333  return true;
334  }
335 
336  value->resize(length);
337 
338  BS_ASSERT(reader.serialize_bytes(reinterpret_cast<uint8_t*>(value->data()), length * sizeof(T) * 8));
339 
340  return true;
341  }
342  };
343 #pragma endregion
344 }
#define BS_ASSERT(x)
Definition: assert.h:15
Definition: parameter.h:64
std::enable_if_t< T::writing, R > is_writing_t
Definition: meta.h:25
constexpr uint32_t bits_to_represent(uintmax_t n)
Definition: bits.h:8
std::enable_if_t< T::reading, R > is_reading_t
Definition: meta.h:28
Definition: bounded_range.h:28
std::conditional_t<(sizeof(T)<=16 &&std::is_trivially_copy_constructible_v< T >), std::add_const_t< T >, std::add_lvalue_reference_t< std::add_const_t< T > >> in
Passes by const or const reference depending on size.
Definition: parameter.h:94
Wrapper type for compiletime known string max_size.
Definition: string_traits.h:18
static utility::is_writing_t< Stream > serialize(Stream &writer, const char *value) noexcept
Writes a c-style string into the writer.
Definition: string_traits.h:99
static utility::is_reading_t< Stream > serialize(Stream &reader, char *value) noexcept
Read a c-style string from the reader into value.
Definition: string_traits.h:123
static utility::is_writing_t< Stream > serialize(Stream &writer, in< std::basic_string< T, Traits, Alloc >> value) noexcept
Writes a string into the writer.
Definition: string_traits.h:297
static utility::is_reading_t< Stream > serialize(Stream &reader, out< std::basic_string< T, Traits, Alloc >> value)
Reads a string from the reader into value.
Definition: string_traits.h:321
static utility::is_reading_t< Stream > serialize(Stream &reader, char *value, uint32_t max_size) noexcept
Read a c-style string from the reader into value.
Definition: string_traits.h:61
static utility::is_writing_t< Stream > serialize(Stream &writer, const char *value, uint32_t max_size) noexcept
Writes a c-style string into the writer.
Definition: string_traits.h:36
static utility::is_reading_t< Stream > serialize(Stream &reader, out< std::basic_string< T, Traits, Alloc >> value, uint32_t max_size)
Reads a string from the reader into value.
Definition: string_traits.h:256
static utility::is_writing_t< Stream > serialize(Stream &writer, in< std::basic_string< T, Traits, Alloc >> value, uint32_t max_size) noexcept
Writes a string into the writer.
Definition: string_traits.h:231
A class for specializing trait serialization functions.
Definition: serialize_traits.h:11