[ox] Move header files to include directory

This commit is contained in:
2026-05-06 00:27:22 -05:00
parent 69957bd7b2
commit bd792a0d25
161 changed files with 93 additions and 153 deletions
+313
View File
@@ -0,0 +1,313 @@
/*
* Copyright 2015 - 2025 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/def.hpp>
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
#include <json/json.h>
OX_ALLOW_UNSAFE_BUFFERS_END
#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>
#include <ox/std/buffer.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/memops.hpp>
#include <ox/std/memory.hpp>
#include <ox/std/string.hpp>
#include <ox/std/uuid.hpp>
namespace ox {
class OrganicClawReader {
private:
Json::Value m_json;
Json::ArrayIndex m_fieldIt = 0;
int const m_unionIdx = -1;
public:
OrganicClawReader() noexcept = default;
OrganicClawReader(uint8_t const *buff, size_t buffSize);
OrganicClawReader(CString json, size_t buffSize);
explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept;
Error field(CString key, bool *val) noexcept;
// array handler
template<typename T>
Error field(CString key, T *val, size_t len) noexcept;
template<typename T>
Error field(CString, HashMap<String, T> *val) noexcept;
template<typename T>
Error field(CString key, T *val) noexcept;
template<typename U, bool force = false>
Error field(CString key, UnionView<U, force> val) noexcept;
template<size_t L>
Error field(CString key, BasicString<L> *val) noexcept;
template<size_t L>
Error field(CString key, IString<L> *val) noexcept;
Error fieldCString(CString key, char *val, size_t buffLen) noexcept;
Error fieldCString(CString key, char **val) noexcept;
Error fieldCString(CString key, char **val, size_t buffLen) noexcept;
Error field(CString key, UUID *val) noexcept;
/**
* Reads an array length from the current location in the buffer.
* @param key
* @param pass indicates that the parsing should iterate past the array length
*/
Result<size_t> arrayLength(CString key, bool pass = true) noexcept;
/**
* Reads an string length from the current location in the buffer.
*/
[[nodiscard]]
size_t stringLength(CString key) noexcept;
template<typename T = void>
constexpr Error setTypeInfo() noexcept {
return {};
}
template<typename T = void>
constexpr Error setTypeInfo(CString) noexcept {
return {};
}
template<typename T = void>
constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}) noexcept {
return {};
}
template<typename T = void>
constexpr Error setTypeInfo(CString, int, const Vector<String>& = {}, size_t = {}) noexcept {
return {};
}
/**
* Returns a OrganicClawReader to parse a child object.
*/
[[nodiscard]]
OrganicClawReader child(CString key, int unionIdx = -1) noexcept;
// compatibility stub
constexpr void nextField() noexcept {}
[[nodiscard]]
bool fieldPresent(CString key) noexcept;
[[nodiscard]]
int whichFieldPresent(CString name, const ModelUnion &u) const noexcept;
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Read;
}
private:
[[nodiscard]]
Json::Value &value(CString key) noexcept;
[[nodiscard]]
bool targetValid() const noexcept;
};
template<typename T>
Error OrganicClawReader::field(CString key, T *val) noexcept {
Error err{};
try {
if constexpr (is_integer_v<T>) {
if (targetValid()) {
auto const &jv = value(key);
auto const rightType = sizeof(T) == 8 ?
(is_signed_v<T> ? jv.isInt64() : jv.isUInt64()) :
(is_signed_v<T> ? jv.isInt() : jv.isUInt());
if (jv.empty()) {
*val = 0;
} else if (rightType) {
if constexpr(is_signed_v<T>) {
*val = static_cast<T>(jv.asInt64());
} else {
*val = static_cast<T>(jv.asUInt64());
}
} else {
err = Error{1, "Type mismatch"};
}
}
} else if constexpr (isVector_v<T>) {
auto const &srcVal = value(key);
auto const srcSize = srcVal.size();
OX_RETURN_ERROR(resizeVector(*val, srcSize));
err = field(key, val->data(), val->size());
} else if constexpr (isArray_v<T>) {
auto const &srcVal = value(key);
auto const srcSize = srcVal.size();
if (srcSize > val->size()) {
err = Error{1, "Input array is too long"};
} else {
err = field(key, val->data(), val->size());
}
} else if (targetValid()) {
auto const &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key);
ModelHandlerInterface handler(reader);
err = model(&handler, val);
} else {
err = Error{1, "Type mismatch"};
}
}
} catch (Json::LogicError const &e) {
err = Error{1, "error reading JSON data"};
}
++m_fieldIt;
return err;
}
template<typename U, bool force>
Error OrganicClawReader::field(CString const key, UnionView<U, force> val) noexcept {
Error err{};
if (targetValid()) {
auto const &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key, val.idx());
ModelHandlerInterface handler(reader);
err = model(&handler, val.get());
} else {
err = Error{1, "Type mismatch"};
}
}
++m_fieldIt;
return err;
}
template<size_t L>
Error OrganicClawReader::field(CString const key, BasicString<L> *val) noexcept {
Error err{};
if (targetValid()) {
auto const &jv = value(key);
if (jv.empty()) {
*val = BasicString<L>{};
} else if (jv.isString()) {
*val = jv.asString().c_str();
} else {
err = Error{1, "Type mismatch"};
}
}
++m_fieldIt;
return err;
}
template<size_t L>
Error OrganicClawReader::field(CString const key, IString<L> *val) noexcept {
Error err{};
if (targetValid()) {
auto const &jv = value(key);
if (jv.empty()) {
*val = IString<L>{};
} else if (jv.isString()) {
*val = jv.asString().c_str();
} else {
err = Error{1, "Type mismatch"};
}
}
++m_fieldIt;
return err;
}
// array handler
template<typename T>
Error OrganicClawReader::field(CString const key, T *val, size_t valLen) noexcept {
auto const &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) {
return Error{1, "Type mismatch"};
}
auto srcSize = srcVal.size();
if (srcSize > valLen) {
return Error{1};
}
OrganicClawReader r(srcVal);
ModelHandlerInterface handler{r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
OX_RETURN_ERROR(handler.field("", &val[i]));
OX_ALLOW_UNSAFE_BUFFERS_END
}
return {};
}
template<typename T>
Error OrganicClawReader::field(CString const key, HashMap<String, T> *val) noexcept {
auto const &srcVal = value(key);
if (!srcVal.isObject()) {
return Error{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) {
auto const k = keys[i].c_str();
OX_RETURN_ERROR(handler.field(k, &val->operator[](k)));
}
return {};
}
Error readOC(BufferView const buff, auto &val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors.
try {
Json::Value doc;
Json::CharReaderBuilder parserBuilder;
auto parser = UPtr<Json::CharReader>(parserBuilder.newCharReader());
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
if (!parser->parse(buff.data(), buff.data() + buff.size(), &doc, nullptr)) {
OX_ALLOW_UNSAFE_BUFFERS_END
return Error{1, "Could not parse JSON"};
}
OrganicClawReader reader(buff.data(), buff.size());
ModelHandlerInterface handler(reader);
return model(&handler, &val);
} catch (Error const &err) {
return err;
} catch (...) {
return Error{1, "Unknown Error"};
}
}
template<typename T>
Result<T> readOC(BufferView buff) noexcept {
Result<T> val;
OX_RETURN_ERROR(readOC(buff, val.value));
return val;
}
template<typename T>
Result<T> readOC(StringViewCR json) noexcept {
return readOC<T>(BufferView{json.data(), json.size()});
}
}