From 112c02f40806f550370b3928f3c1965b5bee5262 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 8 May 2021 20:16:32 +0100 Subject: Implement writing shared objects with @id --- lib/persistence.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++ lib/persistence.h | 66 +++++++++++++++++++++-------------------------------- 2 files changed, 82 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/persistence.cpp b/lib/persistence.cpp index 4f1be8f..b85bff2 100644 --- a/lib/persistence.cpp +++ b/lib/persistence.cpp @@ -1,5 +1,6 @@ #include "persistence.h" #include +#include namespace Persistence { using Factories @@ -26,6 +27,61 @@ namespace Persistence { return namedTypeFactories.at(t).second(); } + [[nodiscard]] std::string + Persistable::getId() const + { + std::stringstream ss; + ss << std::hex << this; + return ss.str(); + } + + PersistenceSelect::PersistenceSelect(const std::string & n) : name {n} { } + + PersistenceStore::NameAction + PersistenceSelect::setName(const std::string_view key) + { + return (key == name) ? NameAction::Push : NameAction::Ignore; + } + + void + PersistenceSelect::setType(const std::string_view, const Persistable *) + { + } + + PersistenceWrite::PersistenceWrite(const Writer & o, bool sh) : out {o}, shared {sh} { } + + PersistenceStore::NameAction + PersistenceWrite::setName(const std::string_view key) + { + if (!first) { + out.nextValue(); + } + else { + first = false; + } + out.pushKey(key); + return NameAction::HandleAndContinue; + } + + void + PersistenceWrite::selHandler() + { + this->sel->write(out); + }; + + void + PersistenceWrite::setType(const std::string_view tn, const Persistable * p) + { + out.pushKey("@typeid"); + out.pushValue(tn); + first = false; + if (shared) { + out.nextValue(); + out.pushKey("@id"); + out.pushValue(p->getId()); + } + } + void Selection::setValue(float) { diff --git a/lib/persistence.h b/lib/persistence.h index 9a143c4..0eba1ab 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -99,6 +99,7 @@ namespace Persistence { } }; + struct Persistable; struct PersistenceStore { template [[nodiscard]] inline bool persistType(const T * const, const std::type_info & ti); @@ -119,60 +120,33 @@ namespace Persistence { virtual NameAction setName(const std::string_view key) = 0; virtual void selHandler() {}; - virtual void setType(const std::string_view) = 0; + virtual void setType(const std::string_view, const Persistable *) = 0; SelectionPtr sel {}; }; struct PersistenceSelect : public PersistenceStore { - explicit PersistenceSelect(const std::string & n) : name {n} { } + explicit PersistenceSelect(const std::string & n); - NameAction - setName(const std::string_view key) override - { - return (key == name) ? NameAction::Push : NameAction::Ignore; - } + NameAction setName(const std::string_view key) override; - void - setType(const std::string_view) override - { - } + void setType(const std::string_view, const Persistable *) override; const std::string & name; }; struct PersistenceWrite : public PersistenceStore { - explicit PersistenceWrite(const Writer & o) : out {o} { } + explicit PersistenceWrite(const Writer & o, bool sh); - NameAction - setName(const std::string_view key) override - { - if (!first) { - out.nextValue(); - } - else { - first = false; - } - out.pushKey(key); - return NameAction::HandleAndContinue; - } + NameAction setName(const std::string_view key) override; - void - selHandler() override - { - this->sel->write(out); - }; + void selHandler() override; - void - setType(const std::string_view tn) override - { - out.pushKey("@typeid"); - out.pushValue(tn); - first = false; - } + void setType(const std::string_view tn, const Persistable * p) override; bool first {true}; const Writer & out; + bool shared; }; template @@ -267,6 +241,8 @@ namespace Persistence { virtual bool persist(PersistenceStore & store) = 0; + [[nodiscard]] virtual std::string getId() const; + template [[nodiscard]] constexpr static auto typeName() @@ -292,20 +268,22 @@ namespace Persistence { template inline bool - PersistenceStore::persistType(const T * const, const std::type_info & ti) + PersistenceStore::persistType(const T * const v, const std::type_info & ti) { if constexpr (!std::is_abstract_v) { [[maybe_unused]] constexpr auto f = &Persistable::addFactory; } if (typeid(std::decay_t) == ti) { - setType(Persistable::typeName()); + setType(Persistable::typeName(), v); } return true; } - // TODO Move this + // TODO Move these using SharedObjects = std::map>; inline SharedObjects sharedObjects; + using SeenSharedObjects = std::map; + inline SeenSharedObjects seenSharedObjects; template struct SelectionPtrBase : public SelectionV { using T = typename Ptr::element_type; @@ -380,7 +358,7 @@ namespace Persistence { write(const Writer & out) const override { out.beginObject(); - PersistenceWrite pw {out}; + PersistenceWrite pw {out, shared}; this->v->persist(pw); out.endObject(); } @@ -425,6 +403,14 @@ namespace Persistence { write(const Writer & out) const override { if (this->v) { + if constexpr (shared) { + if (const auto existing = seenSharedObjects.find(std::to_address(this->v)); + existing != seenSharedObjects.end()) { + out.pushValue(existing->second); + return; + } + seenSharedObjects.emplace(std::to_address(this->v), this->v->getId()); + } SelectionObj {this->v}.write(out); } else { -- cgit v1.2.3