1343 lines
34 KiB
C++
1343 lines
34 KiB
C++
/*
|
|
* 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/serialize.hpp>
|
|
#include <ox/std/string.hpp>
|
|
#include <ox/std/trace.hpp>
|
|
#include <ox/std/typetraits.hpp>
|
|
#include <ox/std/types.hpp>
|
|
#include <ox/std/utility.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 ModelValueArray;
|
|
class ModelValueVector;
|
|
|
|
class ModelValue {
|
|
public:
|
|
enum class Type {
|
|
Undefined,
|
|
Bool,
|
|
UnsignedInteger8,
|
|
UnsignedInteger16,
|
|
UnsignedInteger32,
|
|
UnsignedInteger64,
|
|
SignedInteger8,
|
|
SignedInteger16,
|
|
SignedInteger32,
|
|
SignedInteger64,
|
|
String,
|
|
Object,
|
|
Union,
|
|
Vector,
|
|
InlineArray,
|
|
};
|
|
|
|
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 = 0;
|
|
String *str;
|
|
ModelObject *obj;
|
|
ModelUnion *uni;
|
|
ModelValueVector *vec;
|
|
ModelValueArray *array;
|
|
} m_data;
|
|
|
|
template<typename T>
|
|
static consteval Type getType() noexcept {
|
|
using U = typename ox::remove_reference<T>::type;
|
|
if constexpr(is_bool_v<U>) {
|
|
return Type::Bool;
|
|
} else if constexpr(is_integer_v<U>) {
|
|
if constexpr(!is_signed_v<U> && sizeof(U) == 1) {
|
|
return Type::UnsignedInteger8;
|
|
} else if constexpr(!is_signed_v<U> && sizeof(U) == 2) {
|
|
return Type::UnsignedInteger16;
|
|
} else if constexpr(!is_signed_v<U> && sizeof(U) == 4) {
|
|
return Type::UnsignedInteger32;
|
|
} else if constexpr(!is_signed_v<U> && sizeof(U) == 8) {
|
|
return Type::UnsignedInteger64;
|
|
} else if constexpr(is_signed_v<U> && sizeof(U) == 1) {
|
|
return Type::SignedInteger8;
|
|
} else if constexpr(is_signed_v<U> && sizeof(U) == 2) {
|
|
return Type::SignedInteger16;
|
|
} else if constexpr(is_signed_v<U> && sizeof(U) == 4) {
|
|
return Type::SignedInteger32;
|
|
} else if constexpr(is_signed_v<U> && sizeof(U) == 8) {
|
|
return Type::SignedInteger64;
|
|
}
|
|
} else if constexpr(is_same_v<U, ModelUnion>) {
|
|
return Type::Union;
|
|
} else if constexpr(is_same_v<U, ModelObject>) {
|
|
return Type::Object;
|
|
} else if constexpr(isBasicString_v<U> || isBString_v<U>) {
|
|
return Type::String;
|
|
} else if constexpr(is_same_v<U, ModelValueVector>) {
|
|
return Type::Vector;
|
|
} else if constexpr(is_same_v<U, ModelValueArray>) {
|
|
return Type::InlineArray;
|
|
} 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 if constexpr(type == Type::InlineArray) {
|
|
return *t.m_data.array;
|
|
} else {
|
|
return t.m_data.i32;
|
|
}
|
|
}
|
|
|
|
public:
|
|
constexpr ModelValue() noexcept = default;
|
|
|
|
constexpr ModelValue(const ModelValue &other) noexcept;
|
|
|
|
constexpr ModelValue(ModelValue &&other) noexcept;
|
|
|
|
template<typename T>
|
|
explicit constexpr ModelValue(const T &val) noexcept
|
|
requires(!ox::is_same_v<ox::remove_reference_t<T>, ModelValue>);
|
|
|
|
template<typename T>
|
|
explicit constexpr ModelValue(T &&val) noexcept
|
|
requires(!ox::is_same_v<ox::remove_reference_t<T>, ModelValue>);
|
|
|
|
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(
|
|
DescriptorType const*type,
|
|
int subscriptLevels = 0,
|
|
SubscriptStack const& = {}) 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;
|
|
|
|
private:
|
|
constexpr void freeResources() noexcept;
|
|
|
|
};
|
|
|
|
class ModelValueArray {
|
|
private:
|
|
Vector<ModelValue> m_vec;
|
|
const DescriptorType *m_type = nullptr;
|
|
int m_typeSubscriptLevels = 0;
|
|
SubscriptStack m_subscriptStack;
|
|
String m_typeName;
|
|
int m_typeVersion = 0;
|
|
|
|
public:
|
|
constexpr explicit ModelValueArray() noexcept = default;
|
|
|
|
constexpr ModelValueArray(ModelValueArray const&other) noexcept {
|
|
for (auto &v : other.m_vec) {
|
|
m_vec.emplace_back(v);
|
|
}
|
|
m_typeName = other.m_typeName;
|
|
m_typeVersion = other.m_typeVersion;
|
|
}
|
|
|
|
constexpr ModelValueArray(ModelValueArray &&other) noexcept {
|
|
m_vec = std::move(other.m_vec);
|
|
m_typeName = std::move(other.m_typeName);
|
|
m_typeVersion = other.m_typeVersion;
|
|
}
|
|
|
|
constexpr ox::Error setSize(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) {
|
|
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels));
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto data() const noexcept {
|
|
return m_vec.data();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto data() noexcept {
|
|
return m_vec.data();
|
|
}
|
|
|
|
constexpr static ox::Result<ModelValueArray> make(size_t sz) noexcept {
|
|
ox::Result<ModelValueArray> out;
|
|
out.error = out.value.setSize(sz);
|
|
return out;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto &get() noexcept {
|
|
return m_vec;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto const&get() const noexcept {
|
|
return m_vec;
|
|
}
|
|
|
|
constexpr Error setType(
|
|
DescriptorType const*type,
|
|
int subscriptLevels,
|
|
SubscriptStack subscriptStack) noexcept {
|
|
m_type = type;
|
|
m_typeSubscriptLevels = subscriptLevels;
|
|
m_subscriptStack = std::move(subscriptStack);
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr String const&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 begin() const noexcept {
|
|
return m_vec.cbegin();
|
|
}
|
|
|
|
[[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 end() const noexcept {
|
|
return m_vec.cend();
|
|
}
|
|
|
|
[[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();
|
|
}
|
|
|
|
};
|
|
|
|
class ModelValueVector {
|
|
private:
|
|
Vector<ModelValue> m_vec;
|
|
const DescriptorType *m_type = nullptr;
|
|
int m_typeSubscriptLevels = 0;
|
|
SubscriptStack m_subscriptStack;
|
|
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 ox::Error 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) {
|
|
oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels, m_subscriptStack));
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto &get() noexcept {
|
|
return m_vec;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr const auto &get() const noexcept {
|
|
return m_vec;
|
|
}
|
|
|
|
constexpr Error setType(
|
|
DescriptorType const*type,
|
|
int subscriptLevels,
|
|
SubscriptStack subscriptStack) noexcept {
|
|
m_type = type;
|
|
m_typeSubscriptLevels = subscriptLevels;
|
|
m_subscriptStack = std::move(subscriptStack);
|
|
return {};
|
|
}
|
|
|
|
[[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 begin() const noexcept {
|
|
return m_vec.cbegin();
|
|
}
|
|
|
|
[[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 end() const noexcept {
|
|
return m_vec.cend();
|
|
}
|
|
|
|
[[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;
|
|
}
|
|
|
|
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept;
|
|
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept;
|
|
|
|
|
|
class ModelObject {
|
|
friend constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept;
|
|
public:
|
|
struct Field {
|
|
String name;
|
|
ModelValue value;
|
|
};
|
|
protected:
|
|
oxModelFriend(ModelObject);
|
|
friend ModelValue;
|
|
Vector<UniquePtr<Field>> m_fieldsOrder;
|
|
HashMap<String, ModelValue*> m_fields;
|
|
const DescriptorType *m_type = nullptr;
|
|
|
|
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{ox::String(f->name), f->value});
|
|
m_fields[field->name] = &field->value;
|
|
}
|
|
m_type = other.m_type;
|
|
}
|
|
|
|
constexpr ModelObject(ModelObject &&other) noexcept {
|
|
m_fields = std::move(other.m_fields);
|
|
m_type = other.m_type;
|
|
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto begin() noexcept {
|
|
return m_fieldsOrder.begin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto end() noexcept {
|
|
return m_fieldsOrder.end();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto begin() const noexcept {
|
|
return m_fieldsOrder.begin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto end() const noexcept {
|
|
return m_fieldsOrder.end();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto rbegin() noexcept {
|
|
return m_fieldsOrder.rbegin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto rend() noexcept {
|
|
return m_fieldsOrder.rend();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto rbegin() const noexcept {
|
|
return m_fieldsOrder.rbegin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto rend() const noexcept {
|
|
return m_fieldsOrder.rend();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto cbegin() const noexcept {
|
|
return m_fieldsOrder.cbegin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto cend() const noexcept {
|
|
return m_fieldsOrder.cend();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto crbegin() const noexcept {
|
|
return m_fieldsOrder.crbegin();
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto crend() const noexcept {
|
|
return m_fieldsOrder.crend();
|
|
}
|
|
|
|
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{ox::String(f->name), f->value});
|
|
m_fields[field->name] = &field->value;
|
|
}
|
|
m_type = other.m_type;
|
|
return *this;
|
|
}
|
|
|
|
constexpr auto &operator=(ModelObject &&other) noexcept {
|
|
if (&other == this) [[unlikely]] {
|
|
return *this;
|
|
}
|
|
m_type = other.m_type;
|
|
m_fields = std::move(other.m_fields);
|
|
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr auto set(const std::size_t &i, T &&val) noexcept {
|
|
auto &f = *m_fieldsOrder[i];
|
|
f = val;
|
|
}
|
|
|
|
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
|
if (m_fields.contains(k)) {
|
|
return *m_fields.at(k).value;
|
|
}
|
|
return OxError(1);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Error set(const String &k, T &&val) noexcept {
|
|
oxRequire(t, m_fields.at(k));
|
|
*t = ox::forward<T>(val);
|
|
return {};
|
|
}
|
|
|
|
constexpr auto &operator[](StringView const&k) noexcept {
|
|
auto [v, err] = m_fields.at(k);
|
|
if (err) [[unlikely]] {
|
|
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
|
}
|
|
return **v;
|
|
}
|
|
|
|
constexpr auto &operator[](const std::size_t i) noexcept {
|
|
return *m_fieldsOrder[i];
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr CRString typeName() const noexcept {
|
|
return m_type->typeName;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr int typeVersion() const noexcept {
|
|
return m_type->typeVersion;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto type() const noexcept {
|
|
return m_type;
|
|
}
|
|
|
|
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_type = type;
|
|
for (const auto &f : type->fieldList) {
|
|
auto field = make_unique<Field>();
|
|
field->name = f.fieldName;
|
|
oxReturnError(field->value.setType(f.type, f.subscriptLevels, f.subscriptStack));
|
|
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;
|
|
};
|
|
friend constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept;
|
|
friend ModelValue;
|
|
Vector<UniquePtr<Field>> m_fieldsOrder;
|
|
HashMap<String, Field*> m_fields;
|
|
const DescriptorType *m_type = nullptr;
|
|
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, ox::String(f->name), f->value});
|
|
m_fields[field->name] = field.get();
|
|
++i;
|
|
}
|
|
m_type = other.m_type;
|
|
m_unionIdx = other.m_unionIdx;
|
|
}
|
|
|
|
constexpr ModelUnion(ModelUnion &&other) noexcept {
|
|
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
|
m_fields = std::move(other.m_fields);
|
|
m_type = other.m_type;
|
|
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[](StringView const&k) noexcept {
|
|
const auto [v, err] = m_fields.at(k);
|
|
if (err) [[unlikely]] {
|
|
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
|
}
|
|
return (*v)->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 auto set(int i, auto val) noexcept {
|
|
m_unionIdx = i;
|
|
return m_fieldsOrder[static_cast<std::size_t>(i)]->value.set(val);
|
|
}
|
|
|
|
constexpr void set(std::size_t i, auto val) noexcept {
|
|
m_unionIdx = static_cast<int>(i);
|
|
*m_fieldsOrder[i] = val;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr Result<const ModelValue*> get(std::size_t i) const noexcept {
|
|
if (i < m_fieldsOrder.size()) {
|
|
return &m_fieldsOrder[i]->value;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
|
oxRequire(t, m_fields.at(k));
|
|
return &(*t)->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_type->typeName;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr int typeVersion() const noexcept {
|
|
return m_type->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_type = type;
|
|
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;
|
|
}
|
|
|
|
};
|
|
|
|
template<typename PlatSpec>
|
|
[[nodiscard]]
|
|
constexpr std::size_t sizeOf(const ModelValueVector*) noexcept {
|
|
VectorMemMap<PlatSpec> v;
|
|
return sizeOf<PlatSpec>(&v);
|
|
}
|
|
|
|
template<typename PlatSpec>
|
|
[[nodiscard]]
|
|
constexpr std::size_t sizeOf(const ModelUnion*) noexcept {
|
|
VectorMemMap<PlatSpec> v;
|
|
return sizeOf<PlatSpec>(&v);
|
|
}
|
|
|
|
template<typename PlatSpec>
|
|
[[nodiscard]]
|
|
constexpr std::size_t sizeOf(const ModelValue *t) noexcept {
|
|
std::size_t size = 0;
|
|
switch (t->type()) {
|
|
case ModelValue::Type::Bool:
|
|
size = sizeof(t->get<bool>());
|
|
break;
|
|
case ModelValue::Type::Undefined:
|
|
size = 1;
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger8:
|
|
size = sizeof(t->get<uint8_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger16:
|
|
size = sizeof(t->get<uint16_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger32:
|
|
size = sizeof(t->get<uint32_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger64:
|
|
size = sizeof(t->get<uint64_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger8:
|
|
size = sizeof(t->get<int8_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger16:
|
|
size = sizeof(t->get<int16_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger32:
|
|
size = sizeof(t->get<int32_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger64:
|
|
size = sizeof(t->get<int64_t>());
|
|
break;
|
|
case ModelValue::Type::String:
|
|
size = sizeOf<PlatSpec>(&t->get<ox::String>());
|
|
break;
|
|
case ModelValue::Type::Object:
|
|
size = sizeOf<PlatSpec>(&t->get<ox::ModelObject>());
|
|
break;
|
|
case ModelValue::Type::Union:
|
|
size = sizeOf<PlatSpec>(&t->get<ox::ModelUnion>());
|
|
break;
|
|
case ModelValue::Type::Vector:
|
|
size = sizeOf<PlatSpec>(&t->get<ox::ModelValueVector>());
|
|
break;
|
|
case ModelValue::Type::InlineArray:
|
|
{
|
|
auto &list = t->get<ox::ModelValueArray>();
|
|
size = sizeOf<PlatSpec>(&list[0]) * list.size();
|
|
break;
|
|
}
|
|
}
|
|
return size;
|
|
}
|
|
|
|
template<typename PlatSpec>
|
|
[[nodiscard]]
|
|
constexpr std::size_t alignOf(const ModelValueVector&) noexcept {
|
|
VectorMemMap<PlatSpec> v;
|
|
return alignOf<PlatSpec>(v);
|
|
}
|
|
|
|
template<typename PlatSpec>
|
|
[[nodiscard]]
|
|
constexpr std::size_t alignOf(const ModelValue &t) noexcept {
|
|
std::size_t alignment = 0;
|
|
switch (t.type()) {
|
|
case ModelValue::Type::Bool:
|
|
alignment = PlatSpec::alignOf(t.get<bool>());
|
|
break;
|
|
case ModelValue::Type::Undefined:
|
|
alignment = 1;
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger8:
|
|
alignment = PlatSpec::alignOf(t.get<uint8_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger16:
|
|
alignment = PlatSpec::alignOf(t.get<uint16_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger32:
|
|
alignment = PlatSpec::alignOf(t.get<uint32_t>());
|
|
break;
|
|
case ModelValue::Type::UnsignedInteger64:
|
|
alignment = PlatSpec::alignOf(t.get<uint64_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger8:
|
|
alignment = PlatSpec::alignOf(t.get<int8_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger16:
|
|
alignment = PlatSpec::alignOf(t.get<int16_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger32:
|
|
alignment = PlatSpec::alignOf(t.get<int32_t>());
|
|
break;
|
|
case ModelValue::Type::SignedInteger64:
|
|
alignment = PlatSpec::alignOf(t.get<int64_t>());
|
|
break;
|
|
case ModelValue::Type::String:
|
|
alignment = alignOf<PlatSpec>(t.get<ox::String>());
|
|
break;
|
|
case ModelValue::Type::Object:
|
|
alignment = alignOf<PlatSpec>(t.get<ox::ModelObject>());
|
|
break;
|
|
case ModelValue::Type::Union:
|
|
alignment = alignOf<PlatSpec>(t.get<ox::ModelUnion>());
|
|
break;
|
|
case ModelValue::Type::Vector:
|
|
alignment = alignOf<PlatSpec>(t.get<ox::ModelValueVector>());
|
|
break;
|
|
case ModelValue::Type::InlineArray:
|
|
{
|
|
auto &list = t.get<ox::ModelValueArray>();
|
|
alignment = alignOf<PlatSpec>(list[0]);
|
|
break;
|
|
}
|
|
}
|
|
return alignment;
|
|
}
|
|
|
|
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
|
oxReturnError(h->template setTypeInfo<ModelObject>(
|
|
obj->typeName().c_str(), obj->typeVersion(), {}, 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 {
|
|
oxReturnError(h->template setTypeInfo<ModelUnion>(
|
|
obj->typeName().c_str(), obj->typeVersion(), {}, 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;
|
|
case Type::InlineArray:
|
|
m_data.array = new ModelValueArray(*other.m_data.array);
|
|
break;
|
|
}
|
|
}
|
|
|
|
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 = other.m_data.uni;
|
|
other.m_data.uni = new ModelUnion;
|
|
break;
|
|
case Type::Object:
|
|
m_data.obj = other.m_data.obj;
|
|
other.m_data.obj = new ModelObject;
|
|
break;
|
|
case Type::Vector:
|
|
m_data.vec = other.m_data.vec;
|
|
other.m_data.vec = new ModelValueVector;
|
|
break;
|
|
case Type::InlineArray:
|
|
m_data.array = other.m_data.array;
|
|
other.m_data.array = new ModelValueArray();
|
|
break;
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr ModelValue::ModelValue(const T &val) noexcept
|
|
requires(!ox::is_same_v<ox::remove_reference_t<T>, ModelValue>) {
|
|
oxIgnoreError(set(val));
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr ModelValue::ModelValue(T &&val) noexcept
|
|
requires(!ox::is_same_v<ox::remove_reference_t<T>, ModelValue>) {
|
|
oxIgnoreError(set(ox::forward<T>(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,
|
|
SubscriptStack const&subscriptStack) noexcept {
|
|
freeResources();
|
|
if (subscriptLevels) {
|
|
auto const&subscript = subscriptStack[subscriptStack.size() - static_cast<size_t>(subscriptLevels)];
|
|
if (subscript.subscriptType == Subscript::SubscriptType::InlineArray) {
|
|
m_type = Type::InlineArray;
|
|
m_data.array = new ModelValueArray;
|
|
oxReturnError(m_data.array->setSize(static_cast<size_t>(subscript.length)));
|
|
} else {
|
|
m_type = Type::Vector;
|
|
m_data.vec = new ModelValueVector;
|
|
}
|
|
return m_data.vec->setType(type, subscriptLevels - 1, subscriptStack);
|
|
} else if (type->typeName == types::Bool) {
|
|
m_type = Type::Bool;
|
|
} else if (type->typeName == types::BasicString ||
|
|
type->typeName == types::BString ||
|
|
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));
|
|
}
|
|
oxAssert(m_type != Type::Undefined, "No type set");
|
|
return OxError(0);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr Error ModelValue::setType() noexcept {
|
|
constexpr auto type = getType<T>();
|
|
freeResources();
|
|
m_type = type;
|
|
// 2022.09.04: Clang retardedly requires initializing the union values directly,
|
|
// rather than using getValue<type>()
|
|
if constexpr(type == Type::Object) {
|
|
m_data.obj = new ModelObject;
|
|
oxReturnError(m_data.obj->setType(type));
|
|
} else if constexpr(type == Type::Union) {
|
|
oxRequireM(u, ModelUnion::make(type));
|
|
m_data.uni = u.release();
|
|
oxReturnError(m_data.uni->setType(type));
|
|
} else if constexpr(type == Type::String) {
|
|
m_data.str = new String;
|
|
} else if constexpr(type == Type::Vector) {
|
|
m_data.vec = new ModelValueVector;
|
|
} else if constexpr(type == Type::Bool) {
|
|
m_data.b = false;
|
|
} else if constexpr(type == Type::SignedInteger8) {
|
|
m_data.i8 = 0;
|
|
} else if constexpr(type == Type::SignedInteger16) {
|
|
m_data.i16 = 0;
|
|
} else if constexpr(type == Type::SignedInteger32) {
|
|
m_data.i32 = 0;
|
|
} else if constexpr(type == Type::SignedInteger64) {
|
|
m_data.i64 = 0;
|
|
} else if constexpr(type == Type::UnsignedInteger8) {
|
|
m_data.ui8 = 0;
|
|
} else if constexpr(type == Type::UnsignedInteger16) {
|
|
m_data.ui16 = 0;
|
|
} else if constexpr(type == Type::UnsignedInteger32) {
|
|
m_data.ui32 = 0;
|
|
} else if constexpr(type == Type::UnsignedInteger64) {
|
|
m_data.ui64 = 0;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
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);
|
|
if constexpr(type == Type::Vector || type == Type::Object ||
|
|
type == Type::Union || type == Type::String || type == Type::InlineArray) {
|
|
safeDelete(&value);
|
|
}
|
|
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 || type == Type::InlineArray) {
|
|
safeDelete(&value);
|
|
}
|
|
value = std::move(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;
|
|
case Type::InlineArray:
|
|
m_data.array = new ModelValueArray(*other.m_data.array);
|
|
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 = other.m_data.obj;
|
|
other.m_data.obj = new ModelObject;
|
|
break;
|
|
case Type::Union:
|
|
m_data.uni = other.m_data.uni;
|
|
other.m_data.uni = new ModelUnion;
|
|
break;
|
|
case Type::Vector:
|
|
m_data.vec = other.m_data.vec;
|
|
other.m_data.vec = new ModelValueVector;
|
|
break;
|
|
case Type::InlineArray:
|
|
m_data.array = other.m_data.array;
|
|
other.m_data.array = new ModelValueArray;
|
|
break;
|
|
}
|
|
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;
|
|
case Type::InlineArray:
|
|
safeDelete(m_data.array);
|
|
break;
|
|
}
|
|
m_type = Type::Undefined;
|
|
}
|
|
|
|
constexpr ModelValueVector::ModelValueVector(const ModelValueVector &other) noexcept {
|
|
for (auto &v : other.m_vec) {
|
|
m_vec.emplace_back(v);
|
|
}
|
|
m_typeName = other.m_typeName;
|
|
m_typeVersion = other.m_typeVersion;
|
|
}
|
|
|
|
constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept {
|
|
m_vec = std::move(other.m_vec);
|
|
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_typeName = other.m_typeName;
|
|
m_typeVersion = other.m_typeVersion;
|
|
return *this;
|
|
}
|
|
|
|
constexpr ModelValueVector &ModelValueVector::operator=(ModelValueVector &&other) noexcept {
|
|
if (this == &other) {
|
|
return *this;
|
|
}
|
|
m_vec = std::move(other.m_vec);
|
|
m_typeName = std::move(other.m_typeName);
|
|
m_typeVersion = other.m_typeVersion;
|
|
return *this;
|
|
}
|
|
|
|
}
|