aboutsummaryrefslogtreecommitdiff
path: root/lib/libconfigcpp.c++
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libconfigcpp.c++')
-rw-r--r--lib/libconfigcpp.c++1487
1 files changed, 1487 insertions, 0 deletions
diff --git a/lib/libconfigcpp.c++ b/lib/libconfigcpp.c++
new file mode 100644
index 0000000..9cdee4d
--- /dev/null
+++ b/lib/libconfigcpp.c++
@@ -0,0 +1,1487 @@
+/* ----------------------------------------------------------------------------
+ libconfig - A library for processing structured configuration files
+ Copyright (C) 2005-2018 Mark A Lindner
+
+ This file is part of libconfig.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, see
+ <http://www.gnu.org/licenses/>.
+ ----------------------------------------------------------------------------
+*/
+
+#include "libconfig.h++"
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4996)
+#endif
+
+#include "wincompat.h"
+#include "libconfig.h"
+
+#include <cstring>
+#include <cstdlib>
+#include <sstream>
+
+namespace libconfig {
+
+// ---------------------------------------------------------------------------
+
+static const char **__include_func(config_t *config,
+ const char *include_dir,
+ const char *path,
+ const char **error)
+{
+ Config *self = reinterpret_cast<Config *>(config_get_hook(config));
+ return(self->evaluateIncludePath(path, error));
+}
+
+// ---------------------------------------------------------------------------
+
+ParseException::ParseException(const char *file, int line, const char *error)
+ : _file(file ? ::strdup(file) : NULL), _line(line), _error(error)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+ParseException::ParseException(const ParseException &other)
+ : ConfigException(other),
+ _file(other._file ? ::strdup(other._file) : NULL),
+ _line(other._line),
+ _error(other._error)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+ParseException::~ParseException() LIBCONFIGXX_NOEXCEPT
+{
+ ::free((void *)_file);
+}
+
+// ---------------------------------------------------------------------------
+
+const char *ParseException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("ParseException");
+}
+
+// ---------------------------------------------------------------------------
+
+static int __toTypeCode(Setting::Type type)
+{
+ int typecode;
+
+ switch(type)
+ {
+ case Setting::TypeGroup:
+ typecode = CONFIG_TYPE_GROUP;
+ break;
+
+ case Setting::TypeInt:
+ typecode = CONFIG_TYPE_INT;
+ break;
+
+ case Setting::TypeInt64:
+ typecode = CONFIG_TYPE_INT64;
+ break;
+
+ case Setting::TypeFloat:
+ typecode = CONFIG_TYPE_FLOAT;
+ break;
+
+ case Setting::TypeString:
+ typecode = CONFIG_TYPE_STRING;
+ break;
+
+ case Setting::TypeBoolean:
+ typecode = CONFIG_TYPE_BOOL;
+ break;
+
+ case Setting::TypeArray:
+ typecode = CONFIG_TYPE_ARRAY;
+ break;
+
+ case Setting::TypeList:
+ typecode = CONFIG_TYPE_LIST;
+ break;
+
+ default:
+ typecode = CONFIG_TYPE_NONE;
+ }
+
+ return(typecode);
+}
+
+// ---------------------------------------------------------------------------
+
+static void __constructPath(const Setting &setting,
+ std::stringstream &path)
+{
+ // head recursion to print path from root to target
+
+ if(! setting.isRoot())
+ {
+ __constructPath(setting.getParent(), path);
+ if(path.tellp() > 0)
+ path << '.';
+
+ const char *name = setting.getName();
+ if(name)
+ path << name;
+ else
+ path << '[' << setting.getIndex() << ']';
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::SettingException(const Setting &setting)
+{
+ std::stringstream sstr;
+ __constructPath(setting, sstr);
+
+ _path = ::strdup(sstr.str().c_str());
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::SettingException(const Setting &setting, int idx)
+{
+ std::stringstream sstr;
+ __constructPath(setting, sstr);
+ sstr << ".[" << idx << "]";
+
+ _path = ::strdup(sstr.str().c_str());
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::SettingException(const Setting &setting, const char *name)
+{
+ std::stringstream sstr;
+ __constructPath(setting, sstr);
+ sstr << '.' << name;
+
+ _path = ::strdup(sstr.str().c_str());
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::SettingException(const char *path)
+{
+ _path = ::strdup(path);
+}
+
+// ---------------------------------------------------------------------------
+
+const char *SettingException::getPath() const
+{
+ return(_path);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::SettingException(const SettingException &other)
+ : ConfigException(other)
+{
+ _path = ::strdup(other._path);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException &SettingException::operator=(const SettingException &other)
+{
+ ::free(_path);
+ _path = ::strdup(other._path);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+const char *SettingException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("SettingException");
+}
+
+// ---------------------------------------------------------------------------
+
+SettingException::~SettingException() LIBCONFIGXX_NOEXCEPT
+{
+ ::free(_path);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingTypeException::SettingTypeException(const Setting &setting)
+ : SettingException(setting)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingTypeException::SettingTypeException(const Setting &setting, int idx)
+ : SettingException(setting, idx)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingTypeException::SettingTypeException(const Setting &setting,
+ const char *name)
+ : SettingException(setting, name)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+const char *SettingTypeException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("SettingTypeException");
+}
+
+// ---------------------------------------------------------------------------
+
+SettingNotFoundException::SettingNotFoundException(const Setting &setting,
+ int idx)
+ : SettingException(setting, idx)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingNotFoundException::SettingNotFoundException(const Setting &setting,
+ const char *name)
+ : SettingException(setting, name)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingNotFoundException::SettingNotFoundException(const char *path)
+ : SettingException(path)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+const char *SettingNotFoundException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("SettingNotFoundException");
+}
+
+// ---------------------------------------------------------------------------
+
+SettingNameException::SettingNameException(const Setting &setting,
+ const char *name)
+ : SettingException(setting, name)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+const char *SettingNameException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("SettingNameException");
+}
+
+// ---------------------------------------------------------------------------
+
+const char *FileIOException::what() const LIBCONFIGXX_NOEXCEPT
+{
+ return("FileIOException");
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::ConfigDestructor(void *arg)
+{
+ delete reinterpret_cast<Setting *>(arg);
+}
+
+// ---------------------------------------------------------------------------
+
+Config::Config()
+ : _defaultFormat(Setting::FormatDefault)
+{
+ _config = new config_t;
+ config_init(_config);
+ config_set_hook(_config, reinterpret_cast<void *>(this));
+ config_set_destructor(_config, ConfigDestructor);
+ config_set_include_func(_config, __include_func);
+}
+
+// ---------------------------------------------------------------------------
+
+Config::~Config()
+{
+ config_destroy(_config);
+ delete _config;
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::clear()
+{
+ config_clear(_config);
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setOptions(int options)
+{
+ config_set_options(_config, options);
+}
+
+// ---------------------------------------------------------------------------
+
+int Config::getOptions() const
+{
+ return(config_get_options(_config));
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setOption(Config::Option option, bool flag)
+{
+ config_set_option(_config, (int)option, flag ? CONFIG_TRUE : CONFIG_FALSE);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::getOption(Config::Option option) const
+{
+ return(config_get_option(_config, (int)option) == CONFIG_TRUE);
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setDefaultFormat(Setting::Format format)
+{
+ if(format == Setting::FormatHex)
+ _defaultFormat = Setting::FormatHex;
+ else
+ _defaultFormat = Setting::FormatDefault;
+
+ config_set_default_format(_config, static_cast<short>(_defaultFormat));
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setTabWidth(unsigned short width)
+{
+ config_set_tab_width(_config, width);
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned short Config::getTabWidth() const
+{
+ return(config_get_tab_width(_config));
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setFloatPrecision(unsigned short digits)
+{
+ return (config_set_float_precision(_config,digits));
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned short Config::getFloatPrecision() const
+{
+ return (config_get_float_precision(_config));
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::setIncludeDir(const char *includeDir)
+{
+ config_set_include_dir(_config, includeDir);
+}
+
+// ---------------------------------------------------------------------------
+
+const char *Config::getIncludeDir() const
+{
+ return(config_get_include_dir(_config));
+}
+
+// ---------------------------------------------------------------------------
+
+const char **Config::evaluateIncludePath(const char *path, const char **error)
+{
+ return(config_default_include_func(_config, getIncludeDir(), path, error));
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::handleError() const
+{
+ switch(config_error_type(_config))
+ {
+ case CONFIG_ERR_NONE:
+ break;
+
+ case CONFIG_ERR_PARSE:
+ throw ParseException(config_error_file(_config),
+ config_error_line(_config),
+ config_error_text(_config));
+ break;
+
+ case CONFIG_ERR_FILE_IO:
+ default:
+ throw FileIOException();
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::read(FILE *stream)
+{
+ if(! config_read(_config, stream))
+ handleError();
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::readString(const char *str)
+{
+ if(! config_read_string(_config, str))
+ handleError();
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::write(FILE *stream) const
+{
+ config_write(_config, stream);
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::readFile(const char *filename)
+{
+ if(! config_read_file(_config, filename))
+ handleError();
+}
+
+// ---------------------------------------------------------------------------
+
+void Config::writeFile(const char *filename)
+{
+ if(! config_write_file(_config, filename))
+ handleError();
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Config::lookup(const char *path) const
+{
+ config_setting_t *s = config_lookup(_config, path);
+ if(! s)
+ throw SettingNotFoundException(path);
+
+ return(Setting::wrapSetting(s));
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::exists(const char *path) const
+{
+ config_setting_t *s = config_lookup(_config, path);
+
+ return(s != NULL);
+}
+
+// ---------------------------------------------------------------------------
+
+#define CONFIG_LOOKUP_NO_EXCEPTIONS(P, T, V) \
+ try \
+ { \
+ Setting &s = lookup(P); \
+ V = (T)s; \
+ return(true); \
+ } \
+ catch(const ConfigException &) \
+ { \
+ return(false); \
+ }
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, bool &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, bool, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, int &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, int, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, unsigned int &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned int, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, long long &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, long long, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, unsigned long long &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned long long, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, double &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, double, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, float &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, float, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, const char *&value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Config::lookupValue(const char *path, std::string &value) const
+{
+ CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Config::getRoot() const
+{
+ return(Setting::wrapSetting(config_root_setting(_config)));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::Setting(config_setting_t *setting)
+ : _setting(setting)
+{
+ switch(config_setting_type(setting))
+ {
+ case CONFIG_TYPE_GROUP:
+ _type = TypeGroup;
+ break;
+
+ case CONFIG_TYPE_INT:
+ _type = TypeInt;
+ break;
+
+ case CONFIG_TYPE_INT64:
+ _type = TypeInt64;
+ break;
+
+ case CONFIG_TYPE_FLOAT:
+ _type = TypeFloat;
+ break;
+
+ case CONFIG_TYPE_STRING:
+ _type = TypeString;
+ break;
+
+ case CONFIG_TYPE_BOOL:
+ _type = TypeBoolean;
+ break;
+
+ case CONFIG_TYPE_ARRAY:
+ _type = TypeArray;
+ break;
+
+ case CONFIG_TYPE_LIST:
+ _type = TypeList;
+ break;
+
+ case CONFIG_TYPE_NONE:
+ default:
+ _type = TypeNone;
+ break;
+ }
+
+ switch(config_setting_get_format(setting))
+ {
+ case CONFIG_FORMAT_HEX:
+ _format = FormatHex;
+ break;
+
+ case CONFIG_FORMAT_DEFAULT:
+ default:
+ _format = FormatDefault;
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::~Setting()
+{
+ _setting = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+void Setting::setFormat(Format format)
+{
+ if((_type == TypeInt) || (_type == TypeInt64))
+ {
+ if(format == FormatHex)
+ _format = FormatHex;
+ else
+ _format = FormatDefault;
+ }
+ else
+ _format = FormatDefault;
+
+ config_setting_set_format(_setting, static_cast<short>(_format));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator bool() const
+{
+ assertType(TypeBoolean);
+
+ return(config_setting_get_bool(_setting) ? true : false);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator int() const
+{
+ assertType(TypeInt);
+
+ return(config_setting_get_int(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator unsigned int() const
+{
+ assertType(TypeInt);
+
+ int v = config_setting_get_int(_setting);
+
+ return(static_cast<unsigned int>(v));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator long() const
+{
+ if(sizeof(long) == sizeof(long long))
+ return operator long long();
+ else
+ return operator int();
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator unsigned long() const
+{
+ if(sizeof(long) == sizeof(long long))
+ return operator unsigned long long();
+ else
+ return operator unsigned int();
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator long long() const
+{
+ assertType(TypeInt64);
+
+ return(config_setting_get_int64(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator unsigned long long() const
+{
+ assertType(TypeInt64);
+
+ long long v = config_setting_get_int64(_setting);
+
+ return(static_cast<unsigned long long>(v));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator double() const
+{
+ assertType(TypeFloat);
+
+ return(config_setting_get_float(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator float() const
+{
+ assertType(TypeFloat);
+
+ // may cause loss of precision:
+ return(static_cast<float>(config_setting_get_float(_setting)));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator const char *() const
+{
+ assertType(TypeString);
+
+ return(config_setting_get_string(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::operator std::string() const
+{
+ assertType(TypeString);
+
+ const char *s = config_setting_get_string(_setting);
+
+ std::string str;
+ if(s)
+ str = s;
+
+ return(str);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(bool value)
+{
+ assertType(TypeBoolean);
+
+ config_setting_set_bool(_setting, value);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(int value)
+{
+ assertType(TypeInt);
+
+ config_setting_set_int(_setting, value);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(long value)
+{
+ if(sizeof(long) == sizeof(long long))
+ return(operator=(static_cast<long long>(value)));
+ else
+ return(operator=(static_cast<int>(value)));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(const long long &value)
+{
+ assertType(TypeInt64);
+
+ config_setting_set_int64(_setting, value);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(const double &value)
+{
+ assertType(TypeFloat);
+
+ config_setting_set_float(_setting, value);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(float value)
+{
+ assertType(TypeFloat);
+
+ double cvalue = static_cast<double>(value);
+
+ config_setting_set_float(_setting, cvalue);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(const char *value)
+{
+ assertType(TypeString);
+
+ config_setting_set_string(_setting, value);
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator=(const std::string &value)
+{
+ assertType(TypeString);
+
+ config_setting_set_string(_setting, value.c_str());
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::lookup(const char *path) const
+{
+ assertType(TypeGroup);
+
+ config_setting_t *setting = config_setting_lookup(_setting, path);
+
+ if(! setting)
+ throw SettingNotFoundException(*this, path);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator[](const char *name) const
+{
+ assertType(TypeGroup);
+
+ config_setting_t *setting = config_setting_get_member(_setting, name);
+
+ if(! setting)
+ throw SettingNotFoundException(*this, name);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::operator[](int i) const
+{
+ if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList))
+ throw SettingTypeException(*this, i);
+
+ config_setting_t *setting = config_setting_get_elem(_setting, i);
+
+ if(! setting)
+ throw SettingNotFoundException(*this, i);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+#define SETTING_LOOKUP_NO_EXCEPTIONS(K, T, V) \
+ try \
+ { \
+ Setting &s = operator[](K); \
+ V = (T)s; \
+ return(true); \
+ } \
+ catch(const ConfigException &) \
+ { \
+ return(false); \
+ }
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, bool &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, bool, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, int &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, int, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, unsigned int &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned int, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, long long &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, long long, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, unsigned long long &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned long long, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, double &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, double, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, float &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, float, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, const char *&value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::lookupValue(const char *name, std::string &value) const
+{
+ SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value);
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::exists(const char *name) const
+{
+ if(_type != TypeGroup)
+ return(false);
+
+ config_setting_t *setting = config_setting_get_member(_setting, name);
+
+ return(setting != NULL);
+}
+
+// ---------------------------------------------------------------------------
+
+int Setting::getLength() const
+{
+ return(config_setting_length(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+const char * Setting::getName() const
+{
+ return(config_setting_name(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+std::string Setting::getPath() const
+{
+ std::stringstream path;
+
+ __constructPath(*this, path);
+
+ return(path.str());
+}
+
+// ---------------------------------------------------------------------------
+
+const Setting & Setting::getParent() const
+{
+ config_setting_t *setting = config_setting_parent(_setting);
+
+ if(! setting)
+ throw SettingNotFoundException(NULL);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::getParent()
+{
+ config_setting_t *setting = config_setting_parent(_setting);
+
+ if(! setting)
+ throw SettingNotFoundException(NULL);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned int Setting::getSourceLine() const
+{
+ return(config_setting_source_line(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+const char *Setting::getSourceFile() const
+{
+ return(config_setting_source_file(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+bool Setting::isRoot() const
+{
+ return(config_setting_is_root(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+int Setting::getIndex() const
+{
+ return(config_setting_index(_setting));
+}
+
+// ---------------------------------------------------------------------------
+
+void Setting::remove(const char *name)
+{
+ assertType(TypeGroup);
+
+ if(! config_setting_remove(_setting, name))
+ throw SettingNotFoundException(*this, name);
+}
+
+// ---------------------------------------------------------------------------
+
+void Setting::remove(unsigned int idx)
+{
+ if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList))
+ throw SettingTypeException(*this, idx);
+
+ if(! config_setting_remove_elem(_setting, idx))
+ throw SettingNotFoundException(*this, idx);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::add(const char *name, Setting::Type type)
+{
+ assertType(TypeGroup);
+
+ int typecode = __toTypeCode(type);
+
+ if(typecode == CONFIG_TYPE_NONE)
+ throw SettingTypeException(*this, name);
+
+ config_setting_t *setting = config_setting_add(_setting, name, typecode);
+
+ if(! setting)
+ throw SettingNameException(*this, name);
+
+ return(wrapSetting(setting));
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::add(Setting::Type type)
+{
+ if((_type != TypeArray) && (_type != TypeList))
+ throw SettingTypeException(*this);
+
+ if(_type == TypeArray)
+ {
+ int idx = getLength();
+
+ if(idx > 0)
+ {
+ Setting::Type atype = operator[](0).getType();
+ if(type != atype)
+ throw SettingTypeException(*this, idx);
+ }
+ else
+ {
+ if((type != TypeInt) && (type != TypeInt64) && (type != TypeFloat)
+ && (type != TypeString) && (type != TypeBoolean))
+ throw SettingTypeException(*this, idx);
+ }
+ }
+
+ int typecode = __toTypeCode(type);
+ config_setting_t *s = config_setting_add(_setting, NULL, typecode);
+
+ Setting &ns = wrapSetting(s);
+
+ switch(type)
+ {
+ case TypeInt:
+ ns = 0;
+ break;
+
+ case TypeInt64:
+ ns = INT64_CONST(0);
+ break;
+
+ case TypeFloat:
+ ns = 0.0;
+ break;
+
+ case TypeString:
+ ns = (char *)NULL;
+ break;
+
+ case TypeBoolean:
+ ns = false;
+ break;
+
+ default:
+ // won't happen
+ break;
+ }
+
+ return(ns);
+}
+
+// ---------------------------------------------------------------------------
+
+void Setting::assertType(Setting::Type type) const
+{
+ if(type != _type)
+ {
+ if(!(isNumber() && config_get_auto_convert(_setting->config)
+ && ((type == TypeInt) || (type == TypeInt64) || (type == TypeFloat))))
+ throw SettingTypeException(*this);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+Setting & Setting::wrapSetting(config_setting_t *s)
+{
+ Setting *setting = NULL;
+
+ void *hook = config_setting_get_hook(s);
+ if(! hook)
+ {
+ setting = new Setting(s);
+ config_setting_set_hook(s, reinterpret_cast<void *>(setting));
+ }
+ else
+ setting = reinterpret_cast<Setting *>(hook);
+
+ return(*setting);
+}
+
+// ---------------------------------------------------------------------------
+
+Setting::iterator Setting::begin()
+{ return(iterator(*this)); }
+
+// ---------------------------------------------------------------------------
+
+Setting::iterator Setting::end()
+{ return(iterator(*this, true)); }
+
+// ---------------------------------------------------------------------------
+
+Setting::const_iterator Setting::begin() const
+{ return(const_iterator(*this)); }
+
+// ---------------------------------------------------------------------------
+
+Setting::const_iterator Setting::end() const
+{ return(const_iterator(*this, true)); }
+
+// ---------------------------------------------------------------------------
+
+SettingIterator::SettingIterator(Setting& setting, bool endIterator)
+ : _setting(&setting),
+ _count(setting.getLength()),
+ _idx(endIterator ? _count : 0)
+{
+ if(!setting.isAggregate())
+ throw SettingTypeException(setting);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator::SettingIterator(const SettingIterator &other)
+ : _setting(other._setting),
+ _count(other._count),
+ _idx(other._idx)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator& SettingIterator::operator=(const SettingIterator &other)
+{
+ _setting = other._setting;
+ _count = other._count;
+ _idx = other._idx;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator& SettingIterator::operator++()
+{
+ ++_idx;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator SettingIterator::operator++(int)
+{
+ SettingIterator tmp(*this);
+ ++_idx;
+
+ return(tmp);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator& SettingIterator::operator--()
+{
+ --_idx;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator SettingIterator::operator--(int)
+{
+ SettingIterator tmp(*this);
+ --_idx;
+
+ return(tmp);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator SettingIterator::operator+(int offset) const
+{
+ SettingIterator copy(*this);
+ copy += offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator& SettingIterator::operator+=(int offset)
+{
+ _idx += offset;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator operator+(int offset, SettingIterator& si)
+{
+ SettingIterator copy(si);
+ copy += offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator SettingIterator::operator-(int offset) const
+{
+ SettingIterator copy(*this);
+ copy._idx -= offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingIterator& SettingIterator::operator-=(int offset)
+{
+ _idx -= offset;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+int SettingIterator::operator-(SettingIterator const &other) const
+{
+ return(_idx - other._idx);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator::SettingConstIterator(const Setting &setting,
+ bool endIterator)
+ : _setting(&setting),
+ _count(setting.getLength()),
+ _idx(endIterator ? _count : 0)
+{
+ if(!setting.isAggregate())
+ throw SettingTypeException(setting);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator::SettingConstIterator(const SettingConstIterator &other)
+ : _setting(other._setting),
+ _count(other._count),
+ _idx(other._idx)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator& SettingConstIterator::operator=(
+ const SettingConstIterator &other)
+{
+ _setting = other._setting;
+ _count = other._count;
+ _idx = other._idx;
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator& SettingConstIterator::operator++()
+{
+ ++_idx;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator SettingConstIterator::operator++(int)
+{
+ SettingConstIterator tmp(*this);
+ ++_idx;
+
+ return(tmp);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator& SettingConstIterator::operator--()
+{
+ --_idx;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator SettingConstIterator::operator--(int)
+{
+ SettingConstIterator tmp(*this);
+ --_idx;
+
+ return(tmp);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator SettingConstIterator::operator+(int offset) const
+{
+ SettingConstIterator copy(*this);
+ copy += offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator& SettingConstIterator::operator+=(int offset)
+{
+ _idx += offset;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator operator+(int offset, SettingConstIterator &si)
+{
+ SettingConstIterator copy(si);
+ copy += offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator SettingConstIterator::operator-(int offset) const
+{
+ SettingConstIterator copy(*this);
+ copy -= offset;
+
+ return(copy);
+}
+
+// ---------------------------------------------------------------------------
+
+SettingConstIterator& SettingConstIterator::operator-=(int offset)
+{
+ _idx -= offset;
+
+ return(*this);
+}
+
+// ---------------------------------------------------------------------------
+
+int SettingConstIterator::operator-(SettingConstIterator const &other) const
+{
+ return(_idx - other._idx);
+}
+
+
+} // namespace libconfig
+