Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66972 - in sandbox/configurator: . boost boost/configurator boost/configurator/detail libs libs/configurator libs/configurator/doc libs/configurator/example
From: for.dshevchenko_at_[hidden]
Date: 2010-12-02 08:09:27


Author: dshevchenko
Date: 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
New Revision: 66972
URL: http://svn.boost.org/trac/boost/changeset/66972

Log:
Initial commit of configurator lubrary (version 0.9.3)

Added:
   sandbox/configurator/
   sandbox/configurator/boost/
   sandbox/configurator/boost/configurator/
   sandbox/configurator/boost/configurator/configurator.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/
   sandbox/configurator/boost/configurator/detail/comments_remover.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/incorrect_options_checker.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/misc.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/necessary_options_checker.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/option.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/options_repetition_handler.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/pure_options_obtainer.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/pure_strings_obtainer.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/semantics_checker.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/singleton.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/types.hpp (contents, props changed)
   sandbox/configurator/boost/configurator/detail/validators.hpp (contents, props changed)
   sandbox/configurator/libs/
   sandbox/configurator/libs/configurator/
   sandbox/configurator/libs/configurator/doc/
   sandbox/configurator/libs/configurator/doc/acknowledgments.html (contents, props changed)
   sandbox/configurator/libs/configurator/doc/overview.html (contents, props changed)
   sandbox/configurator/libs/configurator/doc/rationale.html (contents, props changed)
   sandbox/configurator/libs/configurator/example/
   sandbox/configurator/libs/configurator/example/advanced.cpp (contents, props changed)
   sandbox/configurator/libs/configurator/example/advanced_conf.txt (contents, props changed)
   sandbox/configurator/libs/configurator/example/hello_world.cpp (contents, props changed)
   sandbox/configurator/libs/configurator/example/hello_world_conf.txt (contents, props changed)
   sandbox/configurator/libs/configurator/index.html (contents, props changed)

Added: sandbox/configurator/boost/configurator/configurator.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/configurator.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,459 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_HPP
+#define BOOST_CONFIGURATOR_HPP
+
+#include <boost/configurator/detail/option.hpp>
+#include <boost/configurator/detail/validators.hpp>
+#include <boost/configurator/detail/comments_remover.hpp>
+#include <boost/configurator/detail/pure_strings_obtainer.hpp>
+#include <boost/configurator/detail/pure_options_obtainer.hpp>
+#include <boost/configurator/detail/incorrect_options_checker.hpp>
+#include <boost/configurator/detail/necessary_options_checker.hpp>
+#include <boost/configurator/detail/semantics_checker.hpp>
+#include <boost/configurator/detail/options_repetition_handler.hpp>
+
+#ifdef WITH_SINGLETON
+#include <boost/configurator/detail/singleton.hpp>
+#endif
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \class configurator
+/// \brief Configurator.
+///
+/// Core class.
+class configurator : boost::noncopyable {
+public:
+ configurator() :
+ option_name_value_separator( "=" )
+ , sections_separator( "::" )
+ , case_sensitivity_for_names( false )
+ , options_obtainer( option_name_value_separator
+ , sections_separator
+ , unique_names_of_sections
+ , case_sensitivity_for_names )
+ , check_incorrect_options( registered_options, sections_separator )
+ , check_necessary_options( registered_options, sections_separator )
+ , check_options_values_semantics( registered_options, sections_separator )
+ , handle_options_repetition( registered_options, sections_separator )
+ , reparsing( false ) {}
+private:
+ std::string option_name_value_separator;
+ const std::string sections_separator;
+public:
+ void set_name_value_separator( char new_separator ) {
+ check_separator_validity( new_separator );
+ option_name_value_separator = new_separator;
+ }
+private:
+ void check_separator_validity( char new_separator ) const {
+ const int ascii_code = new_separator;
+ if ( ascii_code < 0x20 ) {
+ detail::o_stream what_happened;
+ what_happened << "Symbol (ASCII-code is " << ascii_code
+ << ") is not suitable for name-value separator!"
+ ;
+ notify( what_happened.str() );
+ } else {}
+ }
+private:
+ bool case_sensitivity_for_names;
+public:
+ configurator& set_case_sensitivity_for_names() {
+ case_sensitivity_for_names = true;
+ return *this;
+ }
+public:
+ void use_canonical_one_line_comments() {
+ remove_comments_from.use_canonical_one_line_comments();
+ }
+private:
+ options registered_options;
+ detail::str_set unique_names_of_sections;
+public:
+ configurator& in_section( const std::string& section_name ) {
+ store_unique_section_name( section_name );
+ if ( this_is_begin_call() ) {
+ current_section_path.clear();
+ } else {}
+ current_section_path += section_name + sections_separator;
+ return *this;
+ }
+private:
+ void store_unique_section_name( const std::string& section_name ) {
+ std::string name( section_name.begin(), section_name.end() );
+ convert_name_depending_on_case_sensitivity( name );
+ unique_names_of_sections.insert( name );
+ }
+
+ bool this_is_begin_call() const {
+ return !std::equal( sections_separator.begin()
+ , sections_separator.end()
+ , current_section_path.rbegin() );
+ }
+public:
+ configurator& in( const std::string& section_name ) {
+ return in_section( section_name );
+ }
+
+ configurator& from_section( const std::string& section_name ) {
+ return in_section( section_name );
+ }
+
+ configurator& from( const std::string& section_name ) {
+ return from_section( section_name );
+ }
+public:
+ option& add_option( const std::string& option_name ) {
+ std::string full_name_of_option( option_name.begin(), option_name.end() );
+ convert_name_depending_on_case_sensitivity( full_name_of_option );
+ registered_options.push_back( new option( full_name_of_option, sections_separator ) );
+ return registered_options.back();
+ }
+
+ option& add( const std::string& option_name ) {
+ return add_option( option_name );
+ }
+
+ option& add_option_here( const std::string& option_name ) {
+ cut_current_section_path_if_necessary();
+ std::string full_name_of_option = current_section_path + option_name;
+ convert_name_depending_on_case_sensitivity( full_name_of_option );
+ current_section_path += option_name;
+ registered_options.push_back( new option( full_name_of_option, sections_separator ) );
+ return registered_options.back();
+ }
+
+ option& add_here( const std::string& option_name ) {
+ return add_option_here( option_name );
+ }
+private:
+ void cut_current_section_path_if_necessary() {
+ detail::string_it previous_option_name_begin =
+ boost::find_last( current_section_path, sections_separator ).end();
+ detail::string_it previous_option_name_end = current_section_path.end();
+ current_section_path.erase( previous_option_name_begin, previous_option_name_end );
+ }
+
+ void convert_name_depending_on_case_sensitivity( std::string& full_name_of_option ) const {
+ if ( !case_sensitivity_for_names ) {
+ boost::to_lower( full_name_of_option );
+ } else {}
+ }
+private:
+ // detail::str_storage multiply_sections_names;
+public:
+ configurator& allow_section_multiplicity() {
+ // Not implemented yet, planning...
+ //
+ // std::string section_name( current_section_path.begin(), current_section_path.end() );
+ // convert_name_depending_on_case_sensitivity( section_name );
+ // multiply_sections_names.push_back( section_name );
+ return *this;
+ }
+private:
+ std::string current_section_path;
+ detail::comments_remover remove_comments_from;
+ detail::pure_strings_obtainer obtain_pure_strings;
+ detail::pure_options_obtainer options_obtainer;
+ detail::incorrect_options_checker check_incorrect_options;
+ detail::necessary_options_checker check_necessary_options;
+ detail::semantics_checker check_options_values_semantics;
+ detail::options_repetition_handler handle_options_repetition;
+public:
+ void parse( const std::string& path_to_configuration_file ) {
+ check_registered_options_existence();
+ check_configuration_file_existence( path_to_configuration_file );
+ detail::str_storage obtained_strings = obtain_pure_strings( path_to_configuration_file );
+ check_actual_data_existence( obtained_strings );
+ remove_comments_from( obtained_strings );
+ pure_options factual_obtained_options = options_obtainer( obtained_strings );
+ prepare_names_depending_on_case_sensitivity( factual_obtained_options );
+ check_incorrect_options( factual_obtained_options );
+ check_necessary_options( factual_obtained_options );
+ handle_options_repetition( factual_obtained_options );
+ store_obtained_values( factual_obtained_options );
+ check_options_values_semantics();
+ current_section_path.clear();
+ }
+
+ void load( const std::string& path_to_configuration_file ) {
+ parse( path_to_configuration_file );
+ }
+private:
+ bool reparsing;
+
+ struct reparsing_flag_switch {
+ explicit reparsing_flag_switch( bool& _reparsing ) :
+ reparsing( _reparsing ) {
+ reparsing = true;
+ }
+ ~reparsing_flag_switch() {
+ reparsing = false;
+ }
+ private:
+ bool& reparsing;
+ };
+public:
+ void reparse( const std::string& new_path_to_configuration_file ) {
+ reparsing_flag_switch s( reparsing );
+ parse( new_path_to_configuration_file );
+ }
+
+ void reload( const std::string& new_path_to_configuration_file ) {
+ reparse( new_path_to_configuration_file );
+ }
+
+ void reparse() {
+ reparsing_flag_switch s( reparsing );
+ const std::string previous_path_to_configuration_file = obtain_pure_strings.stored_path();
+ parse( previous_path_to_configuration_file );
+ }
+
+ void reload() {
+ reparse();
+ }
+private:
+ void check_registered_options_existence() const {
+ if ( registered_options.empty() ) {
+ notify( "Cannot parse configuration file, because no one option registered!" );
+ } else {}
+ }
+
+ void check_configuration_file_existence( const std::string& path_to_configuration_file ) const {
+ try {
+ detail::pure_check_path_existence( path_to_configuration_file );
+ } catch ( const std::exception& exc ) {
+ notify( std::string( "Invalid path to configuration file: " ) + exc.what() );
+ }
+ }
+
+ void check_actual_data_existence( detail::str_storage& obtained_strings ) const {
+ if ( at_least_one_option_has_default_value() ) {
+ return;
+ } else {}
+
+ if ( obtained_strings.empty() ) {
+ notify( "No actual data in configuration file, is file empty?" );
+ } else {}
+ }
+
+ bool at_least_one_option_has_default_value() const {
+ option_const_it it = std::find_if( registered_options.begin()
+ , registered_options.end()
+ , boost::mem_fn( &option::already_has_default_value ) );
+ return registered_options.end() != it;
+ }
+
+ void prepare_names_depending_on_case_sensitivity( pure_options& factual_obtained_options ) {
+ if ( !case_sensitivity_for_names ) {
+ BOOST_FOREACH ( option& option, registered_options ) {
+ boost::to_lower( option.name );
+ }
+
+ BOOST_FOREACH ( pure_option& option, factual_obtained_options ) {
+ boost::to_lower( option.name );
+ }
+ } else {}
+ }
+
+ void store_obtained_values( const pure_options& factual_obtained_options ) {
+ BOOST_FOREACH ( const pure_option& option, factual_obtained_options ) {
+ option_it it = std::find( registered_options.begin()
+ , registered_options.end()
+ , option.name );
+ if ( registered_options.end() != it ) {
+ store_if_need( it->value, option.value );
+ } else {}
+ }
+
+ if ( reparsing ) {
+ use_default_value_reserves( factual_obtained_options );
+ } else {}
+ }
+
+ void store_if_need( std::string& value_of_registered_option
+ , const std::string& value_of_obtained_option ) {
+ if ( value_of_obtained_option != value_of_registered_option ) {
+ value_of_registered_option.assign( value_of_obtained_option.begin()
+ , value_of_obtained_option.end() );
+ } else {}
+ }
+
+ void use_default_value_reserves( const pure_options& factual_obtained_options ) {
+ // Not implemented yet.
+ }
+public:
+ std::string get_value( const std::string& name_of_option ) {
+ std::string full_name_of_option( name_of_option.begin(), name_of_option.end() );
+ return get_value_by_name( full_name_of_option );
+ }
+
+ std::string get( const std::string& name_of_option ) {
+ return get_value( name_of_option );
+ }
+public:
+ template< typename ValueType >
+ ValueType get_value( const std::string& name_of_option ) {
+ std::string value_as_string = get_value( name_of_option );
+ ValueType value;
+ try {
+ value = boost::lexical_cast< ValueType >( value_as_string );
+ } catch ( const std::exception& /* exc */ ) {
+ notify( "Value '" + value_as_string + "' of option '" + name_of_option
+ + "' cannot be cast to <" + get_type_identifier< ValueType >() + ">!" );
+ }
+ return value;
+ }
+
+ template< typename ValueType >
+ ValueType get( const std::string& name_of_option ) {
+ return get_value< ValueType >( name_of_option );
+ }
+
+ template< typename ValueType >
+ configurator& get_value( const std::string& name_of_option, ValueType& value ) {
+ value = get_value< ValueType >( name_of_option );
+ return *this;
+ }
+
+ template< typename ValueType >
+ configurator& get( const std::string& name_of_option, ValueType& value ) {
+ return get_value( name_of_option, value );
+ }
+public:
+ std::string get_value_from_here( const std::string& name_of_option ) {
+ cut_current_section_path_if_necessary();
+ std::string full_name_of_option = current_section_path + name_of_option;
+ current_section_path += name_of_option;
+ return get_value_by_name( full_name_of_option );
+ }
+
+ std::string get_from_here( const std::string& name_of_option ) {
+ return get_value_from_here( name_of_option );
+ }
+
+ template< typename ValueType >
+ ValueType get_value_from_here( const std::string& name_of_option ) {
+ std::string value_as_string = get_value_from_here( name_of_option );
+ ValueType value;
+ try {
+ value = boost::lexical_cast< ValueType >( value_as_string );
+ } catch ( const std::exception& /* exc */ ) {
+ const std::string full_name_of_option = current_section_path;
+ notify( "Value '" + value_as_string + "' of option '"
+ + detail::prepare_full_name_for_log( full_name_of_option, sections_separator )
+ + "' cannot be cast to <" + get_type_identifier< ValueType >() + ">!" );
+ }
+ return value;
+ }
+
+ template< typename ValueType >
+ ValueType get_from_here( const std::string& name_of_option ) {
+ return get_value_from_here< ValueType >( name_of_option );
+ }
+
+ template< typename ValueType >
+ configurator& get_value_from_here( const std::string& name_of_option, ValueType& value ) {
+ value = get_value_from_here< ValueType >( name_of_option );
+ return *this;
+ }
+
+ template< typename ValueType >
+ configurator& get_from_here( const std::string& name_of_option, ValueType& value ) {
+ return get_value_from_here( name_of_option, value );
+ }
+private:
+ std::string get_value_by_name( std::string& full_name_of_option ) const {
+ convert_name_depending_on_case_sensitivity( full_name_of_option );
+ option_const_it it = std::find( registered_options.begin()
+ , registered_options.end()
+ , full_name_of_option );
+ std::string value;
+ if ( registered_options.end() != it ) {
+ const std::string& value_of_registered_option = it->value;
+ check_factual_obtaining( value_of_registered_option, full_name_of_option );
+ value.assign( value_of_registered_option.begin(), value_of_registered_option.end() );
+ } else {
+ notify( "You request a value of option '"
+ + detail::prepare_full_name_for_log( full_name_of_option, sections_separator )
+ + "', but such option not registered!" );
+ }
+ return value;
+ }
+
+ void check_factual_obtaining( const std::string& value_of_registered_option
+ , const std::string& full_name_of_option ) const {
+ if ( value_of_registered_option.empty() ) {
+ notify( "You request a value of option '"
+ + detail::prepare_full_name_for_log( full_name_of_option, sections_separator )
+ + "' and such option was registered, but it missed in configuration file!" );
+ } else {}
+ }
+private:
+ template< typename ArgType >
+ std::string get_type_identifier() const {
+ std::string identifier;
+
+ if ( typeid( ArgType ) == typeid( bool ) ) { identifier = "bool"; }
+ else if ( typeid( ArgType ) == typeid( char ) ) { identifier = "char"; }
+ else if ( typeid( ArgType ) == typeid( signed char ) ) { identifier = "signed char"; }
+ else if ( typeid( ArgType ) == typeid( unsigned char ) ) { identifier = "unsigned char"; }
+ else if ( typeid( ArgType ) == typeid( int ) ) { identifier = "int"; }
+ else if ( typeid( ArgType ) == typeid( signed int ) ) { identifier = "signed int"; }
+ else if ( typeid( ArgType ) == typeid( unsigned int ) ) { identifier = "unsigned int"; }
+ else if ( typeid( ArgType ) == typeid( short int ) ) { identifier = "short int"; }
+ else if ( typeid( ArgType ) == typeid( long int ) ) { identifier = "long int"; }
+ else if ( typeid( ArgType ) == typeid( unsigned long int ) ) { identifier = "unsigned long int"; }
+ else if ( typeid( ArgType ) == typeid( unsigned short int ) ) { identifier = "unsigned short int"; }
+ else if ( typeid( ArgType ) == typeid( signed long int ) ) { identifier = "signed long int"; }
+ else if ( typeid( ArgType ) == typeid( signed short int ) ) { identifier = "signed short int"; }
+ else if ( typeid( ArgType ) == typeid( float ) ) { identifier = "float"; }
+ else if ( typeid( ArgType ) == typeid( double ) ) { identifier = "double"; }
+ else if ( typeid( ArgType ) == typeid( long double ) ) { identifier = "long double"; }
+ else if ( typeid( ArgType ) == typeid( std::string ) ) { identifier = "std::string"; }
+ else { identifier = "unknown"; }
+
+ return identifier;
+ }
+};
+
+#ifdef WITH_SINGLETON
+/// \class single_configurator
+/// \brief Singleton-variant of configurator class.
+class single_configurator :
+ public configurator
+ , public detail::singleton< single_configurator > {
+private:
+ single_configurator() {}
+ single_configurator( const single_configurator& another ) {}
+ ~single_configurator() {}
+ single_configurator& operator=( const single_configurator& another ) {
+ return *this;
+ }
+ friend class detail::singleton< single_configurator >;
+public:
+ void parse( const std::string& path_to_configuration_file ) {
+ configurator::parse( path_to_configuration_file );
+ }
+
+ void load( const std::string& path_to_configuration_file ) {
+ configurator::load( path_to_configuration_file );
+ }
+};
+#endif
+
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_HPP

