File: storage.hpp

package info (click to toggle)
openmw 0.49.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 33,992 kB
  • sloc: cpp: 372,479; xml: 2,149; sh: 1,403; python: 797; makefile: 26
file content (135 lines) | stat: -rw-r--r-- 4,831 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#ifndef COMPONENTS_LUA_STORAGE_H
#define COMPONENTS_LUA_STORAGE_H

#include <map>
#include <sol/sol.hpp>
#include <stdexcept>

#include "asyncpackage.hpp"
#include "serialization.hpp"

namespace LuaUtil
{
    class LuaView;

    class LuaStorage
    {
    public:
        static void initLuaBindings(LuaUtil::LuaView& view);
        static sol::table initGlobalPackage(LuaUtil::LuaView& view, LuaStorage* globalStorage);
        static sol::table initLocalPackage(LuaUtil::LuaView& view, LuaStorage* globalStorage);
        static sol::table initPlayerPackage(
            LuaUtil::LuaView& view, LuaStorage* globalStorage, LuaStorage* playerStorage);
        static sol::table initMenuPackage(LuaUtil::LuaView& view, LuaStorage* globalStorage, LuaStorage* playerStorage);

        explicit LuaStorage() {}

        void clearTemporaryAndRemoveCallbacks();
        void load(lua_State* L, const std::filesystem::path& path);
        void save(lua_State* L, const std::filesystem::path& path) const;

        sol::object getSection(lua_State* L, std::string_view sectionName, bool readOnly, bool forMenuScripts = false);
        sol::object getMutableSection(lua_State* L, std::string_view sectionName, bool forMenuScripts = false)
        {
            return getSection(L, sectionName, false, forMenuScripts);
        }
        sol::object getReadOnlySection(lua_State* L, std::string_view sectionName)
        {
            return getSection(L, sectionName, true);
        }
        sol::table getAllSections(lua_State* L, bool readOnly = false);

        void setSingleValue(std::string_view section, std::string_view key, const sol::object& value)
        {
            getSection(section)->set(key, value);
        }

        void setSectionValues(std::string_view section, const sol::optional<sol::table>& values)
        {
            getSection(section)->setAll(values);
        }

        class Listener
        {
        public:
            virtual ~Listener() = default;
            virtual void valueChanged(
                std::string_view section, std::string_view key, const sol::object& value) const = 0;
            virtual void sectionReplaced(std::string_view section, const sol::optional<sol::table>& values) const = 0;
        };
        void setListener(const Listener* listener) { mListener = listener; }
        void setActive(bool active) { mActive = active; }

    private:
        class Value
        {
        public:
            Value() {}
            Value(const sol::object& value)
                : mSerializedValue(serialize(value))
            {
            }
            sol::object getCopy(lua_State* L) const;
            sol::object getReadOnly(lua_State* L) const;

        private:
            std::string mSerializedValue;
            mutable sol::main_object mReadOnlyValue = sol::nil;
        };

        struct Section
        {
            enum LifeTime
            {
                Persistent,
                GameSession,
                Temporary
            };

            explicit Section(LuaStorage* storage, std::string name)
                : mStorage(storage)
                , mSectionName(std::move(name))
            {
            }
            const Value& get(std::string_view key) const;
            void set(std::string_view key, const sol::object& value);
            void setAll(const sol::optional<sol::table>& values);
            sol::table asTable(lua_State* L);
            void runCallbacks(sol::optional<std::string_view> changedKey);
            void throwIfCallbackRecursionIsTooDeep();

            LuaStorage* mStorage;
            std::string mSectionName;
            std::map<std::string, Value, std::less<>> mValues;
            std::vector<Callback> mCallbacks;
            std::vector<Callback> mMenuScriptsCallbacks; // menu callbacks are in a separate vector because we don't
                                                         // remove them in clear()
            LifeTime mLifeTime = Persistent;
            static Value sEmpty;

            void checkIfActive() const { mStorage->checkIfActive(); }
        };
        struct SectionView
        {
            std::shared_ptr<Section> mSection;
            bool mReadOnly;
            bool mForMenuScripts = false;
        };

        const std::shared_ptr<Section>& getSection(std::string_view sectionName);

        std::map<std::string_view, std::shared_ptr<Section>> mData;
        const Listener* mListener = nullptr;
        std::set<const Section*> mRunningCallbacks;
        bool mActive = false;
        void checkIfActive() const
        {
            if (!mActive)
                throw std::logic_error("Trying to access inactive storage");
        }
        static void registerLifeTime(LuaUtil::LuaView& view, sol::table& res);
    };

}

#endif // COMPONENTS_LUA_STORAGE_H