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
|