Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
ConfigDB.h
Go to the documentation of this file.
1/* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
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.
8 *
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.
13 *
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/>.
16 */
17
18/*
19 CConfigDB - Load, access and store configuration variables
20
21 TDD : http://www.wildfiregames.com/forum/index.php?showtopic=1125
22 OVERVIEW:
23
24 JavaScript: Check this documentation: http://trac.wildfiregames.com/wiki/Exposed_ConfigDB_Functions
25*/
26
27#ifndef INCLUDED_CONFIGDB
28#define INCLUDED_CONFIGDB
29
31#include "ps/CStr.h"
32
33#include <array>
34#include <map>
35#include <memory>
36#include <mutex>
37#include <vector>
38
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.
45 */
47{
55};
56
57using CConfigValueSet = std::vector<CStr>;
58
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.
62class CConfigDBHook;
63
64#define g_ConfigDB (*CConfigDB::Instance())
65
67{
69public:
70 CConfigDB();
71 ~CConfigDB();
72 CConfigDB(const CConfigDB&) = delete;
73 CConfigDB(CConfigDB&&) = delete;
74
75 static void Initialise();
76 static void Shutdown();
77 static bool IsInitialised();
78 static CConfigDB* Instance();
79
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.
84 */
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);
96
97 /**
98 * Returns true if changed with respect to last write on file
99 */
100 bool HasChanges(EConfigNamespace ns) const;
101
102 void SetChanges(EConfigNamespace ns, bool value);
103
104 /**
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.
108 */
109 void GetValues(EConfigNamespace ns, const CStr& name, CConfigValueSet& values) const;
110
111 /**
112 * Returns the namespace that the value returned by GetValues was defined in,
113 * or CFG_LAST if it wasn't defined at all.
114 */
115 EConfigNamespace GetValueNamespace(EConfigNamespace ns, const CStr& name) const;
116
117 /**
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.
121 */
122 std::map<CStr, CConfigValueSet> GetValuesWithPrefix(EConfigNamespace ns, const CStr& prefix) const;
123
124 /**
125 * Save a config value in the specified namespace. If the config variable
126 * existed the value is replaced.
127 */
128 void SetValueString(EConfigNamespace ns, const CStr& name, const CStr& value);
129
130 void SetValueBool(EConfigNamespace ns, const CStr& name, const bool value);
131
132 void SetValueList(EConfigNamespace ns, const CStr& name, std::vector<CStr> values);
133
134 /**
135 * Remove a config value in the specified namespace.
136 */
137 bool RemoveValue(EConfigNamespace ns, const CStr& name);
138
139 /**
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.
143 *
144 * 'path': The path to the config file.
145 */
146 void SetConfigFile(EConfigNamespace ns, const VfsPath& path);
147
148 /**
149 * Reload the config file associated with the specified config namespace
150 * (the last config file path set with SetConfigFile)
151 *
152 * Returns:
153 * true: if the reload succeeded,
154 * false: if the reload failed
155 */
157
158 /**
159 * Write the current state of the specified config namespace to the file
160 * specified by 'path'
161 *
162 * Returns:
163 * true: if the config namespace was successfully written to the file
164 * false: if an error occurred
165 */
166 bool WriteFile(EConfigNamespace ns, const VfsPath& path) const;
167
168 /**
169 * Write the current state of the specified config namespace to the file
170 * it was originally loaded from.
171 *
172 * Returns:
173 * true: if the config namespace was successfully written to the file
174 * false: if an error occurred
175 */
176 bool WriteFile(EConfigNamespace ns) const;
177
178 /**
179 * Write a config value to the file specified by 'path'
180 *
181 * Returns:
182 * true: if the config value was successfully saved and written to the file
183 * false: if an error occurred
184 */
185 bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value, const VfsPath& path);
186
187 bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value);
188
189 /**
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.
196 */
197 [[nodiscard]] CConfigDBHook RegisterHookAndCall(const CStr& name, std::function<void()> hook);
198
199 void UnregisterHook(CConfigDBHook&& hook);
200 void UnregisterHook(std::unique_ptr<CConfigDBHook> hook);
201
202private:
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;
207
208 mutable std::recursive_mutex m_Mutex;
209};
210
212{
213 friend class CConfigDB;
214public:
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.
220 {
221 m_Ptr = std::move(h.m_Ptr);
222 h.m_Ptr = m_ConfigDB.m_Hooks.end();
223 }
224 // Unregisters the hook. Must be called before the original ConfigDB gets deleted.
226 {
227 m_ConfigDB.UnregisterHook(std::move(*this));
228 }
229private:
230 CConfigDBHook(CConfigDB& cdb, std::multimap<CStr, std::function<void()>>::iterator p)
231 : m_ConfigDB(cdb), m_Ptr(p)
232 {};
233
234 std::multimap<CStr, std::function<void()>>::iterator m_Ptr;
236};
237
238
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)
243
244#endif // INCLUDED_CONFIGDB
std::vector< CStr > CConfigValueSet
Definition: ConfigDB.h:57
EConfigNamespace
Namespace priorities:
Definition: ConfigDB.h:47
@ CFG_HWDETECT
Definition: ConfigDB.h:51
@ CFG_COMMAND
Definition: ConfigDB.h:53
@ CFG_SYSTEM
Definition: ConfigDB.h:50
@ CFG_DEFAULT
Definition: ConfigDB.h:48
@ CFG_LAST
Definition: ConfigDB.h:54
@ CFG_MOD
Definition: ConfigDB.h:49
@ CFG_USER
Definition: ConfigDB.h:52
Definition: ConfigDB.h:212
CConfigDBHook()=delete
CConfigDBHook(const CConfigDBHook &)=delete
~CConfigDBHook()
Definition: ConfigDB.h:225
CConfigDBHook(CConfigDBHook &&h)
Definition: ConfigDB.h:219
CConfigDBHook(CConfigDB &cdb, std::multimap< CStr, std::function< void()> >::iterator p)
Definition: ConfigDB.h:230
std::multimap< CStr, std::function< void()> >::iterator m_Ptr
Definition: ConfigDB.h:234
CConfigDB & m_ConfigDB
Definition: ConfigDB.h:235
Definition: ConfigDB.h:67
~CConfigDB()
Definition: ConfigDB.cpp:149
bool Reload(EConfigNamespace)
Reload the config file associated with the specified config namespace (the last config file path set ...
Definition: ConfigDB.cpp:289
CConfigDB(const CConfigDB &)=delete
std::map< CStr, CConfigValueSet > GetValuesWithPrefix(EConfigNamespace ns, const CStr &prefix) const
Retrieve a map of values corresponding to settings whose names begin with the given prefix; will sear...
Definition: ConfigDB.cpp:211
bool RemoveValue(EConfigNamespace ns, const CStr &name)
Remove a config value in the specified namespace.
Definition: ConfigDB.cpp:267
void UnregisterHook(CConfigDBHook &&hook)
Definition: ConfigDB.cpp:524
void SetValueString(EConfigNamespace ns, const CStr &name, const CStr &value)
Save a config value in the specified namespace.
Definition: ConfigDB.cpp:232
void SetValueBool(EConfigNamespace ns, const CStr &name, const bool value)
Definition: ConfigDB.cpp:249
void GetValue(EConfigNamespace ns, const CStr &name, bool &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
void SetChanges(EConfigNamespace ns, bool value)
Definition: ConfigDB.cpp:161
bool WriteValueToFile(EConfigNamespace ns, const CStr &name, const CStr &value, const VfsPath &path)
Write a config value to the file specified by 'path'.
Definition: ConfigDB.cpp:501
std::recursive_mutex m_Mutex
Definition: ConfigDB.h:208
CConfigDBHook RegisterHookAndCall(const CStr &name, std::function< void()> hook)
Register a simple lambda that will be called anytime the value changes in any namespace This is simpl...
Definition: ConfigDB.cpp:517
void SetConfigFile(EConfigNamespace ns, const VfsPath &path)
Set the path to the config file used to populate the specified namespace Note that this function does...
Definition: ConfigDB.cpp:281
std::multimap< CStr, std::function< void()> > m_Hooks
Definition: ConfigDB.h:204
CConfigDB()
Definition: ConfigDB.cpp:144
void GetValue(EConfigNamespace ns, const CStr &name, double &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
void GetValue(EConfigNamespace ns, const CStr &name, float &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
static void Shutdown()
Definition: ConfigDB.cpp:129
void GetValues(EConfigNamespace ns, const CStr &name, CConfigValueSet &values) const
Attempt to retrieve a vector of values corresponding to the given setting; will search CFG_COMMAND fi...
Definition: ConfigDB.cpp:169
void GetValue(EConfigNamespace ns, const CStr &name, u32 &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
static void Initialise()
Definition: ConfigDB.cpp:124
EConfigNamespace GetValueNamespace(EConfigNamespace ns, const CStr &name) const
Returns the namespace that the value returned by GetValues was defined in, or CFG_LAST if it wasn't d...
Definition: ConfigDB.cpp:192
void SetValueList(EConfigNamespace ns, const CStr &name, std::vector< CStr > values)
Definition: ConfigDB.cpp:255
static CConfigDB * Instance()
Definition: ConfigDB.cpp:139
static bool IsInitialised()
Definition: ConfigDB.cpp:134
bool HasChanges(EConfigNamespace ns) const
Returns true if changed with respect to last write on file.
Definition: ConfigDB.cpp:153
friend CConfigDBHook
Definition: ConfigDB.h:68
void GetValue(EConfigNamespace ns, const CStr &name, int &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
bool WriteFile(EConfigNamespace ns, const VfsPath &path) const
Write the current state of the specified config namespace to the file specified by 'path'.
Definition: ConfigDB.cpp:461
CConfigDB(CConfigDB &&)=delete
std::array< VfsPath, CFG_LAST > m_ConfigFile
Definition: ConfigDB.h:205
std::array< std::map< CStr, CConfigValueSet >, CFG_LAST > m_Map
Definition: ConfigDB.h:203
void GetValue(EConfigNamespace ns, const CStr &name, std::string &value)
Attempt to retrieve the value of a config variable with the given name; will search CFG_COMMAND first...
std::array< bool, CFG_LAST > m_HasChanges
Definition: ConfigDB.h:206
Definition: path.h:80
uint32_t u32
Definition: types.h:39