Skip to content

Commit ed26f51

Browse files
authored
Merge pull request #8 from KredeGC/dev
Add double trait
2 parents f68353a + 3b43179 commit ed26f51

22 files changed

+405
-264
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,10 @@ uint32_t value = 27; // We can choose any value below 2^5. Otherwise we need mor
254254
writer.serialize_bits(value, 5);
255255
256256
// Flush the writer's remaining state into the buffer
257-
uint32_t num_bytes = writer.flush();
257+
uint32_t num_bits = writer.flush();
258258
259259
// Create a reader, referencing the buffer and bytes written
260-
bit_reader reader(buffer, num_bytes);
260+
bit_reader reader(buffer, num_bits);
261261
262262
// Read the value back
263263
uint32_t out_value; // We don't have to initialize it yet
@@ -275,10 +275,10 @@ int32_t value = -45; // We can choose any value within the range below
275275
writer.serialize<int32_t>(value, -90, 40); // A lower and upper bound which the value will be quantized between
276276

277277
// Flush the writer's remaining state into the buffer
278-
uint32_t num_bytes = writer.flush();
278+
uint32_t num_bits = writer.flush();
279279

280280
// Create a reader by moving and invalidating the writer
281-
bit_reader reader(buffer, num_bytes);
281+
bit_reader reader(buffer, num_bits);
282282

283283
// Read the value back
284284
int32_t out_value; // We don't have to initialize it yet
@@ -296,10 +296,10 @@ const char* value = "Hello world!";
296296
writer.serialize<const char*>(value, 32U); // The second argument is the maximum size we expect the string to be
297297
298298
// Flush the writer's remaining state into the buffer
299-
uint32_t num_bytes = writer.flush();
299+
uint32_t num_bits = writer.flush();
300300
301301
// Create a reader by moving and invalidating the writer
302-
bit_reader reader(buffer, num_bytes);
302+
bit_reader reader(buffer, num_bits);
303303
304304
// Read the value back
305305
char out_value[32]; // Set the size to the max size
@@ -317,10 +317,10 @@ std::string value = "Hello world!";
317317
writer.serialize<std::string>(value, 32U); // The second argument is the maximum size we expect the string to be
318318

319319
// Flush the writer's remaining state into the buffer
320-
uint32_t num_bytes = writer.flush();
320+
uint32_t num_bits = writer.flush();
321321

322322
// Create a reader by moving and invalidating the writer
323-
bit_reader reader(buffer, num_bytes);
323+
bit_reader reader(buffer, num_bits);
324324

