mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 22:59:47 +08:00
Fixes to byte_stream_reader for const data
This commit is contained in:
parent
0754b3380e
commit
49c9393537
@ -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<char*>(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<char> used_data() const
|
||||
{
|
||||
return etl::span<char>(pdata, pcurrent);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of the free portion of the stream.
|
||||
//***************************************************************************
|
||||
etl::span<char> free_data() const
|
||||
{
|
||||
return etl::span<char>(pcurrent, pdata + length);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of whole the stream.
|
||||
//***************************************************************************
|
||||
etl::span<char> data() const
|
||||
{
|
||||
return etl::span<char>(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<char> 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 <typename T, size_t Size>
|
||||
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<char*>(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<char> used_data() const
|
||||
{
|
||||
return etl::span<char>(pdata, pcurrent);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of the free portion of the stream.
|
||||
//***************************************************************************
|
||||
etl::span<char> free_data() const
|
||||
{
|
||||
return etl::span<char>(pcurrent, pdata + length);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of whole the stream.
|
||||
//***************************************************************************
|
||||
etl::span<char> data() const
|
||||
{
|
||||
return etl::span<char>(pdata, pdata + length);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns <b>true</b> 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<char> 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<const char> 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 <typename T, size_t Size>
|
||||
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 T>
|
||||
typename etl::enable_if<sizeof(T) == 1U, etl::optional<etl::span<T> > >::type
|
||||
typename etl::enable_if<sizeof(T) == 1U, etl::optional<etl::span<const T> > >::type
|
||||
read(size_t n)
|
||||
{
|
||||
etl::optional<etl::span<T> > result;
|
||||
etl::optional<etl::span<const T> > result;
|
||||
|
||||
// Do we have enough room?
|
||||
if (available<T>() >= n)
|
||||
{
|
||||
char* pend = pcurrent + (n * sizeof(T));
|
||||
const char* pend = pcurrent + (n * sizeof(T));
|
||||
|
||||
result = etl::span<T>(reinterpret_cast<T*>(pcurrent), reinterpret_cast<T*>(pend));
|
||||
result = etl::span<const T>(reinterpret_cast<const T*>(pcurrent), reinterpret_cast<const T*>(pend));
|
||||
pcurrent = pend;
|
||||
}
|
||||
|
||||
@ -397,10 +417,10 @@ namespace etl
|
||||
/// Read a range of T from the stream.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
typename etl::enable_if<etl::is_integral<T>::value || etl::is_floating_point<T>::value, etl::optional<etl::span<T> > >::type
|
||||
typename etl::enable_if<etl::is_integral<T>::value || etl::is_floating_point<T>::value, bool>::type
|
||||
read(etl::span<T> range)
|
||||
{
|
||||
etl::optional<etl::span<T> > result;
|
||||
bool result = false;
|
||||
|
||||
// Do we have enough room?
|
||||
if (available<T>() >= range.size())
|
||||
@ -412,7 +432,7 @@ namespace etl
|
||||
*destination++ = from_bytes<T>();
|
||||
}
|
||||
|
||||
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<const char> used_data() const
|
||||
{
|
||||
return etl::span<const char>(pdata, pcurrent);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of the free portion of the stream.
|
||||
//***************************************************************************
|
||||
etl::span<const char> free_data() const
|
||||
{
|
||||
return etl::span<const char>(pcurrent, pdata + length);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a span of whole the stream.
|
||||
//***************************************************************************
|
||||
etl::span<const char> data() const
|
||||
{
|
||||
return etl::span<const char>(pdata, pdata + length);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns <b>true</b> if the byte stream is empty.
|
||||
//***************************************************************************
|
||||
@ -460,7 +544,7 @@ namespace etl
|
||||
template <typename T>
|
||||
size_t available() const
|
||||
{
|
||||
return (length - etl::distance(pdata, reinterpret_cast<char* const>(pcurrent))) / sizeof(T);
|
||||
return (length - etl::distance(pdata, reinterpret_cast<const char* const>(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.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -881,7 +881,7 @@ namespace
|
||||
|
||||
etl::byte_stream_reader reader(storage.data(), writer.size_bytes());
|
||||
|
||||
etl::optional<etl::span<char>> output = reader.read<char>(4U);
|
||||
etl::optional<etl::span<const char>> output = reader.read<char>(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<int32_t> output(get_data.begin(), get_data.end());
|
||||
|
||||
etl::optional<etl::span<int32_t>> result = reader.read<int32_t>(output);
|
||||
CHECK_EQUAL(4U, result.value().size());
|
||||
bool result = reader.read<int32_t>(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<int16_t>(5U));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(read_span_int32_t)
|
||||
{
|
||||
std::array<const int32_t, 4> storage = { int32_t(0x00000001), int32_t(0xA55AA55A), int32_t(0x5AA55AA5), int32_t(0xFFFFFFFF) };
|
||||
std::array<int32_t, 4> get_data = { int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000), int32_t(0x00000000) };
|
||||
|
||||
etl::byte_stream_reader reader(reinterpret_cast<const char*>(storage.data()), storage.size() * sizeof(int32_t));
|
||||
|
||||
bool result = reader.read(etl::span<int32_t>(get_data.begin(), get_data.end()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user