File: config-manager.h

package info (click to toggle)
scummvm 2.9.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 450,580 kB
  • sloc: cpp: 4,299,825; asm: 28,322; python: 12,901; sh: 11,302; java: 9,289; xml: 7,895; perl: 2,639; ansic: 2,465; yacc: 1,670; javascript: 1,020; makefile: 933; lex: 578; awk: 275; objc: 82; sed: 11; php: 1
file content (271 lines) | stat: -rw-r--r-- 12,534 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef COMMON_CONFIG_MANAGER_H
#define COMMON_CONFIG_MANAGER_H

#include "common/array.h"
#include "common/hashmap.h"
#include "common/path.h"
#include "common/singleton.h"
#include "common/str.h"
#include "common/hash-str.h"

namespace Common {

/**
 * @defgroup common_config Configuration manager
 * @ingroup common
 *
 * @brief  The (singleton) configuration manager, used to query and set configuration
 *         values using string keys.
 *
 * @{
 */

class WriteStream;
class SeekableReadStream;

/**
 * The (singleton) configuration manager, used to query & set configuration
 * values using string keys.
 *
 * TBD: Implement the callback based notification system (outlined below)
 *       which sends out notifications to interested parties whenever the value
 *       of some specific (or any) configuration key changes.
 */
class ConfigManager : public Singleton<ConfigManager> {

public:

	class Domain {
	private:
		StringMap _entries;
		StringMap _keyValueComments;
		String _domainComment;

	public:
		typedef StringMap::const_iterator const_iterator;
		const_iterator begin() const { return _entries.begin(); } /*!< Return the beginning position of configuration entries. */
		const_iterator end()   const { return _entries.end(); }   /*!< Return the ending position of configuration entries. */

		bool           empty() const { return _entries.empty(); } /*!< Return true if the configuration is empty, i.e. has no [key, value] pairs, and false otherwise. */

		bool           contains(const String &key) const { return _entries.contains(key); } /*!< Check whether the domain contains a @p key. */
		/** Return the configuration value for the given key.
		 *  If no entry exists for the given key in the configuration, it is created.
		 */
		/** Return the configuration value for the given key.
		 *  @note This function does *not* create a configuration entry
		 *  for the given key if it does not exist.
		 */
		const String &operator[](const String &key) const { return _entries[key]; }

		void           setVal(const String &key, const String &value) { _entries.setVal(key, value); } /*!< Assign a @p value to a @p key. */

		String &getOrCreateVal(const String &key) { return _entries.getOrCreateVal(key); }
		String        &getVal(const String &key) { return _entries.getVal(key); } /*!< Retrieve the value of a @p key. */
		const String  &getVal(const String &key) const { return _entries.getVal(key); } /*!< @overload */
		 /**
		  * Retrieve the value of @p key if it exists and leave the referenced variable unchanged if the key does not exist.
		  * @return True if the key exists, false otherwise.
		  * You can use this method if you frequently attempt to access keys that do not exist.
		  */
		const String &getValOrDefault(const String &key) const { return _entries.getValOrDefault(key); }
		bool tryGetVal(const String &key, String &out) const { return _entries.tryGetVal(key, out); }

		void           clear() { _entries.clear(); } /*!< Clear all configuration entries in the domain. */

		void           erase(const String &key) { _entries.erase(key); } /*!< Remove a key from the domain. */

		void           setDomainComment(const String &comment); /*!< Add a @p comment for this configuration domain. */
		const String  &getDomainComment() const; /*!< Retrieve the comment of this configuration domain. */

		void           setKVComment(const String &key, const String &comment); /*!< Add a key-value @p comment to a @p key. */
		const String  &getKVComment(const String &key) const; /*!< Retrieve the key-value comment of a @p key. */
		bool           hasKVComment(const String &key) const; /*!< Check whether a @p key has a key-value comment. */
	};

	/** A hash map of existing configuration domains. */
	typedef HashMap<String, Domain, IgnoreCase_Hash, IgnoreCase_EqualTo> DomainMap;

	/** The name of the application domain (normally 'scummvm'). */
	static char const *const kApplicationDomain;

	/** The transient (pseudo) domain. */
	static char const *const kTransientDomain;

	/** The name of keymapper domain used to store the key maps. */
	static char const *const kKeymapperDomain;

	/** The name of the session domain where configs are put
	 * for the entire session or until they are overwritten or removed.
	 * These settings don't get saved to disk. */
	static char const *const kSessionDomain;

#ifdef USE_CLOUD
	/** The name of cloud domain used to store the user's tokens. */
	static char const *const kCloudDomain;
#endif

	bool                     loadDefaultConfigFile(const Path &fallbackFilename); /*!< Load the default configuration file. */
	bool                     loadConfigFile(const Path &filename, const Path &fallbackFilename); /*!< Load a specific configuration file. */

	/**
	 * Retrieve the config domain with the given name.
	 * @param domName Name of the domain to retrieve.
	 * @return Pointer to the domain, or 0 if the domain does not exist.
	 */
	Domain *			getDomain(const String &domName);
	const Domain            *getDomain(const String &domName) const; /*!< @overload */


	/**
	 * @name Generic access methods
	 * @brief No domain specified, use the values from the
	 *        various domains in the order of their priority.
	 * @{
	 */

	bool                     hasKey(const String &key) const; /*!< Check if a given @p key exists. */
	const String            &get(const String &key) const;    /*!< Get the value of a @p key. */
	void                     set(const String &key, const String &value); /*!< Assign a @p value to a @p key. */
	/** @} */

