/* * The ManaPlus Client * Copyright (C) 2004-2009 The Mana World Development Team * Copyright (C) 2009-2010 The Mana Developers * Copyright (C) 2011-2012 The ManaPlus Developers * * This file is part of The ManaPlus Client. * * 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 2 of the License, or * 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 CONFIGURATION_H #define CONFIGURATION_H #include "utils/stringutils.h" #include "utils/xml.h" #include "defaults.h" #include "localconsts.h" #include <cassert> #include <list> #include <map> #include <string> class ConfigListener; class ConfigurationObject; /** * Configuration list manager interface; responsible for * serializing/deserializing configuration choices in containers. * * \param T Type of the container elements to serialise * \param CONT Type of the container we (de)serialise */ template <class T, class CONT> class ConfigurationListManager { public: /** * Writes a value into a configuration object * * \param value The value to write out * \param obj The configuation object to write to * \return obj, or otherwise NULL to indicate that this option should * be skipped */ virtual ConfigurationObject *writeConfigItem(T value, ConfigurationObject *obj) = 0; /** * Reads a value from a configuration object * * \param obj The configuration object to read from * \param container The container to insert the object to */ virtual CONT readConfigItem(ConfigurationObject *const obj, CONT container) = 0; virtual ~ConfigurationListManager() {} }; /** * Configuration object, mapping values to names and possibly containing * lists of further configuration objects * * \ingroup CORE */ class ConfigurationObject { friend class Configuration; public: virtual ~ConfigurationObject(); /** * Sets an option using a string value. * * \param key Option identifier. * \param value Value. */ virtual void setValue(const std::string &key, const std::string &value); void deleteKey(const std::string &key); /** * Gets a value as string. * * \param key Option identifier. * \param deflt Default option if not there or error. */ std::string getValue(const std::string &key, const std::string &deflt) const; int getValue(const std::string &key, const int deflt) const; int getValueInt(const std::string &key, const int deflt) const; bool getValueBool(const std::string &key, const bool deflt) const; unsigned getValue(const std::string &key, const unsigned deflt) const; double getValue(const std::string &key, const double deflt) const; /** * Re-sets all data in the configuration */ virtual void clear(); /** * Serialises a container into a list of configuration options * * \param IT Iterator type over CONT * \param T Elements that IT iterates over * \param CONT The associated container type * * \param name Name of the list the elements should be stored under * \param begin Iterator start * \param end Iterator end * \param manager An object capable of serialising T items */ template <class IT, class T, class CONT> void setList(const std::string &name, IT begin, IT end, ConfigurationListManager<T, CONT> *manager) { if (!manager) return; ConfigurationObject *nextobj = new ConfigurationObject; deleteList(name); ConfigurationList *list = &(mContainerOptions[name]); for (IT it = begin; it != end; it++) { ConfigurationObject *wrobj = manager->writeConfigItem(*it, nextobj); if (wrobj) { // wrote something assert (wrobj == nextobj); nextobj = new ConfigurationObject; list->push_back(wrobj); } else { nextobj->clear(); // you never know... } } delete nextobj; } /** * Serialises a container into a list of configuration options * * \param IT Iterator type over CONT * \param T Elements that IT iterates over * \param CONT The associated container type * * \param name Name of the list the elements should be read from under * \param empty Initial (empty) container to write to * \param manager An object capable of deserialising items into CONT */ template<class T, class CONT> CONT getList(const std::string &name, CONT empty, ConfigurationListManager<T, CONT> *manager) { ConfigurationList *list = &(mContainerOptions[name]); CONT container = empty; if (!manager) return container; for (ConfigurationList::const_iterator it = list->begin(); it != list->end(); ++ it) { container = manager->readConfigItem(*it, container); } return container; } #ifdef DEBUG_CONFIG void enableKeyLogging() { mLogKeys = true; } void setIsMain(bool b) { mIsMain = b; } #endif protected: virtual void initFromXML(const XmlNodePtr parent_node); virtual void writeToXML(const XmlTextWriterPtr writer); void deleteList(const std::string &name); typedef std::map<std::string, std::string> Options; Options mOptions; typedef std::list<ConfigurationObject *> ConfigurationList; std::map<std::string, ConfigurationList> mContainerOptions; #ifdef DEBUG_CONFIG bool mLogKeys; bool mIsMain; #endif }; /** * Configuration handler for reading (and writing). * * \ingroup CORE */ class Configuration final : public ConfigurationObject { public: Configuration(); ~Configuration(); /** * Reads config file and parse all options into memory. * * @param filename path to config file * @param useResManager Make use of the resource manager. */ void init(const std::string &filename, const bool useResManager = false); /** * Set the default values for each keys. * * @param defaultsData data used as defaults. */ void setDefaultValues(DefaultsData *const defaultsData); /** * Writes the current settings back to the config file. */ void write(); /** * Adds a listener to the listen list of the specified config option. */ void addListener(const std::string &key, ConfigListener *const listener); /** * Removes a listener from the listen list of the specified config * option. */ void removeListener(const std::string &key, ConfigListener *const listener); void removeListeners(ConfigListener *const listener); void setValue(const std::string &key, const std::string &value); void setSilent(const std::string &key, const std::string &value); inline void setValue(const std::string &key, const char *const value) { if (value) setValue(key, std::string(value)); } inline void setSilent(const std::string &key, const char *const value) { if (value) setSilent(key, std::string(value)); } inline void setValue(const std::string &key, const float value) { setValue(key, toString(value)); } inline void setValue(const std::string &key, const double value) { setValue(key, toString(value)); } inline void setValue(const std::string &key, const int value) { setValue(key, toString(value)); } inline void setValueInt(const std::string &key, const int value) { setValue(key, toString(value)); } inline void setValue(const std::string &key, const unsigned value) { setValue(key, toString(value)); } inline void setValue(const std::string &key, const bool value) { setValue(key, value ? "1" : "0"); } inline void setSilent(const std::string &key, const bool value) { setSilent(key, value ? "1" : "0"); } int resetIntValue(const std::string &key); bool resetBoolValue(const std::string &key); const std::string getConfigPath() const { return mConfigPath; } /** * returns a value corresponding to the given key. * The default value returned in based on fallbacks registry. * @see defaults.h */ int getIntValue(const std::string &key) const; float getFloatValue(const std::string &key) const; std::string getStringValue(const std::string &key) const; bool getBoolValue(const std::string &key) const; std::string getDirectory() const { return mDirectory; } void removeOldKeys(); private: /** * Clean up the default values member. */ void cleanDefaults(); typedef std::list<ConfigListener*> Listeners; typedef Listeners::iterator ListenerIterator; typedef std::map<std::string, Listeners> ListenerMap; typedef ListenerMap::iterator ListenerMapIterator; ListenerMap mListenerMap; std::string mConfigPath; /**< Location of config file */ DefaultsData *mDefaultsData; /**< Defaults of value for a given key */ std::string mDirectory; }; extern Configuration branding; extern Configuration config; extern Configuration serverConfig; extern Configuration paths; #endif