00001 #ifndef UTILMM_CONFIG_SET_HH
00002 #define UTILMM_CONFIG_SET_HH
00003
00004 #include <map>
00005 #include <string>
00006 #include <boost/noncopyable.hpp>
00007 #include <boost/lexical_cast.hpp>
00008 #include <boost/utility/enable_if.hpp>
00009
00010 #include <list>
00011
00012 namespace utilmm
00013 {
00014
00015 namespace details
00016 {
00017 template<typename T> struct is_list
00018 { static const bool value = false; };
00019 template<typename T> struct is_list< std::list<T> >
00020 { static const bool value = true; };
00021 }
00022
00024 class config_set
00025 : private boost::noncopyable
00026 {
00027 friend class ConfigFile;
00028
00029 private:
00030 typedef std::list<std::string> stringlist;
00031 template<typename T>
00032 static T convert(std::string const& value);
00033
00034 protected:
00035 config_set* m_parent;
00036 typedef std::multimap<std::string, std::string> ValueMap;
00037 ValueMap m_values;
00038 typedef std::multimap<std::string, const config_set*> ChildMap;
00039 ChildMap m_children;
00040
00041 protected:
00043 void clear();
00044
00045 public:
00046 explicit config_set(config_set* parent = 0);
00047 ~config_set();
00048
00049 typedef std::list<const config_set*> subsets;
00050
00052 bool empty() const;
00053
00055 bool exists (const std::string& attribute) const;
00056
00060 const config_set* parent() const;
00061 config_set* parent();
00062
00064 std::list<const config_set*> children(const std::string& name) const;
00066 config_set const& child(std::string const& name) const;
00067
00069 template<typename T>
00070 T get(std::string const& name, T const& defval = T(),
00071 typename boost::enable_if< details::is_list<T> >::type *enabler = 0) const;
00074 template<typename T>
00075 T get(std::string const& name, T const& defval = T(),
00076 typename boost::disable_if< details::is_list<T> >::type *enabler = 0) const;
00077
00079 void set(std::string const& name, std::string const& value);
00081 void set(std::string const& name, std::list<std::string> const& value);
00083 void insert(std::string const& name, std::string const& value);
00085 void insert(std::string const& name, std::list<std::string> const& value);
00087 void insert(std::string const& name, config_set const* value);
00089 void erase(std::string const& name);
00090 };
00091
00092 namespace details {
00093 typedef std::list<std::string> stringlist;
00094 }
00095
00096 template<> bool config_set::convert(std::string const& value);
00097 template<typename T>
00098 T config_set::convert(const std::string& value)
00099 { return boost::lexical_cast<T>(value); }
00100
00101
00105 template<>
00106 config_set::stringlist config_set::get(std::string const& name,
00107 config_set::stringlist const& defval,
00108 boost::enable_if< details::is_list<config_set::stringlist> >::type *enabler) const;
00109
00111 template<typename T>
00112 T config_set::get(std::string const& name, T const& defval,
00113 typename boost::enable_if< details::is_list<T> >::type *enabler) const
00114 {
00115 stringlist values = get< stringlist >(name);
00116 if (values.empty())
00117 return defval;
00118
00119 T result;
00120 for (stringlist::const_iterator it = values.begin(); it != values.end(); ++it)
00121 result.push_back(convert<typename T::value_type>(*it));
00122
00123 return result;
00124 }
00125
00127 template<typename T>
00128 T config_set::get(std::string const& name, T const& defval,
00129 typename boost::disable_if< details::is_list<T> >::type *enabler) const
00130 {
00131 std::list<T> deflist;
00132 deflist.push_back(defval);
00133 return get< std::list<T> >(name, deflist).front();
00134 }
00135 }
00136
00137 #endif
00138
00139
00140