diff --git a/include/etl/byte_stream.h b/include/etl/byte_stream.h index 9f6d75e5..f97a6090 100644 --- a/include/etl/byte_stream.h +++ b/include/etl/byte_stream.h @@ -48,121 +48,23 @@ SOFTWARE. namespace etl { - namespace private_byte_stream - { - class byte_stream_common - { - public: - - typedef const char* const_iterator; - - //*************************************************************************** - /// Sets the index back to the position in the stream. Default = 0. - //*************************************************************************** - void restart(size_t n = 0U) - { - pcurrent = const_cast(pdata + n); - } - - //*************************************************************************** - /// Returns start of the stream. - //*************************************************************************** - const_iterator begin() const - { - return pdata; - } - - //*************************************************************************** - /// Returns end of the stream. - //*************************************************************************** - const_iterator end() const - { - return pcurrent; - } - - //*************************************************************************** - /// Returns start of the stream. - //*************************************************************************** - const_iterator cbegin() const - { - return pdata; - } - - //*************************************************************************** - /// Returns end of the stream. - //*************************************************************************** - const_iterator cend() const - { - return pcurrent; - } - - //*************************************************************************** - /// Returns a span of the used portion of the stream. - //*************************************************************************** - etl::span used_data() const - { - return etl::span(pdata, pcurrent); - } - - //*************************************************************************** - /// Returns a span of the free portion of the stream. - //*************************************************************************** - etl::span free_data() const - { - return etl::span(pcurrent, pdata + length); - } - - //*************************************************************************** - /// Returns a span of whole the stream. - //*************************************************************************** - etl::span data() const - { - return etl::span(pdata, pdata + length); - } - - protected: - - byte_stream_common(char* pdata_, size_t length_, etl::endian buffer_endianness_) - : pdata(pdata_) - , pcurrent(pdata_) - , length(length_) - , buffer_endianness(buffer_endianness_) - { - } - - void copy_value(const char* source, char* destination, size_t length) const - { - const etl::endian platform_endianness = etl::endianness::value(); - - if (buffer_endianness == platform_endianness) - { - etl::copy(source, source + length, destination); - } - else - { - etl::reverse_copy(source, source + length, destination); - } - } - - char* const pdata; ///< The start of the byte stream buffer. - char* pcurrent; ///< The current position in the byte stream buffer. - const size_t length; ///< The length of the byte stream buffer. - const etl::endian buffer_endianness; ///< The endianness of the buffer data. - }; - } - //*************************************************************************** /// Encodes a byte stream. //*************************************************************************** - class byte_stream_writer : public private_byte_stream::byte_stream_common + class byte_stream_writer { public: + typedef const char* const_iterator; + //*************************************************************************** /// Construct from span. //*************************************************************************** byte_stream_writer(etl::span span_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(span_.begin(), span_.size_bytes(), buffer_endianness_) + : pdata(span_.begin()) + , pcurrent(span_.begin()) + , length(span_.size_bytes()) + , buffer_endianness(buffer_endianness_) { } @@ -170,7 +72,10 @@ namespace etl /// Construct from range. //*************************************************************************** byte_stream_writer(char* begin_, char* end_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, etl::distance(begin_, end_), buffer_endianness_) + : pdata(begin_) + , pcurrent(begin_) + , length(etl::distance(begin_, end_)) + , buffer_endianness(buffer_endianness_) { } @@ -178,7 +83,10 @@ namespace etl /// Construct from begin and length. //*************************************************************************** byte_stream_writer(char* begin_, size_t length_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, length_, buffer_endianness_) + : pdata(begin_) + , pcurrent(begin_) + , length(length_) + , buffer_endianness(buffer_endianness_) { } @@ -187,7 +95,10 @@ namespace etl //*************************************************************************** template byte_stream_writer(T(&begin_)[Size], etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, begin_ + (Size * sizeof(T)), buffer_endianness_) + : pdata(begin_) + , pcurrent(begin_) + , length(begin_ + (Size * sizeof(T))) + , buffer_endianness(buffer_endianness_) { } @@ -249,6 +160,70 @@ namespace etl return success; } + //*************************************************************************** + /// Sets the index back to the position in the stream. Default = 0. + //*************************************************************************** + void restart(size_t n = 0U) + { + pcurrent = const_cast(pdata + n); + } + + //*************************************************************************** + /// Returns start of the stream. + //*************************************************************************** + const_iterator begin() const + { + return pdata; + } + + //*************************************************************************** + /// Returns end of the stream. + //*************************************************************************** + const_iterator end() const + { + return pcurrent; + } + + //*************************************************************************** + /// Returns start of the stream. + //*************************************************************************** + const_iterator cbegin() const + { + return pdata; + } + + //*************************************************************************** + /// Returns end of the stream. + //*************************************************************************** + const_iterator cend() const + { + return pcurrent; + } + + //*************************************************************************** + /// Returns a span of the used portion of the stream. + //*************************************************************************** + etl::span used_data() const + { + return etl::span(pdata, pcurrent); + } + + //*************************************************************************** + /// Returns a span of the free portion of the stream. + //*************************************************************************** + etl::span free_data() const + { + return etl::span(pcurrent, pdata + length); + } + + //*************************************************************************** + /// Returns a span of whole the stream. + //*************************************************************************** + etl::span data() const + { + return etl::span(pdata, pdata + length); + } + //*************************************************************************** /// Returns true if the byte stream index has reached the end. //*************************************************************************** @@ -311,37 +286,79 @@ namespace etl copy_value(pv, pcurrent, sizeof(T)); pcurrent += sizeof(T); } + + //********************************* + void copy_value(const char* source, char* destination, size_t length) const + { + const etl::endian platform_endianness = etl::endianness::value(); + + if (buffer_endianness == platform_endianness) + { + etl::copy(source, source + length, destination); + } + else + { + etl::reverse_copy(source, source + length, destination); + } + } + + char* const pdata; ///< The start of the byte stream buffer. + char* pcurrent; ///< The current position in the byte stream buffer. + const size_t length; ///< The length of the byte stream buffer. + const etl::endian buffer_endianness; ///< The endianness of the buffer data. }; //*************************************************************************** /// Decodes byte streams. /// Data must be stored in the stream in network order. //*************************************************************************** - class byte_stream_reader : public private_byte_stream::byte_stream_common + class byte_stream_reader { public: + typedef const char* const_iterator; + //*************************************************************************** /// Construct from span. //*************************************************************************** byte_stream_reader(etl::span span_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(span_.begin(), span_.size_bytes(), buffer_endianness_) + : pdata(span_.begin()) + , pcurrent(span_.begin()) + , length(span_.size_bytes()) + , buffer_endianness(buffer_endianness_) + { + } + + //*************************************************************************** + /// Construct from span. + //*************************************************************************** + byte_stream_reader(etl::span span_, etl::endian buffer_endianness_ = etl::endian::big) + : pdata(span_.begin()) + , pcurrent(span_.begin()) + , length(span_.size_bytes()) + , buffer_endianness(buffer_endianness_) { } //*************************************************************************** /// Construct from range. //*************************************************************************** - byte_stream_reader(char* begin_, char* end_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, etl::distance(begin_, end_), buffer_endianness_) + byte_stream_reader(const char* begin_, const char* end_, etl::endian buffer_endianness_ = etl::endian::big) + : pdata(begin_) + , pcurrent(begin_) + , length(etl::distance(begin_, end_)) + , buffer_endianness(buffer_endianness_) { } //*************************************************************************** /// Construct from begin and length. //*************************************************************************** - byte_stream_reader(char* begin_, size_t length_, etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, length_, buffer_endianness_) + byte_stream_reader(const char* begin_, size_t length_, etl::endian buffer_endianness_ = etl::endian::big) + : pdata(begin_) + , pcurrent(begin_) + , length(length_) + , buffer_endianness(buffer_endianness_) { } @@ -350,7 +367,10 @@ namespace etl //*************************************************************************** template byte_stream_reader(T(&begin_)[Size], etl::endian buffer_endianness_ = etl::endian::big) - : byte_stream_common(begin_, begin_ + (Size * sizeof(T)), buffer_endianness_) + : pdata(begin_) + , pcurrent(begin_) + , length(begin_ + (Size * sizeof(T))) + , buffer_endianness(buffer_endianness_) { } @@ -376,17 +396,17 @@ namespace etl /// Read a byte range from the stream. //*************************************************************************** template - typename etl::enable_if > >::type + typename etl::enable_if > >::type read(size_t n) { - etl::optional > result; + etl::optional > result; // Do we have enough room? if (available() >= n) { - char* pend = pcurrent + (n * sizeof(T)); + const char* pend = pcurrent + (n * sizeof(T)); - result = etl::span(reinterpret_cast(pcurrent), reinterpret_cast(pend)); + result = etl::span(reinterpret_cast(pcurrent), reinterpret_cast(pend)); pcurrent = pend; } @@ -397,10 +417,10 @@ namespace etl /// Read a range of T from the stream. //*************************************************************************** template - typename etl::enable_if::value || etl::is_floating_point::value, etl::optional > >::type + typename etl::enable_if::value || etl::is_floating_point::value, bool>::type read(etl::span range) { - etl::optional > result; + bool result = false; // Do we have enough room? if (available() >= range.size()) @@ -412,7 +432,7 @@ namespace etl *destination++ = from_bytes(); } - result = range; + result = true; } return result; @@ -438,6 +458,70 @@ namespace etl } } + //*************************************************************************** + /// Sets the index back to the position in the stream. Default = 0. + //*************************************************************************** + void restart(size_t n = 0U) + { + pcurrent = pdata + n; + } + + //*************************************************************************** + /// Returns start of the stream. + //*************************************************************************** + const_iterator begin() const + { + return pdata; + } + + //*************************************************************************** + /// Returns end of the stream. + //*************************************************************************** + const_iterator end() const + { + return pcurrent; + } + + //*************************************************************************** + /// Returns start of the stream. + //*************************************************************************** + const_iterator cbegin() const + { + return pdata; + } + + //*************************************************************************** + /// Returns end of the stream. + //*************************************************************************** + const_iterator cend() const + { + return pcurrent; + } + + //*************************************************************************** + /// Returns a span of the used portion of the stream. + //*************************************************************************** + etl::span used_data() const + { + return etl::span(pdata, pcurrent); + } + + //*************************************************************************** + /// Returns a span of the free portion of the stream. + //*************************************************************************** + etl::span free_data() const + { + return etl::span(pcurrent, pdata + length); + } + + //*************************************************************************** + /// Returns a span of whole the stream. + //*************************************************************************** + etl::span data() const + { + return etl::span(pdata, pdata + length); + } + //*************************************************************************** /// Returns true if the byte stream is empty. //*************************************************************************** @@ -460,7 +544,7 @@ namespace etl template size_t available() const { - return (length - etl::distance(pdata, reinterpret_cast(pcurrent))) / sizeof(T); + return (length - etl::distance(pdata, reinterpret_cast(pcurrent))) / sizeof(T); } private: @@ -488,6 +572,26 @@ namespace etl return value; } + + //********************************* + void copy_value(const char* source, char* destination, size_t length) const + { + const etl::endian platform_endianness = etl::endianness::value(); + + if (buffer_endianness == platform_endianness) + { + etl::copy(source, source + length, destination); + } + else + { + etl::reverse_copy(source, source + length, destination); + } + } + + const char* const pdata; ///< The start of the byte stream buffer. + const char* pcurrent; ///< The current position in the byte stream buffer. + const size_t length; ///< The length of the byte stream buffer. + const etl::endian buffer_endianness; ///< The endianness of the buffer data. }; //*************************************************************************** diff --git a/test/test_byte_stream.cpp b/test/test_byte_stream.cpp index bbe40c77..b2045624 100644 --- a/test/test_byte_stream.cpp +++ b/test/test_byte_stream.cpp @@ -881,7 +881,7 @@ namespace etl::byte_stream_reader reader(storage.data(), writer.size_bytes()); - etl::optional> output = reader.read(4U); + etl::optional> output = reader.read(4U); CHECK_EQUAL(4U, output.value().size()); CHECK_EQUAL(int(put_data[0]), int(output.value()[0])); CHECK_EQUAL(int(put_data[1]), int(output.value()[1])); @@ -909,8 +909,8 @@ namespace etl::span output(get_data.begin(), get_data.end()); - etl::optional> result = reader.read(output); - CHECK_EQUAL(4U, result.value().size()); + bool result = reader.read(output); + CHECK(result); CHECK_EQUAL(put_data[0], get_data[0]); CHECK_EQUAL(put_data[1], get_data[1]); CHECK_EQUAL(put_data[2], get_data[2]); @@ -1071,5 +1071,16 @@ namespace // Skip five int16_t (too many) CHECK(!reader.skip(5U)); } + + //************************************************************************* + TEST(read_span_int32_t) + { + std::array storage = { 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::byte_stream_reader reader(reinterpret_cast(storage.data()), storage.size() * sizeof(int32_t)); + + bool result = reader.read(etl::span(get_data.begin(), get_data.end())); + } }; }