Added: sandbox/configurator/boost/configurator/detail/comments_remover.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/comments_remover.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,141 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_COMMENTS_REMOVER_HPP
+#define BOOST_CONFIGURATOR_COMMENTS_REMOVER_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/foreach.hpp>
+#include <boost/mem_fn.hpp>
+#include <boost/assign.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+using namespace boost::assign;
+
+/// \class comments_remover
+/// \brief Comments remover.
+///
+/// Removes one-line comments and multi-line comments.
+class comments_remover {
+public:
+ comments_remover() :
+ one_line_comment_sign( "//" )
+ , multi_line_comment_begin_sign( "/*" )
+ , multi_line_comment_end_sign( "*/" ) {}
+private:
+ std::string one_line_comment_sign;
+ const std::string multi_line_comment_begin_sign;
+ const std::string multi_line_comment_end_sign;
+public:
+ void use_canonical_one_line_comments() {
+ one_line_comment_sign = "#";
+ }
+public:
+ void operator()( str_storage& obtained_strings ) const {
+ remove_one_line_comments_from( obtained_strings );
+ remove_multi_line_comments_from( obtained_strings );
+ remove_empty_strings_from( obtained_strings );
+ }
+private:
+ void remove_one_line_comments_from( str_storage& obtained_strings ) const {
+ BOOST_FOREACH ( std::string& s, obtained_strings ) {
+ if ( one_line_comment_in_this( s ) ) {
+ remove_one_line_comment_from_this( s );
+ } else {}
+ }
+ }
+
+ bool one_line_comment_in_this( const std::string& s ) const {
+ return boost::contains( s, one_line_comment_sign );
+ }
+
+ void remove_one_line_comment_from_this( std::string& s ) const {
+ s.erase( boost::find_first( s, one_line_comment_sign ).begin()
+ , s.end() );
+ }
+private:
+ void remove_multi_line_comments_from( str_storage& obtained_strings ) const {
+ align_multi_line_comments_in( obtained_strings );
+ remove_aligned_multi_line_comments_from( obtained_strings );
+ }
+
+ void align_multi_line_comments_in( str_storage& obtained_strings ) const {
+ bool waiting_for_comment_closing = false;
+ str_it last_string;
+
+ for ( str_it it = obtained_strings.begin(); obtained_strings.end() != it; ++it ) {
+ std::string& s = *it;
+
+ if ( waiting_for_comment_closing ) {
+ if ( comment_closing_in_this( s ) ) {
+ waiting_for_comment_closing = false;
+ } else {}
+ *last_string += s;
+ s.clear();
+ } else {
+ check_unopened_multi_line_comment( s );
+ string_it begin_of_comment = boost::find_first( s, multi_line_comment_begin_sign ).begin();
+ if ( s.end() != begin_of_comment ) {
+ if ( comment_closing_in_this( s ) ) {
+ remove_multi_line_comment_from_this( s, begin_of_comment );
+ } else {
+ waiting_for_comment_closing = true;
+ last_string = it;
+ }
+ } else {}
+ }
+ }
+
+ check_unclosed_multi_line_comment( waiting_for_comment_closing );
+ }
+
+ bool comment_closing_in_this( const std::string& s ) const {
+ return boost::contains( s, multi_line_comment_end_sign );
+ }
+
+ void remove_aligned_multi_line_comments_from( str_storage& obtained_strings ) const {
+ BOOST_FOREACH ( std::string& s, obtained_strings ) {
+ string_it begin_of_comment = boost::find_first( s, multi_line_comment_begin_sign ).begin();
+ if ( s.end() != begin_of_comment ) {
+ remove_multi_line_comment_from_this( s, begin_of_comment );
+ } else {}
+ }
+ }
+
+ void remove_multi_line_comment_from_this( std::string& s, string_it begin_of_comment ) const {
+ s.erase( begin_of_comment
+ , boost::find_first( s, multi_line_comment_end_sign ).end() );
+ }
+
+ void check_unopened_multi_line_comment( const std::string& s ) const {
+ if ( !boost::contains( s, multi_line_comment_begin_sign )
+ && boost::contains( s, multi_line_comment_end_sign ) ) {
+ notify( "Unopened multi-line comment detected in string '" + s + "'!" );
+ } else {}
+ }
+
+ void check_unclosed_multi_line_comment( bool waiting_for_comment_closing ) const {
+ if ( waiting_for_comment_closing ) {
+ notify( "Unclosed multi-line comment detected!" );
+ } else {}
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_COMMENTS_REMOVER_HPP

Added: sandbox/configurator/boost/configurator/detail/incorrect_options_checker.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/incorrect_options_checker.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,77 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_INCORRECT_OPTIONS_CHECKER_HPP
+#define BOOST_CONFIGURATOR_INCORRECT_OPTIONS_CHECKER_HPP
+
+#include <boost/configurator/detail/option.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class incorrect_options_checker
+/// \brief Incorrect options checker.
+///
+/// Checks existence of incorrect (unregistered) options.
+class incorrect_options_checker {
+public:
+ incorrect_options_checker( const options& _registered_options
+ , const std::string& _sections_separator ) :
+ registered_options( _registered_options )
+ , sections_separator( _sections_separator ) {}
+private:
+ const options& registered_options;
+ const std::string& sections_separator;
+public:
+ void operator()( const pure_options& factual_obtained_options ) {
+ BOOST_FOREACH ( const pure_option& option, factual_obtained_options ) {
+ option_const_it it = std::find( registered_options.begin()
+ , registered_options.end()
+ , option.name );
+ if ( registered_options.end() == it ) {
+ store_incorrect_option( option.name );
+ } else {}
+ }
+
+ notify_about_incorrect_options_if_such_exists();
+ }
+private:
+ str_storage incorrect_options;
+private:
+ void store_incorrect_option( const std::string& option_name ) {
+ incorrect_options += option_name;
+ }
+
+ void notify_about_incorrect_options_if_such_exists() const {
+ if ( incorrect_options.empty() ) {
+ return;
+ } else {}
+
+ std::string what_happened = "Incorrect option detected in configuration file:\n";
+ if ( incorrect_options.size() > 1 ) {
+ boost::replace_all( what_happened, "option", "options" );
+ } else {}
+ BOOST_FOREACH ( const std::string& option, incorrect_options ) {
+ what_happened += "'" + prepare_full_name_for_log( option, sections_separator ) + "'\n";
+ }
+ boost::erase_last( what_happened, "\n" );
+ notify( what_happened );
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_INCORRECT_OPTIONS_CHECKER_HPP

Added: sandbox/configurator/boost/configurator/detail/misc.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/misc.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,106 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_MISC_HPP
+#define BOOST_CONFIGURATOR_MISC_HPP
+
+#include <boost/configurator/detail/types.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem/operations.hpp>
+
+#include <iostream>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+inline void notify( const std::string& notification ) {
+ const std::string what_happened = "[Configurator] " + notification;
+ throw std::runtime_error( what_happened );
+}
+
+inline void warning( const std::string& warning_message ) {
+ std::cout << "[Configurator] " << warning_message << std::endl;
+}
+
+/// \enum value_semantic
+/// \brief Value semantic types (for check).
+enum value_semantic {
+ no_semantic /*!< Default value. */
+ , path /*!< Path semantics check. */
+ , optional_path /*!< Optional path semantics check. */
+ , ipv4 /*!< IPv4 semantics check. */
+ , ipv6 /*!< IPv6 semantics check. */
+ , ip /*!< IP semantics check. */
+ , email /*!< E-mail semantics check. */
+ , size /*!< Size semantics check. */
+ , time_period /*!< Time period semantics check. */
+ , exp_record /*!< Exponential record semantics check. */
+};
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+inline std::string sections_separator_for_log() { return " > "; }
+
+template
+<
+ typename STLContainer
+ , typename Element
+>
+inline void delete_element( STLContainer& cont, const Element& element ) {
+ cont.erase( std::remove( cont.begin(), cont.end(), element )
+ , cont.end() );
+}
+
+inline void notify_without_prefix( const std::string& notification ) {
+ throw std::runtime_error( notification );
+}
+
+inline void pure_check_path_existence( const std::string& _path ) {
+ boost::filesystem::path path( _path );
+
+ const std::string full_path_name = path.string();
+ const std::string path_name = path.parent_path().string();
+ const std::string file_name = path.filename();
+
+ if ( boost::filesystem::exists( path_name ) ) {
+ if ( !boost::filesystem::exists( full_path_name ) ) {
+ notify_without_prefix( "directory '" + path_name + "' exists, but there is no file '" + file_name + "'!" );
+ } else {}
+ } else {
+ notify_without_prefix( "directory '" + path_name + "' not exists!" );
+ }
+}
+
+inline std::string prepare_full_name_for_log( const std::string& full_name_of_option
+ , const std::string& sections_separator ) {
+ std::string s( full_name_of_option.begin(), full_name_of_option.end() );
+ boost::replace_all( s, sections_separator, sections_separator_for_log() );
+ string_const_it last_separator_end = boost::find_last( s, sections_separator_for_log() ).end();
+ if ( s.end() == last_separator_end ) {
+ boost::erase_last( s, sections_separator_for_log() );
+ } else {}
+ return s;
+}
+
+inline void remove_empty_strings_from( str_storage& strings ) {
+ strings.erase( std::remove_if( strings.begin()
+ , strings.end()
+ , boost::mem_fn( &std::string::empty ) )
+ , strings.end() );
+}
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_MISC_HPP

Added: sandbox/configurator/boost/configurator/detail/necessary_options_checker.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/necessary_options_checker.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,85 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_NECESSARY_OPTIONS_CHECKER_HPP
+#define BOOST_CONFIGURATOR_NECESSARY_OPTIONS_CHECKER_HPP
+
+#include <boost/configurator/detail/option.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class necessary_options_checker
+/// \brief Necessary options checker.
+///
+/// Checks existence of all options defined as necessary.
+class necessary_options_checker {
+public:
+ necessary_options_checker( const options& _registered_options
+ , const std::string& _sections_separator ) :
+ registered_options( _registered_options )
+ , sections_separator( _sections_separator ) {}
+private:
+ const options& registered_options;
+ const std::string& sections_separator;
+public:
+ void operator()( const pure_options& factual_obtained_options ) const {
+ str_storage names_that_should_be = collect_names_of_necessary_options();
+ remove_names_of_inputed_necessary_options( factual_obtained_options, names_that_should_be );
+ if ( !names_that_should_be.empty() ) {
+ notify_about_missing_of_necessary_options( names_that_should_be );
+ } else {}
+ }
+private:
+ str_storage collect_names_of_necessary_options() const {
+ str_storage names;
+ BOOST_FOREACH ( const option& registered_option, registered_options ) {
+ if ( registered_option.is_necessary ) {
+ names += registered_option.name;
+ } else {}
+ }
+ return names;
+ }
+
+ void remove_names_of_inputed_necessary_options( const pure_options& factual_obtained_options
+ , str_storage& names_that_should_be ) const {
+ BOOST_FOREACH ( const pure_option& obtained_option, factual_obtained_options ) {
+ delete_element( names_that_should_be, obtained_option.name );
+ }
+ }
+
+ void notify_about_missing_of_necessary_options( const str_storage& names_that_should_be ) const {
+ std::string what_happened = "Option ";
+
+ BOOST_FOREACH ( const std::string& name, names_that_should_be ) {
+ what_happened += "'" + prepare_full_name_for_log( name, sections_separator ) + "', ";
+ }
+ boost::erase_last( what_happened, ", " );
+
+ if ( 1 == names_that_should_be.size() ) {
+ what_happened += " is defined as necessary, but it missed!";
+ } else {
+ boost::replace_first( what_happened, "Option", "Options" );
+ what_happened += " are defined as necessary, but they missed!";
+ }
+
+ notify( what_happened );
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_NECESSARY_OPTIONS_CHECKER_HPP

Added: sandbox/configurator/boost/configurator/detail/option.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/option.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,173 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_OPTION_HPP
+#define BOOST_CONFIGURATOR_OPTION_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class option
+/// \brief One option.
+///
+/// Presents functionality of one configuration option.
+class option {
+public:
+ explicit option( const std::string& _name, const std::string& _sections_separator ) :
+ sections_separator( _sections_separator )
+ , name( _name.begin(), _name.end() )
+ , value()
+ , semantic( no_semantic )
+ , is_necessary( false )
+ , multi_values_allowed( false ) {}
+private:
+ const std::string& sections_separator;
+public:
+ std::string name;
+ std::string value;
+ value_semantic semantic;
+ bool is_necessary;
+ bool multi_values_allowed;
+public:
+ bool operator==( const std::string& full_name ) const {
+ return full_name == name;
+ }
+private:
+ std::string default_value_reserve;
+public:
+ void use_default_value_reserve() {
+ if ( !default_value_reserve.empty() ) {
+ value.assign( default_value_reserve.begin(), default_value_reserve.end() );
+ } else {}
+ }
+public:
+ template< typename ValueType >
+ option& default_value( const ValueType& _value ) {
+ check_option_necessity();
+ try {
+ value = boost::lexical_cast< std::string >( _value );
+ default_value_reserve.assign( value.begin(), value.end() );
+ } catch ( const std::exception& /* exc */ ) {
+ notify( "Default value for option '" + name + "' cannot be stringified!" );
+ }
+ return *this;
+ }
+private:
+ void check_option_necessity() const {
+ if ( is_necessary ) {
+ notify( "Option '"
+ + prepare_full_name_for_log( name, sections_separator )
+ + "' registered as necessary, so it cannot have default_value!" );
+ } else {}
+ }
+public:
+ option& default_value( const std::string& _value ) {
+ value.assign( _value.begin(), _value.end() );
+ return *this;
+ }
+public:
+ option& necessary() {
+ check_default_value_existence();
+ is_necessary = true;
+ return *this;
+ }
+private:
+ void check_default_value_existence() const {
+ if ( !value.empty() ) {
+ notify( "Option '"
+ + prepare_full_name_for_log( name, sections_separator )
+ + "' already have default value '" + value + "', "
+ + "so it cannot be necessary!" );
+ } else {}
+ }
+public:
+ option& check_semantic( const value_semantic& _semantic ) {
+ check_correctness_of( _semantic );
+ semantic = _semantic;
+ return *this;
+ }
+private:
+ void check_correctness_of( const value_semantic& semantic ) const {
+ if ( semantic < no_semantic || semantic > exp_record ) {
+ o_stream what_happened;
+ what_happened << "invalid semantic value '" << semantic
+ << "', use supported semantic only (see documentation)!"
+ ;
+ notify( what_happened.str() );
+ } else {}
+ }
+public:
+ bool semantic_defined() const {
+ return no_semantic != semantic;
+ }
+public:
+ option& allow_multi_values() {
+ multi_values_allowed = true;
+ return *this;
+ }
+public:
+ bool already_has_default_value() const { return !value.empty(); }
+ bool it_is_necessary() const { return is_necessary; }
+ bool empty() const { return value.empty(); }
+};
+
+/// \struct pure_option
+/// \brief
+///
+/// Presents pure option obtained from configuration file.
+struct pure_option {
+ pure_option() {}
+ pure_option( const std::string& _name, const std::string& _value ) :
+ name( _name.begin(), _name.end() )
+ , value( _value.begin(), _value.end() ) {}
+public:
+ std::string name;
+ std::string value;
+public:
+ bool empty() const {
+ return value.empty();
+ }
+
+ bool operator==( const std::string& _name ) const {
+ return _name == name;
+ }
+
+ bool operator==( const pure_option& another ) const {
+ return another.name == name;
+ }
+};
+
+inline bool operator<( const pure_option& left, const pure_option& right ) {
+ return left.name < right.name;
+}
+
+} // namespace detail
+
+typedef detail::option option;
+
+typedef boost::ptr_vector< option > options;
+typedef options::iterator option_it;
+typedef options::const_iterator option_const_it;
+
+typedef detail::pure_option pure_option;
+typedef std::vector< pure_option > pure_options;
+typedef pure_options::iterator pure_option_it;
+
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_OPTION_HPP

Added: sandbox/configurator/boost/configurator/detail/options_repetition_handler.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/options_repetition_handler.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,117 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_OPTIONS_REPETITION_HANDLER_HPP
+#define BOOST_CONFIGURATOR_OPTIONS_REPETITION_HANDLER_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+namespace fs = boost::filesystem;
+
+/// \class options_repetition_handler
+/// \brief Options repetition handler.
+///
+/// Handle repetition of factual obtained option,
+/// with corresponding checks.
+class options_repetition_handler {
+public:
+ options_repetition_handler( const options& _registered_options
+ , const std::string& _sections_separator ) :
+ registered_options( _registered_options )
+ , sections_separator( _sections_separator ) {}
+private:
+ const options& registered_options;
+ const std::string& sections_separator;
+public:
+ void operator()( pure_options& factual_obtained_options ) const {
+ std::sort( factual_obtained_options.begin(), factual_obtained_options.end() );
+ pure_options unique_options = retrieve_unique_options_from( factual_obtained_options );
+
+ if ( no_repetition( unique_options, factual_obtained_options ) ) {
+ return;
+ } else {}
+
+ BOOST_FOREACH ( const pure_option& unique_option, unique_options ) {
+ pure_option_it first_repeating = std::find( factual_obtained_options.begin()
+ , factual_obtained_options.end()
+ , unique_option.name );
+ if ( factual_obtained_options.end() != first_repeating ) {
+ size_t how_many_times_it_repeats = (size_t)std::count( factual_obtained_options.begin()
+ , factual_obtained_options.end()
+ , unique_option.name );
+ if ( 1 == how_many_times_it_repeats ) {
+ continue;
+ } else {}
+
+ check_multi_values_allowance( *first_repeating );
+
+ std::string values_buffer;
+
+ for ( pure_option_it it = first_repeating;
+ it != first_repeating + how_many_times_it_repeats;
+ ++it ) {
+ values_buffer += it->value + " ";
+ it->value.clear();
+ }
+
+ first_repeating->value = values_buffer;
+ } else {}
+ }
+
+ remove_empty_options_from( factual_obtained_options );
+ }
+private:
+ pure_options retrieve_unique_options_from( const pure_options& factual_obtained_options ) const {
+ pure_options unique_options( factual_obtained_options.size() );
+ pure_option_it repeating_end = std::unique_copy( factual_obtained_options.begin()
+ , factual_obtained_options.end()
+ , unique_options.begin() );
+ unique_options.erase( repeating_end, unique_options.end() );
+ return unique_options;
+ }
+
+ bool no_repetition( const pure_options& unique_options, const pure_options& factual_obtained_options ) const {
+ return unique_options.size() == factual_obtained_options.size();
+ }
+
+ void check_multi_values_allowance( const pure_option& factual_obtained_option ) const {
+ option_const_it it = std::find( registered_options.begin()
+ , registered_options.end()
+ , factual_obtained_option.name );
+ if ( registered_options.end() != it ) {
+ if ( !it->multi_values_allowed ) {
+ notify( "Option '" + prepare_full_name_for_log( factual_obtained_option.name
+ , sections_separator )
+ + "' has multiple values, but it not allowed to have multiply values!" );
+ } else {}
+ } else {}
+ }
+
+ void remove_empty_options_from( pure_options& factual_obtained_options ) const {
+ factual_obtained_options.erase( std::remove_if( factual_obtained_options.begin()
+ , factual_obtained_options.end()
+ , boost::mem_fn( &pure_option::empty ) )
+ , factual_obtained_options.end() );
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_OPTIONS_REPETITION_HANDLER_HPP

Added: sandbox/configurator/boost/configurator/detail/pure_options_obtainer.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/pure_options_obtainer.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,305 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_PURE_OPTIONS_OBTAINER_HPP
+#define BOOST_CONFIGURATOR_PURE_OPTIONS_OBTAINER_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/configurator/detail/option.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class pure_options_obtainer
+/// \brief Pure options obtainer.
+///
+/// Obtains pure options from pure strings.
+/// Checks sections correctness.
+class pure_options_obtainer {
+public:
+ pure_options_obtainer( std::string& _option_name_value_separator
+ , const std::string& _sections_separator
+ , const str_set& _unique_names_of_sections
+ , const bool& _case_sensitivity_for_names ) :
+ option_name_value_separator( _option_name_value_separator )
+ , sections_separator( _sections_separator )
+ , unique_names_of_sections( _unique_names_of_sections )
+ , case_sensitivity_for_names( _case_sensitivity_for_names )
+ , open_section_tag_begin_sign( "<" )
+ , open_section_tag_end_sign( ">" )
+ , close_section_tag_begin_sign( "</" )
+ , close_section_tag_end_sign( ">" ) {}
+private:
+ std::string& option_name_value_separator;
+ const std::string& sections_separator;
+ const str_set& unique_names_of_sections;
+ const bool& case_sensitivity_for_names;
+ const std::string open_section_tag_begin_sign;
+ const std::string open_section_tag_end_sign;
+ const std::string close_section_tag_begin_sign;
+ const std::string close_section_tag_end_sign;
+ std::string current_section_path;
+ str_set nonmulti_sections_uniqueness_checker;
+public:
+ pure_options operator()( const str_storage& obtained_strings ) {
+ pure_options factual_obtained_options;
+ BOOST_FOREACH ( const std::string& s, obtained_strings ) {
+ if ( option_exists_in_this( s ) ) {
+ obtain_option( s, factual_obtained_options );
+ } else if ( open_section_tag_exists_in_this( s ) ) {
+ handle_opening_of_section( s );
+ } else if ( close_section_tag_exists_in_this( s ) ) {
+ handle_closing_of_section( s );
+ } else {
+ notify_about_meaningless_string( s );
+ }
+ }
+ check_last_section_closing();
+ nonmulti_sections_uniqueness_checker.clear();
+ return factual_obtained_options;
+ }
+private:
+ bool open_section_tag_exists_in_this( const std::string& s ) const {
+ return boost::contains( s, open_section_tag_begin_sign )
+ && boost::contains( s, open_section_tag_end_sign )
+ && !boost::contains( s, close_section_tag_begin_sign );
+ }
+
+ bool close_section_tag_exists_in_this( const std::string& s ) const {
+ return boost::contains( s, close_section_tag_begin_sign )
+ && boost::contains( s, close_section_tag_end_sign );
+ }
+
+ bool option_exists_in_this( const std::string& s ) const {
+ char separator = *option_name_value_separator.begin();
+ bool extended_predicat = false;
+ if ( ' ' == separator ) {
+ // In this case allowed tabulations as name-value separator.
+ extended_predicat = boost::contains( s, "\t" );
+ } else {}
+ return boost::contains( s, option_name_value_separator )
+ || extended_predicat ;
+ }
+private:
+ void obtain_option( const std::string& s, pure_options& factual_obtained_options ) const {
+ str_storage option_parts = get_option_parts_from( s );
+ check_separator_repetition_in( option_parts );
+ check_parts_quantity_if_use_space_separator( option_parts );
+ std::string name = option_parts.front();
+ std::string value = option_parts.back();
+ boost::trim( name );
+ boost::trim( value );
+ check_option_validity( name, value );
+ const std::string full_name_of_option = current_section_path + name;
+ factual_obtained_options += pure_option( full_name_of_option, value );
+ }
+
+ str_storage get_option_parts_from( const std::string& s ) const {
+ str_storage option_parts;
+ std::string s_for_replacing( s.begin(), s.end() );
+ const char separator = *option_name_value_separator.begin();
+ if ( ' ' == separator ) {
+ // In this case allowed tabulations as name-value separator.
+ boost::replace_all( s_for_replacing, "\t", " " );
+ } else {}
+ boost::split( option_parts, s_for_replacing, boost::is_any_of( option_name_value_separator ) );
+ remove_empty_strings_from( option_parts );
+ return option_parts;
+ }
+
+ void check_parts_quantity_if_use_space_separator( const str_storage& option_parts ) const {
+ const char separator = *option_name_value_separator.begin();
+ if ( ' ' == separator && option_parts.size() > 2 ) {
+ o_stream what_happened;
+ what_happened << "in section '"
+ << prepare_full_name_for_log( current_section_path, sections_separator )
+ << "' detected option (name '" + option_parts[0] << "') "
+ << "with spaces repetition, "
+ << "but you using space symbol as name-value separator, it's incorrect!"
+ ;
+ notify( what_happened.str() );
+ } else {}
+ }
+
+ void check_separator_repetition_in( const str_storage& option_parts ) const {
+ if ( 2 != option_parts.size() ) {
+ const char separator = *option_name_value_separator.begin();
+ if ( ' ' == separator ) {
+ // If separator is space symbol - allows it repetition.
+ return;
+ } else {}
+
+ notify( "Near option '"
+ + option_parts.front()
+ + "' repetition of name-value separator '"
+ + option_name_value_separator
+ + "' detected!" );
+ } else {}
+ }
+
+ void check_option_validity( const std::string& name, const std::string& value ) const {
+ if ( name.empty() ) {
+ notify( "Some option in section '"
+ + prepare_full_name_for_log( current_section_path, sections_separator )
+ + "' have not name!" );
+ } else {}
+
+ if ( value.empty() ) {
+ notify( "Option '"
+ + prepare_full_name_for_log( current_section_path + name, sections_separator )
+ + "' have not value!" );
+ } else {}
+ }
+private:
+ void handle_opening_of_section( const std::string& s ) {
+ std::string opening_section_name = retrieve_section_name_from_open_tag( s );
+ convert_name_depending_on_case_sensitivity( opening_section_name );
+ check_duplication_of( opening_section_name );
+ current_section_path += opening_section_name + sections_separator;
+ check_nonmulti_sections_uniqueness();
+ }
+
+ void handle_closing_of_section( const std::string& s ) {
+ std::string closing_section_name = retrieve_section_name_from_close_tag( s );
+ convert_name_depending_on_case_sensitivity( closing_section_name );
+ check_is_any_section_was_opened( closing_section_name );
+ check_section_symmetry( closing_section_name );
+ cut_current_section_name_by( closing_section_name );
+ }
+
+ void check_duplication_of( const std::string& opening_section_name ) {
+ const std::string name_of_last_opening_section = retrieve_name_of_last_opening_section();
+ if ( opening_section_name == name_of_last_opening_section ) {
+ notify( "Duplication of open tag for section '"
+ + prepare_full_name_for_log( current_section_path, sections_separator )
+ + "' detected!" );
+ } else {}
+ }
+private:
+ void check_section_symmetry( const std::string& closing_section_name ) const {
+ const std::string name_of_last_opening_section = retrieve_name_of_last_opening_section();
+ if ( closing_section_name != name_of_last_opening_section ) {
+ notify( "Dissymmetry of sections detected: last opening section '"
+ + name_of_last_opening_section + "', but closing is '" + closing_section_name + "'!" );
+ } else {}
+ }
+
+ std::string retrieve_name_of_last_opening_section() const {
+ string_const_it name_end = boost::find_last( current_section_path, sections_separator ).begin();
+ string_const_it name_begin;
+ string_const_it checker = std::search( current_section_path.begin()
+ , name_end
+ , sections_separator.begin()
+ , sections_separator.end() );
+ if ( name_end != checker ) {
+ name_begin = boost::find_nth( current_section_path, sections_separator, -2 ).end();
+ } else {
+ name_begin = current_section_path.begin();
+ }
+ return std::string( name_begin, name_end );
+ }
+
+ void check_nonmulti_sections_uniqueness() {
+ const size_t current_nonmulti_sections_quantity = nonmulti_sections_uniqueness_checker.size();
+ nonmulti_sections_uniqueness_checker.insert( current_section_path );
+ const size_t new_nonmulti_sections_quantity = nonmulti_sections_uniqueness_checker.size();
+ if ( current_nonmulti_sections_quantity == new_nonmulti_sections_quantity ) {
+ notify( "Section '"
+ + prepare_full_name_for_log( current_section_path, sections_separator )
+ + "' repeats, but it no allowed repeating!" );
+ } else {}
+ }
+private:
+ std::string retrieve_section_name_from_open_tag( const std::string& s ) const {
+ string_const_it section_name_begin = boost::find_first( s, open_section_tag_begin_sign ).end();
+ string_const_it section_name_end = boost::find_first( s, open_section_tag_end_sign ).begin();
+ std::string section_name( section_name_begin, section_name_end );
+ boost::trim( section_name );
+ check_section_existence( section_name );
+ return section_name;
+ }
+
+ std::string retrieve_section_name_from_close_tag( const std::string& s ) const {
+ string_const_it section_name_begin = boost::find_first( s, close_section_tag_begin_sign ).end();
+ string_const_it section_name_end = boost::find_first( s, close_section_tag_end_sign ).begin();
+ std::string section_name( section_name_begin, section_name_end );
+ boost::trim( section_name );
+ check_section_existence( section_name );
+ return section_name;
+ }
+private:
+ void cut_current_section_name_by( const std::string& closing_section_name ) {
+ boost::erase_last( current_section_path, closing_section_name + sections_separator );
+ }
+private:
+ void check_is_any_section_was_opened( const std::string& closing_section_name ) const {
+ if ( current_section_path.empty() ) {
+ notify( "Closing of section '" + closing_section_name + "' detected, "
+ + "but this section was not opened!" );
+ } else {}
+ }
+
+ void check_last_section_closing() {
+ if ( !current_section_path.empty() ) {
+ boost::erase_last( current_section_path, sections_separator );
+ notify( "Section '" + current_section_path + "' unclosed!" );
+ } else {}
+ }
+
+ void check_section_existence( std::string& section_name ) const {
+ convert_name_depending_on_case_sensitivity( section_name );
+ str_unique_const_it it = unique_names_of_sections.find( section_name );
+ if ( unique_names_of_sections.end() == it ) {
+ notify_about_incorrect_section_name( section_name );
+ } else {}
+ }
+
+ void notify_about_incorrect_section_name( const std::string& incorrect_section_name ) const {
+ std::string what_happened = "Incorrect section name '"
+ + incorrect_section_name
+ + "' detected!";
+ if ( !current_section_path.empty() ) {
+ boost::erase_last( what_happened, "!" );
+ what_happened += " in section '"
+ + prepare_full_name_for_log( current_section_path, sections_separator )
+ + "'!"
+ ;
+ } else {}
+ notify( what_happened );
+ }
+
+ void convert_name_depending_on_case_sensitivity( std::string& section_name ) const {
+ if ( !case_sensitivity_for_names ) {
+ boost::to_lower( section_name );
+ } else {}
+ }
+private:
+ void notify_about_meaningless_string( const std::string& s ) const {
+ std::string what_happened = "in global scope";
+ if ( !current_section_path.empty() ) {
+ what_happened = "in section '"
+ + prepare_full_name_for_log( current_section_path, sections_separator )
+ + "'"
+ ;
+ } else {}
+ what_happened = "Meaningless string '" + s + "' detected " + what_happened + "!";
+ notify( what_happened );
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_PURE_OPTIONS_OBTAINER_HPP

Added: sandbox/configurator/boost/configurator/detail/pure_strings_obtainer.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/pure_strings_obtainer.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,74 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_PURE_STRINGS_OBTAINER_HPP
+#define BOOST_CONFIGURATOR_PURE_STRINGS_OBTAINER_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+namespace fs = boost::filesystem;
+
+/// \class pure_strings_obtainer
+/// \brief Configuration's file strings obtainer.
+///
+/// Obtains pure strings from configuration file.
+class pure_strings_obtainer {
+private:
+ fs::path path_to_configuration_file;
+public:
+ str_storage operator()( const std::string& _path_to_configuration_file ) {
+ path_to_configuration_file = _path_to_configuration_file;
+ return obtained_strings();
+ }
+
+ std::string stored_path() const {
+ return path_to_configuration_file.string();
+ }
+private:
+ str_storage obtained_strings() const {
+ fs::ifstream configuration_file;
+ open_file( configuration_file );
+ return obtained_strings_from( configuration_file );
+ }
+
+ void open_file( fs::ifstream& configuration_file ) const {
+ configuration_file.open( path_to_configuration_file );
+ if ( !configuration_file.good() ) {
+ notify( "Cannot open configuration file '" + path_to_configuration_file.string()
+ + "', probably you have not permissions..." );
+ } else {}
+ }
+
+ str_storage obtained_strings_from( fs::ifstream& configuration_file ) const {
+ str_storage strings;
+ std::string s;
+ while ( std::getline( configuration_file, s ) ) {
+ boost::trim( s );
+ if ( !s.empty() ) {
+ strings += s;
+ } else {}
+ }
+ return strings;
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_PURE_STRINGS_OBTAINER_HPP

Added: sandbox/configurator/boost/configurator/detail/semantics_checker.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/semantics_checker.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,109 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_SEMANTICS_CHECKER_HPP
+#define BOOST_CONFIGURATOR_SEMANTICS_CHECKER_HPP
+
+#include <boost/configurator/detail/option.hpp>
+#ifdef WITH_SEMANTIC_CHECK
+#include <boost/configurator/detail/validators.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+
+#include <map>
+#endif
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class semantics_checker
+/// \brief Semantics checker.
+///
+/// Checks semantics of option's values, if it defined.
+class semantics_checker {
+ #ifdef WITH_SEMANTIC_CHECK
+ typedef boost::function< void ( const std::string& /* arg */
+ , const std::string& /* option name */ ) >
+ check_func;
+
+ typedef std::map
+ <
+ const value_semantic
+ , const check_func
+ >
+ checkers;
+ #endif
+public:
+ semantics_checker( options& _registered_options
+ , const std::string& _sections_separator )
+ #ifdef WITH_SEMANTIC_CHECK
+ : registered_options( _registered_options )
+ , sections_separator( _sections_separator )
+ , check_size_validity( registered_options, sections_separator )
+ , check_time_period_validity( registered_options, sections_separator )
+ , check_exp_record_validity( registered_options, sections_separator )
+ #endif
+ {
+ #ifdef WITH_SEMANTIC_CHECK
+ insert( semantic_checkers )( path, check_path_existence )
+ ( optional_path, check_optional_path_existence )
+ ( ipv4, check_ipv4_validity )
+ ( ipv6, check_ipv6_validity )
+ ( ip, check_ip_validity )
+ ( email, check_email_validity )
+ ( size, boost::bind( &size_validator::check
+ , &check_size_validity
+ , _1
+ , _2 ) )
+ ( time_period, boost::bind( &time_period_validator::check
+ , &check_time_period_validity
+ , _1
+ , _2 ) )
+ ( exp_record, boost::bind( &exp_record_validator::check
+ , &check_exp_record_validity
+ , _1
+ , _2 ) )
+ ;
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ options& registered_options;
+ const std::string& sections_separator;
+ size_validator check_size_validity;
+ time_period_validator check_time_period_validity;
+ exp_record_validator check_exp_record_validity;
+ checkers semantic_checkers;
+#endif
+public:
+ void operator()() {
+ #ifdef WITH_SEMANTIC_CHECK
+ BOOST_FOREACH ( option& registered_option, registered_options ) {
+ if ( !registered_options.empty()
+ && registered_option.semantic_defined() ) {
+ const std::string& value = registered_option.value;
+ const std::string name = prepare_full_name_for_log( registered_option.name
+ , sections_separator );
+ semantic_checkers[ registered_option.semantic ]( value, name );
+ } else {}
+ }
+ #endif
+ }
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_SEMANTICS_CHECKER_HPP

Added: sandbox/configurator/boost/configurator/detail/singleton.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/singleton.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,63 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_SINGLETON_HPP
+#define BOOST_CONFIGURATOR_SINGLETON_HPP
+
+#include <boost/thread.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <cstdlib>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \class singleton
+/// \brief Realization of 'Singleton' pattern.
+template< typename T >
+class singleton : boost::noncopyable {
+public:
+ static boost::mutex mutex;
+private:
+ static T* t;
+public:
+ static T& inst() {
+ if ( 0 == t ) {
+ boost::mutex::scoped_lock lock( mutex );
+ if ( 0 == t ) {
+ t = new T();
+ ::atexit( destroy );
+ } else {}
+ } else {}
+ return *t;
+ }
+private:
+ static void destroy() {
+ boost::mutex::scoped_lock lock( mutex );
+ delete t;
+ t = 0;
+ }
+};
+
+template< typename T >
+boost::mutex singleton< T >::mutex;
+
+template< typename T >
+T* singleton< T >::t = 0;
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_SINGLETON_HPP

Added: sandbox/configurator/boost/configurator/detail/types.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/types.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,43 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_TYPES_HPP
+#define BOOST_CONFIGURATOR_TYPES_HPP
+
+#include <vector>
+#include <set>
+#include <sstream>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+typedef std::string::iterator string_it;
+typedef std::string::const_iterator string_const_it;
+
+typedef std::vector< std::string > str_storage;
+typedef str_storage::iterator str_it;
+typedef str_storage::const_iterator str_const_it;
+typedef std::vector< str_it > iterators_to_strings;
+
+typedef std::set< std::string > str_set;
+typedef str_set::iterator str_unique_it;
+typedef str_set::const_iterator str_unique_const_it;
+
+typedef std::ostringstream o_stream;
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_TYPES_HPP

Added: sandbox/configurator/boost/configurator/detail/validators.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/validators.hpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,492 @@
+// Configurator (C++ library for configuration file parsing)
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_CONFIGURATOR_VALIDATORS_HPP
+#define BOOST_CONFIGURATOR_VALIDATORS_HPP
+
+#include <boost/configurator/detail/misc.hpp>
+#include <boost/configurator/detail/option.hpp>
+
+#ifdef WITH_SEMANTIC_CHECK
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/asio/ip/address_v6.hpp>
+#include <boost/regex.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+#include <boost/foreach.hpp>
+
+#include <cmath>
+#endif
+
+#include <boost/assign.hpp>
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+using namespace boost::assign;
+
+inline std::string semantic_error_prefix() { return "Semantic error: "; }
+
+inline void check_ipv4_validity( const std::string& address, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ try {
+ boost::asio::ip::address_v4 a( boost::asio::ip::address_v4::from_string( address ) );
+ } catch ( const std::exception& /* exc */ ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name + "' has invalid 'IPv4' value '" + address + "'!" );
+ }
+ #endif
+}
+
+inline void check_ipv6_validity( const std::string& address, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ try {
+ boost::asio::ip::address_v6 a( boost::asio::ip::address_v6::from_string( address ) );
+ } catch ( const std::exception& /* exc */ ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name + "' has invalid 'IPv6' value '" + address + "'!" );
+ }
+ #endif
+}
+
+inline void check_ip_validity( const std::string& address, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ try {
+ check_ipv4_validity( address, option_name );
+ } catch ( const std::exception& /* exc */ ) {
+ try {
+ check_ipv6_validity( address, option_name );
+ } catch ( const std::exception& /* exc */ ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name + "' has invalid value '" + address + "' (not IPv4, not IPv6)!" );
+ }
+ }
+ #endif
+}
+
+inline void check_path_existence( const std::string& path, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ try {
+ pure_check_path_existence( path );
+ } catch ( const std::exception& exc ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name + "' has invalid value '" + path + "': " + exc.what() );
+ }
+ #endif
+}
+
+inline void check_optional_path_existence( const std::string& path, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ try {
+ pure_check_path_existence( path );
+ } catch ( const std::exception& exc ) {
+ warning( "Warning: option '" + option_name
+ + "' has invalid value: '" + path + "': " + exc.what() );
+ }
+ #endif
+}
+
+inline void check_email_validity( const std::string& email, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ o_stream regex_for_email_validity;
+ regex_for_email_validity << "[a-zA-Z0-9_]{1,}"
+ << "[a-zA-Z0-9_.-]{1,}"
+ << "[a-zA-Z0-9_]{1,}"
+ << "@"
+ << "[a-zA-Z0-9_]{1,}"
+ << "[a-zA-Z0-9_.-]{1,}"
+ << "[.]{1}"
+ << "[a-zA-Z]{2,6}"
+ ;
+ const boost::regex e( regex_for_email_validity.str() );
+ if ( !regex_match( email, e ) ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name + "' has invalid 'E-MAIL' value '" + email + "'!" );
+ } else {}
+ #endif
+}
+
+///
+struct common_validator {
+#ifdef WITH_SEMANTIC_CHECK
+protected:
+ typedef boost::function< bool ( const std::string& /* string_with_value */ ) >
+ common_checker;
+ typedef boost::function< void ( const std::string& /* string_with_value */
+ , const std::string& /* option_name */ ) >
+ common_storer;
+ typedef std::pair
+ <
+ common_checker
+ , common_storer
+ >
+ check_pair;
+ typedef std::vector< check_pair >
+ common_handlers;
+#endif
+protected:
+ common_validator( options& _registered_options, const std::string& _sections_separator )
+ #ifdef WITH_SEMANTIC_CHECK
+ : registered_options( _registered_options )
+ , sections_separator( _sections_separator )
+ #endif
+ {}
+#ifdef WITH_SEMANTIC_CHECK
+protected:
+ options& registered_options;
+ const std::string& sections_separator;
+ common_handlers handlers;
+protected:
+ void check( const std::string& what
+ , const std::string& checked_string_with_value
+ , const std::string& option_name ) {
+ check_negitivity_of( what, checked_string_with_value, option_name );
+ bool coincided = false;
+ BOOST_FOREACH ( check_pair& p, handlers ) {
+ if ( p.first( checked_string_with_value ) ) {
+ p.second( checked_string_with_value, option_name );
+ coincided = true;
+ } else {}
+ }
+ if ( !coincided ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name
+ + "' has invalid '" + what + "' value '" + checked_string_with_value + "'!" );
+ } else {}
+ }
+
+ void check_negitivity_of( const std::string& what
+ , const std::string& string_with_value
+ , const std::string& option_name ) const {
+ if ( boost::starts_with( string_with_value, "-" ) ) {
+ notify( semantic_error_prefix()
+ + "option '" + option_name
+ + "' has invalid '" + what + "' value '" + string_with_value
+ + "', it cannot be negative!" );
+ } else {}
+ }
+
+ double extract_pure_value_from( const std::string& string_with_value, const std::string& value_sign ) const {
+ string_const_it value_begin = string_with_value.begin();
+ string_const_it value_end = boost::ifind_last( string_with_value, value_sign ).begin();
+ std::string pure_value_as_string( value_begin, value_end );
+ boost::trim( pure_value_as_string );
+ return boost::lexical_cast< double >( pure_value_as_string );
+ }
+
+ template< typename ValueType >
+ void store_for_option( const std::string& option_name, ValueType value_in_minimal_units ) {
+ std::string restored_option_name( option_name.begin(), option_name.end() );
+ boost::replace_all( restored_option_name, sections_separator_for_log(), sections_separator );
+ option_it it = std::find( registered_options.begin()
+ , registered_options.end()
+ , restored_option_name );
+ if ( registered_options.end() != it ) {
+ it->value = boost::lexical_cast< std::string >( value_in_minimal_units );
+ } else {}
+ }
+#endif
+};
+
+/// \class size_validator
+/// \brief Size validator.
+///
+/// Check size semantic.
+class size_validator : common_validator {
+public:
+ size_validator( options& registered_options, const std::string& sections_separator ) :
+ common_validator( registered_options, sections_separator )
+ #ifdef WITH_SEMANTIC_CHECK
+ , regex_size_in_bytes_pure( "[0-9]{1,}" )
+ , regex_size_in_bytes( "[0-9]{1,}[ ]{0,}[bB]{1}" )
+ , regex_size_in_kbytes( "[0-9.]{1,}[ ]{0,}[kK]{1}[bB]{0,1}" )
+ , regex_size_in_mbytes( "[0-9.]{1,}[ ]{0,}[mM]{1}[bB]{0,1}" )
+ , regex_size_in_gbytes( "[0-9.]{1,}[ ]{0,}[gG]{1}[bB]{0,1}" )
+ , b_sign( "b" )
+ , kb_sign( "k" )
+ , mb_sign( "m" )
+ , gb_sign( "g" )
+ , bytes_in_kb( ::pow( 1024, 1 ) )
+ , bytes_in_mb( ::pow( 1024, 2 ) )
+ , bytes_in_gb( ::pow( 1024, 3 ) )
+ #endif
+ {
+ #ifdef WITH_SEMANTIC_CHECK
+ typedef size_validator sv;
+ handlers = list_of( std::make_pair( boost::bind( &sv::size_in_bytes_pure, this, _1 )
+ , boost::bind( &sv::store_in_bytes_pure, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &sv::size_in_bytes, this, _1 )
+ , boost::bind( &sv::store_in_bytes, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &sv::size_in_kbytes, this, _1 )
+ , boost::bind( &sv::store_in_kbytes, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &sv::size_in_mbytes, this, _1 )
+ , boost::bind( &sv::store_in_mbytes, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &sv::size_in_gbytes, this, _1 )
+ , boost::bind( &sv::store_in_gbytes, this, _1, _2 ) ) )
+ ;
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ const boost::regex regex_size_in_bytes_pure;
+ const boost::regex regex_size_in_bytes;
+ const boost::regex regex_size_in_kbytes;
+ const boost::regex regex_size_in_mbytes;
+ const boost::regex regex_size_in_gbytes;
+ const std::string b_sign;
+ const std::string kb_sign;
+ const std::string mb_sign;
+ const std::string gb_sign;
+ const unsigned long int bytes_in_kb;
+ const unsigned long int bytes_in_mb;
+ const unsigned long int bytes_in_gb;
+#endif
+public:
+ void check( const std::string& size, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ common_validator::check( "SIZE", size, option_name );
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ bool size_in_bytes_pure( const std::string& size ) const { return regex_match( size, regex_size_in_bytes_pure ); }
+ bool size_in_bytes( const std::string& size ) const { return regex_match( size, regex_size_in_bytes ); }
+ bool size_in_kbytes( const std::string& size ) const { return regex_match( size, regex_size_in_kbytes ); }
+ bool size_in_mbytes( const std::string& size ) const { return regex_match( size, regex_size_in_mbytes ); }
+ bool size_in_gbytes( const std::string& size ) const { return regex_match( size, regex_size_in_gbytes ); }
+private:
+ void store_in_bytes_pure( const std::string& size, const std::string& option_name ) {
+ const double value_in_bytes = boost::lexical_cast< double >( size );
+ store_for_option( option_name, value_in_bytes );
+ }
+
+ void store_in_bytes( const std::string& size, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( size, b_sign );
+ const unsigned long int value_in_bytes = pure_value;
+ store_for_option( option_name, value_in_bytes );
+ }
+
+ void store_in_kbytes( const std::string& size, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( size, kb_sign );
+ const unsigned long int value_in_bytes = pure_value * bytes_in_kb;
+ store_for_option( option_name, value_in_bytes );
+ }
+
+ void store_in_mbytes( const std::string& size, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( size, mb_sign );
+ const unsigned long int value_in_bytes = pure_value * bytes_in_mb;
+ store_for_option( option_name, value_in_bytes );
+ }
+
+ void store_in_gbytes( const std::string& size, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( size, gb_sign );
+ const unsigned long int value_in_bytes = pure_value * bytes_in_gb;
+ store_for_option( option_name, value_in_bytes );
+ }
+#endif
+};
+
+/// \class time_period_validator
+/// \brief Time period validator.
+///
+/// Check time period semantic.
+class time_period_validator : common_validator {
+public:
+ time_period_validator( options& registered_options, const std::string& sections_separator ) :
+ common_validator( registered_options, sections_separator )
+ #ifdef WITH_SEMANTIC_CHECK
+ , second_sign( "s" )
+ , minute_sign( "m" )
+ , hour_sign( "h" )
+ , day_sign( "d" )
+ , regex_period_in_seconds_pure( "[0-9]{1,}" )
+ , regex_period_in_seconds( "[0-9]{1,}[ ]{0,}[" + second_sign + "]{1}" )
+ , regex_period_in_minutes( "[0-9.]{1,}[ ]{0,}[" + minute_sign + "]{1}" )
+ , regex_period_in_hours( "[0-9.]{1,}[ ]{0,}[" + hour_sign + "]{1}" )
+ , regex_period_in_days( "[0-9.]{1,}[ ]{0,}[" + day_sign + "]{1}" )
+ , seconds_in_minute( 60 )
+ , seconds_in_hour( 60 * seconds_in_minute )
+ , seconds_in_day( 24 * seconds_in_hour )
+ #endif
+ {
+ #ifdef WITH_SEMANTIC_CHECK
+ typedef time_period_validator tpv;
+ handlers = list_of( std::make_pair( boost::bind( &tpv::period_in_seconds_pure, this, _1 )
+ , boost::bind( &tpv::store_in_seconds_pure, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &tpv::period_in_seconds, this, _1 )
+ , boost::bind( &tpv::store_in_seconds, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &tpv::period_in_minutes, this, _1 )
+ , boost::bind( &tpv::store_in_minutes, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &tpv::period_in_hours, this, _1 )
+ , boost::bind( &tpv::store_in_hours, this, _1, _2 ) ) )
+ ( std::make_pair( boost::bind( &tpv::period_in_days, this, _1 )
+ , boost::bind( &tpv::store_in_days, this, _1, _2 ) ) )
+ ;
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ const std::string second_sign;
+ const std::string minute_sign;
+ const std::string hour_sign;
+ const std::string day_sign;
+ const boost::regex regex_period_in_seconds_pure;
+ const boost::regex regex_period_in_seconds;
+ const boost::regex regex_period_in_minutes;
+ const boost::regex regex_period_in_hours;
+ const boost::regex regex_period_in_days;
+ const unsigned long int seconds_in_minute;
+ const unsigned long int seconds_in_hour;
+ const unsigned long int seconds_in_day;
+#endif
+public:
+ void check( const std::string& time_period, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ common_validator::check( "TIME PERIOD", time_period, option_name );
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ bool period_in_seconds_pure( const std::string& time_period ) const {
+ return regex_match( time_period, regex_period_in_seconds_pure );
+ }
+
+ bool period_in_seconds( const std::string& time_period ) const {
+ return regex_match( time_period, regex_period_in_seconds );
+ }
+
+ bool period_in_minutes( const std::string& time_period ) const {
+ return regex_match( time_period, regex_period_in_minutes );
+ }
+
+ bool period_in_hours( const std::string& time_period ) const {
+ return regex_match( time_period, regex_period_in_hours );
+ }
+
+ bool period_in_days( const std::string& time_period ) const {
+ return regex_match( time_period, regex_period_in_days );
+ }
+private:
+ void store_in_seconds_pure( const std::string& time_period, const std::string& option_name ) {
+ const double value_in_seconds = boost::lexical_cast< double >( time_period );
+ store_for_option( option_name, value_in_seconds );
+ }
+
+ void store_in_seconds( const std::string& time_period, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( time_period, second_sign );
+ const unsigned long int value_in_seconds = pure_value;
+ store_for_option( option_name, value_in_seconds );
+ }
+
+ void store_in_minutes( const std::string& time_period, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( time_period, minute_sign );
+ const unsigned long int value_in_seconds = pure_value * seconds_in_minute;
+ store_for_option( option_name, value_in_seconds );
+ }
+
+ void store_in_hours( const std::string& time_period, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( time_period, hour_sign );
+ const unsigned long int value_in_seconds = pure_value * seconds_in_hour;
+ store_for_option( option_name, value_in_seconds );
+ }
+
+ void store_in_days( const std::string& time_period, const std::string& option_name ) {
+ const double pure_value = extract_pure_value_from( time_period, day_sign );
+ const unsigned long int value_in_seconds = pure_value * seconds_in_day;
+ store_for_option( option_name, value_in_seconds );
+ }
+#endif
+};
+
+/// \class exp_record_validator
+/// \brief Exponential record validator.
+///
+/// Check exponential record semantics.
+class exp_record_validator : common_validator {
+public:
+ exp_record_validator( options& registered_options, const std::string& sections_separator ) :
+ common_validator( registered_options, sections_separator )
+ #ifdef WITH_SEMANTIC_CHECK
+ , regex_exp_record( "[-]{0,1}[0-9.]{1,}[eE]{1}[-+]{0,1}[0-9]{0,}" )
+ #endif
+ {}
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ const boost::regex regex_exp_record;
+#endif
+public:
+ void check( const std::string& exp_record, const std::string& option_name ) {
+ #ifdef WITH_SEMANTIC_CHECK
+ if ( valid_exp_record( exp_record ) ) {
+ store_number_from_exp_record( exp_record, option_name );
+ } else {
+ notify_about_invalid_exp_record( option_name, exp_record );
+ }
+ #endif
+ }
+#ifdef WITH_SEMANTIC_CHECK
+private:
+ bool valid_exp_record( const std::string& exp_record ) const {
+ return regex_match( exp_record, regex_exp_record );
+ }
+private:
+ void store_number_from_exp_record( const std::string& exp_record, const std::string& option_name ) {
+ str_storage number_parts = extract_parts_of_number_from( exp_record );
+ double mantissa = 0.0;
+ int degree = 0;
+ try {
+ mantissa = boost::lexical_cast< double >( number_parts[0] );
+ degree = boost::lexical_cast< int >( number_parts[1] );
+ } catch ( const std::exception& exc ) {
+ notify_about_invalid_exp_record( option_name, exp_record );
+ }
+ long double number = mantissa * calculate_ten_in_degree( degree, option_name );
+ store_for_option( option_name, number );
+ }
+private:
+ str_storage extract_parts_of_number_from( const std::string& exp_record ) const {
+ std::string exp_record_for_analize( exp_record.begin(), exp_record.end() );
+ boost::to_lower( exp_record_for_analize );
+ str_storage number_parts;
+ boost::split( number_parts, exp_record_for_analize, boost::is_any_of( "e" ) );
+ return number_parts;
+ }
+
+ long double calculate_ten_in_degree( int degree, const std::string& option_name ) const {
+ long double ten_in_degree = ::pow( 10, degree );
+ if ( HUGE_VAL == ten_in_degree ) {
+ o_stream what_happened;
+ what_happened << "value of option '"
+ << prepare_full_name_for_log( option_name, sections_separator )
+ << "' define in correct exponential record, "
+ << "but it degree '" << degree << "' is too big!";
+ notify( semantic_error_prefix() + what_happened.str() );
+ } else {}
+ return ten_in_degree;
+ }
+
+ void notify_about_invalid_exp_record( const std::string& option_name
+ , const std::string& exp_record ) const {
+ notify( semantic_error_prefix()
+ + "option '" + option_name
+ + "' has invalid 'EXP_RECORD' value '" + exp_record + "'!" );
+ }
+#endif
+};
+
+} // namespace detail
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_VALIDATORS_HPP

Added: sandbox/configurator/libs/configurator/doc/acknowledgments.html
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/doc/acknowledgments.html 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <link rel="stylesheet" type="text/css" href="../../../boost.css">
+
+ <title>Configurator - Acknowledgments</title>
+<link rel="icon" href="/favicon.ico" type="image/ico"><link rel="stylesheet" type="text/css" href="/style-v2/section-basic.css"></head>
+
+<body link="#0000FF" vlink="#800080"> <div id="boost-common-heading-doc">
+ <div class="heading-inner">
+ <div class="heading-placard"></div>
+
+ <h1 class="heading-title">
+ <a href="/">
+ <img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
+ <span class="heading-boost">Boost</span>
+ <span class="heading-cpplibraries">C++ Libraries</span>
+ </a></h1>
+
+ <p class="heading-quote">
+ <q>...one of the most highly
+ regarded and expertly designed C++ library projects in the
+ world.</q> <span class="heading-attribution">&mdash; <a href=
+ "http://www.gotw.ca/" class="external">Herb Sutter</a> and <a href=
+ "http://en.wikipedia.org/wiki/Andrei_Alexandrescu" class="external">Andrei
+ Alexandrescu</a>, <a href=
+ "http://safari.awprofessional.com/?XmlId=0321113586" class="external">C++
+ Coding Standards</a></span></p>
+
+ <div class="heading-sections">
+ <ul>
+ <li class="welcome-section-tab">Welcome</li>
+ <li class="boost-section-tab">Introduction</li>
+ <li class="community-section-tab">Community</li>
+ <li class="development-section-tab">Development</li>
+ <li class="support-section-tab">Support</li>
+ <li class="doc-section-tab">Documentation</li>
+ </ul>
+ </div>
+</div>
+ </div>
+
+ <div id="boost-common-heading-doc-spacer"></div>
+
+
+ <h1 align="center">Configurator</h1>
+
+ <h2 align="center">Acknowledgments</h2>
+ I'm very grateful to <b>Bjarne Stroustrup</b>, who invented so beautiful, so powerful and so dangerous language!
+<br/>
+Also I grateful to all authors of <b>Boost C++ libraries</b>. Thank you for your work!
+ <hr>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->30
+ November, 2010<!--webbot bot="Timestamp" endspan i-checksum="38514" --></p>
+
+ <p><i>Copyright &copy; 2010 Denis Shevchenko</i></p>
+
+ <p><i>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
+</body>
+</html>

Added: sandbox/configurator/libs/configurator/doc/overview.html
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/doc/overview.html 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,667 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <link rel="stylesheet" type="text/css" href="../../../boost.css">
+
+ <title>Configurator - Overview</title>
+<link rel="icon" href="/favicon.ico" type="image/ico"><link rel="stylesheet" type="text/css" href="/style-v2/section-basic.css"></head>
+
+<body link="#0000FF" vlink="#800080"> <div id="boost-common-heading-doc">
+ <div class="heading-inner">
+ <div class="heading-placard"></div>
+
+ <h1 class="heading-title">
+ <a href="/">
+ <img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
+ <span class="heading-boost">Boost</span>
+ <span class="heading-cpplibraries">C++ Libraries</span>
+ </a></h1>
+
+ <p class="heading-quote">
+ <q>...one of the most highly
+ regarded and expertly designed C++ library projects in the
+ world.</q> <span class="heading-attribution">&mdash; <a href=
+ "
http://www.gotw.ca/" class="external">Herb Sutter</a> and <a href=
+ "http://en.wikipedia.org/wiki/Andrei_Alexandrescu" class="external">Andrei
+ Alexandrescu</a>, <a href=
+ "http://safari.awprofessional.com/?XmlId=0321113586" class="external">C++
+ Coding Standards</a></span></p>
+
+ <div class="heading-sections">
+ <ul>
+ <li class="welcome-section-tab">Welcome</li>
+ <li class="boost-section-tab">Introduction</li>
+ <li class="community-section-tab">Community</li>
+ <li class="development-section-tab">Development</li>
+ <li class="support-section-tab">Support</li>
+ <li class="doc-section-tab">Documentation</li>
+ </ul>
+ </div>
+</div>
+ </div>
+
+ <div id="boost-common-heading-doc-spacer"></div>
+
+
+ <h1 align="center">Configurator</h1>
+
+ <h2 align="center">Overview</h2>
+ <dl class="index">
+ <dt>Introduction</dt>
+ <dt>Common usage</dt>
+ <dt>Advanced usage</dt>
+ </dl>
+
+ <h2><a name="introduction" id="introduction"></a>Introduction</h2>
+
+ <p>
+<a name="simplest_config_format"><h3>Simplest configuration file format</h3></a>
+In fact, configuration file contains a set of data. This set presented by options stored in global scope or in section(s). Option has <strong>name</strong> and <strong>value</strong> separated by a some separator.
+
+Simplest configuration file looks like this:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+Host = 127.0.0.1
+</pre>
+</div>
+<br/>
+There is one option, with name <strong>Host</strong> and value <strong>127.0.0.1</strong>. Default name-value separator is "<strong>=</strong>".
+<br/>
+<a name="necessity"><h3>Option's necessity</h3></a>
+Option can be necessary or optionally.
+
+In examples above option <strong>Host</strong> may be optional, so user can skip it. But in some cases this option may be necessary, so user must input it in configuration file.
+<br/>
+<a name="default_value"><h3>Option's default value</h3></a>
+Option can have default value, in this case not required input it.
+This option can be useful for options with predefined default values.
+
+In example above option <strong>Host</strong> may have some default value of address, so user can skip it.
+<br/>
+<a name="value_semantic"><h3>Semantic of option's value</h3></a>
+It is often necessary to check the semantic of concrete option's value. For example, user must inputs valid IP:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+Host = 127.0.0.1
+</pre>
+</div>
+<br/>
+But what if the user inputs an incorrect value, for example:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+Host = 127.678.988.1
+</pre>
+</div>
+<br/>
+Configurator allows to define semantic check for each option.
+<br/>
+Supported semantics:
+<ul>
+ <li><strong>path</strong> (Path semantics check)</li>
+ <li><strong>optional_path</strong> (Optional path semantics check)</li>
+ <li><strong>ipv4</strong> (IPv4 semantics check)</li>
+ <li><strong>ipv6</strong> (IPv6 semantics check)</li>
+ <li><strong>ip</strong> (IP semantics check)</li>
+ <li><strong>email</strong> (E-mail semantics check)</li>
+ <li><strong>size</strong> (Size semantics check)</li>
+ <li><strong>time_period</strong> (Time period semantics check)</li>
+ <li><strong>exp_record</strong> (Exponential record semantics check)</li>
+</ul>
+Note that 'optional_path' semantic check path correctness and in case of failure NOT throw exception,
+but print warning message in std::cout. It may be useful for programs that must create missing files/folders.
+
+
+ </p>
+
+ <h2><a name="topic1" id="topic1"></a>Common usage</h2>
+
+ <p>
+ <a name="config_file_format"><h3>Configuration file format</h3></a>
+Configuration file is a set of options placed in global scope and/or in section(s).
+
+Global options example:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+Host = 127.0.0.1
+Port = 80
+User = user
+Password = password
+</pre></div>
+<br/>
+Section is similar to XML: open tag enclosed in '&lt;' and '&gt;', close tag - in '&lt;/' and '&gt;'.
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+&lt;Server&gt;
+ Host = 127.0.0.1
+ Port = 80
+&lt;/Server&gt;
+</pre></div>
+<br/>
+You can use nested sections:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+&lt;Server&gt;
+ Host = 127.0.0.1
+ Port = 80
+
+ &lt;Security&gt;
+ User = user
+ Password = password
+ &lt;/Security&gt;
+&lt;/Server&gt;
+</pre></div>
+
+<br/>
+<a name="preparing"><h3>Preparing</h3></a>
+Copy 'configurator' folder in some place where your compiler is looking for header files and add:
+<pre>
+#include &lt;boost/configurator/configurator.hpp&gt;
+</pre>in your program.
+
+<a name="options_registering"><h3>Options registering</h3></a>
+Registration of new option included three tasks:
+<ol>
+ <li>define section where this option will be placed <em>(optionally)</em>,</li>
+ <li>define option's name,</li>
+ <li>define required checks and additional settings <em>(optionally)</em>.</li>
+</ol>
+<br/>
+Register option in global scope of configuration file:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.add_option( "Host" );
+ // ...
+}
+</pre>
+or in short variant:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.add( "Host" );
+ // ...
+}
+</pre>
+<br/>
+Register option in section:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.in_section( "Server" ).add_option_here( "Host" );
+ // ...
+}
+</pre>
+or in short variant:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.in( "Server" ).add_here( "Host" );
+ // ...
+}
+</pre>
+
+<a name="parsing"><h3>Parsing</h3></a>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.parse( "/some/path/to/config_file" );
+ // ...
+}
+</pre>After that you can obtain values of options. Of course, <strong>/some/path/to/config_file</strong> must be valid in your filesystem.
+<br/>
+<a name="options_values_obtaining"><h3>Obtaining of option's values</h3></a>
+
+Configuration file:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+DatabaseName = my_db
+&lt;Server&gt;
+ Host = 127.0.0.1
+
+ &lt;Security&gt;
+ User = user
+ &lt;/Security&gt;
+&lt;/Server&gt;
+</pre></div>
+<br/>
+Obtaining values of options example:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string db = conf.get_value( "DatabaseName" );
+ std::string host = conf.from_section( "Server" )
+ .get_value_from_here( "Host" )
+ ;
+ std::string user = conf.from_section( "Server" )
+ .from_section( "Security" )
+ .get_value_from_here( "User" )
+ ;
+ // ...
+}
+</pre>
+or in short variant:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string db = conf.get( "DatabaseName" );
+ std::string host = conf.from( "Server" ).get_from_here( "Host" );
+ std::string user = conf.from( "Server" ).from( "Security" ).get_from_here( "User" );
+ // ...
+}
+</pre>
+
+ </p>
+
+ <h2><a name="topic2" id="topic2"></a>Advanced usage</h2>
+
+ <p>
+ <a name="options_necessity"><h3>How to set option's necessity</h3></a>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.in( "Server" ).add_here( "Host" ).necessary();
+ // ...
+}
+</pre>
+After this user must inputs "Host" option in configuration file. If not, exception will thrown:
+<br/>
+<strong>[Configurator] Option 'Server > Host' is defined as necessary, but it missed!</strong>
+<br/>
+<a name="options_default_value"><h3>How to set option's default value</h3></a>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.in( "Server" ).add_here( "Host" ).default_value( "127.0.0.1" );
+ // ...
+}
+</pre>
+After this user can skip "Host" option in configuration file.
+<br/>
+<a name="options_semantics_check"><h3>How to set option's semantics check</h3></a>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.in( "Server" ).add_here( "Host" ).check_semantic( boost::cf::ip );
+ // ...
+}
+</pre>
+After this value of "Host" option must be valid IP address (IPv4 or IPv6). If not, exception will be thrown:
+<br/>
+<strong>[Configurator] Semantic error: option 'Server > Host' has invalid value 'asdfasdfasd' (not IPv4, not IPv6)!</strong>
+<br/>
+<br/>
+<strong>IMPORTANT!</strong>
+<br/>
+If you use semantics check, you must compile your program with flag WITH_SEMANTIC_CHECK, for example:
+<br/>
+<strong>g++ -DWITH_SEMANTIC_CHECK -o test main.cpp -lboost_system -lboost_filesystem -lboost_regex</strong>
+<br/>
+Note that in this case you must link <strong>boost_system</strong> and <strong>boost_regex</strong> libraries. You only pay for what you use.
+
+<a name="combine_options_settings"><h3>Combine settings</h3></a>
+Of course, you can combine settings for option:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.in( "Server" ).add_here( "Host" )
+ .check_semantic( boost::cf::ip )
+ .default_value( "34.67.56.89" )
+ ;
+ // ...
+}
+</pre>
+But you can not use contradictory settings, for example:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ conf.in( "Server" ).add_here( "Host" )
+ .necessary()
+ .default_value( "34.67.56.89" ) // Default value for necessary option? Hm...
+ ;
+ // ...
+}
+</pre>
+In this case exception will be thrown:
+<br/>
+<strong>[Configurator] Option 'Server > Host' registered as necessary, so it cannot have default_value!</strong>
+
+<a name="advanced_options_values_obtaining"><h3>Advanced obtaining option's value</h3></a>
+You can obtain option's value different ways.
+<br>
+<br>
+Simplest way is pure string obtaining:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string host = conf.from( "Server" ).get_from_here( "Host" );
+ // ...
+}
+</pre>
+
+You can obtain value by passing:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string host;
+ conf.from( "Server" ).get_from_here( "Host", host );
+ // ...
+}
+</pre>
+It is useful when you want obtain many values from one section:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string user;
+ std::string password;
+ conf.from( "Server" ).from( "Security" ).get_from_here( "User", user )
+ .get_from_here( "Password", password )
+ ;
+ // ...
+}
+</pre>
+Of course, you can obtain not only string values:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ std::string host;
+ unsigned int port = 0;
+ conf.from( "Server" ).get_from_here( "Host", host )
+ .get_from_here( "Port", port )
+ ;
+ // ...
+}
+</pre>
+In this case value oh "Port" must be correspond to <strong>unsigned int</strong> type. If not, exception will be thrown:
+<br/>
+<strong>[Configurator] Value 'asdfasdfasd' of option 'Server > Port' cannot be cast to &lt;unsigned int&gt;!</strong>
+<br/>
+<br/>
+You can obtain values with explicitly defining type:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ // ...
+ unsigned int port = conf.from( "Server" ).get_from_here< unsigned int >( "Port" );
+ // ...
+}
+</pre>
+<a name="advanced_options_values_semantics"><h3>Advanced obtaining option's semantics</h3></a>
+If you use semantics <strong>'size'</strong> and <strong>'time_period'</strong>, you can obtain such values
+in minimal units (bytes and seconds respectively).
+<br/>
+Configuration file:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+some_period = 10h
+some_file_size = 10Mb
+</pre></div>
+<br/>
+Code:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.add( "some_period" ).check_semantic( boost::cf::time_period );
+ conf.add( "some_file_size" ).check_semantic( boost::cf::size );
+ // ...
+ unsigned long int period_in_sec = 0;
+ unsigned long int size_in_bytes = 0;
+ conf.get( "some_period", period_in_sec )
+ .get( "some_file_size", size_in_bytes )
+ ;
+
+ std::cout << "period in sec: " << period_in_sec << std::endl;
+ std::cout << "size in bytes: " << size_in_bytes << std::endl;
+
+ // ...
+}
+</pre>
+You will see:
+<pre><strong>
+period in sec: 36000
+size in bytes: 10485760
+</strong> </pre>
+Supported time periods:
+<ul>
+ <li><strong>10</strong> (seconds)</li>
+ <li><strong>10s</strong> (seconds)</li>
+ <li><strong>10m</strong> (minutes)</li>
+ <li><strong>10h</strong> (hours)</li>
+ <li><strong>10d</strong> (days)</li>
+</ul>
+Supported sizes (size literals are case-insensitive):
+<ul>
+ <li><strong>10</strong> (bytes)</li>
+ <li><strong>10b</strong> (bytes)</li>
+ <li><strong>10K</strong> (Kbytes)</li>
+ <li><strong>10Kb</strong> (Kbytes)</li>
+ <li><strong>10M</strong> (Mbytes)</li>
+ <li><strong>10Mb</strong> (Mbytes)</li>
+ <li><strong>10G</strong> (Gbytes)</li>
+ <li><strong>10Gb</strong> (Gbytes)</li>
+</ul>
+Between numbers and literals can be space(s), so "10MB" equal to "10 MB".
+
+<a name="options_with_multi_values"><h3>Options with multi-values</h3></a>
+By default option can't repeat in configuration file, so if you write:
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+DatabaseName = my_db
+DatabaseName = my_db_2
+</pre></div>
+<br/>
+exception will be thrown:
+<br/>
+<strong>[Configurator] Option 'Database' has multiple values, but it not allowed to have multiply values!</strong>
+<br/>
+<br/>
+But you can use multiply values:
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.add( "DatabaseName" ).allow_multi_values();
+ std::cout << "DatabaseName: " << conf.get( "DatabaseName" ) << std::endl;
+
+ // ...
+}
+</pre>
+In this case values of "DatabaseName" option will be accumulated, and you will see:
+<br/>
+<strong>DatabaseName = my_db my_db_2</strong>
+<br/>
+<br/>
+This may be very useful for example, when you register some plugins:
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+Plugin = plug_a plug_b
+Plugin = plug_c
+Plugin = plug_d
+Plugin = plug_e
+</pre></div>
+<br/>
+In this case value of "Plugin" option will be <strong>plug_a plug_b plug_c plug_d plug_e</strong>.
+
+<a name="case_sensitivity_for_names"><h3>Case sensitivity for names</h3></a>
+You can set case sensitivity for names of options and sections. By default it is case insensitive.
+<br/>
+So if we have:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+DatabaseNAME = my_db
+&lt;ServEr&gt;
+ hosT = 127.0.0.1
+&lt;/SERver&gt;
+</pre></div>
+by default it's okay:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.add( "DatabaseName" );
+ conf.in( "Server" ).add_here( "Host" );
+ // ...
+ std::string db;
+ std::string host;
+ conf.get( "DatabaseName", db );
+ conf.from( "Server" ).get_from_here( "Host", host );
+ // ...
+}
+</pre>
+But if we set case sensitivity:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.set_case_sensitivity_for_names();
+ // ...
+}
+</pre>
+exception will be thrown, because Configurator will differentiate between names "DatabaseName" and "DatabaseNAME".
+
+<a name="name_value_separator"><h3>How to set another name-value separator for options</h3></a>
+
+By default name-value separator is '=' sign, but you can set another:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.set_name_value_separator( ':' );
+ // ...
+}
+</pre>
+In this case you must use this sign:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+DatabaseName : my_db
+</pre></div>
+<br/>
+You can use space sign:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.set_name_value_separator( ' ' );
+ // ...
+}
+</pre>
+and use it:
+<br/>
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+DatabaseName my_db
+</pre></div>
+
+<a name="canonical_one_line_comments"><h3>How to use "canonical" one-line comments</h3></a>
+By default Configurator use C++-style comments:
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+/*
+ * My config.
+ */
+DatabaseName : my_db // this is comment for db
+</pre></div>
+<br/>
+But you can use "canonical" one-line comment with sign '#':
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::configurator conf;
+ conf.use_canonical_one_line_comments();
+ // ...
+}
+</pre>
+In this case "//" will be just two slashes.
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+/*
+ * My config.
+ */
+DatabaseName : my_db # this is comment for db
+Host = http://www.mysite.com # "//" after "http:" is NOT comments...
+</pre></div>
+
+<a name="singleton_configurator"><h3>Singleton-variant of boost::cf::configurator class</h3></a>
+If you have many objects that need access to configurator, you can use it Singleton-variant:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ boost::cf::single_configurator::inst().use_canonical_one_line_comments();
+ // ...
+}
+</pre>
+I use it. :-)
+<br/>
+<br/>
+<strong>IMPORTANT!</strong>
+<br/>
+If you use Singleton-variant, you must compile your program with flag WITH_SINGLETON, for example:
+<br/>
+<strong>g++ -DWITH_SINGLETON -o test main.cpp -lboost_filesystem -lboost_thread</strong>
+<br/>
+Note that in this case you must link <strong>boost_thread</strong> libraries. You only pay for what you use.
+
+<a name="reparsing"><h3>Reparsing</h3></a>
+You can reparse configuration file during program execution:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ //
+ boost::cf::single_configurator::inst().reparse();
+ // ...
+}
+</pre>
+In this case "old" configuration file will be reparsed.
+<br/>
+<br/>
+But you can use some "new" file:
+<br/>
+<pre>
+int main( int argc, char* argv[] ) {
+ //
+ boost::cf::single_configurator::inst().reparse( "/some/path/to/new/config" );
+ // ...
+}
+</pre>
+
+ <hr>
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->30
+ November, 2010<!--webbot bot="Timestamp" endspan i-checksum="38514" --></p>
+
+ <p><i>Copyright &copy; 2010 Denis Shevchenko</i></p>
+
+ <p><i>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
+</body>
+</html>

