]> git.lizzy.rs Git - dragonfireclient.git/blob - src/settings.h
Refactor utf8_to_wide/wide_to_utf8 functions
[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 <string>
25 #include <list>
26 #include <set>
27 #include <mutex>
28
29 class Settings;
30 struct NoiseParams;
31
32 // Global objects
33 extern Settings *g_settings; // Same as Settings::getLayer(SL_GLOBAL);
34 extern std::string g_settings_path;
35
36 // Type for a settings changed callback function
37 typedef void (*SettingsChangedCallback)(const std::string &name, void *data);
38
39 typedef std::vector<
40         std::pair<
41                 SettingsChangedCallback,
42                 void *
43         >
44 > SettingsCallbackList;
45
46 typedef std::unordered_map<std::string, SettingsCallbackList> SettingsCallbackMap;
47
48 enum ValueType {
49         VALUETYPE_STRING,
50         VALUETYPE_FLAG // Doesn't take any arguments
51 };
52
53 enum SettingsParseEvent {
54         SPE_NONE,
55         SPE_INVALID,
56         SPE_COMMENT,
57         SPE_KVPAIR,
58         SPE_END,
59         SPE_GROUP,
60         SPE_MULTILINE,
61 };
62
63 enum SettingsLayer {
64         SL_DEFAULTS,
65         SL_GAME,
66         SL_GLOBAL,
67         SL_MAP,
68         SL_TOTAL_COUNT
69 };
70
71 struct ValueSpec {
72         ValueSpec(ValueType a_type, const char *a_help=NULL)
73         {
74                 type = a_type;
75                 help = a_help;
76         }
77
78         ValueType type;
79         const char *help;
80 };
81
82 struct SettingsEntry {
83         SettingsEntry() = default;
84
85         SettingsEntry(const std::string &value_) :
86                 value(value_)
87         {}
88
89         SettingsEntry(Settings *group_) :
90                 group(group_),
91                 is_group(true)
92         {}
93
94         std::string value = "";
95         Settings *group = nullptr;
96         bool is_group = false;
97 };
98
99 typedef std::unordered_map<std::string, SettingsEntry> SettingEntries;
100
101 class Settings {
102 public:
103         static Settings *createLayer(SettingsLayer sl, const std::string &end_tag = "");
104         static Settings *getLayer(SettingsLayer sl);
105         SettingsLayer getLayerType() const { return m_settingslayer; }
106
107         Settings(const std::string &end_tag = "") :
108                 m_end_tag(end_tag)
109         {}
110         ~Settings();
111
112         Settings & operator += (const Settings &other);
113         Settings & operator = (const Settings &other);
114
115         /***********************
116          * Reading and writing *
117          ***********************/
118
119         // Read configuration file.  Returns success.
120         bool readConfigFile(const char *filename);
121         //Updates configuration file.  Returns success.
122         bool updateConfigFile(const char *filename);
123         // NOTE: Types of allowed_options are ignored.  Returns success.
124         bool parseCommandLine(int argc, char *argv[],
125                         std::map<std::string, ValueSpec> &allowed_options);
126         bool parseConfigLines(std::istream &is);
127         void writeLines(std::ostream &os, u32 tab_depth=0) const;
128
129         /***********
130          * Getters *
131          ***********/
132
133         Settings *getGroup(const std::string &name) const;
134         const std::string &get(const std::string &name) const;
135         bool getBool(const std::string &name) const;
136         u16 getU16(const std::string &name) const;
137         s16 getS16(const std::string &name) const;
138         u32 getU32(const std::string &name) const;
139         s32 getS32(const std::string &name) const;
140         u64 getU64(const std::string &name) const;
141         float getFloat(const std::string &name) const;
142         v2f getV2F(const std::string &name) const;
143         v3f getV3F(const std::string &name) const;
144         u32 getFlagStr(const std::string &name, const FlagDesc *flagdesc,
145                         u32 *flagmask) const;
146         bool getNoiseParams(const std::string &name, NoiseParams &np) const;
147         bool getNoiseParamsFromValue(const std::string &name, NoiseParams &np) const;
148         bool getNoiseParamsFromGroup(const std::string &name, NoiseParams &np) const;
149
150         // return all keys used
151         std::vector<std::string> getNames() const;
152         bool exists(const std::string &name) const;
153
154
155         /***************************************
156          * Getters that don't throw exceptions *
157          ***************************************/
158
159         bool getGroupNoEx(const std::string &name, Settings *&val) const;
160         bool getNoEx(const std::string &name, std::string &val) const;
161         bool getFlag(const std::string &name) const;
162         bool getU16NoEx(const std::string &name, u16 &val) const;
163         bool getS16NoEx(const std::string &name, s16 &val) const;
164         bool getS32NoEx(const std::string &name, s32 &val) const;
165         bool getU64NoEx(const std::string &name, u64 &val) const;
166         bool getFloatNoEx(const std::string &name, float &val) const;
167         bool getV2FNoEx(const std::string &name, v2f &val) const;
168         bool getV3FNoEx(const std::string &name, v3f &val) const;
169
170         // Like other getters, but handling each flag individualy:
171         // 1) Read default flags (or 0)
172         // 2) Override using user-defined flags
173         bool getFlagStrNoEx(const std::string &name, u32 &val,
174                 const FlagDesc *flagdesc) const;
175
176
177         /***********
178          * Setters *
179          ***********/
180
181         // N.B. Groups not allocated with new must be set to NULL in the settings
182         // tree before object destruction.
183         bool setEntry(const std::string &name, const void *entry,
184                 bool set_group);
185         bool set(const std::string &name, const std::string &value);
186         bool setDefault(const std::string &name, const std::string &value);
187         bool setGroup(const std::string &name, const Settings &group);
188         bool setBool(const std::string &name, bool value);
189         bool setS16(const std::string &name, s16 value);
190         bool setU16(const std::string &name, u16 value);
191         bool setS32(const std::string &name, s32 value);
192         bool setU64(const std::string &name, u64 value);
193         bool setFloat(const std::string &name, float value);
194         bool setV2F(const std::string &name, v2f value);
195         bool setV3F(const std::string &name, v3f value);
196         bool setFlagStr(const std::string &name, u32 flags,
197                 const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX);
198         bool setNoiseParams(const std::string &name, const NoiseParams &np);
199
200         // remove a setting
201         bool remove(const std::string &name);
202
203         /**************
204          * Miscellany *
205          **************/
206
207         void setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags);
208         const FlagDesc *getFlagDescFallback(const std::string &name) const;
209
210         void registerChangedCallback(const std::string &name,
211                 SettingsChangedCallback cbf, void *userdata = NULL);
212         void deregisterChangedCallback(const std::string &name,
213                 SettingsChangedCallback cbf, void *userdata = NULL);
214
215         void removeSecureSettings();
216
217 private:
218         /***********************
219          * Reading and writing *
220          ***********************/
221
222         SettingsParseEvent parseConfigObject(const std::string &line,
223                 std::string &name, std::string &value);
224         bool updateConfigObject(std::istream &is, std::ostream &os,
225                 u32 tab_depth=0);
226
227         static bool checkNameValid(const std::string &name);
228         static bool checkValueValid(const std::string &value);
229         static std::string getMultiline(std::istream &is, size_t *num_lines=NULL);
230         static void printEntry(std::ostream &os, const std::string &name,
231                 const SettingsEntry &entry, u32 tab_depth=0);
232
233         /***********
234          * Getters *
235          ***********/
236         Settings *getParent() const;
237
238         const SettingsEntry &getEntry(const std::string &name) const;
239
240         // Allow TestSettings to run sanity checks using private functions.
241         friend class TestSettings;
242
243         void updateNoLock(const Settings &other);
244         void clearNoLock();
245         void clearDefaultsNoLock();
246
247         void doCallbacks(const std::string &name) const;
248
249         SettingEntries m_settings;
250         SettingsCallbackMap m_callbacks;
251         std::string m_end_tag;
252
253         mutable std::mutex m_callback_mutex;
254
255         // All methods that access m_settings/m_defaults directly should lock this.
256         mutable std::mutex m_mutex;
257
258         static Settings *s_layers[SL_TOTAL_COUNT];
259         SettingsLayer m_settingslayer = SL_TOTAL_COUNT;
260         static std::unordered_map<std::string, const FlagDesc *> s_flags;
261 };