325325
// Read the value back
326326
std::string out_value; // The string will be resized if the output doesn't fit
@@ -339,10 +339,10 @@ float value = 1.2345678f;
339339
writer.serialize<bounded_range>(range, value);
340340
341341
// Flush the writer's remaining state into the buffer
342-
uint32_t num_bytes = writer.flush();
342+
uint32_t num_bits = writer.flush();
343343
344344
// Create a reader by moving and invalidating the writer
345-
bit_reader reader(buffer, num_bytes);
345+
bit_reader reader(buffer, num_bits);
346346
347347
// Read the value back
348348
float out_value;
@@ -354,7 +354,7 @@ These examples can also be seen in [`src/test/examples_test.cpp`](https://github
354354
# Extensibility
355355
The library is made with extensibility in mind.
356356
The `bit_writer` and `bit_reader` use a template trait specialization of the given type to deduce how to serialize and deserialize the object.
357-
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.
357+
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.
358358
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.
359359

360360
## Adding new serializables types

include/bitstream/quantization/bounded_range.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#pragma once
22

3-
#include <cstdint>
4-
53
/*
64
* Copyright (c) 2018 Stanislav Denisov
75
*
@@ -24,6 +22,8 @@
2422
* SOFTWARE.
2523
*/
2624

25+
#include <cstdint>
26+
2727
namespace bitstream
2828
{
2929
/**

include/bitstream/quantization/half_precision.h

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#pragma once
22

3-
#include <cstdint>
4-
53
/*
64
* Copyright (c) 2018 Stanislav Denisov
75
*
@@ -24,36 +22,25 @@
2422
* SOFTWARE.
2523
*/
2624

25+
#include <cstdint>
26+
#include <cstring>
27+
2728
namespace bitstream
2829
{
2930
/**
3031
* @brief Class for quantizing single-precision floats into half-precision
3132
*/
3233
class half_precision
3334
{
34-
private:
35-
union Values
36-
{
37-
float f;
38-
int32_t i;
39-
};
40-
4135
public:
4236
inline static uint16_t quantize(float value)
4337
{
44-
Values values
45-
{
46-
value
47-
};
38+
int32_t tmp;
39+
std::memcpy(&tmp, &value, sizeof(float));
4840

49-
return quantize(values.i);
50-
}
51-
52-
inline static uint16_t quantize(int32_t value)
53-
{
54-
int32_t s = (value >> 16) & 0x00008000;
55-
int32_t e = ((value >> 23) & 0X000000FF) - (127 - 15);
56-
int32_t m = value & 0X007FFFFF;
41+
int32_t s = (tmp >> 16) & 0x00008000;
42+
int32_t e = ((tmp >> 23) & 0X000000FF) - (127 - 15);
43+
int32_t m = tmp & 0X007FFFFF;
5744

5845
if (e <= 0) {
5946
if (e < -10)
@@ -94,7 +81,7 @@ namespace bitstream
9481

9582
inline static float dequantize(uint16_t value)
9683
{
97-
uint32_t result;
84+
uint32_t tmp;
9885
uint32_t mantissa = (uint32_t)(value & 1023);
9986
uint32_t exponent = 0XFFFFFFF2;
10087

@@ -106,22 +93,22 @@ namespace bitstream
10693
}
10794

10895
mantissa &= 0XFFFFFBFF;
109-
result = (((uint32_t)value & 0x8000) << 16) | ((exponent + 127) << 23) | (mantissa << 13);
96+
tmp = (((uint32_t)value & 0x8000) << 16) | ((exponent + 127) << 23) | (mantissa << 13);
11097
}
11198
else
11299
{
113-
result = (uint32_t)((value & 0x8000) << 16);
100+
tmp = (uint32_t)((value & 0x8000) << 16);
114101
}
115102
}
116103
else
117104
{
118-
result = ((((uint32_t)value & 0x8000) << 16) | ((((((uint32_t)value >> 10) & 0X1F) - 15) + 127) << 23)) | (mantissa << 13);
105+
tmp = ((((uint32_t)value & 0x8000) << 16) | ((((((uint32_t)value >> 10) & 0X1F) - 15) + 127) << 23)) | (mantissa << 13);
119106
}
120107

121-
Values values;
122-
values.i = result;
108+
float result;
109+
std::memcpy(&result, &tmp, sizeof(float));
123110

124-
return values.f;
111+
return result;
125112
}
126113
};
127114
}

include/bitstream/quantization/smallest_three.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#pragma once
22

3-
#include <cstdint>
4-
#include <cmath>
5-
63
/*
74
* Copyright (c) 2020 Stanislav Denisov, Maxim Munning, Davin Carten
85
*
@@ -25,6 +22,9 @@
2522
* SOFTWARE.
2623
*/
2724

25+
#include <cstdint>
26+
#include <cmath>
27+
2828
namespace bitstream
2929
{
3030
/**

include/bitstream/stream/bit_reader.h

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,28 @@ namespace bitstream
3636
m_WordIndex(0) {}
3737

3838
/**
39-
* @brief Construct a reader pointing to the given byte array with @p num_bytes size
39+
* @brief Construct a reader pointing to the given byte array with @p num_bits
4040
* @param bytes The byte array to read from. Should be 4-byte aligned if possible. The size of the array must be a multiple of 4
41-
* @param num_bytes The maximum number of bytes that we can read
41+
* @param num_bits The maximum number of bits that we can read
4242
*/
43-
explicit bit_reader(const void* bytes, uint32_t num_bytes) noexcept :
43+
explicit bit_reader(const void* bytes, uint32_t num_bits) noexcept :
4444
m_Buffer(static_cast<const uint32_t*>(bytes)),
4545
m_NumBitsRead(0),
46-
m_TotalBits(num_bytes * 8),
46+
m_TotalBits(num_bits),
4747
m_Scratch(0),
4848
m_ScratchBits(0),
4949
m_WordIndex(0) {}
5050

5151
/**
5252
* @brief Construct a reader pointing to the given @p buffer
5353
* @param buffer The buffer to read from
54-
* @param num_bytes The maximum number of bytes that we can read
54+
* @param num_bits The maximum number of bits that we can read
5555
*/
5656
template<size_t Size>
57-
explicit bit_reader(byte_buffer<Size>& buffer, uint32_t num_bytes) noexcept :
57+
explicit bit_reader(byte_buffer<Size>& buffer, uint32_t num_bits) noexcept :
5858
m_Buffer(reinterpret_cast<uint32_t*>(buffer.Bytes)),
5959
m_NumBitsRead(0),
60-
m_TotalBits(num_bytes * 8),
60+
m_TotalBits(num_bits),
6161
m_Scratch(0),
6262
m_ScratchBits(0),
6363
m_WordIndex(0) {}
@@ -113,6 +113,12 @@ namespace bitstream
113113
*/
114114
uint32_t get_num_bits_serialized() const noexcept { return m_NumBitsRead; }
115115

116+
/**
117+
* @brief Returns the number of bytes which have been read from the buffer
118+
* @return The number of bytes which have been read
119+
*/
120+
uint32_t get_num_bytes_serialized() const noexcept { return m_NumBitsRead > 0U ? ((m_NumBitsRead - 1U) / 8U + 1U) : 0U; }
121+
116122
/**
117123
* @brief Returns whether the @p num_bits be read from the buffer
118124
* @param num_bits The number of bits to test
@@ -178,24 +184,23 @@ namespace bitstream
178184

179185
BS_ASSERT(num_bytes * 8U >= m_NumBitsRead);
180186

181-
uint32_t offset = m_NumBitsRead / 32;
187+
uint32_t remainder = (num_bytes * 8U - m_NumBitsRead) % 32U;
182188
uint32_t zero;
183189

184-
// Test for zeros in padding
185-
for (uint32_t i = offset; i < num_bytes / 4; i++)
190+
// Test the last word more carefully, as it may have data
191+
if (remainder != 0U)
186192
{
187-
bool status = serialize_bits(zero, 32);
188-
193+
bool status = serialize_bits(zero, remainder);
189194
BS_ASSERT(status && zero == 0);
190195
}
191196

192-
uint32_t remainder = num_bytes * 8U - m_NumBitsRead;
197+
uint32_t offset = m_NumBitsRead / 32;
198+
uint32_t max = num_bytes / 4;
193199

194-
// Test the last word more carefully, as it may have data
195-
if (remainder % 32U != 0U)
200+
// Test for zeros in padding
201+
for (uint32_t i = offset; i < max; i++)
196202
{
197-
bool status = serialize_bits(zero, remainder);
198-
203+
bool status = serialize_bits(zero, 32);
199204
BS_ASSERT(status && zero == 0);
200205
}
201206

@@ -329,9 +334,10 @@ namespace bitstream
329334
* @brief Reads from the buffer, by trying to deduce the trait.
330335
* @note The Trait type in this function is always implicit and will be deduced from the first argument if possible.
331336
* If the trait cannot be deduced it will not compile.
332-
* @tparam Trait A template specialization of serialize_trait<>
337+
* @tparam Trait The type of the first argument, which will be used to deduce the trait specialization
333338
* @tparam ...Args The types of the arguments to pass to the serialize function
334-
* @param ...args The arguments to pass to the serialize function
339+
* @param arg The first argument to pass to the serialize function
340+
* @param ...args The rest of the arguments to pass to the serialize function
335341
* @return Whether successful or not
336342
*/
337343
template<typename Trait, typename... Args>

0 commit comments

Comments
 (0)