Added: sandbox/configurator/libs/configurator/doc/rationale.html
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/doc/rationale.html 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,140 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <link rel="stylesheet" type="text/css" href="../../../boost.css">
+
+ <title>Configurator - Rationale</title>
+<link rel="icon" href="/favicon.ico" type="image/ico"><link rel="stylesheet" type="text/css" href="/style-v2/section-basic.css"></head>
+
+<body link="#0000FF" vlink="#800080"> <div id="boost-common-heading-doc">
+ <div class="heading-inner">
+ <div class="heading-placard"></div>
+
+ <h1 class="heading-title">
+ <a href="/">
+ <img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
+ <span class="heading-boost">Boost</span>
+ <span class="heading-cpplibraries">C++ Libraries</span>
+ </a></h1>
+
+ <p class="heading-quote">
+ <q>...one of the most highly
+ regarded and expertly designed C++ library projects in the
+ world.</q> <span class="heading-attribution">&mdash; <a href=
+ "
http://www.gotw.ca/" class="external">Herb Sutter</a> and <a href=
+ "http://en.wikipedia.org/wiki/Andrei_Alexandrescu" class="external">Andrei
+ Alexandrescu</a>, <a href=
+ "http://safari.awprofessional.com/?XmlId=0321113586" class="external">C++
+ Coding Standards</a></span></p>
+
+ <div class="heading-sections">
+ <ul>
+ <li class="welcome-section-tab">Welcome</li>
+ <li class="boost-section-tab">Introduction</li>
+ <li class="community-section-tab">Community</li>
+ <li class="development-section-tab">Development</li>
+ <li class="support-section-tab">Support</li>
+ <li class="doc-section-tab">Documentation</li>
+ </ul>
+ </div>
+</div>
+ </div>
+
+ <div id="boost-common-heading-doc-spacer"></div>
+
+
+ <h1 align="center">Configurator</h1>
+
+ <h2 align="center">Rationale</h2>
+ <dl class="index">
+ <dt>Introduction</dt>
+ <dt>Hello, world!</dt>
+ <dt>Features</dt>
+ </dl>
+
+ <h2><a name="introduction" id="introduction"></a>Introduction</h2>
+
+ <p>
+ Many programs (especially servers, daemons, etc.) requires configuration file for work, so it handling is very common task. Actually, this handling add up to four tasks:
+ <ol>
+ <li>obtaining options from configuration file,</li>
+ <li>check correctness (in all senses of this word) of obtained options,</li>
+ <li>storing options,</li>
+ <li>issuance of the options values on demand.</li>
+ </ol>
+
+Configurator library provides general solution for this tasks. It very easy to use.
+ </p>
+
+ <h2><a name="topic1" id="topic1"></a>Hello, world!</h2>
+
+ <p>
+ Simplest configuration file:
+<div style="margin-left: 6px; margin-right: 6px; padding-left: 6px; padding-right: 6px; background: #F5F5DC; border: 1px solid #DEB887; font-family: monospace; font-size: 13px">
+<pre>
+// hello_world.conf
+Host = 127.0.0.1
+</pre>
+</div>
+<br/>
+Code for work with it:
+<pre>
+#include &lt;boost/configurator/configurator.hpp&gt;
+
+#include &lt;iostream&gt;
+
+int main( int argc, char* argv[] ) {
+ try {
+ boost::cf::configurator configurator;
+ configurator.add_option( "Host" );
+
+ configurator.parse( "/some/path/to/hello_world.conf" );
+
+ std::string value_of_host = configurator.get_value( "Host" );
+ std::cout << "Value of host: " << value_of_host << std::endl;
+ } catch ( const std::exception& exc ) {
+ std::cerr << exc.what() << std::endl;
+ }
+
+ return 0;
+}
+</pre>
+ </p>
+
+ <h2><a name="topic2" id="topic2"></a>Features</h2>
+
+ <p>
+ <ul>
+ <li>Simplicity (easy-to-learn and easy-to-use).</li>
+ <li>Header-only (does not require building).</li>
+ <li>Cross-platform (there is only ISO C++ code and Boost C++ libraries).</li>
+ <li>Allows to set option's necessity.</li>
+ <li>Allows to set option's default value.</li>
+ <li>Allows to set another "name-value" separator, instead default '='.</li>
+ <li>Allows to use arbitrary nesting of sections.</li>
+ <li>Checks of value's semantic, like correct path, etc.</li>
+ <li>Provides common checks of options and sections, like duplication, incorrection, etc.</li>
+ <li>Supports single-line and multi-line comments (in C++ style).</li>
+ <li>Allow to register options with multi-values.</li>
+ <li>Singleton-variant of configurator class.</li>
+ <li>Case-sensitivity (or insensitivity) for names of options and sections.</li>
+</ul>
+ </p>
+
+ <hr>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->30
+ November, 2010<!--webbot bot="Timestamp" endspan i-checksum="38514" --></p>
+
+ <p><i>Copyright &copy; 2010 Denis Shevchenko</i></p>
+
+ <p><i>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
+</body>
+</html>

