diff --git a/include/etl/byte_stream.h b/include/etl/byte_stream.h index bf93eb5e..c63bcfa7 100644 --- a/include/etl/byte_stream.h +++ b/include/etl/byte_stream.h @@ -45,6 +45,7 @@ SOFTWARE. #include "span.h" #include "iterator.h" #include "optional.h" +#include "delegate.h" namespace etl { @@ -56,37 +57,42 @@ namespace etl public: typedef const char* const_iterator; + typedef etl::span callback_parameter_type; + typedef etl::delegate)> callback_type; //*************************************************************************** /// Construct from span. //*************************************************************************** - byte_stream_writer(etl::span span_, etl::endian buffer_endianness_) + byte_stream_writer(etl::span span_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) : pdata(span_.begin()) , pcurrent(span_.begin()) , length(span_.size_bytes()) , buffer_endianness(buffer_endianness_) + , callback(callback_) { } //*************************************************************************** /// Construct from range. //*************************************************************************** - byte_stream_writer(void* begin_, void* end_, etl::endian buffer_endianness_) + byte_stream_writer(void* begin_, void* end_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) : pdata(reinterpret_cast(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(etl::distance(reinterpret_cast(begin_), reinterpret_cast(end_))) , buffer_endianness(buffer_endianness_) + , callback(callback_) { } //*************************************************************************** /// Construct from begin and length. //*************************************************************************** - byte_stream_writer(void* begin_, size_t length_, etl::endian buffer_endianness_) + byte_stream_writer(void* begin_, size_t length_, etl::endian buffer_endianness_, callback_type callback_ = callback_type()) : pdata(reinterpret_cast(begin_)) , pcurrent(reinterpret_cast(begin_)) , length(length_) , buffer_endianness(buffer_endianness_) + , callback(callback_) { } @@ -94,11 +100,12 @@ namespace etl /// Construct from array. //*************************************************************************** template - byte_stream_writer(T(&begin_)[Size], etl::endian buffer_endianness_) + byte_stream_writer(T(&begin_)[Size], etl::endian buffer_endianness_, callback_type callback_ = callback_type()) : pdata(begin_) , pcurrent(begin_) , length(begin_ + (Size * sizeof(T))) , buffer_endianness(buffer_endianness_) + , callback(callback_) { } @@ -232,12 +239,12 @@ namespace etl if (n < maximum) { - pcurrent += (n * sizeof(T)); + step(n * sizeof(T)); return true; } else { - pcurrent += (maximum * sizeof(T)); + step(maximum * sizeof(T)); return false; } } @@ -355,6 +362,14 @@ namespace etl return available(); } + //*************************************************************************** + /// Sets the function to call afer every write. + //*************************************************************************** + void set_callback(callback_type callback_) + { + callback = callback_; + } + private: //*************************************************************************** @@ -364,7 +379,8 @@ namespace etl typename etl::enable_if::type to_bytes(const T value) { - *pcurrent++ = static_cast(value); + *pcurrent = static_cast(value); + step(1U); } //********************************* @@ -374,7 +390,15 @@ namespace etl { const char* pv = reinterpret_cast(&value); copy_value(pv, pcurrent, sizeof(T)); - pcurrent += sizeof(T); + step(sizeof(T)); + } + + //********************************* + void step(size_t n) + { + callback.call_if(etl::span(pcurrent, pcurrent + n)); + + pcurrent += n; } //********************************* @@ -396,6 +420,7 @@ namespace etl 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. + callback_type callback; ///< An optional callback on every step on the write buffer. }; //*************************************************************************** diff --git a/test/test_byte_stream.cpp b/test/test_byte_stream.cpp index 6688e786..df93a839 100644 --- a/test/test_byte_stream.cpp +++ b/test/test_byte_stream.cpp @@ -1284,7 +1284,7 @@ namespace } //************************************************************************* - TEST(write_byte_stream_iterative_output) + TEST(write_byte_stream_iterative_copy) { std::array storage; std::array put_data = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) }; @@ -1309,5 +1309,37 @@ namespace CHECK_EQUAL(expected[i], result[i]); } } + + //************************************************************************* + TEST(write_byte_stream_callback) + { + std::array storage; + std::array put_data = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) }; + std::vector expected = { char(0x00), char(0x00), char(0x00), char(0x01), + char(0xA5), char(0x5A), char(0xA5), char(0x5A), + char(0x5A), char(0xA5), char(0x5A), char(0xA5), + char(0xFF), char(0xFF), char(0xFF), char(0xFF) }; + + + static std::vector result; + + etl::byte_stream_writer::callback_type callback([&](etl::byte_stream_writer::callback_parameter_type sp) + { + std::copy(sp.begin(), sp.end(), std::back_inserter(result)); + }); + + etl::byte_stream_writer writer(storage.data(), storage.size(), etl::endian::big, callback); + + for (auto i : put_data) + { + writer.write(i); + writer.restart(); + } + + for (size_t i = 0U; i < (4U * sizeof(int32_t)); ++i) + { + CHECK_EQUAL(expected[i], result[i]); + } + } }; }