Files
nostalgia/deps/ox/src/ox/model/descwrite.hpp
Gary Talent 9f338a7429
All checks were successful
Build / build (push) Successful in 3m18s
[ox] Run liccor
2025-01-08 23:03:05 -06:00

405 lines
13 KiB
C++

/*
* 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/byteswap.hpp>
#include <ox/std/istring.hpp>
#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 "desctypes.hpp"
#include "fieldcounter.hpp"
#include "metadata.hpp"
#include "modelhandleradaptor.hpp"
#include "optype.hpp"
#include "typenamecatcher.hpp"
#include "types.hpp"
#include "typestore.hpp"
namespace ox {
namespace detail {
template<typename T>
constexpr int indirectionLevels_v = 0;
template<typename 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>;
template<typename T, std::size_t SmallVecSz>
constexpr int indirectionLevels_v<::ox::Vector<T, SmallVecSz>> = 1 + indirectionLevels_v<T>;
template<typename T>
constexpr auto buildSubscriptStack(const T*, SubscriptStack*) noexcept {
}
template<typename T>
constexpr auto buildSubscriptStack(const T**, SubscriptStack *s) noexcept {
s->push_back({.subscriptType = Subscript::SubscriptType::Ptr});
}
template<typename T>
constexpr auto buildSubscriptStack(const UniquePtr<T>*, SubscriptStack *s) noexcept {
s->push_back({.subscriptType = Subscript::SubscriptType::Ptr});
}
template<typename T, std::size_t sz>
constexpr auto buildSubscriptStack(const Array<T, sz>*, SubscriptStack *s) noexcept {
s->push_back({.subscriptType = Subscript::SubscriptType::InlineArray, .length = sz});
buildSubscriptStack(static_cast<T*>(nullptr), s);
}
template<typename T, std::size_t SmallVecSz>
constexpr auto buildSubscriptStack(const Vector<T, SmallVecSz>*, SubscriptStack *s) noexcept {
s->push_back({
.subscriptType = Subscript::SubscriptType::Vector,
.smallSzLen = SmallVecSz,
});
buildSubscriptStack(static_cast<T*>(nullptr), s);
}
template<typename T>
constexpr auto buildSubscriptStack(const T*) {
SubscriptStack s;
buildSubscriptStack(static_cast<const T*>(nullptr), &s);
return s;
}
}
class TypeDescWriter {
private:
TypeStore *m_typeStore = nullptr;
DescriptorType *m_type = nullptr;
public:
explicit constexpr TypeDescWriter(TypeStore *typeStore = nullptr) noexcept;
constexpr ~TypeDescWriter() noexcept = default;
template<typename T = std::nullptr_t>
constexpr ox::Error setTypeInfo(StringViewCR name = T::TypeName,
int version = T::TypeVersion,
const TypeParamPack &typeParams = {},
std::size_t fields = ModelFieldCount_v<T>) noexcept;
template<typename T>
constexpr Error field(
StringViewCR name,
T const*val,
std::size_t valLen,
SubscriptStack const&subscriptStack) noexcept;
template<typename T>
constexpr Error field(StringViewCR name, T const*val, std::size_t valLen) noexcept;
template<typename T, bool force>
constexpr Error field(StringViewCR name, UnionView<T, force> val) noexcept;
template<typename T>
constexpr Error field(StringViewCR name, const T *val) noexcept;
template<typename ...Args>
constexpr Error fieldCString(StringViewCR name, Args&&...) noexcept;
[[nodiscard]]
constexpr DescriptorType *definition() noexcept {
return m_type;
}
static constexpr auto opType() noexcept {
return OpType::Reflect;
}
private:
[[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;
[[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;
[[nodiscard]]
constexpr const DescriptorType *type(const bool *val) const noexcept;
[[nodiscard]]
constexpr const DescriptorType *type(const char *val) const noexcept;
template<std::size_t SmallStrSz>
[[nodiscard]]
constexpr const DescriptorType *type(const BasicString<SmallStrSz>*) const noexcept {
constexpr auto PT = PrimitiveType::String;
return getType(types::BasicString, 1, PT, 0, {sfmt("{}", SmallStrSz)});
}
template<std::size_t sz>
[[nodiscard]]
constexpr const DescriptorType *type(const IString<sz> *val) const noexcept;
template<typename T>
[[nodiscard]]
constexpr const DescriptorType *type(const T *val) const noexcept;
template<typename T>
[[nodiscard]]
constexpr const DescriptorType *type(const HashMap<String, T> *val) const noexcept;
template<typename U>
[[nodiscard]]
constexpr const DescriptorType *type(UnionView<U> val) const noexcept;
[[nodiscard]]
constexpr const DescriptorType *getType(StringViewCR tn, int typeVersion, PrimitiveType t, int b,
const TypeParamPack &typeParams = {}) const noexcept;
};
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {}
template<typename T>
constexpr ox::Error TypeDescWriter::setTypeInfo(
StringViewCR typeName, int typeVersion,
const TypeParamPack &typeParams, std::size_t) noexcept {
PrimitiveType pt;
if constexpr(is_union_v<T>) {
pt = PrimitiveType::Union;
} else if constexpr(isBasicString_v<T> || isBString_v<T>) {
pt = PrimitiveType::String;
} else {
pt = PrimitiveType::Struct;
}
m_type = m_typeStore->getInit(typeName, typeVersion, pt, typeParams);
m_type->preloadable = preloadable<T>::value;
return {};
}
// array handler
template<typename T>
constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t, SubscriptStack const&subscriptStack) noexcept {
if (m_type) {
constexpr typename remove_pointer<T>::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");
m_type->fieldList.emplace_back(t, String(name), detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
return ox::Error(0);
}
return ox::Error(1);
}
// array handler
template<typename T>
constexpr Error TypeDescWriter::field(StringViewCR name, T const*, std::size_t) noexcept {
if (m_type) {
constexpr typename remove_pointer<T>::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");
auto const lvls = detail::indirectionLevels_v<T> + 1;
SubscriptStack subscriptStack{lvls};
m_type->fieldList.emplace_back(t, String(name), lvls, subscriptStack, buildTypeId(*t));
return ox::Error(0);
}
return ox::Error(1);
}
template<typename T, bool force>
constexpr Error TypeDescWriter::field(StringViewCR name, UnionView<T, force> 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, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return ox::Error(0);
}
return ox::Error(1);
}
template<typename T>
constexpr Error TypeDescWriter::field(StringViewCR name, const T *val) noexcept {
if (m_type) {
if constexpr(isVector_v<T> || isArray_v<T>) {
typename T::value_type *data = nullptr;
return field(name, data, 0, detail::buildSubscriptStack(val));
} else if constexpr(isSmartPtr_v<T>) {
typename T::value_type *data = nullptr;
return field(name, data, 0, detail::buildSubscriptStack(val));
} else if constexpr(is_pointer_v<T>) {
return field(name, val, 0, detail::buildSubscriptStack(val));
} 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, String(name), 0, SubscriptStack{}, buildTypeId(*t));
return {};
}
}
return ox::Error(1);
}
template<typename ...Args>
constexpr Error TypeDescWriter::fieldCString(StringViewCR name, Args&&...) noexcept {
constexpr auto s = "";
const auto t = type(s);
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
return {};
}
template<typename T>
constexpr const DescriptorType *TypeDescWriter::type(const T *val) const noexcept {
if constexpr(isVector_v<T>) {
return type(static_cast<typename T::value_type*>(nullptr));
} else {
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(const HashMap<String, T>*) const noexcept {
return type(static_cast<T*>(nullptr));
}
template<typename U>
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;
}
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);
}
template<std::size_t sz>
constexpr const DescriptorType *TypeDescWriter::type(const IString<sz>*) const noexcept {
constexpr auto PT = PrimitiveType::String;
return getType(types::BString, 0, PT, 0);
}
constexpr const DescriptorType *TypeDescWriter::getType(StringViewCR tn, int typeVersion, PrimitiveType pt, int b,
const TypeParamPack &typeParams) const noexcept {
auto t = m_typeStore->get(tn, typeVersion, typeParams);
if (!t.error) {
auto type = t.value;
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
return type;
} else {
auto dt = ox::make_unique<DescriptorType>(String(tn), typeVersion, pt, typeParams);
dt->length = b;
const auto out = dt.get();
const auto typeId = buildTypeId(tn, typeVersion, typeParams);
m_typeStore->set(typeId, std::move(dt));
return out;
}
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore) noexcept {
TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
if (std::is_constant_evaluated()) {
std::allocator<T> a;
T *t = a.allocate(1);
OX_RETURN_ERROR(model(&handler, t));
a.deallocate(t, 1);
} else {
auto t = ox_malloca(sizeof(T), T);
OX_RETURN_ERROR(model(&handler, t.get()));
}
return writer.definition();
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore &typeStore, T &val) noexcept {
TypeDescWriter writer(&typeStore);
ModelHandlerInterface<TypeDescWriter, ox::OpType::Reflect> handler(&writer);
OX_RETURN_ERROR(model(&handler, &val));
return writer.definition();
}
}