[ox] Cleanup

This commit is contained in:
Gary Talent 2024-05-08 23:35:05 -05:00
parent 47a6a410c4
commit 63486c23d4
20 changed files with 195 additions and 117 deletions

View File

@ -12,34 +12,66 @@
namespace ox { namespace ox {
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept { ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept {
const auto s1End = ox::strchr(buff, ';', buffLen); auto buffRaw = buff.data();
auto buffLen = buff.size();
size_t outSz{};
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) { if (!s1End) {
return OxError(1, "Could not read Claw header"); return OxError(1, "Could not read Claw header");
} }
const auto s1Size = static_cast<std::size_t>(s1End - buff); auto const fmtSz = static_cast<std::size_t>(s1End - buffRaw) + 1;
const String fmt(buff, s1Size); buffRaw += fmtSz;
buff += s1Size + 1; buffLen -= fmtSz;
buffLen -= s1Size + 1; outSz += fmtSz;
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
const auto s2End = ox::strchr(buff, ';', buffLen);
if (!s2End) { if (!s2End) {
return OxError(2, "Could not read Claw header"); return OxError(2, "Could not read Claw header");
} }
const auto s2Size = static_cast<std::size_t>(s2End - buff); auto const s2Size = static_cast<std::size_t>(s2End - buffRaw) + 1;
const String typeName(buff, s2Size); buffRaw += s2Size;
buff += s2Size + 1; buffLen -= s2Size;
buffLen -= s2Size + 1; outSz += s2Size;
auto const s3End = ox::strchr(buffRaw, ';', buffLen) + 1;
const auto s3End = ox::strchr(buff, ';', buffLen);
if (!s3End) { if (!s3End) {
return OxError(3, "Could not read Claw header"); return OxError(3, "Could not read Claw header");
} }
const auto s3Size = static_cast<std::size_t>(s3End - buff); auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
const String versionStr(buff, s3Size); buffRaw += s3Size;
buff += s3Size + 1; buffLen -= s3Size;
buffLen -= s3Size + 1; outSz += s3Size;
return {{buff.data() + fmtSz, outSz - fmtSz - 1}};
}
Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept {
auto buffRaw = buff.data();
auto buffLen = buff.size();
const auto s1End = ox::strchr(buffRaw, ';', buffLen);
if (!s1End) {
return OxError(1, "Could not read Claw header");
}
auto const s1Size = static_cast<std::size_t>(s1End - buffRaw);
StringView const fmt(buffRaw, s1Size);
buffRaw += s1Size + 1;
buffLen -= s1Size + 1;
auto const s2End = ox::strchr(buffRaw, ';', buffLen);
if (!s2End) {
return OxError(2, "Could not read Claw header");
}
auto const s2Size = static_cast<std::size_t>(s2End - buffRaw);
StringView const typeName(buffRaw, s2Size);
buffRaw += s2Size + 1;
buffLen -= s2Size + 1;
auto const s3End = ox::strchr(buffRaw, ';', buffLen);
if (!s3End) {
return OxError(3, "Could not read Claw header");
}
auto const s3Size = static_cast<std::size_t>(s3End - buffRaw);
StringView const versionStr(buffRaw, s3Size);
buffRaw += s3Size + 1;
buffLen -= s3Size + 1;
ClawHeader hdr; ClawHeader hdr;
if (fmt == "M2") { if (fmt == "M2") {
hdr.fmt = ClawFormat::Metal; hdr.fmt = ClawFormat::Metal;
@ -49,32 +81,21 @@ Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcep
return OxError(4, "Claw format does not match any supported format/version combo"); return OxError(4, "Claw format does not match any supported format/version combo");
} }
hdr.typeName = typeName; hdr.typeName = typeName;
if (auto r = ox::atoi(versionStr.c_str()); r.error == 0) { std::ignore = ox::atoi(versionStr).copyTo(hdr.typeVersion);
hdr.typeVersion = r.value; hdr.data = buffRaw;
}
hdr.data = buff;
hdr.dataSize = buffLen; hdr.dataSize = buffLen;
return hdr; return hdr;
} }
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept { Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept {
return readClawHeader(buff.data(), buff.size()); oxRequire(header, readClawHeader(buff));
return {{header.data, header.dataSize}};
} }
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept { Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept {
oxRequire(header, readClawHeader(buff, buffLen)); oxRequire(header, readClawHeader(buff));
Buffer out(header.dataSize); auto const [t, tdErr] = ts.getLoad(
ox::listcpy(out.data(), header.data, out.size()); header.typeName, header.typeVersion, header.typeParams);
return out;
}
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
return stripClawHeader(buff.data(), buff.size());
}
Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept {
oxRequire(header, readClawHeader(buff, buffSz));
auto const [t, tdErr] = ts.getLoad(header.typeName, header.typeVersion, header.typeParams);
if (tdErr) { if (tdErr) {
return OxError(3, "Could not load type descriptor"); return OxError(3, "Could not load type descriptor");
} }
@ -83,7 +104,7 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
{ {
ox::BufferReader br(header.data, header.dataSize); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); oxReturnError(model(&handler, &obj));
@ -92,7 +113,7 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
case ClawFormat::Organic: case ClawFormat::Organic:
{ {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader(header.data, header.dataSize); OrganicClawReader reader({header.data, header.dataSize});
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
oxReturnError(model(&handler, &obj)); oxReturnError(model(&handler, &obj));
return obj; return obj;
@ -106,8 +127,4 @@ Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz
return OxError(1); return OxError(1);
} }
Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept {
return readClaw(ts, buff.data(), buff.size());
}
} }

View File

@ -8,6 +8,7 @@
#pragma once #pragma once
#include <ox/std/span.hpp>
#include <ox/mc/read.hpp> #include <ox/mc/read.hpp>
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
#include <ox/oc/read.hpp> #include <ox/oc/read.hpp>
@ -31,17 +32,15 @@ struct ClawHeader {
std::size_t dataSize = 0; std::size_t dataSize = 0;
}; };
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept; ox::Result<ox::StringView> readClawTypeId(ox::BufferView buff) noexcept;
Result<ClawHeader> readClawHeader(const ox::Buffer &buff) noexcept; Result<ClawHeader> readClawHeader(ox::BufferView buff) noexcept;
Result<Buffer> stripClawHeader(const char *buff, std::size_t buffLen) noexcept; Result<BufferView> stripClawHeader(ox::BufferView buff) noexcept;
Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept;
template<typename T> template<typename T>
Error readClaw(const char *buff, std::size_t buffLen, T *val) { Error readClaw(ox::BufferView buff, T &val) {
oxRequire(header, readClawHeader(buff, buffLen)); oxRequire(header, readClawHeader(buff));
if (header.typeName != getModelTypeName<T>()) { if (header.typeName != getModelTypeName<T>()) {
return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch"); return OxError(Error_ClawTypeMismatch, "Claw Read: Type mismatch");
} }
@ -51,16 +50,16 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
switch (header.fmt) { switch (header.fmt) {
case ClawFormat::Metal: case ClawFormat::Metal:
{ {
ox::BufferReader br(header.data, header.dataSize); ox::BufferReader br({header.data, header.dataSize});
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
return model(&handler, val); return model(&handler, &val);
} }
case ClawFormat::Organic: case ClawFormat::Organic:
{ {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
OrganicClawReader reader(header.data, header.dataSize); OrganicClawReader reader(header.data, header.dataSize);
return model(&reader, val); return model(&reader, &val);
#else #else
break; break;
#endif #endif
@ -72,24 +71,12 @@ Error readClaw(const char *buff, std::size_t buffLen, T *val) {
} }
template<typename T> template<typename T>
Result<T> readClaw(const char *buff, std::size_t buffLen) { Result<T> readClaw(ox::BufferView buff) {
T val; Result<T> val;
oxReturnError(readClaw(buff, buffLen, &val)); oxReturnError(readClaw(buff, val.value));
return val; return val;
} }
template<typename T> Result<ModelObject> readClaw(TypeStore &ts, BufferView buff) noexcept;
Error readClaw(const Buffer &buff, T *val) {
return readClaw<T>(buff.data(), buff.size(), val);
}
template<typename T>
Result<T> readClaw(const Buffer &buff) {
return readClaw<T>(buff.data(), buff.size());
}
Result<ModelObject> readClaw(TypeStore &ts, const char *buff, std::size_t buffSz) noexcept;
Result<ModelObject> readClaw(TypeStore &ts, const Buffer &buff) noexcept;
} }

View File

@ -10,5 +10,6 @@ target_link_libraries(
add_test("[ox/claw] ClawHeaderReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader) add_test("[ox/claw] ClawHeaderReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader)
add_test("[ox/claw] ClawHeaderReader2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader2) add_test("[ox/claw] ClawHeaderReader2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReader2)
add_test("[ox/claw] ClawHeaderReadTypeId" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawHeaderReadTypeId)
add_test("[ox/claw] ClawWriter" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawWriter) add_test("[ox/claw] ClawWriter" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawWriter)
add_test("[ox/claw] ClawReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawReader) add_test("[ox/claw] ClawReader" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ClawTest ClawReader)

View File

@ -109,7 +109,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader", "ClawHeaderReader",
[] { [] {
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;"); constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1); auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
oxAssert(err, "Error parsing header"); oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header", "Type name wrong");
@ -121,7 +121,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
"ClawHeaderReader2", "ClawHeaderReader2",
[] { [] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;"); constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1); auto [ch, err] = ox::readClawHeader({hdr.c_str(), hdr.len() + 1});
oxAssert(err, "Error parsing header"); oxAssert(err, "Error parsing header");
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong"); oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong"); oxAssert(ch.typeName == "com.drinkingtea.ox.claw.test.Header2", "Type name wrong");
@ -129,6 +129,16 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
return OxError(0); return OxError(0);
} }
}, },
{
"ClawHeaderReadTypeId",
[] {
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;awefawf");
constexpr auto expected = ox::StringLiteral("com.drinkingtea.ox.claw.test.Header2;3");
oxRequire(actual, ox::readClawTypeId({hdr.data(), hdr.len() + 1}));
oxExpect(actual, expected);
return ox::Error{};
}
},
{ {
"ClawWriter", "ClawWriter",
[] { [] {
@ -156,7 +166,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
testIn.Struct.String = "Test String 2"; testIn.Struct.String = "Test String 2";
const auto [buff, err] = ox::writeMC(testIn); const auto [buff, err] = ox::writeMC(testIn);
oxAssert(err, "writeClaw failed"); oxAssert(err, "writeClaw failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readClaw failed"); oxAssert(ox::readMC(buff, testOut), "readClaw failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n"; //std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch");

View File

@ -185,7 +185,7 @@ constexpr Result<I> decodeInteger(Reader_c auto&rdr, std::size_t *bytesRead) noe
template<typename I> template<typename I>
Result<I> decodeInteger(McInt m) noexcept { Result<I> decodeInteger(McInt m) noexcept {
std::size_t bytesRead{}; std::size_t bytesRead{};
BufferReader br(reinterpret_cast<const char*>(m.data), 9); BufferReader br({reinterpret_cast<const char*>(m.data), 9});
return decodeInteger<I>(br, &bytesRead); return decodeInteger<I>(br, &bytesRead);
} }

View File

@ -524,25 +524,20 @@ constexpr void MetalClawReaderTemplate<Reader>::nextField() noexcept {
using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>; using MetalClawReader = MetalClawReaderTemplate<ox::BufferReader>;
template<typename T> template<typename T>
Error readMC(const char *buff, std::size_t buffLen, T *val) noexcept { Error readMC(ox::BufferView buff, T &val) noexcept {
BufferReader br(buff, buffLen); BufferReader br(buff);
MetalClawReader reader(br); MetalClawReader reader(br);
ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader); ModelHandlerInterface<MetalClawReader, ox::OpType::Read> handler(&reader);
return model(&handler, val); return model(&handler, &val);
} }
template<typename T> template<typename T>
Result<T> readMC(const char *buff, std::size_t buffLen) noexcept { Result<T> readMC(ox::BufferView buff) noexcept {
T val; Result<T> val;
oxReturnError(readMC(buff, buffLen, &val)); oxReturnError(readMC(buff, val.value));
return val; return val;
} }
template<typename T>
Result<T> readMC(const Buffer &buff) noexcept {
return readMC<T>(buff.data(), buff.size());
}
extern template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>; extern template class ModelHandlerInterface<MetalClawReaderTemplate<BufferReader>>;
} }

View File

@ -143,7 +143,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
// run tests // run tests
const auto [buff, err] = ox::writeMC(testIn); const auto [buff, err] = ox::writeMC(testIn);
oxAssert(err, "writeMC failed"); oxAssert(err, "writeMC failed");
oxAssert(ox::readMC(buff.data(), buff.size(), &testOut), "readMC failed"); oxAssert(ox::readMC(buff, testOut), "readMC failed");
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n"; //std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
@ -319,7 +319,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type)); oxReturnError(testOut.setType(type));
oxAssert(ox::readMC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed"); oxAssert(ox::readMC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.at("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.at("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
oxAssert(testOut.at("IString").unwrap()->get<ox::String>() == testIn.IString.c_str(), "testOut.String failed"); oxAssert(testOut.at("IString").unwrap()->get<ox::String>() == testIn.IString.c_str(), "testOut.String failed");
@ -369,7 +369,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
ox::TypeStore typeStore; ox::TypeStore typeStore;
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn); const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(typeErr, "Descriptor write failed"); oxAssert(typeErr, "Descriptor write failed");
ox::BufferReader br(dataBuff, dataBuffLen); ox::BufferReader br({dataBuff, dataBuffLen});
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br, oxReturnError(ox::walkModel<ox::MetalClawReader>(type, br,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { [](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
//std::cout << f.fieldName.c_str() << '\n'; //std::cout << f.fieldName.c_str() << '\n';

View File

@ -37,12 +37,12 @@ constexpr auto buildTypeId() noexcept {
static constexpr auto buildTypeId(CRStringView name, int version, static constexpr auto buildTypeId(CRStringView name, int version,
const TypeParamPack &typeParams = {}) noexcept { const TypeParamPack &typeParams = {}) noexcept {
String tp; String tp;
if (typeParams.size()) { if (!typeParams.empty()) {
tp = "#"; tp = "#";
for (const auto &p : typeParams) { for (const auto &p : typeParams) {
tp += p + ","; tp += p + ",";
} }
tp = tp.substr(0, tp.len() - 1); tp.resize(tp.len() - 1);
tp += "#"; tp += "#";
} }
return ox::sfmt("{}{};{}", name, tp, version); return ox::sfmt("{}{};{}", name, tp, version);

View File

@ -97,6 +97,7 @@ struct TypeInfoCatcher {
}; };
template<typename T> template<typename T>
[[nodiscard]]
constexpr int getModelTypeVersion(T *val) noexcept { constexpr int getModelTypeVersion(T *val) noexcept {
TypeInfoCatcher nc; TypeInfoCatcher nc;
std::ignore = model(&nc, val); std::ignore = model(&nc, val);
@ -104,6 +105,7 @@ constexpr int getModelTypeVersion(T *val) noexcept {
} }
template<typename T> template<typename T>
[[nodiscard]]
constexpr int getModelTypeVersion() noexcept { constexpr int getModelTypeVersion() noexcept {
std::allocator<T> a; std::allocator<T> a;
const auto t = a.allocate(1); const auto t = a.allocate(1);
@ -113,6 +115,7 @@ constexpr int getModelTypeVersion() noexcept {
} }
template<typename T> template<typename T>
[[nodiscard]]
consteval int requireModelTypeVersion() noexcept { consteval int requireModelTypeVersion() noexcept {
constexpr auto version = getModelTypeVersion<T>(); constexpr auto version = getModelTypeVersion<T>();
static_assert(version != 0, "TypeVersion is required"); static_assert(version != 0, "TypeVersion is required");
@ -120,6 +123,7 @@ consteval int requireModelTypeVersion() noexcept {
} }
template<typename T, typename Str = const char*> template<typename T, typename Str = const char*>
[[nodiscard]]
constexpr Str getModelTypeName(T *val) noexcept { constexpr Str getModelTypeName(T *val) noexcept {
TypeNameCatcher nc; TypeNameCatcher nc;
std::ignore = model(&nc, val); std::ignore = model(&nc, val);
@ -127,6 +131,7 @@ constexpr Str getModelTypeName(T *val) noexcept {
} }
template<typename T, typename Str = const char*> template<typename T, typename Str = const char*>
[[nodiscard]]
constexpr Str getModelTypeName() noexcept { constexpr Str getModelTypeName() noexcept {
std::allocator<T> a; std::allocator<T> a;
auto t = a.allocate(1); auto t = a.allocate(1);
@ -136,8 +141,10 @@ constexpr Str getModelTypeName() noexcept {
} }
template<typename T> template<typename T>
[[nodiscard]]
consteval auto requireModelTypeName() noexcept { consteval auto requireModelTypeName() noexcept {
constexpr auto name = getModelTypeName<T>(); constexpr auto name = getModelTypeName<T>();
static_assert(ox::StringView{name}.len(), "Type lacks required TypeName");
return name; return name;
} }

View File

@ -101,7 +101,7 @@ class TypeStore {
} }
protected: protected:
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView) noexcept { virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::StringView) noexcept {
return OxError(1); return OxError(1);
} }

View File

@ -246,18 +246,18 @@ Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcep
return OxError(0); return OxError(0);
} }
Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept { Error readOC(BufferView buff, auto &val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors. // OrganicClawReader constructor can throw, but readOC should return its errors.
try { try {
Json::Value doc; Json::Value doc;
Json::CharReaderBuilder parserBuilder; Json::CharReaderBuilder parserBuilder;
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader()); auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(buff, buff + buffSize, &doc, nullptr)) { if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
return OxError(1, "Could not parse JSON"); return OxError(1, "Could not parse JSON");
} }
OrganicClawReader reader(buff, buffSize); OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(&reader); ModelHandlerInterface handler(&reader);
return model(&handler, val); return model(&handler, &val);
} catch (const Error &err) { } catch (const Error &err) {
return err; return err;
} catch (...) { } catch (...) {
@ -266,20 +266,15 @@ Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept {
} }
template<typename T> template<typename T>
Result<T> readOC(const char *json, std::size_t jsonLen) noexcept { Result<T> readOC(BufferView buff) noexcept {
T val; Result<T> val;
oxReturnError(readOC(json, jsonLen, &val)); oxReturnError(readOC(buff, val.value));
return val; return val;
} }
template<typename T> template<typename T>
Result<T> readOC(const char *json) noexcept { Result<T> readOC(ox::StringView json) noexcept {
return readOC<T>(json, ox::strlen(json)); return readOC<T>(ox::BufferView{json.data(), json.len()});
}
template<typename T>
Result<T> readOC(const Buffer &buff) noexcept {
return readOC<T>(buff.data(), buff.size());
} }
} }

View File

@ -211,7 +211,7 @@ const std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(type.error, "Descriptor write failed"); oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut; ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value)); oxReturnError(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed"); oxAssert(ox::readOC(dataBuff, testOut), "Data read failed");
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed"); oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed"); oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");

View File

@ -10,6 +10,7 @@
#include "error.hpp" #include "error.hpp"
#include "reader.hpp" #include "reader.hpp"
#include "span.hpp"
#include "vector.hpp" #include "vector.hpp"
#include "writer.hpp" #include "writer.hpp"
@ -18,6 +19,7 @@ namespace ox {
extern template class Vector<char>; extern template class Vector<char>;
using Buffer = Vector<char>; using Buffer = Vector<char>;
using BufferView = SpanView<char>;
class BufferWriter { class BufferWriter {
private: private:
@ -174,10 +176,7 @@ class BufferReader {
char const* m_buff = nullptr; char const* m_buff = nullptr;
public: public:
constexpr explicit BufferReader(char const*buff, std::size_t sz) noexcept: constexpr explicit BufferReader(ox::BufferView buffer) noexcept:
m_size(sz), m_buff(buff) {}
constexpr explicit BufferReader(ox::Buffer const&buffer) noexcept:
m_size(buffer.size()), m_buff(buffer.data()) {} m_size(buffer.size()), m_buff(buffer.data()) {}
constexpr ox::Result<char> peek() const noexcept { constexpr ox::Result<char> peek() const noexcept {

View File

@ -234,6 +234,22 @@ struct [[nodiscard]] Result {
return value; return value;
} }
template<typename U = T>
constexpr ox::Result<U> to() & noexcept {
if (error) [[unlikely]] {
return error;
}
return U(value);
}
template<typename U = T>
constexpr ox::Result<U> to() && noexcept {
if (error) [[unlikely]] {
return error;
}
return U(std::move(value));
}
template<typename U = T> template<typename U = T>
constexpr ox::Result<U> to(auto const&f) & noexcept { constexpr ox::Result<U> to(auto const&f) & noexcept {
if (error) [[unlikely]] { if (error) [[unlikely]] {

View File

@ -40,12 +40,17 @@ constexpr StringView toStringView(const char *s) noexcept {
template<bool force = false, std::size_t size> template<bool force = false, std::size_t size>
constexpr StringView toStringView(const IString<size> &s) noexcept { constexpr StringView toStringView(const IString<size> &s) noexcept {
return s.c_str(); return s;
}
template<bool force = false>
constexpr StringView toStringView(ox::StringLiteral s) noexcept {
return s;
} }
template<bool force = false, std::size_t size> template<bool force = false, std::size_t size>
constexpr StringView toStringView(const BasicString<size> &s) noexcept { constexpr StringView toStringView(const BasicString<size> &s) noexcept {
return s.c_str(); return s;
} }
#if __has_include(<string>) #if __has_include(<string>)

View File

@ -19,8 +19,8 @@ template<typename T>
class SpanView { class SpanView {
private: private:
const T *m_items{}; T const*m_items{};
const std::size_t m_size{}; std::size_t m_size{};
public: public:
using value_type = T; using value_type = T;
@ -106,6 +106,16 @@ class SpanView {
return m_items[i]; return m_items[i];
} }
constexpr SpanView operator+(size_t i) const noexcept {
return {m_items + i, m_size - i};
}
constexpr SpanView operator+=(size_t i) noexcept {
m_items += i;
m_size -= i;
return *this;
}
[[nodiscard]] [[nodiscard]]
constexpr T const*data() const noexcept { constexpr T const*data() const noexcept {
return m_items; return m_items;

View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include "bit.hpp"
#include "error.hpp" #include "error.hpp"
#include "math.hpp"
#include "types.hpp" #include "types.hpp"
#include "writer.hpp" #include "writer.hpp"
@ -39,6 +41,19 @@ constexpr ox::Error writeItoa(Integer v, ox::Writer_c auto &writer) noexcept {
return {}; return {};
} }
constexpr ox::Error writeF32toa(float const v, ox::Writer_c auto &writer) noexcept {
auto const raw = std::bit_cast<uint32_t>(v);
if (raw >> 31) {
oxReturnError(writer.put('-'));
}
auto const mantissa = raw & onMask<uint32_t>(23);
auto const exp = ((raw >> 23) & 0xff) - 126;
auto const p = ox::pow(2u, exp);
auto const out = p * mantissa;
oxReturnError(writeItoa(out, writer));
return {};
}
} }
#include "istring.hpp" #include "istring.hpp"

View File

@ -192,6 +192,10 @@ class BasicString {
[[nodiscard]] [[nodiscard]]
constexpr BasicString substr(std::size_t begin, std::size_t end) const noexcept; constexpr BasicString substr(std::size_t begin, std::size_t end) const noexcept;
constexpr void resize(size_t sz) noexcept {
m_buff.resize(sz);
}
[[nodiscard]] [[nodiscard]]
constexpr const char *data() const noexcept { constexpr const char *data() const noexcept {
return m_buff.data(); return m_buff.data();

View File

@ -11,6 +11,7 @@ add_test("[ox/std] ox_memcmp ABCDEFG != HIJKLMN" ${CMAKE_RUNTIME_OUTPUT_DIRECTOR
add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HIJKLMN != ABCDEFG") add_test("[ox/std] ox_memcmp HIJKLMN != ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HIJKLMN != ABCDEFG")
add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFG == ABCDEFG") add_test("[ox/std] ox_memcmp ABCDEFG == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFG == ABCDEFG")
add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFGHI == ABCDEFG") add_test("[ox/std] ox_memcmp ABCDEFGHI == ABCDEFG" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ABCDEFGHI == ABCDEFG")
#add_test("[ox/std] ftoa" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "ftoa")
add_test("[ox/std] itoa" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "itoa") add_test("[ox/std] itoa" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "itoa")
add_test("[ox/std] BString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "BString") add_test("[ox/std] BString" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "BString")
add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String") add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String")

View File

@ -26,6 +26,16 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
return OxError(0); return OxError(0);
} }
}, },
{
"ftoa",
[]() {
ox::Array<char, 10> buff;
ox::CharBuffWriter bw(buff);
oxAssert(ox::writeF32toa(5, bw), "ox::writeItoa returned Error");
oxExpect(ox::StringView(buff.data()), ox::StringView("5"));
return ox::Error{};
}
},
{ {
"itoa", "itoa",
[]() { []() {
@ -109,7 +119,9 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
oxAssert(ox::StringView("Write") != ox::String(""), "String / StringView comparison broken"); oxAssert(ox::StringView("Write") != ox::String(""), "String / StringView comparison broken");
oxAssert(ox::String("Write") != ox::StringView(""), "String / StringView comparison broken"); oxAssert(ox::String("Write") != ox::StringView(""), "String / StringView comparison broken");
oxAssert(ox::String("Write") == ox::StringView("Write"), "String / StringView comparison broken"); oxAssert(ox::String("Write") == ox::StringView("Write"), "String / StringView comparison broken");
oxAssert(ox::String(ox::StringView("Write")) == ox::StringView("Write"), "String / StringView comparison broken"); oxAssert(
ox::String(ox::StringView("Write")) == ox::StringView("Write"),
"String / StringView comparison broken");
return OxError(0); return OxError(0);
} }
}, },
@ -119,7 +131,7 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
ox::Vector<int> v; ox::Vector<int> v;
oxAssert(v.size() == 0, "Initial Vector size not 0"); oxAssert(v.size() == 0, "Initial Vector size not 0");
oxAssert(v.empty(), "Vector::empty() is broken"); oxAssert(v.empty(), "Vector::empty() is broken");
auto insertTest = [&v](int val, [[maybe_unused]] std::size_t size) { auto insertTest = [&v](int val, std::size_t size) {
v.push_back(val); v.push_back(val);
oxReturnError(OxError(v.size() != size, "Vector size incorrect")); oxReturnError(OxError(v.size() != size, "Vector size incorrect"));
oxReturnError(OxError(v[v.size() - 1] != val, "Vector value wrong")); oxReturnError(OxError(v[v.size() - 1] != val, "Vector value wrong"));
@ -152,7 +164,11 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
[] { [] {
using BA = ox::Array<char, 4>; using BA = ox::Array<char, 4>;
const auto actual = ox::serialize<uint32_t>(256).unwrap(); const auto actual = ox::serialize<uint32_t>(256).unwrap();
oxOutf("[{}, {}, {}, {}]", static_cast<int>(actual[0]), static_cast<int>(actual[1]), static_cast<int>(actual[2]), static_cast<int>(actual[3])); oxOutf("[{}, {}, {}, {}]",
static_cast<int>(actual[0]),
static_cast<int>(actual[1]),
static_cast<int>(actual[2]),
static_cast<int>(actual[3]));
oxExpect(ox::serialize<int32_t>(4).unwrap(), BA({4, 0, 0, 0})); oxExpect(ox::serialize<int32_t>(4).unwrap(), BA({4, 0, 0, 0}));
oxExpect(ox::serialize<int32_t>(256).unwrap(), BA({0, 1, 0, 0})); oxExpect(ox::serialize<int32_t>(256).unwrap(), BA({0, 1, 0, 0}));
oxExpect(ox::serialize<int32_t>(257).unwrap(), BA({1, 1, 0, 0})); oxExpect(ox::serialize<int32_t>(257).unwrap(), BA({1, 1, 0, 0}));