1 /*
2 settings.h
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 */
5 
6 /*
7 This file is part of Freeminer.
8 
9 Freeminer is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Freeminer  is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Freeminer.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #ifndef SETTINGS_HEADER
24 #define SETTINGS_HEADER
25 
26 #include "irrlichttypes_bloated.h"
27 #include "util/string.h"
28 #include "jthread/jmutex.h"
29 #include <string>
30 #include <map>
31 #include <list>
32 #include <set>
33 
34 #include "porting.h"
35 #include "json/json.h" // for json config values
36 #include <stdint.h>
37 
38 enum ValueType
39 {
40 	VALUETYPE_STRING,
41 	VALUETYPE_FLAG // Doesn't take any arguments
42 };
43 
44 struct ValueSpec
45 {
46 	ValueSpec(ValueType a_type, const char *a_help=NULL)
47 	{
48 		type = a_type;
49 		help = a_help;
50 	}
51 	ValueType type;
52 	const char *help;
53 };
54 
55 
56 class Settings
57 {
58 public:
Settings()59 	Settings() {}
60 
61 	Settings & operator += (const Settings &other);
62 	Settings & operator = (const Settings &other);
63 
64 
65 	/***********************
66 	 * Reading and writing *
67 	 ***********************/
68 
69 	// Read configuration file.  Returns success.
70 	bool readConfigFile(const char *filename);
71 	//Updates configuration file.  Returns success.
72 	bool updateConfigFile(const char *filename);
73 	// NOTE: Types of allowed_options are ignored.  Returns success.
74 	bool parseCommandLine(int argc, char *argv[],
75 			std::map<std::string, ValueSpec> &allowed_options);
76 	bool parseConfigLines(std::istream &is, const std::string &end = "");
77 	void writeLines(std::ostream &os) const;
78 
79 
80 	/***********
81 	 * Getters *
82 	 ***********/
83 
84 	std::string get(const std::string &name) const;
85 	bool getBool(const std::string &name) const;
86 	u16 getU16(const std::string &name) const;
87 	s16 getS16(const std::string &name) const;
88 	s32 getS32(const std::string &name) const;
89 	u64 getU64(const std::string &name) const;
90 	float getFloat(const std::string &name) const;
91 	v2f getV2F(const std::string &name) const;
92 	v3f getV3F(const std::string &name) const;
93 	u32 getFlagStr(const std::string &name, const FlagDesc *flagdesc,
94 			u32 *flagmask) const;
95 	// N.B. if getStruct() is used to read a non-POD aggregate type,
96 	// the behavior is undefined.
97 	bool getStruct(const std::string &name, const std::string &format,
98 			void *out, size_t olen) const;
99 
100 	// return all keys used
101 	std::vector<std::string> getNames() const;
102 	bool exists(const std::string &name) const;
103 
104 
105 	/***************************************
106 	 * Getters that don't throw exceptions *
107 	 ***************************************/
108 
109 	bool getNoEx(const std::string &name, std::string &val) const;
110 	bool getFlag(const std::string &name) const;
111 	bool getU16NoEx(const std::string &name, u16 &val) const;
112 	bool getS16NoEx(const std::string &name, s16 &val) const;
113 	bool getS32NoEx(const std::string &name, s32 &val) const;
114 	bool getU64NoEx(const std::string &name, u64 &val) const;
115 	bool getFloatNoEx(const std::string &name, float &val) const;
116 	bool getV2FNoEx(const std::string &name, v2f &val) const;
117 	bool getV3FNoEx(const std::string &name, v3f &val) const;
118 	// N.B. getFlagStrNoEx() does not set val, but merely modifies it.  Thus,
119 	// val must be initialized before using getFlagStrNoEx().  The intention of
120 	// this is to simplify modifying a flags field from a default value.
121 	bool getFlagStrNoEx(const std::string &name, u32 &val, FlagDesc *flagdesc) const;
122 
123 
124 	/***********
125 	 * Setters *
126 	 ***********/
127 
128 	void set(const std::string &name, std::string value);
129 	void set(const std::string &name, const char *value);
130 	void setDefault(const std::string &name, std::string value);
131 	void setBool(const std::string &name, bool value);
132 	void setS16(const std::string &name, s16 value);
133 	void setS32(const std::string &name, s32 value);
134 	void setU64(const std::string &name, uint64_t value);
135 	void setFloat(const std::string &name, float value);
136 	void setV2F(const std::string &name, v2f value);
137 	void setV3F(const std::string &name, v3f value);
138 	void setFlagStr(const std::string &name, u32 flags,
139 		const FlagDesc *flagdesc, u32 flagmask);
140 	// N.B. if setStruct() is used to write a non-POD aggregate type,
141 	// the behavior is undefined.
142 	bool setStruct(const std::string &name, const std::string &format, void *value);
143 	// remove a setting
144 	bool remove(const std::string &name);
145 	void clear();
146 	void updateValue(const Settings &other, const std::string &name);
147 	void update(const Settings &other);
148 
149 	Json::Value getJson(const std::string & name, const Json::Value & def = Json::Value());
150 	void setJson(const std::string & name, const Json::Value & value);
151 
152 private:
153 	/***********************
154 	 * Reading and writing *
155 	 ***********************/
156 
157 	bool parseConfigObject(std::istream &is,
158 			std::string &name, std::string &value);
159 	bool parseConfigObject(std::istream &is,
160 			std::string &name, std::string &value,
161 			const std::string &end, bool &end_found);
162 	/*
163 	 * Reads a configuration object from stream (usually a single line)
164 	 * and adds it to dst.
165 	 * Preserves comments and empty lines.
166 	 * Setting names that were added to dst are also added to updated.
167 	 */
168 	void getUpdatedConfigObject(std::istream &is,
169 			std::list<std::string> &dst,
170 			std::set<std::string> &updated,
171 			bool &changed);
172 
173 
174 	void updateNoLock(const Settings &other);
175 	void clearNoLock();
176 
177 
178 	std::map<std::string, std::string> m_settings;
179 	std::map<std::string, std::string> m_defaults;
180 	// All methods that access m_settings/m_defaults directly should lock this.
181 	Json::Reader json_reader;
182 	Json::FastWriter json_writer;
183 	mutable JMutex m_mutex;
184 };
185 
186 extern Settings *g_settings;
187 extern std::string g_settings_path;
188 
189 #endif
190