mirror of
https://github.com/boostorg/program_options.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
35 Commits
svn-branch
...
boost-1.36
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0a1de7595 | ||
|
|
2a16575f98 | ||
|
|
f14a369077 | ||
|
|
9df5124fed | ||
|
|
86487c7b63 | ||
|
|
6cd68a2fd9 | ||
|
|
f0eae2ccfe | ||
|
|
b2a01d9405 | ||
|
|
2d0c627d34 | ||
|
|
2cc29f6dfa | ||
|
|
198b29d107 | ||
|
|
f407b6ce47 | ||
|
|
87938cfa8e | ||
|
|
9a73a1c412 | ||
|
|
37143a449d | ||
|
|
2e0e9fd30b | ||
|
|
1bd588d677 | ||
|
|
d83e0dea37 | ||
|
|
54daca4c09 | ||
|
|
f4eac99310 | ||
|
|
a367a1b021 | ||
|
|
720d0455dd | ||
|
|
aad1a60172 | ||
|
|
1e4d1dee3d | ||
|
|
e718d0a8a5 | ||
|
|
ab30ec28eb | ||
|
|
682f1b7670 | ||
|
|
43577d0ca8 | ||
|
|
d05b400b13 | ||
|
|
4863727509 | ||
|
|
7d90a1b1b2 | ||
|
|
ac9830625b | ||
|
|
252a3f9ebd | ||
|
|
b1dc87da3c | ||
|
|
1fbf955272 |
@@ -1,49 +0,0 @@
|
||||
|
||||
subproject libs/program_options/build ;
|
||||
|
||||
SOURCES = cmdline config_file options_description parsers variables_map
|
||||
value_semantic positional_options utf8_codecvt_facet convert
|
||||
winmain
|
||||
;
|
||||
|
||||
lib boost_program_options
|
||||
: ../src/$(SOURCES).cpp
|
||||
: # build requirements
|
||||
[ common-names ] # magic for install and auto-link features
|
||||
<include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)
|
||||
std::locale-support
|
||||
: debug release # build variants
|
||||
;
|
||||
|
||||
dll boost_program_options
|
||||
: ../src/$(SOURCES).cpp
|
||||
: # build requirements
|
||||
[ common-names ] # magic for install and auto-link features
|
||||
<define>BOOST_ALL_DYN_LINK=1 # tell source we're building dll's
|
||||
<runtime-link>dynamic # build only for dynamic runtimes
|
||||
<include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)
|
||||
# The following really turns on static runtime linking
|
||||
# which leads to runtime crashes when using DLL, so
|
||||
# seem DLL is not usable on Metrowerks 8
|
||||
# std::facet-support std::locale-support
|
||||
: debug release # build variants
|
||||
;
|
||||
|
||||
install program_options lib
|
||||
: <lib>boost_program_options <dll>boost_program_options
|
||||
;
|
||||
|
||||
stage stage/lib : <lib>boost_program_options <dll>boost_program_options
|
||||
:
|
||||
# copy to a path rooted at BOOST_ROOT:
|
||||
<locate>$(BOOST_ROOT)
|
||||
# make sure the names of the libraries are correctly named:
|
||||
[ common-names ]
|
||||
# add this target to the "stage" and "all" psuedo-targets:
|
||||
<target>stage
|
||||
<target>all
|
||||
:
|
||||
debug release
|
||||
;
|
||||
|
||||
# end
|
||||
@@ -17,12 +17,4 @@ lib boost_program_options
|
||||
<link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1 # tell source we're building dll's
|
||||
;
|
||||
|
||||
install dist-lib
|
||||
:
|
||||
boost_program_options
|
||||
:
|
||||
<install-type>LIB
|
||||
<location>../../../dist/lib
|
||||
;
|
||||
|
||||
explicit dist-lib ;
|
||||
boost-install boost_program_options ;
|
||||
@@ -2,7 +2,10 @@
|
||||
import toolset ;
|
||||
toolset.using doxygen ;
|
||||
|
||||
boostbook program_option : program_options.xml ;
|
||||
boostbook program_option
|
||||
: program_options.xml
|
||||
: <implicit-dependency>autodoc
|
||||
;
|
||||
|
||||
doxygen autodoc
|
||||
: [ glob ../../../boost/program_options/*.hpp ] ;
|
||||
@@ -412,7 +412,7 @@ $ export LC_CTYPE=ru_RU.KOI8-R
|
||||
method of that class:
|
||||
<programlisting>
|
||||
parsed_options parsed =
|
||||
command_line_parser(argv, argc).options(desc).allow_unregistered().run();
|
||||
command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||
</programlisting>
|
||||
|
||||
For each token that looks like an option, but does not have a known name,
|
||||
@@ -427,7 +427,7 @@ parsed_options parsed =
|
||||
The function will collect original tokens for all unrecognized values, and optionally, all found positional options.
|
||||
Say, if your code handles a few options, but does not handles positional options at all, you can use the function like this:
|
||||
<programlisting>
|
||||
vector<string> to_pass_further = collect_arguments(parsed.option, include_positional);
|
||||
vector<string> to_pass_further = collect_unrecognized(parsed.options, include_positional);
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
|
||||
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -181,7 +181,7 @@ options_description desc;
|
||||
desc.add_options()
|
||||
("help", "produce help message")
|
||||
("compression", value<string>(), "compression level")
|
||||
("verbose", value<string>()->zero_token(), "verbosity level")
|
||||
("verbose", value<string>()->zero_tokens(), "verbosity level")
|
||||
("email", value<string>()->multitoken(), "email to send to")
|
||||
;
|
||||
</programlisting>
|
||||
@@ -348,7 +348,7 @@ positional_options_description pd; pd.add("input-file", 1);
|
||||
given the same name.
|
||||
<programlisting>
|
||||
positional_options_description pd;
|
||||
pd.add("output-file", 2).add_optional("input-file", -1);
|
||||
pd.add("output-file", 2).add("input-file", -1);
|
||||
</programlisting>
|
||||
In the above example, the first two positional options will be associated
|
||||
with name "output-file", and any others with the name "input-file".
|
||||
@@ -478,7 +478,45 @@ notify(vm);
|
||||
<title>Specific parsers</title>
|
||||
|
||||
<section>
|
||||
<title>Environment variables</title>
|
||||
<title>Configuration file parser</title>
|
||||
|
||||
<para>The &parse_config_file; function implements parsing
|
||||
of simple INI-like configuration files. Configuration file
|
||||
syntax is line based:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>A line in the form:</para>
|
||||
<screen>
|
||||
<replaceable>name</replaceable>=<replaceable>value</replaceable>
|
||||
</screen>
|
||||
<para>gives a value to an option.</para>
|
||||
</listitem>
|
||||
<listitem><para>A line in the form:</para>
|
||||
<screen>
|
||||
[<replaceable>section name</replaceable>]
|
||||
</screen>
|
||||
<para>introduces a new section in the configuration file.</para>
|
||||
</listitem>
|
||||
<listitem><para>The <literal>#</literal> character introduces a
|
||||
comment that spans until the end of the line.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>The option names are relative to the section names, so
|
||||
the following configuration file part:</para>
|
||||
<screen>
|
||||
[gui.accessibility]
|
||||
visual_bell=yes
|
||||
</screen>
|
||||
<para>is equivalent to</para>
|
||||
<screen>
|
||||
gui.accessibility.visual_bell=yes
|
||||
</screen>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Environment variables parser</title>
|
||||
|
||||
<para><firstterm>Environment variables</firstterm> are string variables
|
||||
which are available to all programs via the <code>getenv</code> function
|
||||
|
||||
@@ -83,5 +83,5 @@
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="acknowledgements.xml"/>
|
||||
|
||||
<xi:include href="autodoc.boostbook"/>
|
||||
<xi:include href="autodoc.xml"/>
|
||||
</library>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
Say that variables_map is actually derived from std::map.
|
||||
|
||||
Make parse_config_file("foo.cfg", desc) work.
|
||||
|
||||
Document handling of positional options which depends on precedding options.
|
||||
|
||||
@@ -96,7 +96,7 @@ Compression level was set to 10.
|
||||
<para>An option value, surely, can have other types than <code>int</code>, and
|
||||
can have other interesting properties, which we'll discuss right now. The
|
||||
complete version of the code snipped below can be found in
|
||||
"example/options_description.cpp".</para>
|
||||
<filename>example/options_description.cpp</filename>.</para>
|
||||
|
||||
<para>Imagine we're writing a compiler. It should take the optimization
|
||||
level, a number of include paths, and a number of input files, and perform some
|
||||
@@ -115,21 +115,29 @@ desc.add_options()
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
<para>The "--help" option should be familiar from the previous example.
|
||||
It's a good idea to have this option in all cases.</para>
|
||||
<para>The <literal>"help"</literal> option should be familiar from
|
||||
the previous example. It's a good idea to have this option in all cases.
|
||||
</para>
|
||||
|
||||
<para>The "optimization" option shows two new features. First, we specify
|
||||
<para>The <literal>"optimization"</literal> option shows two new features. First, we specify
|
||||
the address of the variable(<code>&opt</code>). After storing values, that
|
||||
variable will have the value of the option. Second, we specify a default
|
||||
value of 10, which will be used if no value is specified by the user.
|
||||
</para>
|
||||
|
||||
<para>The "include-path" option is an example of the only case where
|
||||
the interface of the <code>options_description</code> class serves only one
|
||||
<para>The <literal>"include-path"</literal> option is an example of the
|
||||
only case where the interface of the <code>options_description</code>
|
||||
class serves only one
|
||||
source -- the command line. Users typically like to use short option names
|
||||
for common options, and the "include-path,I" name specifies that short
|
||||
option name is "I". So, both "--include-path" and "-I" can be used.
|
||||
</para>
|
||||
|
||||
<para>Note also that the type of the <literal>"include-path"</literal>
|
||||
option is <type>std::vector</type>. The library provides special
|
||||
support for vectors -- it will be possible to specify the option several
|
||||
times, and all specified values will be collected in one vector.
|
||||
</para>
|
||||
|
||||
<para>The "input-file" option specifies the list of files to
|
||||
process. That's okay for a start, but, of course, writing something like:
|
||||
@@ -337,7 +345,7 @@ Optimization level is 4
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
mode: nxml
|
||||
sgml-indent-data: t
|
||||
sgml-parent-document: ("program_options.xml" "section")
|
||||
sgml-set-face: t
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
subproject libs/program_options/example ;
|
||||
|
||||
rule program-options-example ( name extra-sources * )
|
||||
{
|
||||
exe $(name) : $(name).cpp <lib>../build/boost_program_options $(extra-sources)
|
||||
: <include>$(BOOST_ROOT) ;
|
||||
}
|
||||
|
||||
program-options-example first ;
|
||||
program-options-example options_description ;
|
||||
program-options-example multiple_sources ;
|
||||
program-options-example custom_syntax ;
|
||||
program-options-example response_file ;
|
||||
program-options-example option_groups ;
|
||||
program-options-example real ;
|
||||
program-options-example regex <lib>../../regex/build/boost_regex ;
|
||||
|
||||
|
||||
#program-options-example prefix ;
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
project
|
||||
: requirements <library>../build//program_options
|
||||
: requirements <library>../build//boost_program_options
|
||||
<hardcode-dll-paths>true
|
||||
;
|
||||
|
||||
@@ -9,7 +9,5 @@ exe options_description : options_description.cpp ;
|
||||
exe multiple_sources : multiple_sources.cpp ;
|
||||
exe custom_syntax : custom_syntax.cpp ;
|
||||
|
||||
exe a : a.cpp ;
|
||||
|
||||
#exe real : real.cpp ;
|
||||
#exe regex : regex.cpp /boost/regex//boost_regex ;
|
||||
exe real : real.cpp ;
|
||||
exe regex : regex.cpp /boost/regex//boost_regex ;
|
||||
|
||||
@@ -26,11 +26,17 @@ int main(int ac, char* av[])
|
||||
{
|
||||
try {
|
||||
int opt;
|
||||
int portnum;
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help", "produce help message")
|
||||
("optimization", po::value<int>(&opt)->default_value(10),
|
||||
"optimization level")
|
||||
("verbose,v", po::value<int>()->implicit_value(1),
|
||||
"enable verbosity (optionally specify level)")
|
||||
("listen,l", po::value<int>(&portnum)->implicit_value(1001)
|
||||
->default_value(0,"no"),
|
||||
"listen on a port.")
|
||||
("include-path,I", po::value< vector<string> >(),
|
||||
"include path")
|
||||
("input-file", po::value< vector<string> >(), "input file")
|
||||
@@ -62,7 +68,14 @@ int main(int ac, char* av[])
|
||||
<< vm["input-file"].as< vector<string> >() << "\n";
|
||||
}
|
||||
|
||||
if (vm.count("verbose")) {
|
||||
cout << "Verbosity enabled. Level is " << vm["verbose"].as<int>()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
cout << "Optimization level is " << opt << "\n";
|
||||
|
||||
cout << "Listen port is " << portnum << "\n";
|
||||
}
|
||||
catch(exception& e)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See www.boost.org/libs/program_options for documentation.
|
||||
|
||||
#ifndef PROGRAM_OPTIONS_VP_2003_05_19
|
||||
#define PROGRAM_OPTIONS_VP_2003_05_19
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace boost { namespace program_options { namespace command_line_style {
|
||||
There are "long" options, which start with "--" and "short",
|
||||
which start with either "-" or "/". Both kinds can be allowed or
|
||||
disallowed, see allow_long and allow_short. The allowed character
|
||||
for short option is also configurable.
|
||||
for short options is also configurable.
|
||||
|
||||
Option's value can be specified in the same token as value
|
||||
Option's value can be specified in the same token as name
|
||||
("--foo=bar"), or in the next token.
|
||||
|
||||
It's possible to introduce long option by the same character as
|
||||
long option, see allow_long_disguise.
|
||||
It's possible to introduce long options by the same character as
|
||||
short options, see allow_long_disguise.
|
||||
|
||||
Finally, guessing (specifying only prefix of option) and case
|
||||
insensitive processing are supported.
|
||||
@@ -39,7 +39,7 @@ namespace boost { namespace program_options { namespace command_line_style {
|
||||
@endverbatim
|
||||
*/
|
||||
long_allow_adjacent = allow_slash_for_short << 1,
|
||||
/** Allow option parameter in the same token for
|
||||
/** Allow option parameter in the next token for
|
||||
long options. */
|
||||
long_allow_next = long_allow_adjacent << 1,
|
||||
/** Allow option parameter in the same token for
|
||||
@@ -59,7 +59,7 @@ namespace boost { namespace program_options { namespace command_line_style {
|
||||
/** Allow abbreviated spellings for long options,
|
||||
if they unambiguously identify long option.
|
||||
No long option name should be prefix of other
|
||||
long option name is guessing is in effect.
|
||||
long option name if guessing is in effect.
|
||||
*/
|
||||
allow_guessing = allow_sticky << 1,
|
||||
/** Ignore the difference in case for options.
|
||||
|
||||
@@ -70,7 +70,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
public:
|
||||
common_config_file_iterator() { found_eof(); }
|
||||
common_config_file_iterator(
|
||||
const std::set<std::string>& allowed_options);
|
||||
const std::set<std::string>& allowed_options,
|
||||
bool allow_unregistered = false);
|
||||
|
||||
virtual ~common_config_file_iterator() {}
|
||||
|
||||
@@ -103,6 +104,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
// Invariant: no element is prefix of other element.
|
||||
std::set<std::string> allowed_prefixes;
|
||||
std::string m_prefix;
|
||||
bool m_allow_unregistered;
|
||||
};
|
||||
|
||||
template<class charT>
|
||||
@@ -116,7 +118,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
/** Creates a config file parser for the specified stream.
|
||||
*/
|
||||
basic_config_file_iterator(std::basic_istream<charT>& is,
|
||||
const std::set<std::string>& allowed_options);
|
||||
const std::set<std::string>& allowed_options,
|
||||
bool allow_unregistered = false);
|
||||
|
||||
private: // base overrides
|
||||
|
||||
@@ -139,8 +142,9 @@ namespace boost { namespace program_options { namespace detail {
|
||||
template<class charT>
|
||||
basic_config_file_iterator<charT>::
|
||||
basic_config_file_iterator(std::basic_istream<charT>& is,
|
||||
const std::set<std::string>& allowed_options)
|
||||
: common_config_file_iterator(allowed_options)
|
||||
const std::set<std::string>& allowed_options,
|
||||
bool allow_unregistered)
|
||||
: common_config_file_iterator(allowed_options, allow_unregistered)
|
||||
{
|
||||
this->is.reset(&is, null_deleter());
|
||||
get();
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace boost { namespace program_options {
|
||||
: detail::cmdline(
|
||||
// Explicit template arguments are required by gcc 3.3.1
|
||||
// (at least mingw version), and do no harm on other compilers.
|
||||
to_internal(detail::make_vector<charT, charT**>(argv+1, argv+argc)))
|
||||
to_internal(detail::make_vector<charT, charT**>(argv+1, argv+argc+!argc)))
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright © 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
|
||||
// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
|
||||
// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). Permission to copy,
|
||||
// use, modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided "as is"
|
||||
|
||||
@@ -16,7 +16,13 @@ namespace boost { namespace program_options {
|
||||
std::string
|
||||
typed_value<T, charT>::name() const
|
||||
{
|
||||
if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
|
||||
if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
|
||||
std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]";
|
||||
if (!m_default_value.empty() && !m_default_value_as_text.empty())
|
||||
msg += " (=" + m_default_value_as_text + ")";
|
||||
return msg;
|
||||
}
|
||||
else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
|
||||
return arg + " (=" + m_default_value_as_text + ")";
|
||||
} else {
|
||||
return arg;
|
||||
@@ -134,7 +140,14 @@ namespace boost { namespace program_options {
|
||||
for (unsigned i = 0; i < s.size(); ++i)
|
||||
{
|
||||
try {
|
||||
tv->push_back(boost::lexical_cast<T>(s[i]));
|
||||
/* We call validate so that if user provided
|
||||
a validator for class T, we use it even
|
||||
when parsing vector<T>. */
|
||||
boost::any a;
|
||||
std::vector<std::basic_string<charT> > v;
|
||||
v.push_back(s[i]);
|
||||
validate(a, v, (T*)0, 0);
|
||||
tv->push_back(boost::any_cast<T>(a));
|
||||
}
|
||||
catch(const bad_lexical_cast& /*e*/) {
|
||||
boost::throw_exception(invalid_option_value(s[i]));
|
||||
@@ -148,7 +161,13 @@ namespace boost { namespace program_options {
|
||||
xparse(boost::any& value_store,
|
||||
const std::vector<std::basic_string<charT> >& new_tokens) const
|
||||
{
|
||||
validate(value_store, new_tokens, (T*)0, 0);
|
||||
// If no tokens were given, and the option accepts an implicit
|
||||
// value, then assign the implicit value as the stored value;
|
||||
// otherwise, validate the user-provided token(s).
|
||||
if (new_tokens.empty() && !m_implicit_value.empty())
|
||||
value_store = m_implicit_value;
|
||||
else
|
||||
validate(value_store, new_tokens, (T*)0, 0);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -82,11 +82,12 @@ namespace boost { namespace program_options {
|
||||
validation_error(const std::string& what) : error(what) {}
|
||||
~validation_error() throw() {}
|
||||
void set_option_name(const std::string& option);
|
||||
|
||||
const char* what() const throw();
|
||||
private:
|
||||
mutable std::string m_message; // For on-demand formatting in 'what'
|
||||
std::string m_option_name; // The name of the option which
|
||||
// caused the exception.
|
||||
const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace program_options {
|
||||
*/
|
||||
class BOOST_PROGRAM_OPTIONS_DECL options_description {
|
||||
public:
|
||||
static const unsigned m_default_line_length = 80;
|
||||
static const unsigned m_default_line_length;
|
||||
|
||||
/** Creates the instance. */
|
||||
options_description(unsigned line_length = m_default_line_length);
|
||||
|
||||
@@ -153,7 +153,8 @@ namespace boost { namespace program_options {
|
||||
BOOST_PROGRAM_OPTIONS_DECL
|
||||
#endif
|
||||
basic_parsed_options<charT>
|
||||
parse_config_file(std::basic_istream<charT>&, const options_description&);
|
||||
parse_config_file(std::basic_istream<charT>&, const options_description&,
|
||||
bool allow_unregistered = false);
|
||||
|
||||
/** Controls if the 'collect_unregistered' function should
|
||||
include positional options, or not. */
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace boost { namespace program_options {
|
||||
No calls to 'add' can be made after call with 'max_value' equal to
|
||||
'-1'.
|
||||
*/
|
||||
void add(const char* name, int max_count);
|
||||
positional_options_description&
|
||||
add(const char* name, int max_count);
|
||||
|
||||
/** Returns the maximum number of positional options that can
|
||||
be present. Can return numeric_limits<unsigned>::max() to
|
||||
|
||||
@@ -204,6 +204,38 @@ namespace boost { namespace program_options {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Specifies an implicit value, which will be used
|
||||
if the option is given, but without an adjacent value.
|
||||
Using this implies that an explicit value is optional, but if
|
||||
given, must be strictly adjacent to the option, i.e.: '-ovalue'
|
||||
or '--option=value'. Giving '-o' or '--option' will cause the
|
||||
implicit value to be applied.
|
||||
*/
|
||||
typed_value* implicit_value(const T &v)
|
||||
{
|
||||
m_implicit_value = boost::any(v);
|
||||
m_implicit_value_as_text =
|
||||
boost::lexical_cast<std::string>(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Specifies an implicit value, which will be used
|
||||
if the option is given, but without an adjacent value.
|
||||
Using this implies that an explicit value is optional, but if
|
||||
given, must be strictly adjacent to the option, i.e.: '-ovalue'
|
||||
or '--option=value'. Giving '-o' or '--option' will cause the
|
||||
implicit value to be applied.
|
||||
Unlike the above overload, the type 'T' need not provide
|
||||
operator<< for ostream, but textual representation of default
|
||||
value must be provided by the user.
|
||||
*/
|
||||
typed_value* implicit_value(const T &v, const std::string& textual)
|
||||
{
|
||||
m_implicit_value = boost::any(v);
|
||||
m_implicit_value_as_text = textual;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Specifies a function to be called when the final value
|
||||
is determined. */
|
||||
typed_value* notifier(function1<void, const T&> f)
|
||||
@@ -243,7 +275,7 @@ namespace boost { namespace program_options {
|
||||
|
||||
unsigned min_tokens() const
|
||||
{
|
||||
if (m_zero_tokens) {
|
||||
if (m_zero_tokens || !m_implicit_value.empty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
@@ -301,6 +333,8 @@ namespace boost { namespace program_options {
|
||||
// as boost::optional to avoid unnecessary instantiations.
|
||||
boost::any m_default_value;
|
||||
std::string m_default_value_as_text;
|
||||
boost::any m_implicit_value;
|
||||
std::string m_implicit_value_as_text;
|
||||
bool m_composing, m_implicit, m_multitoken, m_zero_tokens;
|
||||
boost::function1<void, const T&> m_notifier;
|
||||
};
|
||||
|
||||
@@ -24,6 +24,29 @@ namespace boost { namespace program_options {
|
||||
class value_semantic;
|
||||
class variables_map;
|
||||
|
||||
// forward declaration
|
||||
|
||||
/** Stores in 'm' all options that are defined in 'options'.
|
||||
If 'm' already has a non-defaulted value of an option, that value
|
||||
is not changed, even if 'options' specify some value.
|
||||
*/
|
||||
BOOST_PROGRAM_OPTIONS_DECL
|
||||
void store(const basic_parsed_options<char>& options, variables_map& m,
|
||||
bool utf8 = false);
|
||||
|
||||
/** Stores in 'm' all options that are defined in 'options'.
|
||||
If 'm' already has a non-defaulted value of an option, that value
|
||||
is not changed, even if 'options' specify some value.
|
||||
This is wide character variant.
|
||||
*/
|
||||
BOOST_PROGRAM_OPTIONS_DECL
|
||||
void store(const basic_parsed_options<wchar_t>& options,
|
||||
variables_map& m);
|
||||
|
||||
|
||||
/** Runs all 'notify' function for options in 'm'. */
|
||||
BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
|
||||
|
||||
/** Class holding value of option. Contains details about how the
|
||||
value is set and allows to conveniently obtain the value.
|
||||
*/
|
||||
@@ -36,10 +59,15 @@ namespace boost { namespace program_options {
|
||||
|
||||
/** If stored value if of type T, returns that value. Otherwise,
|
||||
throws boost::bad_any_cast exception. */
|
||||
template<class T> const T& as() const;
|
||||
|
||||
/** @overload */
|
||||
template<class T> T& as();
|
||||
template<class T>
|
||||
const T& as() const {
|
||||
return boost::any_cast<const T&>(v);
|
||||
}
|
||||
/** @overload */
|
||||
template<class T>
|
||||
T& as() {
|
||||
return boost::any_cast<T&>(v);
|
||||
}
|
||||
|
||||
/// Returns true if no value is stored.
|
||||
bool empty() const;
|
||||
@@ -61,10 +89,10 @@ namespace boost { namespace program_options {
|
||||
// be easily accessible, so we need to store semantic here.
|
||||
shared_ptr<const value_semantic> m_value_semantic;
|
||||
|
||||
friend void BOOST_PROGRAM_OPTIONS_DECL
|
||||
store(const basic_parsed_options<char>& options,
|
||||
friend BOOST_PROGRAM_OPTIONS_DECL
|
||||
void store(const basic_parsed_options<char>& options,
|
||||
variables_map& m, bool);
|
||||
friend void BOOST_PROGRAM_OPTIONS_DECL notify(variables_map& m);
|
||||
friend BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
|
||||
};
|
||||
|
||||
/** Implements string->string mapping with convenient value casting
|
||||
@@ -104,7 +132,11 @@ namespace boost { namespace program_options {
|
||||
const abstract_variables_map* m_next;
|
||||
};
|
||||
|
||||
/** Concrete variables map which store variables in real map. */
|
||||
/** Concrete variables map which store variables in real map.
|
||||
|
||||
This class is derived from std::map<std::string, variable_value>,
|
||||
so you can use all map operators to examine its content.
|
||||
*/
|
||||
class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map,
|
||||
public std::map<std::string, variable_value>
|
||||
{
|
||||
@@ -125,30 +157,12 @@ namespace boost { namespace program_options {
|
||||
be changed by subsequence assignments. */
|
||||
std::set<std::string> m_final;
|
||||
|
||||
friend void store(const basic_parsed_options<char>& options,
|
||||
friend BOOST_PROGRAM_OPTIONS_DECL
|
||||
void store(const basic_parsed_options<char>& options,
|
||||
variables_map& xm,
|
||||
bool utf8);
|
||||
};
|
||||
|
||||
/** Stores in 'm' all options that are defined in 'options'.
|
||||
If 'm' already has a non-defaulted value of an option, that value
|
||||
is not changed, even if 'options' specify some value.
|
||||
*/
|
||||
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<char>& options, variables_map& m,
|
||||
bool utf8 = false);
|
||||
|
||||
/** Stores in 'm' all options that are defined in 'options'.
|
||||
If 'm' already has a non-defaulted value of an option, that value
|
||||
is not changed, even if 'options' specify some value.
|
||||
This is wide character variant.
|
||||
*/
|
||||
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<wchar_t>& options,
|
||||
variables_map& m);
|
||||
|
||||
|
||||
/** Runs all 'notify' function for options in 'm'. */
|
||||
BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
|
||||
|
||||
|
||||
/*
|
||||
* Templates/inlines
|
||||
@@ -180,18 +194,6 @@ namespace boost { namespace program_options {
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T&
|
||||
variable_value::as() const {
|
||||
return boost::any_cast<const T&>(v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T&
|
||||
variable_value::as() {
|
||||
return boost::any_cast<T&>(v);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
|
||||
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
|
||||
<hr>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -98,10 +98,10 @@ namespace boost { namespace program_options { namespace detail {
|
||||
{
|
||||
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
|
||||
vector<string> args;
|
||||
copy(argv+1, argv+argc, inserter(args, args.end()));
|
||||
copy(argv+1, argv+argc+!argc, inserter(args, args.end()));
|
||||
init(args);
|
||||
#else
|
||||
init(vector<string>(argv+1, argv+argc));
|
||||
init(vector<string>(argv+1, argv+argc+!argc));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -290,8 +290,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
|
||||
// First check that the option is valid, and get its description.
|
||||
// TODO: case-sensitivity.
|
||||
const option_description* xd =
|
||||
m_desc->find_nothrow(opt.string_key, (m_style & allow_guessing));
|
||||
const option_description* xd = m_desc->find_nothrow(opt.string_key,
|
||||
(m_style & allow_guessing) ? true : false);
|
||||
|
||||
if (!xd)
|
||||
{
|
||||
@@ -329,6 +329,14 @@ namespace boost { namespace program_options { namespace detail {
|
||||
|
||||
max_tokens -= opt.value.size();
|
||||
|
||||
// A value is optional if min_tokens == 0, but max_tokens > 0.
|
||||
// If a value is optional, it must appear in opt.value (because
|
||||
// it was 'adjacent'. Otherwise, remove the expectation of a
|
||||
// non-adjacent value. (For now, we just check max_tokens == 1,
|
||||
// as there is no current support for max_tokens>1)
|
||||
if (min_tokens == 0 && max_tokens == 1 && opt.value.empty())
|
||||
--max_tokens;
|
||||
|
||||
// Everything's OK, move the values to the result.
|
||||
for(;!other_tokens.empty() && max_tokens--; ) {
|
||||
opt.value.push_back(other_tokens[0]);
|
||||
@@ -462,7 +470,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
((m_style & allow_slash_for_short) && tok[0] == '/')))
|
||||
{
|
||||
if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),
|
||||
m_style & allow_guessing)) {
|
||||
(m_style & allow_guessing) ? true : false))
|
||||
{
|
||||
args[0].insert(0, "-");
|
||||
if (args[0][1] == '/')
|
||||
args[0][1] = '-';
|
||||
@@ -498,7 +507,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
if (!r.first.empty()) {
|
||||
option next;
|
||||
next.string_key = r.first;
|
||||
next.value.push_back(r.second);
|
||||
if (!r.second.empty())
|
||||
next.value.push_back(r.second);
|
||||
result.push_back(next);
|
||||
args.erase(args.begin());
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@ namespace boost { namespace program_options { namespace detail {
|
||||
using namespace std;
|
||||
|
||||
common_config_file_iterator::common_config_file_iterator(
|
||||
const std::set<std::string>& allowed_options)
|
||||
: allowed_options(allowed_options)
|
||||
const std::set<std::string>& allowed_options,
|
||||
bool allow_unregistered)
|
||||
: allowed_options(allowed_options),
|
||||
m_allow_unregistered(allow_unregistered)
|
||||
{
|
||||
for(std::set<std::string>::const_iterator i = allowed_options.begin();
|
||||
i != allowed_options.end();
|
||||
@@ -100,7 +102,8 @@ namespace boost { namespace program_options { namespace detail {
|
||||
string name = m_prefix + trim_ws(s.substr(0, n));
|
||||
string value = trim_ws(s.substr(n+1));
|
||||
|
||||
if (!allowed_option(name))
|
||||
bool registered = allowed_option(name);
|
||||
if (!registered && !m_allow_unregistered)
|
||||
boost::throw_exception(unknown_option(name));
|
||||
|
||||
if (value.empty())
|
||||
@@ -110,6 +113,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
this->value().string_key = name;
|
||||
this->value().value.clear();
|
||||
this->value().value.push_back(value);
|
||||
this->value().unregistered = !registered;
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
using namespace std;
|
||||
|
||||
namespace boost { namespace program_options {
|
||||
@@ -200,6 +201,8 @@ namespace boost { namespace program_options {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const unsigned options_description::m_default_line_length = 80;
|
||||
|
||||
options_description::options_description(unsigned line_length)
|
||||
: m_line_length(line_length)
|
||||
{}
|
||||
@@ -251,11 +254,12 @@ namespace boost { namespace program_options {
|
||||
return m_options;
|
||||
}
|
||||
|
||||
const option_description*
|
||||
const option_description*
|
||||
options_description::find_nothrow(const std::string& name,
|
||||
bool approx) const
|
||||
{
|
||||
int found = -1;
|
||||
shared_ptr<option_description> found;
|
||||
vector<string> approximate_matches;
|
||||
// We use linear search because matching specified option
|
||||
// name with the declared option name need to take care about
|
||||
// case sensitivity and trailing '*' and so we can't use simple map.
|
||||
@@ -275,31 +279,22 @@ namespace boost { namespace program_options {
|
||||
//
|
||||
// For now, we don't check the situation when there are
|
||||
// two full matches.
|
||||
|
||||
|
||||
if (r == option_description::full_match)
|
||||
{
|
||||
return m_options[i].get();
|
||||
return m_options[i].get();
|
||||
}
|
||||
|
||||
if (found != -1)
|
||||
{
|
||||
vector<string> alts;
|
||||
// FIXME: the use of 'key' here might not
|
||||
// be the best approach.
|
||||
alts.push_back(m_options[found]->key(name));
|
||||
alts.push_back(m_options[i]->key(name));
|
||||
boost::throw_exception(ambiguous_option(name, alts));
|
||||
}
|
||||
else
|
||||
{
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if (found != -1) {
|
||||
return m_options[found].get();
|
||||
} else {
|
||||
return 0;
|
||||
found = m_options[i];
|
||||
// FIXME: the use of 'key' here might not
|
||||
// be the best approach.
|
||||
approximate_matches.push_back(m_options[i]->key(name));
|
||||
}
|
||||
if (approximate_matches.size() > 1)
|
||||
boost::throw_exception(
|
||||
ambiguous_option(name, approximate_matches));
|
||||
|
||||
return found.get();
|
||||
}
|
||||
|
||||
BOOST_PROGRAM_OPTIONS_DECL
|
||||
@@ -390,13 +385,12 @@ namespace boost { namespace program_options {
|
||||
}
|
||||
}
|
||||
|
||||
string::const_iterator line_end;
|
||||
|
||||
line_end = line_begin + line_length;
|
||||
if (line_end > par_end)
|
||||
{
|
||||
line_end = par_end;
|
||||
}
|
||||
// Take care to never increment the iterator past
|
||||
// the end, since MSVC 8.0 (brokenly), assumes that
|
||||
// doing that, even if no access happens, is a bug.
|
||||
unsigned remaining = distance(line_begin, par_end);
|
||||
string::const_iterator line_end = line_begin +
|
||||
((remaining < line_length) ? remaining : line_length);
|
||||
|
||||
// prevent chopped words
|
||||
// Is line_end between two non-space characters?
|
||||
@@ -414,7 +408,7 @@ namespace boost { namespace program_options {
|
||||
{
|
||||
// is last_space within the second half ot the
|
||||
// current line
|
||||
if (unsigned(distance(last_space, line_end)) <
|
||||
if ((unsigned)distance(last_space, line_end) <
|
||||
(line_length - indent) / 2)
|
||||
{
|
||||
line_end = last_space;
|
||||
|
||||
@@ -88,7 +88,8 @@ namespace boost { namespace program_options {
|
||||
template<class charT>
|
||||
basic_parsed_options<charT>
|
||||
parse_config_file(std::basic_istream<charT>& is,
|
||||
const options_description& desc)
|
||||
const options_description& desc,
|
||||
bool allow_unregistered)
|
||||
{
|
||||
set<string> allowed_options;
|
||||
|
||||
@@ -106,7 +107,8 @@ namespace boost { namespace program_options {
|
||||
|
||||
// Parser return char strings
|
||||
parsed_options result(&desc);
|
||||
copy(detail::basic_config_file_iterator<charT>(is, allowed_options),
|
||||
copy(detail::basic_config_file_iterator<charT>(
|
||||
is, allowed_options, allow_unregistered),
|
||||
detail::basic_config_file_iterator<charT>(),
|
||||
back_inserter(result.options));
|
||||
// Convert char strings into desired type.
|
||||
@@ -116,13 +118,15 @@ namespace boost { namespace program_options {
|
||||
template
|
||||
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
|
||||
parse_config_file(std::basic_istream<char>& is,
|
||||
const options_description& desc);
|
||||
const options_description& desc,
|
||||
bool allow_unregistered);
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
template
|
||||
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
|
||||
parse_config_file(std::basic_istream<wchar_t>& is,
|
||||
const options_description& desc);
|
||||
const options_description& desc,
|
||||
bool allow_unregistered);
|
||||
#endif
|
||||
|
||||
// This versio, which accepts any options without validation, is disabled,
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace boost { namespace program_options {
|
||||
positional_options_description::positional_options_description()
|
||||
{}
|
||||
|
||||
void
|
||||
positional_options_description&
|
||||
positional_options_description::add(const char* name, int max_count)
|
||||
{
|
||||
assert(max_count != -1 || m_trailing.empty());
|
||||
@@ -27,7 +27,7 @@ namespace boost { namespace program_options {
|
||||
else {
|
||||
m_names.resize(m_names.size() + max_count, name);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
||||
@@ -122,8 +122,8 @@ namespace boost { namespace program_options {
|
||||
/* Validates bool value.
|
||||
Any of "1", "true", "yes", "on" will be converted to "1".<br>
|
||||
Any of "0", "false", "no", "off" will be converted to "0".<br>
|
||||
Case is ignored. Regardless of name passed, parameter will always
|
||||
be optional.
|
||||
Case is ignored. The 'xs' vector can either be empty, in which
|
||||
case the value is 'true', or can contain explicit value.
|
||||
*/
|
||||
BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs,
|
||||
bool*, int)
|
||||
@@ -170,9 +170,12 @@ namespace boost { namespace program_options {
|
||||
{
|
||||
check_first_occurrence(v);
|
||||
string s(get_single_string(xs));
|
||||
if (*s.begin() == '\'' && *s.rbegin() == '\'' ||
|
||||
*s.begin() == '"' && *s.rbegin() == '"')
|
||||
if (!s.empty() && (
|
||||
(*s.begin() == '\'' && *s.rbegin() == '\'' ||
|
||||
*s.begin() == '"' && *s.rbegin() == '"')))
|
||||
{
|
||||
v = any(s.substr(1, s.size()-2));
|
||||
}
|
||||
else
|
||||
v = any(s);
|
||||
}
|
||||
|
||||
@@ -35,8 +35,11 @@ namespace boost { namespace program_options {
|
||||
|
||||
std::set<std::string> new_final;
|
||||
|
||||
// Declared once, to please Intel in VC++ mode;
|
||||
unsigned i;
|
||||
|
||||
// First, convert/store all given options
|
||||
for (size_t i = 0; i < options.options.size(); ++i) {
|
||||
for (i = 0; i < options.options.size(); ++i) {
|
||||
|
||||
const string& name = options.options[i].string_key;
|
||||
// Skip positional options without name
|
||||
@@ -92,7 +95,7 @@ namespace boost { namespace program_options {
|
||||
|
||||
// Second, apply default values.
|
||||
const vector<shared_ptr<option_description> >& all = desc.options();
|
||||
for(unsigned i = 0; i < all.size(); ++i)
|
||||
for(i = 0; i < all.size(); ++i)
|
||||
{
|
||||
const option_description& d = *all[i];
|
||||
string key = d.key("");
|
||||
|
||||
47
test/Jamfile
47
test/Jamfile
@@ -1,47 +0,0 @@
|
||||
|
||||
subproject libs/program_options/test ;
|
||||
|
||||
import testing ;
|
||||
|
||||
rule program-options-test ( name )
|
||||
{
|
||||
return [
|
||||
run $(name).cpp <lib>../build/boost_program_options
|
||||
<lib>../../test/build/boost_test_exec_monitor : :
|
||||
: <include>$(BOOST_ROOT)
|
||||
std::locale-support ]
|
||||
;
|
||||
}
|
||||
|
||||
rule program-options-dll-test ( name )
|
||||
{
|
||||
return [
|
||||
run $(name).cpp <dll>../build/boost_program_options
|
||||
<lib>../../test/build/boost_test_exec_monitor : :
|
||||
: <include>$(BOOST_ROOT)
|
||||
<define>BOOST_ALL_DYN_LINK=1
|
||||
<runtime-link>dynamic
|
||||
: $(name)_dll ]
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
test-suite program_options :
|
||||
[ program-options-test options_description_test ]
|
||||
[ program-options-test parsers_test ]
|
||||
[ program-options-test variable_map_test ]
|
||||
[ program-options-test cmdline_test ]
|
||||
[ program-options-test positional_options_test ]
|
||||
[ program-options-test unicode_test ]
|
||||
[ program-options-test winmain ]
|
||||
[ program-options-dll-test options_description_test ]
|
||||
[ program-options-dll-test parsers_test ]
|
||||
[ program-options-dll-test variable_map_test ]
|
||||
[ program-options-dll-test cmdline_test ]
|
||||
[ program-options-dll-test positional_options_test ]
|
||||
[ program-options-dll-test unicode_test ]
|
||||
[ program-options-dll-test winmain ]
|
||||
|
||||
|
||||
;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
project
|
||||
: requirements
|
||||
<library>../build//boost_program_options
|
||||
<library>/boost/test//boost_test_exec_monitor
|
||||
<link>static
|
||||
<variant>debug
|
||||
|
||||
# <define>_GLIBCXX_CONCEPT_CHECKS
|
||||
# <define>_GLIBCXX_DEBUG
|
||||
@@ -13,7 +13,7 @@ rule po-test ( source )
|
||||
{
|
||||
return
|
||||
[ run $(source) ]
|
||||
[ run $(source) : : : <link>shared <define>BOOST_ALL_DYN_LINK=1
|
||||
[ run $(source) : : : <link>shared <define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
|
||||
: $(source:B)_dll ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
using namespace boost::program_options;
|
||||
using boost::program_options::detail::cmdline;
|
||||
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
using namespace std;
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
/* To facilitate testing, declare a number of error codes. Otherwise,
|
||||
we'd have to specify the type of exception that should be thrown.
|
||||
*/
|
||||
@@ -600,7 +599,7 @@ void test_unregistered()
|
||||
// It's not clear yet, so I'm leaving the decision till later.
|
||||
}
|
||||
|
||||
int test_main(int ac, char* av[])
|
||||
int main(int ac, char* av[])
|
||||
{
|
||||
test_long_options();
|
||||
test_short_options();
|
||||
|
||||
25
test/minitest.hpp
Normal file
25
test/minitest.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef BOOST_PROGRAM_OPTIONS_MINITEST
|
||||
#define BOOST_PROGRAM_OPTIONS_MINITEST
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BOOST_REQUIRE(b) assert(b)
|
||||
#define BOOST_CHECK(b) assert(b)
|
||||
#define BOOST_CHECK_EQUAL(a, b) assert(a == b)
|
||||
#define BOOST_ERROR(description) std::cerr << description; std::cerr << "\n"; abort();
|
||||
#define BOOST_CHECK_THROW(expression, exception) \
|
||||
try \
|
||||
{ \
|
||||
expression; \
|
||||
BOOST_ERROR("expected exception not thrown");\
|
||||
throw 10; \
|
||||
} \
|
||||
catch(exception &) \
|
||||
{ \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -10,13 +10,13 @@ using namespace boost::program_options;
|
||||
#include <boost/function.hpp>
|
||||
using namespace boost;
|
||||
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
void test_type()
|
||||
{
|
||||
options_description desc;
|
||||
@@ -43,9 +43,9 @@ void test_approximation()
|
||||
("foo", new untyped_value())
|
||||
("fee", new untyped_value())
|
||||
("baz", new untyped_value())
|
||||
("all", new untyped_value())
|
||||
("all-chroots", new untyped_value())
|
||||
("all-sessions", new untyped_value())
|
||||
("all", new untyped_value())
|
||||
;
|
||||
|
||||
BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "foo");
|
||||
@@ -61,9 +61,25 @@ void test_approximation()
|
||||
// BOOST_CHECK(*(++a.begin()) == "foo");
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
void test_formatting()
|
||||
{
|
||||
// Long option descriptions used to crash on MSVC-8.0.
|
||||
options_description desc;
|
||||
desc.add_options()(
|
||||
"test", new untyped_value(),
|
||||
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
|
||||
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
|
||||
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
|
||||
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo");
|
||||
|
||||
stringstream ss;
|
||||
ss << desc;
|
||||
}
|
||||
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_type();
|
||||
test_approximation();
|
||||
test_formatting();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,13 +14,17 @@ namespace po = boost::program_options;
|
||||
#include <boost/function.hpp>
|
||||
using namespace boost;
|
||||
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#if defined(__sun)
|
||||
#include <stdlib.h> // for putenv on solaris
|
||||
#else
|
||||
#include <cstdlib> // for putenv
|
||||
#endif
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
#define TEST_CHECK_THROW(expression, exception, description) \
|
||||
try \
|
||||
@@ -133,6 +137,16 @@ void test_command_line()
|
||||
check_value(a4[0], "foo", "4");
|
||||
check_value(a4[1], "bar", "11");
|
||||
|
||||
// Check that we don't crash on empty values of type 'string'
|
||||
char* cmdline4[] = {"", "--open", ""};
|
||||
options_description desc2;
|
||||
desc2.add_options()
|
||||
("open", po::value<string>())
|
||||
;
|
||||
variables_map vm;
|
||||
po::store(po::parse_command_line(3, cmdline4, desc2), vm);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -228,9 +242,23 @@ void test_unregistered()
|
||||
vm);
|
||||
|
||||
BOOST_CHECK_EQUAL(vm.size(), 0u);
|
||||
|
||||
|
||||
const char content1[] =
|
||||
"gv1 = 0\n"
|
||||
"[m1]\n"
|
||||
"v1 = 1\n"
|
||||
;
|
||||
|
||||
stringstream ss(content1);
|
||||
vector<option> a3 = parse_config_file(ss, desc, true).options;
|
||||
BOOST_REQUIRE(a3.size() == 2);
|
||||
cout << "XXX" << a3[0].value.front() << "\n";
|
||||
check_value(a3[0], "gv1", "0");
|
||||
check_value(a3[1], "m1.v1", "1");
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_command_line();
|
||||
test_config_file();
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace po = boost::program_options;
|
||||
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
@@ -49,28 +50,31 @@ void test_parsing()
|
||||
("first", po::value<int>())
|
||||
("second", po::value<int>())
|
||||
("input-file", po::value< vector<string> >())
|
||||
("some-other", po::value<string>())
|
||||
;
|
||||
|
||||
positional_options_description p;
|
||||
p.add("input-file", 2);
|
||||
p.add("input-file", 2).add("some-other", 1);
|
||||
|
||||
vector<string> args;
|
||||
args.push_back("--first=10");
|
||||
args.push_back("file1");
|
||||
args.push_back("--second=10");
|
||||
args.push_back("file2");
|
||||
args.push_back("file3");
|
||||
|
||||
// Check that positional options are handled.
|
||||
parsed_options parsed =
|
||||
command_line_parser(args).options(desc).positional(p).run();
|
||||
|
||||
BOOST_REQUIRE(parsed.options.size() == 4);
|
||||
BOOST_REQUIRE(parsed.options.size() == 5);
|
||||
BOOST_CHECK_EQUAL(parsed.options[1].string_key, "input-file");
|
||||
BOOST_CHECK_EQUAL(parsed.options[1].value[0], "file1");
|
||||
BOOST_CHECK_EQUAL(parsed.options[3].string_key, "input-file");
|
||||
BOOST_CHECK_EQUAL(parsed.options[3].value[0], "file2");
|
||||
BOOST_CHECK_EQUAL(parsed.options[4].value[0], "file3");
|
||||
|
||||
args.push_back("file3");
|
||||
args.push_back("file4");
|
||||
|
||||
// Check that excessive number of positional options is detected.
|
||||
BOOST_CHECK_THROW(command_line_parser(args).options(desc).positional(p)
|
||||
@@ -78,7 +82,7 @@ void test_parsing()
|
||||
too_many_positional_options_error);
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_positional_options();
|
||||
test_parsing();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
@@ -14,6 +15,8 @@
|
||||
#include <boost/program_options/detail/convert.hpp>
|
||||
#include <boost/program_options/detail/utf8_codecvt_facet.hpp>
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
string file_content(const string& filename)
|
||||
@@ -74,7 +77,7 @@ std::wstring from_8_bit_2(const std::string& s,
|
||||
void test_convert(const std::string& input,
|
||||
const std::string& expected_output)
|
||||
{
|
||||
boost::program_options::detail::utf8_codecvt_facet<wchar_t, char> facet;
|
||||
boost::program_options::detail::utf8_codecvt_facet facet;
|
||||
|
||||
std::wstring output;
|
||||
{
|
||||
@@ -118,7 +121,7 @@ void test_convert(const std::string& input,
|
||||
BOOST_CHECK(ref == input);
|
||||
}
|
||||
|
||||
int test_main(int ac, char* av[])
|
||||
int main(int ac, char* av[])
|
||||
{
|
||||
std::string input = file_content("utf8.txt");
|
||||
std::string expected = file_content("ucs2.txt");
|
||||
|
||||
@@ -15,12 +15,11 @@ namespace po = boost::program_options;
|
||||
#include <boost/function.hpp>
|
||||
using namespace boost;
|
||||
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include "minitest.hpp"
|
||||
|
||||
// Test that unicode input is forwarded to unicode option without
|
||||
// problems.
|
||||
void test_unicode_to_unicode()
|
||||
@@ -149,7 +148,7 @@ void test_config_file()
|
||||
BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_unicode_to_unicode();
|
||||
test_unicode_to_native();
|
||||
|
||||
@@ -15,22 +15,10 @@ namespace po = boost::program_options;
|
||||
#include <boost/function.hpp>
|
||||
using namespace boost;
|
||||
|
||||
#define BOOST_INCLUDE_MAIN // for testing, include rather than link
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#define TEST_CHECK_THROW(expression, exception, description) \
|
||||
try \
|
||||
{ \
|
||||
expression; \
|
||||
BOOST_ERROR(description);\
|
||||
throw 10; \
|
||||
} \
|
||||
catch(exception &) \
|
||||
{ \
|
||||
}
|
||||
#include "minitest.hpp"
|
||||
|
||||
vector<string> sv(char* array[], unsigned size)
|
||||
{
|
||||
@@ -102,6 +90,25 @@ void test_variable_map()
|
||||
BOOST_CHECK(vm3["vee"].as<string>() == "42");
|
||||
BOOST_CHECK(vm3["voo"].as<string>() == "1");
|
||||
BOOST_CHECK(vm3["iii"].as<int>() == 123);
|
||||
|
||||
options_description desc3;
|
||||
desc3.add_options()
|
||||
("imp", po::value<int>()->implicit_value(100))
|
||||
("iim", po::value<int>()->implicit_value(200)->default_value(201))
|
||||
("mmp,m", po::value<int>()->implicit_value(123)->default_value(124))
|
||||
;
|
||||
char* cmdline6_[] = { "--imp=1", "-m" };
|
||||
vector<string> cmdline6 = sv(cmdline6_,
|
||||
sizeof(cmdline6_)/sizeof(cmdline6_[0]));
|
||||
parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
|
||||
|
||||
variables_map vm4;
|
||||
store(a6, vm4);
|
||||
notify(vm4);
|
||||
BOOST_REQUIRE(vm4.size() == 3);
|
||||
BOOST_CHECK(vm4["imp"].as<int>() == 1);
|
||||
BOOST_CHECK(vm4["iim"].as<int>() == 201);
|
||||
BOOST_CHECK(vm4["mmp"].as<int>() == 123);
|
||||
}
|
||||
|
||||
int stored_value;
|
||||
@@ -269,7 +276,7 @@ void test_multiple_assignments_with_different_option_description()
|
||||
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
int main(int, char* [])
|
||||
{
|
||||
test_variable_map();
|
||||
test_semantic_values();
|
||||
|
||||
@@ -7,26 +7,42 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cctype>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
using namespace boost::program_options;
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
void check_equal(const std::vector<string>& actual, char **expected, int n)
|
||||
{
|
||||
if (actual.size() != n)
|
||||
{
|
||||
std::cerr << "Size mismatch between expected and actual data\n";
|
||||
abort();
|
||||
}
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (actual[i] != expected[i])
|
||||
{
|
||||
std::cerr << "Unexpected content\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
void test_winmain()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
#define C ,
|
||||
#define TEST(input, expected) \
|
||||
char* BOOST_PP_CAT(e, __LINE__)[] = expected;\
|
||||
vector<string> BOOST_PP_CAT(v, __LINE__) = split_winmain(input);\
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(BOOST_PP_CAT(v, __LINE__).begin(),\
|
||||
BOOST_PP_CAT(v, __LINE__).end(),\
|
||||
BOOST_PP_CAT(e, __LINE__),\
|
||||
BOOST_PP_CAT(e, __LINE__) + \
|
||||
sizeof(BOOST_PP_CAT(e, __LINE__))/sizeof(char*));
|
||||
check_equal(BOOST_PP_CAT(v, __LINE__), BOOST_PP_CAT(e, __LINE__),\
|
||||
sizeof(BOOST_PP_CAT(e, __LINE__))/sizeof(char*));
|
||||
|
||||
// The following expectations were obtained in Win2000 shell:
|
||||
TEST("1 ", {"1"});
|
||||
@@ -45,13 +61,13 @@ void test_winmain()
|
||||
TEST("1\\\\1 ", {"1\\\\1"});
|
||||
}
|
||||
|
||||
int test_main(int, char*[])
|
||||
int main(int, char*[])
|
||||
{
|
||||
test_winmain();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main(int, char*[])
|
||||
int main(int, char*[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user