Skip to content

Commit 5f665ac

Browse files
authored
Merge pull request #15 from KredeGC/optimization
Add policies
2 parents 48cb8f4 + 7bc1360 commit 5f665ac

20 files changed

+476
-288
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Test
1+
name: Staging
22

33
on:
44
push:

README.md

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ bool serialize_custom_type(Stream& stream, custom_type& value)
8686
}
8787

8888
byte_buffer<32> buffer;
89-
bit_writer writer(buffer);
89+
fixed_bit_writer writer(buffer);
9090

9191
custom_type in_value;
9292
serialize_custom_type(writer, in_value); // Serialize the value
9393

9494
uint32_t num_bits = writer.flush();
95-
bit_reader reader(buffer, num_bits);
95+
fixed_bit_reader reader(buffer, num_bits);
9696

9797
custom_type out_value;
9898
serialize_custom_type(reader, out_value); // Deserialize the value
@@ -119,7 +119,7 @@ Writing the first 5 bits of an int to the buffer, then reading it back:
119119
```cpp
120120
// Create a writer, referencing the buffer and its size
121121
alignas(uint32_t) uint8_t buffer[4]; // Buffer must be a multiple of 4 bytes / 32 bits and 4-byte-aligned
122-
bit_writer writer(buffer, 4);
122+
fixed_bit_writer writer(buffer, 4);
123123
124124
// Write the value
125125
uint32_t value = 27; // We can choose any value below 2^5. Otherwise we need more than 5 bits
@@ -129,7 +129,7 @@ writer.serialize_bits(value, 5);
129129
uint32_t num_bits = writer.flush();
130130
131131
// Create a reader, referencing the buffer and bits written
132-
bit_reader reader(buffer, num_bits);
132+
fixed_bit_reader reader(buffer, num_bits);
133133
134134
// Read the value back
135135
uint32_t out_value; // We don't have to initialize it yet
@@ -140,7 +140,7 @@ Writing a signed int to the buffer, within a range:
140140
```cpp
141141
// Create a writer, referencing the buffer and its size
142142
byte_buffer<4> buffer; // byte_bufer is just a wrapper for a 4-byte aligned buffer
143-
bit_writer writer(buffer);
143+
fixed_bit_writer writer(buffer);
144144

145145
// Write the value
146146
int32_t value = -45; // We can choose any value within the range below
@@ -150,7 +150,7 @@ writer.serialize<int32_t>(value, -90, 40); // A lower and upper bound which the
150150
uint32_t num_bits = writer.flush();
151151

152152
// Create a reader, referencing the buffer and bits written
153-
bit_reader reader(buffer, num_bits);
153+
fixed_bit_reader reader(buffer, num_bits);
154154

155155
// Read the value back
156156
int32_t out_value; // We don't have to initialize it yet
@@ -161,7 +161,7 @@ Writing a c-style string into the buffer:
161161
```cpp
162162
// Create a writer, referencing the buffer and its size
163163
byte_buffer<32> buffer;
164-
bit_writer writer(buffer);
164+
fixed_bit_writer writer(buffer);
165165
166166
// Write the value
167167
const char* value = "Hello world!";
@@ -171,7 +171,7 @@ writer.serialize<const char*>(value, 32U); // The second argument is the maximum
171171
uint32_t num_bits = writer.flush();
172172
173173
// Create a reader, referencing the buffer and bits written
174-
bit_reader reader(buffer, num_bits);
174+
fixed_bit_reader reader(buffer, num_bits);
175175
176176
// Read the value back
177177
char out_value[32]; // Set the size to the max size
@@ -182,7 +182,7 @@ Writing a std::string into the buffer:
182182
```cpp
183183
// Create a writer, referencing the buffer and its size
184184
byte_buffer<32> buffer;
185-
bit_writer writer(buffer);
185+
fixed_bit_writer writer(buffer);
186186

187187
// Write the value
188188
std::string value = "Hello world!";
@@ -192,7 +192,7 @@ writer.serialize<std::string>(value, 32U); // The second argument is the maximum
192192
uint32_t num_bits = writer.flush();
193193

194194
// Create a reader, referencing the buffer and bits written
195-
bit_reader reader(buffer, num_bits);
195+
fixed_bit_reader reader(buffer, num_bits);
196196

