BitStream
Loading...
Searching...
No Matches
integral_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 <limits>
11#include <type_traits>
12
13namespace bitstream
14{
19 template<typename T, T = (std::numeric_limits<T>::min)(), T = (std::numeric_limits<T>::max)()>
21
22#pragma region const integral types
29 template<typename T, T Min, T Max>
30 struct serialize_traits<bounded_int<T, Min, Max>, typename std::enable_if_t<std::is_integral_v<T> && !std::is_const_v<T>>>
31 {
32 static_assert(sizeof(T) <= 8, "Integers larger than 8 bytes are currently not supported. You will have to write this functionality yourself");
33
40 template<typename Stream>
42 static serialize(Stream& writer, in<T> value) noexcept
43 {
44 static_assert(Min < Max);
45
46 BS_ASSERT(value >= Min && value <= Max);
47
48 constexpr uint32_t num_bits = utility::bits_in_range(Min, Max);
49
50 static_assert(num_bits <= sizeof(T) * 8);
51
52 if constexpr (sizeof(T) > 4 && num_bits > 32)
53 {
54 // If the given range is bigger than a word (32 bits)
55 uint32_t unsigned_value = static_cast<uint32_t>(value - Min);
56 BS_ASSERT(writer.serialize_bits(unsigned_value, 32));
57
58 unsigned_value = static_cast<uint32_t>((value - Min) >> 32);
59 BS_ASSERT(writer.serialize_bits(unsigned_value, num_bits - 32));
60 }
61 else
62 {
63 // If the given range is smaller than or equal to a word (32 bits)
64 uint32_t unsigned_value = static_cast<uint32_t>(value - Min);
65 BS_ASSERT(writer.serialize_bits(unsigned_value, num_bits));
66 }
67
68 return true;
69 }
70
77 template<typename Stream>
79 static serialize(Stream& reader, T& value) noexcept
80 {
81 static_assert(Min < Max);
82
83 constexpr uint32_t num_bits = utility::bits_in_range(Min, Max);
84
85 static_assert(num_bits <= sizeof(T) * 8);
86
87 if constexpr (sizeof(T) > 4 && num_bits > 32)
88 {
89 // If the given range is bigger than a word (32 bits)
90 value = 0;
91 uint32_t unsigned_value;
92
93 BS_ASSERT(reader.serialize_bits(unsigned_value, 32));
94 value |= static_cast<T>(unsigned_value);
95
96 BS_ASSERT(reader.serialize_bits(unsigned_value, num_bits - 32));
97 value |= static_cast<T>(unsigned_value) << 32;
98
99 value += Min;
100 }
101 else
102 {
103 // If the given range is smaller than or equal to a word (32 bits)
104 uint32_t unsigned_value;
105 BS_ASSERT(reader.serialize_bits(unsigned_value, num_bits));
106
107 value = static_cast<T>(unsigned_value) + Min;
108 }
109
110 BS_ASSERT(value >= Min && value <= Max);
111
112 return true;
113 }
114 };
115#pragma endregion
116
117#pragma region integral types
122 template<typename T>
123 struct serialize_traits<T, typename std::enable_if_t<std::is_integral_v<T> && !std::is_const_v<T>>>
124 {
125 static_assert(sizeof(T) <= 8, "Integers larger than 8 bytes are currently not supported. You will have to write this functionality yourself");
126
135 template<typename Stream>
137 static serialize(Stream& writer, in<T> value, T min, T max) noexcept
138 {
139 BS_ASSERT(min < max);
140
141 BS_ASSERT(value >= min && value <= max);
142
143 uint32_t num_bits = utility::bits_in_range(min, max);
144
145 BS_ASSERT(num_bits <= sizeof(T) * 8);
146
147 if constexpr (sizeof(T) > 4)
148 {
149 if (num_bits > 32)
150 {
151 // If the given range is bigger than a word (32 bits)
152 uint32_t unsigned_value = static_cast<uint32_t>(value - min);
153 BS_ASSERT(writer.serialize_bits(unsigned_value, 32));
154
155 unsigned_value = static_cast<uint32_t>((value - min) >> 32);
156 BS_ASSERT(writer.serialize_bits(unsigned_value, num_bits - 32));
157
158 return true;
159 }
160 }
161
162 // If the given range is smaller than or equal to a word (32 bits)
163 uint32_t unsigned_value = static_cast<uint32_t>(value - min);
164 BS_ASSERT(writer.serialize_bits(unsigned_value, num_bits));
165
166 return true;
167 }
168
177 template<typename Stream>
179 static serialize(Stream& reader, T& value, T min, T max) noexcept
180 {
181 BS_ASSERT(min < max);
182
183 uint32_t num_bits = utility::bits_in_range(min, max);
184
185 BS_ASSERT(num_bits <= sizeof(T) * 8);
186
187 if constexpr (sizeof(T) > 4)
188 {
189 if (num_bits > 32)
190 {
191 // If the given range is bigger than a word (32 bits)
192 value = 0;
193 uint32_t unsigned_value;
194
195 BS_ASSERT(reader.serialize_bits(unsigned_value, 32));
196 value |= static_cast<T>(unsigned_value);
197
198 BS_ASSERT(reader.serialize_bits(unsigned_value, num_bits - 32));
199 value |= static_cast<T>(unsigned_value) << 32;
200
201 value += min;
202
203 BS_ASSERT(value >= min && value <= max);
204
205 return true;
206 }
207 }
208
209 // If the given range is smaller than or equal to a word (32 bits)
210 uint32_t unsigned_value;
211 BS_ASSERT(reader.serialize_bits(unsigned_value, num_bits));
212
213 value = static_cast<T>(unsigned_value) + min;
214
215 BS_ASSERT(value >= min && value <= max);
216
217 return true;
218 }
219
226 template<typename Stream, typename U>
227 static bool serialize(Stream& stream, U&& value) noexcept
228 {
229 return serialize_traits<bounded_int<T>>::serialize(stream, std::forward<U>(value));
230 }
231 };
232#pragma endregion
233}
#define BS_ASSERT(...)
Definition assert.h:15
constexpr uint32_t bits_in_range(intmax_t min, intmax_t max)
Definition bits.h:22
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
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:89
Wrapper type for compiletime known integer bounds.
Definition integral_traits.h:20
static utility::is_writing_t< Stream > serialize(Stream &writer, in< T > value, T min, T max) noexcept
Writes an integer into the writer.
Definition integral_traits.h:137
static utility::is_reading_t< Stream > serialize(Stream &reader, T &value, T min, T max) noexcept
Reads an integer from the reader into value.
Definition integral_traits.h:179
static bool serialize(Stream &stream, U &&value) noexcept
Writes or reads an integer into the stream.
Definition integral_traits.h:227
static utility::is_writing_t< Stream > serialize(Stream &writer, in< T > value) noexcept
Writes an integer into the writer.
Definition integral_traits.h:42
static utility::is_reading_t< Stream > serialize(Stream &reader, T &value) noexcept
Reads an integer from the writer into value.
Definition integral_traits.h:79
A class for specializing trait serialization functions.
Definition serialize_traits.h:11