|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r67205 - in sandbox/configurator: boost/configurator boost/configurator/detail libs/configurator/doc
From: for.dshevchenko_at_[hidden]
Date: 2010-12-13 02:33:53
Author: dshevchenko
Date: 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
New Revision: 67205
URL: http://svn.boost.org/trac/boost/changeset/67205
Log:
Change value semantics API to type-based instead enum-based.
Added:
sandbox/configurator/boost/configurator/detail/value_semantics.hpp (contents, props changed)
Text files modified:
sandbox/configurator/boost/configurator/configurator.hpp | 6
sandbox/configurator/boost/configurator/configurator_settings.hpp | 9
sandbox/configurator/boost/configurator/detail/misc.hpp | 15 --
sandbox/configurator/boost/configurator/detail/semantics_checker.hpp | 1
sandbox/configurator/boost/configurator/option.hpp | 24 ---
sandbox/configurator/libs/configurator/doc/advanced_usage.html | 299 ++++++++++++++-------------------------
sandbox/configurator/libs/configurator/doc/common_usage.html | 50 ++++--
7 files changed, 147 insertions(+), 257 deletions(-)
Modified: sandbox/configurator/boost/configurator/configurator.hpp
==============================================================================
--- sandbox/configurator/boost/configurator/configurator.hpp (original)
+++ sandbox/configurator/boost/configurator/configurator.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -10,7 +10,7 @@
#define BOOST_CONFIGURATOR_HPP
#include <boost/configurator/macro.hpp>
-#include <boost/configurator/detail/configurator_settings.hpp>
+#include <boost/configurator/configurator_settings.hpp>
#include <boost/configurator/detail/validators.hpp>
#include <boost/configurator/detail/type_name.hpp>
#include <boost/configurator/detail/pure_option.hpp>
@@ -56,9 +56,9 @@
private:
const std::string sections_separator;
private:
- detail::configurator_settings settings_of_configurator;
+ configurator_settings settings_of_configurator;
public:
- detail::configurator_settings& settings() {
+ configurator_settings& settings() {
return settings_of_configurator;
}
public:
Modified: sandbox/configurator/boost/configurator/configurator_settings.hpp
==============================================================================
--- sandbox/configurator/boost/configurator/configurator_settings.hpp (original)
+++ sandbox/configurator/boost/configurator/configurator_settings.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -1,5 +1,5 @@
-// detail/configurator_settings.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// configurator_settings.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (C) 2010 Denis Shevchenko (for @ dshevchenko.biz)
//
@@ -20,10 +20,6 @@
/// \brief Main namespace of library.
namespace cf {
-/// \namespace cf::detail
-/// \brief Details of realization.
-namespace detail {
-
///
struct configurator_settings {
configurator_settings() :
@@ -63,7 +59,6 @@
//
};
-} // namespace detail
} // namespace cf
} // namespace boost
Modified: sandbox/configurator/boost/configurator/detail/misc.hpp
==============================================================================
--- sandbox/configurator/boost/configurator/detail/misc.hpp (original)
+++ sandbox/configurator/boost/configurator/detail/misc.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -39,21 +39,6 @@
/// \brief Details of realization.
namespace detail {
-/// \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. */
-};
-
inline std::string sections_separator_for_log() { return " > "; }
template
Modified: sandbox/configurator/boost/configurator/detail/semantics_checker.hpp
==============================================================================
--- sandbox/configurator/boost/configurator/detail/semantics_checker.hpp (original)
+++ sandbox/configurator/boost/configurator/detail/semantics_checker.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -15,6 +15,7 @@
#ifdef WITH_SEMANTIC_CHECK
#include <boost/configurator/detail/validators.hpp>
+#include <boost/configurator/detail/value_semantics.hpp>
#include <boost/function.hpp>
#include <boost/assign.hpp>
#include <boost/bind.hpp>
Added: sandbox/configurator/boost/configurator/detail/value_semantics.hpp
==============================================================================
--- (empty file)
+++ sandbox/configurator/boost/configurator/detail/value_semantics.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -0,0 +1,66 @@
+// detail/value_semantics.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// 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_VALUE_SEMANTICS_HPP
+#define BOOST_CONFIGURATOR_VALUE_SEMANTICS_HPP
+
+namespace boost {
+
+/// \namespace cf
+/// \brief Main namespace of library.
+namespace cf {
+
+/// \namespace cf::detail
+/// \brief Details of realization.
+namespace detail {
+
+/// \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. */
+};
+
+///
+struct common_semantic {
+ explicit common_semantic( const detail::value_semantic& _semantic ) :
+ semantic( _semantic ) {}
+public:
+ const detail::value_semantic semantic;
+};
+
+#define BOOST_CONFIGURATOR_SEMANTIC( type ) \
+ struct type : public detail::common_semantic { \
+ type() : detail::common_semantic( detail::type ) {} \
+ };
+
+} // namespace detail
+
+BOOST_CONFIGURATOR_SEMANTIC( no_semantic )
+BOOST_CONFIGURATOR_SEMANTIC( path )
+BOOST_CONFIGURATOR_SEMANTIC( optional_path )
+BOOST_CONFIGURATOR_SEMANTIC( ipv4 )
+BOOST_CONFIGURATOR_SEMANTIC( ipv6 )
+BOOST_CONFIGURATOR_SEMANTIC( ip )
+BOOST_CONFIGURATOR_SEMANTIC( email )
+BOOST_CONFIGURATOR_SEMANTIC( size )
+BOOST_CONFIGURATOR_SEMANTIC( time_period )
+BOOST_CONFIGURATOR_SEMANTIC( exp_record )
+
+} // namespace cf
+} // namespace boost
+
+#endif // BOOST_CONFIGURATOR_VALUE_SEMANTICS_HPP
Modified: sandbox/configurator/boost/configurator/option.hpp
==============================================================================
--- sandbox/configurator/boost/configurator/option.hpp (original)
+++ sandbox/configurator/boost/configurator/option.hpp 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -10,6 +10,7 @@
#define BOOST_CONFIGURATOR_OPTION_HPP
#include <boost/configurator/detail/misc.hpp>
+#include <boost/configurator/detail/value_semantics.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
namespace boost {
@@ -18,29 +19,6 @@
/// \brief Main namespace of library.
namespace cf {
-struct common_semantic {
- explicit common_semantic( const detail::value_semantic& _semantic ) :
- semantic( _semantic ) {}
-public:
- const detail::value_semantic semantic;
-};
-
-#define BOOST_CONFIGURATOR_SEMANTIC( type ) \
- struct type : public boost::cf::common_semantic { \
- type() : boost::cf::common_semantic( boost::cf::detail::type ) {} \
- };
-
-BOOST_CONFIGURATOR_SEMANTIC( no_semantic )
-BOOST_CONFIGURATOR_SEMANTIC( path )
-BOOST_CONFIGURATOR_SEMANTIC( optional_path )
-BOOST_CONFIGURATOR_SEMANTIC( ipv4 )
-BOOST_CONFIGURATOR_SEMANTIC( ipv6 )
-BOOST_CONFIGURATOR_SEMANTIC( ip )
-BOOST_CONFIGURATOR_SEMANTIC( email )
-BOOST_CONFIGURATOR_SEMANTIC( size )
-BOOST_CONFIGURATOR_SEMANTIC( time_period )
-BOOST_CONFIGURATOR_SEMANTIC( exp_record )
-
///
struct option {
option() {}
Modified: sandbox/configurator/libs/configurator/doc/advanced_usage.html
==============================================================================
--- sandbox/configurator/libs/configurator/doc/advanced_usage.html (original)
+++ sandbox/configurator/libs/configurator/doc/advanced_usage.html 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -24,59 +24,95 @@
<h2>Advanced usage</h2>
+ <dl class="index">
+ <dt>Option's default value</dt>
+ <dt>Option's necessity</dt>
+ <dt>Semantic of option's value</dt>
+ <dt>Multi values for option</dt>
+ <dt>Case sensitivity for names</dt>
+ <dt>Non-string values obtating</dt>
+ </dl>
+
+
+ <h3><a name="default_values"></a>Option's default value</h3>
+
+ Very often useful to define some default value for option, especially for big configuration files. Let's do it:
+<pre class="cpp">
+ // ...
+ conf.add< UdpHost >().set_default_value( "127.0.0.1" );
+ conf.add< UdpPort >().set_default_value( 100 );
+ // ...
+</pre>
+In this case user can skip these options in configuration file. Now write:
+<pre class="cpp">
+ // ...
+ std::cout << "Udp host: " << conf.get_value_of< UdpHost >() << std::endl;
+ std::cout << "Udp port: " << conf.get_value_of< UdpPort >() << std::endl;
+ // ...
+</pre>
+If we have such config:
+<pre class="config">
+UdpHost = 12.34.56.78
+UdpPort = 103
+</pre>
+console output:
+<pre class="terminal">
+Udp host: 12.34.56.78
+Udp port: 103
+</pre>
+But if we comment out:
+<pre class="config">
+// UdpHost = 12.34.56.78
+// UdpPort = 103
+</pre>
+console output changed:
+<pre class="terminal">
+Udp host: 127.0.0.1
+Udp port: 100
+</pre>
-
-
-
-
-
-
-
-
-
-
-
-
-<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;
+ <br/>
+ <h3><a name="necessity"></a>Option's necessity</h3>
+
+ No less frequently useful to define necessity of some options, because it can be mandatory for program. Let's do it:
+<pre class="cpp">
// ...
- conf.in( "Server" ).add_here( "Host" ).necessary();
+ conf.add< UdpHost >().set_necessity();
// ...
-}
</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;
+In this case user <strong><em>must</em></strong> inputs this option in configuration file. If not, he get error message like this:
+<pre class="terminal">
+[Configurator] Option 'UdpHost' is defined as necessary, but it missed!
+</pre>
+
+ <br/>
+ <h3><a name="semantic"></a>Semantic of option's value</h3>
+
+ Many options must be set to appropriate some semantics. Considering the fact that some values is "internationally known and unchanging essence", such check added in library, so possible errors will be detected already at the stage of parsing.
+<br/><br/>
+ For example, we may want that value of <strong>UdpHost</strong> will be valid IPv4.
+<pre class="cpp">
// ...
- conf.in( "Server" ).add_here( "Host" ).default_value( "127.0.0.1" );
+ conf.add< UdpHost >().check_semantic( boost::cf::ipv4 );
// ...
-}
</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;
+So:
+<pre class="cpp">
// ...
- conf.in( "Server" ).add_here( "Host" ).check_semantic( boost::cf::ip );
+ std::cout << "Udp host: " << conf.get_value_of< UdpHost >() << std::endl;
// ...
-}
</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/>
+If value in configuration file is incorrect:
+<pre class="config">
+UdpHost = 1233.34.56.78
+</pre>
+user get error message like this:
+<pre class="terminal">
+[Configurator] Semantic error: option 'UdpHost' has invalid 'IPv4' value '1233.34.56.78'!
+</pre>
+Supported semantic:
+
+
<br/>
<strong>IMPORTANT!</strong>
<br/>
@@ -84,7 +120,30 @@
<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.
+Note that only in this case you must link <strong>boost_system</strong> and <strong>boost_regex</strong> libraries. You only pay for what you use.
+
+
+
+
+
+ <br/><br/>
+ <h3><a name="multi_values"></a>Multi values for option</h3>
+
+
+ <br/><br/>
+ <h3><a name="case_sensitivity"></a>Case sensitivity for names</h3>
+
+
+ <br/><br/>
+ <h3><a name="values_obtaining"></a>Non-string values obtating</h3>
+
+
+
+
+
+
+
+
<a name="combine_options_settings"><h3>Combine settings</h3></a>
Of course, you can combine settings for option:
@@ -289,157 +348,11 @@
</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>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
<br/><br/>
<hr/>
Last revised
Modified: sandbox/configurator/libs/configurator/doc/common_usage.html
==============================================================================
--- sandbox/configurator/libs/configurator/doc/common_usage.html (original)
+++ sandbox/configurator/libs/configurator/doc/common_usage.html 2010-12-13 02:33:46 EST (Mon, 13 Dec 2010)
@@ -125,8 +125,9 @@
<pre class="terminal">
Udp host: 12.34.56.78
</pre>
+By default function <strong>get_value_of</strong> returns pure-string value. Other obtating ways see in Non-string values obtating.
- <br/>
+ <br/><br/>
<h3><a name="concepts_vs_location"></a>Concepts vs location</h3>
As mentioned above, every option considered from two points of view: concept and location. And, strictly speaking, these points of view is not related to each other. So you specify (as you remember, this is not necessarily) location only in one place (during option adding), and in all other places of the program you will not think about it.
@@ -164,20 +165,22 @@
return 0;
}
-
-// some_second_file.cpp
- void logger() {
- // ...
- std::string path_to_log = conf.get_value_of< ReserveLogForSystem >();
- // ...
- }
-
-// some_third_file.cpp
- void size_checker() {
- // ...
- std::string path_to_log = conf.get_value_of< ReserveLogForSystem >();
- // ...
- }
+</pre>
+In some second .cpp
+<pre class="cpp">
+void logger() {
+ // ...
+ std::string path_to_log = conf.get_value_of< ReserveLogForSystem >();
+ // ...
+}
+</pre>
+In some third .cpp
+<pre class="cpp">
+void size_checker() {
+ // ...
+ std::string path_to_log = conf.get_value_of< ReserveLogForSystem >();
+ // ...
+}
</pre>
But what if we want to change loaction of this option? It may be renaming or re-nesting, for example:
<pre class="config">
@@ -190,7 +193,22 @@
// ...
</ReserveServer>
</pre>
- In this case we must rewrite path <strong>"ReserveServer::System::Log"</strong> only in one place, and other parts of the program will not even know about this change, because concept <strong>ReserveLogForSystem</strong> not changed.
+ In this case we must rewrite path <strong>"ReserveServer::System::Log"</strong> only in one place:
+<pre class="cpp">
+int main( int argc, char* argv[] ) {
+ try {
+ // ...
+ conf.add< ReserveLogForSystem >().set_location( "ReserveServer::System::Log" );
+ // ...
+ } catch ( const std::exception& exc ) {
+ std::cerr << exc.what() << std::endl;
+ }
+
+ return 0;
+}
+</pre>
+
+and other parts of the program will not even know about this change, because concept <strong>ReserveLogForSystem</strong> not changed.
<br/><br/>
In addition we use type instead string identifier, so any spelling error will be checked on compile-time, not on runtime.
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