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