]> git.lizzy.rs Git - dragonfireclient.git/blob - src/settings.h
Don't look for zlib and zstd manually on Windows
[dragonfireclient.git] / src / settings.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include "irrlichttypes_bloated.h"
23 #include "util/string.h"
24 #include "util/basic_macros.h"
25 #include <string>
26 #include <list>
27 #include <set>
28 #include <mutex>
29
30 class Settings;
31 struct NoiseParams;
32
33 // Global objects
34 extern Settings *g_settings; // Same as Settings::getLayer(SL_GLOBAL);
35 extern std::string g_settings_path;
36
37 // Type for a settings changed callback function
38 typedef void (*SettingsChangedCallback)(const std::string &name, void *data);
39
40 typedef std::vector<
41         std::pair<
42                 SettingsChangedCallback,
43                 void *
44         >
45 > SettingsCallbackList;
46
47 typedef std::unordered_map<std::string, SettingsCallbackList> SettingsCallbackMap;
48
49 enum ValueType {
50         VALUETYPE_STRING,
51         VALUETYPE_FLAG // Doesn't take any arguments
52 };
53
54 enum SettingsParseEvent {
55         SPE_NONE,
56         SPE_INVALID,
57         SPE_COMMENT,
58         SPE_KVPAIR,
59         SPE_END,
60         SPE_GROUP,
61         SPE_MULTILINE,
62 };
63
64 // Describes the global setting layers, SL_GLOBAL is where settings are read from
65 enum SettingsLayer {
66         SL_DEFAULTS,
67         SL_GAME,
68         SL_GLOBAL,
69         SL_TOTAL_COUNT
70 };
71
72 // Implements the hierarchy a settings object may be part of
73 class SettingsHierarchy {
74 public:
75         /*
76          * A settings object that may be part of another hierarchy can
77          * occupy the index 0 as a fallback. If not set you can use 0 on your own.
78          */
79         SettingsHierarchy(Settings *fallback = nullptr);
80
81         DISABLE_CLASS_COPY(SettingsHierarchy)
82
83         Settings *getLayer(int layer) const;
84
85 private:
86         friend class Settings;
87         Settings *getParent(int layer) const;
88         void onLayerCreated(int layer, Settings *obj);
89         void onLayerRemoved(int layer);
90
91         std::vector<Settings*> layers;
92 };
93
94 struct ValueSpec {
95         ValueSpec(ValueType a_type, const char *a_help=NULL)
96         {
97                 type = a_type;
98                 help = a_help;
99         }
100
101         ValueType type;
102         const char *help;
103 };
104
105 struct SettingsEntry {
106         SettingsEntry() = default;
107
108         SettingsEntry(const std::string &value_) :
109                 value(value_)
110         {}
111
112         SettingsEntry(Settings *group_) :
113                 group(group_),
114                 is_group(true)
115         {}
116
117         std::string value = "";
118         Settings *group = nullptr;
119         bool is_group = false;
120 };
121
122 typedef std::unordered_map<std::string, SettingsEntry> SettingEntries;
123
124 class Settings {
125 public:
126         /* These functions operate on the global hierarchy! */
127         static Settings *createLayer(SettingsLayer sl, const std::string &end_tag = "");
128         static Settings *getLayer(SettingsLayer sl);
129         /**/
130
131         Settings(const std::string &end_tag = "") :
132                 m_end_tag(end_tag)
133         {}
134         Settings(const std::string &end_tag, SettingsHierarchy *h, int settings_layer);
135         ~Settings();
136
137         Settings & operator += (const Settings &other);
138         Settings & operator = (const Settings &other);
139
140         /***********************
141          * Reading and writing *
142          ***********************/
143
144         // Read configuration file.  Returns success.
145         bool readConfigFile(const char *filename);
146         //Updates configuration file.  Returns success.
147         bool updateConfigFile(const char *filename);
148         // NOTE: Types of allowed_options are ignored.  Returns success.
149         bool parseCommandLine(int argc, char *argv[],
150                         std::map<std::string, ValueSpec> &allowed_options);
151         bool parseConfigLines(std::istream &is);
152         void writeLines(std::ostream &os, u32 tab_depth=0) const;
153
154         /***********
155          * Getters *
156          ***********/
157
158         Settings *getGroup(const std::string &name) const;
159         const std::string &get(const std::string &name) const;
160         bool getBool(const std::string &name) const;
161         u16 getU16(const std::string &name) const;
162         s16 getS16(const std::string &name) const;
163         u32 getU32(const std::string &name) const;
164         s32 getS32(const std::string &name) const;
165         u64 getU64(const std::string &name) const;
166         float getFloat(const std::string &name) const;
167         v2f getV2F(const std::string &name) const;
168         v3f getV3F(const std::string &name) const;
169         u32 getFlagStr(const std::string &name, const FlagDesc *flagdesc,
170                         u32 *flagmask) const;
171         bool getNoiseParams(const std::string &name, NoiseParams &np) const;
172         bool getNoiseParamsFromValue(const std::string &name, NoiseParams &np) const;
173         bool getNoiseParamsFromGroup(const std::string &name, NoiseParams &np) const;
174
175         // return all keys used
176         std::vector<std::string> getNames() const;
177         bool exists(const std::string &name) const;
178
179
180         /***************************************
181          * Getters that don't throw exceptions *
182          ***************************************/
183
184         bool getGroupNoEx(const std::string &name, Settings *&val) const;
185         bool getNoEx(const std::string &name, std::string &val) const;
186         bool getFlag(const std::string &name) const;
187         bool getU16NoEx(const std::string &name, u16 &val) const;
188         bool getS16NoEx(const std::string &name, s16 &val) const;
189         bool getU32NoEx(const std::string &name, u32 &val) const;
190         bool getS32NoEx(const std::string &name, s32 &val) const;
191         bool getU64NoEx(const std::string &name, u64 &val) const;
192         bool getFloatNoEx(const std::string &name, float &val) const;
193         bool getV2FNoEx(const std::string &name, v2f &val) const;
194         bool getV3FNoEx(const std::string &name, v3f &val) const;
195
196         // Like other getters, but handling each flag individualy:
197         // 1) Read default flags (or 0)
198         // 2) Override using user-defined flags
199         bool getFlagStrNoEx(const std::string &name, u32 &val,
200                 const FlagDesc *flagdesc) const;
201
202
203         /***********
204          * Setters *
205          ***********/
206
207         // N.B. Groups not allocated with new must be set to NULL in the settings
208         // tree before object destruction.
209         bool setEntry(const std::string &name, const void *entry,
210                 bool set_group);
211         bool set(const std::string &name, const std::string &value);
212         bool setDefault(const std::string &name, const std::string &value);
213         bool setGroup(const std::string &name, const Settings &group);
214         bool setBool(const std::string &name, bool value);
215         bool setS16(const std::string &name, s16 value);
216         bool setU16(const std::string &name, u16 value);
217         bool setS32(const std::string &name, s32 value);
218         bool setU64(const std::string &name, u64 value);
219         bool setFloat(const std::string &name, float value);
220         bool setV2F(const std::string &name, v2f value);
221         bool setV3F(const std::string &name, v3f value);
222         bool setFlagStr(const std::string &name, u32 flags,
223                 const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX);
224         bool setNoiseParams(const std::string &name, const NoiseParams &np);
225
226         // remove a setting
227         bool remove(const std::string &name);
228
229         /*****************
230          * Miscellaneous *
231          *****************/
232
233         void setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags);
234         const FlagDesc *getFlagDescFallback(const std::string &name) const;
235
236         void registerChangedCallback(const std::string &name,
237                 SettingsChangedCallback cbf, void *userdata = NULL);
238         void deregisterChangedCallback(const std::string &name,
239                 SettingsChangedCallback cbf, void *userdata = NULL);
240
241         void removeSecureSettings();
242
243         // Returns the settings layer this object is.
244         // If within the global hierarchy you can cast this to enum SettingsLayer
245         inline int getLayer() const { return m_settingslayer; }
246
247 private:
248         /***********************
249          * Reading and writing *
250          ***********************/
251
252         SettingsParseEvent parseConfigObject(const std::string &line,
253                 std::string &name, std::string &value);
254         bool updateConfigObject(std::istream &is, std::ostream &os,
255                 u32 tab_depth=0);
256
257         static bool checkNameValid(const std::string &name);
258         static bool checkValueValid(const std::string &value);
259         static std::string getMultiline(std::istream &is, size_t *num_lines=NULL);
260         static void printEntry(std::ostream &os, const std::string &name,
261                 const SettingsEntry &entry, u32 tab_depth=0);
262
263         /***********
264          * Getters *
265          ***********/
266         Settings *getParent() const;
267
268         const SettingsEntry &getEntry(const std::string &name) const;
269
270         // Allow TestSettings to run sanity checks using private functions.
271         friend class TestSettings;
272         // For sane mutex locking when iterating
273         friend class LuaSettings;
274
275         void updateNoLock(const Settings &other);
276         void clearNoLock();
277         void clearDefaultsNoLock();
278
279         void doCallbacks(const std::string &name) const;
280
281         SettingEntries m_settings;
282         SettingsCallbackMap m_callbacks;
283         std::string m_end_tag;
284
285         mutable std::mutex m_callback_mutex;
286
287         // All methods that access m_settings/m_defaults directly should lock this.
288         mutable std::mutex m_mutex;
289
290         SettingsHierarchy *m_hierarchy = nullptr;
291         int m_settingslayer = -1;
292
293         static std::unordered_map<std::string, const FlagDesc *> s_flags;
294 };