Added: sandbox/configurator/libs/configurator/example/advanced.cpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/example/advanced.cpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,113 @@
+// Example of advanced usage of Configurator library.
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see
http://www.boost.org/LICENSE_1_0.txt)
+//
+// IMPORTANT! Example must compile with flags WITH_SINGLETON and WITH_SEMANTIC_CHECK, example:
+// # g++ -DWITH_SINGLETON -DWITH_SEMANTIC_CHECK -o test main.cpp -lboost_system -lboost_filesystem -lboost_regex -lboost_thread
+
+#include <boost/configurator/configurator.hpp>
+
+#include <iostream>
+
+using namespace boost;
+
+void register_options( cf::single_configurator& configurator ) {
+ configurator.add_option( "DbName" );
+ configurator.add_option( "DbHost" );
+ configurator.add_option( "DbPort" );
+ configurator.add_option( "DbUser" );
+ configurator.add_option( "DbPassword" );
+
+ configurator.in_section( "Server" );
+ configurator.add_option_here( "Host" )
+ .default_value( "127.0.0.1" )
+ .check_semantic( cf::ip )
+ ;
+ configurator.add_option_here( "Port" )
+ .default_value( 80 )
+ ;
+ configurator.add_option_here( "Administrator" )
+ .check_semantic( cf::email );
+ configurator.add_option_here( "StorePath" )
+ .check_semantic( cf::path );
+ configurator.add_option_here( "ReconnectPeriod" )
+ .necessary();
+
+ configurator.in( "Server" ).in( "Internal" );
+ configurator.add_option_here( "Logfile" )
+ .check_semantic( cf::optional_path );
+ configurator.add_option_here( "MaxLogFileSize" )
+ .check_semantic( cf::size )
+ .necessary();
+
+ configurator.in( "Plugins" ).add_option_here( "plugins" )
+ .allow_multi_values();
+}
+
+void view_options_values( cf::single_configurator& configurator ) {
+ std::string name;
+ std::string host;
+ unsigned int port = 0;
+ std::string user;
+ std::string password;
+ configurator.get_value( "DbName", name )
+ .get_value( "DbHost", host )
+ .get_value( "DbPort", port )
+ .get_value( "DbUser", user )
+ .get_value( "DbPassword", password )
+ ;
+ std::cout << "db name: " << name << std::endl;
+ std::cout << "db host: " << host << std::endl;
+ std::cout << "db port: " << port << std::endl;
+ std::cout << "db user: " << user << std::endl;
+ std::cout << "db password: " << password << std::endl;
+
+ configurator.from_section( "Server" );
+ std::string serv_host = configurator.get_value_from_here( "Host" );
+ unsigned int serv_port = configurator.get_value_from_here< unsigned int >( "Port" );
+ std::string admin_email = configurator.get_value_from_here( "Administrator" );
+ std::string store_path = configurator.get_value_from_here( "StorePath" );
+ size_t period = configurator.get_value_from_here< size_t >( "ReconnectPeriod" );
+
+ std::cout << "From Server: " << std::endl;
+ std::cout << " serv_host: " << serv_host << std::endl;
+ std::cout << " serv_port: " << serv_port << std::endl;
+ std::cout << " admin_email: " << admin_email << std::endl;
+ std::cout << " store_path: " << store_path << std::endl;
+ std::cout << " period: " << period << std::endl;
+
+ std::string logfile;
+ unsigned long int max_log_file_size = 0;
+ configurator.from( "Server" ).from( "Internal" ).get_from_here( "Logfile", logfile )
+ .get_from_here( "MaxLogFileSize", max_log_file_size )
+ ;
+ std::cout << "From Server > Internal: " << std::endl;
+ std::cout << " logfile path: " << logfile << std::endl;
+ std::cout << " max_log_file_size (in bytes): " << max_log_file_size << std::endl;
+
+ std::string plugins_list = configurator.from( "Plugins" )
+ .get_from_here( "plugins" )
+ ;
+ std::cout << "From Plugins, plugins_list: " << plugins_list << std::endl;
+}
+
+int main( int argc, char* argv[] ) {
+ try {
+ cf::single_configurator& configurator = cf::single_configurator::inst();
+ configurator.set_name_value_separator( ':' );
+ configurator.set_case_sensitivity_for_names();
+
+ register_options( configurator );
+
+ configurator.parse( "/some/path/to/advanced_conf.txt" ); // See advanced_conf.txt in 'example'.
+
+ view_options_values( configurator );
+ } catch ( const std::exception& exc ) {
+ std::cerr << exc.what() << std::endl;
+ }
+
+ return 0;
+}

