[ox] Overhaul serialization/model system and add ModelValue/ModelObject/ModelUnion variant system
This commit is contained in:
parent
bc391b45fc
commit
ca64f95be3
2
deps/ox/.liccor.yml
vendored
2
deps/ox/.liccor.yml
vendored
@ -6,4 +6,4 @@ copyright_notice: |-
|
||||
|
||||
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/.
|
||||
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
4
deps/ox/deps/jsoncpp/CMakeLists.txt
vendored
4
deps/ox/deps/jsoncpp/CMakeLists.txt
vendored
@ -191,6 +191,10 @@ if(JSONCPP_WITH_TESTS)
|
||||
include(CTest)
|
||||
endif()
|
||||
|
||||
# DrinkingTea - begin
|
||||
set(CMAKE_CXX_FLAGS "-Wno-everything")
|
||||
# DrinkingTea - end
|
||||
|
||||
# Build the different applications
|
||||
add_subdirectory(src)
|
||||
|
||||
|
32
deps/ox/src/ox/claw/read.cpp
vendored
32
deps/ox/src/ox/claw/read.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/buffer.hpp>
|
||||
@ -72,4 +72,34 @@ Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
|
||||
return stripClawHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept {
|
||||
oxRequire(header, readClawHeader(buff));
|
||||
oxRequire(t, ts->template getLoad(header.typeName, header.typeVersion));
|
||||
ModelObject obj;
|
||||
oxReturnError(obj.setType(t));
|
||||
switch (header.fmt) {
|
||||
case ClawFormat::Metal:
|
||||
{
|
||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
oxReturnError(model(&handler, &obj));
|
||||
return obj;
|
||||
}
|
||||
case ClawFormat::Organic:
|
||||
{
|
||||
#ifdef OX_USE_STDLIB
|
||||
OrganicClawReader reader(header.data, header.dataSize);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
oxReturnError(model(&handler, &obj));
|
||||
return obj;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
case ClawFormat::None:
|
||||
return OxError(1);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
11
deps/ox/src/ox/claw/read.hpp
vendored
11
deps/ox/src/ox/claw/read.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -50,13 +50,14 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
|
||||
switch (header.fmt) {
|
||||
case ClawFormat::Metal:
|
||||
{
|
||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), buffLen);
|
||||
return model(&reader, val);
|
||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(header.data), header.dataSize);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
return model(&handler, val);
|
||||
}
|
||||
case ClawFormat::Organic:
|
||||
{
|
||||
#ifdef OX_USE_STDLIB
|
||||
OrganicClawReader reader(header.data, buffLen);
|
||||
OrganicClawReader reader(header.data, header.dataSize);
|
||||
return model(&reader, val);
|
||||
#else
|
||||
break;
|
||||
@ -85,4 +86,6 @@ Result<T> readClaw(const Buffer &buff) {
|
||||
return readClaw<T>(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept;
|
||||
|
||||
}
|
||||
|
26
deps/ox/src/ox/claw/test/tests.cpp
vendored
26
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
@ -25,7 +25,7 @@ union TestUnion {
|
||||
static constexpr auto TypeVersion = 1;
|
||||
bool Bool;
|
||||
uint32_t Int = 5;
|
||||
char String[32];
|
||||
char *String;
|
||||
};
|
||||
|
||||
struct TestStructNest {
|
||||
@ -49,6 +49,7 @@ struct TestStruct {
|
||||
int32_t Int6 = 0;
|
||||
int32_t Int7 = 0;
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::BString<32> String = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
@ -56,21 +57,24 @@ struct TestStruct {
|
||||
TestStructNest Struct;
|
||||
|
||||
~TestStruct() {
|
||||
if (unionIdx == 2) {
|
||||
ox::safeDelete(Union.String);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestUnion *obj) {
|
||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) {
|
||||
io->template setTypeInfo<TestUnion>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
oxReturnError(io->field("String", ox::SerStr(obj->String)));
|
||||
oxReturnError(io->fieldCString("String", &obj->String));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStructNest *obj) {
|
||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStructNest> auto *obj) {
|
||||
io->template setTypeInfo<TestStructNest>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
@ -79,7 +83,7 @@ constexpr ox::Error model(T *io, TestStructNest *obj) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStruct *obj) {
|
||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
|
||||
io->template setTypeInfo<TestStruct>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
@ -91,7 +95,11 @@ constexpr ox::Error model(T *io, TestStruct *obj) {
|
||||
oxReturnError(io->field("Int6", &obj->Int6));
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
|
||||
int unionIdx = 0;
|
||||
if constexpr(ox_strcmp(T::opType(), ox::OpType::Reflect) != 0) {
|
||||
unionIdx = obj->unionIdx;
|
||||
}
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
|
||||
oxReturnError(io->field("String", &obj->String));
|
||||
oxReturnError(io->field("List", obj->List, 4));
|
||||
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
||||
@ -99,7 +107,7 @@ constexpr ox::Error model(T *io, TestStruct *obj) {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ClawHeaderReader",
|
||||
@ -153,7 +161,7 @@ std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
|
||||
auto [buff, err] = ox::writeClaw(&testIn, ox::ClawFormat::Metal);
|
||||
oxAssert(err, "writeMC failed");
|
||||
oxAssert(ox::readClaw(buff.data(), buff.size(), &testOut), "writeMC failed");
|
||||
oxAssert(ox::readClaw(buff.data(), buff.size(), &testOut), "readMC failed");
|
||||
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
||||
|
||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||
|
3
deps/ox/src/ox/claw/write.hpp
vendored
3
deps/ox/src/ox/claw/write.hpp
vendored
@ -82,8 +82,7 @@ Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<Buffer> writeClaw(T *t, ClawFormat fmt = ClawFormat::Metal) {
|
||||
Result<Buffer> writeClaw(auto *t, ClawFormat fmt = ClawFormat::Metal) {
|
||||
oxRequire(header, detail::writeClawHeader(t, fmt));
|
||||
oxRequire(data, fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t));
|
||||
Buffer out(header.len() + data.size());
|
||||
|
19
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
19
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
@ -3,12 +3,13 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/std.hpp>
|
||||
#include <ox/model/def.hpp>
|
||||
#include <ox/model/typenamecatcher.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
|
||||
@ -24,7 +25,7 @@ enum class FileAddressType: int8_t {
|
||||
class FileAddress {
|
||||
|
||||
template<typename T>
|
||||
friend constexpr Error model(T*, FileAddress*) noexcept;
|
||||
friend constexpr Error model(T*, CommonPtrWith<FileAddress> auto*) noexcept;
|
||||
|
||||
public:
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
|
||||
@ -129,22 +130,16 @@ constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, FileAddress::Data *obj) noexcept {
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||
io->template setTypeInfo<FileAddress::Data>();
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
String dummy;
|
||||
oxReturnError(io->field("path", &dummy));
|
||||
oxReturnError(io->field("constPath", &dummy));
|
||||
} else {
|
||||
oxReturnError(io->field("path", SerStr(&obj->path)));
|
||||
oxReturnError(io->field("constPath", SerStr(&obj->path)));
|
||||
}
|
||||
oxReturnError(io->fieldCString("path", &obj->path));
|
||||
oxReturnError(io->fieldCString("constPath", &obj->path));
|
||||
oxReturnError(io->field("inode", &obj->inode));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, FileAddress *fa) noexcept {
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
io->template setTypeInfo<FileAddress>();
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
int8_t type = 0;
|
||||
|
7
deps/ox/src/ox/mc/intops.hpp
vendored
7
deps/ox/src/ox/mc/intops.hpp
vendored
@ -64,7 +64,7 @@ template<typename I>
|
||||
[[nodiscard]]
|
||||
constexpr McInt encodeInteger(I input) noexcept {
|
||||
McInt out;
|
||||
auto inputNegative = is_signed_v<I> && input < 0;
|
||||
const auto inputNegative = is_signed_v<I> && input < 0;
|
||||
// move input to uint64_t to allow consistent bit manipulation, and to avoid
|
||||
// overflow concerns
|
||||
uint64_t val = 0;
|
||||
@ -72,7 +72,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
||||
if (val) {
|
||||
// bits needed to represent number factoring in space possibly
|
||||
// needed for signed bit
|
||||
const auto highBit = inputNegative ? (highestBit(~val)) : highestBit(val);
|
||||
const auto highBit = inputNegative ? highestBit(~val) : highestBit(val);
|
||||
const auto bits = highBit + 1 + (is_signed_v<I> ? 1 : 0);
|
||||
// bytes needed to store value
|
||||
std::size_t bytes = bits / 8 + (bits % 8 != 0);
|
||||
@ -84,7 +84,6 @@ constexpr McInt encodeInteger(I input) noexcept {
|
||||
++bytes;
|
||||
}
|
||||
const auto bytesIndicator = onMask<uint8_t>(bytes - 1);
|
||||
|
||||
// ensure we are copying from little endian representation
|
||||
LittleEndian<uint64_t> leVal = val;
|
||||
if (inputNegative) {
|
||||
@ -116,7 +115,7 @@ constexpr McInt encodeInteger(I input) noexcept {
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t countBytes(uint8_t b) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; (b >> i) & 1; i++);
|
||||
while ((b >> i) & 1) ++i;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
|
150
deps/ox/src/ox/mc/read.cpp
vendored
150
deps/ox/src/ox/mc/read.cpp
vendored
@ -3,157 +3,9 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
#include <ox/std/byteswap.hpp>
|
||||
#include <ox/std/memops.hpp>
|
||||
|
||||
#include "read.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
MetalClawReader::MetalClawReader(const uint8_t *buff, std::size_t buffLen, int unionIdx, MetalClawReader *parent) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff),
|
||||
m_parent(parent) {
|
||||
}
|
||||
|
||||
MetalClawReader::~MetalClawReader() noexcept {
|
||||
if (m_parent) {
|
||||
m_parent->m_buffIt += m_buffIt;
|
||||
}
|
||||
if (m_field != m_fields) {
|
||||
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
|
||||
}
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, int8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, int16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, int32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, int64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
|
||||
Error MetalClawReader::field(const char*, uint8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, uint16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, uint32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, uint64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, bool *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
auto valErr = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
||||
*val = valErr.value;
|
||||
oxReturnError(valErr.error);
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error MetalClawReader::field(const char*, SerStr val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
m_buffIt += bytesRead;
|
||||
oxReturnError(err);
|
||||
auto data = val.data(size + 1);
|
||||
// read the string
|
||||
if (val.cap() > -1 && static_cast<StringLength>(val.cap()) >= size) {
|
||||
if (m_buffIt + size <= m_buffLen) {
|
||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
||||
data[size] = 0;
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
} else {
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
} else {
|
||||
auto data = val.data();
|
||||
if (data) {
|
||||
data[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error MetalClawReader::fieldCString(const char *name, char **val, int len) noexcept {
|
||||
return field(name, SerStr(val, len));
|
||||
}
|
||||
|
||||
Result<ArrayLength> MetalClawReader::arrayLength(const char*, bool pass) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto out = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead).value;
|
||||
if (pass) {
|
||||
m_buffIt += bytesRead;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
StringLength MetalClawReader::stringLength(const char*) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && 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;
|
||||
}
|
||||
|
||||
MetalClawReader MetalClawReader::child(const char*, int unionIdx) noexcept {
|
||||
return MetalClawReader(m_buff + m_buffIt, m_buffLen - m_buffIt, unionIdx, this);
|
||||
}
|
||||
|
||||
bool MetalClawReader::fieldPresent(const char*) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
||||
}
|
||||
|
||||
bool MetalClawReader::fieldPresent(int fieldNo) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
||||
}
|
||||
|
||||
void MetalClawReader::nextField() noexcept {
|
||||
++m_field;
|
||||
}
|
||||
|
||||
}
|
||||
|
484
deps/ox/src/ox/mc/read.hpp
vendored
484
deps/ox/src/ox/mc/read.hpp
vendored
@ -3,12 +3,13 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/typenamecatcher.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
@ -25,7 +26,8 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
class MetalClawReader {
|
||||
template<auto HandlerMaker>
|
||||
class MetalClawReaderTemplate {
|
||||
|
||||
private:
|
||||
FieldBitmapReader<const uint8_t*> m_fieldPresence;
|
||||
@ -35,87 +37,93 @@ class MetalClawReader {
|
||||
std::size_t m_buffIt = 0;
|
||||
std::size_t m_buffLen = 0;
|
||||
const uint8_t *m_buff = nullptr;
|
||||
MetalClawReader *m_parent = nullptr;
|
||||
MetalClawReaderTemplate<HandlerMaker> *m_parent = nullptr;
|
||||
|
||||
public:
|
||||
MetalClawReader(const uint8_t *buff, std::size_t buffLen, int unionIdx = -1, MetalClawReader *parent = nullptr) noexcept;
|
||||
constexpr MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen, int unionIdx = -1,
|
||||
MetalClawReaderTemplate<HandlerMaker> *parent = nullptr) noexcept;
|
||||
|
||||
~MetalClawReader() noexcept;
|
||||
constexpr ~MetalClawReaderTemplate() noexcept;
|
||||
|
||||
Error field(const char*, int8_t *val) noexcept;
|
||||
Error field(const char*, int16_t *val) noexcept;
|
||||
Error field(const char*, int32_t *val) noexcept;
|
||||
Error field(const char*, int64_t *val) noexcept;
|
||||
constexpr Error field(const char*, int8_t *val) noexcept;
|
||||
constexpr Error field(const char*, int16_t *val) noexcept;
|
||||
constexpr Error field(const char*, int32_t *val) noexcept;
|
||||
constexpr Error field(const char*, int64_t *val) noexcept;
|
||||
|
||||
Error field(const char*, uint8_t *val) noexcept;
|
||||
Error field(const char*, uint16_t *val) noexcept;
|
||||
Error field(const char*, uint32_t *val) noexcept;
|
||||
Error field(const char*, uint64_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint8_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint16_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint32_t *val) noexcept;
|
||||
constexpr Error field(const char*, uint64_t *val) noexcept;
|
||||
|
||||
Error field(const char*, bool *val) noexcept;
|
||||
constexpr Error field(const char*, bool *val) noexcept;
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
constexpr Error field(const char*, auto *val, std::size_t len) noexcept;
|
||||
|
||||
// map handler
|
||||
template<typename T>
|
||||
Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
|
||||
// array handler, with callback to allow handling individual elements
|
||||
template<typename T, typename Handler>
|
||||
Error field(const char*, Handler handler) noexcept;
|
||||
template<typename T, typename CB>
|
||||
constexpr Error field(const char*, CB cb) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val) noexcept;
|
||||
constexpr Error field(const char*, T *val) noexcept;
|
||||
|
||||
template<typename U>
|
||||
Error field(const char*, UnionView<U> val) noexcept;
|
||||
template<typename U, bool force>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char*, BString<L> *val) noexcept;
|
||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
Error field(const char*, SerStr val) noexcept;
|
||||
constexpr Error fieldCString(const char*, char *val, std::size_t buffLen) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
constexpr Error fieldCString(const char*, char **val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char*, char **val, std::size_t buffLen) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
*/
|
||||
Result<ArrayLength> arrayLength(const char *name, bool pass = true) noexcept;
|
||||
constexpr Result<ArrayLength> arrayLength(const char *name, bool pass = true) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an string length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
StringLength stringLength(const char *name) noexcept;
|
||||
constexpr StringLength stringLength(const char *name) noexcept;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
/**
|
||||
* Returns a MetalClawReader to parse a child object.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
MetalClawReader child(const char *name, int unionIdx = -1) noexcept;
|
||||
constexpr MetalClawReaderTemplate<HandlerMaker> child(const char *name, int unionIdx = -1) noexcept;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the next field to be read is present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool fieldPresent(const char *name) const noexcept;
|
||||
constexpr bool fieldPresent(const char *name) const noexcept;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the given field is present.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
bool fieldPresent(int fieldNo) const noexcept;
|
||||
constexpr bool fieldPresent(int fieldNo) const noexcept;
|
||||
|
||||
void nextField() noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr int whichFieldPresent(const char *name, const ModelUnion&) const noexcept;
|
||||
|
||||
constexpr void nextField() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
@ -124,12 +132,145 @@ class MetalClawReader {
|
||||
|
||||
private:
|
||||
template<typename I>
|
||||
Error readInteger(I *val) noexcept;
|
||||
constexpr Error readInteger(I *val) noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr MetalClawReaderTemplate<HandlerMaker>::MetalClawReaderTemplate(const uint8_t *buff, std::size_t buffLen,
|
||||
int unionIdx,
|
||||
MetalClawReaderTemplate *parent) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff),
|
||||
m_parent(parent) {
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr MetalClawReaderTemplate<HandlerMaker>::~MetalClawReaderTemplate() noexcept {
|
||||
if (m_parent) {
|
||||
m_parent->m_buffIt += m_buffIt;
|
||||
}
|
||||
if (m_field != m_fields) {
|
||||
oxTrace("ox::mc::MetalClawReader::error") << "MetalClawReader: incorrect fields number given";
|
||||
}
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, int64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint8_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint16_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint32_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, uint64_t *val) noexcept {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, bool *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
auto valErr = m_fieldPresence.get(static_cast<std::size_t>(m_field));
|
||||
*val = valErr.value;
|
||||
oxReturnError(valErr.error);
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// array handler
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, auto *val, std::size_t valLen) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
// read the list
|
||||
if (valLen >= len) {
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
oxReturnError(handler.field("", &val[i]));
|
||||
}
|
||||
} else {
|
||||
oxTrace("ox::mc::read::field(T)") << name << ", size:" << valLen;
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<typename T>
|
||||
Error MetalClawReader::field(const char *name, T *val) noexcept {
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
const auto keyLen = handler.stringLength(nullptr);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
auto wkeyPtr = wkey.get();
|
||||
oxReturnError(handler.fieldCString("", &wkeyPtr, static_cast<int>(keyLen + 1)));
|
||||
oxReturnError(handler.field("", &val->operator[](wkey.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, T *val) noexcept {
|
||||
if constexpr(isVector_v<T>) {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
// set size of val if the field is present, don't worry about it if not
|
||||
@ -142,27 +283,35 @@ Error MetalClawReader::field(const char *name, T *val) noexcept {
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
} else {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val && m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
auto reader = child("");
|
||||
oxReturnError(model(&reader, val));
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
oxReturnError(model(&handler, val));
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Error MetalClawReader::field(const char*, UnionView<U> val) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val.get() && m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
auto reader = child("", val.idx());
|
||||
oxReturnError(model(&reader, val.get()));
|
||||
template<auto HandlerMaker>
|
||||
template<typename U, bool force>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, UnionView<U, force> val) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && val.get()) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
auto reader = child("", val.idx());
|
||||
auto handler = HandlerMaker(&reader);
|
||||
oxReturnError(model(&handler, val.get()));
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<std::size_t SmallStringSize>
|
||||
Error MetalClawReader::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
@ -193,13 +342,129 @@ Error MetalClawReader::field(const char*, BasicString<SmallStringSize> *val) noe
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<std::size_t L>
|
||||
Error MetalClawReader::field(const char *name, BString<L> *val) noexcept {
|
||||
return field(name, SerStr(val->data(), val->cap()));
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, BString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char *val, std::size_t buffLen) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
if (size > buffLen) {
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
m_buffIt += bytesRead;
|
||||
oxReturnError(err);
|
||||
// re-allocate in case too small
|
||||
auto data = val;
|
||||
// read the string
|
||||
if (m_buffIt + size <= m_buffLen) {
|
||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
||||
data[size] = 0;
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val) noexcept {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
m_buffIt += bytesRead;
|
||||
oxReturnError(err);
|
||||
// re-allocate in case too small
|
||||
safeDelete(*val);
|
||||
*val = new char[size + 1];
|
||||
auto data = *val;
|
||||
// read the string
|
||||
if (m_buffIt + size <= m_buffLen) {
|
||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
||||
data[size] = 0;
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::fieldCString(const char*, char **val, std::size_t buffLen) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
m_buffIt += bytesRead;
|
||||
oxReturnError(err);
|
||||
// re-allocate if too small
|
||||
if (buffLen < size + 1) {
|
||||
safeDelete(*val);
|
||||
*val = new char[size + 1];
|
||||
buffLen = size + 1;
|
||||
}
|
||||
auto data = *val;
|
||||
// read the string
|
||||
if (m_buffIt + size <= m_buffLen) {
|
||||
ox_memcpy(data, &m_buff[m_buffIt], size);
|
||||
data[size] = 0;
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
} else {
|
||||
auto data = *val;
|
||||
if (data) {
|
||||
data[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr Result<ArrayLength> MetalClawReaderTemplate<HandlerMaker>::arrayLength(const char*, bool pass) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
auto out = mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead).value;
|
||||
if (pass) {
|
||||
m_buffIt += bytesRead;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<typename I>
|
||||
Error MetalClawReader::readInteger(I *val) noexcept {
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::readInteger(I *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
std::size_t bytesRead = 0;
|
||||
@ -219,65 +484,9 @@ Error MetalClawReader::readInteger(I *val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
Error MetalClawReader::field(const char *name, T *val, std::size_t valLen) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
|
||||
// read the list
|
||||
if (valLen >= len) {
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
oxReturnError(reader.field("", &val[i]));
|
||||
}
|
||||
} else {
|
||||
oxTrace("ox::mc::read::field(T)") << name << ", size:" << valLen;
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error MetalClawReader::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
const auto keyLen = reader.stringLength(nullptr);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
auto wkeyPtr = wkey.get();
|
||||
oxReturnError(reader.fieldCString("", &wkeyPtr, static_cast<int>(keyLen + 1)));
|
||||
oxReturnError(reader.field("", &val->operator[](wkey.get())));
|
||||
}
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T, typename Handler>
|
||||
Error MetalClawReader::field(const char*, Handler handler) noexcept {
|
||||
template<auto HandlerMaker>
|
||||
template<typename T, typename CB>
|
||||
constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
@ -290,11 +499,12 @@ Error MetalClawReader::field(const char*, Handler handler) noexcept {
|
||||
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
T val;
|
||||
oxReturnError(reader.field("", &val));
|
||||
oxReturnError(handler(i, &val));
|
||||
oxReturnError(handler.field("", &val));
|
||||
oxReturnError(cb(i, &val));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -302,18 +512,70 @@ Error MetalClawReader::field(const char*, Handler handler) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr StringLength MetalClawReaderTemplate<HandlerMaker>::stringLength(const char*) noexcept {
|
||||
if ((m_unionIdx == -1 || 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>
|
||||
constexpr void MetalClawReader::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
m_fields = fields;
|
||||
m_buffIt = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
m_fieldPresence.setFields(fields);
|
||||
m_fieldPresence.setMaxLen(static_cast<int>(m_buffIt));
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr MetalClawReaderTemplate<HandlerMaker> MetalClawReaderTemplate<HandlerMaker>::child(const char*, int unionIdx) noexcept {
|
||||
return MetalClawReaderTemplate<HandlerMaker>(m_buff + m_buffIt, m_buffLen - m_buffIt, unionIdx, this);
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(const char*) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(m_field)).value;
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr bool MetalClawReaderTemplate<HandlerMaker>::fieldPresent(int fieldNo) const noexcept {
|
||||
return m_fieldPresence.get(static_cast<std::size_t>(fieldNo)).value;
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
[[nodiscard]]
|
||||
constexpr int MetalClawReaderTemplate<HandlerMaker>::whichFieldPresent(const char*, const ModelUnion &u) const noexcept {
|
||||
FieldBitmapReader<const uint8_t*> p(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
p.setFields(u.fieldCount());
|
||||
for (auto i = 0u; i < u.fieldCount(); ++i) {
|
||||
if (p.get(i)) {
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<auto HandlerMaker>
|
||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::nextField() noexcept {
|
||||
++m_field;
|
||||
}
|
||||
|
||||
using MetalClawReader = MetalClawReaderTemplate<[](auto r) {
|
||||
return ModelHandlerInterface{r};
|
||||
}>;
|
||||
|
||||
template<typename T>
|
||||
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept {
|
||||
MetalClawReader reader(reinterpret_cast<const uint8_t*>(buff), buffLen);
|
||||
return model(&reader, val);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
return model(&handler, val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
3
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
3
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
@ -10,6 +10,7 @@ target_link_libraries(
|
||||
|
||||
add_test("[ox/mc] McTest Writer" McTest MetalClawWriter)
|
||||
add_test("[ox/mc] McTest Reader" McTest MetalClawReader)
|
||||
add_test("[ox/mc] McTest MetalClawDef" McTest MetalClawDef)
|
||||
#add_test("[ox/mc] McTest MetalClawDef" McTest MetalClawDef)
|
||||
add_test("[ox/mc] McTest MetalClawModelValue" McTest MetalClawModelValue)
|
||||
add_test("[ox/mc] McTest encodeInteger" McTest encodeInteger)
|
||||
add_test("[ox/mc] McTest decodeInteger" McTest decodeInteger)
|
||||
|
106
deps/ox/src/ox/mc/test/tests.cpp
vendored
106
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
@ -19,7 +19,7 @@ union TestUnion {
|
||||
static constexpr auto TypeVersion = 1;
|
||||
bool Bool;
|
||||
uint32_t Int = 5;
|
||||
char CString[32];
|
||||
char *CString;
|
||||
};
|
||||
|
||||
struct TestStructNest {
|
||||
@ -43,6 +43,7 @@ struct TestStruct {
|
||||
int32_t Int6 = 0;
|
||||
int32_t Int7 = 0;
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String = "";
|
||||
ox::BString<32> BString = "";
|
||||
@ -50,14 +51,19 @@ struct TestStruct {
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
TestStructNest Struct;
|
||||
constexpr ~TestStruct() noexcept {
|
||||
if (unionIdx == 2) {
|
||||
ox::safeDelete(Union.CString);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestUnion *obj) noexcept {
|
||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
|
||||
io->template setTypeInfo<TestUnion>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
oxReturnError(io->field("CString", ox::SerStr(obj->CString)));
|
||||
oxReturnError(io->fieldCString("CString", &obj->CString));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
@ -68,7 +74,7 @@ oxModelBegin(TestStructNest)
|
||||
oxModelEnd()
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
||||
io->template setTypeInfo<TestStruct>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
@ -80,7 +86,12 @@ constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
oxReturnError(io->field("Int6", &obj->Int6));
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
|
||||
oxReturnError(io->field("unionIdx", &obj->unionIdx));
|
||||
if (ox_strcmp(io->opType(), ox::OpType::Reflect) == 0) {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0}));
|
||||
} else {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
||||
}
|
||||
oxReturnError(io->field("String", &obj->String));
|
||||
oxReturnError(io->field("BString", &obj->BString));
|
||||
oxReturnError(io->field("List", obj->List, 4));
|
||||
@ -165,14 +176,15 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
using ox::MaxValue;
|
||||
using ox::mc::McInt;
|
||||
using ox::mc::encodeInteger;
|
||||
static constexpr auto check = [](McInt val, ox::Vector<uint8_t, 9> &&expected) {
|
||||
static constexpr auto check = [](McInt val, const ox::Vector<uint8_t, 9> &expected) {
|
||||
if (val.length != expected.size()) {
|
||||
std::cout << "val.length: " << val.length << ", expected: " << expected.size() << '\n';
|
||||
return OxError(1);
|
||||
}
|
||||
for (std::size_t i = 0; i < expected.size(); i++) {
|
||||
if (expected[i] != val.data[i]) {
|
||||
std::cout << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
|
||||
std::cout << "decoded: " << static_cast<uint32_t>(val.data[i]) << ", expected: " << static_cast<uint32_t>(expected[i]) << '\n';
|
||||
std::cout << "decoded: " << i << ": " << static_cast<uint32_t>(val.data[i]) << '\n';
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
@ -195,6 +207,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
oxAssert(check(encodeInteger(int64_t(2)), {0b000'0010'0}), "Encode 2 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(3)), {0b000'0011'0}), "Encode 3 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(4)), {0b000'0100'0}), "Encode 4 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(64)), {0b00'0000'01, 0b1}), "Encode 64 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(128)), {0b00'0000'01, 0b10}), "Encode 128 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(129)), {0b00'0001'01, 0b10}), "Encode 129 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(130)), {0b00'0010'01, 0b10}), "Encode 130 fail");
|
||||
@ -204,6 +217,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
oxAssert(check(encodeInteger( int64_t(-2)), {0b111'1110'0}), "Encode -2 fail");
|
||||
oxAssert(check(encodeInteger( int64_t(-3)), {0b111'1101'0}), "Encode -3 fail");
|
||||
oxAssert(check(encodeInteger( int64_t(-4)), {0b111'1100'0}), "Encode -4 fail");
|
||||
oxAssert(check(encodeInteger( int64_t(-64)), {0b100'0000'0}), "Encode -64 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(-128)), {0b00'0000'01, 0b11'1111'10}), "Encode -128 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(-129)), {0b11'1111'01, 0b11'1111'01}), "Encode -129 fail");
|
||||
oxAssert(check(encodeInteger(int64_t(-130)), {0b11'1110'01, 0b11'1111'01}), "Encode -130 fail");
|
||||
@ -214,6 +228,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
oxAssert(check(encodeInteger(uint64_t(2)), {0b0100}), "Encode 2 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(3)), {0b0110}), "Encode 3 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(4)), {0b1000}), "Encode 4 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(64)), {0b1000'000'0}), "Encode 4 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(128)), {0b0001, 0b10}), "Encode 128 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(129)), {0b0101, 0b10}), "Encode 129 fail");
|
||||
oxAssert(check(encodeInteger(uint64_t(130)), {0b1001, 0b10}), "Encode 130 fail");
|
||||
@ -267,14 +282,13 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"MetalClawDef",
|
||||
"MetalClawModelValue",
|
||||
[] {
|
||||
//constexpr size_t descBuffLen = 1024;
|
||||
//uint8_t descBuff[descBuffLen];
|
||||
static constexpr size_t dataBuffLen = ox::units::MB;
|
||||
char dataBuff[dataBuffLen];
|
||||
TestStruct testIn, testOut;
|
||||
ox::Buffer dataBuff(dataBuffLen);
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.BString = "Test String 1";
|
||||
@ -285,18 +299,71 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.BString = "Test String 2";
|
||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), &testIn), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type.value, dataBuff, dataBuffLen,
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readMC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct["BString"].get<ox::String>() == testIn.Struct.BString.c_str(), "testOut.Struct.BString failed");
|
||||
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy["BString"].get<ox::String>() == testIn.Struct.BString.c_str(), "testOut.Struct.BString (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"MetalClawDef",
|
||||
[] {
|
||||
//constexpr size_t descBuffLen = 1024;
|
||||
//uint8_t descBuff[descBuffLen];
|
||||
static constexpr size_t dataBuffLen = ox::units::MB;
|
||||
char dataBuff[dataBuffLen];
|
||||
TestStruct testIn, testOut;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.BString = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.BString = "Test String 2";
|
||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type.value, dataBuff, dataBuffLen,
|
||||
[](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';
|
||||
auto fieldName = f.fieldName.c_str();
|
||||
switch (f.type->primitiveType) {
|
||||
case ox::PrimitiveType::UnsignedInteger:
|
||||
std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t";
|
||||
switch (f.type->length) {
|
||||
std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t";
|
||||
switch (f.type->length) {
|
||||
case 1: {
|
||||
uint8_t i = {};
|
||||
oxAssert(rdr->field(fieldName, &i), "Walking model failed.");
|
||||
@ -382,12 +449,11 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
int retval = -1;
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
retval = tests[testName]();
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
85
deps/ox/src/ox/mc/write.cpp
vendored
85
deps/ox/src/ox/mc/write.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
@ -15,87 +15,4 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff) {
|
||||
}
|
||||
|
||||
MetalClawWriter::~MetalClawWriter() noexcept {
|
||||
if (m_field != m_fields) {
|
||||
oxTrace("ox::mc::MetalClawWriter::error") << "MetalClawReader: incorrect fields number given";
|
||||
}
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, int8_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, int16_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, int32_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, int64_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
|
||||
Error MetalClawWriter::field(const char*, uint8_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, uint16_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, uint32_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, uint64_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, bool *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::field(const char*, SerStr val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val.len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto strLen = mc::encodeInteger(val.len());
|
||||
if (m_buffIt + strLen.length + static_cast<std::size_t>(val.len()) < m_buffLen) {
|
||||
ox_memcpy(&m_buff[m_buffIt], strLen.data, strLen.length);
|
||||
m_buffIt += strLen.length;
|
||||
// write the string
|
||||
ox_memcpy(&m_buff[m_buffIt], val.c_str(), static_cast<std::size_t>(val.len()));
|
||||
m_buffIt += static_cast<std::size_t>(val.len());
|
||||
fieldSet = true;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error MetalClawWriter::fieldCString(const char *name, char **val, int len) noexcept {
|
||||
return field(name, SerStr(val, len));
|
||||
}
|
||||
|
||||
std::size_t MetalClawWriter::size() const noexcept {
|
||||
return m_buffIt;
|
||||
}
|
||||
|
||||
}
|
||||
|
280
deps/ox/src/ox/mc/write.hpp
vendored
280
deps/ox/src/ox/mc/write.hpp
vendored
@ -3,12 +3,13 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
#include <ox/std/bit.hpp>
|
||||
@ -38,49 +39,73 @@ class MetalClawWriter {
|
||||
uint8_t *m_buff = nullptr;
|
||||
|
||||
public:
|
||||
MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx = -1) noexcept;
|
||||
constexpr MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx = -1) noexcept;
|
||||
|
||||
~MetalClawWriter() noexcept;
|
||||
constexpr ~MetalClawWriter() noexcept;
|
||||
|
||||
Error field(const char*, int8_t *val) noexcept;
|
||||
Error field(const char*, int16_t *val) noexcept;
|
||||
Error field(const char*, int32_t *val) noexcept;
|
||||
Error field(const char*, int64_t *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int64_t> auto *val) noexcept;
|
||||
|
||||
Error field(const char*, uint8_t *val) noexcept;
|
||||
Error field(const char*, uint16_t *val) noexcept;
|
||||
Error field(const char*, uint32_t *val) noexcept;
|
||||
Error field(const char*, uint64_t *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept;
|
||||
|
||||
Error field(const char*, bool *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<bool> auto *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
constexpr Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char*, BString<L> *val) noexcept;
|
||||
constexpr Error field(const char*, const BString<L> *val) noexcept;
|
||||
|
||||
Error field(const char*, SerStr val) noexcept;
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val), buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val));
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char*>(val), buffLen);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val) noexcept;
|
||||
constexpr Error field(const char*, T *val) noexcept;
|
||||
|
||||
template<typename U>
|
||||
Error field(const char*, UnionView<U> val) noexcept;
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t size() const noexcept;
|
||||
constexpr std::size_t size() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
@ -88,13 +113,81 @@ class MetalClawWriter {
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename I>
|
||||
Error appendInteger(I val) noexcept;
|
||||
constexpr Error appendInteger(Integer_c auto val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
auto mi = mc::encodeInteger(val);
|
||||
if (mi.length < m_buffLen) {
|
||||
fieldSet = true;
|
||||
ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length);
|
||||
m_buffIt += mi.length;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
m_field++;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff) {
|
||||
}
|
||||
|
||||
constexpr MetalClawWriter::~MetalClawWriter() noexcept {
|
||||
if (m_field != m_fields) {
|
||||
oxTrace("ox::mc::MetalClawWriter::error") << "MetalClawReader: incorrect fields number given";
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error MetalClawWriter::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
constexpr Error MetalClawWriter::field(const char*, const BasicString<SmallStringSize> *val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
@ -116,19 +209,77 @@ Error MetalClawWriter::field(const char*, BasicString<SmallStringSize> *val) noe
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error MetalClawWriter::field(const char *name, BString<L> *val) noexcept {
|
||||
return field(name, SerStr(val->data(), val->cap()));
|
||||
constexpr Error MetalClawWriter::field(const char *name, const BString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error MetalClawWriter::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
|
||||
return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error MetalClawWriter::field(const char *name, BString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::fieldCString(const char*, const char **val, std::size_t) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
const auto strLen = *val ? ox_strlen(*val) : 0;
|
||||
// write the length
|
||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) {
|
||||
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
|
||||
m_buffIt += strLenBuff.length;
|
||||
// write the string
|
||||
ox_memcpy(&m_buff[m_buffIt], *val, static_cast<std::size_t>(strLen));
|
||||
m_buffIt += static_cast<std::size_t>(strLen);
|
||||
fieldSet = true;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::fieldCString(const char *name, const char **val) noexcept {
|
||||
return fieldCString(name, val, {});
|
||||
}
|
||||
|
||||
constexpr Error MetalClawWriter::fieldCString(const char*, const char *val, std::size_t strLen) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (strLen && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto strLenBuff = mc::encodeInteger(strLen);
|
||||
if (m_buffIt + strLenBuff.length + static_cast<std::size_t>(strLen) < m_buffLen) {
|
||||
ox_memcpy(&m_buff[m_buffIt], strLenBuff.data, strLenBuff.length);
|
||||
m_buffIt += strLenBuff.length;
|
||||
// write the string
|
||||
ox_memcpy(&m_buff[m_buffIt], val, static_cast<std::size_t>(strLen));
|
||||
m_buffIt += static_cast<std::size_t>(strLen);
|
||||
fieldSet = true;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error MetalClawWriter::field(const char*, T *val) noexcept {
|
||||
constexpr Error MetalClawWriter::field(const char*, T *val) noexcept {
|
||||
if constexpr(isVector_v<T>) {
|
||||
return field(nullptr, val->data(), val->size());
|
||||
} else {
|
||||
bool fieldSet = false;
|
||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
oxReturnError(model(&writer, val));
|
||||
ModelHandlerInterface handler{&writer};
|
||||
oxReturnError(model(&handler, val));
|
||||
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
|
||||
m_buffIt += writer.m_buffIt;
|
||||
fieldSet = true;
|
||||
@ -140,12 +291,13 @@ Error MetalClawWriter::field(const char*, T *val) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Error MetalClawWriter::field(const char*, UnionView<U> val) noexcept {
|
||||
template<typename U, bool force>
|
||||
constexpr Error MetalClawWriter::field(const char*, UnionView<U, force> val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val.get() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt, val.idx());
|
||||
oxReturnError(model(&writer, val.get()));
|
||||
ModelHandlerInterface handler{&writer};
|
||||
oxReturnError(model(&handler, val.get()));
|
||||
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
|
||||
m_buffIt += writer.m_buffIt;
|
||||
fieldSet = true;
|
||||
@ -157,7 +309,7 @@ Error MetalClawWriter::field(const char*, UnionView<U> val) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept {
|
||||
constexpr Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept {
|
||||
bool fieldSet = false;
|
||||
|
||||
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
@ -171,11 +323,12 @@ Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept {
|
||||
}
|
||||
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
writer.setTypeInfo<T>("List", 0, len);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
handler.setTypeInfo<T>("List", 0, len);
|
||||
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
oxReturnError(writer.field("", &val[i]));
|
||||
oxReturnError(handler.field("", &val[i]));
|
||||
}
|
||||
|
||||
m_buffIt += writer.m_buffIt;
|
||||
@ -188,11 +341,10 @@ Error MetalClawWriter::field(const char*, T *val, std::size_t len) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error MetalClawWriter::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *val) noexcept {
|
||||
const auto &keys = val->keys();
|
||||
const auto len = keys.size();
|
||||
bool fieldSet = false;
|
||||
|
||||
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto arrLen = mc::encodeInteger(len);
|
||||
@ -202,69 +354,57 @@ Error MetalClawWriter::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
// double len for both key and value
|
||||
writer.setTypeInfo("Map", 0, len * 2);
|
||||
|
||||
handler.setTypeInfo("Map", 0, len * 2);
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
const auto &key = keys[i];
|
||||
const auto keyLen = ox_strlen(key);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
memcpy(wkey, key.c_str(), keyLen + 1);
|
||||
oxReturnError(writer.field("", SerStr(wkey.get(), keyLen)));
|
||||
oxReturnError(writer.field("", &(*val)[key]));
|
||||
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
|
||||
oxReturnError(handler.field("", val->at(key).value));
|
||||
}
|
||||
|
||||
m_buffIt += writer.m_buffIt;
|
||||
fieldSet = true;
|
||||
}
|
||||
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
m_field++;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
Error MetalClawWriter::appendInteger(I val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
auto mi = mc::encodeInteger(val);
|
||||
if (mi.length < m_buffLen) {
|
||||
fieldSet = true;
|
||||
ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length);
|
||||
m_buffIt += mi.length;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
m_field++;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWriter::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
constexpr Error MetalClawWriter::field(const char *name, HashMap<String, T> *val) noexcept {
|
||||
return field(name, const_cast<const HashMap<String, T>*>(val));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void MetalClawWriter::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
m_fields = fields;
|
||||
m_fieldPresence.setFields(fields);
|
||||
m_buffIt = static_cast<std::size_t>(m_fieldPresence.getMaxLen());
|
||||
ox_memset(m_buff, 0, m_buffIt);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<Buffer> writeMC(T *val) noexcept {
|
||||
constexpr std::size_t MetalClawWriter::size() const noexcept {
|
||||
return m_buffIt;
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(auto *val) noexcept {
|
||||
Buffer buff(10 * units::MB);
|
||||
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff.data()), buff.size());
|
||||
oxReturnError(model(&writer, val));
|
||||
ModelHandlerInterface handler{&writer};
|
||||
oxReturnError(model(&handler, val));
|
||||
buff.resize(writer.size());
|
||||
return buff;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error writeMC(char *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
Error writeMC(char *buff, std::size_t buffLen, auto *val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
MetalClawWriter writer(reinterpret_cast<uint8_t*>(buff), buffLen);
|
||||
auto err = model(&writer, val);
|
||||
ModelHandlerInterface handler(&writer);
|
||||
auto err = model(&handler, val);
|
||||
if (sizeOut) {
|
||||
*sizeOut = writer.size();
|
||||
}
|
||||
|
2
deps/ox/src/ox/model/CMakeLists.txt
vendored
2
deps/ox/src/ox/model/CMakeLists.txt
vendored
@ -27,7 +27,9 @@ install(
|
||||
optype.hpp
|
||||
metadata.hpp
|
||||
model.hpp
|
||||
modelhandleradaptor.hpp
|
||||
modelops.hpp
|
||||
modelvalue.hpp
|
||||
typenamecatcher.hpp
|
||||
types.hpp
|
||||
typestore.hpp
|
||||
|
8
deps/ox/src/ox/model/def.hpp
vendored
8
deps/ox/src/ox/model/def.hpp
vendored
@ -3,13 +3,15 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, modelName *o) noexcept { io->template setTypeInfo<modelName>();
|
||||
#include <ox/std/concepts.hpp>
|
||||
|
||||
#define oxModelBegin(modelName) constexpr ox::Error model(auto *io, ox::CommonPtrWith<modelName> auto *o) noexcept { io->template setTypeInfo<modelName>();
|
||||
#define oxModelEnd() return OxError(0); }
|
||||
#define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName));
|
||||
#define oxModelFieldRename(serFieldName, objFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName));
|
||||
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, modelName*) noexcept
|
||||
#define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith<modelName> auto*) noexcept
|
||||
|
21
deps/ox/src/ox/model/desctypes.hpp
vendored
21
deps/ox/src/ox/model/desctypes.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -13,8 +13,11 @@
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "optype.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
@ -42,15 +45,16 @@ struct DescriptorField {
|
||||
String fieldName;
|
||||
int subscriptLevels = 0;
|
||||
String typeName; // gives reference to type for lookup if type is null
|
||||
bool list = false;
|
||||
|
||||
constexpr DescriptorField() noexcept = default;
|
||||
|
||||
constexpr DescriptorField(const DescriptorType *pType, String pFieldName,
|
||||
int pSubscriptLevels, String pTypeName) noexcept:
|
||||
type(pType),
|
||||
fieldName(pFieldName),
|
||||
fieldName(std::move(pFieldName)),
|
||||
subscriptLevels(pSubscriptLevels),
|
||||
typeName(pTypeName) {
|
||||
typeName(std::move(pTypeName)) {
|
||||
}
|
||||
|
||||
constexpr DescriptorField(const DescriptorField &other) noexcept:
|
||||
@ -96,7 +100,8 @@ struct DescriptorType {
|
||||
|
||||
constexpr DescriptorType() noexcept = default;
|
||||
|
||||
constexpr explicit DescriptorType(String tn) noexcept: typeName(std::move(tn)) {
|
||||
constexpr explicit DescriptorType(String tn, int typeVersion) noexcept:
|
||||
typeName(std::move(tn)), typeVersion(typeVersion) {
|
||||
}
|
||||
|
||||
constexpr DescriptorType(String tn, PrimitiveType t, int b) noexcept:
|
||||
@ -115,11 +120,11 @@ struct DescriptorType {
|
||||
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, DescriptorType *type) noexcept {
|
||||
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
|
||||
io->template setTypeInfo<DescriptorType>();
|
||||
oxReturnError(io->field("typeName", &type->typeName));
|
||||
oxReturnError(io->field("typeVersion", &type->typeVersion));
|
||||
if constexpr(ox_strcmp(T::opType(), "Reflect") == 0) {
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
uint8_t pt = 0;
|
||||
oxReturnError(io->field("primitiveType", &pt));
|
||||
} else {
|
||||
@ -134,7 +139,7 @@ constexpr Error model(T *io, DescriptorType *type) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, DescriptorField *field) noexcept {
|
||||
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
|
||||
io->template setTypeInfo<DescriptorField>();
|
||||
oxReturnError(io->field("typeName", &field->typeName));
|
||||
oxReturnError(io->field("fieldName", &field->fieldName));
|
||||
@ -149,7 +154,7 @@ template<typename ReaderBase>
|
||||
class TypeDescReader;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(TypeDescReader<T> *io, DescriptorField *field) noexcept {
|
||||
constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
|
||||
io->template setTypeInfo<DescriptorField>(DescriptorField::TypeName, DescriptorField::TypeVersion, 4);
|
||||
oxReturnError(io->field("typeName", &field->typeName));
|
||||
auto &typeStore = io->typeStore();
|
||||
|
110
deps/ox/src/ox/model/descwrite.cpp
vendored
110
deps/ox/src/ox/model/descwrite.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/typeinfo.hpp>
|
||||
@ -33,115 +33,19 @@ static_assert(!preloadable<non_preloadable_type2>::value);
|
||||
|
||||
|
||||
static_assert([] {
|
||||
int i = 0;
|
||||
return detail::indirectionLevels(i) == 0;
|
||||
return detail::indirectionLevels_v<int> == 0;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int)");
|
||||
|
||||
static_assert([] {
|
||||
int i = 0;
|
||||
return detail::indirectionLevels(&i) == 1;
|
||||
return detail::indirectionLevels_v<int*> == 1;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int*)");
|
||||
|
||||
static_assert([] {
|
||||
int i[2] = {};
|
||||
return detail::indirectionLevels(i) == 1;
|
||||
return detail::indirectionLevels_v<int[2]> == 1;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int[])");
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(int8_t*) noexcept {
|
||||
constexpr auto String = "B:int8_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(int16_t*) noexcept {
|
||||
constexpr auto String = "B:int16_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(int32_t*) noexcept {
|
||||
constexpr auto String = "B:int32_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(int64_t*) noexcept {
|
||||
constexpr auto String = "B:int64_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(uint8_t*) noexcept {
|
||||
constexpr auto String = "B:uint8_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(uint16_t*) noexcept {
|
||||
constexpr auto String = "B:uint16_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(uint32_t*) noexcept {
|
||||
constexpr auto String = "B:uint32_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(uint64_t*) noexcept {
|
||||
constexpr auto String = "B:uint64_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(char*) noexcept {
|
||||
constexpr auto String = "B:string";
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(String, PT, 0);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(SerStr) noexcept {
|
||||
constexpr auto String = "B:string";
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(String, PT, 0);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(String*) noexcept {
|
||||
constexpr auto String = "B:string";
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(String, PT, 0);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::type(bool*) noexcept {
|
||||
constexpr auto String = "B:bool";
|
||||
constexpr auto PT = PrimitiveType::Bool;
|
||||
constexpr auto Bytes = 0;
|
||||
return getType(String, PT, Bytes);
|
||||
}
|
||||
|
||||
const DescriptorType *TypeDescWriter::getType(const String &tn, PrimitiveType pt, int b) noexcept {
|
||||
auto t = m_typeStore->get(tn);
|
||||
if (!t.error) {
|
||||
auto type = t.value;
|
||||
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
||||
return type;
|
||||
} else {
|
||||
auto dt = ox::make_unique<DescriptorType>(tn);
|
||||
dt->primitiveType = pt;
|
||||
dt->length = b;
|
||||
const auto out = dt.get();
|
||||
m_typeStore->set(tn, std::move(dt));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
static_assert([] {
|
||||
return detail::indirectionLevels_v<int**> == 2;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int[])");
|
||||
|
||||
}
|
||||
|
261
deps/ox/src/ox/model/descwrite.hpp
vendored
261
deps/ox/src/ox/model/descwrite.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -19,6 +19,7 @@
|
||||
#include "desctypes.hpp"
|
||||
#include "fieldcounter.hpp"
|
||||
#include "metadata.hpp"
|
||||
#include "modelhandleradaptor.hpp"
|
||||
#include "optype.hpp"
|
||||
#include "typenamecatcher.hpp"
|
||||
#include "types.hpp"
|
||||
@ -29,14 +30,13 @@ namespace ox {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
static constexpr int indirectionLevels(T) noexcept {
|
||||
return 0;
|
||||
}
|
||||
constexpr int indirectionLevels_v = 0;
|
||||
|
||||
template<typename T>
|
||||
static constexpr int indirectionLevels(T *t) noexcept {
|
||||
return 1 + indirectionLevels(*t);
|
||||
}
|
||||
constexpr int indirectionLevels_v<T*> = 1 + indirectionLevels_v<T>;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr int indirectionLevels_v<T[sz]> = 1 + indirectionLevels_v<T>;
|
||||
|
||||
}
|
||||
|
||||
@ -49,17 +49,24 @@ class TypeDescWriter {
|
||||
public:
|
||||
explicit constexpr TypeDescWriter(TypeStore *typeStore = nullptr) noexcept;
|
||||
|
||||
constexpr ~TypeDescWriter() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName,
|
||||
int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T *val, std::size_t valLen) noexcept;
|
||||
constexpr Error field(const char *name, const T *val, std::size_t valLen) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T *val) noexcept;
|
||||
constexpr Error field(const char *name, const T *val) noexcept;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(const char *name, Args&&...) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr DescriptorType *definition() noexcept {
|
||||
@ -71,56 +78,79 @@ class TypeDescWriter {
|
||||
}
|
||||
|
||||
private:
|
||||
const DescriptorType *type(int8_t *val) noexcept;
|
||||
const DescriptorType *type(int16_t *val) noexcept;
|
||||
const DescriptorType *type(int32_t *val) noexcept;
|
||||
const DescriptorType *type(int64_t *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int8_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int16_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int32_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int64_t *val) const noexcept;
|
||||
|
||||
const DescriptorType *type(uint8_t *val) noexcept;
|
||||
const DescriptorType *type(uint16_t *val) noexcept;
|
||||
const DescriptorType *type(uint32_t *val) noexcept;
|
||||
const DescriptorType *type(uint64_t *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint8_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint16_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint32_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint64_t *val) const noexcept;
|
||||
|
||||
const DescriptorType *type(bool *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const bool *val) const noexcept;
|
||||
|
||||
const DescriptorType *type(char *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const char *val) const noexcept;
|
||||
|
||||
const DescriptorType *type(SerStr val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(SerStr val) const noexcept;
|
||||
|
||||
const DescriptorType *type(String *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const String *val) const noexcept;
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr const DescriptorType *type(BString<sz> *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const BString<sz> *val) const noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *type(T *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const T *val) const noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *type(Vector<T> *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *type(HashMap<String, T> *val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const HashMap<String, T> *val) const noexcept;
|
||||
|
||||
template<typename U>
|
||||
constexpr const DescriptorType *type(UnionView<U> val) noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(UnionView<U> val) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *getType(const String &tn, int typeVersion, PrimitiveType t, int b) const noexcept;
|
||||
|
||||
const DescriptorType *getType(const String &tn, PrimitiveType t, int b) noexcept;
|
||||
};
|
||||
|
||||
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void TypeDescWriter::setTypeInfo(const char *typeName, int typeVersion, int) noexcept {
|
||||
m_type = m_typeStore->getInit(typeName, typeVersion);
|
||||
if constexpr(is_union_v<T>) {
|
||||
m_type->primitiveType = PrimitiveType::Union;
|
||||
} else {
|
||||
m_type->primitiveType = PrimitiveType::Struct;
|
||||
}
|
||||
m_type->preloadable = detail::preloadable<T>::value;
|
||||
}
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
constexpr Error TypeDescWriter::field(const char *name, T *val, std::size_t) noexcept {
|
||||
constexpr Error TypeDescWriter::field(const char *name, const T *val, std::size_t) noexcept {
|
||||
if (m_type) {
|
||||
constexpr typename remove_pointer<decltype(val)>::type *p = nullptr;
|
||||
const auto t = type(p);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
|
||||
if (t == nullptr) {
|
||||
type(p);
|
||||
}
|
||||
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels(val), t->typeName);
|
||||
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, t->typeName);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
@ -138,70 +168,153 @@ constexpr Error TypeDescWriter::field(const char *name, T val) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error TypeDescWriter::field(const char *name, T *val) noexcept {
|
||||
constexpr Error TypeDescWriter::field(const char *name, const T *val) noexcept {
|
||||
if (m_type) {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, t->typeName);
|
||||
return OxError(0);
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(name, val->data(), val->size());
|
||||
} else {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, t->typeName);
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(BString<sz> *val) noexcept {
|
||||
return type(SerStr(val));
|
||||
template<typename ...Args>
|
||||
constexpr Error TypeDescWriter::fieldCString(const char *name, Args&&...) noexcept {
|
||||
String s;
|
||||
return field(name, &s);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(T *val) noexcept {
|
||||
auto [t, err] = m_typeStore->template get<T>();
|
||||
if (!err) {
|
||||
return t;
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const T *val) const noexcept {
|
||||
if constexpr(isVector_v<T>) {
|
||||
return type(val->data());
|
||||
} else {
|
||||
TypeDescWriter dw(m_typeStore);
|
||||
oxLogError(model(&dw, val));
|
||||
return dw.m_type;
|
||||
auto [t, err] = m_typeStore->template get<T>();
|
||||
if (!err) {
|
||||
return t;
|
||||
} else {
|
||||
TypeDescWriter dw(m_typeStore);
|
||||
const auto reflectErr = model(&dw, val);
|
||||
oxLogError(reflectErr);
|
||||
oxAssert(reflectErr, "field(const char *name, T val): Type info could not be generated");
|
||||
return dw.m_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(Vector<T> *val) noexcept {
|
||||
return type(val->data());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(HashMap<String, T>*) noexcept {
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const HashMap<String, T>*) const noexcept {
|
||||
return type(static_cast<T*>(nullptr));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(UnionView<U> val) noexcept {
|
||||
return type(val.get());
|
||||
constexpr const DescriptorType *TypeDescWriter::type(UnionView<U> val) const noexcept {
|
||||
const auto t = type(val.get());
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void TypeDescWriter::setTypeInfo(const char *name, int) noexcept {
|
||||
m_type = m_typeStore->getInit(name);
|
||||
if constexpr(is_union_v<T>) {
|
||||
m_type->primitiveType = PrimitiveType::Union;
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int8_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(types::Int8, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int16_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(types::Int16, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int32_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(types::Int32, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int64_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(types::Int64, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint8_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(types::Uint8, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint16_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(types::Uint16, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint32_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(types::Uint32, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint64_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(types::Uint64, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const bool*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::Bool;
|
||||
constexpr auto Bytes = 0;
|
||||
return getType(types::Bool, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const char*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(SerStr) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const String*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const BString<sz>*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::getType(const String &tn, int typeVersion, PrimitiveType pt, int b) const noexcept {
|
||||
auto t = m_typeStore->get(tn, typeVersion);
|
||||
if (!t.error) {
|
||||
auto type = t.value;
|
||||
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
||||
return type;
|
||||
} else {
|
||||
m_type->primitiveType = PrimitiveType::Struct;
|
||||
auto dt = ox::make_unique<DescriptorType>(tn, typeVersion);
|
||||
dt->primitiveType = pt;
|
||||
dt->length = b;
|
||||
const auto out = dt.get();
|
||||
m_typeStore->set(tn, typeVersion, std::move(dt));
|
||||
return out;
|
||||
}
|
||||
m_type->preloadable = detail::preloadable<T>::value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
|
||||
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
|
||||
TypeDescWriter writer(typeStore);
|
||||
oxReturnError(model(&writer, val));
|
||||
ModelHandlerInterface handler(&writer);
|
||||
oxReturnError(model(&handler, val));
|
||||
return writer.definition();
|
||||
}
|
||||
|
||||
auto writeTypeDefOC(auto *val) noexcept {
|
||||
TypeStore typeStore;
|
||||
oxRequire(def, buildTypeDef(&typeStore, val));
|
||||
return writeOC(def.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
7
deps/ox/src/ox/model/fieldcounter.hpp
vendored
7
deps/ox/src/ox/model/fieldcounter.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -44,6 +44,11 @@ class FieldCounter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(Args&&...) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
static constexpr auto opType() {
|
||||
return OpType::Reflect;
|
||||
}
|
||||
|
4
deps/ox/src/ox/model/model.hpp
vendored
4
deps/ox/src/ox/model/model.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -13,7 +13,9 @@
|
||||
#include "desctypes.hpp"
|
||||
#include "descwrite.hpp"
|
||||
#include "fieldcounter.hpp"
|
||||
#include "modelhandleradaptor.hpp"
|
||||
#include "modelops.hpp"
|
||||
#include "modelvalue.hpp"
|
||||
#include "typenamecatcher.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typestore.hpp"
|
||||
|
155
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
Normal file
155
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/utility.hpp>
|
||||
|
||||
#include "modelvalue.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename Handler>
|
||||
class ModelHandlerInterface {
|
||||
private:
|
||||
Handler *m_handler = nullptr;
|
||||
|
||||
public:
|
||||
constexpr explicit ModelHandlerInterface(Handler *handler) noexcept: m_handler(handler) {
|
||||
}
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept {
|
||||
m_handler->setTypeInfo(name, version, fields);
|
||||
}
|
||||
|
||||
template<std::size_t len>
|
||||
constexpr Error fieldCString(const char *name, char val[len]) noexcept {
|
||||
return m_handler->fieldCString(name, &val[0], len);
|
||||
}
|
||||
|
||||
template<std::size_t len>
|
||||
constexpr Error fieldCString(const char *name, const char val[len]) noexcept {
|
||||
return m_handler->fieldCString(name, &val[0], len);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
||||
return m_handler->fieldCString(name, val);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept {
|
||||
return m_handler->fieldCString(name, val);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val, std::size_t buffLen) noexcept {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept {
|
||||
switch (v->type()) {
|
||||
case ModelValue::Type::Undefined:
|
||||
break;
|
||||
case ModelValue::Type::Bool:
|
||||
return m_handler->field(name, &v->template get<bool>());
|
||||
case ModelValue::Type::UnsignedInteger8:
|
||||
return m_handler->field(name, &v->template get<uint8_t>());
|
||||
case ModelValue::Type::UnsignedInteger16:
|
||||
return m_handler->field(name, &v->template get<uint16_t>());
|
||||
case ModelValue::Type::UnsignedInteger32:
|
||||
return m_handler->field(name, &v->template get<uint32_t>());
|
||||
case ModelValue::Type::UnsignedInteger64:
|
||||
return m_handler->field(name, &v->template get<uint64_t>());
|
||||
case ModelValue::Type::SignedInteger8:
|
||||
return m_handler->field(name, &v->template get<int8_t>());
|
||||
case ModelValue::Type::SignedInteger16:
|
||||
return m_handler->field(name, &v->template get<int16_t>());
|
||||
case ModelValue::Type::SignedInteger32:
|
||||
return m_handler->field(name, &v->template get<int32_t>());
|
||||
case ModelValue::Type::SignedInteger64:
|
||||
return m_handler->field(name, &v->template get<int64_t>());
|
||||
case ModelValue::Type::String:
|
||||
return m_handler->field(name, &v->template get<String>());
|
||||
case ModelValue::Type::Object:
|
||||
return m_handler->field(name, &v->template get<ModelObject>());
|
||||
case ModelValue::Type::Union:
|
||||
{
|
||||
auto &u = v->template get<ModelUnion>();
|
||||
if constexpr(ox_strcmp(Handler::opType(), OpType::Read) == 0) {
|
||||
u.setActiveField(m_handler->whichFieldPresent(name, u));
|
||||
}
|
||||
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
|
||||
}
|
||||
case ModelValue::Type::Vector:
|
||||
return m_handler->field(name, &v->template get<ModelValueVector>());
|
||||
}
|
||||
oxPanic(OxError(1), "invalid type");
|
||||
return OxError(1, "invalid type");
|
||||
}
|
||||
|
||||
// array handler, with callback to allow handling individual elements
|
||||
template<typename T, typename Callback>
|
||||
constexpr Error field(const char *name, Callback cb) noexcept {
|
||||
return m_handler->template field<T, Callback>(name, cb);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, const auto *v) noexcept {
|
||||
return m_handler->field(name, v);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, auto *v) noexcept {
|
||||
return m_handler->field(name, v);
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char *name, UnionView<U, force> val) noexcept {
|
||||
return m_handler->field(name, val);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, auto *val, std::size_t len) noexcept {
|
||||
return m_handler->field(name, val, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto arrayLength(const char *name, bool pass = true) noexcept {
|
||||
return m_handler->arrayLength(name, pass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an string length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto stringLength(const char *name) noexcept {
|
||||
return m_handler->stringLength(name);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return Handler::opType();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto handler() noexcept {
|
||||
return m_handler;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
86
deps/ox/src/ox/model/modelops.hpp
vendored
86
deps/ox/src/ox/model/modelops.hpp
vendored
@ -14,12 +14,36 @@
|
||||
#include <ox/std/utility.hpp>
|
||||
|
||||
#include "fieldcounter.hpp"
|
||||
#include "modelvalue.hpp"
|
||||
#include "optype.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class Wrap {
|
||||
public:
|
||||
virtual ~Wrap() = default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class WrapT: public Wrap {
|
||||
private:
|
||||
T *m_obj = nullptr;
|
||||
|
||||
public:
|
||||
constexpr WrapT(T *obj) noexcept: m_obj(obj) {
|
||||
}
|
||||
constexpr WrapT() = default;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto obj() noexcept {
|
||||
return m_obj;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<std::size_t size>
|
||||
class MemberList {
|
||||
|
||||
@ -27,7 +51,7 @@ class MemberList {
|
||||
std::size_t m_i = 0;
|
||||
|
||||
public:
|
||||
void *vars[size];
|
||||
Array<void*, size> vars;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *v) noexcept {
|
||||
@ -41,8 +65,8 @@ class MemberList {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(u.get());
|
||||
return OxError(0);
|
||||
}
|
||||
@ -57,7 +81,7 @@ class MemberList {
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "GetMembers";
|
||||
return OpType::Reflect;
|
||||
}
|
||||
|
||||
};
|
||||
@ -97,8 +121,8 @@ class Copier {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) {
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> u) {
|
||||
auto &dst = *cbit_cast<U*>(m_dst->vars[m_i]);
|
||||
auto &src = *u.get();
|
||||
dst = src;
|
||||
@ -116,7 +140,7 @@ class Copier {
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "Copy";
|
||||
return OpType::Read;
|
||||
}
|
||||
|
||||
};
|
||||
@ -158,8 +182,8 @@ class Mover {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
|
||||
auto &dst = *cbit_cast<U*>(m_dst->vars[m_i]);
|
||||
auto &src = *u.get();
|
||||
dst = std::move(src);
|
||||
@ -177,7 +201,7 @@ class Mover {
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "Copy";
|
||||
return OpType::Read;
|
||||
}
|
||||
|
||||
};
|
||||
@ -222,8 +246,8 @@ class Equals {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> u) noexcept {
|
||||
const auto &dst = *cbit_cast<U*>(m_other->vars[m_i]);
|
||||
const auto &src = *u.get();
|
||||
++m_i;
|
||||
@ -253,13 +277,31 @@ class Equals {
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "Copy";
|
||||
return OpType::Read;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void moveModel(ModelObject *dst, T *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Mover<size> mover(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&mover, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void moveModel(T *dst, ModelObject *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Mover<size> mover(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&mover, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void moveModel(T *dst, T *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
@ -269,6 +311,24 @@ constexpr void moveModel(T *dst, T *src) noexcept {
|
||||
oxIgnoreError(model(&mover, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void copyModel(ModelObject *dst, const T *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Copier<size> copier(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&copier, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void copyModel(T *dst, const ModelObject *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Copier<size> copier(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&copier, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void copyModel(T *dst, const T *src) noexcept {
|
||||
constexpr auto size = ModelFieldCount_v<T>;
|
||||
|
9
deps/ox/src/ox/model/modelvalue.cpp
vendored
Normal file
9
deps/ox/src/ox/model/modelvalue.cpp
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "modelvalue.hpp"
|
886
deps/ox/src/ox/model/modelvalue.hpp
vendored
Normal file
886
deps/ox/src/ox/model/modelvalue.hpp
vendored
Normal file
@ -0,0 +1,886 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include "def.hpp"
|
||||
#include "desctypes.hpp"
|
||||
#include "fieldcounter.hpp"
|
||||
#include "metadata.hpp"
|
||||
#include "optype.hpp"
|
||||
#include "typenamecatcher.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typestore.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
class ModelObject;
|
||||
class ModelUnion;
|
||||
class ModelValue;
|
||||
class ModelValueVector;
|
||||
|
||||
class ModelValue {
|
||||
public:
|
||||
enum class Type {
|
||||
Undefined,
|
||||
Bool,
|
||||
UnsignedInteger8,
|
||||
UnsignedInteger16,
|
||||
UnsignedInteger32,
|
||||
UnsignedInteger64,
|
||||
SignedInteger8,
|
||||
SignedInteger16,
|
||||
SignedInteger32,
|
||||
SignedInteger64,
|
||||
String,
|
||||
Object,
|
||||
Union,
|
||||
Vector,
|
||||
};
|
||||
|
||||
private:
|
||||
Type m_type = Type::Undefined;
|
||||
union {
|
||||
bool b{};
|
||||
int8_t i8;
|
||||
uint8_t ui8;
|
||||
int16_t i16;
|
||||
uint16_t ui16;
|
||||
int32_t i32;
|
||||
uint32_t ui32;
|
||||
int64_t i64;
|
||||
uint64_t ui64;
|
||||
String *str;
|
||||
ModelObject *obj;
|
||||
ModelUnion *uni;
|
||||
ModelValueVector *vec;
|
||||
} m_data;
|
||||
|
||||
template<typename T>
|
||||
consteval static Type getType() noexcept {
|
||||
if constexpr(is_bool_v<T>) {
|
||||
return Type::Bool;
|
||||
} else if constexpr(is_integer_v<T>) {
|
||||
if (!is_signed_v<T> && sizeof(T) == 1) {
|
||||
return Type::UnsignedInteger8;
|
||||
} else if constexpr(!is_signed_v<T> && sizeof(T) == 2) {
|
||||
return Type::UnsignedInteger16;
|
||||
} else if constexpr(!is_signed_v<T> && sizeof(T) == 4) {
|
||||
return Type::UnsignedInteger32;
|
||||
} else if constexpr(!is_signed_v<T> && sizeof(T) == 8) {
|
||||
return Type::UnsignedInteger64;
|
||||
} else if constexpr(is_signed_v<T> && sizeof(T) == 1) {
|
||||
return Type::SignedInteger8;
|
||||
} else if constexpr(is_signed_v<T> && sizeof(T) == 2) {
|
||||
return Type::SignedInteger16;
|
||||
} else if constexpr(is_signed_v<T> && sizeof(T) == 4) {
|
||||
return Type::SignedInteger32;
|
||||
} else if constexpr(is_signed_v<T> && sizeof(T) == 8) {
|
||||
return Type::SignedInteger64;
|
||||
}
|
||||
} else if constexpr(is_same_v<T, ModelUnion>) {
|
||||
return Type::Union;
|
||||
} else if constexpr(is_same_v<T, ModelObject>) {
|
||||
return Type::Object;
|
||||
} else if constexpr(is_same_v<T, String>) {
|
||||
return Type::String;
|
||||
} else if constexpr(is_same_v<T, ModelValueVector>) {
|
||||
return Type::Vector;
|
||||
} else {
|
||||
return Type::Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
template<Type type>
|
||||
static constexpr auto &getValue(auto &t) noexcept {
|
||||
if constexpr(type == Type::Bool) {
|
||||
return t.m_data.b;
|
||||
} else if constexpr(type == Type::UnsignedInteger8) {
|
||||
return t.m_data.ui8;
|
||||
} else if constexpr(type == Type::UnsignedInteger16) {
|
||||
return t.m_data.ui16;
|
||||
} else if constexpr(type == Type::UnsignedInteger32) {
|
||||
return t.m_data.ui32;
|
||||
} else if constexpr(type == Type::UnsignedInteger64) {
|
||||
return t.m_data.ui64;
|
||||
} else if constexpr(type == Type::SignedInteger8) {
|
||||
return t.m_data.i8;
|
||||
} else if constexpr(type == Type::SignedInteger16) {
|
||||
return t.m_data.i16;
|
||||
} else if constexpr(type == Type::SignedInteger32) {
|
||||
return t.m_data.i32;
|
||||
} else if constexpr(type == Type::SignedInteger64) {
|
||||
return t.m_data.i64;
|
||||
} else if constexpr(type == Type::String) {
|
||||
return *t.m_data.str;
|
||||
} else if constexpr(type == Type::Union) {
|
||||
return *t.m_data.uni;
|
||||
} else if constexpr(type == Type::Object) {
|
||||
return *t.m_data.obj;
|
||||
} else if constexpr(type == Type::Vector) {
|
||||
return *t.m_data.vec;
|
||||
} else {
|
||||
return t.m_data.i32;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr ModelValue() noexcept = default;
|
||||
|
||||
constexpr ModelValue(const ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &&other) noexcept;
|
||||
|
||||
template<typename T>
|
||||
explicit constexpr ModelValue(const T &val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
explicit constexpr ModelValue(T &&val) noexcept;
|
||||
|
||||
constexpr ~ModelValue() noexcept;
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr const auto &get() const noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
oxPanic(OxError(1), "invalid cast");
|
||||
}
|
||||
return getValue<type>(*this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto &get() noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
oxPanic(OxError(1), "invalid cast");
|
||||
}
|
||||
return getValue<type>(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Type type() const noexcept;
|
||||
|
||||
constexpr Error setType(const DescriptorType *type, int subscriptLevels = 0) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error setType() noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error set(const T &v) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error set(T &&v) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(const ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &&val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(const auto &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(auto &&val) noexcept;
|
||||
|
||||
private:
|
||||
constexpr void freeResources() noexcept;
|
||||
|
||||
};
|
||||
|
||||
class ModelValueVector {
|
||||
private:
|
||||
Vector<ModelValue> m_vec;
|
||||
ModelValue m_templateValue;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
|
||||
public:
|
||||
constexpr ModelValueVector() noexcept = default;
|
||||
|
||||
constexpr ModelValueVector(const ModelValueVector &other) noexcept;
|
||||
|
||||
constexpr ModelValueVector(ModelValueVector &&other) noexcept;
|
||||
|
||||
constexpr ModelValueVector &operator=(const ModelValueVector &other) noexcept;
|
||||
|
||||
constexpr ModelValueVector &operator=(ModelValueVector &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto data() const noexcept {
|
||||
return m_vec.data();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto data() noexcept {
|
||||
return m_vec.data();
|
||||
}
|
||||
|
||||
constexpr void resize(std::size_t sz) noexcept {
|
||||
const auto oldSz = m_vec.size();
|
||||
m_vec.resize(sz);
|
||||
if (sz > oldSz) {
|
||||
for (auto i = oldSz; i < sz; ++i) {
|
||||
m_vec[i] = m_templateValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &get() noexcept {
|
||||
return m_vec;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const auto &get() const noexcept {
|
||||
return m_vec;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type, int subscriptLevels) noexcept {
|
||||
return m_templateValue.setType(type, subscriptLevels);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
return m_typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return m_vec.size();
|
||||
}
|
||||
|
||||
constexpr auto &operator[](std::size_t i) noexcept {
|
||||
return m_vec[i];
|
||||
}
|
||||
|
||||
constexpr auto &operator[](std::size_t i) const noexcept {
|
||||
return m_vec[i];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto begin() noexcept {
|
||||
return m_vec.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cbegin() const noexcept {
|
||||
return m_vec.cbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto rbegin() noexcept {
|
||||
return m_vec.rbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto crbegin() const noexcept {
|
||||
return m_vec.crbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto end() noexcept {
|
||||
return m_vec.end();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cend() const noexcept {
|
||||
return m_vec.cend();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto rend() noexcept {
|
||||
return m_vec.rend();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto crend() const noexcept {
|
||||
return m_vec.crend();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
consteval bool isVector(const ModelValueVector*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
class ModelObject {
|
||||
protected:
|
||||
struct Field {
|
||||
String name;
|
||||
ModelValue value;
|
||||
};
|
||||
oxModelFriend(ModelObject);
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, ModelValue*> m_fields;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
|
||||
public:
|
||||
constexpr ModelObject() noexcept = default;
|
||||
|
||||
constexpr ModelObject(const ModelObject &other) noexcept {
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr ModelObject(ModelObject &&other) noexcept {
|
||||
for (auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(std::move(f));
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr auto &operator=(const ModelObject &other) noexcept {
|
||||
if (&other == this) [[unlikely]] {
|
||||
return *this;
|
||||
}
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr auto &operator=(ModelObject &&other) noexcept {
|
||||
if (&other == this) [[unlikely]] {
|
||||
return *this;
|
||||
}
|
||||
for (auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(std::move(f));
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t &i) noexcept {
|
||||
return *m_fieldsOrder[i];
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return *m_fields[k];
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
return *m_fieldsOrder[i];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
return m_typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type) noexcept {
|
||||
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
|
||||
return OxError(1, "Cannot load a non-struct type to ModelObject");
|
||||
}
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
for (const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
oxReturnError(field->value.setType(f.type, f.subscriptLevels));
|
||||
m_fields[field->name] = &field->value;
|
||||
m_fieldsOrder.emplace_back(std::move(field));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ModelUnion {
|
||||
protected:
|
||||
struct Field {
|
||||
int idx = -1;
|
||||
String name;
|
||||
ModelValue value;
|
||||
};
|
||||
oxModelFriend(ModelUnion);
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, Field*> m_fields;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
int m_unionIdx = -1;
|
||||
|
||||
private:
|
||||
constexpr ModelUnion() noexcept = default;
|
||||
|
||||
public:
|
||||
constexpr ModelUnion(const ModelUnion &other) noexcept {
|
||||
for (auto i = 0; const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{i, f->name, f->value});
|
||||
m_fields[field->name] = field.get();
|
||||
++i;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
m_unionIdx = other.m_unionIdx;
|
||||
}
|
||||
|
||||
static constexpr Result<UniquePtr<ModelUnion>> make(const DescriptorType *type) noexcept {
|
||||
UniquePtr<ModelUnion> out(new ModelUnion);
|
||||
oxReturnError(out->setType(type));
|
||||
return out;
|
||||
}
|
||||
|
||||
static constexpr Result<UniquePtr<ModelUnion>> make(const ModelUnion &other) noexcept {
|
||||
return UniquePtr<ModelUnion>(new ModelUnion(other));
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return m_fields[k]->value;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
return m_fieldsOrder[i]->value;
|
||||
}
|
||||
|
||||
constexpr void setActiveField(int i) noexcept {
|
||||
m_unionIdx = i;
|
||||
}
|
||||
|
||||
constexpr void set(int i, auto val) noexcept {
|
||||
m_unionIdx = i;
|
||||
*m_fieldsOrder[i] = val;
|
||||
}
|
||||
|
||||
constexpr void set(std::size_t i, auto val) noexcept {
|
||||
m_unionIdx = static_cast<int>(i);
|
||||
*m_fieldsOrder[i] = val;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(std::size_t i) noexcept {
|
||||
return m_fieldsOrder[i]->value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(const String &k) noexcept {
|
||||
return (*m_fields.at(k).value)->value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int getKeyIdx(const auto &k) const noexcept {
|
||||
for (auto i = 0; const auto &f : m_fieldsOrder) {
|
||||
if (f->name == k) {
|
||||
return i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
return m_typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type) noexcept {
|
||||
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
|
||||
return OxError(1, "Cannot load a non-struct type to ModelUnion");
|
||||
}
|
||||
m_fields.clear();
|
||||
m_fieldsOrder.clear();
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
for (auto i = 0; const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
field->idx = i;
|
||||
oxReturnError(field->value.setType(f.type, f.subscriptLevels));
|
||||
m_fields[field->name] = field.get();
|
||||
m_fieldsOrder.emplace_back(std::move(field));
|
||||
++i;
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto fieldCount() const noexcept {
|
||||
return m_fields.size();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto unionIdx() const noexcept {
|
||||
return m_unionIdx;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
case Type::Undefined:
|
||||
case Type::Bool:
|
||||
case Type::UnsignedInteger8:
|
||||
case Type::UnsignedInteger16:
|
||||
case Type::UnsignedInteger32:
|
||||
case Type::UnsignedInteger64:
|
||||
case Type::SignedInteger8:
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox_memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = new String(other.get<String>());
|
||||
break;
|
||||
case Type::Union:
|
||||
m_data.uni = new ModelUnion(other.get<ModelUnion>());
|
||||
break;
|
||||
case Type::Object:
|
||||
m_data.obj = new ModelObject(other.get<ModelObject>());
|
||||
break;
|
||||
case Type::Vector:
|
||||
m_data.vec = new ModelValueVector(*other.m_data.vec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &other) noexcept: ModelValue(const_cast<const ModelValue&>(other)) {
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
case Type::Undefined:
|
||||
case Type::Bool:
|
||||
case Type::UnsignedInteger8:
|
||||
case Type::UnsignedInteger16:
|
||||
case Type::UnsignedInteger32:
|
||||
case Type::UnsignedInteger64:
|
||||
case Type::SignedInteger8:
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox_memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
ox_memset(&other.m_data, 0, sizeof(m_data));
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = other.m_data.str;
|
||||
other.m_data.str = new String;
|
||||
break;
|
||||
case Type::Union:
|
||||
m_data.uni = new ModelUnion(*other.m_data.uni);
|
||||
break;
|
||||
case Type::Object:
|
||||
m_data.obj = new ModelObject(*other.m_data.obj);
|
||||
break;
|
||||
case Type::Vector:
|
||||
m_data.vec = new ModelValueVector(*other.m_data.vec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ModelValue::ModelValue(const T &val) noexcept {
|
||||
set(val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ModelValue::ModelValue(T &&val) noexcept {
|
||||
set(ox::forward(val));
|
||||
}
|
||||
|
||||
constexpr ModelValue::~ModelValue() noexcept {
|
||||
freeResources();
|
||||
}
|
||||
|
||||
constexpr ModelValue::Type ModelValue::type() const noexcept {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
constexpr Error ModelValue::setType(const DescriptorType *type, int subscriptLevels) noexcept {
|
||||
freeResources();
|
||||
if (subscriptLevels) {
|
||||
m_type = Type::Vector;
|
||||
m_data.vec = new ModelValueVector;
|
||||
return m_data.vec->setType(type, subscriptLevels - 1);
|
||||
} else if (type->typeName == types::Bool) {
|
||||
m_type = Type::Bool;
|
||||
} else if (type->typeName == types::String) {
|
||||
m_type = Type::String;
|
||||
m_data.str = new String;
|
||||
} else if (type->typeName == types::Uint8) {
|
||||
m_type = Type::UnsignedInteger8;
|
||||
} else if (type->typeName == types::Uint16) {
|
||||
m_type = Type::UnsignedInteger16;
|
||||
} else if (type->typeName == types::Uint32) {
|
||||
m_type = Type::UnsignedInteger32;
|
||||
} else if (type->typeName == types::Uint64) {
|
||||
m_type = Type::UnsignedInteger64;
|
||||
} else if (type->typeName == types::Int8) {
|
||||
m_type = Type::SignedInteger8;
|
||||
} else if (type->typeName == types::Int16) {
|
||||
m_type = Type::SignedInteger16;
|
||||
} else if (type->typeName == types::Int32) {
|
||||
m_type = Type::SignedInteger32;
|
||||
} else if (type->typeName == types::Int64) {
|
||||
m_type = Type::SignedInteger64;
|
||||
} else if (type->primitiveType == PrimitiveType::Struct) {
|
||||
m_type = Type::Object;
|
||||
m_data.obj = new ModelObject;
|
||||
oxReturnError(m_data.obj->setType(type));
|
||||
} else if (type->primitiveType == PrimitiveType::Union) {
|
||||
m_type = Type::Union;
|
||||
oxRequireM(u, ModelUnion::make(type));
|
||||
m_data.uni = u.release();
|
||||
oxReturnError(m_data.uni->setType(type));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error ModelValue::setType() noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
return setType(type);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error ModelValue::set(const T &v) noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
return OxError(1, "type mismatch");
|
||||
}
|
||||
auto &value = getValue<type>(*this);
|
||||
value = v;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error ModelValue::set(T &&v) noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
if (m_type != type) [[unlikely]] {
|
||||
return OxError(1, "type mismatch");
|
||||
}
|
||||
auto &value = getValue<type>(*this);
|
||||
if constexpr(type == Type::Vector || type == Type::Object ||
|
||||
type == Type::Union || type == Type::String) {
|
||||
safeDelete(value);
|
||||
}
|
||||
value = ox::forward<T>(v);
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {
|
||||
return this->operator=(const_cast<const ModelValue&>(other));
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
|
||||
if (this == &other) [[unlikely]] {
|
||||
return *this;
|
||||
}
|
||||
freeResources();
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
case Type::Undefined:
|
||||
case Type::Bool:
|
||||
case Type::UnsignedInteger8:
|
||||
case Type::UnsignedInteger16:
|
||||
case Type::UnsignedInteger32:
|
||||
case Type::UnsignedInteger64:
|
||||
case Type::SignedInteger8:
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox_memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = new String(other.get<String>());
|
||||
break;
|
||||
case Type::Union:
|
||||
m_data.uni = new ModelUnion(other.get<ModelUnion>());
|
||||
break;
|
||||
case Type::Object:
|
||||
m_data.obj = new ModelObject(other.get<ModelObject>());
|
||||
break;
|
||||
case Type::Vector:
|
||||
m_data.vec = new ModelValueVector(*other.m_data.vec);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(ModelValue &&other) noexcept {
|
||||
if (this == &other) [[unlikely]] {
|
||||
return *this;
|
||||
}
|
||||
freeResources();
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
case Type::Undefined:
|
||||
case Type::Bool:
|
||||
case Type::UnsignedInteger8:
|
||||
case Type::UnsignedInteger16:
|
||||
case Type::UnsignedInteger32:
|
||||
case Type::UnsignedInteger64:
|
||||
case Type::SignedInteger8:
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
ox_memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||
ox_memset(&other.m_data, 0, sizeof(m_data));
|
||||
break;
|
||||
case Type::String:
|
||||
m_data.str = other.m_data.str;
|
||||
other.m_data.str = new String;
|
||||
break;
|
||||
case Type::Object:
|
||||
m_data.obj = new ModelObject(*other.m_data.obj);
|
||||
break;
|
||||
case Type::Union:
|
||||
m_data.uni = new ModelUnion(*other.m_data.uni);
|
||||
break;
|
||||
case Type::Vector:
|
||||
m_data.vec = new ModelValueVector(*other.m_data.vec);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(const auto &val) noexcept {
|
||||
if (this == &val) {
|
||||
return *this;
|
||||
}
|
||||
set(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(auto &&val) noexcept {
|
||||
if (this == &val) {
|
||||
return *this;
|
||||
}
|
||||
set(ox::forward(val));
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr void ModelValue::freeResources() noexcept {
|
||||
switch (m_type) {
|
||||
case Type::Undefined:
|
||||
case Type::Bool:
|
||||
case Type::UnsignedInteger8:
|
||||
case Type::UnsignedInteger16:
|
||||
case Type::UnsignedInteger32:
|
||||
case Type::UnsignedInteger64:
|
||||
case Type::SignedInteger8:
|
||||
case Type::SignedInteger16:
|
||||
case Type::SignedInteger32:
|
||||
case Type::SignedInteger64:
|
||||
break;
|
||||
case Type::String:
|
||||
safeDelete(m_data.str);
|
||||
break;
|
||||
case Type::Object:
|
||||
safeDelete(m_data.obj);
|
||||
break;
|
||||
case Type::Union:
|
||||
safeDelete(m_data.uni);
|
||||
break;
|
||||
case Type::Vector:
|
||||
safeDelete(m_data.vec);
|
||||
break;
|
||||
}
|
||||
m_type = Type::Undefined;
|
||||
}
|
||||
|
||||
constexpr ModelValueVector::ModelValueVector(const ModelValueVector &other) noexcept {
|
||||
for (auto &v : other.m_vec) {
|
||||
m_vec.emplace_back(v);
|
||||
}
|
||||
m_templateValue = other.m_templateValue;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept {
|
||||
for (auto &v : other.m_vec) {
|
||||
m_vec.emplace_back(std::move(v));
|
||||
}
|
||||
m_templateValue = std::move(other.m_templateValue);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr ModelValueVector &ModelValueVector::operator=(const ModelValueVector &other) noexcept {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
for (auto &v : other.m_vec) {
|
||||
m_vec.emplace_back(v);
|
||||
}
|
||||
m_templateValue = other.m_templateValue;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ModelValueVector &ModelValueVector::operator=(ModelValueVector &&other) noexcept {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
for (auto &v : other.m_vec) {
|
||||
m_vec.emplace_back(std::move(v));
|
||||
}
|
||||
m_templateValue = std::move(other.m_templateValue);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
48
deps/ox/src/ox/model/optype.hpp
vendored
48
deps/ox/src/ox/model/optype.hpp
vendored
@ -3,54 +3,18 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
#include <ox/std/concepts.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
namespace OpType {
|
||||
constexpr auto Read = "Read";
|
||||
constexpr auto Write = "Write";
|
||||
constexpr auto Reflect = "Reflect";
|
||||
}
|
||||
|
||||
// empty default implementations of model functions
|
||||
|
||||
template<typename T, typename O>
|
||||
constexpr Error modelRead(T*, O*) noexcept {
|
||||
oxAssert(OxError(1), "Missing modelRead function");
|
||||
return OxError(1, "Model: modelRead not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
constexpr Error modelWrite(T*, O*) noexcept {
|
||||
oxAssert(OxError(1), "Missing modelWrite function");
|
||||
return OxError(1, "Model: modelWrite not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
constexpr Error modelReflect(T*, O*) noexcept {
|
||||
return OxError(1, "Model: modelReflect not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
constexpr Error model(T *io, O *obj) noexcept {
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Read) == 0) {
|
||||
return modelRead(io, obj);
|
||||
} else if constexpr(ox_strcmp(T::opType(), OpType::Write) == 0) {
|
||||
return modelWrite(io, obj);
|
||||
} else if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
return modelReflect(io, obj);
|
||||
} else {
|
||||
oxAssert(OxError(1), "Missing model function");
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ox::OpType {
|
||||
constexpr auto Read = "Read";
|
||||
constexpr auto Write = "Write";
|
||||
constexpr auto Reflect = "Reflect";
|
||||
}
|
||||
|
6
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
6
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -40,8 +40,8 @@ struct TypeNameCatcher {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error fieldCString(const char*, T) noexcept {
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(Args&&...) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
48
deps/ox/src/ox/model/types.hpp
vendored
48
deps/ox/src/ox/model/types.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -12,10 +12,15 @@
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#if __has_include(<array>)
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
#if __has_include(<QVector>)
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/bstring.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
@ -24,19 +29,32 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
namespace types {
|
||||
constexpr auto String = "B:string";
|
||||
constexpr auto Bool = "B:bool";
|
||||
constexpr auto Uint8 = "B:uint8_t";
|
||||
constexpr auto Uint16 = "B:uint16_t";
|
||||
constexpr auto Uint32 = "B:uint32_t";
|
||||
constexpr auto Uint64 = "B:uint64_t";
|
||||
constexpr auto Int8 = "B:int8_t";
|
||||
constexpr auto Int16 = "B:int16_t";
|
||||
constexpr auto Int32 = "B:int32_t";
|
||||
constexpr auto Int64 = "B:int64_t";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isVector(const T*) noexcept {
|
||||
consteval bool isVector(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isVector(const Vector<T>*) noexcept {
|
||||
consteval bool isVector(const Vector<T>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if __has_include(<vector>)
|
||||
template<typename T>
|
||||
constexpr bool isVector(const std::vector<T>*) noexcept {
|
||||
consteval bool isVector(const std::vector<T>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -51,6 +69,24 @@ constexpr bool isVector(const QVector<T>*) noexcept {
|
||||
template<typename T>
|
||||
constexpr bool isVector_v = isVector(static_cast<const T*>(nullptr));
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isArray_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isArray_v<T[]> = false;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<T[sz]> = false;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<Array<T, sz>> = false;
|
||||
|
||||
#if __has_include(<array>)
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<std::array<T, sz>> = false;
|
||||
#endif
|
||||
|
||||
|
||||
class SerStr {
|
||||
|
||||
protected:
|
||||
@ -121,12 +157,12 @@ class SerStr {
|
||||
|
||||
};
|
||||
|
||||
template<typename Union>
|
||||
template<typename Union, bool force = false>
|
||||
class UnionView {
|
||||
|
||||
protected:
|
||||
int m_idx = -1;
|
||||
typename enable_if<is_union_v<Union>, Union>::type *m_union = nullptr;
|
||||
typename enable_if<is_union_v<Union> || force, Union>::type *m_union = nullptr;
|
||||
|
||||
public:
|
||||
constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {
|
||||
|
60
deps/ox/src/ox/model/typestore.hpp
vendored
60
deps/ox/src/ox/model/typestore.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -13,6 +13,7 @@
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
|
||||
#include "ox/std/fmt.hpp"
|
||||
#include "typenamecatcher.hpp"
|
||||
#include "desctypes.hpp"
|
||||
|
||||
@ -22,29 +23,37 @@ class TypeStore {
|
||||
private:
|
||||
HashMap<String, UniquePtr<DescriptorType>> m_cache;
|
||||
|
||||
static constexpr auto buildTypeId(const auto &name, auto version) noexcept {
|
||||
return ox::sfmt("{};{}", name, version);
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr TypeStore() noexcept = default;
|
||||
|
||||
constexpr virtual ~TypeStore() noexcept = default;
|
||||
|
||||
constexpr Result<DescriptorType*> get(const auto &name) const noexcept {
|
||||
oxRequire(out, m_cache.at(name));
|
||||
constexpr Result<DescriptorType*> get(const auto &name, int typeVersion) const noexcept {
|
||||
const auto typeId = buildTypeId(name, typeVersion);
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<DescriptorType*> get() const noexcept {
|
||||
constexpr auto name = requireModelTypeName<T>();
|
||||
oxRequire(out, m_cache.at(name));
|
||||
constexpr auto typeName = requireModelTypeName<T>();
|
||||
constexpr auto typeVersion = requireModelTypeVersion<T>();
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
}
|
||||
|
||||
constexpr DescriptorType *getInit(const auto &name) noexcept {
|
||||
auto [out, err] = m_cache.at(name);
|
||||
constexpr DescriptorType *getInit(const auto &typeName, int typeVersion) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
auto [out, err] = m_cache.at(typeId);
|
||||
if (err) {
|
||||
auto &out = m_cache[name];
|
||||
out = ox::make_unique<DescriptorType>(name);
|
||||
return out.get();
|
||||
out = &m_cache[typeId];
|
||||
*out = ox::make_unique<DescriptorType>(typeName, typeVersion);
|
||||
return out->get();
|
||||
}
|
||||
return out->get();
|
||||
}
|
||||
@ -55,15 +64,13 @@ class TypeStore {
|
||||
return getInit(name);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<DescriptorType*> getLoad() noexcept {
|
||||
constexpr auto nameCstr = requireModelTypeName<T>();
|
||||
const String name = nameCstr;
|
||||
auto [val, err] = m_cache.at(name);
|
||||
constexpr Result<DescriptorType*> getLoad(const auto &typeName, auto typeVersion) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
auto [val, err] = m_cache.at(typeId);
|
||||
if (err) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
oxRequireM(dt, loadDescriptor(name));
|
||||
auto &out = m_cache[name];
|
||||
oxRequireM(dt, loadDescriptor(typeName, typeVersion));
|
||||
auto &out = m_cache[typeId];
|
||||
out = std::move(dt);
|
||||
return out.get();
|
||||
} else {
|
||||
@ -73,12 +80,21 @@ class TypeStore {
|
||||
return val->get();
|
||||
}
|
||||
|
||||
constexpr void set(const String &name, UniquePtr<DescriptorType> dt) noexcept {
|
||||
m_cache[name] = std::move(dt);
|
||||
template<typename T>
|
||||
constexpr Result<DescriptorType*> getLoad() noexcept {
|
||||
constexpr auto typeName = requireModelTypeName<T>();
|
||||
constexpr auto typeVersion = requireModelTypeVersion<T>();
|
||||
return getLoad(typeName, typeVersion);
|
||||
}
|
||||
|
||||
constexpr void set(const String &name, DescriptorType *dt) noexcept {
|
||||
m_cache[name] = UniquePtr<DescriptorType>(dt);
|
||||
constexpr void set(const auto &typeName, auto typeVersion, UniquePtr<DescriptorType> dt) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
m_cache[typeId] = std::move(dt);
|
||||
}
|
||||
|
||||
constexpr void set(const auto &typeName, auto typeVersion, DescriptorType *dt) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
m_cache[typeId] = UniquePtr<DescriptorType>(dt);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -92,7 +108,7 @@ class TypeStore {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(const ox::String&) noexcept {
|
||||
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(const ox::String&, int) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
|
108
deps/ox/src/ox/oc/read.cpp
vendored
108
deps/ox/src/ox/oc/read.cpp
vendored
@ -3,10 +3,11 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <ox/std/bit.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "read.hpp"
|
||||
|
||||
@ -18,7 +19,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize)
|
||||
Json::CharReaderBuilder parserBuilder;
|
||||
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
||||
throw OxError(1, "Could not parse JSON");
|
||||
throw OxException(1, "Could not parse JSON");
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,12 +27,12 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
|
||||
Json::CharReaderBuilder parserBuilder;
|
||||
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
|
||||
throw OxError(1, "Could not parse JSON");
|
||||
throw OxException(1, "Could not parse JSON");
|
||||
}
|
||||
}
|
||||
|
||||
OrganicClawReader::OrganicClawReader(const Json::Value &json, int unionIdx) noexcept:
|
||||
m_json(json),
|
||||
OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
|
||||
m_json(std::move(json)),
|
||||
m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
@ -208,6 +209,87 @@ Error OrganicClawReader::field(const char *key, SerStr val) noexcept {
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
|
||||
auto err = OxError(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
if (targetValid()) {
|
||||
if (jv.empty()) {
|
||||
auto data = val;
|
||||
if (data) {
|
||||
data[0] = 0;
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
auto data = val;
|
||||
if (strSize >= buffLen) {
|
||||
err = OxError(2, "String size exceeds capacity of destination");
|
||||
} else {
|
||||
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
data[strSize] = 0;
|
||||
}
|
||||
} else {
|
||||
err = OxError(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
|
||||
auto err = OxError(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
auto &data = *val;
|
||||
if (targetValid()) {
|
||||
if (jv.empty()) {
|
||||
if (data) {
|
||||
data[0] = 0;
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
safeDelete(*val);
|
||||
*val = new char[strSize + 1];
|
||||
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
data[strSize] = 0;
|
||||
} else {
|
||||
err = OxError(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
|
||||
auto err = OxError(0);
|
||||
const char *begin = nullptr, *end = nullptr;
|
||||
const auto &jv = value(key);
|
||||
if (targetValid()) {
|
||||
if (jv.empty()) {
|
||||
auto data = val;
|
||||
if (data) {
|
||||
data[0] = 0;
|
||||
}
|
||||
} else if (jv.isString()) {
|
||||
jv.getString(&begin, &end);
|
||||
const auto strSize = static_cast<std::size_t>(end - begin);
|
||||
auto data = val;
|
||||
if (strSize >= buffLen) {
|
||||
safeDelete(*val);
|
||||
*val = new char[strSize + 1];
|
||||
}
|
||||
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
|
||||
data[strSize] = 0;
|
||||
} else {
|
||||
err = OxError(1, "Type mismatch");
|
||||
}
|
||||
}
|
||||
++m_fieldIt;
|
||||
return err;
|
||||
}
|
||||
|
||||
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept {
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty()) {
|
||||
@ -234,13 +316,25 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
|
||||
}
|
||||
|
||||
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {
|
||||
return OrganicClawReader(m_json[key], unionIdx);
|
||||
return OrganicClawReader(value(key), unionIdx);
|
||||
}
|
||||
|
||||
bool OrganicClawReader::fieldPresent(const char *key) noexcept {
|
||||
return !m_json[key].empty();
|
||||
}
|
||||
|
||||
int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u) const noexcept {
|
||||
const auto &obj = m_json[name];
|
||||
if (!obj.isObject()) {
|
||||
return -1;
|
||||
}
|
||||
const auto &keys = obj.getMemberNames();
|
||||
if (keys.size() != 1) {
|
||||
return -1;
|
||||
}
|
||||
return u.getKeyIdx(keys.front().c_str());
|
||||
}
|
||||
|
||||
Json::Value &OrganicClawReader::value(const char *key) noexcept {
|
||||
if (m_json.isArray()) {
|
||||
return m_json[m_fieldIt];
|
||||
@ -249,7 +343,7 @@ Json::Value &OrganicClawReader::value(const char *key) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
bool OrganicClawReader::targetValid() noexcept {
|
||||
bool OrganicClawReader::targetValid() const noexcept {
|
||||
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
|
||||
}
|
||||
|
||||
|
58
deps/ox/src/ox/oc/read.hpp
vendored
58
deps/ox/src/ox/oc/read.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -11,6 +11,7 @@
|
||||
#include <json/json.h>
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/typenamecatcher.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
@ -37,7 +38,7 @@ class OrganicClawReader {
|
||||
|
||||
OrganicClawReader(const char *json, std::size_t buffSize);
|
||||
|
||||
explicit OrganicClawReader(const Json::Value &json, int unionIdx = -1) noexcept;
|
||||
explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char *key, int8_t *val) noexcept;
|
||||
Error field(const char *key, int16_t *val) noexcept;
|
||||
@ -61,8 +62,8 @@ class OrganicClawReader {
|
||||
template<typename T>
|
||||
Error field(const char *key, T *val) noexcept;
|
||||
|
||||
template<typename U>
|
||||
Error field(const char *key, UnionView<U> val) noexcept;
|
||||
template<typename U, bool force = false>
|
||||
Error field(const char *key, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BasicString<L> *val) noexcept;
|
||||
@ -72,6 +73,12 @@ class OrganicClawReader {
|
||||
|
||||
Error field(const char *key, SerStr val) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char *val, std::size_t buffLen) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char **val) noexcept;
|
||||
|
||||
Error fieldCString(const char *key, char **val, std::size_t buffLen) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
@ -109,16 +116,23 @@ class OrganicClawReader {
|
||||
// compatibility stub
|
||||
constexpr void nextField() noexcept {}
|
||||
|
||||
[[nodiscard]]
|
||||
bool fieldPresent(const char *key) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int whichFieldPresent(const char *name, const ModelUnion &u) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Read;
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]]
|
||||
Json::Value &value(const char *key) noexcept;
|
||||
|
||||
bool targetValid() noexcept;
|
||||
[[nodiscard]]
|
||||
bool targetValid() const noexcept;
|
||||
|
||||
};
|
||||
|
||||
@ -134,7 +148,8 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty() || jv.isObject()) {
|
||||
auto reader = child(key);
|
||||
return model(&reader, val);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
return model(&handler, val);
|
||||
} else {
|
||||
err = OxError(1, "Type mismatch");
|
||||
}
|
||||
@ -143,14 +158,15 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Error OrganicClawReader::field(const char *key, UnionView<U> val) noexcept {
|
||||
template<typename U, bool force>
|
||||
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
|
||||
auto err = OxError(0);
|
||||
if (targetValid()) {
|
||||
const auto &jv = value(key);
|
||||
if (jv.empty() || jv.isObject()) {
|
||||
auto reader = child(key, val.idx());
|
||||
err = model(&reader, val.get());
|
||||
ModelHandlerInterface handler(&reader);
|
||||
err = model(&handler, val.get());
|
||||
} else {
|
||||
err = OxError(1, "Type mismatch");
|
||||
}
|
||||
@ -185,13 +201,17 @@ Error OrganicClawReader::field(const char *key, BString<L> *val) noexcept {
|
||||
template<typename T>
|
||||
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
|
||||
const auto &srcVal = value(key);
|
||||
if (!srcVal.isNull() && !srcVal.isArray()) {
|
||||
return OxError(1, "Type mismatch");
|
||||
}
|
||||
auto srcSize = srcVal.size();
|
||||
if (srcSize > valLen) {
|
||||
return OxError(1);
|
||||
}
|
||||
OrganicClawReader r(srcVal);
|
||||
ModelHandlerInterface handler{&r};
|
||||
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
|
||||
oxReturnError(r.field("", &val[i]));
|
||||
oxReturnError(handler.field("", &val[i]));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
@ -199,28 +219,32 @@ Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noex
|
||||
template<typename T>
|
||||
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
const auto &srcVal = value(key);
|
||||
if (!srcVal.isObject()) {
|
||||
return OxError(1, "Type mismatch");
|
||||
}
|
||||
auto keys = srcVal.getMemberNames();
|
||||
auto srcSize = srcVal.size();
|
||||
OrganicClawReader r(srcVal);
|
||||
ModelHandlerInterface handler{&r};
|
||||
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
|
||||
const auto k = keys[i].c_str();
|
||||
oxReturnError(r.field(k, &val->operator[](k)));
|
||||
oxReturnError(handler.field(k, &val->operator[](k)));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept {
|
||||
Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept {
|
||||
// OrganicClawReader constructor can throw, but readOC should return its errors.
|
||||
try {
|
||||
Json::Value doc;
|
||||
Json::CharReaderBuilder parserBuilder;
|
||||
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(json, json + jsonSize, &doc, nullptr)) {
|
||||
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
|
||||
if (!parser->parse(buff, buff + buffSize, &doc, nullptr)) {
|
||||
return OxError(1, "Could not parse JSON");
|
||||
}
|
||||
OrganicClawReader reader(json, jsonSize);
|
||||
return model(&reader, val);
|
||||
OrganicClawReader reader(buff, buffSize);
|
||||
ModelHandlerInterface handler(&reader);
|
||||
return model(&handler, val);
|
||||
} catch (const Error &err) {
|
||||
return err;
|
||||
} catch (...) {
|
||||
|
1
deps/ox/src/ox/oc/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/oc/test/CMakeLists.txt
vendored
@ -10,4 +10,5 @@ target_link_libraries(
|
||||
|
||||
add_test("[ox/oc] OcTest Writer" OcTest OrganicClawWriter)
|
||||
add_test("[ox/oc] OcTest Reader" OcTest OrganicClawReader)
|
||||
add_test("[ox/oc] OcTest OrganicClawModelValue" OcTest OrganicClawModelValue)
|
||||
add_test("[ox/oc] OcTest OrganicClawDef" OcTest OrganicClawDef)
|
||||
|
79
deps/ox/src/ox/oc/test/tests.cpp
vendored
79
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
@ -19,7 +19,7 @@ union TestUnion {
|
||||
static constexpr auto TypeVersion = 1;
|
||||
bool Bool;
|
||||
uint32_t Int = 5;
|
||||
char String[32];
|
||||
char *String;
|
||||
};
|
||||
|
||||
struct TestStructNest {
|
||||
@ -43,8 +43,9 @@ struct TestStruct {
|
||||
int32_t Int6 = 0;
|
||||
int32_t Int7 = 0;
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::BString<32> String = "";
|
||||
ox::String String = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
@ -55,23 +56,24 @@ struct TestStruct {
|
||||
TestStruct(TestStruct &&other) noexcept;
|
||||
|
||||
constexpr ~TestStruct() noexcept {
|
||||
if (unionIdx == 2) {
|
||||
ox::safeDelete(Union.String);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr TestStruct &operator=(TestStruct&&) noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestUnion *obj) noexcept {
|
||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *obj) noexcept {
|
||||
io->template setTypeInfo<TestUnion>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
oxReturnError(io->field("String", ox::SerStr(obj->String)));
|
||||
oxReturnError(io->fieldCString("String", &obj->String));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStructNest *obj) noexcept {
|
||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
|
||||
io->template setTypeInfo<TestStructNest>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
@ -79,8 +81,7 @@ constexpr ox::Error model(T *io, TestStructNest *obj) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
|
||||
io->template setTypeInfo<TestStruct>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
@ -92,7 +93,12 @@ constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
oxReturnError(io->field("Int6", &obj->Int6));
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
|
||||
oxReturnError(io->field("unionIdx", &obj->unionIdx));
|
||||
if (ox_strcmp(io->opType(), ox::OpType::Reflect) == 0) {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0}));
|
||||
} else {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
||||
}
|
||||
oxReturnError(io->field("String", &obj->String));
|
||||
oxReturnError(io->field("List", obj->List, 4));
|
||||
oxReturnError(io->field("Map", &obj->Map));
|
||||
@ -173,6 +179,57 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"OrganicClawModelValue",
|
||||
[] {
|
||||
ox::Buffer dataBuff;
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(&testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"OrganicClawDef",
|
||||
[] {
|
||||
|
103
deps/ox/src/ox/oc/write.cpp
vendored
103
deps/ox/src/ox/oc/write.cpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "write.hpp"
|
||||
@ -18,87 +18,6 @@ OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept:
|
||||
m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, int8_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, int16_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, int32_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, int64_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, uint8_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, uint16_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, uint32_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, uint64_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, bool *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, String *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, SerStr val) noexcept {
|
||||
if (targetValid() && val.len()) {
|
||||
value(key) = val.c_str();
|
||||
@ -107,6 +26,26 @@ Error OrganicClawWriter::field(const char *key, SerStr val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char **val, int len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val, int len) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), len);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char **val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Json::Value &OrganicClawWriter::value(const char *key) noexcept {
|
||||
if (m_json.isArray()) {
|
||||
return m_json[m_fieldIt];
|
||||
|
177
deps/ox/src/ox/oc/write.hpp
vendored
177
deps/ox/src/ox/oc/write.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -11,6 +11,7 @@
|
||||
#include <json/json.h>
|
||||
|
||||
#include <ox/model/fieldcounter.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
#include <ox/model/typenamecatcher.hpp>
|
||||
@ -22,8 +23,7 @@ namespace ox {
|
||||
|
||||
class OrganicClawWriter {
|
||||
|
||||
template<typename T>
|
||||
friend Result<Buffer> writeOC(T *val) noexcept;
|
||||
friend Result<Buffer> writeOC(auto *val) noexcept;
|
||||
|
||||
protected:
|
||||
Json::Value m_json;
|
||||
@ -35,36 +35,140 @@ class OrganicClawWriter {
|
||||
|
||||
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char*, int8_t *val) noexcept;
|
||||
Error field(const char*, int16_t *val) noexcept;
|
||||
Error field(const char*, int32_t *val) noexcept;
|
||||
Error field(const char*, int64_t *val) noexcept;
|
||||
Error field(const char *key, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char*, uint8_t *val) noexcept;
|
||||
Error field(const char*, uint16_t *val) noexcept;
|
||||
Error field(const char*, uint32_t *val) noexcept;
|
||||
Error field(const char*, uint64_t *val) noexcept;
|
||||
Error field(const char *key, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char*, bool *val) noexcept;
|
||||
Error field(const char *key, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<bool> auto *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename U>
|
||||
Error field(const char*, UnionView<U> val) noexcept;
|
||||
template<typename U, bool force = true>
|
||||
Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
Error field(const char *key, const HashMap<String, T> *val) noexcept {
|
||||
if (targetValid()) {
|
||||
const auto &keys = val->keys();
|
||||
OrganicClawWriter w;
|
||||
ModelHandlerInterface handler{&w};
|
||||
for (std::size_t i = 0; i < keys.size(); ++i) {
|
||||
const auto k = keys[i].c_str();
|
||||
oxReturnError(handler.field(k, val->at(k).value));
|
||||
}
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
return field(key, const_cast<const HashMap<String, T>*>(val));
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char*, BString<L> *val) noexcept;
|
||||
Error field(const char *key, const BString<L> *val) noexcept {
|
||||
return field(key, SerStr(val->data(), val->cap()));
|
||||
}
|
||||
|
||||
Error field(const char*, String *val) noexcept;
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BString<L> *val) noexcept {
|
||||
return field(key, SerStr(val->data(), val->cap()));
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, const BasicString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BasicString<L> *val) noexcept {
|
||||
return field(key, const_cast<const BasicString<L>*>(val));
|
||||
}
|
||||
|
||||
Error field(const char*, SerStr val) noexcept;
|
||||
|
||||
Error fieldCString(const char*, const char **val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, const char **val) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val) noexcept;
|
||||
|
||||
@ -91,8 +195,9 @@ template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
OrganicClawWriter w((Json::Value(Json::arrayValue)));
|
||||
ModelHandlerInterface handler{&w};
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
oxReturnError(w.field("", &val[i]));
|
||||
oxReturnError(handler.field("", &val[i]));
|
||||
}
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
@ -100,18 +205,14 @@ Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcep
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error OrganicClawWriter::field(const char *key, BString<L> *val) noexcept {
|
||||
return field(key, SerStr(val->data(), val->cap()));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, T *val) noexcept {
|
||||
if constexpr(isVector_v<T>) {
|
||||
return field(key, val->data(), val->size());
|
||||
} else if (val && targetValid()) {
|
||||
OrganicClawWriter w;
|
||||
oxReturnError(model(&w, val));
|
||||
ModelHandlerInterface handler{&w};
|
||||
oxReturnError(model(&handler, val));
|
||||
if (!w.m_json.isNull()) {
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
@ -120,11 +221,12 @@ Error OrganicClawWriter::field(const char *key, T *val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Error OrganicClawWriter::field(const char *key, UnionView<U> val) noexcept {
|
||||
template<typename U, bool force>
|
||||
Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept {
|
||||
if (targetValid()) {
|
||||
OrganicClawWriter w(val.idx());
|
||||
oxReturnError(model(&w, val.get()));
|
||||
ModelHandlerInterface handler{&w};
|
||||
oxReturnError(model(&handler, val.get()));
|
||||
if (!w.m_json.isNull()) {
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
@ -133,25 +235,10 @@ Error OrganicClawWriter::field(const char *key, UnionView<U> val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
if (targetValid()) {
|
||||
const auto &keys = val->keys();
|
||||
OrganicClawWriter w;
|
||||
for (std::size_t i = 0; i < keys.size(); ++i) {
|
||||
const auto k = keys[i].c_str();
|
||||
oxReturnError(w.field(k, &val->operator[](k)));
|
||||
}
|
||||
value(key) = w.m_json;
|
||||
}
|
||||
++m_fieldIt;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<Buffer> writeOC(T *val) noexcept {
|
||||
Result<Buffer> writeOC(auto *val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
oxReturnError(model(&writer, val));
|
||||
ModelHandlerInterface handler(&writer);
|
||||
oxReturnError(model(&handler, val));
|
||||
Json::StreamWriterBuilder jsonBuilder;
|
||||
const auto str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
Buffer buff(str.size() + 1);
|
||||
|
2
deps/ox/src/ox/std/CMakeLists.txt
vendored
2
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -24,6 +24,7 @@ add_library(
|
||||
buffer.cpp
|
||||
buildinfo.cpp
|
||||
byteswap.cpp
|
||||
concepts.cpp
|
||||
fmt.cpp
|
||||
heapmgr.cpp
|
||||
math.cpp
|
||||
@ -73,6 +74,7 @@ install(
|
||||
buffer.hpp
|
||||
buildinfo.hpp
|
||||
byteswap.hpp
|
||||
concepts.hpp
|
||||
def.hpp
|
||||
defines.hpp
|
||||
defer.hpp
|
||||
|
23
deps/ox/src/ox/std/concepts.cpp
vendored
Normal file
23
deps/ox/src/ox/std/concepts.cpp
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "concepts.hpp"
|
||||
|
||||
namespace ox::detail::test {
|
||||
|
||||
class TestType;
|
||||
|
||||
[[nodiscard]] constexpr bool ok(auto*) noexcept { return false; }
|
||||
[[nodiscard]] constexpr bool ok(CommonPtrWith<TestType> auto*) noexcept { return true; }
|
||||
|
||||
static_assert(ok(static_cast<TestType*>(nullptr)));
|
||||
static_assert(ok(static_cast<const TestType*>(nullptr)));
|
||||
static_assert(!ok(static_cast<int*>(nullptr)));
|
||||
static_assert(!ok(static_cast<const int*>(nullptr)));
|
||||
|
||||
}
|
17
deps/ox/src/ox/std/concepts.hpp
vendored
Normal file
17
deps/ox/src/ox/std/concepts.hpp
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "typetraits.hpp"
|
||||
|
||||
namespace ox {
|
||||
template<typename T, typename U>
|
||||
concept CommonPtrWith = ox::is_same_v<typename ox::remove_pointer<const T*>::type,
|
||||
typename ox::remove_pointer<const U*>::type>;
|
||||
}
|
6
deps/ox/src/ox/std/error.hpp
vendored
6
deps/ox/src/ox/std/error.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -31,7 +31,7 @@ class exception {
|
||||
#include "utility.hpp"
|
||||
|
||||
#define OxError(...) ox::Error(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#define OxException(...) ox::Error(__FILE__, __LINE__, __VA_ARGS__)
|
||||
#define OxException(...) ox::Exception(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -83,7 +83,7 @@ constexpr auto errCode(const Error &err) noexcept {
|
||||
template<typename T=const char*>
|
||||
[[nodiscard]]
|
||||
constexpr auto toStr(const Error &err) noexcept {
|
||||
return T(err.msg);
|
||||
return err.msg ? T(err.msg) : "";
|
||||
}
|
||||
|
||||
struct Exception: public std::exception {
|
||||
|
64
deps/ox/src/ox/std/hashmap.hpp
vendored
64
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -46,21 +46,21 @@ class HashMap {
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
constexpr T &operator[](K key);
|
||||
constexpr T &operator[](const K &key);
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
constexpr Result<T*> at(K key) noexcept;
|
||||
constexpr Result<T*> at(const K &key) noexcept;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
constexpr Result<const T*> at(K key) const noexcept;
|
||||
constexpr Result<const T*> at(const K &key) const noexcept;
|
||||
|
||||
constexpr void erase(const K &key);
|
||||
|
||||
constexpr bool contains(K key) const noexcept;
|
||||
constexpr bool contains(const K &key) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept;
|
||||
@ -68,6 +68,8 @@ class HashMap {
|
||||
[[nodiscard]]
|
||||
constexpr const Vector<K> &keys() const noexcept;
|
||||
|
||||
constexpr void clear();
|
||||
|
||||
private:
|
||||
constexpr void expand();
|
||||
|
||||
@ -79,14 +81,12 @@ class HashMap {
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
constexpr Pair *const&access(const Vector<Pair*> &pairs, K key) const;
|
||||
constexpr Pair *const&access(const Vector<Pair*> &pairs, const K &key) const;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
constexpr Pair *&access(Vector<Pair*> &pairs, K key);
|
||||
|
||||
constexpr void clear();
|
||||
constexpr Pair *&access(Vector<Pair*> &pairs, const K &key);
|
||||
|
||||
};
|
||||
|
||||
@ -145,7 +145,7 @@ constexpr HashMap<K, T> &HashMap<K, T>::operator=(HashMap<K, T> &&other) {
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr T &HashMap<K, T>::operator[](K k) {
|
||||
constexpr T &HashMap<K, T>::operator[](const K &k) {
|
||||
auto &p = access(m_pairs, k);
|
||||
if (p == nullptr) {
|
||||
if (m_pairs.size() * 0.7 < m_keys.size()) {
|
||||
@ -159,19 +159,19 @@ constexpr T &HashMap<K, T>::operator[](K k) {
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr Result<T*> HashMap<K, T>::at(K k) noexcept {
|
||||
constexpr Result<T*> HashMap<K, T>::at(const K &k) noexcept {
|
||||
auto p = access(m_pairs, k);
|
||||
if (!p) {
|
||||
return {nullptr, OxError(1)};
|
||||
return {nullptr, OxError(1, "value not found for given key")};
|
||||
}
|
||||
return &p->value;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr Result<const T*> HashMap<K, T>::at(K k) const noexcept {
|
||||
constexpr Result<const T*> HashMap<K, T>::at(const K &k) const noexcept {
|
||||
auto p = access(m_pairs, k);
|
||||
if (!p) {
|
||||
return {nullptr, OxError(1)};
|
||||
return {nullptr, OxError(1, "value not found for given key")};
|
||||
}
|
||||
return &p->value;
|
||||
}
|
||||
@ -196,8 +196,9 @@ constexpr void HashMap<K, T>::erase(const K &k) {
|
||||
}
|
||||
oxIgnoreError(m_keys.erase(ox::find(m_keys.begin(), m_keys.end(), k)));
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr bool HashMap<K, T>::contains(K k) const noexcept {
|
||||
constexpr bool HashMap<K, T>::contains(const K &k) const noexcept {
|
||||
return access(m_pairs, k) != nullptr;
|
||||
}
|
||||
|
||||
@ -211,12 +212,21 @@ constexpr const Vector<K> &HashMap<K, T>::keys() const noexcept {
|
||||
return m_keys;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void HashMap<K, T>::clear() {
|
||||
for (std::size_t i = 0; i < m_pairs.size(); i++) {
|
||||
delete m_pairs[i];
|
||||
}
|
||||
m_pairs.clear();
|
||||
m_pairs.resize(100);
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void HashMap<K, T>::expand() {
|
||||
Vector<Pair*> r;
|
||||
for (std::size_t i = 0; i < m_keys.size(); ++i) {
|
||||
auto k = m_keys[i];
|
||||
access(r, k) = access(m_pairs, k);
|
||||
access(r, k) = std::move(access(m_pairs, k));
|
||||
}
|
||||
m_pairs = std::move(r);
|
||||
}
|
||||
@ -231,43 +241,29 @@ constexpr uint64_t HashMap<K, T>::hash(K k, int len) noexcept {
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(const Vector<Pair*> &pairs, K k) const {
|
||||
constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(const Vector<Pair*> &pairs, const K &k) const {
|
||||
auto h = hash(k) % pairs.size();
|
||||
char hashStr[sizeof(h) + 1];
|
||||
ox_memcpy(hashStr, &h, sizeof(h));
|
||||
hashStr[sizeof(h)] = 0;
|
||||
while (true) {
|
||||
const auto &p = pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
return p;
|
||||
} else {
|
||||
h = hash(hashStr, 8) % pairs.size();
|
||||
h = (h + 1) % pairs.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pairs, K k) {
|
||||
constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pairs, const K &k) {
|
||||
auto h = hash(k) % pairs.size();
|
||||
char hashStr[sizeof(h) + 1];
|
||||
ox_memcpy(hashStr, &h, sizeof(h));
|
||||
hashStr[sizeof(h)] = 0;
|
||||
while (true) {
|
||||
auto &p = pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
return p;
|
||||
} else {
|
||||
h = hash(hashStr, 8) % pairs.size();
|
||||
h = (h + 1) % pairs.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
constexpr void HashMap<K, T>::clear() {
|
||||
for (std::size_t i = 0; i < m_pairs.size(); i++) {
|
||||
delete m_pairs[i];
|
||||
}
|
||||
m_pairs.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
4
deps/ox/src/ox/std/memory.hpp
vendored
4
deps/ox/src/ox/std/memory.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -14,6 +14,8 @@
|
||||
|
||||
#else
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace std {
|
||||
|
||||
template<class T>
|
||||
|
40
deps/ox/src/ox/std/new.hpp
vendored
40
deps/ox/src/ox/std/new.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -47,43 +47,43 @@ class MallocaPtr {
|
||||
T *m_val = nullptr;
|
||||
|
||||
public:
|
||||
inline MallocaPtr() noexcept = default;
|
||||
constexpr MallocaPtr() noexcept = default;
|
||||
|
||||
inline MallocaPtr(MallocaPtr &other) = delete;
|
||||
constexpr MallocaPtr(MallocaPtr &other) = delete;
|
||||
|
||||
inline MallocaPtr(const MallocaPtr &other) = delete;
|
||||
constexpr MallocaPtr(const MallocaPtr &other) = delete;
|
||||
|
||||
inline MallocaPtr(MallocaPtr &&other) noexcept {
|
||||
constexpr MallocaPtr(MallocaPtr &&other) noexcept {
|
||||
m_onHeap = other.m_onHeap;
|
||||
m_val = other.m_val;
|
||||
other.m_onHeap = false;
|
||||
other.m_val = nullptr;
|
||||
}
|
||||
|
||||
inline MallocaPtr(bool onHeap, T *val) noexcept {
|
||||
constexpr MallocaPtr(bool onHeap, T *val) noexcept {
|
||||
m_onHeap = onHeap;
|
||||
m_val = val;
|
||||
}
|
||||
|
||||
inline ~MallocaPtr() noexcept {
|
||||
constexpr ~MallocaPtr() noexcept {
|
||||
if (m_onHeap && m_val) {
|
||||
delete[] reinterpret_cast<uint8_t*>(m_val);
|
||||
}
|
||||
}
|
||||
|
||||
inline const T *get() const noexcept {
|
||||
constexpr const T *get() const noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline T *get() noexcept {
|
||||
constexpr T *get() noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline const T &operator=(MallocaPtr &other) = delete;
|
||||
constexpr const T &operator=(MallocaPtr &other) = delete;
|
||||
|
||||
inline const T &operator=(const MallocaPtr &other) = delete;
|
||||
constexpr const T &operator=(const MallocaPtr &other) = delete;
|
||||
|
||||
inline const T &operator=(MallocaPtr &&other) noexcept {
|
||||
constexpr const T &operator=(MallocaPtr &&other) noexcept {
|
||||
if (m_onHeap && m_val) {
|
||||
delete[] reinterpret_cast<uint8_t*>(m_val);
|
||||
}
|
||||
@ -93,35 +93,35 @@ class MallocaPtr {
|
||||
other.m_val = nullptr;
|
||||
}
|
||||
|
||||
inline const T *operator->() const noexcept {
|
||||
constexpr const T *operator->() const noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline T *operator->() noexcept {
|
||||
constexpr T *operator->() noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline operator const T*() const noexcept {
|
||||
constexpr operator const T*() const noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline operator T*() noexcept {
|
||||
constexpr operator T*() noexcept {
|
||||
return reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline const T &operator*() const noexcept {
|
||||
constexpr const T &operator*() const noexcept {
|
||||
return *reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline T &operator*() noexcept {
|
||||
constexpr T &operator*() noexcept {
|
||||
return *reinterpret_cast<T*>(m_val);
|
||||
}
|
||||
|
||||
inline bool operator==(const MallocaPtr<T> &other) const noexcept {
|
||||
constexpr bool operator==(const MallocaPtr<T> &other) const noexcept {
|
||||
return m_val == other.m_val && m_onHeap == other.m_onHeap;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MallocaPtr<T> &other) const noexcept {
|
||||
constexpr bool operator!=(const MallocaPtr<T> &other) const noexcept {
|
||||
return m_val != other.m_val || m_onHeap != other.m_onHeap;
|
||||
}
|
||||
|
||||
|
14
deps/ox/src/ox/std/optional.hpp
vendored
14
deps/ox/src/ox/std/optional.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -26,10 +26,10 @@ class Optional {
|
||||
public:
|
||||
constexpr Optional() noexcept = default;
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Optional(Args &&... args);
|
||||
|
||||
constexpr Optional(const Optional &other) {
|
||||
if (m_ptr) {
|
||||
m_ptr->~T();
|
||||
}
|
||||
if (other.m_ptr) {
|
||||
m_ptr = new(m_data) T(*other.m_ptr);
|
||||
} else {
|
||||
@ -149,4 +149,10 @@ class Optional {
|
||||
|
||||
};
|
||||
|
||||
template<typename T, std::size_t buffSize>
|
||||
template<typename... Args>
|
||||
constexpr Optional<T, buffSize>::Optional(Args &&... args) {
|
||||
emplace(ox::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
}
|
3
deps/ox/src/ox/std/std.hpp
vendored
3
deps/ox/src/ox/std/std.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -13,6 +13,7 @@
|
||||
#include "bit.hpp"
|
||||
#include "bstring.hpp"
|
||||
#include "byteswap.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "defer.hpp"
|
||||
#include "def.hpp"
|
||||
#include "defines.hpp"
|
||||
|
26
deps/ox/src/ox/std/string.hpp
vendored
26
deps/ox/src/ox/std/string.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -134,8 +134,12 @@ class BasicString {
|
||||
|
||||
constexpr BasicString operator+(const BasicString &src) const noexcept;
|
||||
|
||||
constexpr bool operator==(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator==(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const BasicString &other) const noexcept;
|
||||
|
||||
constexpr bool operator<(const BasicString &other) const noexcept;
|
||||
@ -404,8 +408,23 @@ constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(c
|
||||
return cpy;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator==(const char *other) const noexcept {
|
||||
bool retval = true;
|
||||
for (auto i = 0u; i < m_buff.size() && (m_buff[i] || other[i]); ++i) {
|
||||
if (m_buff[i] != other[i]) {
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator==(const BasicString &other) const noexcept {
|
||||
if (len() != other.len()) {
|
||||
return false;
|
||||
}
|
||||
bool retval = true;
|
||||
std::size_t i = 0;
|
||||
while (i < m_buff.size() && (m_buff[i] || other.m_buff[i])) {
|
||||
@ -418,6 +437,11 @@ constexpr bool BasicString<SmallStringSize>::operator==(const BasicString &other
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator!=(const char *other) const noexcept {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator!=(const BasicString &other) const noexcept {
|
||||
return !operator==(other);
|
||||
|
4
deps/ox/src/ox/std/strops.hpp
vendored
4
deps/ox/src/ox/std/strops.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -54,7 +54,7 @@ constexpr auto ox_strlen(T str1) noexcept {
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(T1 str1, T2 str2) noexcept {
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
|
17
deps/ox/src/ox/std/typetraits.hpp
vendored
17
deps/ox/src/ox/std/typetraits.hpp
vendored
@ -3,7 +3,7 @@
|
||||
*
|
||||
* 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/.
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@ -138,6 +138,21 @@ constexpr bool is_class_v = is_class<T>();
|
||||
template<typename T>
|
||||
constexpr bool is_signed_v = integral_constant<bool, T(-1) < T(0)>::value;
|
||||
|
||||
template<typename T, std::size_t bits>
|
||||
concept Signed_c = is_signed_v<T> && sizeof(T) == 8 * bits;
|
||||
|
||||
template<typename T, std::size_t bits>
|
||||
concept Unsigned_c = !is_signed_v<T> && sizeof(T) == 8 * bits;
|
||||
|
||||
template<typename T, typename U>
|
||||
struct is_same: false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct is_same<T, T>: true_type {};
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr auto is_same_v = is_same<T, U>::value;
|
||||
|
||||
// enable_if ///////////////////////////////////////////////////////////////////
|
||||
|
||||
template<bool B, class T = void>
|
||||
|
Loading…
Reference in New Issue
Block a user