diff options
-rw-r--r-- | lib/persistence.h | 173 | ||||
-rw-r--r-- | test/fixtures/json/shared_ptr3.json | 8 | ||||
-rw-r--r-- | test/test-persistence.cpp | 8 |
3 files changed, 71 insertions, 118 deletions
diff --git a/lib/persistence.h b/lib/persistence.h index ed21ec8..5ef1400 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -179,93 +179,12 @@ namespace Persistence { return true; } - template<typename T> struct SelectionT<std::unique_ptr<T>> : public SelectionV<std::unique_ptr<T>> { - using Ptr = std::unique_ptr<T>; - struct SelectionObj : public SelectionV<Ptr> { - struct MakeObjectByTypeName : public SelectionV<Ptr> { - using SelectionV<Ptr>::SelectionV; - - void - setValue(std::string & type) override - { - auto no = Persistable::callFactory(type); - if (dynamic_cast<T *>(no.get())) { - this->v.reset(static_cast<T *>(no.release())); - } - } - }; - - using SelectionV<Ptr>::SelectionV; - - SelectionPtr - select(const std::string & mbr) override - { - using namespace std::literals; - if (mbr == "@typeid"sv) { - if (this->v) { - throw std::runtime_error("cannot set object type after creation"); - } - return this->template make_s<MakeObjectByTypeName>(this->v); - } - else { - if (!this->v) { - if constexpr (std::is_abstract_v<T>) { - throw std::runtime_error("cannot select member of null object"); - } - else { - this->v = std::make_unique<T>(); - } - } - PersistenceStore ps {mbr}; - if (this->v->persist(ps)) { - throw std::runtime_error("cannot find member: " + mbr); - } - return std::move(ps.sel); - } - } - - void - endObject(Stack & stk) override - { - if (!this->v) { - if constexpr (std::is_abstract_v<T>) { - throw std::runtime_error("cannot default create abstract object"); - } - else { - this->v = std::make_unique<T>(); - } - } - stk.pop(); - } - }; - - using SelectionV<Ptr>::SelectionV; - - void - setValue(const std::nullptr_t &) override - { - this->v.reset(); - } - - void - beginObject(Stack & stk) override - { - stk.push(this->template make_s<SelectionObj>(this->v)); - } - - void - endObject(Stack & stk) override - { - stk.pop(); - } - }; - // TODO Move this using SharedObjects = std::map<std::string, std::shared_ptr<Persistable>>; inline SharedObjects sharedObjects; - template<typename T> struct SelectionT<std::shared_ptr<T>> : public SelectionV<std::shared_ptr<T>> { - using Ptr = std::shared_ptr<T>; + template<typename Ptr, bool shared> struct SelectionPtrBase : public SelectionV<Ptr> { + using T = typename Ptr::element_type; struct SelectionObj : public SelectionV<Ptr> { struct MakeObjectByTypeName : public SelectionV<Ptr> { using SelectionV<Ptr>::SelectionV; @@ -273,9 +192,17 @@ namespace Persistence { void setValue(std::string & type) override { - auto no = Persistable::callSharedFactory(type); - if (auto tno = std::dynamic_pointer_cast<T>(no)) { - this->v = std::move(tno); + if constexpr (shared) { + auto no = Persistable::callSharedFactory(type); + if (auto tno = std::dynamic_pointer_cast<T>(no)) { + this->v = std::move(tno); + } + } + else { + auto no = Persistable::callFactory(type); + if (dynamic_cast<T *>(no.get())) { + this->v.reset(static_cast<T *>(no.release())); + } } } }; @@ -302,41 +229,43 @@ namespace Persistence { } return this->template make_s<MakeObjectByTypeName>(this->v); } - else if (mbr == "@id"sv) { - return this->template make_s<RememberObjectById>(this->v); - } - else { - if (!this->v) { - if constexpr (std::is_abstract_v<T>) { - throw std::runtime_error("cannot select member of null object"); - } - else { - this->v = std::make_shared<T>(); - } - } - PersistenceStore ps {mbr}; - if (this->v->persist(ps)) { - throw std::runtime_error("cannot find member: " + mbr); + if constexpr (shared) { + if (mbr == "@id"sv) { + return this->template make_s<RememberObjectById>(this->v); } - return std::move(ps.sel); } + make_default_as_needed(this->v); + PersistenceStore ps {mbr}; + if (this->v->persist(ps)) { + throw std::runtime_error("cannot find member: " + mbr); + } + return std::move(ps.sel); } void endObject(Stack & stk) override { - if (!this->v) { - if constexpr (std::is_abstract_v<T>) { - throw std::runtime_error("cannot default create abstract object"); - } - else { - this->v = std::make_shared<T>(); - } - } + make_default_as_needed(this->v); stk.pop(); } }; + static inline void + make_default_as_needed(Ptr & v) + { + if (!v) { + if constexpr (std::is_abstract_v<T>) { + throw std::runtime_error("cannot select member of null abstract object"); + } + else if constexpr (shared) { + v = std::make_shared<T>(); + } + else { + v = std::make_unique<T>(); + } + } + } + using SelectionV<Ptr>::SelectionV; void @@ -346,14 +275,6 @@ namespace Persistence { } void - setValue(std::string & id) override - { - if (auto teo = std::dynamic_pointer_cast<T>(sharedObjects.at(id))) { - this->v = std::move(teo); - } - } - - void beginObject(Stack & stk) override { stk.push(this->template make_s<SelectionObj>(this->v)); @@ -365,6 +286,22 @@ namespace Persistence { stk.pop(); } }; + + template<typename T> struct SelectionT<std::unique_ptr<T>> : public SelectionPtrBase<std::unique_ptr<T>, false> { + using SelectionPtrBase<std::unique_ptr<T>, false>::SelectionPtrBase; + }; + + template<typename T> struct SelectionT<std::shared_ptr<T>> : public SelectionPtrBase<std::shared_ptr<T>, true> { + using SelectionPtrBase<std::shared_ptr<T>, true>::SelectionPtrBase; + + void + setValue(std::string & id) override + { + if (auto teo = std::dynamic_pointer_cast<T>(sharedObjects.at(id))) { + this->v = std::move(teo); + } + } + }; } #define STORE_TYPE store.persistType<std::decay_t<decltype(*this)>>() diff --git a/test/fixtures/json/shared_ptr3.json b/test/fixtures/json/shared_ptr3.json new file mode 100644 index 0000000..69f5e85 --- /dev/null +++ b/test/fixtures/json/shared_ptr3.json @@ -0,0 +1,8 @@ +{ + "@typeid": "SharedTestObject", + "sptr": { + "@typeid": "SubObject", + "@id": "someid" + }, + "ssptr": {} +} diff --git a/test/test-persistence.cpp b/test/test-persistence.cpp index 6dcb94d..523ca41 100644 --- a/test/test-persistence.cpp +++ b/test/test-persistence.cpp @@ -215,6 +215,14 @@ BOOST_FIXTURE_TEST_CASE(load_shared_object2, JPP) BOOST_CHECK_EQUAL(to->ssptr.use_count(), 2); } +BOOST_FIXTURE_TEST_CASE(load_shared_object3, JPP) +{ + auto to = load_json<std::unique_ptr<SharedTestObject>>(FIXTURESDIR "json/shared_ptr3.json"); + BOOST_CHECK(to->sptr); + BOOST_CHECK(to->ssptr); + BOOST_CHECK_NE(to->sptr, to->ssptr); +} + BOOST_FIXTURE_TEST_CASE(load_shared_object_null, JPP) { auto to = load_json<std::unique_ptr<SharedTestObject>>(FIXTURESDIR "json/shared_ptr_null.json"); |