[ox] Cleanup serialization writers, make MC and Claw use Writer_c
This commit is contained in:
parent
6f5f2c7219
commit
2c8e073172
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -139,7 +139,7 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
// This test doesn't confirm much, but it does show that the writer
|
||||
// doesn't segfault
|
||||
TestStruct ts;
|
||||
oxReturnError(ox::writeClaw(&ts, ox::ClawFormat::Metal));
|
||||
oxReturnError(ox::writeClaw(ts, ox::ClawFormat::Metal));
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
50
deps/ox/src/ox/claw/write.hpp
vendored
50
deps/ox/src/ox/claw/write.hpp
vendored
@ -14,6 +14,7 @@
|
||||
#endif
|
||||
#include <ox/std/buffer.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/stringview.hpp>
|
||||
|
||||
#include "format.hpp"
|
||||
|
||||
@ -27,7 +28,11 @@ struct TypeInfoCatcher {
|
||||
int version = 0;
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int v = T::TypeVersion, const Vector<String>& = {}, std::size_t = 0) noexcept {
|
||||
constexpr void setTypeInfo(
|
||||
const char *name = T::TypeName,
|
||||
int v = T::TypeVersion,
|
||||
const Vector<String>& = {},
|
||||
std::size_t = 0) noexcept {
|
||||
this->name = name;
|
||||
this->version = v;
|
||||
}
|
||||
@ -53,57 +58,64 @@ struct type_version<T, decltype((void) T::TypeVersion, -1)> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr const char *getTypeName(T *t) noexcept {
|
||||
constexpr const char *getTypeName(const T *t) noexcept {
|
||||
TypeInfoCatcher tnc;
|
||||
oxIgnoreError(model(&tnc, t));
|
||||
return tnc.name;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr int getTypeVersion(T *t) noexcept {
|
||||
constexpr int getTypeVersion(const T *t) noexcept {
|
||||
TypeInfoCatcher tnc;
|
||||
oxIgnoreError(model(&tnc, t));
|
||||
return tnc.version;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
|
||||
String out;
|
||||
ox::Error writeClawHeader(Writer_c auto &writer, T *t, ClawFormat fmt) noexcept {
|
||||
switch (fmt) {
|
||||
case ClawFormat::Metal:
|
||||
out += "M2;";
|
||||
oxReturnError(write(&writer, "M2;"));
|
||||
break;
|
||||
case ClawFormat::Organic:
|
||||
out += "O1;";
|
||||
oxReturnError(write(&writer, "O1;"));
|
||||
break;
|
||||
default:
|
||||
return OxError(1);
|
||||
}
|
||||
out += detail::getTypeName(t);
|
||||
out += ";";
|
||||
oxReturnError(write(&writer, detail::getTypeName(t)));
|
||||
oxReturnError(writer.put(';'));
|
||||
const auto tn = detail::getTypeVersion(t);
|
||||
if (tn > -1) {
|
||||
out += tn;
|
||||
oxReturnError(ox::itoa(tn, writer));
|
||||
}
|
||||
out += ";";
|
||||
return out;
|
||||
oxReturnError(writer.put(';'));
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result<Buffer> writeClaw(auto *t, ClawFormat fmt = ClawFormat::Metal) {
|
||||
oxRequire(header, detail::writeClawHeader(t, fmt));
|
||||
Result<Buffer> writeClaw(
|
||||
auto &t,
|
||||
ClawFormat fmt = ClawFormat::Metal,
|
||||
std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||
Buffer out(buffReserveSz);
|
||||
BufferWriter bw(&out, 0);
|
||||
oxReturnError(detail::writeClawHeader(bw, &t, fmt));
|
||||
#ifdef OX_USE_STDLIB
|
||||
oxRequire(data, fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t));
|
||||
if (fmt == ClawFormat::Metal) {
|
||||
oxReturnError(writeMC(bw, t));
|
||||
} else if (fmt == ClawFormat::Organic) {
|
||||
oxRequire(data, writeOC(t));
|
||||
oxReturnError(bw.write(data.data(), data.size()));
|
||||
}
|
||||
#else
|
||||
if (fmt != ClawFormat::Metal) {
|
||||
return OxError(1, "OC is not supported in this build");
|
||||
}
|
||||
oxRequire(data, writeMC(t));
|
||||
oxReturnError(writeMC(bw, t));
|
||||
#endif
|
||||
Buffer out(header.len() + data.size());
|
||||
memcpy(out.data(), header.data(), header.len());
|
||||
memcpy(out.data() + header.len(), data.data(), data.size());
|
||||
out.resize(bw.tellp());
|
||||
return out;
|
||||
}
|
||||
|
||||
|
2
deps/ox/src/ox/mc/write.hpp
vendored
2
deps/ox/src/ox/mc/write.hpp
vendored
@ -31,7 +31,7 @@ template<Writer_c Writer>
|
||||
class MetalClawWriter {
|
||||
|
||||
private:
|
||||
ox::Vector<uint8_t, 16> m_presenceMapBuff;
|
||||
ox::Vector<uint8_t, 16> m_presenceMapBuff{};
|
||||
FieldBitmap m_fieldPresence;
|
||||
int m_field = 0;
|
||||
int m_unionIdx = -1;
|
||||
|
8
deps/ox/src/ox/oc/test/tests.cpp
vendored
8
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -132,7 +132,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
// This test doesn't confirm much, but it does show that the writer
|
||||
// doesn't segfault
|
||||
TestStruct ts;
|
||||
return ox::writeOC(&ts).error;
|
||||
return ox::writeOC(ts).error;
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -153,7 +153,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
|
||||
auto [oc, writeErr] = ox::writeOC(&testIn);
|
||||
auto [oc, writeErr] = ox::writeOC(testIn);
|
||||
oxAssert(writeErr, "writeOC failed");
|
||||
oxOutf("{}\n", oc.data());
|
||||
auto [testOut, readErr] = ox::readOC<TestStruct>(oc.data());
|
||||
@ -205,7 +205,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(&testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
@ -254,7 +254,7 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
|
||||
auto [oc, ocErr] = ox::writeOC(&testIn);
|
||||
auto [oc, ocErr] = ox::writeOC(testIn);
|
||||
oxAssert(ocErr, "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
|
6
deps/ox/src/ox/oc/write.hpp
vendored
6
deps/ox/src/ox/oc/write.hpp
vendored
@ -24,7 +24,7 @@ namespace ox {
|
||||
|
||||
class OrganicClawWriter {
|
||||
|
||||
friend Result<Buffer> writeOC(auto *val) noexcept;
|
||||
friend Result<Buffer> writeOC(auto &val) noexcept;
|
||||
|
||||
protected:
|
||||
Json::Value m_json;
|
||||
@ -242,10 +242,10 @@ Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcep
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Result<Buffer> writeOC(auto *val) noexcept {
|
||||
Result<Buffer> writeOC(auto &val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
ModelHandlerInterface handler(&writer);
|
||||
oxReturnError(model(&handler, val));
|
||||
oxReturnError(model(&handler, &val));
|
||||
Json::StreamWriterBuilder jsonBuilder;
|
||||
const auto str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
Buffer buff(str.size() + 1);
|
||||
|
8
deps/ox/src/ox/std/buffer.hpp
vendored
8
deps/ox/src/ox/std/buffer.hpp
vendored
@ -60,7 +60,7 @@ class BufferWriter {
|
||||
}
|
||||
|
||||
constexpr ox::Error put(char val) noexcept {
|
||||
if (m_it >= m_buff.size()) [[unlikely]] {
|
||||
if (m_it >= m_buff.size()) {
|
||||
m_buff.resize(m_buff.size() + 1);
|
||||
}
|
||||
m_buff[m_it] = val;
|
||||
@ -98,9 +98,9 @@ class CharBuffWriter {
|
||||
|
||||
public:
|
||||
template<std::size_t sz>
|
||||
explicit constexpr CharBuffWriter(ox::Array<char, sz> *buff) noexcept:
|
||||
m_cap(buff->size()),
|
||||
m_buff(buff->data()) {
|
||||
explicit constexpr CharBuffWriter(ox::Array<char, sz> &buff) noexcept:
|
||||
m_cap(buff.size()),
|
||||
m_buff(buff.data()) {
|
||||
}
|
||||
|
||||
explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) {
|
||||
|
2
deps/ox/src/ox/std/serialize.hpp
vendored
2
deps/ox/src/ox/std/serialize.hpp
vendored
@ -87,7 +87,7 @@ constexpr ox::Error serialize(Writer_c auto *buff, T val) noexcept requires(is_i
|
||||
template<typename T>
|
||||
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
|
||||
ox::Array<char, sizeof(T)> out = {};
|
||||
CharBuffWriter w(&out);
|
||||
CharBuffWriter w(out);
|
||||
oxReturnError(serialize(&w, in));
|
||||
return out;
|
||||
};
|
||||
|
2
deps/ox/src/ox/std/stringview.hpp
vendored
2
deps/ox/src/ox/std/stringview.hpp
vendored
@ -280,7 +280,7 @@ using CRStringView = const StringView&;
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
|
37
deps/ox/src/ox/std/strops.hpp
vendored
37
deps/ox/src/ox/std/strops.hpp
vendored
@ -12,6 +12,7 @@
|
||||
#include "math.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr char *ox_strcpy(T1 dest, T2 src) noexcept {
|
||||
@ -125,6 +126,42 @@ constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen
|
||||
return retval;
|
||||
}
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename Integer>
|
||||
constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
oxReturnError(writer.put('-'));
|
||||
++it;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
oxReturnError(writer.put(static_cast<char>(start + digit)));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 0 is a special case
|
||||
oxReturnError(writer.put('0'));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
|
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@ -11,6 +11,7 @@ add_test("[ox/std] ox_memcmp ABCDEFG != HIJKLMN" StdTest "ABCDEFG != HIJKLMN")
|
||||
add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" StdTest "HIJKLMN != ABCDEFG")
|
||||
add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" StdTest "ABCDEFG == ABCDEFG")
|
||||
add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" StdTest "ABCDEFGHI == ABCDEFG")
|
||||
add_test("[ox/std] itoa" StdTest "itoa")
|
||||
add_test("[ox/std] BString" StdTest "BString")
|
||||
add_test("[ox/std] String" StdTest "String")
|
||||
add_test("[ox/std] Vector" StdTest "Vector")
|
||||
|
16
deps/ox/src/ox/std/test/tests.cpp
vendored
16
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -25,6 +25,22 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
"itoa",
|
||||
[]() {
|
||||
ox::Array<char, 10> buff;
|
||||
ox::CharBuffWriter bw(buff);
|
||||
oxAssert(ox::itoa(5, bw), "ox::itoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("5"));
|
||||
oxReturnError(bw.seekp(0));
|
||||
oxAssert(ox::itoa(50, bw), "ox::itoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("50"));
|
||||
oxReturnError(bw.seekp(0));
|
||||
oxAssert(ox::itoa(500, bw), "ox::itoa returned Error");
|
||||
oxExpect(ox::StringView(buff.data()), ox::StringView("500"));
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"ABCDEFG != HIJKLMN",
|
||||
[]() {
|
||||
|
Loading…
Reference in New Issue
Block a user