Added: sandbox/configurator/libs/configurator/example/advanced_conf.txt
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/example/advanced_conf.txt 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,34 @@
+/*
+ * advanced_conf.txt
+ */
+
+DbName : my_database
+DbHost : localhost
+DbPort : 100
+DbUser : some_user
+DbPassword : some_password
+
+<Server>
+ Host : 12.45.46.15 // IP semantics will be check.
+ Port : 1080 // Value must be integer number.
+ Admin/*this is comment with unnecessary info
+ asdfasdfasdfasdfasdfasdffasdffasdfasdfasdasd
+ asf*/istrator : admin_at_[hidden] // e-mail semantics will be check.
+
+ StorePath : /some/path // path semantics will be check.
+
+ <Internal>
+ Logfile : /some/path/to/logfile // optional path semantics will be check.
+ MaxLogFileSize : 10 MB // size semantics will be check.
+ </Internal>
+
+ ReconnectPeriod : 10 s // time period semantics will be check.
+</Server>
+
+<Plugins>
+ // plugins is option with multivalues.
+ plugins : a_plug b_plug
+ plugins : c_plug
+ plugins : d_plug
+ plugins : e_plug
+</Plugins>

Added: sandbox/configurator/libs/configurator/example/hello_world.cpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/example/hello_world.cpp 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,26 @@
+// Example of simplest usage of Configurator library.
+//
+// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
+//
+// Distributed under the Boost Software License, version 1.0
+// (see http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/configurator/configurator.hpp>
+
+#include <iostream>
+
+int main( int argc, char* argv[] ) {
+ try {
+ boost::cf::configurator conf;
+ conf.add_option( "Host" );
+
+ conf.load( "/some/path/to/hello_world_conf.txt" ); // See hello_world_conf.txt in 'example'.
+
+ std::string value_of_host = conf.get_value( "Host" );
+ std::cout << "Value of host: " << value_of_host << std::endl;
+ } catch ( const std::exception& exc ) {
+ std::cerr << exc.what() << std::endl;
+ }
+
+ return 0;
+}

