[ox/model] Add modelops with copy, move, and equals

This commit is contained in:
Gary Talent 2021-04-24 15:37:11 -05:00
parent 2dc9ce4015
commit 24f26d822a
4 changed files with 335 additions and 4 deletions

View File

@ -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
View 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;
}
}

View File

@ -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);

View File

@ -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;
}