From 9923219ce7e1f791b079ecaf21cb20d0938f8d6a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 1 May 2021 18:29:26 +0100 Subject: Common implementation for shared and unique pointers --- lib/persistence.h | 173 ++++++++++++------------------------ test/fixtures/json/shared_ptr3.json | 8 ++ test/test-persistence.cpp | 8 ++ 3 files changed, 71 insertions(+), 118 deletions(-) create mode 100644 test/fixtures/json/shared_ptr3.json 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 struct SelectionT> : public SelectionV> { - using Ptr = std::unique_ptr; - struct SelectionObj : public SelectionV { - struct MakeObjectByTypeName : public SelectionV { - using SelectionV::SelectionV; - - void - setValue(std::string & type) override - { - auto no = Persistable::callFactory(type); - if (dynamic_cast(no.get())) { - this->v.reset(static_cast(no.release())); - } - } - }; - - using SelectionV::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(this->v); - } - else { - if (!this->v) { - if constexpr (std::is_abstract_v) { - throw std::runtime_error("cannot select member of null object"); - } - else { - this->v = std::make_unique(); - } - } - 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) { - throw std::runtime_error("cannot default create abstract object"); - } - else { - this->v = std::make_unique(); - } - } - stk.pop(); - } - }; - - using SelectionV::SelectionV; - - void - setValue(const std::nullptr_t &) override - { - this->v.reset(); - } - - void - beginObject(Stack & stk) override - { - stk.push(this->template make_s(this->v)); - } - - void - endObject(Stack & stk) override - { - stk.pop(); - } - }; - // TODO Move this using SharedObjects = std::map>; inline SharedObjects sharedObjects; - template struct SelectionT> : public SelectionV> { - using Ptr = std::shared_ptr; + template struct SelectionPtrBase : public SelectionV { + using T = typename Ptr::element_type; struct SelectionObj : public SelectionV { struct MakeObjectByTypeName : public SelectionV { using SelectionV::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(no)) { - this->v = std::move(tno); + if constexpr (shared) { + auto no = Persistable::callSharedFactory(type); + if (auto tno = std::dynamic_pointer_cast(no)) { + this->v = std::move(tno); + } + } + else { + auto no = Persistable::callFactory(type); + if (dynamic_cast(no.get())) { + this->v.reset(static_cast(no.release())); + } } } }; @@ -302,41 +229,43 @@ namespace Persistence { } return this->template make_s(this->v); } - else if (mbr == "@id"sv) { - return this->template make_s(this->v); - } - else { - if (!this->v) { - if constexpr (std::is_abstract_v) { - throw std::runtime_error("cannot select member of null object"); - } - else { - this->v = std::make_shared(); - } - } - 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(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) { - throw std::runtime_error("cannot default create abstract object"); - } - else { - this->v = std::make_shared(); - } - } + 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) { + throw std::runtime_error("cannot select member of null abstract object"); + } + else if constexpr (shared) { + v = std::make_shared(); + } + else { + v = std::make_unique(); + } + } + } + using SelectionV::SelectionV; void @@ -345,14 +274,6 @@ namespace Persistence { this->v.reset(); } - void - setValue(std::string & id) override - { - if (auto teo = std::dynamic_pointer_cast(sharedObjects.at(id))) { - this->v = std::move(teo); - } - } - void beginObject(Stack & stk) override { @@ -365,6 +286,22 @@ namespace Persistence { stk.pop(); } }; + + template struct SelectionT> : public SelectionPtrBase, false> { + using SelectionPtrBase, false>::SelectionPtrBase; + }; + + template struct SelectionT> : public SelectionPtrBase, true> { + using SelectionPtrBase, true>::SelectionPtrBase; + + void + setValue(std::string & id) override + { + if (auto teo = std::dynamic_pointer_cast(sharedObjects.at(id))) { + this->v = std::move(teo); + } + } + }; } #define STORE_TYPE store.persistType>() 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>(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>(FIXTURESDIR "json/shared_ptr_null.json"); -- cgit v1.2.3