From 71c5280bc6393669777147b5036dc510e74d93c4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 17 Apr 2021 21:41:26 +0100 Subject: Second swing persistance Mostly functional JSON deserialising for most types. --- lib/jsonParse.impl.cpp | 23 +++--- lib/jsonParse.ll | 2 + lib/persistance.cpp | 74 ++++++++++++++++++ lib/persistance.h | 201 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+), 10 deletions(-) create mode 100644 lib/persistance.cpp create mode 100644 lib/persistance.h (limited to 'lib') diff --git a/lib/jsonParse.impl.cpp b/lib/jsonParse.impl.cpp index 27e73b4..3ed8e62 100644 --- a/lib/jsonParse.impl.cpp +++ b/lib/jsonParse.impl.cpp @@ -1,4 +1,7 @@ #include "jsonParse.h" +#include +#include +#include void json::jsonParser::LexerError(const char * msg) @@ -16,24 +19,24 @@ void json::jsonParser::appendEscape(unsigned long cp, std::string & str) { if (cp <= 0x7F) { - str += cp; + str += (char)cp; } else if (cp <= 0x7FF) { - str += (cp >> 6) + 192; - str += (cp & 63) + 128; + str += char((cp >> 6) + 192); + str += char((cp & 63) + 128); } else if (0xd800 <= cp && cp <= 0xdfff) { throw std::range_error("Invalid UTF-8 sequence"); } else if (cp <= 0xFFFF) { - str += (cp >> 12) + 224; - str += ((cp >> 6) & 63) + 128; - str += (cp & 63) + 128; + str += char((cp >> 12) + 224); + str += char(((cp >> 6) & 63) + 128); + str += char((cp & 63) + 128); } else if (cp <= 0x10FFFF) { - str += (cp >> 18) + 240; - str += ((cp >> 12) & 63) + 128; - str += ((cp >> 6) & 63) + 128; - str += (cp & 63) + 128; + str += char((cp >> 18) + 240); + str += char(((cp >> 12) & 63) + 128); + str += char(((cp >> 6) & 63) + 128); + str += char((cp & 63) + 128); } } diff --git a/lib/jsonParse.ll b/lib/jsonParse.ll index 0fc27e9..7e0b8ca 100644 --- a/lib/jsonParse.ll +++ b/lib/jsonParse.ll @@ -9,6 +9,8 @@ %{ #include +#include +class jsonBaseFlexLexer; #include "jsonParse.h" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" diff --git a/lib/persistance.cpp b/lib/persistance.cpp new file mode 100644 index 0000000..7539b44 --- /dev/null +++ b/lib/persistance.cpp @@ -0,0 +1,74 @@ +#include "persistance.h" +#include + +namespace Persistanace { + using NamedTypeFactories = std::map()>>; + static NamedTypeFactories namedTypeFactories; + + void + Persistable::addFactory(const std::string_view t, std::function()> f) + { + namedTypeFactories.emplace(t, std::move(f)); + } + + std::unique_ptr + Persistable::callFactory(const std::string_view t) + { + return namedTypeFactories.at(t)(); + } + + void + Selection::operator()(float &) + { + throw std::runtime_error("Unexpected float"); + } + + void + Selection::operator()(bool &) + { + throw std::runtime_error("Unexpected bool"); + } + + void + Selection::operator()(const std::nullptr_t &) + { + throw std::runtime_error("Unexpected null"); + } + + void + Selection::operator()(std::string &) + { + throw std::runtime_error("Unexpected string"); + } + + void + Selection::BeginArray(Stack &) + { + throw std::runtime_error("Unexpected array"); + } + + SelectionPtr + Selection::BeginObject() + { + throw std::runtime_error("Unexpected object"); + } + + void + Selection::beforeValue(Stack &) + { + throw std::runtime_error("Unexpected value"); + } + + SelectionPtr + Selection::select(const std::string &) + { + throw std::runtime_error("Unexpected persist"); + } + + static_assert(!SelectionT::ArrayLike); + static_assert(!SelectionT::ArrayLike); + static_assert(!SelectionT::ArrayLike); + static_assert(SelectionT>::ArrayLike); + static_assert(SelectionT::ArrayLike); + static_assert(SelectionT>::ArrayLike); +} diff --git a/lib/persistance.h b/lib/persistance.h new file mode 100644 index 0000000..75222e0 --- /dev/null +++ b/lib/persistance.h @@ -0,0 +1,201 @@ +#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 -- cgit v1.2.3