File: ConfigHandler.h

package info (click to toggle)
spring 104.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 47,512 kB
  • sloc: cpp: 391,093; ansic: 79,943; python: 12,356; java: 12,201; awk: 5,889; sh: 1,826; xml: 655; makefile: 486; perl: 405; php: 211; objc: 194; sed: 2
file content (178 lines) | stat: -rw-r--r-- 5,539 bytes parent folder | download | duplicates (4)
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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef CONFIGHANDLER_H
#define CONFIGHANDLER_H

#include <string>
#include <sstream>
#include <vector>
#include <map>

#include <functional>

#include "ConfigVariable.h"

/**
 * @brief Config handler interface
 */
class ConfigHandler
{
public:
	/**
	 * @brief Instantiate global configHandler
	 * @param configSource the config file to be used, using the default one if empty
	 *
	 * Re-instantiates if the configHandler already existed.
	 *
	 * Note: we don't use &ConfigSource, because showed in past that under some
	 *    conditions this default variable isn't initialized yet and so getting the
	 *    ref of it fails causing a crash.
	 */
	static void Instantiate(const std::string configSource = "", const bool safemode = false);

	/**
	 * @brief Deallocate global configHandler
	 */
	static void Deallocate();

public:
	/**
	 * @brief Register an observer
	 *
	 * The observer must have a method ConfigNotify, that takes a key-value-pair
	 * using two std::strings as argument. It is called whenever the config
	 * variable changes from within the current application.
	 *
	 * It is not called when the config variable is changed from another
	 * application and the new value was read in a read-modify-write cycle.
	 */
	template<class T>
	void NotifyOnChange(T* observer, const std::vector<std::string>& configs)
	{
		// issues: still needs to call configHandler->Get() on startup, automate it
		AddObserver(std::bind(&T::ConfigNotify, observer, std::placeholders::_1, std::placeholders::_2), (void*) observer, configs);
	}

	template<class T>
	void RemoveObserver(T* observer)
	{
		RemoveObserver((void*) observer);
	}


	/// @see SetString
	template<typename T>
	void Set(const std::string& key, const T& value, bool useOverlay = false)
	{
		std::ostringstream buffer;
		buffer << value;
		SetString(key, buffer.str(), useOverlay);
	}

	/// @brief Get bool, throw if key not present
	bool GetBool(const std::string& key) const { return (Get<bool>(key)); }
	/// @brief Get int, throw if key not present
	int GetInt(const std::string& key) const { return (Get<int>(key)); }
	/// @brief Get int, throw if key not present
	int GetUnsigned(const std::string& key) const { return (Get<unsigned>(key)); }
	/// @brief Get float, throw if key not present
	float GetFloat(const std::string& key) const { return (Get<float>(key)); }

	bool GetBoolSafe(const std::string& key, bool def) const { return (IsSet(key)? GetBool(key): def); }
	int GetIntSafe(const std::string& key, int def) const { return (IsSet(key)? GetInt(key): def); }
	float GetFloatSafe(const std::string& key, float def) const { return (IsSet(key)? GetFloat(key): def); }
	std::string GetStringSafe(const std::string& key, const std::string& def) const { return (IsSet(key)? GetString(key): def); }

public:
	virtual ~ConfigHandler() {}

	/**
	 * @brief Set string config value
	 * @param key name of key to set
	 * @param value string value to set
	 * @param useOverlay if true, the value will only be set in memory,
	 *        and therefore be lost for the next game
	 */
	virtual void SetString(const std::string& key, const std::string& value, bool useOverlay = false) = 0;

	/**
	 * @brief Get string config value
	 * @param key name of key to get
	 * @return string value
	 * @note Throws if key not present! (But if you specified
	 *       a default, then that will always be present.)
	 */
	virtual std::string GetString(const std::string& key) const = 0;

	/**
	 * @brief Queries whether config variable is set anywhere
	 * @param key name of key to query
	 * @return true if the key exists
	 * @note If the config variable has a default value then it is always set!
	 */
	virtual bool IsSet(const std::string& key) const = 0;
	/**
	 * @brief Queries if config variable is readonly
	 * @param key name of key to query
	 * @return true if key is read only
	 */
	virtual bool IsReadOnly(const std::string& key) const = 0;

	/**
	 * @brief Delete a config variable from all mutable config sources
	 * @param key name of key to query
	 */
	virtual void Delete(const std::string& key) = 0;

	/**
	 * @brief Get the name of the main (first) config file
	 */
	virtual std::string GetConfigFile() const = 0;

	/**
	 * @brief Get a map containing all key value pairs
	 * @note This includes default values!
	 */
	virtual const std::map<std::string, std::string> GetData() const = 0;

	/**
	 * @brief Get a map containing all key value pairs, which aren't default values
	 * @note This excludes default values!
	 */
	virtual std::map<std::string, std::string> GetDataWithoutDefaults() const = 0;

	/**
	 * @brief Calls observers if config values changed
	 */
	virtual void Update() = 0;

	/**
	 * @brief Toggles write protection for this confighandler
	 */
	virtual void EnableWriting(bool write) = 0;

protected:
	typedef std::function<void(const std::string&, const std::string&)> ConfigNotifyCallback;

	virtual void AddObserver(ConfigNotifyCallback callback, void* observer, const std::vector<std::string>& configs) = 0;
	virtual void RemoveObserver(void* observer) = 0;

private:
	/// @see GetString
	template<typename T>
	T Get(const std::string& key) const
	{
		std::istringstream buf(GetString(key));
		T temp;
		buf >> temp;
		return temp;
	}

	/// @see Get
	/// @brief <bool> specialization of Get<> (we cannot use template spezialization here, so just overload it)
	bool Get(const std::string& key) const;
};

extern ConfigHandler* configHandler;

#endif /* CONFIGHANDLER_H */