mirror of
https://github.com/boostorg/program_options.git
synced 2026-01-20 04:42:24 +00:00
Compare commits
44 Commits
boost-1.33
...
boost-1.34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
8f0bc7ad72 | ||
|
|
48ee128928 | ||
|
|
596f8aa46f | ||
|
|
cbe799d914 | ||
|
|
5e4b39d672 | ||
|
|
d8c809b0a3 | ||
|
|
881c3b4e3a | ||
|
|
e17d52165f | ||
|
|
6e7b140c98 | ||
|
|
4cde608b3e | ||
|
|
7bc84f1b39 | ||
|
|
3400019810 | ||
|
|
e1d38380f4 | ||
|
|
f2e43384fb | ||
|
|
78f209eb0b | ||
|
|
e7e1550269 | ||
|
|
a00a6c9d19 | ||
|
|
84cc0d2972 | ||
|
|
d43c947002 |
@@ -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
|
||||
@@ -52,8 +52,7 @@
|
||||
<listitem>
|
||||
<para>ascii input passed to a Unicode value, and Unicode input
|
||||
passed to an ascii value will be converted using a codecvt
|
||||
facet (which may be specified by the user(which can be
|
||||
specified by the user)
|
||||
facet (which may be specified by the user).
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@@ -83,7 +82,7 @@
|
||||
</para>
|
||||
|
||||
<para>The Unicode support outlined above is not complete. For example, we
|
||||
don't plan allow Unicode in option names. Unicode support is hard and
|
||||
don't support Unicode option names. Unicode support is hard and
|
||||
requires a Boost-wide solution. Even comparing two arbitrary Unicode
|
||||
strings is non-trivial. Finally, using Unicode in option names is
|
||||
related to internationalization, which has it's own
|
||||
|
||||
@@ -184,7 +184,7 @@ store(command_line_parser(args).options(desc).run(), vm);
|
||||
options_description general("General options");
|
||||
general.add_options()
|
||||
("help", "produce a help message")
|
||||
("help-module", value<string>()->implicit(),
|
||||
("help-module", value<string>(),
|
||||
"produce a help for a given module")
|
||||
("version", "output the version number")
|
||||
;
|
||||
@@ -284,7 +284,7 @@ void validate(boost::any& v,
|
||||
using namespace boost::program_options;
|
||||
|
||||
// Make sure no previous assignment to 'a' was made.
|
||||
validators::check_first_occurence(v);
|
||||
validators::check_first_occurrence(v);
|
||||
// Extract the first string from 'values'. If there is more than
|
||||
// one string, it's an error, and exception will be thrown.
|
||||
const string& s = validators::get_single_string(values);
|
||||
@@ -398,13 +398,49 @@ $ export LC_CTYPE=ru_RU.KOI8-R
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Allowing Unknown Options</title>
|
||||
|
||||
<para>Usually, the library throws an exception on unknown option names. This
|
||||
behaviour can be changed. For example, only some part of your application uses
|
||||
<libraryname>Program_options</libraryname>, and you wish to pass unrecognized options to another part of
|
||||
the program, or even to another application.</para>
|
||||
|
||||
<para>To allow unregistered options on the command line, you need to use
|
||||
the &basic_command_line_parser; class for parsing (not &parse_command_line;)
|
||||
and call the <methodname alt="boost::program_options::basic_command_line_parser::allow_unregistered">allow_unregistered</methodname>
|
||||
method of that class:
|
||||
<programlisting>
|
||||
parsed_options parsed =
|
||||
command_line_parser(argv, argc).options(desc).allow_unregistered().run();
|
||||
</programlisting>
|
||||
|
||||
For each token that looks like an option, but does not have a known name,
|
||||
an instance of &basic_option; will be added to the result.
|
||||
The <code>string_key</code> and <code>value</code> fields of the instance will contain results
|
||||
of syntactic parsing of the token, the <code>unregistered</code> field will be set to <code>true</code>,
|
||||
and the <code>original_tokens</code> field will contain the token as it appeared on the command line.
|
||||
</para>
|
||||
|
||||
<para>If you want to pass the unrecognized options further, the
|
||||
<functionname alt="boost::program_options::collect_unrecognized">collect_unrecognized</functionname> function can be used.
|
||||
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);
|
||||
</programlisting>
|
||||
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: xml
|
||||
sgml-indent-data: t
|
||||
sgml-parent-document: ("program_options.xml" "section")
|
||||
mode: nxml
|
||||
sgml-indent-data: t
|
||||
sgml-parent-document: ("userman.xml" "chapter")
|
||||
sgml-set-face: t
|
||||
End:
|
||||
-->
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_option.html">
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_options.html">
|
||||
</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>()->implicit(), "verbosity level")
|
||||
("verbose", value<string>()->zero_token(), "verbosity level")
|
||||
("email", value<string>()->multitoken(), "email to send to")
|
||||
;
|
||||
</programlisting>
|
||||
@@ -348,11 +348,18 @@ 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".
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>The &positional_options_desc; class only specifies translation from
|
||||
position to name, and the option name should still be registered with
|
||||
an instance of the &options_description; class.</para>
|
||||
</warning>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
@@ -481,7 +488,7 @@ notify(vm);
|
||||
<filename>autoexec.bat</filename> file or (on recent versions) the
|
||||
<filename>Control Panel/System/Advanced/Environment Variables</filename>
|
||||
dialog, and on Unix —, the <filename>/etc/profile</filename>,
|
||||
<filename>~/profile</filename> and <filename>~/bash_profile</filename>
|
||||
<filename>~/.profile</filename> and <filename>~/.bash_profile</filename>
|
||||
files. Because environment variables can be set for the entire system,
|
||||
they are particularly suitable for options which apply to all programs.
|
||||
</para>
|
||||
@@ -560,8 +567,15 @@ notify(vm);
|
||||
|
||||
<row>
|
||||
<entry>&parse_command_line;</entry>
|
||||
<entry>parses command line</entry>
|
||||
<entry>parses command line (simpified interface)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>&basic_command_line_parser;</entry>
|
||||
<entry>parses command line (extended interface)</entry>
|
||||
</row>
|
||||
|
||||
|
||||
<row>
|
||||
<entry>&parse_config_file;</entry>
|
||||
<entry>parses config file</entry>
|
||||
|
||||
@@ -37,3 +37,10 @@
|
||||
<!ENTITY command_line_parser
|
||||
"<classname alt='boost::program_options::command_line_parser'>command_line_parser</classname>">
|
||||
|
||||
<!ENTITY basic_command_line_parser
|
||||
"<classname alt='boost::program_options::basic_command_line_parser'>basic_command_line_parser</classname>">
|
||||
|
||||
|
||||
<!ENTITY basic_option
|
||||
"<classname alt='boost::program_options::basic_option'>basic_option</classname>">
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
Make parse_config_file("foo.cfg", desc) work.
|
||||
|
||||
Document handling of positional options which depends on precedding options.
|
||||
I.e scanning the parsed options and creating new variables_map when we see
|
||||
a positional option. (Email from Tony).
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -76,6 +76,24 @@ namespace boost { namespace program_options {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class charT>
|
||||
basic_command_line_parser<charT>&
|
||||
basic_command_line_parser<charT>::allow_unregistered()
|
||||
{
|
||||
detail::cmdline::allow_unregistered();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class charT>
|
||||
basic_command_line_parser<charT>&
|
||||
basic_command_line_parser<charT>::extra_style_parser(style_parser s)
|
||||
{
|
||||
detail::cmdline::extra_style_parser(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class charT>
|
||||
basic_parsed_options<charT>
|
||||
basic_command_line_parser<charT>::run()
|
||||
@@ -101,6 +119,26 @@ namespace boost { namespace program_options {
|
||||
style(style).extra_parser(ext).run();
|
||||
}
|
||||
|
||||
template<class charT>
|
||||
std::vector< std::basic_string<charT> >
|
||||
collect_unrecognized(const std::vector< basic_option<charT> >& options,
|
||||
enum collect_unrecognized_mode mode)
|
||||
{
|
||||
std::vector< std::basic_string<charT> > result;
|
||||
for(unsigned i = 0; i < options.size(); ++i)
|
||||
{
|
||||
if (options[i].unregistered ||
|
||||
(mode == include_positional && options[i].position_key != -1))
|
||||
{
|
||||
copy(options[i].original_tokens.begin(),
|
||||
options[i].original_tokens.end(),
|
||||
back_inserter(result));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,10 +41,16 @@ namespace boost { namespace program_options {
|
||||
int position_key;
|
||||
/** Option's value */
|
||||
std::vector< std::basic_string<charT> > value;
|
||||
/** The original unchanged tokens this option was
|
||||
created from. */
|
||||
std::vector< std::basic_string<charT> > original_tokens;
|
||||
/** True if option was not recognized. In that case,
|
||||
'string_key' and 'value' are results of purely
|
||||
syntactic parsing of source. */
|
||||
syntactic parsing of source. The original tokens can be
|
||||
recovered from the "original_tokens" member.
|
||||
*/
|
||||
bool unregistered;
|
||||
|
||||
};
|
||||
typedef basic_option<char> option;
|
||||
typedef basic_option<wchar_t> woption;
|
||||
|
||||
@@ -78,10 +78,12 @@ namespace program_options {
|
||||
|
||||
virtual ~option_description();
|
||||
|
||||
enum match_result { no_match, full_match, approximate_match };
|
||||
|
||||
/** Given 'option', specified in the input source,
|
||||
return 'true' is 'option' specifies *this.
|
||||
*/
|
||||
bool match(const std::string& option, bool approx) const;
|
||||
match_result match(const std::string& option, bool approx) const;
|
||||
|
||||
/** Return the key that should identify the option, in
|
||||
particular in the variables_map class.
|
||||
|
||||
@@ -73,13 +73,16 @@ namespace boost { namespace program_options {
|
||||
/** Command line parser.
|
||||
|
||||
The class allows one to specify all the information needed for parsing
|
||||
and to parser the parse the command line. It is primarily needed to
|
||||
and to parse the command line. It is primarily needed to
|
||||
emulate named function parameters -- a regular function with 5
|
||||
parameters will be hard to use and creating overloads with a smaller
|
||||
nuber of parameters will be confusing.
|
||||
|
||||
For the most common case, the function parse_command_line is a better
|
||||
alternative.
|
||||
|
||||
There are two typedefs -- command_line_parser and wcommand_line_parser,
|
||||
for charT == char and charT == wchar_t cases.
|
||||
*/
|
||||
template<class charT>
|
||||
class basic_command_line_parser : private detail::cmdline {
|
||||
@@ -90,7 +93,7 @@ namespace boost { namespace program_options {
|
||||
basic_command_line_parser(const std::vector<
|
||||
std::basic_string<charT> >& args);
|
||||
/** Creates a command line parser for the specified arguments
|
||||
list. The parameter should be the same as passes to 'main'.
|
||||
list. The parameters should be the same as passed to 'main'.
|
||||
*/
|
||||
basic_command_line_parser(int argc, charT* argv[]);
|
||||
|
||||
@@ -104,8 +107,26 @@ namespace boost { namespace program_options {
|
||||
basic_command_line_parser& style(int);
|
||||
/** Sets the extra parsers. */
|
||||
basic_command_line_parser& extra_parser(ext_parser);
|
||||
|
||||
|
||||
/** Parses the options and returns the result of parsing.
|
||||
Throws on error.
|
||||
*/
|
||||
basic_parsed_options<charT> run();
|
||||
|
||||
/** Specifies that unregistered options are allowed and should
|
||||
be passed though. For each command like token that looks
|
||||
like an option but does not contain a recognized name, an
|
||||
instance of basic_option<charT> will be added to result,
|
||||
with 'unrecognized' field set to 'true'. It's possible to
|
||||
collect all unrecognized options with the 'collect_unrecognized'
|
||||
funciton.
|
||||
*/
|
||||
basic_command_line_parser& allow_unregistered();
|
||||
|
||||
using detail::cmdline::style_parser;
|
||||
|
||||
basic_command_line_parser& extra_style_parser(style_parser s);
|
||||
|
||||
private:
|
||||
const options_description* m_desc;
|
||||
};
|
||||
@@ -134,6 +155,22 @@ namespace boost { namespace program_options {
|
||||
basic_parsed_options<charT>
|
||||
parse_config_file(std::basic_istream<charT>&, const options_description&);
|
||||
|
||||
/** Controls if the 'collect_unregistered' function should
|
||||
include positional options, or not. */
|
||||
enum collect_unrecognized_mode
|
||||
{ include_positional, exclude_positional };
|
||||
|
||||
/** Collects the original tokens for all named options with
|
||||
'unregistered' flag set. If 'mode' is 'include_positional'
|
||||
also collects all positional options.
|
||||
Returns the vector of origianl tokens for all collected
|
||||
options.
|
||||
*/
|
||||
template<class charT>
|
||||
std::vector< std::basic_string<charT> >
|
||||
collect_unrecognized(const std::vector< basic_option<charT> >& options,
|
||||
enum collect_unrecognized_mode mode);
|
||||
|
||||
/** Parse environment.
|
||||
|
||||
For each environment variable, the 'name_mapper' function is called to
|
||||
@@ -180,6 +217,7 @@ namespace boost { namespace program_options {
|
||||
split_winmain(const std::wstring& cmdline);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -37,10 +37,11 @@ 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
|
||||
be present. Can return (numeric_limits<unsigned>::max)() to
|
||||
indicate unlimited number. */
|
||||
unsigned max_total_count() const;
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace boost { namespace program_options {
|
||||
|
||||
@@ -74,6 +74,13 @@ namespace boost { namespace program_options {
|
||||
// Nothing here. Specializations to follow.
|
||||
};
|
||||
|
||||
/** Helper conversion class for values that accept ascii
|
||||
strings as input.
|
||||
Overrides the 'parse' method and defines new 'xparse'
|
||||
method taking std::string. Depending on whether input
|
||||
to parse is ascii or UTF8, will pass it to xparse unmodified,
|
||||
or with UTF8->ascii conversion.
|
||||
*/
|
||||
template<>
|
||||
class BOOST_PROGRAM_OPTIONS_DECL
|
||||
value_semantic_codecvt_helper<char> : public value_semantic {
|
||||
@@ -87,6 +94,13 @@ namespace boost { namespace program_options {
|
||||
const = 0;
|
||||
};
|
||||
|
||||
/** Helper conversion class for values that accept ascii
|
||||
strings as input.
|
||||
Overrides the 'parse' method and defines new 'xparse'
|
||||
method taking std::wstring. Depending on whether input
|
||||
to parse is ascii or UTF8, will recode input to Unicode, or
|
||||
pass it unmodified.
|
||||
*/
|
||||
template<>
|
||||
class BOOST_PROGRAM_OPTIONS_DECL
|
||||
value_semantic_codecvt_helper<wchar_t> : public value_semantic {
|
||||
@@ -101,6 +115,7 @@ namespace boost { namespace program_options {
|
||||
const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Class which specifies a simple handling of a value: the value will
|
||||
have string type and only one token is allowed. */
|
||||
class BOOST_PROGRAM_OPTIONS_DECL
|
||||
@@ -134,9 +149,29 @@ namespace boost { namespace program_options {
|
||||
bool m_zero_tokens;
|
||||
};
|
||||
|
||||
/** Base class for all option that have a fixed type, and are
|
||||
willing to announce this type to the outside world.
|
||||
Any 'value_semantics' for which you want to find out the
|
||||
type can be dynamic_cast-ed to typed_value_base. If conversion
|
||||
succeeds, the 'type' method can be called.
|
||||
*/
|
||||
class typed_value_base
|
||||
{
|
||||
public:
|
||||
// Returns the type of the value described by this
|
||||
// object.
|
||||
virtual const std::type_info& value_type() const = 0;
|
||||
// Not really needed, since deletion from this
|
||||
// class is silly, but just in case.
|
||||
virtual ~typed_value_base() {}
|
||||
};
|
||||
|
||||
|
||||
/** Class which handles value of a specific type. */
|
||||
template<class T, class charT = char>
|
||||
class typed_value : public value_semantic_codecvt_helper<charT> {
|
||||
class typed_value : public value_semantic_codecvt_helper<charT>,
|
||||
public typed_value_base
|
||||
{
|
||||
public:
|
||||
/** Ctor. The 'store_to' parameter tells where to store
|
||||
the value when it's known. The parameter can be NULL. */
|
||||
@@ -227,7 +262,7 @@ namespace boost { namespace program_options {
|
||||
|
||||
|
||||
/** Creates an instance of the 'validator' class and calls
|
||||
its operator() to perform athe ctual conversion. */
|
||||
its operator() to perform the actual conversion. */
|
||||
void xparse(boost::any& value_store,
|
||||
const std::vector< std::basic_string<charT> >& new_tokens)
|
||||
const;
|
||||
@@ -250,6 +285,13 @@ namespace boost { namespace program_options {
|
||||
when creating *this, stores the value there. Otherwise,
|
||||
does nothing. */
|
||||
void notify(const boost::any& value_store) const;
|
||||
|
||||
public: // typed_value_base overrides
|
||||
|
||||
const std::type_info& value_type() const
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -24,6 +24,27 @@ 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 +57,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 +87,9 @@ 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 void store(const basic_parsed_options<char>& options,
|
||||
variables_map& m, bool);
|
||||
friend void BOOST_PROGRAM_OPTIONS_DECL notify(variables_map& m);
|
||||
friend void notify(variables_map& m);
|
||||
};
|
||||
|
||||
/** Implements string->string mapping with convenient value casting
|
||||
@@ -104,7 +129,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>
|
||||
{
|
||||
@@ -130,25 +159,6 @@ namespace boost { namespace program_options {
|
||||
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 +190,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>
|
||||
@@ -83,7 +83,7 @@ namespace boost { namespace program_options {
|
||||
namespace boost { namespace program_options { namespace detail {
|
||||
|
||||
// vc6 needs this, but borland chokes when this is added.
|
||||
#if BOOST_WORKAROUND(_MSC_VER, <= 1200)
|
||||
#if BOOST_WORKAROUND(_MSC_VER, < 1300)
|
||||
using namespace std;
|
||||
using namespace program_options;
|
||||
#endif
|
||||
@@ -248,6 +248,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
if (!ok) {
|
||||
option opt;
|
||||
opt.value.push_back(args[0]);
|
||||
opt.original_tokens.push_back(args[0]);
|
||||
result.push_back(opt);
|
||||
args.erase(args.begin());
|
||||
}
|
||||
@@ -331,6 +332,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
// Everything's OK, move the values to the result.
|
||||
for(;!other_tokens.empty() && max_tokens--; ) {
|
||||
opt.value.push_back(other_tokens[0]);
|
||||
opt.original_tokens.push_back(other_tokens[0]);
|
||||
other_tokens.erase(other_tokens.begin());
|
||||
}
|
||||
}
|
||||
@@ -368,6 +370,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
opt.string_key = name;
|
||||
if (!adjacent.empty())
|
||||
opt.value.push_back(adjacent);
|
||||
opt.original_tokens.push_back(tok);
|
||||
result.push_back(opt);
|
||||
args.erase(args.begin());
|
||||
}
|
||||
@@ -416,6 +419,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
|
||||
option opt;
|
||||
opt.string_key = name;
|
||||
opt.original_tokens.push_back(tok);
|
||||
if (!adjacent.empty())
|
||||
opt.value.push_back(adjacent);
|
||||
result.push_back(opt);
|
||||
@@ -442,6 +446,7 @@ namespace boost { namespace program_options { namespace detail {
|
||||
opt.string_key = name;
|
||||
if (!adjacent.empty())
|
||||
opt.value.push_back(adjacent);
|
||||
opt.original_tokens.push_back(tok);
|
||||
result.push_back(opt);
|
||||
args.erase(args.begin());
|
||||
}
|
||||
@@ -493,7 +498,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());
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
using namespace std;
|
||||
|
||||
namespace boost { namespace program_options {
|
||||
@@ -53,10 +54,10 @@ namespace boost { namespace program_options {
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
option_description::match_result
|
||||
option_description::match(const std::string& option, bool approx) const
|
||||
{
|
||||
bool result = false;
|
||||
match_result result = no_match;
|
||||
if (!m_long_name.empty()) {
|
||||
|
||||
if (*m_long_name.rbegin() == '*')
|
||||
@@ -65,23 +66,26 @@ namespace boost { namespace program_options {
|
||||
// prefix is OK.
|
||||
if (option.find(m_long_name.substr(0, m_long_name.length()-1))
|
||||
== 0)
|
||||
result = true;
|
||||
result = approximate_match;
|
||||
}
|
||||
|
||||
if (approx)
|
||||
{
|
||||
if (m_long_name.find(option) == 0)
|
||||
result = true;
|
||||
if (m_long_name == option)
|
||||
result = full_match;
|
||||
else
|
||||
result = approximate_match;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_long_name == option)
|
||||
result = true;
|
||||
result = full_match;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_short_name == option)
|
||||
result = true;
|
||||
result = full_match;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -258,21 +262,38 @@ namespace boost { namespace program_options {
|
||||
// case sensitivity and trailing '*' and so we can't use simple map.
|
||||
for(unsigned i = 0; i < m_options.size(); ++i)
|
||||
{
|
||||
if (m_options[i]->match(name, approx))
|
||||
option_description::match_result r =
|
||||
m_options[i]->match(name, approx);
|
||||
|
||||
if (r == option_description::no_match)
|
||||
continue;
|
||||
|
||||
// If we have a full patch, and an approximate match,
|
||||
// ignore approximate match instead of reporting error.
|
||||
// Say, if we have options "all" and "all-chroots", then
|
||||
// "--all" on the command line should select the first one,
|
||||
// without ambiguity.
|
||||
//
|
||||
// For now, we don't check the situation when there are
|
||||
// two full matches.
|
||||
|
||||
if (r == option_description::full_match)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
@@ -291,11 +312,26 @@ namespace boost { namespace program_options {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Given a string 'par', that contains no newline characters
|
||||
outputs it to 'os' with wordwrapping, that is, as several
|
||||
line.
|
||||
|
||||
Each output line starts with 'indent' space characters,
|
||||
following by characters from 'par'. The total length of
|
||||
line is no longer than 'line_length'.
|
||||
|
||||
*/
|
||||
void format_paragraph(std::ostream& os,
|
||||
std::string par,
|
||||
unsigned first_column_width,
|
||||
unsigned indent,
|
||||
unsigned line_length)
|
||||
{
|
||||
// Through reminder of this function, 'line_length' will
|
||||
// be the length available for characters, not including
|
||||
// indent.
|
||||
assert(indent < line_length);
|
||||
line_length -= indent;
|
||||
|
||||
// index of tab (if present) is used as additional indent relative
|
||||
// to first_column_width if paragrapth is spanned over multiple
|
||||
// lines if tab is not on first line it is ignored
|
||||
@@ -319,16 +355,16 @@ namespace boost { namespace program_options {
|
||||
|
||||
// this assert may fail due to user error or
|
||||
// environment conditions!
|
||||
assert(par_indent < (line_length - first_column_width));
|
||||
assert(par_indent < line_length);
|
||||
|
||||
// ignore tab if not on first line
|
||||
if (par_indent >= (line_length - first_column_width))
|
||||
if (par_indent >= line_length)
|
||||
{
|
||||
par_indent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (par.size() < (line_length - first_column_width))
|
||||
if (par.size() < line_length)
|
||||
{
|
||||
os << par;
|
||||
}
|
||||
@@ -337,17 +373,16 @@ namespace boost { namespace program_options {
|
||||
string::const_iterator line_begin = par.begin();
|
||||
const string::const_iterator par_end = par.end();
|
||||
|
||||
bool first_line = true; // of current paragraph!
|
||||
|
||||
unsigned indent = first_column_width;
|
||||
bool first_line = true; // of current paragraph!
|
||||
|
||||
while (line_begin < par_end) // paragraph lines
|
||||
{
|
||||
if (!first_line)
|
||||
{
|
||||
// trimm leading single spaces
|
||||
// if (firstchar == ' ') &&
|
||||
// ((exists(firstchar + 1) && (firstchar + 1 != ' '))
|
||||
// If line starts with space, but second character
|
||||
// is not space, remove the leading space.
|
||||
// We don't remove double spaces because those
|
||||
// might be intentianal.
|
||||
if ((*line_begin == ' ') &&
|
||||
((line_begin + 1 < par_end) &&
|
||||
(*(line_begin + 1) != ' ')))
|
||||
@@ -356,35 +391,30 @@ namespace boost { namespace program_options {
|
||||
}
|
||||
}
|
||||
|
||||
string::const_iterator line_end;
|
||||
|
||||
if (line_begin + (line_length - indent) > par_end)
|
||||
{
|
||||
line_end = par_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
line_end = line_begin + (line_length - indent);
|
||||
}
|
||||
// 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
|
||||
// if (lastchar != ' ') &&
|
||||
// ((exists(lastchar + 1) && (lastchar + 1 != ' '))
|
||||
// Is line_end between two non-space characters?
|
||||
if ((*(line_end - 1) != ' ') &&
|
||||
((line_end < par_end) && (*line_end != ' ')))
|
||||
{
|
||||
// find last ' ' in the second half of the current paragraph line
|
||||
string::const_iterator last_space =
|
||||
find(reverse_iterator<string::const_iterator>(line_end - 1),
|
||||
reverse_iterator<string::const_iterator>(line_begin - 1),
|
||||
find(reverse_iterator<string::const_iterator>(line_end),
|
||||
reverse_iterator<string::const_iterator>(line_begin),
|
||||
' ')
|
||||
.base();
|
||||
|
||||
if (last_space != line_begin - 1)
|
||||
if (last_space != line_begin)
|
||||
{
|
||||
// is last_space within the second half ot the
|
||||
// is last_space within the second half of the
|
||||
// current line
|
||||
if (unsigned(distance(last_space, line_end)) <
|
||||
if ((unsigned)std::distance(last_space, line_end) <
|
||||
(line_length - indent) / 2)
|
||||
{
|
||||
line_end = last_space;
|
||||
@@ -397,7 +427,7 @@ namespace boost { namespace program_options {
|
||||
|
||||
if (first_line)
|
||||
{
|
||||
indent = first_column_width + par_indent;
|
||||
indent += par_indent;
|
||||
first_line = false;
|
||||
}
|
||||
|
||||
@@ -436,7 +466,7 @@ namespace boost { namespace program_options {
|
||||
assert(line_length > first_column_width);
|
||||
|
||||
// Note: can't use 'tokenizer' as name of typedef -- borland
|
||||
// will consider subsequence uses of 'tokenizer' as uses of
|
||||
// will consider uses of 'tokenizer' below as uses of
|
||||
// boost::tokenizer, not typedef.
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tok;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,14 +35,25 @@ 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
|
||||
if (name.empty())
|
||||
continue;
|
||||
|
||||
// Ignore unregistered option. The 'unregistered'
|
||||
// field can be true only if user has explicitly asked
|
||||
// to allow unregistered options. We can't store them
|
||||
// to variables map (lacking any information about paring),
|
||||
// so just ignore them.
|
||||
if (options.options[i].unregistered)
|
||||
continue;
|
||||
|
||||
// If option has final value, skip this assignment
|
||||
if (xm.m_final.count(name))
|
||||
continue;
|
||||
@@ -84,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("");
|
||||
|
||||
@@ -12,10 +12,12 @@ namespace boost { namespace program_options {
|
||||
|
||||
using namespace std;
|
||||
|
||||
// The rules for windows command line are pretty funny, see
|
||||
// Take a command line string and splits in into tokens, according
|
||||
// to the rules windows command line processor uses.
|
||||
//
|
||||
// The rules are pretty funny, see
|
||||
// http://article.gmane.org/gmane.comp.lib.boost.user/3005
|
||||
// http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
|
||||
|
||||
BOOST_PROGRAM_OPTIONS_DECL
|
||||
std::vector<std::string> split_winmain(const std::string& input)
|
||||
{
|
||||
@@ -23,7 +25,7 @@ namespace boost { namespace program_options {
|
||||
|
||||
string::const_iterator i = input.begin(), e = input.end();
|
||||
for(;i != e; ++i)
|
||||
if (!isspace(*i))
|
||||
if (!isspace((unsigned char)*i))
|
||||
break;
|
||||
|
||||
if (i != e) {
|
||||
@@ -55,11 +57,11 @@ namespace boost { namespace program_options {
|
||||
current.append(backslash_count, '\\');
|
||||
backslash_count = 0;
|
||||
}
|
||||
if (isspace(*i) && !inside_quoted) {
|
||||
if (isspace((unsigned char)*i) && !inside_quoted) {
|
||||
// Space outside quoted section terminate the current argument
|
||||
result.push_back(current);
|
||||
current.resize(0);
|
||||
for(;i != e && isspace(*i); ++i)
|
||||
for(;i != e && isspace((unsigned char)*i); ++i)
|
||||
;
|
||||
--i;
|
||||
} else {
|
||||
@@ -86,7 +88,7 @@ namespace boost { namespace program_options {
|
||||
{
|
||||
vector<wstring> result;
|
||||
vector<string> aux = split_winmain(to_internal(cmdline));
|
||||
for (unsigned i = 0, e = result.size(); i < e; ++i)
|
||||
for (unsigned i = 0, e = aux.size(); i < e; ++i)
|
||||
result.push_back(from_utf8(aux[i]));
|
||||
return result;
|
||||
}
|
||||
|
||||
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,7 +2,7 @@
|
||||
project
|
||||
: requirements
|
||||
<library>../build//boost_program_options
|
||||
<library>/boost/test//boost_test_exec_monitor
|
||||
<library>/boost/test//boost_test_exec_monitor/<link>static
|
||||
<link>static
|
||||
|
||||
# <define>_GLIBCXX_CONCEPT_CHECKS
|
||||
@@ -13,7 +13,8 @@ rule po-test ( source )
|
||||
{
|
||||
return
|
||||
[ run $(source) ]
|
||||
[ run $(source) : : : <link>shared : $(source:B)_dll ]
|
||||
[ run $(source) : : : <link>shared <define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
|
||||
: $(source:B)_dll ]
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,17 +14,47 @@ using namespace boost;
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
void test_type()
|
||||
{
|
||||
options_description desc;
|
||||
desc.add_options()
|
||||
("foo", value<int>(), "")
|
||||
("bar", value<std::string>(), "")
|
||||
;
|
||||
|
||||
const typed_value_base* b = dynamic_cast<const typed_value_base*>
|
||||
(desc.find("foo", false).semantic().get());
|
||||
BOOST_CHECK(b);
|
||||
BOOST_CHECK(b->value_type() == typeid(int));
|
||||
|
||||
const typed_value_base* b2 = dynamic_cast<const typed_value_base*>
|
||||
(desc.find("bar", false).semantic().get());
|
||||
BOOST_CHECK(b2);
|
||||
BOOST_CHECK(b2->value_type() == typeid(std::string));
|
||||
}
|
||||
|
||||
void test_approximation()
|
||||
{
|
||||
options_description desc;
|
||||
desc.add_options()
|
||||
("foo", new untyped_value())
|
||||
("fee", new untyped_value())
|
||||
("baz", new untyped_value());
|
||||
("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())
|
||||
;
|
||||
|
||||
BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "foo");
|
||||
|
||||
BOOST_CHECK_EQUAL(desc.find("all", true).long_name(), "all");
|
||||
BOOST_CHECK_EQUAL(desc.find("all-ch", true).long_name(), "all-chroots");
|
||||
|
||||
|
||||
// BOOST_CHECK(desc.count_approx("foo") == 1);
|
||||
// set<string> a = desc.approximations("f");
|
||||
// BOOST_CHECK(a.size() == 2);
|
||||
@@ -32,8 +62,25 @@ void test_approximation()
|
||||
// BOOST_CHECK(*(++a.begin()) == "foo");
|
||||
}
|
||||
|
||||
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 test_main(int, char* [])
|
||||
{
|
||||
test_type();
|
||||
test_approximation();
|
||||
test_formatting();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
using namespace boost::program_options;
|
||||
// We'll use po::value everywhere to workaround vc6 bug.
|
||||
namespace po = boost::program_options;
|
||||
@@ -132,6 +133,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);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -192,11 +203,49 @@ void test_environment()
|
||||
// which already has a value.
|
||||
}
|
||||
|
||||
void test_unregistered()
|
||||
{
|
||||
options_description desc;
|
||||
|
||||
char* cmdline1_[] = { "--foo=12", "--bar", "1"};
|
||||
vector<string> cmdline1 = sv(cmdline1_,
|
||||
sizeof(cmdline1_)/sizeof(cmdline1_[0]));
|
||||
vector<option> a1 =
|
||||
command_line_parser(cmdline1).options(desc).allow_unregistered().run()
|
||||
.options;
|
||||
|
||||
BOOST_REQUIRE(a1.size() == 3);
|
||||
BOOST_CHECK(a1[0].string_key == "foo");
|
||||
BOOST_CHECK(a1[0].unregistered == true);
|
||||
BOOST_REQUIRE(a1[0].value.size() == 1);
|
||||
BOOST_CHECK(a1[0].value[0] == "12");
|
||||
BOOST_CHECK(a1[1].string_key == "bar");
|
||||
BOOST_CHECK(a1[1].unregistered == true);
|
||||
BOOST_CHECK(a1[2].string_key == "");
|
||||
BOOST_CHECK(a1[2].unregistered == false);
|
||||
|
||||
|
||||
vector<string> a2 = collect_unrecognized(a1, include_positional);
|
||||
BOOST_CHECK(a2[0] == "--foo=12");
|
||||
BOOST_CHECK(a2[1] == "--bar");
|
||||
BOOST_CHECK(a2[2] == "1");
|
||||
|
||||
// Test that storing unregisted options has no effect
|
||||
variables_map vm;
|
||||
|
||||
store(command_line_parser(cmdline1).options(desc).
|
||||
allow_unregistered().run(),
|
||||
vm);
|
||||
|
||||
BOOST_CHECK_EQUAL(vm.size(), 0u);
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
{
|
||||
test_command_line();
|
||||
test_config_file();
|
||||
test_environment();
|
||||
test_unregistered();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,28 +49,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)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <boost/progress.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
@@ -94,7 +93,7 @@ void test_convert(const std::string& input,
|
||||
facet);
|
||||
}
|
||||
|
||||
assert(output.size()*2 == expected_output.size());
|
||||
BOOST_CHECK(output.size()*2 == expected_output.size());
|
||||
|
||||
for(unsigned i = 0; i < output.size(); ++i) {
|
||||
|
||||
@@ -103,20 +102,20 @@ void test_convert(const std::string& input,
|
||||
low &= 0xFF;
|
||||
unsigned low2 = expected_output[2*i];
|
||||
low2 &= 0xFF;
|
||||
assert(low == low2);
|
||||
BOOST_CHECK(low == low2);
|
||||
}
|
||||
{
|
||||
unsigned high = output[i];
|
||||
high >>= 8;
|
||||
high &= 0xFF;
|
||||
unsigned high2 = expected_output[2*i+1];
|
||||
assert(high == high2);
|
||||
BOOST_CHECK(high == high2);
|
||||
}
|
||||
}
|
||||
|
||||
string ref = boost::to_8_bit(output, facet);
|
||||
|
||||
assert(ref == input);
|
||||
BOOST_CHECK(ref == input);
|
||||
}
|
||||
|
||||
int test_main(int ac, char* av[])
|
||||
|
||||
Reference in New Issue
Block a user