From 24f26d822ad9c6f8f043bd638708683bbcd4d49a Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 24 Apr 2021 15:37:11 -0500 Subject: [PATCH] [ox/model] Add modelops with copy, move, and equals --- deps/ox/src/ox/model/model.hpp | 1 + deps/ox/src/ox/model/modelops.hpp | 286 ++++++++++++++++++++++++++++++ deps/ox/src/ox/model/optype.hpp | 8 +- deps/ox/src/ox/model/types.hpp | 44 +++++ 4 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 deps/ox/src/ox/model/modelops.hpp diff --git a/deps/ox/src/ox/model/model.hpp b/deps/ox/src/ox/model/model.hpp index 2bb448c5..ca9fdd67 100644 --- a/deps/ox/src/ox/model/model.hpp +++ b/deps/ox/src/ox/model/model.hpp @@ -11,5 +11,6 @@ #include "descread.hpp" #include "desctypes.hpp" #include "descwrite.hpp" +#include "modelops.hpp" #include "types.hpp" #include "walk.hpp" diff --git a/deps/ox/src/ox/model/modelops.hpp b/deps/ox/src/ox/model/modelops.hpp new file mode 100644 index 00000000..c6aa38da --- /dev/null +++ b/deps/ox/src/ox/model/modelops.hpp @@ -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 +#include +#include + +#include "types.hpp" + +namespace ox { + +namespace detail { + +template +class MemberList { + + private: + std::size_t m_i = 0; + + public: + void *vars[size]; + + template + constexpr Error field(const char*, T *v) noexcept { + vars[m_i++] = static_cast(v); + return OxError(0); + } + + template + constexpr Error field(const char*, T *v, int) noexcept { + vars[m_i++] = static_cast(v); + return OxError(0); + } + + template + constexpr Error field(const char*, UnionView u) noexcept { + vars[m_i++] = static_cast(u.get()); + return OxError(0); + } + + constexpr Error field(const char *name, SerStr s) noexcept { + return field(name, s.target()); + } + + template + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept { + } + + [[nodiscard]] + static constexpr auto opType() noexcept { + return "GetMembers"; + } + +}; + +template +class Copier { + + private: + std::size_t m_i = 0; + MemberList *m_dst = nullptr; + + public: + constexpr Copier(MemberList *dst) noexcept: m_dst(dst) { + } + + template + 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(m_dst->vars[m_i]); + dst = src; + ++m_i; + return OxError(0); + } + } + + template + 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(m_dst->vars[m_i])[i]; + dst = src; + } + ++m_i; + return OxError(0); + } + + template + constexpr Error field(const char*, UnionView u) { + auto &dst = *cbit_cast(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 + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) { + } + + [[nodiscard]] + static constexpr auto opType() { + return "Copy"; + } + +}; + +template +class Mover { + + private: + std::size_t m_i = 0; + MemberList *m_dst = nullptr; + + public: + constexpr Mover(MemberList *dst) noexcept: m_dst(dst) { + } + + template + 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(m_dst->vars[m_i]); + dst = move(src); + src = FT{}; + ++m_i; + return OxError(0); + } + } + + template + 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(m_dst->vars[m_i])[i]; + dst = move(src); + src = FT{}; + } + ++m_i; + return OxError(0); + } + + template + constexpr Error field(const char*, UnionView u) noexcept { + auto &dst = *cbit_cast(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 + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept { + } + + [[nodiscard]] + static constexpr auto opType() noexcept { + return "Copy"; + } + +}; + +template +class Equals { + + private: + std::size_t m_i = 0; + MemberList *m_dst = nullptr; + + public: + bool value = false; + + constexpr Equals(MemberList *dst) noexcept: m_dst(dst) { + } + + template + 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(m_dst->vars[m_i]); + ++m_i; + if (dst == src) { + return OxError(0); + } else { + this->value = false; + return OxError(1); + } + } + } + + template + 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(m_dst->vars[m_i])[i]; + if (!(dst == src)) { + this->value = false; + return OxError(1); + } + } + ++m_i; + return OxError(0); + } + + template + constexpr Error field(const char*, UnionView u) noexcept { + auto &dst = *cbit_cast(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 + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept { + } + + [[nodiscard]] + static constexpr auto opType() noexcept { + return "Copy"; + } + +}; + +} + +template +constexpr void moveModel(T *dst, T *src) noexcept { + constexpr auto size = T::Fields; + detail::MemberList dstFields; + detail::Mover mover(&dstFields); + oxIgnoreError(model(&dstFields, dst)); + oxIgnoreError(model(&mover, src)); +} + +template +constexpr void copyModel(T *dst, const T *src) noexcept { + constexpr auto size = T::Fields; + detail::MemberList dstFields; + detail::Copier copier(&dstFields); + oxIgnoreError(model(&dstFields, dst)); + oxIgnoreError(model(&copier, src)); +} + +template +[[nodiscard]] +constexpr bool equalsModel(T *a, T *b) noexcept { + constexpr auto size = T::Fields; + detail::MemberList aFields; + detail::Equals equals(&aFields); + oxIgnoreError(model(&aFields, a)); + oxIgnoreError(model(&equals, b)); + return equals.value; +} + +} diff --git a/deps/ox/src/ox/model/optype.hpp b/deps/ox/src/ox/model/optype.hpp index 3780612a..64a7fbc2 100644 --- a/deps/ox/src/ox/model/optype.hpp +++ b/deps/ox/src/ox/model/optype.hpp @@ -23,22 +23,22 @@ namespace OpType { // empty default implementations of model functions template -Error modelRead(T*, O*) { +constexpr Error modelRead(T*, O*) { return OxError(1, "Model: modelRead not implemented"); } template -Error modelWrite(T*, O*) { +constexpr Error modelWrite(T*, O*) { return OxError(1, "Model: modelWrite not implemented"); } template -Error modelWriteDefinition(T*, O*) { +constexpr Error modelWriteDefinition(T*, O*) { return OxError(1, "Model: modelWriteDefinition not implemented"); } template -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); diff --git a/deps/ox/src/ox/model/types.hpp b/deps/ox/src/ox/model/types.hpp index 626b97de..57e7ab7b 100644 --- a/deps/ox/src/ox/model/types.hpp +++ b/deps/ox/src/ox/model/types.hpp @@ -8,13 +8,46 @@ #pragma once +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + #include #include #include #include +#include namespace ox { +template +constexpr bool isVector(const T&) noexcept { + return false; +} + +template +constexpr bool isVector(const Vector*) noexcept { + return true; +} + +#if __has_include() +template +constexpr bool isVector(const std::vector*) noexcept { + return true; +} +#endif + +#if __has_include() +template +constexpr bool isVector(const QVector*) 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(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; }