Added: sandbox/configurator/libs/configurator/example/hello_world_conf.txt
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/example/hello_world_conf.txt 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,2 @@
+// hello_world_conf.txt
+Host = 127.0.0.1

Added: sandbox/configurator/libs/configurator/index.html
==============================================================================
--- (empty file)
+++ sandbox/configurator/libs/configurator/index.html 2010-12-02 08:09:22 EST (Thu, 02 Dec 2010)
@@ -0,0 +1,79 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+ <link rel="stylesheet" type="text/css" href="../../../boost.css">
+
+ <title>Configurator</title>
+<link rel="icon" href="/favicon.ico" type="image/ico"><link rel="stylesheet" type="text/css" href="/style-v2/section-basic.css"></head>
+
+<body link="#0000FF" vlink="#800080"> <div id="boost-common-heading-doc">
+ <div class="heading-inner">
+ <div class="heading-placard"></div>
+
+ <h1 class="heading-title">
+ <a href="/">
+ <img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
+ <span class="heading-boost">Boost</span>
+ <span class="heading-cpplibraries">C++ Libraries</span>
+ </a></h1>
+
+ <p class="heading-quote">
+ <q>...one of the most highly
+ regarded and expertly designed C++ library projects in the
+ world.</q> <span class="heading-attribution">&mdash; <a href=
+ "http://www.gotw.ca/" class="external">Herb Sutter</a> and <a href=
+ "http://en.wikipedia.org/wiki/Andrei_Alexandrescu" class="external">Andrei
+ Alexandrescu</a>, <a href=
+ "http://safari.awprofessional.com/?XmlId=0321113586" class="external">C++
+ Coding Standards</a></span></p>
+
+ <div class="heading-sections">
+ <ul>
+ <li class="welcome-section-tab">Welcome</li>
+ <li class="boost-section-tab">Introduction</li>
+ <li class="community-section-tab">Community</li>
+ <li class="development-section-tab">Development</li>
+ <li class="support-section-tab">Support</li>
+ <li class="doc-section-tab">Documentation</li>
+ </ul>
+ </div>
+</div>
+ </div>
+
+ <div id="boost-common-heading-doc-spacer"></div>
+
+
+ <h1 align="center">Configurator</h1>
+
+ <h2 align="center">0.9.2</h2>
+ <h2>Contents</h2>
+
+ <dl class="index">
+ <dt>Rationale</dt>
+ <dt>Overview</dt>
+ <dt>Acknowledgments</dt>
+ </dl>
+
+ <hr/>
+ <br/>
+ This document describes Configurator, flexible and easy-to-use library for configuration file parsing.
+ <br/>
+ This is first version of documentation, future documentation will significantly improve.
+ <br/>
+ <hr/>
+
+ <p>Revised
+ <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->30
+ November, 2010<!--webbot bot="Timestamp" endspan i-checksum="38514" --></p>
+
+ <p><i>Copyright &copy; 2010 Denis Shevchenko</i></p>
+
+ <p><i>Distributed under the Boost Software License, Version 1.0. (See
+ accompanying file LICENSE_1_0.txt or
+ copy at <a href=
+ "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
+</body>
+</html>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk