1 #pragma once
2 
3 #include <pajlada/serialize.hpp>
4 #include <pajlada/settings/common.hpp>
5 #include <pajlada/settings/equal.hpp>
6 #include <pajlada/settings/internal.hpp>
7 #include <pajlada/settings/settingmanager.hpp>
8 #include <pajlada/settings/signalargs.hpp>
9 
10 #include <rapidjson/document.h>
11 #include <rapidjson/pointer.h>
12 #include <pajlada/signals/signal.hpp>
13 
14 #include <atomic>
15 #include <functional>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 namespace pajlada {
21 namespace Settings {
22 
23 class SettingData
24 {
25     SettingData(std::string _path, std::weak_ptr<SettingManager> _instance);
26 
27     // Setting path (i.e. /a/b/c/3/d/e)
28     const std::string path;
29 
30     std::weak_ptr<SettingManager> instance;
31 
32     std::atomic<int> updateIteration{};
33 
34 public:
35     Signals::Signal<const rapidjson::Value &, const SignalArgs &> updated;
36 
37     const std::string &getPath() const;
38 
39     void notifyUpdate(const rapidjson::Value &value, SignalArgs args);
40 
41     bool
marshalJSON(const rapidjson::Value & v)42     marshalJSON(const rapidjson::Value &v)
43     {
44         auto locked = this->instance.lock();
45         if (!locked) {
46             return false;
47         }
48 
49         return locked->set(this->path.c_str(), v);
50     }
51 
52     template <typename Type>
53     bool
marshal(const Type & v,SignalArgs args=SignalArgs ())54     marshal(const Type &v, SignalArgs args = SignalArgs())
55     {
56         auto locked = this->instance.lock();
57         if (!locked) {
58             return false;
59         }
60 
61         auto jsonValue =
62             Serialize<Type>::get(v, locked->document.GetAllocator());
63 
64         return locked->set(this->path.c_str(), jsonValue, std::move(args));
65     }
66 
67     rapidjson::Value *
unmarshalJSON()68     unmarshalJSON()
69     {
70         return this->get();
71     }
72 
73     template <typename Type>
74     ValueResult<Type>
unmarshal() const75     unmarshal() const
76     {
77         auto *ptr = this->get();
78 
79         if (ptr == nullptr) {
80             return {OptionalNull, -1};
81         }
82 
83         return {Deserialize<Type>::get(*ptr), this->getUpdateIteration()};
84     }
85 
86     int getUpdateIteration() const;
87 
88 private:
89     friend class SettingManager;
90 
91     rapidjson::Value *get() const;
92 };
93 
94 }  // namespace Settings
95 }  // namespace pajlada
96