197197
// Read the value back
198198
std::string out_value; // The string will be resized if the output doesn't fit
@@ -203,7 +203,7 @@ Writing a float into the buffer with a bounded range and precision:
203203
```cpp
204204
// Create a writer, referencing the buffer and its size
205205
byte_buffer<4> buffer;
206-
bit_writer writer(buffer);
206+
fixed_bit_writer writer(buffer);
207207
208208
// Write the value
209209
bounded_range range(1.0f, 4.0f, 1.0f / 128.0f); // Min, Max, Precision
@@ -214,7 +214,7 @@ writer.serialize<bounded_range>(range, value);
214214
uint32_t num_bits = writer.flush();
215215
216216
// Create a reader, referencing the buffer and bits written
217-
bit_reader reader(buffer, num_bits);
217+
fixed_bit_reader reader(buffer, num_bits);
218218
219219
// Read the value back
220220
float out_value;
@@ -445,8 +445,8 @@ bool status_read = reader.serialize<smallest_three<quaternion, 12>>(out_value);
445445
446446
# Extensibility
447447
The library is made with extensibility in mind.
448-
The `bit_writer` and `bit_reader` use a template trait specialization of the given type to deduce how to serialize and deserialize the object.
449-
The only requirements of the trait is that it has (or can deduce) 2 static functions which take a `bit_writer&` and a `bit_reader&` respectively as their first argument.
448+
The `bit_writer<T>` and `bit_reader<T>` use a template trait specialization of the given type to deduce how to serialize and deserialize the object.
449+
The only requirements of the trait is that it has (or can deduce) 2 static functions which take a `bit_writer<T>&` and a `bit_reader<T>&` respectively as their first argument.
450450
The 2 functions must also return a bool indicating whether the serialization was a success or not, but can otherwise take any number of additional arguments.
451451
452452
## Adding new serializables types
@@ -457,17 +457,21 @@ template<>
457457
struct serialize_traits<TRAIT_TYPE> // The type to use when referencing this specific trait
458458
{
459459
// Will be called when writing the object to a stream
460-
static bool serialize(bit_writer& stream, ...)
460+
template<typename Stream>
461+
typename utility::is_writing_t<Stream>
462+
static serialize(Stream& stream, ...)
461463
{ ... }
462464
463465
// Will be called when reading the object from a stream
464-
static bool serialize(bit_reader& stream, ...)
466+
template<typename Stream>
467+
typename utility::is_reading_t<Stream>
468+
static serialize(Stream& stream, ...)
465469
{ ... }
466470
};
467471
```
468472

469473
As with any functions, you are free to overload them if you want to serialize an object differently, depending on any parameters you pass.
470-
As long as their list of parameters starts with `bit_writer&` and `bit_reader&` respectively they will be able to be called.
474+
As long as the first parameter can be deduced to `bit_writer<T>&` and `bit_reader<T>&` respectively they will be able to be called.
471475

472476
## Unified serialization
473477
The serialization can also be unified with templating, if writing and reading look similar.
@@ -488,7 +492,7 @@ struct serialize_traits<TRAIT_TYPE> // The type to use when serializing
488492
}
489493

490494
// A variable that differs if the stream is writing or reading
491-
int value = Stream::reading ? 0 : 1;
495+
int value = Stream::reading ? 500 : 200;
492496

493497
...
494498
}
@@ -525,19 +529,23 @@ template<>
525529
struct serialize_traits<TRAIT_TYPE> // The type to use when referencing this specific trait
526530
{
527531
// The second argument is the same as TRAIT_TYPE (const and lvalue references are removed when deducing)
528-
static bool serialize(bit_writer& stream, const TRAIT_TYPE&, ...)
532+
template<typename Stream>
533+
typename utility::is_writing_t<Stream>
534+
static serialize(Stream& stream, const TRAIT_TYPE&, ...)
529535
{ ... }
530536

531537
// The second argument is the same as TRAIT_TYPE (lvalue is removed)
532-
static bool serialize(bit_reader& stream, TRAIT_TYPE&, ...)
538+
template<typename Stream>
539+
typename utility::is_reading_t<Stream>
540+
static serialize(Stream& stream, TRAIT_TYPE&, ...)
533541
{ ... }
534542
};
535543
```
536544
537545
The above trait could then be used when implicitly serializing an object of type `TRAIT_TYPE`:
538546
```cpp
539547
TRAIT_TYPE value;
540-
bool status = writer.serialize(value, ...);
548+
bool status = writer.serialize(value, ...); // No need for "serialize<TRAIT_TYPE>"
541549
```
542550

543551
It doesn't work on all types, and there is some guesswork involved relating to const qualifiers.

include/bitstream/stream/bit_measure.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99

1010
#include <cstdint>
1111
#include <cstring>
12+
#include <limits>
1213
#include <memory>
1314
#include <type_traits>
1415

1516
namespace bitstream
1617
{
17-
class bit_reader;
18-
1918
/**
2019
* @brief A stream for writing objects tightly into a buffer
2120
* @note Does not take ownership of the buffer
@@ -31,13 +30,13 @@ namespace bitstream
3130
*/
3231
bit_measure() noexcept :
3332
m_NumBitsWritten(0),
34-
m_TotalBits(0) {}
33+
m_TotalBits((std::numeric_limits<uint32_t>::max)()) {}
3534

3635
/**
3736
* @brief Construct a writer pointing to the given byte array with @p num_bytes size
3837
* @param num_bytes The number of bytes in the array
3938
*/
40-
explicit bit_measure(uint32_t num_bytes) noexcept :
39+
bit_measure(uint32_t num_bytes) noexcept :
4140
m_NumBitsWritten(0),
4241
m_TotalBits(num_bytes * 8) {}
4342

0 commit comments

Comments
 (0)