Civ backgrounds for minimap
[0ad.git] / source / ps / ConfigDB.h
blob55d643d595095ffa90dcb5492fb76222662cb4d8
1 /* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
19 CConfigDB - Load, access and store configuration variables
21 TDD : http://www.wildfiregames.com/forum/index.php?showtopic=1125
22 OVERVIEW:
24 JavaScript: Check this documentation: http://trac.wildfiregames.com/wiki/Exposed_ConfigDB_Functions
27 #ifndef INCLUDED_CONFIGDB
28 #define INCLUDED_CONFIGDB
30 #include "lib/file/vfs/vfs_path.h"
31 #include "ps/CStr.h"
33 #include <array>
34 #include <map>
35 #include <memory>
36 #include <mutex>
37 #include <vector>
39 /**
40 * Namespace priorities:
41 * - Command line args override everything
42 * - User supersedes HWDetect (let the user try crashing his system).
43 * - HWDetect supersedes mods & default -> mods can mod hwdetect itself.
44 * - SYSTEM is used for local.cfg and is basically for setting custom defaults.
46 enum EConfigNamespace
48 CFG_DEFAULT,
49 CFG_MOD,
50 CFG_SYSTEM,
51 CFG_HWDETECT,
52 CFG_USER,
53 CFG_COMMAND,
54 CFG_LAST
57 using CConfigValueSet = std::vector<CStr>;
59 // Opaque data type so that callers that hook into ConfigDB can delete their hooks.
60 // Would be defined in CConfigDB but then it couldn't be forward-declared, which is rather annoying.
61 // Actually defined below - requires access to CConfigDB.
62 class CConfigDBHook;
64 #define g_ConfigDB (*CConfigDB::Instance())
66 class CConfigDB
68 friend CConfigDBHook;
69 public:
70 CConfigDB();
71 ~CConfigDB();
72 CConfigDB(const CConfigDB&) = delete;
73 CConfigDB(CConfigDB&&) = delete;
75 static void Initialise();
76 static void Shutdown();
77 static bool IsInitialised();
78 static CConfigDB* Instance();
80 /**
81 * Attempt to retrieve the value of a config variable with the given name;
82 * will search CFG_COMMAND first, and then all namespaces from the specified
83 * namespace down.
85 void GetValue(EConfigNamespace ns, const CStr& name, bool& value);
86 ///@copydoc CConfigDB::GetValue
87 void GetValue(EConfigNamespace ns, const CStr& name, int& value);
88 ///@copydoc CConfigDB::GetValue
89 void GetValue(EConfigNamespace ns, const CStr& name, u32& value);
90 ///@copydoc CConfigDB::GetValue
91 void GetValue(EConfigNamespace ns, const CStr& name, float& value);
92 ///@copydoc CConfigDB::GetValue
93 void GetValue(EConfigNamespace ns, const CStr& name, double& value);
94 ///@copydoc CConfigDB::GetValue
95 void GetValue(EConfigNamespace ns, const CStr& name, std::string& value);
97 /**
98 * Returns true if changed with respect to last write on file
100 bool HasChanges(EConfigNamespace ns) const;
102 void SetChanges(EConfigNamespace ns, bool value);
105 * Attempt to retrieve a vector of values corresponding to the given setting;
106 * will search CFG_COMMAND first, and then all namespaces from the specified
107 * namespace down.
109 void GetValues(EConfigNamespace ns, const CStr& name, CConfigValueSet& values) const;
112 * Returns the namespace that the value returned by GetValues was defined in,
113 * or CFG_LAST if it wasn't defined at all.
115 EConfigNamespace GetValueNamespace(EConfigNamespace ns, const CStr& name) const;
118 * Retrieve a map of values corresponding to settings whose names begin
119 * with the given prefix;
120 * will search all namespaces from default up to the specified namespace.
122 std::map<CStr, CConfigValueSet> GetValuesWithPrefix(EConfigNamespace ns, const CStr& prefix) const;
125 * Save a config value in the specified namespace. If the config variable
126 * existed the value is replaced.
128 void SetValueString(EConfigNamespace ns, const CStr& name, const CStr& value);
130 void SetValueBool(EConfigNamespace ns, const CStr& name, const bool value);
132 void SetValueList(EConfigNamespace ns, const CStr& name, std::vector<CStr> values);
135 * Remove a config value in the specified namespace.
137 void RemoveValue(EConfigNamespace ns, const CStr& name);
140 * Set the path to the config file used to populate the specified namespace
141 * Note that this function does not actually load the config file. Use
142 * the Reload() method if you want to read the config file at the same time.
144 * 'path': The path to the config file.
146 void SetConfigFile(EConfigNamespace ns, const VfsPath& path);
149 * Reload the config file associated with the specified config namespace
150 * (the last config file path set with SetConfigFile)
152 * Returns:
153 * true: if the reload succeeded,
154 * false: if the reload failed
156 bool Reload(EConfigNamespace);
159 * Write the current state of the specified config namespace to the file
160 * specified by 'path'
162 * Returns:
163 * true: if the config namespace was successfully written to the file
164 * false: if an error occurred
166 bool WriteFile(EConfigNamespace ns, const VfsPath& path) const;
169 * Write the current state of the specified config namespace to the file
170 * it was originally loaded from.
172 * Returns:
173 * true: if the config namespace was successfully written to the file
174 * false: if an error occurred
176 bool WriteFile(EConfigNamespace ns) const;
179 * Write a config value to the file specified by 'path'
181 * Returns:
182 * true: if the config value was successfully saved and written to the file
183 * false: if an error occurred
185 bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value, const VfsPath& path);
187 bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value);
190 * Register a simple lambda that will be called anytime the value changes in any namespace
191 * This is simple on purpose, the hook is responsible for checking if it should do something.
192 * When RegisterHookAndCall is called, the hook is immediately triggered.
193 * NB: CConfigDBHook will auto-unregister the hook when destroyed,
194 * so you can use it to tie the lifetime of the hook to your object.
195 * The hook will be deleted alongside ConfigDB anyways.
197 [[nodiscard]] CConfigDBHook RegisterHookAndCall(const CStr& name, std::function<void()> hook);
199 void UnregisterHook(CConfigDBHook&& hook);
200 void UnregisterHook(std::unique_ptr<CConfigDBHook> hook);
202 private:
203 std::array<std::map<CStr, CConfigValueSet>, CFG_LAST> m_Map;
204 std::multimap<CStr, std::function<void()>> m_Hooks;
205 std::array<VfsPath, CFG_LAST> m_ConfigFile;
206 std::array<bool, CFG_LAST> m_HasChanges;
208 mutable std::recursive_mutex m_Mutex;
211 class CConfigDBHook
213 friend class CConfigDB;
214 public:
215 CConfigDBHook() = delete;
216 CConfigDBHook(const CConfigDBHook&) = delete;
217 // Point the moved-from hook to end, which is checked for in UnregisterHook,
218 // to avoid a double-erase error.
219 CConfigDBHook(CConfigDBHook&& h) : m_ConfigDB(h.m_ConfigDB)
221 m_Ptr = std::move(h.m_Ptr);
222 h.m_Ptr = m_ConfigDB.m_Hooks.end();
224 // Unregisters the hook. Must be called before the original ConfigDB gets deleted.
225 ~CConfigDBHook()
227 m_ConfigDB.UnregisterHook(std::move(*this));
229 private:
230 CConfigDBHook(CConfigDB& cdb, std::multimap<CStr, std::function<void()>>::iterator p)
231 : m_ConfigDB(cdb), m_Ptr(p)
234 std::multimap<CStr, std::function<void()>>::iterator m_Ptr;
235 CConfigDB& m_ConfigDB;
239 // stores the value of the given key into <destination>. this quasi-template
240 // convenience wrapper on top of GetValue simplifies user code
241 #define CFG_GET_VAL(name, destination)\
242 g_ConfigDB.GetValue(CFG_USER, name, destination)
244 #endif // INCLUDED_CONFIGDB