summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/persistence.cpp56
-rw-r--r--lib/persistence.h66
2 files changed, 82 insertions, 40 deletions
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 <map>
+#include <sstream>
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<typename T> [[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<glm::length_t L, typename T, glm::qualifier Q>
@@ -267,6 +241,8 @@ namespace Persistence {
virtual bool persist(PersistenceStore & store) = 0;
+ [[nodiscard]] virtual std::string getId() const;
+
template<typename T>
[[nodiscard]] constexpr static auto
typeName()
@@ -292,20 +268,22 @@ namespace Persistence {
template<typename T>
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<T>) {
[[maybe_unused]] constexpr auto f = &Persistable::addFactory<T>;
}
if (typeid(std::decay_t<T>) == ti) {
- setType(Persistable::typeName<T>());
+ setType(Persistable::typeName<T>(), v);
}
return true;
}
- // TODO Move this
+ // TODO Move these
using SharedObjects = std::map<std::string, std::shared_ptr<Persistable>>;
inline SharedObjects sharedObjects;
+ using SeenSharedObjects = std::map<void *, std::string>;
+ inline SeenSharedObjects seenSharedObjects;
template<typename Ptr, bool shared> struct SelectionPtrBase : public SelectionV<Ptr> {
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 {