From 5a460f7fec8d0d651465bdb18dcb35c76fdcaa39 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 19 Jun 2022 18:37:20 +0100 Subject: [PATCH] Latest refactoring Added little endian bit stream reader tests --- include/etl/bit_stream.h | 146 +-- include/etl/byte_stream.h | 44 +- test/CMakeLists.txt | 1 + test/test_bit_stream_reader_big_endian.cpp | 34 +- test/test_bit_stream_reader_little_endian.cpp | 1121 +++++++++++++++++ test/test_bit_stream_writer_big_endian.cpp | 12 +- test/test_bit_stream_writer_little_endian.cpp | 18 +- test/vs2019/etl.vcxproj | 1 + test/vs2019/etl.vcxproj.filters | 3 + 9 files changed, 1245 insertions(+), 135 deletions(-) create mode 100644 test/test_bit_stream_reader_little_endian.cpp diff --git a/include/etl/bit_stream.h b/include/etl/bit_stream.h index 2d9d883c..d3169e59 100644 --- a/include/etl/bit_stream.h +++ b/include/etl/bit_stream.h @@ -562,10 +562,10 @@ namespace etl //*************************************************************************** /// Construct from span. //*************************************************************************** - bit_stream_writer(etl::span span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) + bit_stream_writer(etl::span 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 span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) + bit_stream_writer(etl::span span_, etl::endian stream_endianness_, callback_type callback_ = callback_type()) : pdata(reinterpret_cast(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(begin_)) , length_chars(etl::distance(reinterpret_cast(begin_), reinterpret_cast(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(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 - void to_bytes(T value, unsigned char* data) - { - unsigned char* pf = reinterpret_cast(&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 span_, etl::endian buffer_endianness_) + bit_stream_reader(etl::span 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 span_, etl::endian buffer_endianness_) + bit_stream_reader(etl::span span_, etl::endian stream_endianness_) : pdata(reinterpret_cast(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(begin_)) , length_chars(etl::distance(reinterpret_cast(begin_), reinterpret_cast(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(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 etl::enable_if::value, etl::optional>::type + typename etl::enable_if::value, etl::optional >::type read() { etl::optional result; @@ -1267,29 +1248,11 @@ namespace etl typename etl::enable_if::value && !etl::is_same::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::type unsigned_t; - // Get the bits from the stream. - while (nbits != 0) - { - unsigned char mask_width = static_cast(etl::min(nbits, bits_available_in_char)); + T value = read_value(nbits, etl::is_signed::value); - typedef typename etl::make_unsigned::type chunk_t; - chunk_t chunk = get_chunk(mask_width); - - nbits -= mask_width; - value |= static_cast(chunk << nbits); - } - - // Sign extend if signed type and not already full bit width. - if (etl::is_signed::value && (bits != (CHAR_BIT * sizeof(T)))) - { - typedef typename etl::make_signed::type ST; - value = etl::sign_extend(value, bits); - } - - return value; + return static_cast(value); } //*************************************************************************** @@ -1364,6 +1327,54 @@ namespace etl private: + //*************************************************************************** + /// Defines one of five unsigned types that has the same size as T. + //*************************************************************************** + template + struct unsigned_type + { + typedef typename etl::conditional::type>::type>::type>::type type; + }; + + //*************************************************************************** + /// Read a value from the stream. + /// It will be passed one of five unsigned types. + //*************************************************************************** + template + 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(etl::min(nbits, bits_available_in_char)); + + T chunk = get_chunk(mask_width); + + nbits -= mask_width; + value |= static_cast(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(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 - void from_bytes(const unsigned char* data, T& value) - { - etl::uninitialized_buffer_of 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(temp.raw); - } - //*************************************************************************** /// Step the specified number of bits along the stream. /// The nbits will never be larger than 'bits_available_in_char'. diff --git a/include/etl/byte_stream.h b/include/etl/byte_stream.h index 2d0ed704..51b61551 100644 --- a/include/etl/byte_stream.h +++ b/include/etl/byte_stream.h @@ -93,11 +93,11 @@ namespace etl //*************************************************************************** /// Construct from span. //*************************************************************************** - byte_stream_writer(etl::span span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) + byte_stream_writer(etl::span 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 span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) + byte_stream_writer(etl::span span_, etl::endian stream_endianness_, callback_type callback_ = callback_type()) : pdata(reinterpret_cast(span_.begin())) , pcurrent(reinterpret_cast(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(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(etl::distance(reinterpret_cast(begin_), reinterpret_cast(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(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(length_) - , stream_endianness(buffer_endianness_) + , stream_endianness(stream_endianness_) , callback(callback_) { } @@ -142,11 +142,11 @@ namespace etl /// Construct from array. //*************************************************************************** template - 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 span_, etl::endian buffer_endianness_) + byte_stream_reader(etl::span 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 span_, etl::endian buffer_endianness_) + byte_stream_reader(etl::span 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(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(etl::distance(reinterpret_cast(begin_), reinterpret_cast(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(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(length_) - , stream_endianness(buffer_endianness_) + , stream_endianness(stream_endianness_) { } @@ -592,11 +592,11 @@ namespace etl /// Construct from array. //*************************************************************************** template - 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 - 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_) { } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3a066af1..296e7237 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/test_bit_stream_reader_big_endian.cpp b/test/test_bit_stream_reader_big_endian.cpp index bdf40f86..8cd7b6c4 100644 --- a/test/test_bit_stream_reader_big_endian.cpp +++ b/test/test_bit_stream_reader_big_endian.cpp @@ -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), diff --git a/test/test_bit_stream_reader_little_endian.cpp b/test/test_bit_stream_reader_little_endian.cpp new file mode 100644 index 00000000..58c82d63 --- /dev/null +++ b/test/test_bit_stream_reader_little_endian.cpp @@ -0,0 +1,1121 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/bit_stream.h" + +#include +#include + +namespace +{ + //*********************************** + struct Object + { + int16_t s; + int32_t i; + uint8_t c; + }; + + bool operator ==(const Object& lhs, const Object& rhs) + { + return (lhs.s == rhs.s) && + (lhs.i == rhs.i) && + (lhs.c == rhs.c); + } + + std::ostream& operator << (std::ostream& os, const Object& object) + { + os << object.s << "," << object.i << "," << (int)object.c; + return os; + } +} + +namespace etl +{ + //*********************************** + template <> + Object read_unchecked(etl::bit_stream_reader& stream) + { + bool success = true; + + int16_t result_s = stream.read_unchecked(14); + int32_t result_i = stream.read_unchecked(23); + uint8_t result_c = stream.read_unchecked(); + + return Object{ result_s, result_i, result_c }; + } + + //*********************************** + template <> + optional read(etl::bit_stream_reader& stream) + { + optional result; + + etl::optional result_s = stream.read(14); + etl::optional result_i = stream.read(23); + etl::optional result_c = stream.read(); + + if (result_s.has_value() && result_i.has_value() && result_c.has_value()) + { + result = Object{ result_s.value(), result_i.value(), result_c.value() }; + } + + return result; + } +} + +namespace +{ + SUITE(test_bit_stream_reader) + { + //************************************************************************* + TEST(test_read_bool) + { + char storage = 0x5AU; + + etl::bit_stream_reader bit_stream(&storage, 1, etl::endian::little); + + CHECK_EQUAL(1U, bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_bool_using_non_member_function) + { + char storage = 0x5AU; + + etl::bit_stream_reader bit_stream(&storage, 1, etl::endian::little); + + CHECK_EQUAL(1U, bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(true, result.value()); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(false, result.value()); + + // One too many. + CHECK_THROW(etl::read(bit_stream), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int8_t) + { + std::array storage = { char(0x80), char(0x5A), char(0xA5), char(0xFF) }; + std::array expected = { int8_t(0x01), int8_t(0x5A), int8_t(0xA5), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_checked_int8_t_using_non_member_function) + { + std::array storage = { char(0x80), char(0x5A), char(0xA5), char(0xFF) }; + std::array expected = { int8_t(0x01), int8_t(0x5A), int8_t(0xA5), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(etl::read(bit_stream), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_unchecked_int8_t_using_non_member_function) + { + std::array storage = { char(0x80), char(0x5A), char(0xA5), char(0xFF) }; + std::array expected = { int8_t(0x01), int8_t(0x5A), int8_t(0xA5), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + int8_t result; + + result = etl::read_unchecked(bit_stream); + CHECK_EQUAL(int(expected[0]), int(result)); + + result = etl::read_unchecked(bit_stream); + CHECK_EQUAL(int(expected[1]), int(result)); + + result = etl::read_unchecked(bit_stream); + CHECK_EQUAL(int(expected[2]), int(result)); + + result = etl::read_unchecked(bit_stream); + CHECK_EQUAL(int(expected[3]), int(result)); + } + + //************************************************************************* + TEST(test_read_int8_t_5bits) + { + std::array storage = { char(0x85), char(0x69), char(0xF0) }; + std::array expected = { int8_t(0x01), int8_t(0xF5), int8_t(0x05), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(bit_stream.read(5U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_checked_int8_t_5bits_using_non_member_function) + { + std::array storage = { char(0x85), char(0x69), char(0xF0) }; + std::array expected = { int8_t(0x01), int8_t(0xF5), int8_t(0x05), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = etl::read(bit_stream, 5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream, 5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream, 5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = etl::read(bit_stream, 5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(etl::read(bit_stream, 5U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_unchecked_int8_t_5bits_using_non_member_function) + { + std::array storage = { char(0x85), char(0x69), char(0xF0) }; + std::array expected = { int8_t(0x01), int8_t(0xF5), int8_t(0x05), int8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + int8_t result; + + result = etl::read_unchecked(bit_stream, 5U); + CHECK_EQUAL(int(expected[0]), int(result)); + + result = etl::read_unchecked(bit_stream, 5U); + CHECK_EQUAL(int(expected[1]), int(result)); + + result = etl::read_unchecked(bit_stream, 5U); + CHECK_EQUAL(int(expected[2]), int(result)); + + result = etl::read_unchecked(bit_stream, 5U); + CHECK_EQUAL(int(expected[3]), int(result)); + } + + //************************************************************************* + TEST(test_read_uint8_t) + { + std::array storage = { char(0x80), char(0x5A), char(0xA5), char(0xFF) }; + std::array expected = { uint8_t(0x01), uint8_t(0x5A), uint8_t(0xA5), uint8_t(0xFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint8_t_5bits) + { + std::array storage = { char(0x85), char(0x69), char(0xF0) }; + std::array expected = { uint8_t(0x01), uint8_t(0x15), uint8_t(0x05), uint8_t(0x1F) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[0]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[1]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[2]), int(result.value())); + + result.reset(); + result = bit_stream.read(5U); + CHECK(result.has_value()); + CHECK_EQUAL(int(expected[3]), int(result.value())); + + // One too many. + CHECK_THROW(bit_stream.read(5U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int16_t) + { + std::array storage = { char(0x80), char(0x00), char(0xA5), char(0x5A), + char(0x5A), char(0xA5), char(0xFF), char(0xFF) }; + std::array expected = { int16_t(0x0001), int16_t(0x5AA5), int16_t(0xA55A), int16_t(0xFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int16_t_10bits) + { + std::array storage = { char(0x80), char(0x16), char(0xAA), char(0x57), char(0xFF) }; + std::array expected = { int16_t(0x0001), int16_t(0x015A), int16_t(0xFEA5), int16_t(0xFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(10U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint16_t) + { + std::array storage = { char(0x80), char(0x00), char(0xA5), char(0x5A), + char(0x5A), char(0xA5), char(0xFF), char(0xFF) }; + std::array expected = { uint16_t(0x0001), uint16_t(0x5AA5), uint16_t(0xA55A), uint16_t(0xFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint16_t_10bits) + { + std::array storage = { char(0x80), char(0x16), char(0xAA), char(0x57), char(0xFF) }; + std::array expected = { uint16_t(0x0001), uint16_t(0x015A), uint16_t(0x02A5), uint16_t(0x03FF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(10U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(10U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int32_t) + { + std::array storage = { 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) }; + std::array expected = { int32_t(0x00000001), int32_t(0x5AA5A55A), int32_t(0xA55A5AA5), int32_t(0xFFFFFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int32_t_22bits) + { + std::array storage = { char(0x80), char(0x00), char(0x01), char(0x6A), + char(0x95), char(0x6A), char(0x55), char(0xAA), + char(0x7F), char(0xFF), char(0xFF) }; + std::array expected = { int32_t(0x00000001), int32_t(0x001AA55A), int32_t(0xFFE55AA5), int32_t(0xFFFFFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(22U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint32_t) + { + std::array storage = { 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) }; + std::array expected = { int32_t(0x00000001), int32_t(0x5AA5A55A), int32_t(0xA55A5AA5), int32_t(0xFFFFFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint32_t_22bits) + { + std::array storage = { char(0x80), char(0x00), char(0x01), char(0x6A), + char(0x95), char(0x6A), char(0x55), char(0xAA), + char(0x7F), char(0xFF), char(0xFF) }; + std::array expected = { uint32_t(0x00000001), uint32_t(0x001AA55A), uint32_t(0x00255AA5), uint32_t(0x003FFFFF) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(22U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(22U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int64_t) + { + std::array storage = { char(0x80), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), + char(0xA5), char(0x5A), char(0x5A), char(0xA5), char(0x5A), char(0xA5), char(0xA5), char(0x5A), + 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(0xFF), char(0xFF), char(0xFF), char(0xFF) }; + std::array expected = { int64_t(0x0000000000000001LL), int64_t(0x5AA5A55AA55A5AA5LL), int64_t(0xA55A5AA55AA5A55ALL), int64_t(0xFFFFFFFFFFFFFFFFLL) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_int64_t_47bits) + { + std::array storage = { char(0x80), char(0x00), char(0x00), char(0x00), + char(0x00), char(0x00), char(0xB5), char(0x4A), + char(0xB5), char(0x4A), char(0xB5), char(0x4A), + char(0x95), char(0x6A), char(0x95), char(0x6A), + char(0x95), char(0x6F), char(0xFF), char(0xFF), + char(0xFF), char(0xFF), char(0xFF), char(0xF0) }; + std::array expected = { int64_t(0x0000000000000001LL), int64_t(0x0000255AA55AA55ALL), int64_t(0xFFFFDAA55AA55AA5LL), int64_t(0xFFFFFFFFFFFFFFFFLL) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(47U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint64_t) + { + std::array storage = { char(0x80), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), char(0x00), + char(0xA5), char(0x5A), char(0x5A), char(0xA5), char(0x5A), char(0xA5), char(0xA5), char(0x5A), + 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(0xFF), char(0xFF), char(0xFF), char(0xFF) }; + std::array expected = { uint64_t(0x0000000000000001ULL), uint64_t(0x5AA5A55AA55A5AA5ULL), uint64_t(0xA55A5AA55AA5A55AULL), uint64_t(0xFFFFFFFFFFFFFFFFULL) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_uint64_t_47bits) + { + std::array storage = { char(0x80), char(0x00), char(0x00), char(0x00), + char(0x00), char(0x00), char(0xB5), char(0x4A), + char(0xB5), char(0x4A), char(0xB5), char(0x4A), + char(0x95), char(0x6A), char(0x95), char(0x6A), + char(0x95), char(0x6F), char(0xFF), char(0xFF), + char(0xFF), char(0xFF), char(0xFF), char(0xF0) }; + std::array expected = { uint64_t(0x0000000000000001ULL), uint64_t(0x0000255AA55AA55AULL), uint64_t(0x00005AA55AA55AA5ULL), uint64_t(0x00007FFFFFFFFFFFULL) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + etl::optional result; + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[0], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[1], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[2], result.value()); + + result.reset(); + result = bit_stream.read(47U); + CHECK(result.has_value()); + CHECK_EQUAL(expected[3], result.value()); + + // One too many. + CHECK_THROW(bit_stream.read(47U), etl::bit_stream_overflow); + } + + //************************************************************************* + TEST(test_read_multiple_full_size) + { + int8_t c1 = 90; // 0x5A + uint16_t s1 = 4660; // 0x1234 + int32_t i1 = 0x89ABCDEF; // 0x89ABCDEF + int32_t i2 = 0xFEDCBA98; // 0xFEDCBA98 + uint16_t s2 = 22136; // 0x5678 + int8_t c2 = -91; // 0xA5 + + std::array storage = { char(0x5A), + char(0x2C), char(0x48), + char(0xF7), char(0xB3), char(0xD5), char(0x91), + char(0x19), char(0x5D), char(0x3B), char(0x7F), + char(0x1E), char(0x6A), + char(0xA5) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + auto result_c1 = bit_stream.read(); + CHECK(result_c1.has_value()); + CHECK_EQUAL(int8_t(0x5A), result_c1.value()); + + auto result_s1 = bit_stream.read(); + CHECK(result_s1.has_value()); + CHECK_EQUAL(uint16_t(0x1234), result_s1.value()); + + auto result_i1 = bit_stream.read(); + CHECK(result_i1.has_value()); + CHECK_EQUAL(int32_t(0x89ABCDEF), result_i1.value()); + + auto result_i2 = bit_stream.read(); + CHECK(result_i2.has_value()); + CHECK_EQUAL(int32_t(0xFEDCBA98), result_i2.value()); + + auto result_s2 = bit_stream.read(); + CHECK(result_s2.has_value()); + CHECK_EQUAL(uint16_t(0x5678), result_s2.value()); + + auto result_c2 = bit_stream.read(); + CHECK(result_c2.has_value()); + CHECK_EQUAL(int8_t(0xA5), result_c2.value()); + } + + //************************************************************************* + TEST(test_read_multiple_variable_size) + { + 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(0x58), char(0xB1), char(0x3E), char(0xF6), + char(0x7A), char(0x86), char(0x57), char(0x4E), + char(0xC3), char(0xCE), char(0x90) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + auto result_c1 = bit_stream.read(6U); + CHECK(result_c1.has_value()); + CHECK_EQUAL(int8_t(0x1A), result_c1.value()); + + auto result_s1 = bit_stream.read(13U); + CHECK(result_s1.has_value()); + CHECK_EQUAL(uint16_t(0x1234), result_s1.value()); + + auto result_i1 = bit_stream.read(23U); + CHECK(result_i1.has_value()); + CHECK_EQUAL(int32_t(0x002BCDEF), result_i1.value()); + + auto result_i2 = bit_stream.read(25U); + CHECK(result_i2.has_value()); + CHECK_EQUAL(int32_t(0x00DCBA98), result_i2.value()); + + auto result_s2 = bit_stream.read(11U); + CHECK(result_s2.has_value()); + CHECK_EQUAL(uint16_t(0x0678), result_s2.value()); + + auto result_c2 = bit_stream.read(7U); + CHECK(result_c2.has_value()); + CHECK_EQUAL(int8_t(0x25), result_c2.value()); + } + + //************************************************************************* + 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 = 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(0x58), char(0xB1), char(0x3E), char(0xF6), + char(0x7A), char(0x86), char(0x57), char(0x4E), + char(0xC3), char(0xCE), char(0x90) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + auto result_c1 = etl::read(bit_stream, 6U); + CHECK(result_c1.has_value()); + CHECK_EQUAL(int8_t(0x1A), result_c1.value()); + + auto result_s1 = etl::read(bit_stream, 13U); + CHECK(result_s1.has_value()); + CHECK_EQUAL(uint16_t(0x1234), result_s1.value()); + + auto result_i1 = etl::read(bit_stream, 23U); + CHECK(result_i1.has_value()); + CHECK_EQUAL(int32_t(0x002BCDEF), result_i1.value()); + + auto result_i2 = etl::read(bit_stream, 25U); + CHECK(result_i2.has_value()); + CHECK_EQUAL(int32_t(0x00DCBA98), result_i2.value()); + + auto result_s2 = etl::read(bit_stream, 11U); + CHECK(result_s2.has_value()); + CHECK_EQUAL(uint16_t(0x0678), result_s2.value()); + + auto result_c2 = etl::read(bit_stream, 7U); + CHECK(result_c2.has_value()); + CHECK_EQUAL(int8_t(0x25), result_c2.value()); + } + + //************************************************************************* + TEST(test_read_checked_object) + { + std::array storage = { char(0x74), char(0xDE), char(0xA2), char(0xCF), + char(0x6A), char(0xFB), char(0xA3), char(0x5E), + char(0x5D), char(0x30), char(0x9F), char(0x80) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + Object object1 = { -1234, -2372331, 250 }; + Object object2 = { 5678, 2201423, 126 }; + + etl::optional result1 = etl::read(bit_stream); + etl::optional result2 = etl::read(bit_stream); + + CHECK(result1.has_value()); + CHECK(result2.has_value()); + + CHECK_EQUAL(object1.s, result1.value().s); + CHECK_EQUAL(object1.i, result1.value().i); + CHECK_EQUAL(object1.c, result1.value().c); + + CHECK_EQUAL(object2.s, result2.value().s); + CHECK_EQUAL(object2.i, result2.value().i); + CHECK_EQUAL(object2.c, result2.value().c); + } + + //************************************************************************* + TEST(test_read_unchecked_object) + { + std::array storage = { char(0x74), char(0xDE), char(0xA2), char(0xCF), + char(0x6A), char(0xFB), char(0xA3), char(0x5E), + char(0x5D), char(0x30), char(0x9F), char(0x80) }; + + etl::bit_stream_reader bit_stream(storage.data(), storage.size(), etl::endian::little); + + CHECK_EQUAL(storage.size(), bit_stream.size_bytes()); + + Object object1 = { -1234, -2372331, 250 }; + Object object2 = { 5678, 2201423, 126 }; + + Object result1 = etl::read_unchecked(bit_stream); + Object result2 = etl::read_unchecked(bit_stream); + + CHECK_EQUAL(object1.s, result1.s); + CHECK_EQUAL(object1.i, result1.i); + CHECK_EQUAL(object1.c, result1.c); + + CHECK_EQUAL(object2.s, result2.s); + CHECK_EQUAL(object2.i, result2.i); + CHECK_EQUAL(object2.c, result2.c); + } + }; +} diff --git a/test/test_bit_stream_writer_big_endian.cpp b/test/test_bit_stream_writer_big_endian.cpp index ecfb189a..7b07ab3e 100644 --- a/test/test_bit_stream_writer_big_endian.cpp +++ b/test/test_bit_stream_writer_big_endian.cpp @@ -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 storage; std::array 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 storage; std::array 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 storage; storage.fill(0); diff --git a/test/test_bit_stream_writer_little_endian.cpp b/test/test_bit_stream_writer_little_endian.cpp index 6c6d0464..9a9e6fbc 100644 --- a/test/test_bit_stream_writer_little_endian.cpp +++ b/test/test_bit_stream_writer_little_endian.cpp @@ -329,9 +329,9 @@ namespace { std::array storage; std::array 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 storage; std::array 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 storage; std::array 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 storage; std::array expected = { char(0x58), char(0xB1), char(0x3E), char(0xF6), diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 3a52ace3..fc89c487 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -10912,6 +10912,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 2547f609..7c94ce46 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -3257,6 +3257,9 @@ Tests\Binary + + Tests\Binary +