Latest refactoring

Added little endian bit stream reader tests
This commit is contained in:
John Wellbelove 2022-06-19 18:37:20 +01:00
parent d1a522eb68
commit 5a460f7fec
9 changed files with 1245 additions and 135 deletions

View File

@ -562,10 +562,10 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
bit_stream_writer(etl::span<char> span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
bit_stream_writer(etl::span<char> span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(span_.begin())
, length_chars(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
restart();
@ -574,10 +574,10 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
bit_stream_writer(etl::span<unsigned char> span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
bit_stream_writer(etl::span<unsigned char> span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(span_.begin()))
, length_chars(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
restart();
@ -586,10 +586,10 @@ namespace etl
//***************************************************************************
/// Construct from range.
//***************************************************************************
bit_stream_writer(void* begin_, void* end_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
bit_stream_writer(void* begin_, void* end_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(begin_))
, length_chars(etl::distance(reinterpret_cast<unsigned char*>(begin_), reinterpret_cast<unsigned char*>(end_)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
restart();
@ -598,10 +598,10 @@ namespace etl
//***************************************************************************
/// Construct from begin and length.
//***************************************************************************
bit_stream_writer(void* begin_, size_t length_chars_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
bit_stream_writer(void* begin_, size_t length_chars_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(begin_))
, length_chars(length_chars_)
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
restart();
@ -1079,25 +1079,6 @@ namespace etl
}
}
//***************************************************************************
/// Convert to bytes.
//***************************************************************************
template <typename T>
void to_bytes(T value, unsigned char* data)
{
unsigned char* pf = reinterpret_cast<unsigned char*>(&value);
// Host to network.
if (etl::endianness::value() == etl::endian::little)
{
etl::reverse_copy(pf, pf + sizeof(T), data);
}
else
{
etl::copy(pf, pf + sizeof(T), data);
}
}
//***************************************************************************
/// Step the specified number of bits along the stream.
/// The width will never be larger than 'bits_available_in_char'.
@ -1178,10 +1159,10 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
bit_stream_reader(etl::span<char> span_, etl::endian buffer_endianness_)
bit_stream_reader(etl::span<char> span_, etl::endian stream_endianness_)
: pdata(span_.begin())
, length_chars(span_.size_bytes())
, stream_endianness(etl::endian::big)
, stream_endianness(stream_endianness_)
{
restart();
}
@ -1189,10 +1170,10 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
bit_stream_reader(etl::span<unsigned char> span_, etl::endian buffer_endianness_)
bit_stream_reader(etl::span<unsigned char> span_, etl::endian stream_endianness_)
: pdata(reinterpret_cast<char*>(span_.begin()))
, length_chars(span_.size_bytes())
, stream_endianness(etl::endian::big)
, stream_endianness(stream_endianness_)
{
restart();
}
@ -1200,10 +1181,10 @@ namespace etl
//***************************************************************************
/// Construct from range.
//***************************************************************************
bit_stream_reader(void* begin_, void* end_, etl::endian buffer_endianness_)
bit_stream_reader(void* begin_, void* end_, etl::endian stream_endianness_)
: pdata(reinterpret_cast<char*>(begin_))
, length_chars(etl::distance(reinterpret_cast<char*>(begin_), reinterpret_cast<char*>(end_)))
, stream_endianness(etl::endian::big)
, stream_endianness(stream_endianness_)
{
restart();
}
@ -1211,10 +1192,10 @@ namespace etl
//***************************************************************************
/// Construct from begin and length.
//***************************************************************************
bit_stream_reader(void* begin_, size_t length_, etl::endian buffer_endianness_)
bit_stream_reader(void* begin_, size_t length_, etl::endian stream_endianness_)
: pdata(reinterpret_cast<char*>(begin_))
, length_chars(length_)
, stream_endianness(etl::endian::big)
, stream_endianness(stream_endianness_)
{
restart();
}
@ -1243,7 +1224,7 @@ namespace etl
/// For bool types
//***************************************************************************
template <typename T>
typename etl::enable_if<etl::is_same<bool, T>::value, etl::optional<bool>>::type
typename etl::enable_if<etl::is_same<bool, T>::value, etl::optional<bool> >::type
read()
{
etl::optional<bool> result;
@ -1267,29 +1248,11 @@ namespace etl
typename etl::enable_if<etl::is_integral<T>::value && !etl::is_same<bool, T>::value, T>::type
read_unchecked(uint_least8_t nbits = CHAR_BIT * sizeof(T))
{
T value = 0;
uint_least8_t bits = nbits;
typedef typename unsigned_type<T>::type unsigned_t;
// Get the bits from the stream.
while (nbits != 0)
{
unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
T value = read_value<unsigned_t>(nbits, etl::is_signed<T>::value);
typedef typename etl::make_unsigned<T>::type chunk_t;
chunk_t chunk = get_chunk(mask_width);
nbits -= mask_width;
value |= static_cast<T>(chunk << nbits);
}
// Sign extend if signed type and not already full bit width.
if (etl::is_signed<T>::value && (bits != (CHAR_BIT * sizeof(T))))
{
typedef typename etl::make_signed<T>::type ST;
value = etl::sign_extend<ST, ST>(value, bits);
}
return value;
return static_cast<T>(value);
}
//***************************************************************************
@ -1364,6 +1327,54 @@ namespace etl
private:
//***************************************************************************
/// Defines one of five unsigned types that has the same size as T.
//***************************************************************************
template <typename T>
struct unsigned_type
{
typedef typename etl::conditional<sizeof(T) == sizeof(unsigned char), unsigned char,
typename etl::conditional<sizeof(T) == sizeof(unsigned short), unsigned short,
typename etl::conditional<sizeof(T) == sizeof(unsigned int), unsigned int,
typename etl::conditional<sizeof(T) == sizeof(unsigned long), unsigned long,
unsigned long long>::type>::type>::type>::type type;
};
//***************************************************************************
/// Read a value from the stream.
/// It will be passed one of five unsigned types.
//***************************************************************************
template <typename T>
T read_value(uint_least8_t nbits, bool is_signed)
{
T value = 0;
uint_least8_t bits = nbits;
// Get the bits from the stream.
while (nbits != 0)
{
unsigned char mask_width = static_cast<unsigned char>(etl::min(nbits, bits_available_in_char));
T chunk = get_chunk(mask_width);
nbits -= mask_width;
value |= static_cast<T>(chunk << nbits);
}
if (stream_endianness == etl::endian::little)
{
value = value << ((CHAR_BIT * sizeof(T)) - bits);
value = etl::reverse_bits(value);
}
if (is_signed && (bits != (CHAR_BIT * sizeof(T))))
{
value = etl::sign_extend<T, T>(value, bits);
}
return value;
}
//***************************************************************************
/// Get a data chunk from the stream
//***************************************************************************
@ -1402,27 +1413,6 @@ namespace etl
return result;
}
//***************************************************************************
/// Helper function for floating point types
//***************************************************************************
template <typename T>
void from_bytes(const unsigned char* data, T& value)
{
etl::uninitialized_buffer_of<T, 1U> temp;
// Network to host.
if (etl::endianness::value() == etl::endian::little)
{
etl::reverse_copy(data, data + sizeof(T), temp.raw);
}
else
{
etl::copy(data, data + sizeof(T), temp.raw);
}
value = *reinterpret_cast<T*>(temp.raw);
}
//***************************************************************************
/// Step the specified number of bits along the stream.
/// The nbits will never be larger than 'bits_available_in_char'.

View File

@ -93,11 +93,11 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
byte_stream_writer(etl::span<char> span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
byte_stream_writer(etl::span<char> span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(span_.begin())
, pcurrent(span_.begin())
, length(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
}
@ -105,11 +105,11 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
byte_stream_writer(etl::span<unsigned char> span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
byte_stream_writer(etl::span<unsigned char> span_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(span_.begin()))
, pcurrent(reinterpret_cast<char*>(span_.begin()))
, length(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
}
@ -117,11 +117,11 @@ namespace etl
//***************************************************************************
/// Construct from range.
//***************************************************************************
byte_stream_writer(void* begin_, void* end_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
byte_stream_writer(void* begin_, void* end_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(begin_))
, pcurrent(reinterpret_cast<char*>(begin_))
, length(etl::distance(reinterpret_cast<char*>(begin_), reinterpret_cast<char*>(end_)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
}
@ -129,11 +129,11 @@ namespace etl
//***************************************************************************
/// Construct from begin and length.
//***************************************************************************
byte_stream_writer(void* begin_, size_t length_, etl::endian buffer_endianness_, callback_type callback_ = callback_type())
byte_stream_writer(void* begin_, size_t length_, etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(reinterpret_cast<char*>(begin_))
, pcurrent(reinterpret_cast<char*>(begin_))
, length(length_)
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
}
@ -142,11 +142,11 @@ namespace etl
/// Construct from array.
//***************************************************************************
template <typename T, size_t Size>
byte_stream_writer(T(&begin_)[Size], etl::endian buffer_endianness_, callback_type callback_ = callback_type())
byte_stream_writer(T(&begin_)[Size], etl::endian stream_endianness_, callback_type callback_ = callback_type())
: pdata(begin_)
, pcurrent(begin_)
, length(begin_ + (Size * sizeof(T)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
, callback(callback_)
{
}
@ -547,44 +547,44 @@ namespace etl
//***************************************************************************
/// Construct from span.
//***************************************************************************
byte_stream_reader(etl::span<char> span_, etl::endian buffer_endianness_)
byte_stream_reader(etl::span<char> span_, etl::endian stream_endianness_)
: pdata(span_.begin())
, pcurrent(span_.begin())
, length(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}
//***************************************************************************
/// Construct from span.
//***************************************************************************
byte_stream_reader(etl::span<const char> span_, etl::endian buffer_endianness_)
byte_stream_reader(etl::span<const char> span_, etl::endian stream_endianness_)
: pdata(span_.begin())
, pcurrent(span_.begin())
, length(span_.size_bytes())
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}
//***************************************************************************
/// Construct from range.
//***************************************************************************
byte_stream_reader(const void* begin_, const void* end_, etl::endian buffer_endianness_)
byte_stream_reader(const void* begin_, const void* end_, etl::endian stream_endianness_)
: pdata(reinterpret_cast<const char*>(begin_))
, pcurrent(reinterpret_cast<const char*>(begin_))
, length(etl::distance(reinterpret_cast<const char*>(begin_), reinterpret_cast<const char*>(end_)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}
//***************************************************************************
/// Construct from begin and length.
//***************************************************************************
byte_stream_reader(const void* begin_, size_t length_, etl::endian buffer_endianness_)
byte_stream_reader(const void* begin_, size_t length_, etl::endian stream_endianness_)
: pdata(reinterpret_cast<const char*>(begin_))
, pcurrent(reinterpret_cast<const char*>(begin_))
, length(length_)
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}
@ -592,11 +592,11 @@ namespace etl
/// Construct from array.
//***************************************************************************
template <typename T, size_t Size>
byte_stream_reader(T(&begin_)[Size], etl::endian buffer_endianness_)
byte_stream_reader(T(&begin_)[Size], etl::endian stream_endianness_)
: pdata(begin_)
, pcurrent(begin_)
, length(begin_ + (Size * sizeof(T)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}
@ -604,11 +604,11 @@ namespace etl
/// Construct from const array.
//***************************************************************************
template <typename T, size_t Size>
byte_stream_reader(const T(&begin_)[Size], etl::endian buffer_endianness_)
byte_stream_reader(const T(&begin_)[Size], etl::endian stream_endianness_)
: pdata(begin_)
, pcurrent(begin_)
, length(begin_ + (Size * sizeof(T)))
, stream_endianness(buffer_endianness_)
, stream_endianness(stream_endianness_)
{
}

View File

@ -49,6 +49,7 @@ set(TEST_SOURCE_FILES
test_bitset.cpp
test_bit_stream.cpp
test_bit_stream_reader_big_endian.cpp
test_bit_stream_reader_little_endian.cpp
test_bit_stream_writer_big_endian.cpp
test_bit_stream_writer_little_endian.cpp
test_byte.cpp

View File

@ -55,12 +55,6 @@ namespace
os << object.s << "," << object.i << "," << (int)object.c;
return os;
}
struct Object2
{
};
}
namespace etl
@ -934,8 +928,8 @@ namespace
{
int8_t c1 = 90; // 0x5A
uint16_t s1 = 4660; // 0x1234
int32_t i1 = 2309737967L; // 0x89ABCDEF
int32_t i2 = 4275878552L; // 0xFEDCBA98
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98
uint16_t s2 = 22136; // 0x5678
int8_t c2 = -91; // 0xA5
@ -978,12 +972,12 @@ namespace
//*************************************************************************
TEST(test_read_multiple_variable_size)
{
int8_t c1 = 90; // 0x5A 6 bits
uint16_t s1 = 4660; // 0x1234 13 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
uint16_t s2 = 22136; // 0x5678 11 bits
int8_t c2 = -91; // 0xA5 7 bits
int8_t c1 = 90; // 0x5A 6 bits
uint16_t s1 = 4660; // 0x1234 13 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
uint16_t s2 = 22136; // 0x5678 11 bits
int8_t c2 = -91; // 0xA5 7 bits
std::array storage = { char(0x6A), char(0x46), char(0x8A), char(0xF3),
char(0x7B), char(0xDB), char(0x97), char(0x53),
@ -1021,12 +1015,12 @@ namespace
//*************************************************************************
TEST(test_read_multiple_variable_size_using_non_member_functions)
{
int8_t c1 = 90; // 0x5A 6 bits
uint16_t s1 = 4660; // 0x1234 13 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
uint16_t s2 = 22136; // 0x5678 11 bits
int8_t c2 = -91; // 0xA5 7 bits
int8_t c1 = 90; // 0x5A 6 bits
uint16_t s1 = 4660; // 0x1234 13 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
uint16_t s2 = 22136; // 0x5678 11 bits
int8_t c2 = -91; // 0xA5 7 bits
std::array storage = { char(0x6A), char(0x46), char(0x8A), char(0xF3),
char(0x7B), char(0xDB), char(0x97), char(0x53),

File diff suppressed because it is too large Load Diff

View File

@ -624,8 +624,8 @@ namespace
char c2 = -91; // 0xA5
unsigned short s1 = 4660; // 0x1234
unsigned short s2 = 22136; // 0x5678
int32_t i1 = 2309737967L; // 0x89ABCDEF
int32_t i2 = 4275878552L; // 0xFEDCBA98
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98
std::array<char, 14> storage;
std::array<char, 14> expected = { char(0x5A),
@ -674,8 +674,8 @@ namespace
char c2 = -91; // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
std::array<char, 14> storage;
std::array<char, 14> expected = { char(0x6A), char(0x46), char(0x8A), char(0xF3),
@ -720,8 +720,8 @@ namespace
char c2 = -91; // 0xA5 7 bits
unsigned short s1 = 4660U; // 0x1234 13 bits
unsigned short s2 = 22136U; // 0x5678 11 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
std::array<char, 14> storage;
storage.fill(0);

View File

@ -329,9 +329,9 @@ namespace
{
std::array<char, sizeof(uint32_t) * 4> storage;
std::array<char, sizeof(uint32_t) * 4> expected = { char(0x80), char(0x00), char(0x00), char(0x00),
char(0x5A), char(0xA5), char(0xA5), char(0x5A),
char(0xA5), char(0x5A), char(0x5A), char(0xA5),
char(0xFF), char(0xFF), char(0xFF), char(0xFF) };
char(0x5A), char(0xA5), char(0xA5), char(0x5A),
char(0xA5), char(0x5A), char(0x5A), char(0xA5),
char(0xFF), char(0xFF), char(0xFF), char(0xFF) };
CHECK(expected.size() == storage.size());
@ -713,8 +713,8 @@ namespace
char c2 = -91; // 0xA5
unsigned short s1 = 4660; // 0x1234
unsigned short s2 = 22136; // 0x5678
int32_t i1 = 2309737967L; // 0x89ABCDEF
int32_t i2 = 4275878552L; // 0xFEDCBA98
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98
std::array<char, 14> storage;
std::array<char, 14> expected = { char(0x5A),
@ -763,8 +763,8 @@ namespace
char c2 = -91; // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
std::array<char, 14> storage;
std::array<char, 14> expected = { char(0x58), char(0xB1), char(0x3E), char(0xF6),
@ -807,8 +807,8 @@ namespace
char c2 = -91; // 0xA5 7 bits
unsigned short s1 = 4660; // 0x1234 13 bits
unsigned short s2 = 22136; // 0x5678 11 bits
int32_t i1 = 2309737967L; // 0x89ABCDEF 23 bits
int32_t i2 = 4275878552L; // 0xFEDCBA98 25 bits
int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF 23 bits
int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 25 bits
std::array<char, 14> storage;
std::array<char, 14> expected = { char(0x58), char(0xB1), char(0x3E), char(0xF6),

View File

@ -10912,6 +10912,7 @@
<ClCompile Include="..\test_atomic.cpp" />
<ClCompile Include="..\test_bit.cpp" />
<ClCompile Include="..\test_bit_stream_reader_big_endian.cpp" />
<ClCompile Include="..\test_bit_stream_reader_little_endian.cpp" />
<ClCompile Include="..\test_bit_stream_writer_big_endian.cpp" />
<ClCompile Include="..\test_bit_stream_writer_little_endian.cpp" />
<ClCompile Include="..\test_bresenham_line.cpp" />

View File

@ -3257,6 +3257,9 @@
<ClCompile Include="..\test_bit_stream_writer_little_endian.cpp">
<Filter>Tests\Binary</Filter>
</ClCompile>
<ClCompile Include="..\test_bit_stream_reader_little_endian.cpp">
<Filter>Tests\Binary</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">