2 * @brief provides config file reading and automatic propagation of the values.
4 * @author Reinhard Pfau \<Reinhard.Pfau@intra2net.com\>
6 * @copyright © Copyright 2008 by Intra2net AG
8 * @contact info@intra2net.com
10 * Basic idea of this module is that one need only to declare its config vars of
11 * the type Config::Var\< T \> and pass the desired section and key from the
12 * (INI style) config file where the value for this var should be searched.
13 * The string value from the config file is converted to the desired type using a
14 * converter class (a default is provided and uses a conversion based on string_to template
17 * Populating the var is automagically done when the config is read or reread or when
18 * the variable is defined.
21 * @todo review. consolidate. beautify.
22 * @todo the converter should be better named as "validator" since they do not only convert...
23 * @todo support for std::set<> ?
26 #ifndef __I2N_GLOBAL_CONFIG_HPP__
27 #define __I2N_GLOBAL_CONFIG_HPP__
35 #include <stringfunc.hxx>
36 #include <boost/shared_ptr.hpp>
37 #include <boost/static_assert.hpp>
38 #include <boost/type_traits.hpp>
39 #include <boost/function.hpp>
40 #include <boost/bind.hpp>
41 #include <boost/foreach.hpp>
57 typedef std::vector< std::string > StringList;
60 * @brief contains the "magic" details of the config module
61 * (i.e. all the stuff which must be declared here, but U shouldn't use it!)
66 typedef boost::function< bool(const std::string&) > FeedFunction;
67 typedef boost::function< bool(const StringList&) > FeedFunction2;
75 typedef boost::shared_ptr< Thing > FlowerShop;
80 FlowerShop seymour(const std::string& section, const std::string& key, const FeedFunction& feed);
81 FlowerShop seymour(const std::string& section, const std::string& key, const FeedFunction2& feed);
82 FlowerShop seymour(FlowerShop shop, const FeedFunction& feed);
83 FlowerShop seymour(FlowerShop shop, const FeedFunction2& feed);
90 * @brief determines if a type is one of the supported list containers.
91 * @tparam Container the type to test for supported list type.
93 * currently we support std::list<> and std::vector<> (and derivates).
95 template< class Container >
96 struct is_list_container
98 static Container gen();
100 template< typename T >
101 static boost::type_traits::yes_type c1( const std::vector< T >& );
103 template< typename T >
104 static boost::type_traits::yes_type c1( const std::list< T >& );
106 static boost::type_traits::no_type c1(...);
108 BOOST_STATIC_CONSTANT( bool, value= ( sizeof(c1(gen())) == sizeof(boost::type_traits::yes_type) ) );
112 template< class C, bool is_list >
113 struct extract_type_impl
115 typedef typename boost::remove_reference< typename boost::remove_const< C >::type>::type type;
119 struct extract_type_impl< C, true >
121 typedef typename boost::remove_reference<
122 typename boost::remove_const< typename C::value_type >::type
128 : public extract_type_impl< C, is_list_container< C >::value >
145 typedef ValueType result_type;
146 typedef typename boost::remove_reference< ValueType >::type unref_value_type;
147 typedef typename boost::remove_const< unref_value_type>::type base_value_type;
148 typedef typename boost::add_const<
149 typename boost::add_reference< base_value_type >::type
150 >::type const_ref_value_type;
152 typedef FeedFunction FeedFunctionType;
155 friend class Var<ValueType, Converter>;
157 OuterSpace(ValueType initial_value)
158 : Value(initial_value)
159 , InitialValue(initial_value)
163 OuterSpace(const OuterSpace& other)
164 : Value( other.Value)
165 , InitialValue( other.InitialValue)
169 bool audreyII(const std::string& v)
171 bool res= Converter()(v,Value);
172 if (!res) Value= InitialValue;
174 } // eo audreyII(const std::string&)
176 base_value_type Value;
177 base_value_type InitialValue;
178 }; // eo class OuterSpace
185 class OuterSpace< ValueType, Converter, true >
188 typedef ValueType result_type;
189 typedef typename boost::remove_reference< ValueType >::type unref_value_type;
190 typedef typename boost::remove_const< unref_value_type>::type base_value_type;
191 typedef typename boost::add_const<
192 typename boost::add_reference< base_value_type >::type
193 >::type const_ref_value_type;
195 typedef FeedFunction2 FeedFunctionType;
198 friend class Var<ValueType, Converter>;
200 OuterSpace(ValueType initial_value)
201 : Value(initial_value)
202 , InitialValue(initial_value)
206 bool audreyII(const StringList& v)
211 BOOST_FOREACH(const std::string& s, v)
213 typename base_value_type::value_type value;
214 if (not convert(s,value))
219 Value.push_back( value );
221 if (not res) Value= InitialValue;
223 } // eo audreyII(const std::string&)
225 base_value_type Value;
226 base_value_type InitialValue;
227 }; // eo class OuterSpace
229 } // eo namespace Detail
233 * @brief default converter for the Var class.
234 * @tparam ValueType the type of the result value (which the input should be converted to)
236 * Uses stringTo to convert the values.
243 struct DefaultConverter
244 : public std::binary_function< std::string, ValueType&, bool >
247 bool operator () ( const std::string& str, ValueType& v )
249 return string_to< ValueType >( str, v );
250 } // eo operator()(const std::string&,ValueType&)
252 }; // eo struct DefaultConverter
256 * @brief specialized converter for std::string result type.
258 * just copies the input to the result var and returns true.
260 template<> struct DefaultConverter< std::string >
261 : public std::binary_function< std::string, std::string&, bool >
264 bool operator () ( const std::string& str, std::string& v )
268 } // eo operator()(const std::string&,std::string&)
270 }; // eo struct DefaultConverter< std::string >
275 * @brief specialized converter for int types which accepts also octal and hex notation as input.
276 * @tparam ValueType the type of the result value (which the input should be converted to)
281 struct AutoIntConverter
282 : public std::binary_function< std::string, ValueType&, bool >
285 bool operator () ( const std::string& str, ValueType& v )
287 std::istringstream istr(str);
288 if (has_prefix(str,"0x"))
290 istr.get(); istr.get();
291 istr.setf( std::ios::hex, std::ios::basefield );
293 else if (has_prefix(str,"0") or has_prefix(str,"-0"))
295 istr.setf( std::ios::oct, std::ios::basefield );
299 } // eo operator()(const std::string&,ValueType&)
301 }; // eo struct AutoIntConverter
306 * @brief represents a configuration variable with automatic update.
307 * @tparam ValueType type of the value this variable should hold.
308 * @tparam Converter a converter class which converts a string (from config file) to the desired
310 * Needs to be derived from std::binary_function (taking a string as first arg, a reference to the
311 * desired type as second and returning bool (@a true if conversion was succesful).
313 * Basic idea is to pass a point (section, key) in the config where the value for this
314 * variable is stored. The config value (a string) should be converted to the desired value (type).
315 * When the config is loaded (or reloaded) the var (content) is automatically updated.
317 * @see DefaultConverter
319 * @bug value accessing methods are @a const, but the result type may allow changing the internal value...
323 class Converter = DefaultConverter<
324 typename Detail::extract_type< ValueType >::type
328 : public Detail::OuterSpace<
329 ValueType, Converter,
330 Detail::is_list_container< ValueType >::value >
332 BOOST_STATIC_ASSERT(( boost::is_base_of<
333 std::binary_function<
335 typename boost::add_reference<
336 typename Detail::extract_type< ValueType >::type
339 Converter >::value ));
341 typedef Detail::OuterSpace<
342 ValueType, Converter,
343 Detail::is_list_container< ValueType >::value
348 typedef typename MySpace::result_type result_type;
349 typedef typename MySpace::base_value_type base_value_type;
354 * @brief constructor with config location and initial value.
355 * @param section the section in the config where the value is located in.
356 * @param key the key (in the section) which identifies the value.
357 * @param initial_value the initial value.
359 Var(const std::string& section,
360 const std::string& key,
361 ValueType initial_value)
362 : MySpace(initial_value)
364 FlowerShop= Detail::seymour(
366 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
371 * @brief constructor with config location (key in global section) and initial value.
372 * @param key the key (in the global section) which identifies the value.
373 * @param initial_value the initial value.
375 Var(const std::string& key,
376 ValueType initial_value)
377 : MySpace(initial_value)
379 FlowerShop= Detail::seymour(
381 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
386 * @brief operator for accessing the value.
387 * @return the current value.
389 result_type operator()() const { return MySpace::Value; }
393 * @brief method for accessing the value.
394 * @return the current value.
396 result_type get_value() const { return MySpace::Value; }
400 * @brief copy constructor.
401 * @param other the instance to copy from.
403 Var(const Var& other)
406 FlowerShop= Detail::seymour(
408 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
409 } // eo Var(const Var&)
413 * @brief cast operator for the underlying value type. delivers the value.
414 * @return the current value.
416 * The cast operator allows the instance to be used whereever the underlying value type
419 operator result_type () const { return MySpace::Value; }
424 Detail::FlowerShop FlowerShop;
431 * @brief convenience: \<\< operator which streams the current value of a config var.
437 std::ostream& operator<<(std::ostream& o, const Var< ValueType, Converter >& v)
440 } // eo operator<<(std::ostream&,const Var< ValueType, Converter>&
443 bool set_config_file(const std::string& path);
445 std::string get_config_file();
450 } // eo namespace Config
452 } // eo namespace I2n