2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
21 * @brief provides config file reading and automatic propagation of the values.
23 * @author Reinhard Pfau
25 * @copyright © Copyright 2008 by Intra2net AG
27 * Basic idea of this module is that one need only to declare its config vars of
28 * the type Config::Var\< T \> and pass the desired section and key from the
29 * (INI style) config file where the value for this var should be searched.
30 * The string value from the config file is converted to the desired type using a
31 * converter class (a default is provided and uses a conversion based on string_to template
34 * Populating the var is automagically done when the config is read or reread or when
35 * the variable is defined.
38 * @todo review. consolidate. beautify.
39 * @todo the converter should be better named as "validator" since they do not only convert...
40 * @todo support for std::set<> ?
43 #ifndef __I2N_GLOBAL_CONFIG_HPP__
44 #define __I2N_GLOBAL_CONFIG_HPP__
52 #include <stringfunc.hxx>
53 #include <boost/shared_ptr.hpp>
54 #include <boost/static_assert.hpp>
55 #include <boost/type_traits.hpp>
56 #include <boost/function.hpp>
57 #include <boost/bind.hpp>
58 #include <boost/foreach.hpp>
74 typedef std::vector< std::string > StringList;
77 * @brief contains the "magic" details of the config module
78 * (i.e. all the stuff which must be declared here, but U shouldn't use it!)
83 typedef boost::function< bool(const std::string&) > FeedFunction;
84 typedef boost::function< bool(const StringList&) > FeedFunction2;
92 typedef boost::shared_ptr< Thing > FlowerShop;
97 FlowerShop seymour(const std::string& section, const std::string& key, const FeedFunction& feed);
98 FlowerShop seymour(const std::string& section, const std::string& key, const FeedFunction2& feed);
99 FlowerShop seymour(FlowerShop shop, const FeedFunction& feed);
100 FlowerShop seymour(FlowerShop shop, const FeedFunction2& feed);
107 * @brief determines if a type is one of the supported list containers.
108 * @tparam Container the type to test for supported list type.
110 * currently we support std::list<> and std::vector<> (and derivates).
112 template< class Container >
113 struct is_list_container
115 static Container gen();
117 template< typename T >
118 static boost::type_traits::yes_type c1( const std::vector< T >& );
120 template< typename T >
121 static boost::type_traits::yes_type c1( const std::list< T >& );
123 static boost::type_traits::no_type c1(...);
125 BOOST_STATIC_CONSTANT( bool, value= ( sizeof(c1(gen())) == sizeof(boost::type_traits::yes_type) ) );
129 template< class C, bool is_list >
130 struct extract_type_impl
132 typedef typename boost::remove_reference< typename boost::remove_const< C >::type>::type type;
136 struct extract_type_impl< C, true >
138 typedef typename boost::remove_reference<
139 typename boost::remove_const< typename C::value_type >::type
145 : public extract_type_impl< C, is_list_container< C >::value >
162 typedef ValueType result_type;
163 typedef typename boost::remove_reference< ValueType >::type unref_value_type;
164 typedef typename boost::remove_const< unref_value_type>::type base_value_type;
165 typedef typename boost::add_const<
166 typename boost::add_reference< base_value_type >::type
167 >::type const_ref_value_type;
169 typedef FeedFunction FeedFunctionType;
172 friend class Var<ValueType, Converter>;
174 OuterSpace(ValueType initial_value)
175 : Value(initial_value)
176 , InitialValue(initial_value)
180 OuterSpace(const OuterSpace& other)
181 : Value( other.Value)
182 , InitialValue( other.InitialValue)
186 bool audreyII(const std::string& v)
188 bool res= Converter()(v,Value);
189 if (!res) Value= InitialValue;
191 } // eo audreyII(const std::string&)
193 base_value_type Value;
194 base_value_type InitialValue;
195 }; // eo class OuterSpace
202 class OuterSpace< ValueType, Converter, true >
205 typedef ValueType result_type;
206 typedef typename boost::remove_reference< ValueType >::type unref_value_type;
207 typedef typename boost::remove_const< unref_value_type>::type base_value_type;
208 typedef typename boost::add_const<
209 typename boost::add_reference< base_value_type >::type
210 >::type const_ref_value_type;
212 typedef FeedFunction2 FeedFunctionType;
215 friend class Var<ValueType, Converter>;
217 OuterSpace(ValueType initial_value)
218 : Value(initial_value)
219 , InitialValue(initial_value)
223 bool audreyII(const StringList& v)
228 BOOST_FOREACH(const std::string& s, v)
230 typename base_value_type::value_type value;
231 if (not convert(s,value))
236 Value.push_back( value );
238 if (not res) Value= InitialValue;
240 } // eo audreyII(const std::string&)
242 base_value_type Value;
243 base_value_type InitialValue;
244 }; // eo class OuterSpace
246 } // eo namespace Detail
250 * @brief default converter for the Var class.
251 * @tparam ValueType the type of the result value (which the input should be converted to)
253 * Uses stringTo to convert the values.
260 struct DefaultConverter
261 : public std::binary_function< std::string, ValueType&, bool >
264 bool operator () ( const std::string& str, ValueType& v )
266 return string_to< ValueType >( str, v );
267 } // eo operator()(const std::string&,ValueType&)
269 }; // eo struct DefaultConverter
273 * @brief specialized converter for std::string result type.
275 * just copies the input to the result var and returns true.
277 template<> struct DefaultConverter< std::string >
278 : public std::binary_function< std::string, std::string&, bool >
281 bool operator () ( const std::string& str, std::string& v )
285 } // eo operator()(const std::string&,std::string&)
287 }; // eo struct DefaultConverter< std::string >
292 * @brief specialized converter for int types which accepts also octal and hex notation as input.
293 * @tparam ValueType the type of the result value (which the input should be converted to)
298 struct AutoIntConverter
299 : public std::binary_function< std::string, ValueType&, bool >
302 bool operator () ( const std::string& str, ValueType& v )
304 std::istringstream istr(str);
305 if (has_prefix(str,"0x"))
307 istr.get(); istr.get();
308 istr.setf( std::ios::hex, std::ios::basefield );
310 else if (has_prefix(str,"0") or has_prefix(str,"-0"))
312 istr.setf( std::ios::oct, std::ios::basefield );
316 } // eo operator()(const std::string&,ValueType&)
318 }; // eo struct AutoIntConverter
323 * @brief represents a configuration variable with automatic update.
324 * @tparam ValueType type of the value this variable should hold.
325 * @tparam Converter a converter class which converts a string (from config file) to the desired
327 * Needs to be derived from std::binary_function (taking a string as first arg, a reference to the
328 * desired type as second and returning bool (@a true if conversion was succesful).
330 * Basic idea is to pass a point (section, key) in the config where the value for this
331 * variable is stored. The config value (a string) should be converted to the desired value (type).
332 * When the config is loaded (or reloaded) the var (content) is automatically updated.
334 * @see DefaultConverter
336 * @bug value accessing methods are @a const, but the result type may allow changing the internal value...
340 class Converter = DefaultConverter<
341 typename Detail::extract_type< ValueType >::type
345 : public Detail::OuterSpace<
346 ValueType, Converter,
347 Detail::is_list_container< ValueType >::value >
349 BOOST_STATIC_ASSERT(( boost::is_base_of<
350 std::binary_function<
352 typename boost::add_reference<
353 typename Detail::extract_type< ValueType >::type
356 Converter >::value ));
358 typedef Detail::OuterSpace<
359 ValueType, Converter,
360 Detail::is_list_container< ValueType >::value
365 typedef typename MySpace::result_type result_type;
366 typedef typename MySpace::base_value_type base_value_type;
371 * @brief constructor with config location and initial value.
372 * @param section the section in the config where the value is located in.
373 * @param key the key (in the section) which identifies the value.
374 * @param initial_value the initial value.
376 Var(const std::string& section,
377 const std::string& key,
378 ValueType initial_value)
379 : MySpace(initial_value)
381 FlowerShop= Detail::seymour(
383 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
388 * @brief constructor with config location (key in global section) and initial value.
389 * @param key the key (in the global section) which identifies the value.
390 * @param initial_value the initial value.
392 Var(const std::string& key,
393 ValueType initial_value)
394 : MySpace(initial_value)
396 FlowerShop= Detail::seymour(
398 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
403 * @brief operator for accessing the value.
404 * @return the current value.
406 result_type operator()() const { return MySpace::Value; }
410 * @brief method for accessing the value.
411 * @return the current value.
413 result_type get_value() const { return MySpace::Value; }
417 * @brief copy constructor.
418 * @param other the instance to copy from.
420 Var(const Var& other)
423 FlowerShop= Detail::seymour(
425 typename MySpace::FeedFunctionType( boost::bind( &MySpace::audreyII, this, _1 ) ) );
426 } // eo Var(const Var&)
430 * @brief cast operator for the underlying value type. delivers the value.
431 * @return the current value.
433 * The cast operator allows the instance to be used whereever the underlying value type
436 operator result_type () const { return MySpace::Value; }
441 Detail::FlowerShop FlowerShop;
448 * @brief convenience: \<\< operator which streams the current value of a config var.
454 std::ostream& operator<<(std::ostream& o, const Var< ValueType, Converter >& v)
457 } // eo operator<<(std::ostream&,const Var< ValueType, Converter>&
460 bool set_config_file(const std::string& path);
462 std::string get_config_file();
467 } // eo namespace Config
469 } // eo namespace I2n