Added optional byte_stream callback

This commit is contained in:
John Wellbelove 2022-05-21 20:16:19 +01:00
parent 9c9bd93549
commit 6a979fb7c9
2 changed files with 66 additions and 9 deletions

View File

@ -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<char> callback_parameter_type;
typedef etl::delegate<void(etl::span<char>)> callback_type;
//***************************************************************************
/// Construct from span.
//***************************************************************************
byte_stream_writer(etl::span<char> span_, etl::endian buffer_endianness_)
byte_stream_writer(etl::span<char> 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<char*>(begin_))
, pcurrent(reinterpret_cast<char*>(begin_))
, length(etl::distance(reinterpret_cast<char*>(begin_), reinterpret_cast<char*>(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<char*>(begin_))
, pcurrent(reinterpret_cast<char*>(begin_))
, length(length_)
, buffer_endianness(buffer_endianness_)
, callback(callback_)
{
}
@ -94,11 +100,12 @@ namespace etl
/// Construct from array.
//***************************************************************************
template <typename T, size_t Size>
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<char>();
}
//***************************************************************************
/// 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<sizeof(T) == 1U, void>::type
to_bytes(const T value)
{
*pcurrent++ = static_cast<char>(value);
*pcurrent = static_cast<char>(value);
step(1U);
}
//*********************************
@ -374,7 +390,15 @@ namespace etl
{
const char* pv = reinterpret_cast<const char*>(&value);
copy_value(pv, pcurrent, sizeof(T));
pcurrent += sizeof(T);
step(sizeof(T));
}
//*********************************
void step(size_t n)
{
callback.call_if(etl::span<char>(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.
};
//***************************************************************************

View File

@ -1284,7 +1284,7 @@ namespace
}
//*************************************************************************
TEST(write_byte_stream_iterative_output)
TEST(write_byte_stream_iterative_copy)
{
std::array<char, sizeof(int32_t)> storage;
std::array<int32_t, 4> 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<char, sizeof(int32_t)> storage;
std::array<int32_t, 4> put_data = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) };
std::vector<char> 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<char> 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]);
}
}
};
}