diff --git a/include/etl/binary.h b/include/etl/binary.h index 82bbbaeb1..a06293469 100644 --- a/include/etl/binary.h +++ b/include/etl/binary.h @@ -344,8 +344,8 @@ namespace etl ETL_ASSERT((NBITS <= std::numeric_limits::digits), ETL_ERROR(binary_out_of_range)); - TReturn mask = TReturn(1U) << (NBITS - 1); - value = value & ((1U << NBITS) - 1); + TReturn mask = TReturn(1) << (NBITS - 1); + value = value & static_cast((TReturn(1) << NBITS) - 1); return TReturn((value ^ mask) - mask); } @@ -364,8 +364,8 @@ namespace etl ETL_ASSERT((NBITS <= std::numeric_limits::digits), ETL_ERROR(binary_out_of_range)); - TReturn mask = TReturn(1U) << (NBITS - 1); - value = (value >> SHIFT) & ((1U << NBITS) - 1); + TReturn mask = TReturn(1) << (NBITS - 1); + value = (value >> SHIFT) & static_cast((TReturn(1) << NBITS) - 1); return TReturn((value ^ mask) - mask); } diff --git a/include/etl/bit_stream.h b/include/etl/bit_stream.h new file mode 100644 index 000000000..c6055ff4f --- /dev/null +++ b/include/etl/bit_stream.h @@ -0,0 +1,529 @@ +#ifndef ETL_BIT_STREAM_INCLUDED +#define ETL_BIT_STREAM_INCLUDED + +#include +#include + +#include "etl/platform.h" +#include "etl/type_traits.h" +#include "etl/nullptr.h" +#include "etl/endianness.h" +#include "etl/integral_limits.h" +#include "etl/binary.h" + +#include "etl/stl/algorithm.h" +#include "etl/stl/iterator.h" + +#include "private/minmax_push.h" + +namespace etl +{ + //*************************************************************************** + /// Encodes and decodes bitstreams. + /// Data must be stored in the stream in network order. + //*************************************************************************** + class bit_stream + { + public: + + typedef const unsigned char* const_iterator; + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + bit_stream() + : pdata(nullptr), + length(0U) + { + restart(); + } + + //*************************************************************************** + /// Construct from range. + //*************************************************************************** + bit_stream(char* begin_, char* end_) + : pdata(reinterpret_cast(begin_)), + length(std::distance(begin_, end_)) + { + restart(); + } + + //*************************************************************************** + /// Construct from range. + //*************************************************************************** + bit_stream(unsigned char* begin_, unsigned char* end_) + : pdata(begin_), + length(std::distance(begin_, end_)) + { + restart(); + } + + //*************************************************************************** + /// Construct from begin and length. + //*************************************************************************** + bit_stream(char* begin_, size_t length_) + : pdata(reinterpret_cast(begin_)), + length(length_) + { + restart(); + } + + //*************************************************************************** + /// Construct from begin and length. + //*************************************************************************** + bit_stream(unsigned char* begin_, size_t length_) + : pdata(begin_), + length(length_) + { + restart(); + } + + //*************************************************************************** + /// Construct from begin and length. + //*************************************************************************** + void set_stream(char* begin_, size_t length_) + { + pdata = reinterpret_cast(begin_); + length = length_; + restart(); + } + + //*************************************************************************** + /// Construct from begin and length. + //*************************************************************************** + void set_stream(unsigned char* begin_, size_t length_) + { + pdata = begin_; + length = length_; + restart(); + } + + //*************************************************************************** + /// Construct from range. + //*************************************************************************** + void set_stream(char* begin_, char* end_) + { + set_stream(begin_, std::distance(begin_, end_)); + } + + //*************************************************************************** + /// Construct from range. + //*************************************************************************** + void set_stream(unsigned char* begin_, unsigned char* end_) + { + set_stream(begin_, std::distance(begin_, end_)); + } + + //*************************************************************************** + /// Sets the indexes back to the beginning of the stream. + //*************************************************************************** + void restart() + { + bits_in_byte = 8; + byte_index = 0U; + bits_remaining = CHAR_BIT * length; + } + + //*************************************************************************** + /// Returns true if the bitsteam indexes have reached the end. + //*************************************************************************** + bool at_end() const + { + return (bits_remaining == 0U); + } + + //*************************************************************************** + /// Puts a boolean to the stream + //*************************************************************************** + bool put(bool value) + { + bool success = false; + + if (pdata != nullptr) + { + if (bits_remaining > 0) + { + unsigned char chunk = value ? 1 : 0; + put_integral(uint32_t(chunk), 1); + success = true; + } + } + + return success; + } + + //*************************************************************************** + /// For integral types + //*************************************************************************** + template + typename etl::enable_if::value, bool>::type + put(T value, uint_least8_t width = CHAR_BIT * sizeof(T)) + { + return put_integral(static_cast(value), width); + } + + //*************************************************************************** + /// For 64bit integral types + //*************************************************************************** + bool put(int64_t value, uint_least8_t width = CHAR_BIT * sizeof(int64_t)) + { + return put_integral(uint64_t(value), width); + } + + //*************************************************************************** + /// For 64bit integral types + //*************************************************************************** + bool put(uint64_t value, uint_least8_t width = CHAR_BIT * sizeof(uint64_t)) + { + return put_integral(value, width); + } + + //*************************************************************************** + /// For floating point types + //*************************************************************************** + template + typename etl::enable_if::value, bool>::type + put(T value) + { + bool success = true; + + unsigned char data[sizeof(T)]; + to_bytes(value, data); + + for (size_t i = 0; i < sizeof(T); ++i) + { + if (!put_integral(uint32_t(data[i]), CHAR_BIT)) + { + success = false; + } + } + + return success; + } + + //*************************************************************************** + /// For bool types + //*************************************************************************** + bool get(bool& value) + { + bool success = false; + + if (pdata != nullptr) + { + // Do we have enough bits? + if (bits_remaining > 0) + { + value = get_bit(); + success = true; + } + } + + return success; + } + + //*************************************************************************** + /// For integral types + //*************************************************************************** + template + typename etl::enable_if::value, bool>::type + get(T& value, uint_least8_t width = CHAR_BIT * sizeof(T)) + { + bool success = false; + uint_least8_t bits = width; + + if (pdata != nullptr) + { + // Do we have enough bits? + if (bits_remaining >= width) + { + value = 0; + + // Get the bits from the stream. + while (width != 0) + { + unsigned char mask_width = static_cast(std::min(width, bits_in_byte)); + unsigned char chunk = get_chunk(mask_width); + + width -= mask_width; + value |= static_cast(chunk) << width; + } + + success = true; + } + } + + // 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 success; + } + + //*************************************************************************** + /// For floating point types + //*************************************************************************** + template + typename etl::enable_if::value, bool>::type + get(T& value) + { + bool success = false; + + if (pdata != nullptr) + { + uint_least8_t width = CHAR_BIT * sizeof(T); + + // Do we have enough bits? + if (bits_remaining >= width) + { + // Temporary storage. + unsigned char data[sizeof(T)]; + + for (size_t i = 0; i < sizeof(T); ++i) + { + get(data[i], CHAR_BIT); + } + + from_bytes(data, value); + + bits_remaining -= width; + + success = true; + } + } + + return success; + } + + //*************************************************************************** + /// Returns the number of bytes used in the stream. + //*************************************************************************** + size_t size() const + { + size_t s = byte_index; + + // Current byte is used? + if (bits_in_byte != CHAR_BIT) + { + ++s; + } + + return s; + } + + //*************************************************************************** + /// Returns the number of bits used in the stream. + //*************************************************************************** + size_t bits() const + { + return (length * CHAR_BIT) - bits_remaining; + } + + //*************************************************************************** + /// Returns start of the stream. + //*************************************************************************** + const_iterator begin() const + { + return pdata; + } + + //*************************************************************************** + /// Returns end of the stream. + //*************************************************************************** + const_iterator end() const + { + return pdata + size(); + } + + private: + + //*************************************************************************** + /// For unsigned integral types + //*************************************************************************** + bool put_integral(uint32_t value, uint_least8_t width) + { + bool success = false; + + if (pdata != nullptr) + { + // Do we have enough bits? + if (bits_remaining >= width) + { + // Send the bits to the stream. + while (width != 0) + { + unsigned char mask_width = static_cast(std::min(width, bits_in_byte)); + width -= mask_width; + uint32_t mask = ((uint32_t(1U) << mask_width) - 1U) << width; + + // Move chunk to lowest char bits. + // Chunks are never larger than one char. + uint32_t chunk = ((value & mask) >> width) << (bits_in_byte - mask_width); + + put_chunk(static_cast(chunk), mask_width); + } + + success = true; + } + } + + return success; + } + + //*************************************************************************** + /// For unsigned integral types. 64bit + //*************************************************************************** + bool put_integral(uint64_t value, uint_least8_t width) + { + bool success = false; + + if (pdata != nullptr) + { + // Do we have enough bits? + if (bits_remaining >= width) + { + // Send the bits to the stream. + while (width != 0) + { + unsigned char mask_width = static_cast(std::min(width, bits_in_byte)); + width -= mask_width; + uint64_t mask = ((uint64_t(1U) << mask_width) - 1U) << width; + + // Move chunk to lowest char bits. + // Chunks are never larger than one char. + uint64_t chunk = ((value & mask) >> width) << (bits_in_byte - mask_width); + + put_chunk(static_cast(chunk), mask_width); + } + + success = true; + } + } + + return success; + } + + //*************************************************************************** + /// Put a data chunk to the stream + //*************************************************************************** + void put_chunk(unsigned char chunk, unsigned char width) + { + // Clear if new byte. + if (bits_in_byte == 8) + { + pdata[byte_index] = 0U; + } + + pdata[byte_index] |= chunk; + step(width); + } + + //*************************************************************************** + /// Get a data chunk from the stream + //*************************************************************************** + unsigned char get_chunk(unsigned char width) + { + unsigned char value = pdata[byte_index]; + + value >>= (bits_in_byte - width); + + unsigned char mask; + + if (width == CHAR_BIT) + { + mask = etl::integral_limits::max; + } + else + { + mask = (1U << width) - 1; + } + + value &= mask; + + step(width); + + return value; + } + + //*************************************************************************** + /// Get a bool from the stream + //*************************************************************************** + bool get_bit() + { + bool result = (pdata[byte_index] & (1 << (bits_in_byte - 1))) != 0; + + step(1U); + + return result; + } + + //*************************************************************************** + /// Helper function for floating point types + //*************************************************************************** + template + void from_bytes(const unsigned char* data, T& value) + { + unsigned char temp[sizeof(T)]; + + // Network to host. + if (etl::endianness::value() == etl::endian::little) + { + std::reverse_copy(data, data + sizeof(T), temp); + } + else + { + std::copy(data, data + sizeof(T), temp); + } + + value = *reinterpret_cast(temp); + } + + //*************************************************************************** + /// Helper function for floating point types + //*************************************************************************** + 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) + { + std::reverse_copy(pf, pf + sizeof(T), data); + } + else + { + std::copy(pf, pf + sizeof(T), data); + } + } + + //*************************************************************************** + /// Step the specified number of bits along the stream. + /// The width will never be larger than 'bits_in_byte'. + //*************************************************************************** + void step(unsigned char width) + { + bits_in_byte -= width; + + if (bits_in_byte == 0) + { + ++byte_index; + bits_in_byte = 8; + } + + bits_remaining -= width; + } + + unsigned char *pdata; ///< The start of the bitstream buffer. + size_t length; ///< The length, in unsigned char, of the bitstream buffer. + unsigned char bits_in_byte; ///< The number of available bits in the current char. + size_t byte_index; ///< The index of the char in the bitstream buffer. + size_t bits_remaining; ///< The number of bits still available in the bitstream buffer. + }; +} + +#include "private/minmax_pop.h" + +#endif diff --git a/include/etl/endianness.h b/include/etl/endianness.h index f779b65ef..3bb189cd5 100644 --- a/include/etl/endianness.h +++ b/include/etl/endianness.h @@ -35,6 +35,7 @@ SOFTWARE. #include "platform.h" #include "enum_type.h" +#include "binary.h" ///\defgroup endian endian /// Constants & utilities for endianess @@ -101,6 +102,96 @@ namespace etl return (u.ui16[0] == 0x5678) ? etl::endian::little : etl::endian::big; } }; + + //*************************************************************************** + inline uint8_t ntoh(const uint8_t network) + { + return network; + } + + //*************************************************************************** + inline uint16_t ntoh(const uint16_t network) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(network); + } + else + { + return network; + } + } + + //*************************************************************************** + inline uint32_t ntoh(const uint32_t network) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(network); + } + else + { + return network; + } + } + + //*************************************************************************** + inline uint64_t ntoh(const uint64_t network) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(network); + } + else + { + return network; + } + } + + //*************************************************************************** + inline uint8_t hton(const uint8_t host) + { + return host; + } + + //*************************************************************************** + inline uint16_t hton(const uint16_t host) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(host); + } + else + { + return host; + } + } + + //*************************************************************************** + inline uint32_t hton(const uint32_t host) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(host); + } + else + { + return host; + } + } + + //*************************************************************************** + inline uint64_t hton(const uint64_t host) + { + if (endianness::value() == endian::little) + { + return etl::reverse_bytes(host); + } + else + { + return host; + } + } } #endif diff --git a/include/etl/profiles/armv6.h b/include/etl/profiles/armv6.h index 9e39d0182..8570b9e4e 100644 --- a/include/etl/profiles/armv6.h +++ b/include/etl/profiles/armv6.h @@ -37,7 +37,7 @@ SOFTWARE. #define ETL_TARGET_DEVICE_ARM #define ETL_TARGET_OS_NONE -#define ETL_COMPILER_ARM6 +#define ETL_COMPILER_CLANG #define ETL_CPP11_SUPPORTED 1 #define ETL_CPP14_SUPPORTED 0 #define ETL_CPP17_SUPPORTED 0 diff --git a/include/etl/profiles/armv6_no_stl.h b/include/etl/profiles/armv6_no_stl.h index fbf4fc6e5..07bc98ba3 100644 --- a/include/etl/profiles/armv6_no_stl.h +++ b/include/etl/profiles/armv6_no_stl.h @@ -37,7 +37,7 @@ SOFTWARE. #define ETL_TARGET_DEVICE_ARM #define ETL_TARGET_OS_NONE -#define ETL_COMPILER_ARM6 +#define ETL_COMPILER_CLANG #define ETL_CPP11_SUPPORTED 1 #define ETL_CPP14_SUPPORTED 0 #define ETL_CPP17_SUPPORTED 0 diff --git a/include/etl/scheduler.h b/include/etl/scheduler.h index 210854590..218f4fe5e 100644 --- a/include/etl/scheduler.h +++ b/include/etl/scheduler.h @@ -376,8 +376,6 @@ namespace etl { ETL_ASSERT(task_list.size() > 0, ETL_ERROR(etl::scheduler_no_tasks_exception)); - const size_t task_list_size = task_list.size(); - scheduler_running = true; while (!scheduler_exit) diff --git a/include/etl/unordered_map.h b/include/etl/unordered_map.h index 86890a0ff..7dabff955 100644 --- a/include/etl/unordered_map.h +++ b/include/etl/unordered_map.h @@ -772,7 +772,6 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full)); const key_type& key = key_value_pair.first; - const mapped_type& mapped = key_value_pair.second; // Get the hash index. size_t index = get_bucket_index(key); diff --git a/include/etl/unordered_multimap.h b/include/etl/unordered_multimap.h index e1222b41a..80ff8d91d 100644 --- a/include/etl/unordered_multimap.h +++ b/include/etl/unordered_multimap.h @@ -663,7 +663,6 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full)); const key_type& key = key_value_pair.first; - const mapped_type& mapped = key_value_pair.second; // Get the hash index. size_t index = get_bucket_index(key); diff --git a/include/etl/version.h b/include/etl/version.h index 365eebfdc..65c0c1f1c 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -37,13 +37,13 @@ SOFTWARE. /// Definitions of the ETL version ///\ingroup utilities -#define ETL_VERSION "12.1.1" -#define ETL_VERSION_W L"12.1.1" -#define ETL_VERSION_U16 u"12.1.1" -#define ETL_VERSION_U32 U"12.1.1" -#define ETL_VERSION_MAJOR 12 -#define ETL_VERSION_MINOR 1 -#define ETL_VERSION_PATCH 1 +#define ETL_VERSION "13.0.0" +#define ETL_VERSION_W L"13.0.0" +#define ETL_VERSION_U16 u"13.0.0" +#define ETL_VERSION_U32 U"13.0.0" +#define ETL_VERSION_MAJOR 13 +#define ETL_VERSION_MINOR 0 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION_VALUE ((ETL_VERSION_MAJOR * 10000) + (ETL_VERSION_MINOR * 100) + ETL_VERSION_PATCH) #endif diff --git a/support/Release notes.txt b/support/Release notes.txt index 4be3e53c5..dca882a5b 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +13.0.0 +Added bit stream serialiser/deserialiser + =============================================================================== 12.1.1 Added random_pcg Permuted Congruential Generator diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index 8c0190fe4..847415b54 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -156,6 +156,7 @@ + @@ -348,6 +349,7 @@ + @@ -388,6 +390,7 @@ + diff --git a/test/test_bit_stream.cpp b/test/test_bit_stream.cpp new file mode 100644 index 000000000..05dd906c0 --- /dev/null +++ b/test/test_bit_stream.cpp @@ -0,0 +1,1081 @@ +/****************************************************************************** +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 "UnitTest++.h" + +#include "etl/bit_stream.h" + +#include +#include + +namespace +{ + //*********************************** + struct Object + { + int16_t i; + double d; + uint8_t c; + }; + + bool operator ==(const Object& lhs, const Object& rhs) + { + return (lhs.i == rhs.i) && + (lhs.d == rhs.d) && + (lhs.c == rhs.c); + } + + std::ostream& operator << (std::ostream& os, const Object& object) + { + os << object.i << "," << object.d << "," << (int)object.c; + return os; + } +} + +namespace etl +{ + //*********************************** + bool bit_stream_put(etl::bit_stream& stream, const Object& object) + { + bool success = true; + + if (!stream.put(object.i, 14)) + { + success = false; + } + + if (!stream.put(object.d)) + { + success = false; + } + + if (!stream.put(object.c)) + { + success = false; + } + + return success; + } + + //*********************************** + bool bit_stream_get(etl::bit_stream& stream, Object& object) + { + bool success = true; + + if (!stream.get(object.i, 14)) + { + success = false; + } + + if (!stream.get(object.d)) + { + success = false; + } + + if (!stream.get(object.c)) + { + success = false; + } + + return success; + } +} + +namespace +{ + SUITE(test_bit_stream) + { + //************************************************************************* + TEST(put_bool) + { + unsigned char storage = 0; + unsigned char compare_data = 0x5A; + + etl::bit_stream bit_stream(&storage, 1); + + CHECK(bit_stream.put(false)); + CHECK(bit_stream.put(true)); + CHECK(bit_stream.put(false)); + CHECK(bit_stream.put(true)); + CHECK(bit_stream.put(true)); + CHECK(bit_stream.put(false)); + CHECK(bit_stream.put(true)); + CHECK(bit_stream.put(false)); + + // One too many. + CHECK(!bit_stream.put(true)); + + CHECK_EQUAL(int(compare_data), int(storage)); + } + + //************************************************************************* + TEST(put_int8_t) + { + std::array storage; + + std::array compare_data; + std::iota(compare_data.begin(), compare_data.end(), 0); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + for (size_t i = 0; i < 256; ++i) + { + CHECK(bit_stream.put(int8_t(i))); + } + + // One too many. + CHECK(!bit_stream.put(int8_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_uint8_t) + { + std::array storage; + + std::array compare_data; + std::iota(compare_data.begin(), compare_data.end(), 0); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + for (size_t i = 0; i < 256; ++i) + { + CHECK(bit_stream.put(uint8_t(i))); + } + + // One too many. + CHECK(!bit_stream.put(uint8_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_int16_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x01, 0x5A, 0xA5, 0xA5, 0x5A, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(int16_t(0x0001))); + CHECK(bit_stream.put(int16_t(0x5AA5))); + CHECK(bit_stream.put(int16_t(0xA55A))); + CHECK(bit_stream.put(int16_t(0xFFFF))); + + // One too many. + CHECK(!bit_stream.put(int16_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_uint16_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x01, 0x5A, 0xA5, 0xA5, 0x5A, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(uint16_t(0x0001))); + CHECK(bit_stream.put(uint16_t(0x5AA5))); + CHECK(bit_stream.put(uint16_t(0xA55A))); + CHECK(bit_stream.put(uint16_t(0xFFFF))); + + // One too many. + CHECK(!bit_stream.put(uint16_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_int32_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x00, 0x00, 0x01, + 0x5A, 0xA5, 0xA5, 0x5A, + 0xA5, 0x5A, 0x5A, 0xA5, + 0xFF, 0xFF, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(int32_t(0x00000001))); + CHECK(bit_stream.put(int32_t(0x5AA5A55A))); + CHECK(bit_stream.put(int32_t(0xA55A5AA5))); + CHECK(bit_stream.put(int32_t(0xFFFFFFFF))); + + // One too many. + CHECK(!bit_stream.put(int32_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_uint32_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x00, 0x00, 0x01, + 0x5A, 0xA5, 0xA5, 0x5A, + 0xA5, 0x5A, 0x5A, 0xA5, + 0xFF, 0xFF, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(uint32_t(0x00000001))); + CHECK(bit_stream.put(uint32_t(0x5AA5A55A))); + CHECK(bit_stream.put(uint32_t(0xA55A5AA5))); + CHECK(bit_stream.put(uint32_t(0xFFFFFFFF))); + + // One too many. + CHECK(!bit_stream.put(uint32_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_int64_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x5A, 0xA5, 0xA5, 0x5A, 0xA5, 0x5A, 0x5A, 0xA5, + 0xA5, 0x5A, 0x5A, 0xA5, 0x5A, 0xA5, 0xA5, 0x5A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(int64_t(0x0000000000000001))); + CHECK(bit_stream.put(int64_t(0x5AA5A55AA55A5AA5))); + CHECK(bit_stream.put(int64_t(0xA55A5AA55AA5A55A))); + CHECK(bit_stream.put(int64_t(0xFFFFFFFFFFFFFFFF))); + + // One too many. + CHECK(!bit_stream.put(int64_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_uint64_t) + { + // Tests assume big endian. + std::array storage; + std::array compare_data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x5A, 0xA5, 0xA5, 0x5A, 0xA5, 0x5A, 0x5A, 0xA5, + 0xA5, 0x5A, 0x5A, 0xA5, 0x5A, 0xA5, 0xA5, 0x5A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + CHECK(compare_data.size() == storage.size()); + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + CHECK(bit_stream.put(uint64_t(0x0000000000000001))); + CHECK(bit_stream.put(uint64_t(0x5AA5A55AA55A5AA5))); + CHECK(bit_stream.put(uint64_t(0xA55A5AA55AA5A55A))); + CHECK(bit_stream.put(uint64_t(0xFFFFFFFFFFFFFFFF))); + + // One too many. + CHECK(!bit_stream.put(uint64_t(0))); + + for (size_t i = 0; i < storage.size(); ++i) + { + CHECK_EQUAL(int(compare_data[i]), int(storage[i])); + } + } + + //************************************************************************* + TEST(put_get_bool) + { + std::array flags = + { + false, true, false, true, true, false, true, false + }; + + unsigned char storage = 0; + etl::bit_stream bit_stream(&storage, 1); + + for (size_t i = 0; i < flags.size(); ++i) + { + bit_stream.put(flags[i]); + } + + bit_stream.restart(); + + for (size_t i = 0; i < flags.size(); ++i) + { + bool flag; + CHECK(bit_stream.get(flag)); + CHECK_EQUAL(flags[i], flag); + } + } + + //************************************************************************* + TEST(put_get_int8_t) + { + std::array storage; + std::array put_data = { int8_t(0x01), int8_t(0x5A), int8_t(0xA5), int8_t(0xFF) }; + std::array get_data = { int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x00) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], (int)get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], (int)get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], (int)get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], (int)get_data[3]); + } + + //************************************************************************* + TEST(put_get_int8_t_5bits) + { + std::array storage; + std::array put_data = { int8_t(0x01), int8_t(0x15), int8_t(0xA5), int8_t(0x1F) }; // 1, -11, 10, -1 + std::array expect_data = { int8_t(0x01), int8_t(0xF5), int8_t(0x05), int8_t(0xFF) }; // 1, -11, 10, -1 + std::array get_data = { int8_t(0x00), int8_t(0x00), int8_t(0x00), int8_t(0x00) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 5); + bit_stream.put(put_data[1], 5); + bit_stream.put(put_data[2], 5); + bit_stream.put(put_data[3], 5); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 5)); + CHECK_EQUAL((int)expect_data[0], (int)get_data[0]); + + CHECK(bit_stream.get(get_data[1], 5)); + CHECK_EQUAL((int)expect_data[1], (int)get_data[1]); + + CHECK(bit_stream.get(get_data[2], 5)); + CHECK_EQUAL((int)expect_data[2], (int)get_data[2]); + + CHECK(bit_stream.get(get_data[3], 5)); + CHECK_EQUAL((int)expect_data[3], (int)get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint8_t) + { + std::array storage; + std::array put_data = { uint8_t(0x01), uint8_t(0x5A), uint8_t(0xA5), uint8_t(0xFF) }; + std::array get_data = { uint8_t(0x00), uint8_t(0x00), uint8_t(0x00), uint8_t(0x00) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], (int)get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], (int)get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], (int)get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], (int)get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint8_t_5bits) + { + std::array storage; + std::array put_data = { uint8_t(0x01), uint8_t(0x5A), uint8_t(0xA5), uint8_t(0xFF) }; // 1, -11, 10, -1 + std::array expect_data = { uint8_t(0x01), uint8_t(0x1A), uint8_t(0x05), uint8_t(0x1F) }; // 1, -11, 10, -1 + std::array get_data = { uint8_t(0x00), uint8_t(0x00), uint8_t(0x00), uint8_t(0x00) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 5); + bit_stream.put(put_data[1], 5); + bit_stream.put(put_data[2], 5); + bit_stream.put(put_data[3], 5); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 5)); + CHECK_EQUAL((int)expect_data[0], (int)get_data[0]); + + CHECK(bit_stream.get(get_data[1], 5)); + CHECK_EQUAL((int)expect_data[1], (int)get_data[1]); + + CHECK(bit_stream.get(get_data[2], 5)); + CHECK_EQUAL((int)expect_data[2], (int)get_data[2]); + + CHECK(bit_stream.get(get_data[3], 5)); + CHECK_EQUAL((int)expect_data[3], (int)get_data[3]); + } + + //************************************************************************* + TEST(put_get_int16_t) + { + std::array storage; + std::array put_data = { int16_t(0x0001), int16_t(0xA55A), int16_t(0x5AA5), int16_t(0xFFFF) }; + std::array get_data = { int16_t(0x0000), int16_t(0x0000), int16_t(0x0000), int16_t(0x0000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_int16_t_10bits) + { + std::array storage; + std::array put_data = { int16_t(0x0001), int16_t(0xA55A), int16_t(0x5AA5), int16_t(0xFFFF) }; + std::array expect_data = { int16_t(0x0001), int16_t(0x015A), int16_t(0xFEA5), int16_t(0xFFFF) }; + std::array get_data = { int16_t(0x0000), int16_t(0x0000), int16_t(0x0000), int16_t(0x0000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 10); + bit_stream.put(put_data[1], 10); + bit_stream.put(put_data[2], 10); + bit_stream.put(put_data[3], 10); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 10)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 10)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 10)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 10)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint16_t) + { + std::array storage; + std::array put_data = { uint16_t(0x0001), uint16_t(0xA55A), uint16_t(0x5AA5), uint16_t(0xFFFF) }; + std::array get_data = { uint16_t(0x0000), uint16_t(0x0000), uint16_t(0x0000), uint16_t(0x0000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint16_t_10bits) + { + std::array storage; + std::array put_data = { uint16_t(0x0001), uint16_t(0xA55A), uint16_t(0x5AA5), uint16_t(0xFFFF) }; + std::array expect_data = { uint16_t(0x0001), uint16_t(0x015A), uint16_t(0x02A5), uint16_t(0x03FF) }; + std::array get_data = { uint16_t(0x0000), uint16_t(0x0000), uint16_t(0x0000), uint16_t(0x0000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 10); + bit_stream.put(put_data[1], 10); + bit_stream.put(put_data[2], 10); + bit_stream.put(put_data[3], 10); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 10)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 10)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 10)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 10)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_int32_t) + { + std::array storage; + std::array put_data = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) }; + std::array get_data = { int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_int32_t_22bits) + { + std::array storage; + std::array put_data = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) }; + std::array expect_data = { int32_t(0x00000001), int32_t(0x001AA55A), int32_t(0xFFE55AA5), int32_t(0xFFFFFFFF) }; + std::array get_data = { int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 22); + bit_stream.put(put_data[1], 22); + bit_stream.put(put_data[2], 22); + bit_stream.put(put_data[3], 22); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 22)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 22)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 22)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 22)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint32_t) + { + std::array storage; + std::array put_data = { uint32_t(0x00000001), uint32_t(0xA55AA55A), uint32_t(0x5AA55AA5), uint32_t(0xFFFFFFFF) }; + std::array get_data = { uint32_t(0x00000000), uint32_t(0x00000000), uint32_t(0x00000000), uint32_t(0x00000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(put_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(put_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(put_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(put_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint32_t_22bits) + { + std::array storage; + std::array put_data = { uint32_t(0x00000001), uint32_t(0xA55AA55A), uint32_t(0x5AA55AA5), uint32_t(0xFFFFFFFF) }; + std::array expect_data = { uint32_t(0x00000001), uint32_t(0x001AA55A), uint32_t(0x00255AA5), uint32_t(0x003FFFFF) }; + std::array get_data = { uint32_t(0x00000000), uint32_t(0x00000000), uint32_t(0x00000000), uint32_t(0x00000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 22); + bit_stream.put(put_data[1], 22); + bit_stream.put(put_data[2], 22); + bit_stream.put(put_data[3], 22); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 22)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 22)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 22)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 22)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_int64_t) + { + std::array storage; + std::array put_data = { int64_t(0x0000000000000001), int64_t(0xA55AA55AA55AA55A), int64_t(0x5AA55AA55AA55AA5), int64_t(0xFFFFFFFFFFFFFFFF) }; + std::array expect_data = { int64_t(0x0000000000000001), int64_t(0xA55AA55AA55AA55A), int64_t(0x5AA55AA55AA55AA5), int64_t(0xFFFFFFFFFFFFFFFF) }; + std::array get_data = { int64_t(0x0000000000000000), int64_t(0x0000000000000000), int64_t(0x0000000000000000), int64_t(0x0000000000000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_int64_t_47bits) + { + std::array storage; + std::array put_data = { int64_t(0x0000000000000001), int64_t(0xA55AA55AA55AA55A), int64_t(0x5AA55AA55AA55AA5), int64_t(0xFFFFFFFFFFFFFFFF) }; + std::array expect_data = { int64_t(0x0000000000000001), int64_t(0x0000255AA55AA55A), int64_t(0xFFFFDAA55AA55AA5), int64_t(0xFFFFFFFFFFFFFFFF) }; + std::array get_data = { int64_t(0x0000000000000000), int64_t(0x0000000000000000), int64_t(0x0000000000000000), int64_t(0x0000000000000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 47); + bit_stream.put(put_data[1], 47); + bit_stream.put(put_data[2], 47); + bit_stream.put(put_data[3], 47); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 47)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 47)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 47)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 47)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint64_t) + { + std::array storage; + std::array put_data = { uint64_t(0x0000000000000001), uint64_t(0xA55AA55AA55AA55A), uint64_t(0x5AA55AA55AA55AA5), uint64_t(0xFFFFFFFFFFFFFFFF) }; + std::array expect_data = { uint64_t(0x0000000000000001), uint64_t(0xA55AA55AA55AA55A), uint64_t(0x5AA55AA55AA55AA5), uint64_t(0xFFFFFFFFFFFFFFFF) }; + std::array get_data = { uint64_t(0x0000000000000000), uint64_t(0x0000000000000000), uint64_t(0x0000000000000000), uint64_t(0x0000000000000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0]); + bit_stream.put(put_data[1]); + bit_stream.put(put_data[2]); + bit_stream.put(put_data[3]); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0])); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1])); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2])); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3])); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_uint64_t_47bits) + { + std::array storage; + std::array put_data = { uint64_t(0x0000000000000001), uint64_t(0xA55AA55AA55AA55A), uint64_t(0x5AA55AA55AA55AA5), uint64_t(0xFFFFFFFFFFFFFFFF) }; + std::array expect_data = { uint64_t(0x0000000000000001), uint64_t(0x0000255AA55AA55A), uint64_t(0x00005AA55AA55AA5), uint64_t(0x00007FFFFFFFFFFF) }; + std::array get_data = { uint64_t(0x0000000000000000), uint64_t(0x0000000000000000), uint64_t(0x0000000000000000), uint64_t(0x0000000000000000) }; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream + bit_stream.put(put_data[0], 47); + bit_stream.put(put_data[1], 47); + bit_stream.put(put_data[2], 47); + bit_stream.put(put_data[3], 47); + + bit_stream.restart(); + + CHECK(bit_stream.get(get_data[0], 47)); + CHECK_EQUAL(expect_data[0], get_data[0]); + + CHECK(bit_stream.get(get_data[1], 47)); + CHECK_EQUAL(expect_data[1], get_data[1]); + + CHECK(bit_stream.get(get_data[2], 47)); + CHECK_EQUAL(expect_data[2], get_data[2]); + + CHECK(bit_stream.get(get_data[3], 47)); + CHECK_EQUAL(expect_data[3], get_data[3]); + } + + //************************************************************************* + TEST(put_get_multiple_full_size) + { + char c1 = 90; + char c2 = -91; + unsigned short s1 = 23205; + unsigned short s2 = 42330; + int32_t i1 = 1520786085; // 0x5AA55AA5 + int32_t i2 = -1520786086; // 0xA55AA55A + float f = 3.1415927f; + double d = 3.1415927; + long double ld = 3.1414927L; + + std::array storage; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream. + bit_stream.put(c1); + bit_stream.put(s1); + bit_stream.put(i1); + bit_stream.put(f); + bit_stream.put(i2); + bit_stream.put(d); + bit_stream.put(s2); + bit_stream.put(ld); + bit_stream.put(c2); + + bit_stream.restart(); + + char rc1; + char rc2; + unsigned short rs1; + unsigned short rs2; + int32_t ri1; + int32_t ri2; + float rf; + double rd; + long double rld; + + // Read them all back. + CHECK(bit_stream.get(rc1)); + CHECK_EQUAL(int(c1), int(rc1)); + + CHECK(bit_stream.get(rs1)); + CHECK_EQUAL(s1, rs1); + + CHECK(bit_stream.get(ri1)); + CHECK_EQUAL(i1, ri1); + + CHECK(bit_stream.get(rf)); + CHECK_CLOSE(f, rf, 0.1f); + + CHECK(bit_stream.get(ri2)); + CHECK_EQUAL(i2, ri2); + + CHECK(bit_stream.get(rd)); + CHECK_CLOSE(d, rd, 0.1); + + CHECK(bit_stream.get(rs2)); + CHECK_EQUAL(s2, rs2); + + CHECK(bit_stream.get(rld)); + CHECK_CLOSE(ld, rld, 0.1); + + CHECK(bit_stream.get(rc2)); + CHECK_EQUAL(int(c2), int(rc2)); + } + + //************************************************************************* + TEST(put_get_multiple_variable_size) + { + char c1 = 26; // 6 bits + char c2 = -10; // 7 bits + unsigned short s1 = 6742; // 13 bits + unsigned short s2 = 1878; // 11 bits + int32_t i1 = 2448037; // 23 bits + int32_t i2 = -10836646; // 25 bits + float f = 3.1415927f; + double d = 3.1415927; + long double ld = 3.1414927L; + int64_t ll = 140737488355327LL; + + std::array storage; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + // Insert into the stream. + bit_stream.put(c1, 6); + CHECK_EQUAL(1U, bit_stream.size()); + CHECK_EQUAL(6U, bit_stream.bits()); + + bit_stream.put(s1, 13); + CHECK_EQUAL(3U, bit_stream.size()); + CHECK_EQUAL(19U, bit_stream.bits()); + + bit_stream.put(i1, 23); + CHECK_EQUAL(6U, bit_stream.size()); + CHECK_EQUAL(42U, bit_stream.bits()); + + bit_stream.put(f); + CHECK_EQUAL(10U, bit_stream.size()); + CHECK_EQUAL(74U, bit_stream.bits()); + + bit_stream.put(i2, 25); + CHECK_EQUAL(13U, bit_stream.size()); + CHECK_EQUAL(99U, bit_stream.bits()); + + bit_stream.put(d); + CHECK_EQUAL(21U, bit_stream.size()); + CHECK_EQUAL(163U, bit_stream.bits()); + + bit_stream.put(s2, 11); + CHECK_EQUAL(22U, bit_stream.size()); + CHECK_EQUAL(174U, bit_stream.bits()); + + if (sizeof(long double) == 8) + { + bit_stream.put(ld); + CHECK_EQUAL(30U, bit_stream.size()); + CHECK_EQUAL(238U, bit_stream.bits()); + + bit_stream.put(c2, 7); + CHECK_EQUAL(31U, bit_stream.size()); + CHECK_EQUAL(245U, bit_stream.bits()); + + bit_stream.put(ll, 47); + CHECK_EQUAL(37U, bit_stream.size()); + CHECK_EQUAL(292U, bit_stream.bits()); + } + else if (sizeof(long double) == 12) + { + bit_stream.put(ld); + CHECK_EQUAL(34U, bit_stream.size()); + CHECK_EQUAL(270U, bit_stream.bits()); + + bit_stream.put(c2, 7); + CHECK_EQUAL(35U, bit_stream.size()); + CHECK_EQUAL(277U, bit_stream.bits()); + + bit_stream.put(ll, 47); + CHECK_EQUAL(41U, bit_stream.size()); + CHECK_EQUAL(324U, bit_stream.bits()); + } + else + { + assert(false); + } + + bit_stream.restart(); + + char rc1; + char rc2; + unsigned short rs1; + unsigned short rs2; + int32_t ri1; + int32_t ri2; + float rf; + double rd; + long double rld; + int64_t rll; + + // Read them all back. + CHECK(bit_stream.get(rc1, 6)); + CHECK_EQUAL(int(c1), int(rc1)); + + CHECK(bit_stream.get(rs1, 13)); + CHECK_EQUAL(s1, rs1); + + CHECK(bit_stream.get(ri1, 23)); + CHECK_EQUAL(i1, ri1); + + CHECK(bit_stream.get(rf)); + CHECK_CLOSE(f, rf, 0.1f); + + CHECK(bit_stream.get(ri2, 25)); + CHECK_EQUAL(i2, ri2); + + CHECK(bit_stream.get(rd)); + CHECK_CLOSE(d, rd, 0.1); + + CHECK(bit_stream.get(rs2, 11)); + CHECK_EQUAL(s2, rs2); + + CHECK(bit_stream.get(rld)); + CHECK_CLOSE(ld, rld, 0.1); + + CHECK(bit_stream.get(rc2, 7)); + CHECK_EQUAL(int(c2), int(rc2)); + + CHECK(bit_stream.get(rll, 47)); + CHECK_EQUAL(int(ll), int(rll)); + } + + //************************************************************************* + TEST(put_get_object_global) + { + std::array storage; + + etl::bit_stream bit_stream(storage.data(), storage.size()); + + Object object1 = { -1234, 2.71578369, 250 }; + Object object2 = { 5678, 5.24685744, 126 }; + + CHECK(etl::bit_stream_put(bit_stream, object1)); + CHECK(etl::bit_stream_put(bit_stream, object2)); + + Object object1a; + Object object2a; + + bit_stream.restart(); + + CHECK(etl::bit_stream_get(bit_stream, object1a)); + CHECK(etl::bit_stream_get(bit_stream, object2a)); + + CHECK_EQUAL(object1, object1a); + CHECK_EQUAL(object2, object2a); + } + }; +} diff --git a/test/test_list_shared_pool.cpp b/test/test_list_shared_pool.cpp index cc1591391..c5aa280ba 100644 --- a/test/test_list_shared_pool.cpp +++ b/test/test_list_shared_pool.cpp @@ -104,7 +104,7 @@ namespace { DataNDC data; - CHECK_EQUAL(data.max_size(), 0); + CHECK_EQUAL(data.max_size(), 0U); CHECK(data.has_shared_pool()); } @@ -403,7 +403,7 @@ namespace CHECK_EQUAL(0U, data1.size()); CHECK_EQUAL(half_data.size(), data2.size()); - bool are_equal = std::equal(data2.begin(), data2.end(), half_data.begin()); + are_equal = std::equal(data2.begin(), data2.end(), half_data.begin()); CHECK(are_equal); // Do it again to check that clear() didn't screw up the internals. @@ -696,7 +696,7 @@ namespace compare_data2.push_front(ItemNDC("7")); compare_data2.push_front(ItemNDC("8")); compare_data2.push_front(ItemNDC("9")); - + CHECK_NO_THROW(data1.push_front(ItemNDC("0"))); CHECK_NO_THROW(data1.push_front(ItemNDC("1"))); CHECK_NO_THROW(data1.push_front(ItemNDC("2"))); diff --git a/test/test_reference_flat_map.cpp b/test/test_reference_flat_map.cpp index 4e0988a7c..76014edb2 100644 --- a/test/test_reference_flat_map.cpp +++ b/test/test_reference_flat_map.cpp @@ -220,6 +220,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* @@ -492,6 +494,8 @@ namespace bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin()); + + CHECK(isEqual); } //************************************************************************* diff --git a/test/test_reference_flat_multimap.cpp b/test/test_reference_flat_multimap.cpp index 58d7fc712..2425f1a0b 100644 --- a/test/test_reference_flat_multimap.cpp +++ b/test/test_reference_flat_multimap.cpp @@ -178,6 +178,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* diff --git a/test/test_reference_flat_multiset.cpp b/test/test_reference_flat_multiset.cpp index 056e6a80a..ede583ba1 100644 --- a/test/test_reference_flat_multiset.cpp +++ b/test/test_reference_flat_multiset.cpp @@ -164,6 +164,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* diff --git a/test/test_reference_flat_set.cpp b/test/test_reference_flat_set.cpp index a38b3b4e2..ab7c4995e 100644 --- a/test/test_reference_flat_set.cpp +++ b/test/test_reference_flat_set.cpp @@ -176,6 +176,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 5a945d603..91a5ef056 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -806,7 +806,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const value_t INITIAL_VALUE = STR('A'); for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 4c8c93cfd..3d409062b 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -805,7 +805,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const value_t INITIAL_VALUE = STR('A'); for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index b25793d49..6e6c7f03a 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -803,7 +803,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const value_t INITIAL_VALUE = STR('A'); for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index 724aca5c6..0c43fe33d 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -805,7 +805,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const value_t INITIAL_VALUE = STR('A'); for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 25304d95d..4ef72f277 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -462,6 +462,7 @@ namespace CHECK((std::is_same::type, std::make_signed::type>::value)); CHECK((std::is_same::type, std::make_signed::type>::value)); CHECK((std::is_same::type, std::make_signed::type>::value)); + CHECK((std::is_same::type, std::make_signed::type>::value)); } //************************************************************************* @@ -487,6 +488,7 @@ namespace CHECK((std::is_same::type, std::make_unsigned::type>::value)); CHECK((std::is_same::type, std::make_unsigned::type>::value)); CHECK((std::is_same::type, std::make_unsigned::type>::value)); + CHECK((std::is_same::type, std::make_unsigned::type>::value)); } //************************************************************************* diff --git a/test/test_unordered_map.cpp b/test/test_unordered_map.cpp index c5f5c73cb..eff6662dd 100644 --- a/test/test_unordered_map.cpp +++ b/test/test_unordered_map.cpp @@ -125,7 +125,7 @@ namespace DC M17 = DC("R"); DC M18 = DC("S"); DC M19 = DC("T"); - + const char* K0 = "FF"; // 0 const char* K1 = "FG"; // 1 const char* K2 = "FH"; // 2 @@ -240,6 +240,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* @@ -508,7 +510,7 @@ namespace DataNDC::iterator idata_end = data.begin(); std::advance(idata_end, 5); - + data.erase(idata, idata_end); CHECK_EQUAL(initial_data.size() - 3, data.size()); diff --git a/test/test_unordered_multimap.cpp b/test/test_unordered_multimap.cpp index 65106b716..f0d1a2eb5 100644 --- a/test/test_unordered_multimap.cpp +++ b/test/test_unordered_multimap.cpp @@ -217,6 +217,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* diff --git a/test/test_unordered_multiset.cpp b/test/test_unordered_multiset.cpp index 71f069ddd..5b6095dbf 100644 --- a/test/test_unordered_multiset.cpp +++ b/test/test_unordered_multiset.cpp @@ -151,6 +151,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* @@ -397,7 +399,7 @@ namespace CHECK_EQUAL(data.size(), size_t(0)); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_count_key) { @@ -474,7 +476,7 @@ namespace CHECK_EQUAL(std::distance(result.first, result.second), 1); CHECK_EQUAL(*result.first, N2); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_equal) { diff --git a/test/test_unordered_set.cpp b/test/test_unordered_set.cpp index 55f28f823..69150180e 100644 --- a/test/test_unordered_set.cpp +++ b/test/test_unordered_set.cpp @@ -143,6 +143,8 @@ namespace IDataNDC* pidata = pdata; delete pidata; + + CHECK_EQUAL(current_count, NDC::get_instance_count()); } //************************************************************************* @@ -377,7 +379,7 @@ namespace CHECK_EQUAL(data.size(), size_t(0)); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_count_key) { diff --git a/test/test_vector.cpp b/test/test_vector.cpp index fcd777a57..3b35ceac9 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -593,7 +593,6 @@ namespace { const size_t INITIAL_SIZE = SIZE; const int INITIAL_VALUE = 1; - const int UNINITIALISED_VALUE = -1; Data data(INITIAL_SIZE, INITIAL_VALUE); @@ -667,7 +666,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const int INITIAL_VALUE = 1; for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { diff --git a/test/test_vector_pointer.cpp b/test/test_vector_pointer.cpp index 08e11a341..6ee7842cc 100644 --- a/test/test_vector_pointer.cpp +++ b/test/test_vector_pointer.cpp @@ -1198,7 +1198,6 @@ namespace TEST_FIXTURE(SetupFixture, test_insert_position_range) { const size_t INITIAL_SIZE = 5; - const int INITIAL_VALUE = 1; for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { @@ -1222,7 +1221,6 @@ namespace TEST_FIXTURE(SetupFixture, test_const_insert_position_range) { const size_t INITIAL_SIZE = 5; - const int INITIAL_VALUE = 1; for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { @@ -1266,7 +1264,7 @@ namespace CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_const_insert_position_range_excess) { diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 628b95d8a..5abed724c 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -362,6 +362,7 @@ + @@ -387,6 +388,9 @@ + + + @@ -570,6 +574,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 454cab6a6..8a2ae5cd6 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -693,6 +693,18 @@ ETL\Utilities\Atomic + + ETL\Utilities + + + ETL\Private + + + ETL\Private + + + ETL\Private + ETL\Frameworks @@ -1142,6 +1154,9 @@ Source Files + + Source Files + Source Files