[ox/model] Add modelops with copy, move, and equals
This commit is contained in:
parent
2dc9ce4015
commit
24f26d822a
1
deps/ox/src/ox/model/model.hpp
vendored
1
deps/ox/src/ox/model/model.hpp
vendored
@ -11,5 +11,6 @@
|
||||
#include "descread.hpp"
|
||||
#include "desctypes.hpp"
|
||||
#include "descwrite.hpp"
|
||||
#include "modelops.hpp"
|
||||
#include "types.hpp"
|
||||
#include "walk.hpp"
|
||||
|
286
deps/ox/src/ox/model/modelops.hpp
vendored
Normal file
286
deps/ox/src/ox/model/modelops.hpp
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright 2015 - 2021 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/utility.hpp>
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t size>
|
||||
class MemberList {
|
||||
|
||||
private:
|
||||
std::size_t m_i = 0;
|
||||
|
||||
public:
|
||||
void *vars[size];
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *v) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(v);
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *v, int) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(v);
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
vars[m_i++] = static_cast<void*>(u.get());
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, SerStr s) noexcept {
|
||||
return field(name, s.target());
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "GetMembers";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<std::size_t size>
|
||||
class Copier {
|
||||
|
||||
private:
|
||||
std::size_t m_i = 0;
|
||||
MemberList<size> *m_dst = nullptr;
|
||||
|
||||
public:
|
||||
constexpr Copier(MemberList<size> *dst) noexcept: m_dst(dst) {
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char *name, const FT *v) noexcept {
|
||||
if constexpr(isVector(v)) {
|
||||
return field(name, v->data(), v->size());
|
||||
} else {
|
||||
auto &src = *v;
|
||||
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
|
||||
dst = src;
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char*, const FT *list, int elements) {
|
||||
for (auto i = 0l; i < elements; ++i) {
|
||||
auto &src = list[i];
|
||||
auto &dst = cbit_cast<FT*>(m_dst->vars[m_i])[i];
|
||||
dst = src;
|
||||
}
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) {
|
||||
auto &dst = *cbit_cast<U*>(m_dst->vars[m_i]);
|
||||
auto &src = *u.get();
|
||||
dst = src;
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, SerStr s) {
|
||||
return field(name, s.target());
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() {
|
||||
return "Copy";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<std::size_t size>
|
||||
class Mover {
|
||||
|
||||
private:
|
||||
std::size_t m_i = 0;
|
||||
MemberList<size> *m_dst = nullptr;
|
||||
|
||||
public:
|
||||
constexpr Mover(MemberList<size> *dst) noexcept: m_dst(dst) {
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char *name, FT *v) noexcept {
|
||||
if constexpr(isVector(v)) {
|
||||
return field(name, v->data(), v->size());
|
||||
} else {
|
||||
auto &src = *v;
|
||||
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
|
||||
dst = move(src);
|
||||
src = FT{};
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char*, FT *list, int elements) noexcept {
|
||||
for (auto i = 0l; i < elements; ++i) {
|
||||
auto &src = list[i];
|
||||
auto &dst = cbit_cast<FT*>(m_dst->vars[m_i])[i];
|
||||
dst = move(src);
|
||||
src = FT{};
|
||||
}
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
auto &dst = *cbit_cast<U*>(m_dst->vars[m_i]);
|
||||
auto &src = *u.get();
|
||||
dst = move(src);
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, SerStr s) noexcept {
|
||||
return field(name, s.target());
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "Copy";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<std::size_t size>
|
||||
class Equals {
|
||||
|
||||
private:
|
||||
std::size_t m_i = 0;
|
||||
MemberList<size> *m_dst = nullptr;
|
||||
|
||||
public:
|
||||
bool value = false;
|
||||
|
||||
constexpr Equals(MemberList<size> *dst) noexcept: m_dst(dst) {
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char *name, const FT *v) noexcept {
|
||||
if constexpr(isVector(v)) {
|
||||
return field(name, v->data(), v->size());
|
||||
} else {
|
||||
auto &src = *v;
|
||||
auto &dst = *cbit_cast<FT*>(m_dst->vars[m_i]);
|
||||
++m_i;
|
||||
if (dst == src) {
|
||||
return OxError(0);
|
||||
} else {
|
||||
this->value = false;
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FT>
|
||||
constexpr Error field(const char*, const FT *list, int elements) noexcept {
|
||||
for (auto i = 0l; i < elements; ++i) {
|
||||
auto &src = list[i];
|
||||
auto &dst = cbit_cast<FT*>(m_dst->vars[m_i])[i];
|
||||
if (!(dst == src)) {
|
||||
this->value = false;
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
++m_i;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Error field(const char*, UnionView<U> u) noexcept {
|
||||
auto &dst = *cbit_cast<U*>(m_dst->vars[m_i]);
|
||||
auto &src = *u.get();
|
||||
++m_i;
|
||||
if (dst == src) {
|
||||
return OxError(0);
|
||||
} else {
|
||||
this->value = false;
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, SerStr s) noexcept {
|
||||
return field(name, s.target());
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return "Copy";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void moveModel(T *dst, T *src) noexcept {
|
||||
constexpr auto size = T::Fields;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Mover<size> mover(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&mover, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void copyModel(T *dst, const T *src) noexcept {
|
||||
constexpr auto size = T::Fields;
|
||||
detail::MemberList<size> dstFields;
|
||||
detail::Copier<size> copier(&dstFields);
|
||||
oxIgnoreError(model(&dstFields, dst));
|
||||
oxIgnoreError(model(&copier, src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr bool equalsModel(T *a, T *b) noexcept {
|
||||
constexpr auto size = T::Fields;
|
||||
detail::MemberList<size> aFields;
|
||||
detail::Equals<size> equals(&aFields);
|
||||
oxIgnoreError(model(&aFields, a));
|
||||
oxIgnoreError(model(&equals, b));
|
||||
return equals.value;
|
||||
}
|
||||
|
||||
}
|
8
deps/ox/src/ox/model/optype.hpp
vendored
8
deps/ox/src/ox/model/optype.hpp
vendored
@ -23,22 +23,22 @@ namespace OpType {
|
||||
// empty default implementations of model functions
|
||||
|
||||
template<typename T, typename O>
|
||||
Error modelRead(T*, O*) {
|
||||
constexpr Error modelRead(T*, O*) {
|
||||
return OxError(1, "Model: modelRead not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
Error modelWrite(T*, O*) {
|
||||
constexpr Error modelWrite(T*, O*) {
|
||||
return OxError(1, "Model: modelWrite not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
Error modelWriteDefinition(T*, O*) {
|
||||
constexpr Error modelWriteDefinition(T*, O*) {
|
||||
return OxError(1, "Model: modelWriteDefinition not implemented");
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
Error model(T *io, O *obj) {
|
||||
constexpr Error model(T *io, O *obj) {
|
||||
Error err;
|
||||
if constexpr(ox_strcmp(T::opType(), ox::OpType::Read) == 0) {
|
||||
err = modelRead(io, obj);
|
||||
|
44
deps/ox/src/ox/model/types.hpp
vendored
44
deps/ox/src/ox/model/types.hpp
vendored
@ -8,13 +8,46 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __has_include(<vector>)
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
#if __has_include(<QVector>)
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
#include <ox/std/bstring.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isVector(const T&) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isVector(const Vector<T>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if __has_include(<vector>)
|
||||
template<typename T>
|
||||
constexpr bool isVector(const std::vector<T>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __has_include(<QVector>)
|
||||
template<typename T>
|
||||
constexpr bool isVector(const QVector<T>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
class SerStr {
|
||||
|
||||
protected:
|
||||
@ -46,10 +79,16 @@ class SerStr {
|
||||
m_cap = cap;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return m_str;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto target() const noexcept {
|
||||
return m_tgt;
|
||||
}
|
||||
|
||||
constexpr char *data(std::size_t sz = 0) noexcept {
|
||||
if (m_tgt && sz) {
|
||||
*m_tgt = new char[sz];
|
||||
@ -59,10 +98,12 @@ class SerStr {
|
||||
return m_str;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int len() const noexcept {
|
||||
return static_cast<int>(m_str ? ox_strlen(m_str) : 0);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int cap() const noexcept {
|
||||
return m_cap;
|
||||
}
|
||||
@ -80,14 +121,17 @@ class UnionView {
|
||||
constexpr UnionView(Union *u, int idx) noexcept: m_idx(idx), m_union(u) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto idx() const noexcept {
|
||||
return m_idx;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const Union *get() const noexcept {
|
||||
return m_union;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Union *get() noexcept {
|
||||
return m_union;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user