Replace various std::map with UNORDERED_MAP + various cleanups
[oweals/minetest.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 #ifndef SETTINGS_HEADER
21 #define SETTINGS_HEADER
22
23 #include "irrlichttypes_bloated.h"
24 #include "util/string.h"
25 #include "threading/mutex.h"
26 #include <string>
27 #include "util/cpp11_container.h"
28 #include <list>
29 #include <set>
30
31 class Settings;
32 struct NoiseParams;
33
34 // Global objects
35 extern Settings *g_settings;
36 extern std::string g_settings_path;
37
38 // Type for a settings changed callback function
39 typedef void (*SettingsChangedCallback)(const std::string &name, void *data);
40
41 typedef std::vector<
42         std::pair<
43                 SettingsChangedCallback,
44                 void *
45         >
46 > SettingsCallbackList;
47
48 typedef UNORDERED_MAP<std::string, SettingsCallbackList> SettingsCallbackMap;
49
50 enum ValueType {
51         VALUETYPE_STRING,
52         VALUETYPE_FLAG // Doesn't take any arguments
53 };
54
55 enum SettingsParseEvent {
56         SPE_NONE,
57         SPE_INVALID,
58         SPE_COMMENT,
59         SPE_KVPAIR,
60         SPE_END,
61         SPE_GROUP,
62         SPE_MULTILINE,
63 };
64
65 struct ValueSpec {
66         ValueSpec(ValueType a_type, const char *a_help=NULL)
67         {
68                 type = a_type;
69                 help = a_help;
70         }
71
72         ValueType type;
73         const char *help;
74 };
75
76 struct SettingsEntry {
77         SettingsEntry()
78         {
79                 group    = NULL;
80                 is_group = false;
81         }
82
83         SettingsEntry(const std::string &value_)
84         {
85                 value    = value_;
86                 group    = NULL;
87                 is_group = false;
88         }
89
90         SettingsEntry(Settings *group_)
91         {
92                 group    = group_;
93                 is_group = true;
94         }
95
96         std::string value;
97         Settings *group;
98         bool is_group;
99 };
100
101 typedef UNORDERED_MAP<std::string, SettingsEntry> SettingEntries;
102
103 class Settings {
104 public:
105         Settings() {}
106         ~Settings();
107
108         Settings & operator += (const Settings &other);
109         Settings & operator = (const Settings &other);
110
111         /***********************
112          * Reading and writing *
113          ***********************/
114
115         // Read configuration file.  Returns success.
116         bool readConfigFile(const char *filename);
117         //Updates configuration file.  Returns success.
118         bool updateConfigFile(const char *filename);
119         // NOTE: Types of allowed_options are ignored.  Returns success.
120         bool parseCommandLine(int argc, char *argv[],
121                         std::map<std::string, ValueSpec> &allowed_options);
122         bool parseConfigLines(std::istream &is, const std::string &end = "");
123         void writeLines(std::ostream &os, u32 tab_depth=0) const;
124
125         SettingsParseEvent parseConfigObject(const std::string &line,
126                 const std::string &end, std::string &name, std::string &value);
127         bool updateConfigObject(std::istream &is, std::ostream &os,
128                 const std::string &end, u32 tab_depth=0);
129
130         static bool checkNameValid(const std::string &name);
131         static bool checkValueValid(const std::string &value);
132         static std::string sanitizeName(const std::string &name);
133         static std::string sanitizeValue(const std::string &value);
134         static std::string getMultiline(std::istream &is, size_t *num_lines=NULL);
135         static void printEntry(std::ostream &os, const std::string &name,
136                 const SettingsEntry &entry, u32 tab_depth=0);
137
138         /***********
139          * Getters *
140          ***********/
141
142         const SettingsEntry &getEntry(const std::string &name) const;
143         Settings *getGroup(const std::string &name) const;
144         std::string get(const std::string &name) const;
145         bool getBool(const std::string &name) const;
146         u16 getU16(const std::string &name) const;
147         s16 getS16(const std::string &name) const;
148         s32 getS32(const std::string &name) const;
149         u64 getU64(const std::string &name) const;
150         float getFloat(const std::string &name) const;
151         v2f getV2F(const std::string &name) const;
152         v3f getV3F(const std::string &name) const;
153         u32 getFlagStr(const std::string &name, const FlagDesc *flagdesc,
154                         u32 *flagmask) const;
155         // N.B. if getStruct() is used to read a non-POD aggregate type,
156         // the behavior is undefined.
157         bool getStruct(const std::string &name, const std::string &format,
158                         void *out, size_t olen) const;
159         bool getNoiseParams(const std::string &name, NoiseParams &np) const;
160         bool getNoiseParamsFromValue(const std::string &name, NoiseParams &np) const;
161         bool getNoiseParamsFromGroup(const std::string &name, NoiseParams &np) const;
162
163         // return all keys used
164         std::vector<std::string> getNames() const;
165         bool exists(const std::string &name) const;
166
167
168         /***************************************
169          * Getters that don't throw exceptions *
170          ***************************************/
171
172         bool getEntryNoEx(const std::string &name, SettingsEntry &val) const;
173         bool getGroupNoEx(const std::string &name, Settings *&val) const;
174         bool getNoEx(const std::string &name, std::string &val) const;
175         bool getFlag(const std::string &name) const;
176         bool getU16NoEx(const std::string &name, u16 &val) const;
177         bool getS16NoEx(const std::string &name, s16 &val) const;
178         bool getS32NoEx(const std::string &name, s32 &val) const;
179         bool getU64NoEx(const std::string &name, u64 &val) const;
180         bool getFloatNoEx(const std::string &name, float &val) const;
181         bool getV2FNoEx(const std::string &name, v2f &val) const;
182         bool getV3FNoEx(const std::string &name, v3f &val) const;
183         // N.B. getFlagStrNoEx() does not set val, but merely modifies it.  Thus,
184         // val must be initialized before using getFlagStrNoEx().  The intention of
185         // this is to simplify modifying a flags field from a default value.
186         bool getFlagStrNoEx(const std::string &name, u32 &val, FlagDesc *flagdesc) const;
187
188
189         /***********
190          * Setters *
191          ***********/
192
193         // N.B. Groups not allocated with new must be set to NULL in the settings
194         // tree before object destruction.
195         bool setEntry(const std::string &name, const void *entry,
196                 bool set_group, bool set_default);
197         bool set(const std::string &name, const std::string &value);
198         bool setDefault(const std::string &name, const std::string &value);
199         bool setGroup(const std::string &name, Settings *group);
200         bool setGroupDefault(const std::string &name, Settings *group);
201         bool setBool(const std::string &name, bool value);
202         bool setS16(const std::string &name, s16 value);
203         bool setU16(const std::string &name, u16 value);
204         bool setS32(const std::string &name, s32 value);
205         bool setU64(const std::string &name, u64 value);
206         bool setFloat(const std::string &name, float value);
207         bool setV2F(const std::string &name, v2f value);
208         bool setV3F(const std::string &name, v3f value);
209         bool setFlagStr(const std::string &name, u32 flags,
210                 const FlagDesc *flagdesc, u32 flagmask);
211         bool setNoiseParams(const std::string &name, const NoiseParams &np,
212                 bool set_default=false);
213         // N.B. if setStruct() is used to write a non-POD aggregate type,
214         // the behavior is undefined.
215         bool setStruct(const std::string &name, const std::string &format, void *value);
216
217         // remove a setting
218         bool remove(const std::string &name);
219         void clear();
220         void clearDefaults();
221         void updateValue(const Settings &other, const std::string &name);
222         void update(const Settings &other);
223
224         void registerChangedCallback(const std::string &name,
225                 SettingsChangedCallback cbf, void *userdata = NULL);
226         void deregisterChangedCallback(const std::string &name,
227                 SettingsChangedCallback cbf, void *userdata = NULL);
228
229 private:
230         void updateNoLock(const Settings &other);
231         void clearNoLock();
232         void clearDefaultsNoLock();
233
234         void doCallbacks(const std::string &name) const;
235
236         SettingEntries m_settings;
237         SettingEntries m_defaults;
238
239         SettingsCallbackMap m_callbacks;
240
241         mutable Mutex m_callback_mutex;
242
243         // All methods that access m_settings/m_defaults directly should lock this.
244         mutable Mutex m_mutex;
245
246 };
247
248 #endif
249