	/**
	 * Indicate if a default value has been set for the given key.
	 */
	bool                     hasDefault(const String &key) const;

	/**
	 * Update a configuration entry for the active domain and flush
	 * the configuration file to disk if the value changed.
	 */
	void				setAndFlush(const String &key, const Common::String &value);

#if 1
	/**
	 * @name Domain-specific access methods
	 * @brief Access one specific domain and modify it.
	 *
	 * TBD: Get rid of most of those if possible, or at least reduce
	 * their usage, by using getDomain as often as possible. For example in the
	 * options dialog code.
	 * @{
	 */

	bool                     hasKey(const String &key, const String &domName) const; /*!< Check if a given @p key exists in the @p domName domain. */
	const String            &get(const String &key, const String &domName) const; /*!< Get the value of a @p key from the @p domName domain. */
	void                     set(const String &key, const String &value, const String &domName); /*!< Assign a @p value to a @p key in the @p domName domain. */

	void                     removeKey(const String &key, const String &domName); /*!< Remove a @p key to a @p key from the @p domName domain. */
	/** @} */
#endif

	/**
	 * @name Additional convenience accessors
	 * @{
	 */

	int                      getInt(const String &key, const String &domName = String()) const; /*!< Get integer value. */
	bool                     getBool(const String &key, const String &domName = String()) const; /*!< Get Boolean value. */
	Path                     getPath(const String &key, const String &domName = String()) const; /*!< Get path value. */
	float                    getFloat(const String &key, const String &domName = String()) const; /*!< Get float value. */
	void                     setInt(const String &key, int value, const String &domName = String()); /*!< Set integer value. */
	void                     setBool(const String &key, bool value, const String &domName = String()); /*!< Set Boolean value. */
	void                     setPath(const String &key, const Path &value, const String &domName = String()); /*!< Set path value. */
	void                     setFloat(const String &key, float value, const String &domName = String()); /*!< Set float value. */

	void                     registerDefault(const String &key, const String &value); /*!< Register a value as the default. */
	void                     registerDefault(const String &key, const char *value); /*!< @overload */
	void                     registerDefault(const String &key, int value); /*!< @overload */
	void                     registerDefault(const String &key, bool value); /*!< @overload */
	void                     registerDefault(const String &key, const Path &value); /*!< @overload */

	void                     flushToDisk(); /*!< Flush configuration to disk. */

	void                     setActiveDomain(const String &domName); /*!< Set the given domain as active. */
	Domain                  *getActiveDomain() { return _activeDomain; } /*!< Get the active domain. */
	const Domain            *getActiveDomain() const { return _activeDomain; } /*!< @overload */
	const String            &getActiveDomainName() const { return _activeDomainName; } /*!< Get the name of the active domain. */

	void                     addGameDomain(const String &domName); /*!< Add a new game domain. */
	void                     removeGameDomain(const String &domName); /*!< Remove a game domain. */
	void                     renameGameDomain(const String &oldName, const String &newName); /*!< Rename a game domain. */

	void                     addMiscDomain(const String &domName); /*!< Add a miscellaneous domain. */
	void                     removeMiscDomain(const String &domName); /*!< Remove a miscellaneous domain. */
	void                     renameMiscDomain(const String &oldName, const String &newName); /*!< Rename a miscellaneous domain. */

	bool                     hasGameDomain(const String &domName) const; /*!< Check if a specific game domain exists in the DomainMap. */
	bool                     hasMiscDomain(const String &domName) const; /*!< Check if a specific miscellaneous domain exists in the DomainMap. */

	bool                     isKeyTemporary(const String &key) const; /*!< Check if a specific key exists in either transient or session domain. */

	const DomainMap         &getGameDomains() const { return _gameDomains; } /*!< Return all game domains in the DomainMap. */
	DomainMap::iterator      beginGameDomains() { return _gameDomains.begin(); } /*!< Return the beginning position of game domains. */
	DomainMap::iterator      endGameDomains() { return _gameDomains.end(); } /*!< Return the ending position of game domains. */

	const Path              &getCustomConfigFileName() { return _filename; } /*!< Return the custom config file being used, or an empty string when using the default config file */

	static void              defragment(); /*!< Move the configuration in memory to reduce fragmentation. */
	void                     copyFrom(ConfigManager &source); /*!< Copy from a ConfigManager instance. */
	/** @} */
private:
	friend class Singleton<SingletonBaseType>;
	ConfigManager();

	bool			loadFallbackConfigFile(const Path &filename);
	bool			loadFromStream(SeekableReadStream &stream);
	void			addDomain(const String &domainName, const Domain &domain);
	void			writeDomain(WriteStream &stream, const String &name, const Domain &domain);
	void			renameDomain(const String &oldName, const String &newName, DomainMap &map);

	Domain			_transientDomain;
	DomainMap		_gameDomains;
	DomainMap		_miscDomains; // Any other domains
	Domain			_appDomain;
	Domain			_defaultsDomain;

	Domain			_keymapperDomain;

	Domain          _sessionDomain;

#ifdef USE_CLOUD
	Domain			_cloudDomain;
#endif

	Array<String>	_domainSaveOrder;

	String			_activeDomainName;
	Domain *		_activeDomain;

	Path			_filename;
};

/** @} */

} // End of namespace Common

/** Shortcut for accessing the configuration manager. */
#define ConfMan		Common::ConfigManager::instance()

#endif