[ox] Add Reader_c and make MetalClawReader use it
This commit is contained in:
parent
4ab710b155
commit
1f78ea1f37
12
deps/ox/src/ox/claw/CMakeLists.txt
vendored
12
deps/ox/src/ox/claw/CMakeLists.txt
vendored
@ -5,7 +5,6 @@ add_library(
|
|||||||
write.cpp
|
write.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_compile_options(OxClaw PRIVATE -Wsign-conversion)
|
target_compile_options(OxClaw PRIVATE -Wsign-conversion)
|
||||||
target_compile_options(OxClaw PRIVATE -Wconversion)
|
target_compile_options(OxClaw PRIVATE -Wconversion)
|
||||||
@ -17,6 +16,17 @@ target_link_libraries(
|
|||||||
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(OX_USE_STDLIB)
|
||||||
|
add_executable(
|
||||||
|
readclaw
|
||||||
|
readclaw.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(
|
||||||
|
readclaw PUBLIC
|
||||||
|
OxClaw
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(TARGETS OxClaw
|
install(TARGETS OxClaw
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
|
3
deps/ox/src/ox/claw/read.cpp
vendored
3
deps/ox/src/ox/claw/read.cpp
vendored
@ -80,7 +80,8 @@ Result<ModelObject> readClaw(TypeStore *ts, const char *buff, std::size_t buffSz
|
|||||||
switch (header.fmt) {
|
switch (header.fmt) {
|
||||||
case ClawFormat::Metal:
|
case ClawFormat::Metal:
|
||||||
{
|
{
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
ox::BufferReader br(header.data, header.dataSize);
|
||||||
|
MetalClawReader reader(br);
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
oxReturnError(model(&handler, &obj));
|
oxReturnError(model(&handler, &obj));
|
||||||
return obj;
|
return obj;
|
||||||
|
3
deps/ox/src/ox/claw/read.hpp
vendored
3
deps/ox/src/ox/claw/read.hpp
vendored
@ -51,7 +51,8 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
|
|||||||
switch (header.fmt) {
|
switch (header.fmt) {
|
||||||
case ClawFormat::Metal:
|
case ClawFormat::Metal:
|
||||||
{
|
{
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
ox::BufferReader br(header.data, header.dataSize);
|
||||||
|
MetalClawReader reader(br);
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
return model(&handler, val);
|
return model(&handler, val);
|
||||||
}
|
}
|
||||||
|
6
deps/ox/src/ox/mc/err.hpp
vendored
6
deps/ox/src/ox/mc/err.hpp
vendored
@ -11,9 +11,9 @@
|
|||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MC_PRESENCEMASKOUTBOUNDS = 1,
|
McPresenceMapOverflow = 1,
|
||||||
MC_BUFFENDED = 2,
|
McBuffEnded = 2,
|
||||||
MC_OUTBUFFENDED = 4
|
McOutputBuffEnded = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
90
deps/ox/src/ox/mc/intops.hpp
vendored
90
deps/ox/src/ox/mc/intops.hpp
vendored
@ -14,6 +14,7 @@
|
|||||||
#include <ox/std/byteswap.hpp>
|
#include <ox/std/byteswap.hpp>
|
||||||
#include <ox/std/math.hpp>
|
#include <ox/std/math.hpp>
|
||||||
#include <ox/std/memops.hpp>
|
#include <ox/std/memops.hpp>
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
|
||||||
namespace ox::mc {
|
namespace ox::mc {
|
||||||
|
|
||||||
@ -114,7 +115,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
|||||||
* length integer.
|
* length integer.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static constexpr std::size_t countBytes(unsigned b) noexcept {
|
constexpr std::size_t countBytes(unsigned b) noexcept {
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
while ((b >> i) & 1) ++i;
|
while ((b >> i) & 1) ++i;
|
||||||
return i + 1;
|
return i + 1;
|
||||||
@ -131,55 +132,60 @@ static_assert(countBytes(0b0111'1111) == 8);
|
|||||||
static_assert(countBytes(0b1111'1111) == 9);
|
static_assert(countBytes(0b1111'1111) == 9);
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Result<I> decodeInteger(const uint8_t buff[9], std::size_t buffLen, std::size_t *bytesRead) noexcept {
|
constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noexcept {
|
||||||
const auto bytes = countBytes(buff[0]);
|
uint8_t firstByte = 0;
|
||||||
|
oxReturnError(rdr.read(&firstByte, 1));
|
||||||
|
oxReturnError(rdr.seekg(-1, ox::ios_base::cur));
|
||||||
|
const auto bytes = countBytes(firstByte);
|
||||||
if (bytes == 9) {
|
if (bytes == 9) {
|
||||||
*bytesRead = bytes;
|
*bytesRead = bytes;
|
||||||
I out = 0;
|
I out = 0;
|
||||||
ox_memcpy(&out, &buff[1], sizeof(I));
|
oxReturnError(rdr.seekg(1, ox::ios_base::cur));
|
||||||
|
oxReturnError(rdr.read(&out, sizeof(I)));
|
||||||
return fromLittleEndian<I>(out);
|
return fromLittleEndian<I>(out);
|
||||||
} else if (buffLen >= bytes) {
|
|
||||||
*bytesRead = bytes;
|
|
||||||
uint64_t decoded = 0;
|
|
||||||
ox_memcpy(&decoded, &buff[0], bytes);
|
|
||||||
decoded >>= bytes;
|
|
||||||
// move sign bit
|
|
||||||
if constexpr(is_signed_v<I>) {
|
|
||||||
const auto negBit = bytes * 8 - bytes - 1;
|
|
||||||
// move sign
|
|
||||||
const auto negative = (decoded >> negBit) == 1;
|
|
||||||
if (negative) {
|
|
||||||
// fill in all bits between encoded sign and real sign with 1s
|
|
||||||
// split it up because the 32-bit ARM can't shift more than 32 bits
|
|
||||||
ox::Array<uint32_t, 2> d = {};
|
|
||||||
ox_memcpy(d.data(), &decoded, sizeof(decoded));
|
|
||||||
auto bit = negBit;
|
|
||||||
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
|
|
||||||
d[0] |= 1 << bit;
|
|
||||||
}
|
|
||||||
bit -= 32;
|
|
||||||
for (; bit < Bits<I>; ++bit) {
|
|
||||||
d[1] |= 1 << bit;
|
|
||||||
}
|
|
||||||
I out = 0;
|
|
||||||
if constexpr(ox::defines::BigEndian) {
|
|
||||||
const auto d0Tmp = d[0];
|
|
||||||
d[0] = d[1];
|
|
||||||
d[1] = d0Tmp;
|
|
||||||
}
|
|
||||||
ox_memcpy(&out, d.data(), sizeof(out));
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return static_cast<I>(decoded);
|
|
||||||
}
|
}
|
||||||
return OxError(1);
|
*bytesRead = bytes;
|
||||||
|
uint64_t decoded = 0;
|
||||||
|
oxReturnError(rdr.read(&decoded, bytes));
|
||||||
|
decoded >>= bytes;
|
||||||
|
// move sign bit
|
||||||
|
if constexpr(is_signed_v<I>) {
|
||||||
|
const auto negBit = bytes * 8 - bytes - 1;
|
||||||
|
// move sign
|
||||||
|
const auto negative = (decoded >> negBit) == 1;
|
||||||
|
if (negative) {
|
||||||
|
// fill in all bits between encoded sign and real sign with 1s
|
||||||
|
// split it up because the 32-bit ARM can't shift more than 32 bits
|
||||||
|
ox::Array<uint32_t, 2> d = {};
|
||||||
|
//d[0] = decoded & 0xffff'ffff;
|
||||||
|
//d[1] = decoded >> 32;
|
||||||
|
ox_memcpy(d.data(), &decoded, sizeof(decoded));
|
||||||
|
auto bit = negBit;
|
||||||
|
for (; bit < ox::min<std::size_t>(Bits<I>, 32); ++bit) {
|
||||||
|
d[0] |= 1 << bit;
|
||||||
|
}
|
||||||
|
bit -= 32;
|
||||||
|
for (; bit < Bits<I>; ++bit) {
|
||||||
|
d[1] |= 1 << bit;
|
||||||
|
}
|
||||||
|
I out = 0;
|
||||||
|
if constexpr(ox::defines::BigEndian) {
|
||||||
|
const auto d0Tmp = d[0];
|
||||||
|
d[0] = d[1];
|
||||||
|
d[1] = d0Tmp;
|
||||||
|
}
|
||||||
|
ox_memcpy(&out, d.data(), sizeof(out));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return static_cast<I>(decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Result<I> decodeInteger(McInt m) noexcept {
|
Result<I> decodeInteger(McInt m) noexcept {
|
||||||
std::size_t bytesRead;
|
std::size_t bytesRead{};
|
||||||
return decodeInteger<I>(m.data, 9, &bytesRead);
|
BufferReader br(reinterpret_cast<const char*>(m.data), 9);
|
||||||
|
return decodeInteger<I>(br, &bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
4
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template class FieldBitmapReader<uint8_t*>;
|
template class FieldBitmapWriterBase<uint8_t*>;
|
||||||
template class FieldBitmapReader<const uint8_t*>;
|
template class FieldBitmapWriterBase<const uint8_t*>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
85
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
85
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
@ -8,21 +8,77 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ox/std/array.hpp>
|
||||||
|
#include <ox/std/bit.hpp>
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
#include <ox/std/types.hpp>
|
#include <ox/std/types.hpp>
|
||||||
|
#include <ox/std/reader.hpp>
|
||||||
|
|
||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template<typename T>
|
template<Reader_c Reader>
|
||||||
class FieldBitmapReader {
|
class FieldBitmapReader {
|
||||||
|
protected:
|
||||||
|
mutable std::size_t m_mapBlockIdx = ~std::size_t{0};
|
||||||
|
mutable uint64_t m_mapBlock = 0;
|
||||||
|
std::size_t m_mapStart = 0;
|
||||||
|
Reader &m_reader;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
|
||||||
|
|
||||||
|
constexpr Result<bool> get(std::size_t i) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
constexpr ox::Error loadMapBlock(std::size_t id) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
|
||||||
|
m_mapStart(reader.tellg()),
|
||||||
|
m_reader(reader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr Result<bool> FieldBitmapReader<Reader>::get(std::size_t idx) const noexcept {
|
||||||
|
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||||
|
auto const blockIdx = idx / blockBits;
|
||||||
|
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||||
|
oxReturnError(loadMapBlock(blockIdx));
|
||||||
|
}
|
||||||
|
idx %= blockBits;
|
||||||
|
return (m_mapBlock >> idx) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
|
constexpr ox::Error FieldBitmapReader<Reader>::loadMapBlock(std::size_t idx) const noexcept {
|
||||||
|
oxRequire(g, m_reader.tellg());
|
||||||
|
oxReturnError(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||||
|
ox::Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||||
|
oxReturnError(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||||
|
// Warning: narrow-conv
|
||||||
|
oxReturnError(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||||
|
m_mapBlock = 0;
|
||||||
|
for (auto i = 0ull; auto b : mapBlock) {
|
||||||
|
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||||
|
i += 8;
|
||||||
|
}
|
||||||
|
m_mapBlockIdx = idx;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class FieldBitmapWriterBase {
|
||||||
protected:
|
protected:
|
||||||
T m_map = nullptr;
|
T m_map = nullptr;
|
||||||
std::size_t m_mapLen = 0;
|
std::size_t m_mapLen = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FieldBitmapReader(T map, std::size_t maxLen) noexcept;
|
constexpr FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept;
|
||||||
|
|
||||||
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
|
constexpr auto setBuffer(T map, std::size_t maxLen) noexcept;
|
||||||
|
|
||||||
@ -38,45 +94,45 @@ class FieldBitmapReader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr FieldBitmapReader<T>::FieldBitmapReader(T map, std::size_t maxLen) noexcept {
|
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(T map, std::size_t maxLen) noexcept {
|
||||||
m_map = map;
|
m_map = map;
|
||||||
m_mapLen = maxLen;
|
m_mapLen = maxLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto FieldBitmapReader<T>::setBuffer(T map, std::size_t maxLen) noexcept {
|
constexpr auto FieldBitmapWriterBase<T>::setBuffer(T map, std::size_t maxLen) noexcept {
|
||||||
m_map = map;
|
m_map = map;
|
||||||
m_mapLen = maxLen;
|
m_mapLen = maxLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Result<bool> FieldBitmapReader<T>::get(std::size_t i) const noexcept {
|
constexpr Result<bool> FieldBitmapWriterBase<T>::get(std::size_t i) const noexcept {
|
||||||
if (i / 8 < m_mapLen) {
|
if (i / 8 < m_mapLen) {
|
||||||
return (m_map[i / 8] >> (i % 8)) & 1;
|
return (m_map[i / 8] >> (i % 8)) & 1;
|
||||||
} else {
|
} else {
|
||||||
return OxError(MC_PRESENCEMASKOUTBOUNDS);
|
return OxError(McPresenceMapOverflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr void FieldBitmapReader<T>::setFields(int fields) noexcept {
|
constexpr void FieldBitmapWriterBase<T>::setFields(int fields) noexcept {
|
||||||
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
m_mapLen = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr void FieldBitmapReader<T>::setMaxLen(int maxLen) noexcept {
|
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int maxLen) noexcept {
|
||||||
m_mapLen = static_cast<std::size_t>(maxLen);
|
m_mapLen = static_cast<std::size_t>(maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr int64_t FieldBitmapReader<T>::getMaxLen() const noexcept {
|
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
|
||||||
return static_cast<int64_t>(m_mapLen);
|
return static_cast<int64_t>(m_mapLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern template class FieldBitmapReader<uint8_t*>;
|
extern template class FieldBitmapWriterBase<uint8_t*>;
|
||||||
extern template class FieldBitmapReader<const uint8_t*>;
|
extern template class FieldBitmapWriterBase<const uint8_t*>;
|
||||||
|
|
||||||
class FieldBitmap: public FieldBitmapReader<uint8_t*> {
|
class FieldBitmap: public FieldBitmapWriterBase<uint8_t*> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
|
constexpr FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept;
|
||||||
@ -85,7 +141,8 @@ class FieldBitmap: public FieldBitmapReader<uint8_t*> {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept: FieldBitmapReader<uint8_t*>(map, maxLen) {
|
constexpr FieldBitmap::FieldBitmap(uint8_t *map, std::size_t maxLen) noexcept:
|
||||||
|
FieldBitmapWriterBase<uint8_t*>(map, maxLen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
||||||
@ -97,7 +154,7 @@ constexpr Error FieldBitmap::set(std::size_t i, bool on) noexcept {
|
|||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
return OxError(MC_PRESENCEMASKOUTBOUNDS);
|
return OxError(McPresenceMapOverflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
338
deps/ox/src/ox/mc/read.hpp
vendored
338
deps/ox/src/ox/mc/read.hpp
vendored
@ -26,22 +26,22 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
class MetalClawReaderTemplate {
|
class MetalClawReaderTemplate: public ModelHandlerBase<MetalClawReaderTemplate<Reader>> {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FieldBitmapReader<const uint8_t*> m_fieldPresence;
|
FieldBitmapReader<Reader> m_fieldPresence;
|
||||||
std::size_t m_fields = 0;
|
std::size_t m_fields = 0;
|
||||||
std::size_t m_field = 0;
|
std::size_t m_field = 0;
|
||||||
int m_unionIdx = -1;
|
int m_unionIdx = -1;
|
||||||
std::size_t m_buffIt = 0;
|
Reader &m_reader;
|
||||||
std::size_t m_buffLen = 0;
|
MetalClawReaderTemplate<Reader> *m_parent = nullptr;
|
||||||
const uint8_t *m_buff = nullptr;
|
|
||||||
MetalClawReaderTemplate<HandlerMaker> *m_parent = nullptr;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen, int unionIdx = -1,
|
explicit constexpr MetalClawReaderTemplate(
|
||||||
MetalClawReaderTemplate<HandlerMaker> *parent = nullptr) noexcept;
|
Reader &reader,
|
||||||
|
int unionIdx = -1,
|
||||||
|
MetalClawReaderTemplate<Reader> *parent = nullptr) noexcept;
|
||||||
|
|
||||||
constexpr ~MetalClawReaderTemplate() noexcept;
|
constexpr ~MetalClawReaderTemplate() noexcept;
|
||||||
|
|
||||||
@ -95,8 +95,7 @@ class MetalClawReaderTemplate {
|
|||||||
/**
|
/**
|
||||||
* Reads an string length from the current location in the buffer.
|
* Reads an string length from the current location in the buffer.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
constexpr Result<StringLength> stringLength(const char *name) noexcept;
|
||||||
constexpr StringLength stringLength(const char *name) noexcept;
|
|
||||||
|
|
||||||
template<typename T = std::nullptr_t>
|
template<typename T = std::nullptr_t>
|
||||||
constexpr ox::Error setTypeInfo(
|
constexpr ox::Error setTypeInfo(
|
||||||
@ -109,7 +108,7 @@ class MetalClawReaderTemplate {
|
|||||||
* Returns a MetalClawReader to parse a child object.
|
* Returns a MetalClawReader to parse a child object.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker> child(const char *name, int unionIdx = -1) noexcept;
|
constexpr MetalClawReaderTemplate<Reader> child(const char *name, int unionIdx = -1) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not the next field to be read is present.
|
* Indicates whether or not the next field to be read is present.
|
||||||
@ -139,127 +138,118 @@ class MetalClawReaderTemplate {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker>::MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen,
|
constexpr MetalClawReaderTemplate<Reader>::MetalClawReaderTemplate(
|
||||||
int unionIdx,
|
Reader &reader,
|
||||||
MetalClawReaderTemplate *parent) noexcept:
|
int unionIdx,
|
||||||
m_fieldPresence(buff, buffLen),
|
MetalClawReaderTemplate *parent) noexcept:
|
||||||
|
m_fieldPresence(reader),
|
||||||
m_unionIdx(unionIdx),
|
m_unionIdx(unionIdx),
|
||||||
m_buffLen(buffLen),
|
m_reader(reader),
|
||||||
m_buff(buff),
|
|
||||||
m_parent(parent) {
|
m_parent(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker>::~MetalClawReaderTemplate() noexcept {
|
constexpr MetalClawReaderTemplate<Reader>::~MetalClawReaderTemplate() noexcept {
|
||||||
if (m_parent) {
|
|
||||||
m_parent->m_buffIt += m_buffIt;
|
|
||||||
}
|
|
||||||
if (m_field != m_fields) {
|
if (m_field != m_fields) {
|
||||||
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
|
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int8_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int8_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int16_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int16_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int32_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int32_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int64_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, int64_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint8_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint8_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint16_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint16_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint32_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint32_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint64_t *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, uint64_t *val) noexcept {
|
||||||
return readInteger(val);
|
return readInteger(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, bool *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, bool *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
auto valErr = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
auto const result = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
||||||
*val = valErr.value;
|
*val = result.value;
|
||||||
oxReturnError(valErr.error);
|
oxReturnError(result);
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// array handler
|
// array handler
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
// read the list
|
// read the list
|
||||||
if (valLen >= len) {
|
if (valLen >= len) {
|
||||||
auto reader = child("");
|
auto reader = child({});
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
oxReturnError(handler.field("", &val[i]));
|
oxReturnError(handler.field({}, &val[i]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oxTrace("ox::mc::read::field(T)") << name << ", size:" << valLen;
|
oxTracef("ox::mc::read::field(T)", "{}, length: {}", name, valLen);
|
||||||
return OxError(MC_OUTBUFFENDED);
|
return OxError(McOutputBuffEnded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMap<String, T> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, HashMap<String, T> *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
oxRequire(g, m_reader.tellg());
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
oxReturnError(m_reader.seekg(g));
|
||||||
// read the list
|
// read the list
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
const auto keyLen = handler.stringLength(nullptr);
|
oxRequire(keyLen, handler.stringLength(nullptr));
|
||||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||||
auto wkeyPtr = wkey.get();
|
auto wkeyPtr = wkey.get();
|
||||||
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
|
oxReturnError(handler.fieldCString("", &wkeyPtr, keyLen + 1));
|
||||||
@ -271,18 +261,19 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMa
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val) noexcept {
|
||||||
if constexpr(isVector_v<T>) {
|
if constexpr(isVector_v<T>) {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
// set size of val if the field is present, don't worry about it if not
|
// set size of val if the field is present, don't worry about it if not
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
oxRequire(len, arrayLength(name, false));
|
oxRequire(len, arrayLength(name, false));
|
||||||
val->resize(len);
|
val->resize(len);
|
||||||
|
return field(name, val->data(), val->size());
|
||||||
}
|
}
|
||||||
return field(name, val->data(), val->size());
|
|
||||||
}
|
}
|
||||||
|
val->resize(0);
|
||||||
++m_field;
|
++m_field;
|
||||||
return {};
|
return {};
|
||||||
} else if constexpr(isArray_v<T>) {
|
} else if constexpr(isArray_v<T>) {
|
||||||
@ -302,8 +293,7 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T
|
|||||||
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val) {
|
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
oxReturnError(model(reader.interface(), val));
|
||||||
oxReturnError(model(&handler, val));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
@ -311,44 +301,35 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename U, bool force>
|
template<typename U, bool force>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, UnionView<U, force> val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, UnionView<U, force> val) noexcept {
|
||||||
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val.get()) {
|
if ((m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) && val.get()) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
auto reader = child("", val.idx());
|
auto reader = child("", val.idx());
|
||||||
auto handler = HandlerMaker(&reader);
|
oxReturnError(model(reader.interface(), val.get()));
|
||||||
oxReturnError(model(&handler, val.get()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<std::size_t SmallStringSize>
|
template<std::size_t SmallStringSize>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(size, mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
const auto cap = size;
|
const auto cap = size;
|
||||||
*val = BasicString<SmallStringSize>(cap);
|
*val = BasicString<SmallStringSize>(cap);
|
||||||
auto data = val->data();
|
auto data = val->data();
|
||||||
// read the string
|
// read the string
|
||||||
if (static_cast<StringLength>(cap) < size) {
|
if (static_cast<StringLength>(cap) < size) {
|
||||||
return OxError(MC_OUTBUFFENDED);
|
return OxError(McOutputBuffEnded);
|
||||||
}
|
}
|
||||||
if (m_buffIt + size > m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
ox_strncpy(data, &m_buff[m_buffIt], size);
|
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
} else {
|
||||||
*val = "";
|
*val = "";
|
||||||
}
|
}
|
||||||
@ -357,81 +338,56 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, BasicS
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<std::size_t L>
|
template<std::size_t L>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, BString<L> *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, BString<L> *val) noexcept {
|
||||||
return fieldCString(name, val->data(), val->cap());
|
return fieldCString(name, val->data(), val->cap());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
if (size > buffLen) {
|
if (size > buffLen) {
|
||||||
return OxError(MC_OUTBUFFENDED);
|
return OxError(McOutputBuffEnded);
|
||||||
}
|
}
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate in case too small
|
// re-allocate in case too small
|
||||||
auto data = val;
|
auto data = val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
data[size] = 0;
|
||||||
data[size] = 0;
|
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val) noexcept {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate in case too small
|
// re-allocate in case too small
|
||||||
safeDelete(*val);
|
safeDelete(*val);
|
||||||
*val = new char[size + 1];
|
*val = new char[size + 1];
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
data[size] = 0;
|
||||||
data[size] = 0;
|
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++m_field;
|
++m_field;
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
oxRequire(size, mc::decodeInteger<StringLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(err);
|
|
||||||
// re-allocate if too small
|
// re-allocate if too small
|
||||||
if (buffLen < size + 1) {
|
if (buffLen < size + 1) {
|
||||||
safeDelete(*val);
|
safeDelete(*val);
|
||||||
@ -440,13 +396,8 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*,
|
|||||||
}
|
}
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
// read the string
|
// read the string
|
||||||
if (m_buffIt + size <= m_buffLen) {
|
oxReturnError(m_reader.read(data, size));
|
||||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
data[size] = 0;
|
||||||
data[size] = 0;
|
|
||||||
m_buffIt += size;
|
|
||||||
} else {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
auto data = *val;
|
auto data = *val;
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -458,18 +409,16 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*,
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr Result<ArrayLength> MetalClawReaderTemplate<HandlerMaker>::arrayLength(const char*, bool pass) noexcept {
|
constexpr Result<ArrayLength> MetalClawReaderTemplate<Reader>::arrayLength(const char*, bool pass) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
auto out = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead).value;
|
oxRequire(g, m_reader.tellg());
|
||||||
if (pass) {
|
oxRequire(out, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
if (!pass) {
|
||||||
|
oxReturnError(m_reader.seekg(g));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -477,20 +426,29 @@ constexpr Result<ArrayLength> MetalClawReaderTemplate<HandlerMaker>::arrayLength
|
|||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
|
constexpr Result<StringLength> MetalClawReaderTemplate<Reader>::stringLength(const char*) noexcept {
|
||||||
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
|
// read the length
|
||||||
|
std::size_t bytesRead = 0;
|
||||||
|
auto len = mc::decodeInteger<StringLength>(m_reader, &bytesRead);
|
||||||
|
oxReturnError(m_reader.seekg(-static_cast<int64_t>(bytesRead), ox::ios_base::cur));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Reader_c Reader>
|
||||||
template<typename I>
|
template<typename I>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::readInteger(I *val) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::readInteger(I *val) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
if (m_buffIt >= m_buffLen) {
|
auto const result = mc::decodeInteger<I>(m_reader, &bytesRead);
|
||||||
oxTrace("ox::MetalClaw::readInteger") << "Buffer ended";
|
oxReturnError(result);
|
||||||
return OxError(MC_BUFFENDED);
|
*val = result.value;
|
||||||
}
|
|
||||||
auto valErr = mc::decodeInteger<I>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
|
||||||
m_buffIt += bytesRead;
|
|
||||||
oxReturnError(valErr.error);
|
|
||||||
*val = valErr.value;
|
|
||||||
} else {
|
} else {
|
||||||
*val = 0;
|
*val = 0;
|
||||||
}
|
}
|
||||||
@ -499,22 +457,17 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::readInteger(I *val) noexc
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
template<typename T, typename CB>
|
template<typename T, typename CB>
|
||||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb) noexcept {
|
constexpr Error MetalClawReaderTemplate<Reader>::field(const char*, CB cb) noexcept {
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||||
// read the length
|
// read the length
|
||||||
if (m_buffIt >= m_buffLen) {
|
|
||||||
return OxError(MC_BUFFENDED);
|
|
||||||
}
|
|
||||||
std::size_t bytesRead = 0;
|
std::size_t bytesRead = 0;
|
||||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
oxRequire(len, mc::decodeInteger<ArrayLength>(m_reader, &bytesRead));
|
||||||
m_buffIt += bytesRead;
|
|
||||||
|
|
||||||
// read the list
|
// read the list
|
||||||
auto reader = child("");
|
auto reader = child("");
|
||||||
auto handler = HandlerMaker(&reader);
|
auto &handler = *reader.interface();
|
||||||
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
oxReturnError(handler.setTypeInfo("List", 0, {}, static_cast<std::size_t>(len)));
|
||||||
for (std::size_t i = 0; i < len; ++i) {
|
for (std::size_t i = 0; i < len; ++i) {
|
||||||
T val;
|
T val;
|
||||||
@ -527,50 +480,36 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb)
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr StringLength MetalClawReaderTemplate<HandlerMaker>::stringLength(const char*) noexcept {
|
|
||||||
if (m_unionIdx == -1 || static_cast<std::size_t>(m_unionIdx) == m_field) {
|
|
||||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
|
||||||
// read the length
|
|
||||||
std::size_t bytesRead = 0;
|
|
||||||
auto len = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
|
||||||
return len.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error MetalClawReaderTemplate<HandlerMaker>::setTypeInfo(
|
constexpr ox::Error MetalClawReaderTemplate<Reader>::setTypeInfo(
|
||||||
const char*, int, const Vector<String>&, std::size_t fields) noexcept {
|
const char*, int, const Vector<String>&, std::size_t fields) noexcept {
|
||||||
m_fields = fields;
|
m_fields = fields;
|
||||||
m_buffIt = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
// Warning: narrow-conv
|
||||||
m_fieldPresence.setFields(static_cast<int>(fields));
|
return m_reader.seekg(
|
||||||
m_fieldPresence.setMaxLen(static_cast<int>(m_buffIt));
|
static_cast<int>((fields / 8 + 1) - (fields % 8 == 0)),
|
||||||
return {};
|
ox::ios_base::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr MetalClawReaderTemplate<HandlerMaker> MetalClawReaderTemplate<HandlerMaker>::child(const char*, int unionIdx) noexcept {
|
constexpr MetalClawReaderTemplate<Reader> MetalClawReaderTemplate<Reader>::child(const char*, int unionIdx) noexcept {
|
||||||
return MetalClawReaderTemplate<HandlerMaker>(m_buff + m_buffIt, m_buffLen - m_buffIt, unionIdx, this);
|
return MetalClawReaderTemplate<Reader>(m_reader, unionIdx, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(const char*) const noexcept {
|
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(const char*) const noexcept {
|
||||||
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(int fieldNo) const noexcept {
|
constexpr bool MetalClawReaderTemplate<Reader>::fieldPresent(int fieldNo) const noexcept {
|
||||||
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int MetalClawReaderTemplate<HandlerMaker>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
constexpr int MetalClawReaderTemplate<Reader>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
||||||
FieldBitmapReader<const uint8_t*> p(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
FieldBitmapReader<Reader> p(m_reader);
|
||||||
p.setFields(static_cast<int>(u.fieldCount()));
|
|
||||||
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
||||||
if (p.get(i)) {
|
if (p.get(i)) {
|
||||||
return static_cast<int>(i);
|
return static_cast<int>(i);
|
||||||
@ -579,18 +518,17 @@ constexpr int MetalClawReaderTemplate<HandlerMaker>::whichFieldPresent(const cha
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<auto HandlerMaker>
|
template<Reader_c Reader>
|
||||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::nextField() noexcept {
|
constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
|
||||||
++m_field;
|
++m_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
using MetalClawReader = MetalClawReaderTemplate<[](auto r) {
|
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
|
||||||
return ModelHandlerInterface{r};
|
|
||||||
}>;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
|
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
|
||||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(buff), buffLen);
|
BufferReader br(buff, buffLen);
|
||||||
|
MetalClawReader reader(br);
|
||||||
ModelHandlerInterface handler(&reader);
|
ModelHandlerInterface handler(&reader);
|
||||||
return model(&handler, val);
|
return model(&handler, val);
|
||||||
}
|
}
|
||||||
|
39
deps/ox/src/ox/mc/test/tests.cpp
vendored
39
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -18,8 +18,8 @@ union TestUnion {
|
|||||||
static constexpr auto TypeName = "TestUnion";
|
static constexpr auto TypeName = "TestUnion";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
bool Bool;
|
bool Bool;
|
||||||
uint32_t Int = 5;
|
uint32_t Int;
|
||||||
char *CString;
|
char *CString{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestStructNest {
|
struct TestStructNest {
|
||||||
@ -49,6 +49,7 @@ struct TestStruct {
|
|||||||
ox::BString<32> BString = "";
|
ox::BString<32> BString = "";
|
||||||
uint32_t List[4] = {0, 0, 0, 0};
|
uint32_t List[4] = {0, 0, 0, 0};
|
||||||
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
||||||
|
ox::Vector<uint32_t> Vector2 = {1, 2, 3, 4, 5};
|
||||||
ox::HashMap<ox::String, int> Map;
|
ox::HashMap<ox::String, int> Map;
|
||||||
TestStructNest EmptyStruct;
|
TestStructNest EmptyStruct;
|
||||||
TestStructNest Struct;
|
TestStructNest Struct;
|
||||||
@ -77,7 +78,6 @@ oxModelEnd()
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
||||||
oxReturnError(io->template setTypeInfo<TestStruct>());
|
oxReturnError(io->template setTypeInfo<TestStruct>());
|
||||||
oxReturnError(io->field("Vector", &obj->Vector));
|
|
||||||
oxReturnError(io->field("Bool", &obj->Bool));
|
oxReturnError(io->field("Bool", &obj->Bool));
|
||||||
oxReturnError(io->field("Int", &obj->Int));
|
oxReturnError(io->field("Int", &obj->Int));
|
||||||
oxReturnError(io->field("Int1", &obj->Int1));
|
oxReturnError(io->field("Int1", &obj->Int1));
|
||||||
@ -97,9 +97,10 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
|
|||||||
oxReturnError(io->field("String", &obj->String));
|
oxReturnError(io->field("String", &obj->String));
|
||||||
oxReturnError(io->field("BString", &obj->BString));
|
oxReturnError(io->field("BString", &obj->BString));
|
||||||
oxReturnError(io->field("List", obj->List, 4));
|
oxReturnError(io->field("List", obj->List, 4));
|
||||||
|
oxReturnError(io->field("Vector", &obj->Vector));
|
||||||
oxReturnError(io->field("Map", &obj->Map));
|
oxReturnError(io->field("Map", &obj->Map));
|
||||||
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
|
||||||
oxReturnError(io->field("Struct", &obj->Struct));
|
oxReturnError(io->field("Struct", &obj->Struct));
|
||||||
|
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,10 +111,9 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
[] {
|
[] {
|
||||||
// This test doesn't confirm much, but it does show that the writer
|
// This test doesn't confirm much, but it does show that the writer
|
||||||
// doesn't segfault
|
// doesn't segfault
|
||||||
static constexpr size_t buffLen = 1024;
|
ox::Array<char, 1024> buff;
|
||||||
char buff[buffLen];
|
|
||||||
TestStruct ts;
|
TestStruct ts;
|
||||||
oxReturnError(ox::writeMC(buff, buffLen, ts));
|
oxReturnError(ox::writeMC(buff.data(), buff.size(), ts));
|
||||||
oxReturnError(ox::writeMC(ts));
|
oxReturnError(ox::writeMC(ts));
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
@ -126,18 +126,19 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
TestStruct testIn, testOut;
|
TestStruct testIn, testOut;
|
||||||
testIn.Bool = true;
|
testIn.Bool = true;
|
||||||
testIn.Int = 42;
|
testIn.Int = 42;
|
||||||
testIn.Union.Int = 42;
|
|
||||||
testIn.String = "Test String 0";
|
|
||||||
testIn.BString = "Test String 1";
|
testIn.BString = "Test String 1";
|
||||||
|
testIn.String = "Test String 2";
|
||||||
|
testIn.Vector = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
|
||||||
|
testIn.Vector2 = {};
|
||||||
testIn.List[0] = 1;
|
testIn.List[0] = 1;
|
||||||
testIn.List[1] = 2;
|
testIn.List[1] = 2;
|
||||||
testIn.List[2] = 3;
|
testIn.List[2] = 3;
|
||||||
testIn.List[3] = 4;
|
testIn.List[3] = 4;
|
||||||
testIn.Map["asdf"] = 93;
|
testIn.Struct.Bool = true;
|
||||||
testIn.Map["aoeu"] = 94;
|
|
||||||
testIn.Struct.Bool = false;
|
|
||||||
testIn.Struct.Int = 300;
|
testIn.Struct.Int = 300;
|
||||||
testIn.Struct.BString = "Test String 2";
|
testIn.Struct.BString = "Test String 3";
|
||||||
|
testIn.unionIdx = 1;
|
||||||
|
testIn.Union.Int = 93;
|
||||||
// run tests
|
// run tests
|
||||||
const auto [buff, err] = ox::writeMC(testIn);
|
const auto [buff, err] = ox::writeMC(testIn);
|
||||||
oxAssert(err, "writeMC failed");
|
oxAssert(err, "writeMC failed");
|
||||||
@ -160,10 +161,11 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||||
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
||||||
oxAssert(testIn.Vector[0] == testOut.Vector[0], "Vector[0] value mismatch");
|
oxAssert(testIn.Vector.size() == testOut.Vector.size(), "Vector size mismatch");
|
||||||
oxAssert(testIn.Vector[1] == testOut.Vector[1], "Vector[1] value mismatch");
|
for (auto i = 0u; i < testIn.Vector.size(); ++i) {
|
||||||
oxAssert(testIn.Vector[2] == testOut.Vector[2], "Vector[2] value mismatch");
|
oxAssert(testIn.Vector[i] == testOut.Vector[i], ox::sfmt("Vector[{}] value mismatch", i));
|
||||||
oxAssert(testIn.Vector[3] == testOut.Vector[3], "Vector[3] value mismatch");
|
}
|
||||||
|
oxAssert(testIn.Vector2.size() == testOut.Vector2.size(), "Vector2 size mismatch");
|
||||||
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
|
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
|
||||||
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
|
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
|
||||||
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
|
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
|
||||||
@ -363,7 +365,8 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
|||||||
ox::TypeStore typeStore;
|
ox::TypeStore typeStore;
|
||||||
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
||||||
oxAssert(typeErr, "Descriptor write failed");
|
oxAssert(typeErr, "Descriptor write failed");
|
||||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, dataBuff, dataBuffLen,
|
ox::BufferReader br(dataBuff, dataBuffLen);
|
||||||
|
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br,
|
||||||
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
||||||
//std::cout << f.fieldName.c_str() << '\n';
|
//std::cout << f.fieldName.c_str() << '\n';
|
||||||
auto fieldName = f.fieldName.c_str();
|
auto fieldName = f.fieldName.c_str();
|
||||||
|
4
deps/ox/src/ox/mc/types.hpp
vendored
4
deps/ox/src/ox/mc/types.hpp
vendored
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
using StringLength = uint32_t;
|
using StringLength = std::size_t;
|
||||||
using ArrayLength = uint32_t;
|
using ArrayLength = std::size_t;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
7
deps/ox/src/ox/model/walk.hpp
vendored
7
deps/ox/src/ox/model/walk.hpp
vendored
@ -144,6 +144,13 @@ constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
|
|||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Reader, typename Handler>
|
||||||
|
constexpr Error walkModel(DescriptorType *type, Reader_c auto &reader, Handler handler) noexcept {
|
||||||
|
DataWalker<Reader, Handler> walker(type, handler);
|
||||||
|
Reader rdr(reader);
|
||||||
|
return model(&rdr, &walker);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Reader, typename Handler>
|
template<typename Reader, typename Handler>
|
||||||
constexpr Error walkModel(DescriptorType *type, const char *data, std::size_t dataLen, Handler handler) noexcept {
|
constexpr Error walkModel(DescriptorType *type, const char *data, std::size_t dataLen, Handler handler) noexcept {
|
||||||
DataWalker<Reader, Handler> walker(type, handler);
|
DataWalker<Reader, Handler> walker(type, handler);
|
||||||
|
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -30,6 +30,7 @@ add_library(
|
|||||||
math.cpp
|
math.cpp
|
||||||
memops.cpp
|
memops.cpp
|
||||||
random.cpp
|
random.cpp
|
||||||
|
reader.cpp
|
||||||
substitutes.cpp
|
substitutes.cpp
|
||||||
stacktrace.cpp
|
stacktrace.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
|
1
deps/ox/src/ox/std/buffer.cpp
vendored
1
deps/ox/src/ox/std/buffer.cpp
vendored
@ -13,6 +13,7 @@ namespace ox {
|
|||||||
|
|
||||||
template class Vector<char>;
|
template class Vector<char>;
|
||||||
|
|
||||||
|
template class ReaderT<BufferReader>;
|
||||||
template class WriterT<BufferWriter>;
|
template class WriterT<BufferWriter>;
|
||||||
template class WriterT<CharBuffWriter>;
|
template class WriterT<CharBuffWriter>;
|
||||||
|
|
||||||
|
70
deps/ox/src/ox/std/buffer.hpp
vendored
70
deps/ox/src/ox/std/buffer.hpp
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "reader.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include "writer.hpp"
|
#include "writer.hpp"
|
||||||
|
|
||||||
@ -166,6 +167,73 @@ class CharBuffWriter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BufferReader {
|
||||||
|
private:
|
||||||
|
std::size_t m_it = 0;
|
||||||
|
std::size_t m_size = 0;
|
||||||
|
char const* m_buff = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr explicit BufferReader(char const*buff, std::size_t sz) noexcept:
|
||||||
|
m_size(sz), m_buff(buff) {}
|
||||||
|
|
||||||
|
constexpr explicit BufferReader(ox::Buffer const&buffer) noexcept:
|
||||||
|
m_size(buffer.size()), m_buff(buffer.data()) {}
|
||||||
|
|
||||||
|
constexpr ox::Result<char> peek() const noexcept {
|
||||||
|
if (m_it >= m_size) [[unlikely]] {
|
||||||
|
return OxError(1, "Peek failed: buffer overrun");
|
||||||
|
}
|
||||||
|
return m_buff[m_it];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ox::Result<std::size_t> read(void *v, std::size_t sz) noexcept {
|
||||||
|
sz = ox::min(sz, m_size - m_it);
|
||||||
|
if (m_it + sz > m_size) [[unlikely]] {
|
||||||
|
return OxError(1, "Read failed: Buffer overrun");
|
||||||
|
}
|
||||||
|
ox_memcpy(v, &m_buff[m_it], sz);
|
||||||
|
m_it += sz;
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ox::Error seekg(std::size_t p) noexcept {
|
||||||
|
if (p > m_size) [[unlikely]] {
|
||||||
|
return OxError(1, "Seek failed: Buffer overrun");
|
||||||
|
}
|
||||||
|
m_it = p;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ox::Error seekg(int64_t off, ios_base::seekdir dir) noexcept {
|
||||||
|
ox::Signed<std::size_t> base = 0;
|
||||||
|
switch (dir) {
|
||||||
|
case ox::ios_base::beg:
|
||||||
|
base = 0;
|
||||||
|
break;
|
||||||
|
case ox::ios_base::end:
|
||||||
|
base = static_cast<ox::Signed<std::size_t>>(m_size);
|
||||||
|
break;
|
||||||
|
case ox::ios_base::cur:
|
||||||
|
base = static_cast<ox::Signed<std::size_t>>(m_it);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return OxError(1, "Invalid seekdir");
|
||||||
|
}
|
||||||
|
auto const newIt = static_cast<std::size_t>(base + off);
|
||||||
|
if (newIt > m_size) [[unlikely]] {
|
||||||
|
return OxError(1, "Seek failed: Buffer overrun");
|
||||||
|
}
|
||||||
|
m_it = newIt;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ox::Result<std::size_t> tellg() const noexcept {
|
||||||
|
return m_it;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern template class ReaderT<BufferReader>;
|
||||||
extern template class WriterT<BufferWriter>;
|
extern template class WriterT<BufferWriter>;
|
||||||
extern template class WriterT<CharBuffWriter>;
|
extern template class WriterT<CharBuffWriter>;
|
||||||
|
|
||||||
|
59
deps/ox/src/ox/std/reader.cpp
vendored
Normal file
59
deps/ox/src/ox/std/reader.cpp
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OX_USE_STDLIB
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "array.hpp"
|
||||||
|
#include "reader.hpp"
|
||||||
|
|
||||||
|
namespace ox {
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr int sdMap(ox::ios_base::seekdir in) noexcept {
|
||||||
|
switch (in) {
|
||||||
|
case ox::ios_base::beg:
|
||||||
|
return SEEK_SET;
|
||||||
|
case ox::ios_base::end:
|
||||||
|
return SEEK_END;
|
||||||
|
case ox::ios_base::cur:
|
||||||
|
return SEEK_CUR;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<char> FileReader::peek() const noexcept {
|
||||||
|
auto const c = fgetc(m_file);
|
||||||
|
auto const ok = c != EOF;
|
||||||
|
if (ok && ungetc(c, m_file)) [[unlikely]] {
|
||||||
|
return OxError(1, "Unable to unget character");
|
||||||
|
}
|
||||||
|
return {static_cast<char>(c), OxError(!ok, "File peek failed")};
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<std::size_t> FileReader::read(char *v, std::size_t cnt) noexcept {
|
||||||
|
return fread(v, 1, cnt, m_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error FileReader::seekg(std::size_t p) noexcept {
|
||||||
|
return OxError(fseek(m_file, static_cast<int64_t>(p), SEEK_CUR) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error FileReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
|
||||||
|
return OxError(fseek(m_file, p, sdMap(sd)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<std::size_t> FileReader::tellg() noexcept {
|
||||||
|
const auto sz = ftell(m_file);
|
||||||
|
return {static_cast<std::size_t>(sz), OxError(sz == -1)};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
96
deps/ox/src/ox/std/reader.hpp
vendored
Normal file
96
deps/ox/src/ox/std/reader.hpp
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef OX_USE_STDLIB
|
||||||
|
#include <cstdio>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "concepts.hpp"
|
||||||
|
#include "error.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
#include "writer.hpp"
|
||||||
|
|
||||||
|
namespace ox {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept Reader_c = requires(T v) {
|
||||||
|
{v.peek()} -> ox::same_as<ox::Result<char>>;
|
||||||
|
{v.read(static_cast<char*>(nullptr), static_cast<std::size_t>(0))} -> ox::same_as<ox::Result<std::size_t>>;
|
||||||
|
{v.seekg(static_cast<int64_t>(0))} -> ox::same_as<ox::Error>;
|
||||||
|
{v.seekg(static_cast<std::size_t>(0), ios_base::beg)} -> ox::same_as<ox::Error>;
|
||||||
|
{v.tellg()} -> ox::same_as<ox::Result<std::size_t>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Reader_v {
|
||||||
|
public:
|
||||||
|
virtual constexpr ~Reader_v() noexcept = default;
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual constexpr ox::Result<char> peek() const noexcept = 0;
|
||||||
|
virtual constexpr ox::Result<std::size_t> read(char*, std::size_t) noexcept = 0;
|
||||||
|
virtual constexpr ox::Result<std::size_t> tellg() noexcept = 0;
|
||||||
|
virtual constexpr ox::Error seekg(std::size_t) noexcept = 0;
|
||||||
|
virtual constexpr ox::Error seekg(int64_t, ios_base::seekdir) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Reader_c T>
|
||||||
|
class ReaderT: public Reader_v {
|
||||||
|
private:
|
||||||
|
T m_reader{};
|
||||||
|
public:
|
||||||
|
template<typename ...Args>
|
||||||
|
constexpr explicit ReaderT(Args&&... args) noexcept: m_reader(args...) {
|
||||||
|
}
|
||||||
|
constexpr ox::Result<char> peek() const noexcept override {
|
||||||
|
return m_reader.peek();
|
||||||
|
}
|
||||||
|
constexpr ox::Result<std::size_t> read(char *v, std::size_t cnt) noexcept override {
|
||||||
|
return m_reader.read(v, cnt);
|
||||||
|
}
|
||||||
|
constexpr ox::Error seekg(std::size_t p) noexcept override {
|
||||||
|
return m_reader.seekg(p);
|
||||||
|
}
|
||||||
|
constexpr ox::Error seekg(int64_t p, ios_base::seekdir sd) noexcept override {
|
||||||
|
return m_reader.seekg(p, sd);
|
||||||
|
}
|
||||||
|
constexpr ox::Result<std::size_t> tellg() noexcept override {
|
||||||
|
return m_reader.tellg();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef OX_USE_STDLIB
|
||||||
|
class FileReader: public Reader_v {
|
||||||
|
private:
|
||||||
|
FILE *m_file = nullptr;
|
||||||
|
public:
|
||||||
|
constexpr explicit FileReader(FILE *file) noexcept: m_file(file) {}
|
||||||
|
ox::Result<char> peek() const noexcept override;
|
||||||
|
ox::Result<std::size_t> read(char *v, std::size_t cnt) noexcept override;
|
||||||
|
ox::Error seekg(std::size_t p) noexcept override;
|
||||||
|
ox::Error seekg(int64_t p, ios_base::seekdir sd) noexcept override;
|
||||||
|
ox::Result<std::size_t> tellg() noexcept override;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates the specified amount of data at the end of the current read stream.
|
||||||
|
* @param reader
|
||||||
|
* @param sz
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
constexpr ox::Result<std::size_t> allocate(Reader_c auto *reader, std::size_t sz) noexcept {
|
||||||
|
const auto p = reader->tellg();
|
||||||
|
oxReturnError(reader->seekg(0, ios_base::end));
|
||||||
|
const auto out = reader->tellg();
|
||||||
|
oxReturnError(reader->read(nullptr, sz));
|
||||||
|
oxReturnError(reader->seekg(p));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user