diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-03-28 17:17:11 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-11-07 16:41:37 +0000 |
commit | 3cd4ff83a253e098e6524df5be3a686727e4f50b (patch) | |
tree | cfbfaac4753d6321339f8653c3cabaca440afec8 /test/test-persistance.cpp | |
parent | Compile stb wrapper in C++ mode (diff) | |
download | ilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.tar.bz2 ilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.tar.xz ilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.zip |
Initial commit of basis persistence
JSON parser lifted almost verbatim for libjsonpp running into some
custom code for populating ilt objects. Pretty minimal per object code
requirements.
Diffstat (limited to 'test/test-persistance.cpp')
-rw-r--r-- | test/test-persistance.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/test/test-persistance.cpp b/test/test-persistance.cpp new file mode 100644 index 0000000..7d66675 --- /dev/null +++ b/test/test-persistance.cpp @@ -0,0 +1,281 @@ +#define BOOST_TEST_MODULE test_persistance + +#include <boost/test/unit_test.hpp> + +#include <gfx/models/vertex.hpp> +#include <glm/glm.hpp> +#include <jsonParse.h> +#include <maths.h> +#include <memory> +#include <stack> +#include <stream_support.hpp> +#include <utility> +#include <variant> +#include <vector> + +struct PersistanceStore; +struct Selection; +using SelectionPtr = std::unique_ptr<Selection>; +struct Selection { + virtual ~Selection() = default; + virtual void + operator()(float &) + { + throw std::runtime_error("Unexpected float"); + } + virtual void + operator()(bool &) + { + throw std::runtime_error("Unexpected bool"); + } + virtual void + operator()(const std::nullptr_t &) + { + throw std::runtime_error("Unexpected null"); + } + virtual void + operator()(std::string &) + { + throw std::runtime_error("Unexpected string"); + } + virtual void + BeginArray() + { + throw std::runtime_error("Unexpected array"); + } + virtual SelectionPtr + BeginObject() + { + throw std::runtime_error("Unexpected object"); + } + virtual SelectionPtr select(std::string) + { + throw std::runtime_error("Unexpected persist"); + } +}; + +template<typename T> struct SelectionT : public Selection { + SelectionT(T & value) : v {value} { } + void + operator()(T & evalue) override + { + std::swap(v, evalue); + } + T & v; +}; + +template<glm::length_t L, glm::qualifier Q> struct SelectionT<glm::vec<L, float, Q>> : public Selection { + SelectionT(glm::vec3 & value) : v {value} + { + CLOG(__PRETTY_FUNCTION__); + } + void + operator()(float & value) override + { + v[idx++] = value; + } + void + BeginArray() override + { + } + glm::vec3 & v; + glm::vec3::length_type idx {0}; +}; + +template<typename T> struct SelectionT<std::vector<T>> : public Selection { + SelectionT(std::vector<T> & value) : v {value} { } + void + operator()(T & value) override + { + v.push_back(value); + } + void + BeginArray() + { + } + std::vector<T> & v; +}; + +struct TestObject; + +template<typename Ptr> struct MakeObjectByTypeName : public Selection { + MakeObjectByTypeName(Ptr & o) : o {o} { } + virtual void + operator()(std::string &) + { + o = std::make_unique<TestObject>(); // TODO shared_ptr + } + Ptr & o; +}; + +struct PersistanceStore { + // virtual bool persistType(const std::type_info &) = 0; + template<typename T> + bool + persistValue(const std::string_view & key, T & value) + { + if (key == name) { + sel = std::make_unique<SelectionT<T>>(std::ref(value)); + return false; + } + return true; + } + const std::string & name; + std::unique_ptr<Selection> sel {}; +}; + +template<typename Ptr> struct SelectionObj : public Selection { + SelectionObj(Ptr & o) : v {o} { } + + SelectionPtr + select(std::string mbr) override + { + if (mbr == "@typeid") { + return std::make_unique<MakeObjectByTypeName<Ptr>>(std::ref(v)); + } + else if (v) { + CLOG(mbr); + PersistanceStore ps {mbr}; + v->persist(ps); + return std::move(ps.sel); + } + throw std::runtime_error("cannot select member of null object"); + } + + Ptr & v; +}; + +template<typename T> struct SelectionT<std::unique_ptr<T>> : public Selection { + SelectionT(std::unique_ptr<T> & o) : v {o} { } + SelectionPtr + BeginObject() override + { + CLOG(__PRETTY_FUNCTION__); + return std::make_unique<SelectionObj<std::unique_ptr<T>>>(v); + } + std::unique_ptr<T> & v; +}; + +struct Persistable { + virtual void persist(PersistanceStore & store) = 0; +}; + +struct JsonLoadPersistanceStore : public json::jsonParser { + JsonLoadPersistanceStore(std::istream & in) : json::jsonParser {&in} { } + + std::stack<std::unique_ptr<Selection>> stk; + std::unique_ptr<Selection> selection; + + template<typename T> + void + loadState(std::unique_ptr<T> & t) + { + yy_push_state(0); + stk.push(std::make_unique<SelectionT<std::unique_ptr<T>>>(std::ref(t))); + yylex(); + } + void + BeginObject() override + { + CLOG(__FUNCTION__); + stk.push(stk.top()->BeginObject()); + } + void + BeginArray() override + { + CLOG(__FUNCTION__); + selection->BeginArray(); + } + void + PushBoolean(bool value) override + { + CLOG(__FUNCTION__); + (*selection)(value); + } + void + PushNumber(float value) override + { + CLOG(__FUNCTION__); + (*selection)(value); + } + void + PushNull() override + { + CLOG(__FUNCTION__); + (*selection)(nullptr); + } + void + PushText(std::string && value) override + { + CLOG(__FUNCTION__); + (*selection)(value); + } + void + PushKey(std::string && k) override + { + CLOG(__FUNCTION__); + selection = stk.top()->select(std::move(k)); + } + void + EndArray() override + { + CLOG(__FUNCTION__); + } + void + EndObject() override + { + CLOG(__FUNCTION__); + stk.pop(); + } +}; + +#define STORE_TYPE store.persistType(typeid(*this)) +#define STORE_MEMBER(mbr) store.persistValue(#mbr##sv, mbr) + +struct TestObject : public Persistable { + TestObject() = default; + + float flt {}; + std::string str {}; + bool bl {}; + glm::vec3 pos {}; + std::vector<float> flts; + + void + persist(PersistanceStore & store) override + { + using namespace std::literals; + STORE_MEMBER(flt) && STORE_MEMBER(str) && STORE_MEMBER(bl) && STORE_MEMBER(pos) && STORE_MEMBER(flts); + } +}; + +const std::string input(R"J({ + "@typeid": "TestObject", + "flt": 3.14, + "str": "Lovely string", + "bl": true, + "pos": [3.14, 6.28, 1.57], + "flts": [3.14, 6.28, 1.57, 0, -1, -3.14], +})J"); + +BOOST_AUTO_TEST_CASE(load_object) +{ + std::stringstream ss {input}; + JsonLoadPersistanceStore jlps {ss}; + std::unique_ptr<TestObject> to; + jlps.loadState(to); + + BOOST_CHECK_CLOSE(to->flt, 3.14, 0.01); + BOOST_CHECK_EQUAL(to->str, "Lovely string"); + BOOST_CHECK_EQUAL(to->bl, true); + BOOST_CHECK_CLOSE(to->pos[0], 3.14, 0.01); + BOOST_CHECK_CLOSE(to->pos[1], 6.28, 0.01); + BOOST_CHECK_CLOSE(to->pos[2], 1.57, 0.01); + BOOST_REQUIRE_EQUAL(to->flts.size(), 6); + BOOST_CHECK_CLOSE(to->flts[0], 3.14, 0.01); + BOOST_CHECK_CLOSE(to->flts[1], 6.28, 0.01); + BOOST_CHECK_CLOSE(to->flts[2], 1.57, 0.01); + BOOST_CHECK_CLOSE(to->flts[3], 0, 0.01); + BOOST_CHECK_CLOSE(to->flts[4], -1, 0.01); + BOOST_CHECK_CLOSE(to->flts[5], -3.14, 0.01); +} |