mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 14:49:53 +08:00
Initial byte_stream code
This commit is contained in:
parent
4aabb886d0
commit
c1e4c5b670
@ -37,6 +37,7 @@ SOFTWARE.
|
||||
#include "binary.h"
|
||||
#include "algorithm.h"
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "private/minmax_push.h"
|
||||
|
||||
@ -305,14 +306,14 @@ namespace etl
|
||||
if (bits_remaining >= width)
|
||||
{
|
||||
// Temporary storage.
|
||||
unsigned char data[sizeof(T)];
|
||||
etl::uninitialized_buffer_of<T, 1U> data;
|
||||
|
||||
for (size_t i = 0; i < sizeof(T); ++i)
|
||||
{
|
||||
get(data[i], CHAR_BIT);
|
||||
get(data.raw[i], CHAR_BIT);
|
||||
}
|
||||
|
||||
from_bytes(data, value);
|
||||
from_bytes(reinterpret_cast<const unsigned char*>(data.raw), value);
|
||||
|
||||
success = true;
|
||||
}
|
||||
@ -491,19 +492,19 @@ namespace etl
|
||||
template <typename T>
|
||||
void from_bytes(const unsigned char* data, T& value)
|
||||
{
|
||||
unsigned char temp[sizeof(T)];
|
||||
etl::uninitialized_buffer_of<T, 1U> temp;
|
||||
|
||||
// Network to host.
|
||||
if (etl::endianness::value() == etl::endian::little)
|
||||
{
|
||||
etl::reverse_copy(data, data + sizeof(T), temp);
|
||||
etl::reverse_copy(data, data + sizeof(T), temp.raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
etl::copy(data, data + sizeof(T), temp);
|
||||
etl::copy(data, data + sizeof(T), temp.raw);
|
||||
}
|
||||
|
||||
value = *reinterpret_cast<T*>(temp);
|
||||
value = *reinterpret_cast<T*>(temp.raw);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
432
include/etl/byte_stream.h
Normal file
432
include/etl/byte_stream.h
Normal file
@ -0,0 +1,432 @@
|
||||
///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2021 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.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_BYTE_STREAM_INCLUDED
|
||||
#define ETL_BYTE_STREAM_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if ETL_USING_8BIT_TYPES
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "type_traits.h"
|
||||
#include "nullptr.h"
|
||||
#include "endianness.h"
|
||||
#include "integral_limits.h"
|
||||
#include "algorithm.h"
|
||||
#include "iterator.h"
|
||||
#include "memory.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace etl
|
||||
{
|
||||
class byte_stream_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef const int8_t* const_iterator;
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
void set_stream(int8_t* begin_, size_t length_)
|
||||
{
|
||||
pdata = begin_;
|
||||
pcurrent = begin_;
|
||||
length = length_;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
void set_stream(uint8_t* begin_, size_t length_)
|
||||
{
|
||||
pdata = reinterpret_cast<int8_t*>(begin_);
|
||||
pcurrent = begin_;
|
||||
length = length_;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
void set_stream(int8_t* begin_, int8_t* end_)
|
||||
{
|
||||
set_stream(begin_, etl::distance(begin_, end_));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
void set_stream(uint8_t* begin_, uint8_t* end_)
|
||||
{
|
||||
set_stream(begin_, etl::distance(begin_, end_));
|
||||
}
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
/// Sets the index back to the beginning of the stream.
|
||||
//***************************************************************************
|
||||
void restart()
|
||||
{
|
||||
pcurrent = pdata;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns <b>true</b> if the byte stream index has reached the end.
|
||||
//***************************************************************************
|
||||
bool at_end() const
|
||||
{
|
||||
return (pcurrent == (pdata + length));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns <b>true</b> if the byte stream index has reached the end.
|
||||
//***************************************************************************
|
||||
bool full() const
|
||||
{
|
||||
return at_end();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns the number of bytes used in the stream.
|
||||
//***************************************************************************
|
||||
size_t size() const
|
||||
{
|
||||
return etl::distance(pdata, pcurrent);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns the maximum number of bytes in the stream.
|
||||
//***************************************************************************
|
||||
size_t capacity() const
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// The number of bytes left in the stream.
|
||||
//***************************************************************************
|
||||
size_t available() const
|
||||
{
|
||||
return capacity() - size();
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns start of the stream.
|
||||
//***************************************************************************
|
||||
const_iterator begin() const
|
||||
{
|
||||
return pdata;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns end of the stream.
|
||||
//***************************************************************************
|
||||
const_iterator end() const
|
||||
{
|
||||
return pcurrent;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
byte_stream_base(int8_t* pdata_, size_t length_)
|
||||
: pdata(pdata_)
|
||||
, pcurrent(pdata_)
|
||||
, length(length_)
|
||||
{
|
||||
}
|
||||
|
||||
byte_stream_base(uint8_t* pdata_, size_t length_)
|
||||
: pdata(reinterpret_cast<int8_t*>(pdata_))
|
||||
, pcurrent(pdata_)
|
||||
, length(length_)
|
||||
{
|
||||
}
|
||||
|
||||
void copy_value(const int8_t* sb, const int8_t* se, int8_t* db)
|
||||
{
|
||||
etl::endian platform_endianness = etl::endianness::value();
|
||||
|
||||
if (network_endianness == platform_endianness)
|
||||
{
|
||||
etl::copy(sb, se, db);
|
||||
}
|
||||
else
|
||||
{
|
||||
etl::reverse_copy(sb, se, db);
|
||||
}
|
||||
}
|
||||
|
||||
const int8_t* pdata; ///< The start of the byte stream buffer.
|
||||
mutable int8_t* pcurrent; ///< The current position in the byte stream buffer.
|
||||
const size_t length; ///< The length of the byte stream buffer.
|
||||
const etl::endian network_endianness;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Encodes a byte stream.
|
||||
//***************************************************************************
|
||||
class byte_stream_writer : public byte_stream_base
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
/// Default constructor.
|
||||
//***************************************************************************
|
||||
byte_stream_writer()
|
||||
: byte_stream_base()
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
byte_stream_writer(int8_t* begin_, int8_t* end_)
|
||||
: byte_stream_base(begin_, etl::distance(begin_, end_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
byte_stream_writer(uint8_t* begin_, uint8_t* end_)
|
||||
: byte_stream_base(begin_), etl::distance(begin_, end_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
byte_stream_writer(int8_t* begin_, size_t length_)
|
||||
: byte_stream_base(begin_), length_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
byte_stream_writer(uint8_t* begin_, size_t length_)
|
||||
: byte_stream_base(begin_), length_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Writes a boolean to the stream
|
||||
//***************************************************************************
|
||||
bool write(bool value)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (available() > 0)
|
||||
{
|
||||
*pdata++ = value ? 1 : 0;
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Write a value to the stream.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
typename etl::enable_if<etl::is_integral<T>::value || etl::is_floating_point<T>::value, bool>::type
|
||||
write(T value)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (available() >= sizeof(T))
|
||||
{
|
||||
to_bytes(value, pdata);
|
||||
pdata += sizeof(T);
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Write a range of value to the stream.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
typename etl::enable_if<etl::is_integral<T>::value || etl::is_floating_point<T>::value, bool>::type
|
||||
bool write(const etl::span<T>& range)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
size_t length = range.size_bytes();
|
||||
|
||||
if (available() >= length)
|
||||
{
|
||||
etl::span<int8_t>::const_iterator itr = range.begin();
|
||||
|
||||
while (itr != range.end())
|
||||
{
|
||||
to_bytes(*itr++);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
/// to_bytes
|
||||
//***************************************************************************
|
||||
void to_bytes(int8_t value)
|
||||
{
|
||||
*pcurrent++ = value;
|
||||
}
|
||||
|
||||
void to_bytes(uint8_t value)
|
||||
{
|
||||
*pcurrent++ = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void to_bytes(T value)
|
||||
{
|
||||
const int8_t* pv = reinterpret_cast<int8_t*>(&value);
|
||||
|
||||
copy_value(pv, pv + sizeof(T), pcurrent);
|
||||
|
||||
pcurrent += sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// Decodes byte streams.
|
||||
/// Data must be stored in the stream in network order.
|
||||
//***************************************************************************
|
||||
class byte_stream_reader : public byte_stream_base
|
||||
{
|
||||
public:
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
byte_stream_reader(int8_t* begin_, int8_t* end_)
|
||||
: byte_stream_base(begin_, etl::distance(begin_, end_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from range.
|
||||
//***************************************************************************
|
||||
byte_stream_reader(uint8_t* begin_, uint8_t* end_)
|
||||
: byte_stream_base(begin_), etl::distance(begin_, end_))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
byte_stream_reader(int8_t* begin_, size_t length_)
|
||||
: byte_stream_base(begin_), length_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Construct from begin and length.
|
||||
//***************************************************************************
|
||||
byte_stream_reader(uint8_t* begin_, size_t length_)
|
||||
: byte_stream_base(begin_), length_)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Read a value from the stream.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
typename etl::enable_if<etl::is_bool<T>::value || etl::is_integral<T>::value || etl::is_floating_point<T>::value, etl::optional<T>>::type
|
||||
read() const
|
||||
{
|
||||
etl::optional<T> result;
|
||||
|
||||
// Do we have enough bytes?
|
||||
if (available() >= size_t(T))
|
||||
{
|
||||
result = from_bytes<T>();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Read a range from the stream.
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
typename etl::enable_if<etl::is_bool<T>::value || etl::is_integral<T>::value || etl::is_floating_point<T>::value, etl::span<T>>::type
|
||||
etl::span<T> read(size_t length) const
|
||||
{
|
||||
etl::span<T> result;
|
||||
|
||||
if (available() >= (length * sizeof(T)))
|
||||
{
|
||||
const int8_t* pend = pcurrent + (length * sizeof(T));
|
||||
|
||||
result = etl::span<T>(reinterpret_cast<const T*>(pcurrent), reinterpret_cast<const T*>(pend));
|
||||
pcurrent += length * sizeof(T);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//***************************************************************************
|
||||
/// from_bytes
|
||||
//***************************************************************************
|
||||
template <typename T>
|
||||
T from_bytes() const
|
||||
{
|
||||
T value;
|
||||
|
||||
int8_t* pv = reinterpret_cast<int8_t*>(&value);
|
||||
|
||||
if ETL_IF_CONSTEXPR(sizeof(T) == 1U)
|
||||
{
|
||||
*pv = *pcurrent;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_value(pcurrent, pcurrent + sizeof(T), pv);
|
||||
}
|
||||
|
||||
pcurrent += sizeof(T);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user