#ifndef PERSISTANCE_H #define PERSISTANCE_H #include #include #include #include #include #include #include #include #include #include #include namespace glm { template struct vec; } namespace Persistanace { struct Selection; using SelectionPtr = std::unique_ptr; using Stack = std::stack; struct Selection { Selection() = default; virtual ~Selection() = default; DEFAULT_MOVE_COPY(Selection); virtual void operator()(float &); virtual void operator()(bool &); virtual void operator()(const std::nullptr_t &); virtual void operator()(std::string &); virtual void BeginArray(Stack &); virtual SelectionPtr BeginObject(); virtual void beforeValue(Stack &); virtual SelectionPtr select(const std::string &); }; template struct SelectionT : public Selection { explicit SelectionT(T & value) : v {value} { } void beforeValue(Stack &) override { } void operator()(T & evalue) override { std::swap(v, evalue); } static constexpr bool ArrayLike {false}; T & v; }; struct PersistanceStore { // virtual bool persistType(const std::type_info &) = 0; template bool persistValue(const std::string_view & key, T & value) { if (key == name) { sel = std::make_unique>(std::ref(value)); return false; } return true; } const std::string & name; SelectionPtr sel {}; }; template struct SelectionT> : public Selection { explicit SelectionT(glm::vec & value) : v {value} { } void BeginArray(Stack &) override { } void beforeValue(Stack & stk) override { stk.push(std::make_unique>(std::ref(v[idx++]))); } static constexpr bool ArrayLike {true}; glm::vec & v; glm::length_t idx {0}; }; template struct SelectionT> : public Selection { explicit SelectionT(std::vector & value) : v {value} { } void BeginArray(Stack &) override { } void beforeValue(Stack & stk) override { stk.push(std::make_unique>(std::ref(v.emplace_back()))); } static constexpr bool ArrayLike {true}; std::vector & v; }; template concept ArrayLike = SelectionT::ArrayLike; template struct SelectionT> : public Selection { explicit SelectionT(std::vector & value) : v {value} { } void BeginArray(Stack & stk) override { stk.push(std::make_unique>(std::ref(v.emplace_back()))); } static constexpr bool ArrayLike {true}; std::vector & v; }; struct Persistable { Persistable() = default; virtual ~Persistable() = default; DEFAULT_MOVE_COPY(Persistable); virtual void persist(PersistanceStore & store) = 0; static void addFactory(const std::string_view, std::function()>); static std::unique_ptr callFactory(const std::string_view); }; template struct SelectionT> : public Selection { using Ptr = std::unique_ptr; struct SelectionObj : public Selection { struct MakeObjectByTypeName : public Selection { explicit MakeObjectByTypeName(Ptr & o) : o {o} { } void beforeValue(Stack &) override { } void operator()(std::string & type) override { auto no = Persistable::callFactory(type); if (dynamic_cast(no.get())) { o.reset(static_cast(no.release())); } } Ptr & o; }; explicit SelectionObj(Ptr & o) : v {o} { } SelectionPtr select(const std::string & mbr) override { using namespace std::literals; if (mbr == "@typeid"sv) { if (v) { throw std::runtime_error("cannot set object type after creation"); } return std::make_unique(std::ref(v)); } else { if (!v) { if constexpr (!std::is_abstract_v) { v = std::make_unique(); } throw std::runtime_error("cannot select member of null object"); } PersistanceStore ps {mbr}; v->persist(ps); return std::move(ps.sel); } } Ptr & v; }; explicit SelectionT(std::unique_ptr & o) : v {o} { } SelectionPtr BeginObject() override { return std::make_unique(v); } std::unique_ptr & v; }; } #endif