/*
* 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 <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 *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, int deflt) const;
int getValueInt(const std::string &key, int deflt) const;
bool getValueBool(const std::string &key, bool deflt) const;
unsigned getValue(const std::string &key, unsigned deflt) const;
double getValue(const std::string &key, 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;
nextobj = 0;
}
/**
* 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;
}
protected:
virtual void initFromXML(XmlNodePtr node);
virtual void writeToXML(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;
};
/**
* Configuration handler for reading (and writing).
*
* \ingroup CORE
*/
class Configuration : 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, bool useResManager = false);
/**
* Set the default values for each keys.
*
* @param defaultsData data used as defaults.
*/
void setDefaultValues(DefaultsData *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 *listener);
/**
* Removes a listener from the listen list of the specified config
* option.
*/
void removeListener(const std::string &key, ConfigListener *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 *value)
{ setValue(key, std::string(value)); }
inline void setSilent(const std::string &key, const char *value)
{ setSilent(key, std::string(value)); }
inline void setValue(const std::string &key, float value)
{ setValue(key, toString(value)); }
inline void setValue(const std::string &key, double value)
{ setValue(key, toString(value)); }
inline void setValue(const std::string &key, int value)
{ setValue(key, toString(value)); }
inline void setValueInt(const std::string &key, int value)
{ setValue(key, toString(value)); }
inline void setValue(const std::string &key, unsigned value)
{ setValue(key, toString(value)); }
inline void setValue(const std::string &key, bool value)
{ setValue(key, value ? "1" : "0"); }
inline void setSilent(const std::string &key, 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; }
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