First draft of new ostd::Serial class

This commit is contained in:
OmniaX-Dev 2026-05-16 13:00:47 +02:00
parent 72f2a0285f
commit 14cb854387
6 changed files with 709 additions and 30 deletions

View file

@ -12,7 +12,7 @@ set(CMAKE_C_COMPILER "clang")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.18)
project(${PROJ_NAME} LANGUAGES C CXX) project(${PROJ_NAME} LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 23)
file(STRINGS "./other/build.nr" BUILD_NUMBER) file(STRINGS "./other/build.nr" BUILD_NUMBER)
#----------------------------------------------------------------------------------------- #-----------------------------------------------------------------------------------------

View file

@ -1 +1 @@
2087 2090

View file

@ -20,14 +20,14 @@
#pragma once #pragma once
#include <ostd/string/String.hpp> #include <ostd/io/Serial.hpp>
#include <functional> #include <functional>
namespace ostd namespace ostd
{ {
class OutputHandlerBase; class OutputHandlerBase;
struct Signal; struct Signal;
class BaseObject : public __i_stringeable class BaseObject : public __i_stringeable, public __i_serializable
{ {
public: using SignalCallback = std::function<void(Signal&)>; public: using SignalCallback = std::function<void(Signal&)>;
public: public:
@ -60,9 +60,11 @@ namespace ostd
virtual inline String toString(void) const override { return getObjectHeaderString(); }; virtual inline String toString(void) const override { return getObjectHeaderString(); };
virtual void print(bool newLine = true, OutputHandlerBase* __destination = nullptr) const; virtual void print(bool newLine = true, OutputHandlerBase* __destination = nullptr) const;
virtual inline Serial::Stream serialize(void) const override { return { 0 }; };
virtual inline bool deserialize(const Serial::Stream& data) override { return false; };
virtual inline void handleSignal(Signal& signal) { } virtual inline void handleSignal(Signal& signal) { }
void connectSignal(u32 signal_id); void connectSignal(u32 signal_id);
void __handle_signal(Signal& signal); void __handle_signal(Signal& signal);
protected: protected:

View file

@ -97,6 +97,17 @@ namespace ostd
static inline const u8 ADDR = 4; static inline const u8 ADDR = 4;
static inline const u8 FLOAT = 4; static inline const u8 FLOAT = 4;
static inline const u8 DOUBLE = 8; static inline const u8 DOUBLE = 8;
static inline const u8 INT8 = 1;
static inline const u8 UINT8 = 1;
static inline const u8 INT16 = 2;
static inline const u8 UINT16 = 2;
static inline const u8 INT32 = 4;
static inline const u8 UINT32 = 4;
static inline const u8 INT64 = 8;
static inline const u8 UINT64 = 8;
static inline const u8 FLOAT32 = 4;
static inline const u8 FLOAT64 = 8;
}; };
typedef stdvec<i8> ByteStream; typedef stdvec<i8> ByteStream;

View file

@ -3,6 +3,496 @@
namespace ostd namespace ostd
{ {
bool Serial::isValidAddress(u64 addr, u32 size)
{
if (addr == 0) return false;
if (size == 0) return false;
if (addr > u64Range::max() - size) return false; // u64 overflow check
return (addr + size - 1) < s_openStream.size();
}
Serial::ReadResult<i8> Serial::read::int8(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT8)) return { 0, true };
i8 val = s_openStream[addr];
s_addr += tTypeSize::INT8;
return { val, false };
}
Serial::ReadResult<u8> Serial::read::uint8(u64 addr)
{
auto res = int8(addr);
return { cast<u8>(res.value), res.error };
}
Serial::ReadResult<i16> Serial::read::int16(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT16)) return { 0, true };
i16 val = 0;
if (isLittleEndian())
{
val = ((s_openStream[addr + 0] ) & 0x00FFU)
| ((s_openStream[addr + 1] << 8) & 0xFF00U);
}
else if (isBigEndian())
{
val = ((s_openStream[addr + 0] << 8) & 0xFF00U)
| ( s_openStream[addr + 1] & 0x00FFU);
}
else return { 0, true };
s_addr += tTypeSize::INT16;
return { val, false };
}
Serial::ReadResult<u16> Serial::read::uint16(u64 addr)
{
auto res = int16(addr);
return { cast<u16>(res.value), res.error };
}
Serial::ReadResult<i32> Serial::read::int32(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT32)) return { 0, true };
i32 val = 0;
if (isLittleEndian())
{
val = ((s_openStream[addr + 0] ) & 0x000000FF)
| ((s_openStream[addr + 1] << 8) & 0x0000FF00)
| ((s_openStream[addr + 2] << 16) & 0x00FF0000)
| ((s_openStream[addr + 3] << 24) & 0xFF000000);
}
else if (isBigEndian())
{
val = ((s_openStream[addr + 0] << 24) & 0xFF000000U)
| ((s_openStream[addr + 1] << 16) & 0x00FF0000U)
| ((s_openStream[addr + 2] << 8) & 0x0000FF00U)
| ( s_openStream[addr + 3] & 0x000000FFU);
}
else return { 0, true };
s_addr += tTypeSize::INT32;
return { val, false };
}
Serial::ReadResult<u32> Serial::read::uint32(u64 addr)
{
auto res = int32(addr);
return { cast<u32>(res.value), res.error };
}
Serial::ReadResult<i64> Serial::read::int64(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT64)) return { 0, true };
i64 val = 0;
if (isLittleEndian())
{
val = ( s_openStream[addr + 7] & 0x00000000000000FFU)
| (( s_openStream[addr + 6] << 8) & 0x000000000000FF00U)
| (( s_openStream[addr + 5] << 16) & 0x0000000000FF0000U)
| (( s_openStream[addr + 4] << 24) & 0x00000000FF000000U)
| (((i64)s_openStream[addr + 3] << 32) & 0x000000FF00000000U)
| (((i64)s_openStream[addr + 2] << 40) & 0x0000FF0000000000U)
| (((i64)s_openStream[addr + 1] << 48) & 0x00FF000000000000U)
| (((i64)s_openStream[addr + 0] << 56) & 0xFF00000000000000U);
}
else if (isBigEndian())
{
val = (((i64)s_openStream[addr + 0] << 56) & 0xFF00000000000000U)
| (((i64)s_openStream[addr + 1] << 48) & 0x00FF000000000000U)
| (((i64)s_openStream[addr + 2] << 40) & 0x0000FF0000000000U)
| (((i64)s_openStream[addr + 3] << 32) & 0x000000FF00000000U)
| (( s_openStream[addr + 4] << 24) & 0x00000000FF000000U)
| (( s_openStream[addr + 5] << 16) & 0x0000000000FF0000U)
| (( s_openStream[addr + 6] << 8) & 0x000000000000FF00U)
| ( s_openStream[addr + 7] & 0x00000000000000FFU);
}
else return { 0, true };
s_addr += tTypeSize::INT64;
return { val, false };
}
Serial::ReadResult<u64> Serial::read::uint64(u64 addr)
{
auto res = int64(addr);
return { cast<u64>(res.value), res.error };
}
Serial::ReadResult<f32> Serial::read::float32(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::FLOAT32)) return { 0, true };
__float_parser fp;
if (isLittleEndian())
{
fp.data[3] = s_openStream[addr + 0];
fp.data[2] = s_openStream[addr + 1];
fp.data[1] = s_openStream[addr + 2];
fp.data[0] = s_openStream[addr + 3];
}
else if (isBigEndian())
{
fp.data[0] = s_openStream[addr + 0];
fp.data[1] = s_openStream[addr + 1];
fp.data[2] = s_openStream[addr + 2];
fp.data[3] = s_openStream[addr + 3];
}
else return { 0, true };
s_addr += tTypeSize::FLOAT32;
return { fp.val, false };
}
Serial::ReadResult<f64> Serial::read::float64(u64 addr)
{
if (!isStreamAttached()) return { 0, true };
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::FLOAT64)) return { 0, true };
__double_parser dp;
if (isLittleEndian())
{
dp.data[7] = s_openStream[addr++];
dp.data[6] = s_openStream[addr++];
dp.data[5] = s_openStream[addr++];
dp.data[4] = s_openStream[addr++];
dp.data[3] = s_openStream[addr++];
dp.data[2] = s_openStream[addr++];
dp.data[1] = s_openStream[addr++];
dp.data[0] = s_openStream[addr ];
}
else if (isBigEndian())
{
dp.data[0] = s_openStream[addr++];
dp.data[1] = s_openStream[addr++];
dp.data[2] = s_openStream[addr++];
dp.data[3] = s_openStream[addr++];
dp.data[4] = s_openStream[addr++];
dp.data[5] = s_openStream[addr++];
dp.data[6] = s_openStream[addr++];
dp.data[7] = s_openStream[addr ];
}
else return { 0, true };
s_addr += tTypeSize::FLOAT64;
return { dp.val, false };
}
bool Serial::read::stream(Stream& outStream, u64 addr, bool sizeStored, u32 size_if_not_stored)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!sizeStored && size_if_not_stored < 1) return false;
u32 size = size_if_not_stored;
if (sizeStored)
{
auto tmp = uint32(addr);
if (tmp.error) return false;
addr += tTypeSize::UINT32;
size = tmp.value;
}
Endianness endianness;
{
auto tmp = uint8(addr);
if (tmp.error) return false;
addr += tTypeSize::UINT8;
if (tmp.value == cast<u8>(Endianness::LittleEndian))
endianness = Endianness::LittleEndian;
else if (tmp.value == cast<u8>(Endianness::BigEndian))
endianness = Endianness::BigEndian;
else return false;
}
if (!isValidAddress(addr, size)) return false;
Serial::Stream data = { size, endianness };
StreamEdit edit = data.data();
std::copy_n(s_openStream.begin() + addr, size, edit.begin());
outStream = std::move(data);
s_addr = addr + size;
return true;
}
bool Serial::read::string(String& outString, u64 addr, bool sizeStored, u32 size_if_not_stored, bool null_terminated)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!null_terminated || sizeStored) // I want null_terminated to have the lowest priority
{
if (!sizeStored && size_if_not_stored < 1) return false;
u32 size = size_if_not_stored;
if (sizeStored)
{
auto tmp = uint32(addr);
if (tmp.error) return false;
addr += tTypeSize::UINT32;
size = tmp.value;
}
if (!isValidAddress(addr, size)) return false;
for (u64 i = addr; i < (addr + size); i++)
{
outString += cast<char>(s_openStream[i]);
}
s_addr = addr + size;
return true;
}
else
{
String out = "";
auto tmp = int8(addr);
if (tmp.error) return false;
addr += tTypeSize::INT8;
while (tmp.value != '\0')
{
out += cast<char>(tmp.value);
tmp = int8(addr);
if (tmp.error) return false;
addr += tTypeSize::INT8;
}
outString = out;
s_addr = addr;
return true;
}
}
bool Serial::read::object(__i_serializable& outObject, u64 addr)
{
Serial::Stream objData(0);
if (!stream(objData, addr, true, 0))
return false;
return outObject.deserialize(objData);
}
bool Serial::write::int8(u64 addr, i8 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT8)) return false;
s_openStream[addr] = value;
s_addr += tTypeSize::INT8;
return true;
}
bool Serial::write::uint8(u64 addr, u8 value)
{
return int8(addr, cast<i8>(value));
}
bool Serial::write::int16(u64 addr, i16 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT16)) return false;
if (isLittleEndian())
{
s_openStream[addr + 0] = value & 0xFF;
s_openStream[addr + 1] = (value >> 8) & 0xFF;
}
else if (isBigEndian())
{
s_openStream[addr + 0] = (value >> 8) & 0xFF;
s_openStream[addr + 1] = value & 0xFF;
}
else return false;
s_addr += tTypeSize::INT16;
return true;
}
bool Serial::write::uint16(u64 addr, u16 value)
{
return int16(addr, cast<i16>(value));
}
bool Serial::write::int32(u64 addr, i32 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT32)) return false;
if (isLittleEndian())
{
s_openStream[addr + 0] = value & 0xFF;
s_openStream[addr + 1] = (value >> 8) & 0xFF;
s_openStream[addr + 2] = (value >> 16) & 0xFF;
s_openStream[addr + 3] = (value >> 24) & 0xFF;
}
else if (isBigEndian())
{
s_openStream[addr + 0] = (value >> 24) & 0xFF;
s_openStream[addr + 1] = (value >> 16) & 0xFF;
s_openStream[addr + 2] = (value >> 8) & 0xFF;
s_openStream[addr + 3] = value & 0xFF;
}
else return false;
s_addr += tTypeSize::INT32;
return true;
}
bool Serial::write::uint32(u64 addr, u32 value)
{
return int32(addr, cast<i32>(value));
}
bool Serial::write::int64(u64 addr, i64 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::INT64)) return false;
if (isLittleEndian())
{
s_openStream[addr + 0] = value & 0xFF;
s_openStream[addr + 1] = (value >> 8) & 0xFF;
s_openStream[addr + 2] = (value >> 16) & 0xFF;
s_openStream[addr + 3] = (value >> 24) & 0xFF;
s_openStream[addr + 4] = (value >> 32) & 0xFF;
s_openStream[addr + 5] = (value >> 40) & 0xFF;
s_openStream[addr + 6] = (value >> 48) & 0xFF;
s_openStream[addr + 7] = (value >> 56) & 0xFF;
}
else if (isBigEndian())
{
s_openStream[addr + 0] = (value >> 56) & 0xFF;
s_openStream[addr + 1] = (value >> 48) & 0xFF;
s_openStream[addr + 2] = (value >> 40) & 0xFF;
s_openStream[addr + 3] = (value >> 32) & 0xFF;
s_openStream[addr + 4] = (value >> 24) & 0xFF;
s_openStream[addr + 5] = (value >> 16) & 0xFF;
s_openStream[addr + 6] = (value >> 8) & 0xFF;
s_openStream[addr + 7] = value & 0xFF;
}
else return false;
s_addr += tTypeSize::INT64;
return true;
}
bool Serial::write::uint64(u64 addr, u64 value)
{
if (!isStreamAttached()) return false;
if (!isValidAddress(addr, tTypeSize::UINT64)) return false;
return int64(addr, cast<i64>(value));
}
bool Serial::write::float32(u64 addr, f32 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::FLOAT32)) return false;
__float_parser fp;
fp.val = value;
if (isLittleEndian())
{
s_openStream[addr + 0] = fp.data[3];
s_openStream[addr + 1] = fp.data[2];
s_openStream[addr + 2] = fp.data[1];
s_openStream[addr + 3] = fp.data[0];
}
else if (isBigEndian())
{
s_openStream[addr + 0] = fp.data[0];
s_openStream[addr + 1] = fp.data[1];
s_openStream[addr + 2] = fp.data[2];
s_openStream[addr + 3] = fp.data[3];
}
else return false;
s_addr += tTypeSize::FLOAT32;
return true;
}
bool Serial::write::float64(u64 addr, f64 value)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
if (!isValidAddress(addr, tTypeSize::FLOAT64)) return false;
__double_parser dp;
dp.val = value;
if (isLittleEndian())
{
s_openStream[addr++] = dp.data[7];
s_openStream[addr++] = dp.data[6];
s_openStream[addr++] = dp.data[5];
s_openStream[addr++] = dp.data[4];
s_openStream[addr++] = dp.data[3];
s_openStream[addr++] = dp.data[2];
s_openStream[addr++] = dp.data[1];
s_openStream[addr ] = dp.data[0];
}
else if (isBigEndian())
{
s_openStream[addr++] = dp.data[0];
s_openStream[addr++] = dp.data[1];
s_openStream[addr++] = dp.data[2];
s_openStream[addr++] = dp.data[3];
s_openStream[addr++] = dp.data[4];
s_openStream[addr++] = dp.data[5];
s_openStream[addr++] = dp.data[6];
s_openStream[addr ] = dp.data[7];
}
else return false;
s_addr += tTypeSize::FLOAT64;
return true;
}
bool Serial::write::stream(u64 addr, const Stream& value, bool storeSize)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
u32 size = value.size();
if (size < 1) return false;
if (storeSize)
{
if (!uint32(addr, size)) return false;
addr += tTypeSize::UINT32;
}
if (!isValidAddress(addr, size)) return false;
StreamView view = value.data();
for (u64 i = addr; i < addr + size; i++)
s_openStream[i] = view[i - addr];
s_addr = addr + size;
return true;
}
bool Serial::write::string(u64 addr, const String& value, bool storeSize, bool null_terminated)
{
if (!isStreamAttached()) return false;
managed_address_check(addr);
u32 size = value.len();
if (size < 1) return false;
if (storeSize)
{
null_terminated = false;
if (!uint32(addr, value.len())) return false;
addr += tTypeSize::UINT32;
}
size += (null_terminated ? 1 : 0);
if (!isValidAddress(addr, size))
return false;
for (u64 i = addr; i < addr + size; i++)
{
i8 c = cast<i8>(value[i - addr]);
if (null_terminated && i == addr + size - 1)
c = '\0';
s_openStream[i] = c;
}
s_addr = addr + size;
return true;
}
bool Serial::write::object(u64 addr, const __i_serializable& value)
{
if (!isStreamAttached()) return false;
const Serial::Stream data = value.serialize();
if (data.size() < 1) return false;
return stream(addr, data, true);
}
// =============================================== OLD VERSION ===============================================
namespace serial namespace serial
{ {
bool SerialIO::init(u64 size, u8 endianness) bool SerialIO::init(u64 size, u8 endianness)
@ -20,10 +510,10 @@ namespace ostd
if (!is_validAddr(addr, tTypeSize::QWORD)) return false; if (!is_validAddr(addr, tTypeSize::QWORD)) return false;
if (isLittleEndian()) if (isLittleEndian())
{ {
outVal = ( m_data[addr + 7] & 0x00000000000000FFU) outVal = ( m_data[addr + 7] & 0x00000000000000FFU)
| (( m_data[addr + 6] << 8) & 0x000000000000FF00U) | (( m_data[addr + 6] << 8) & 0x000000000000FF00U)
| (( m_data[addr + 5] << 16) & 0x0000000000FF0000U) | (( m_data[addr + 5] << 16) & 0x0000000000FF0000U)
| (( m_data[addr + 4] << 24) & 0x00000000FF000000U) | (( m_data[addr + 4] << 24) & 0x00000000FF000000U)
| (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U) | (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U)
| (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U) | (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U)
| (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U) | (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U)
@ -35,10 +525,10 @@ namespace ostd
| (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U) | (((QWord)m_data[addr + 1] << 48) & 0x00FF000000000000U)
| (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U) | (((QWord)m_data[addr + 2] << 40) & 0x0000FF0000000000U)
| (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U) | (((QWord)m_data[addr + 3] << 32) & 0x000000FF00000000U)
| (( m_data[addr + 4] << 24) & 0x00000000FF000000U) | (( m_data[addr + 4] << 24) & 0x00000000FF000000U)
| (( m_data[addr + 5] << 16) & 0x0000000000FF0000U) | (( m_data[addr + 5] << 16) & 0x0000000000FF0000U)
| (( m_data[addr + 6] << 8) & 0x000000000000FF00U) | (( m_data[addr + 6] << 8) & 0x000000000000FF00U)
| ( m_data[addr + 7] & 0x00000000000000FFU); | ( m_data[addr + 7] & 0x00000000000000FFU);
} }
else return false; else return false;
return true; return true;

View file

@ -1,33 +1,209 @@
/* /*
OmniaFramework - A collection of useful functionality OmniaFramework - A collection of useful functionality
Copyright (C) 2026 OmniaX-Dev Copyright (C) 2026 OmniaX-Dev
This file is part of OmniaFramework. This file is part of OmniaFramework.
OmniaFramework is free software: you can redistribute it and/or modify OmniaFramework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
OmniaFramework is distributed in the hope that it will be useful, OmniaFramework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>. along with OmniaFramework. If not, see <https://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <ostd/data/Types.hpp> #include <ostd/string/String.hpp>
#include <ostd/data/Bitfields.hpp> #include <span>
#include <ostd/data/BaseObject.hpp>
namespace ostd namespace ostd
{ {
class OutputHandlerBase; class __i_serializable;
class Serial
{
public: template<typename T> struct ReadResult { T value; bool error { false }; };
public: enum class Endianness : u8 { LittleEndian = 0, BigEndian };
public: using StreamEdit = std::span<int8_t>;
public: using StreamView = std::span<const int8_t>;
public: class Stream
{
public:
Stream(const Stream&) = delete;
Stream& operator=(const Stream&) = delete;
inline Stream(u64 size, Endianness endianness = Endianness::LittleEndian, bool preInitialize = false, i8 initialValue = 0) {
if (size < 1) return;
if constexpr (sizeof(size_t) < sizeof(uint64_t))
{
if (size > std::numeric_limits<size_t>::max())
throw "Serial::Stream size can't excede UINT32_MAX on a 32bit system.";
}
m_data = new i8[size];
m_size = size;
m_endianness = endianness;
if (preInitialize)
{
for (u64 i = 0; i < size; i++)
m_data[i] = initialValue;
}
}
inline Stream(Stream&& other) noexcept : m_data(other.m_data), m_size(other.m_size) {
other.m_data = nullptr;
other.m_size = 0;
m_endianness = other.m_endianness;
}
inline Stream& operator=(Stream&& other) noexcept {
if (this != &other) {
delete[] m_data;
m_data = other.m_data;
m_size = other.m_size;
m_endianness = other.m_endianness;
other.m_data = nullptr;
other.m_size = 0;
}
return *this;
}
inline ~Stream(void) {
delete[] m_data;
m_data = nullptr;
}
inline bool isValid(void) const { return m_size > 0 && m_data != nullptr; }
inline u64 size(void) const { return isValid() ? m_size : 0; }
inline bool isLittleEndian(void) const { return m_endianness == Endianness::LittleEndian; }
inline bool isBigEndian(void) const { return m_endianness == Endianness::BigEndian; }
inline Endianness getEndianness(void) const { return m_endianness; }
inline StreamEdit data() {
if (isValid())
return { m_data, cast<std::size_t>(m_size) };
return {};
}
inline StreamView data() const {
if (isValid())
return { m_data, cast<std::size_t>(m_size) };
return {};
}
private:
i8* m_data { nullptr };
u64 m_size { 0 };
Endianness m_endianness { Endianness::LittleEndian };
};
public:
inline static void attachStream(Stream& stream) { s_openStream = stream.data(); s_endianness = stream.getEndianness(); disableManagedAddress(); }
inline static void detachStrean(void) { s_openStream = {}; }
inline static bool setManagedAddress(u64 addr) { if (!isManagedAddressEnabled() || !isValidAddress(addr)) return false; s_addr = addr; return true; }
inline static bool isManagedAddressEnabled(void) { return s_managedAddress; }
inline static void enableManagedAddress(bool enable = true) { s_managedAddress = enable; s_addr = 0; }
inline static void disableManagedAddress(void) { enableManagedAddress(false); }
inline static bool isStreamAttached(void) { return !s_openStream.empty(); }
inline static bool isLittleEndian(void) { return s_endianness == Endianness::LittleEndian; }
inline static bool isBigEndian(void) { return s_endianness == Endianness::BigEndian; }
static bool isValidAddress(u64 addr, u32 size = 1);
public: struct read
{
ReadResult<i8> int8(u64 addr = 0);
inline i8 int8d(u64 addr = 0, bool* outError = nullptr) { auto val = int8(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<u8> uint8(u64 addr = 0);
inline u8 uint8d(u64 addr = 0, bool* outError = nullptr) { auto val = uint8(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<i16> int16(u64 addr = 0);
inline i16 int16d(u64 addr = 0, bool* outError = nullptr) { auto val = int16(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<u16> uint16(u64 addr = 0);
inline u16 uint16d(u64 addr = 0, bool* outError = nullptr) { auto val = uint16(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<i32> int32(u64 addr = 0);
inline i32 int32d(u64 addr = 0, bool* outError = nullptr) { auto val = int32(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<u32> uint32(u64 addr = 0);
inline u32 uint32d(u64 addr = 0, bool* outError = nullptr) { auto val = uint32(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<i64> int64(u64 addr = 0);
inline i64 int64d(u64 addr = 0, bool* outError = nullptr) { auto val = int64(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<u64> uint64(u64 addr = 0);
inline u64 uint64d(u64 addr = 0, bool* outError = nullptr) { auto val = uint64(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<f32> float32(u64 addr = 0);
inline f32 float32d(u64 addr = 0, bool* outError = nullptr) { auto val = float32(addr); if (outError) *outError = val.error; return val.value; }
ReadResult<f64> float64(u64 addr = 0);
inline f64 float64d(u64 addr = 0, bool* outError = nullptr) { auto val = float64(addr); if (outError) *outError = val.error; return val.value; }
bool stream(Stream& outStream, u64 addr = 0, bool sizeStored = true, u32 size_if_not_stored = 0);
bool string(String& outString, u64 addr = 0, bool sizeStored = true, u32 size_if_not_stored = 0, bool null_terminated = false);
bool object(__i_serializable& outObject, u64 addr = 0);
private:
read(void) = default;
};
public: struct write
{
bool int8(u64 addr, i8 value);
inline bool int8(i8 value) { return int8(0, value); }
bool uint8(u64 addr, u8 value);
inline bool uint8(i8 value) { return uint8(0, value); }
bool int16(u64 addr, i16 value);
inline bool int16(i8 value) { return int16(0, value); }
bool uint16(u64 addr, u16 value);
inline bool uint16(i8 value) { return uint16(0, value); }
bool int32(u64 addr, i32 value);
inline bool int32(i8 value) { return int32(0, value); }
bool uint32(u64 addr, u32 value);
inline bool uint32(i8 value) { return uint32(0, value); }
bool int64(u64 addr, i64 value);
inline bool int64(i8 value) { return int64(0, value); }
bool uint64(u64 addr, u64 value);
inline bool uint64(i8 value) { return uint64(0, value); }
bool float32(u64 addr, f32 value);
inline bool float32(i8 value) { return float32(0, value); }
bool float64(u64 addr, f64 value);
inline bool float64(i8 value) { return float64(0, value); }
bool stream(u64 addr, const Stream& value, bool storeSize = true);
inline bool stream(const Stream& value, bool storeSize = true) { return stream(0, value, storeSize); }
bool string(u64 addr, const String& value, bool storeSize = true, bool null_terminated = false); // if sizeStored, null_terminated will be ignored
inline bool string(const String& value, bool storeSize = true, bool null_terminated = false) { return string(0, value, storeSize, null_terminated); }
bool object(u64 addr, const __i_serializable& value);
inline bool object(const __i_serializable& value) { return object(0, value); }
private:
write(void) = default;
};
private:
Serial(void) = default;
inline static void managed_address_check(u64& addr) { if (isManagedAddressEnabled()) addr = s_addr; }
private:
inline static StreamEdit s_openStream { };
inline static Endianness s_endianness { Endianness::LittleEndian };
inline static u64 s_addr { 0 };
inline static bool s_managedAddress { false };
};
class __i_serializable
{
public:
virtual Serial::Stream serialize(void) const = 0;
virtual bool deserialize(const Serial::Stream& data) = 0;
};
// =============================================== OLD VERSION ===============================================
class OutputHandlerBase;
namespace serial namespace serial
{ {
class SerialIO class SerialIO