BitStream
array_traits.h
Go to the documentation of this file.
1 #pragma once
2 #include "../utility/assert.h"
3 #include "../utility/meta.h"
4 #include "../utility/parameter.h"
5 
6 #include "../stream/serialize_traits.h"
7 
8 #include "../traits/bool_trait.h"
9 #include "../traits/integral_traits.h"
10 
11 #include <cstdint>
12 
13 namespace bitstream
14 {
19  template<typename T, typename = T>
20  struct array_subset;
21 
27  template<typename T, typename Trait>
28  struct serialize_traits<array_subset<T, Trait>>
29  {
30  private:
31  template<uint32_t Min, uint32_t Max, typename Stream>
32  static bool serialize_difference(Stream& stream, int& previous, int& current, uint32_t& difference)
33  {
34  bool use_bits;
35  if constexpr (Stream::writing)
36  use_bits = difference <= Max;
37  BS_ASSERT(stream.template serialize<bool>(use_bits));
38  if (use_bits)
39  {
40  using bounded_trait = bounded_int<uint32_t, Min, Max>;
41 
42  BS_ASSERT(stream.template serialize<bounded_trait>(difference));
43  if constexpr (Stream::reading)
44  current = previous + difference;
45  previous = current;
46  return true;
47  }
48 
49  return false;
50  }
51 
52  template<typename Stream>
53  static bool serialize_index(Stream& stream, int& previous, int& current, int max_size)
54  {
55  uint32_t difference;
56  if constexpr (Stream::writing)
57  {
58  BS_ASSERT(previous < current);
59  difference = current - previous;
60  BS_ASSERT(difference > 0);
61  }
62 
63  // +1 (1 bit)
64  bool plus_one;
65  if constexpr (Stream::writing)
66  plus_one = difference == 1;
67  BS_ASSERT(stream.template serialize<bool>(plus_one));
68  if (plus_one)
69  {
70  if constexpr (Stream::reading)
71  current = previous + 1;
72  previous = current;
73  return true;
74  }
75 
76  // [+2,5] -> [0,3] (2 bits)
77  if (serialize_difference<2, 5>(stream, previous, current, difference))
78  return true;
79 
80  // [6,13] -> [0,7] (3 bits)
81  if (serialize_difference<6, 13>(stream, previous, current, difference))
82  return true;
83 
84  // [14,29] -> [0,15] (4 bits)
85  if (serialize_difference<14, 29>(stream, previous, current, difference))
86  return true;
87 
88  // [30,61] -> [0,31] (5 bits)
89  if (serialize_difference<30, 61>(stream, previous, current, difference))
90  return true;
91 
92  // [62,125] -> [0,63] (6 bits)
93  if (serialize_difference<62, 125>(stream, previous, current, difference))
94  return true;
95 
96  // [126,MaxObjects+1]
97  BS_ASSERT(stream.template serialize<uint32_t>(difference, 126, max_size));
98  if constexpr (Stream::reading)
99  current = previous + difference;
100  previous = current;
101  return true;
102  }
103 
104  public:
116  template<typename Stream, typename Compare, typename... Args>
118  static serialize(Stream& writer, T* values, int max_size, Compare compare, Args&&... args) noexcept
119  {
120  int prev_index = -1;
121  for (int index = 0; index < max_size; index++)
122  {
123  if (!compare(values[index]))
124  continue;
125 
126  BS_ASSERT(serialize_index(writer, prev_index, index, max_size));
127 
128  BS_ASSERT(writer.template serialize<Trait>(values[index], std::forward<Args>(args)...));
129  }
130 
131  BS_ASSERT(serialize_index(writer, prev_index, max_size, max_size));
132 
133  return true;
134  }
135 
146  template<typename Stream, typename... Args>
148  static serialize(Stream& reader, T* values, int max_size, Args&&... args) noexcept
149  {
150  int prev_index = -1;
151  int index = 0;
152  while (true)
153  {
154  BS_ASSERT(serialize_index(reader, prev_index, index, max_size));
155 
156  if (index == max_size)
157  break;
158 
159  BS_ASSERT(reader.template serialize<Trait>(values[index], std::forward<Args>(args)...));
160  }
161 
162  return true;
163  }
164  };
165 }
#define BS_ASSERT(x)
Definition: assert.h:15
std::enable_if_t< T::writing, R > is_writing_t
Definition: meta.h:25
std::enable_if_t< T::reading, R > is_reading_t
Definition: meta.h:28
Definition: bounded_range.h:28
Wrapper type for subsets of arrays.
Definition: array_traits.h:20
Wrapper type for compiletime known integer bounds.
Definition: integral_traits.h:20
static utility::is_reading_t< Stream > serialize(Stream &reader, T *values, int max_size, Args &&... args) noexcept
Writes a subset of a serialized array into values.
Definition: array_traits.h:148
static utility::is_writing_t< Stream > serialize(Stream &writer, T *values, int max_size, Compare compare, Args &&... args) noexcept
Writes a subset of the array values into the writer.
Definition: array_traits.h:118
A class for specializing trait serialization functions.
Definition: serialize_traits.h:11