Compare commits

..

2 Commits

Author SHA1 Message Date
nobody
767cacbced This commit was manufactured by cvs2svn to create tag
'Version_1_33_0'.

[SVN r30532]
2005-08-12 03:25:34 +00:00
nobody
3ae92db179 This commit was manufactured by cvs2svn to create branch 'RC_1_33_0'.
[SVN r30300]
2005-07-28 18:22:24 +00:00
59 changed files with 680 additions and 2522 deletions

49
build/Jamfile Normal file
View File

@@ -0,0 +1,49 @@
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

View File

@@ -1,19 +1,28 @@
project boost/program_options
: source-location ../src
:
source-location ../src
;
SOURCES =
cmdline config_file options_description parsers variables_map
value_semantic positional_options utf8_codecvt_facet
convert winmain split
convert winmain
;
lib boost_program_options
: $(SOURCES).cpp
: <link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1 # tell source we're building dll's
:
: <link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
$(SOURCES).cpp
:
<link>shared:<define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1 # tell source we're building dll's
;
boost-install boost_program_options ;
install dist-lib
:
boost_program_options
:
<install-type>LIB
<location>../../../dist/lib
;
explicit dist-lib ;

View File

@@ -2,12 +2,7 @@
import toolset ;
toolset.using doxygen ;
boostbook program_option
: program_options.xml
: <implicit-dependency>autodoc
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
boostbook program_option : program_options.xml ;
doxygen autodoc
: [ glob ../../../boost/program_options/*.hpp ] ;

View File

@@ -52,7 +52,8 @@
<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).
facet (which may be specified by the user(which can be
specified by the user)
</para>
</listitem>
</itemizedlist>
@@ -82,7 +83,7 @@
</para>
<para>The Unicode support outlined above is not complete. For example, we
don't support Unicode option names. Unicode support is hard and
don't plan allow Unicode in 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

View File

@@ -107,7 +107,7 @@ if (vm.count("response-file")) {
// Load the file and tokenize it
ifstream ifs(vm["response-file"].as<string>().c_str());
if (!ifs) {
cout << "Could not open the response file\n";
cout << "Could no open the response file\n";
return 1;
}
// Read the whole file into a string
@@ -115,8 +115,7 @@ if (vm.count("response-file")) {
ss << ifs.rdbuf();
// Split the file content
char_separator<char> sep(" \n\r");
std::string ResponsefileContents( ss.str() );
tokenizer<char_separator<char> > tok(ResponsefileContents, sep);
tokenizer<char_separator<char> > tok(ss.str(), sep);
vector<string> args;
copy(tok.begin(), tok.end(), back_inserter(args));
// Parse the file and store the options
@@ -147,7 +146,7 @@ if (vm.count("response-file")) {
vector&lt;string&gt; args = split_winmain(lpCmdLine);
store(command_line_parser(args).options(desc).run(), vm);
</programlisting>
The <code>split_winmain</code> function is overloaded for <code>wchar_t</code> strings, so can
The function is an overload for <code>wchar_t</code> strings, so can
also be used in Unicode applications.
</para>
@@ -185,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>(),
("help-module", value<string>()->implicit(),
"produce a help for a given module")
("version", "output the version number")
;
@@ -285,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_occurrence(v);
validators::check_first_occurence(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);
@@ -296,7 +295,7 @@ void validate(boost::any& v,
if (regex_match(s, match, r)) {
v = any(magic_number(lexical_cast<int>(match[1])));
} else {
throw validation_error(validation_error::invalid_option_value);
throw validation_error("invalid value");
}
}
]]>
@@ -399,49 +398,13 @@ $ 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(argc, argv).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&lt;string&gt; to_pass_further = collect_unrecognized(parsed.options, include_positional);
</programlisting>
</para>
</section>
</section>
<!--
Local Variables:
mode: nxml
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
mode: xml
sgml-indent-data: t
sgml-parent-document: ("program_options.xml" "section")
sgml-set-face: t
End:
-->

View File

@@ -1,14 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_options.html">
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_option.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
&nbsp;<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>
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
</body>
</html>

View File

@@ -181,7 +181,7 @@ options_description desc;
desc.add_options()
("help", "produce help message")
("compression", value&lt;string&gt;(), "compression level")
("verbose", value&lt;string&gt;()->zero_tokens(), "verbosity level")
("verbose", value&lt;string&gt;()->implicit(), "verbosity level")
("email", value&lt;string&gt;()->multitoken(), "email to send to")
;
</programlisting>
@@ -348,18 +348,11 @@ positional_options_description pd; pd.add("input-file", 1);
given the same name.
<programlisting>
positional_options_description pd;
pd.add("output-file", 2).add("input-file", -1);
pd.add("output-file", 2).add_optional("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>
@@ -478,45 +471,7 @@ notify(vm);
<title>Specific parsers</title>
<section>
<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>
<title>Environment variables</title>
<para><firstterm>Environment variables</firstterm> are string variables
which are available to all programs via the <code>getenv</code> function
@@ -526,7 +481,7 @@ gui.accessibility.visual_bell=yes
<filename>autoexec.bat</filename> file or (on recent versions) the
<filename>Control Panel/System/Advanced/Environment Variables</filename>
dialog, and on Unix &#x2014;, 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>
@@ -605,15 +560,8 @@ gui.accessibility.visual_bell=yes
<row>
<entry>&parse_command_line;</entry>
<entry>parses command line (simpified interface)</entry>
<entry>parses command line</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>

View File

@@ -37,10 +37,3 @@
<!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>">

View File

@@ -83,5 +83,5 @@
<xi:include href="design.xml"/>
<xi:include href="acknowledgements.xml"/>
<xi:include href="autodoc.xml"/>
<xi:include href="autodoc.boostbook"/>
</library>

View File

@@ -1,8 +1,4 @@
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.
I.e scanning the parsed options and creating new variables_map when we see
a positional option. (Email from Tony).

View File

@@ -77,13 +77,13 @@ if (vm.count(&quot;compression&quot;)) {
<para>It's now a good time to try compiling the code yourself, but if
you're not yet ready, here's an example session:
<screen>
$ <userinput>bin/gcc/debug/first</userinput>
$<userinput>bin/gcc/debug/first</userinput>
Compression level was not set.
$ <userinput>bin/gcc/debug/first --help</userinput>
$<userinput>bin/gcc/debug/first --help</userinput>
Allowed options:
--help : produce help message
--compression arg : set compression level
$ <userinput>bin/gcc/debug/first --compression 10</userinput>
$<userinput>bin/gcc/debug/first --compression 10</userinput>
Compression level was set to 10.
</screen>
</para>
@@ -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
<filename>example/options_description.cpp</filename>.</para>
"example/options_description.cpp".</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,29 +115,21 @@ desc.add_options()
</programlisting>
</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 "--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>"optimization"</literal> option shows two new features. First, we specify
<para>The "optimization" option shows two new features. First, we specify
the address of the variable(<code>&amp;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 <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
<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
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:
@@ -199,16 +191,16 @@ cout &lt;&lt; &quot;Optimization level is &quot; &lt;&lt; opt &lt;&lt; &quot;\n&
<para>Here's an example session:
<screen>
$ <userinput>bin/gcc/debug/options_description --help</userinput>
$<userinput>bin/gcc/debug/options_description --help</userinput>
Usage: options_description [options]
Allowed options:
--help : produce help message
--optimization arg : optimization level
-I [ --include-path ] arg : include path
--input-file arg : input file
$ <userinput>bin/gcc/debug/options_description</userinput>
$bin/gcc/debug/options_description
Optimization level is 10
$ <userinput>bin/gcc/debug/options_description --optimization 4 -I foo a.cpp</userinput>
$<userinput>bin/gcc/debug/options_description --optimization 4 -I foo a.cpp</userinput>
Include paths are: foo
Input files are: a.cpp
Optimization level is 4
@@ -308,10 +300,10 @@ visible.add(generic).add(config);
<para>Here's an example session:
<screen>
$ <userinput>bin/gcc/debug/multiple_sources</userinput>
$<userinput>bin/gcc/debug/multiple_sources</userinput>
Include paths are: /opt
Optimization level is 1
$ <userinput>bin/gcc/debug/multiple_sources --help</userinput>
$<userinput>bin/gcc/debug/multiple_sources --help</userinput>
Allows options:
Generic options:
@@ -322,7 +314,7 @@ Configuration:
--optimization n : optimization level
-I [ --include-path ] path : include path
$ <userinput>bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp</userinput>
$<userinput>bin/gcc/debug/multiple_sources --optimization=4 -I foo a.cpp b.cpp</userinput>
Include paths are: foo /opt
Input files are: a.cpp b.cpp
Optimization level is 4
@@ -345,7 +337,7 @@ Optimization level is 4
<!--
Local Variables:
mode: nxml
mode: xml
sgml-indent-data: t
sgml-parent-document: ("program_options.xml" "section")
sgml-set-face: t

23
example/Jamfile Normal file
View File

@@ -0,0 +1,23 @@
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 ;

View File

@@ -1,8 +1,7 @@
project
: requirements <library>../build//boost_program_options
: requirements <library>../build//program_options
<hardcode-dll-paths>true
<link>static
;
exe first : first.cpp ;
@@ -10,5 +9,7 @@ exe options_description : options_description.cpp ;
exe multiple_sources : multiple_sources.cpp ;
exe custom_syntax : custom_syntax.cpp ;
exe real : real.cpp ;
exe regex : regex.cpp /boost/regex//boost_regex ;
exe a : a.cpp ;
#exe real : real.cpp ;
#exe regex : regex.cpp /boost/regex//boost_regex ;

View File

@@ -27,16 +27,13 @@ int main(int ac, char* av[])
{
try {
int opt;
string config_file;
// Declare a group of options that will be
// allowed only on command line
po::options_description generic("Generic options");
generic.add_options()
("version,v", "print version string")
("help", "produce help message")
("config,c", po::value<string>(&config_file)->default_value("multiple_sources.cfg"),
"name of a file of a configuration.")
("help", "produce help message")
;
// Declare a group of options that will be
@@ -74,19 +71,10 @@ int main(int ac, char* av[])
po::variables_map vm;
store(po::command_line_parser(ac, av).
options(cmdline_options).positional(p).run(), vm);
ifstream ifs("multiple_sources.cfg");
store(parse_config_file(ifs, config_file_options), vm);
notify(vm);
ifstream ifs(config_file.c_str());
if (!ifs)
{
cout << "can not open config file: " << config_file << "\n";
return 0;
}
else
{
store(parse_config_file(ifs, config_file_options), vm);
notify(vm);
}
if (vm.count("help")) {
cout << visible << "\n";

View File

@@ -26,17 +26,11 @@ 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")
@@ -68,16 +62,9 @@ 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(std::exception& e)
catch(exception& e)
{
cout << e.what() << "\n";
return 1;

View File

@@ -43,7 +43,7 @@ public:
*/
void validate(boost::any& v,
const std::vector<std::string>& values,
magic_number*, int)
magic_number* target_type, int)
{
static regex r("\\d\\d\\d-(\\d\\d\\d)");
@@ -61,7 +61,7 @@ void validate(boost::any& v,
if (regex_match(s, match, r)) {
v = any(magic_number(lexical_cast<int>(match[1])));
} else {
throw validation_error(validation_error::invalid_option_value);
throw validation_error("invalid value");
}
}
@@ -94,7 +94,7 @@ int main(int ac, char* av[])
<< vm["magic"].as<magic_number>().n << "\"\n";
}
}
catch(std::exception& e)
catch(exception& e)
{
cout << e.what() << "\n";
}

View File

@@ -70,8 +70,7 @@ int main(int ac, char* av[])
ss << ifs.rdbuf();
// Split the file content
char_separator<char> sep(" \n\r");
string sstr = ss.str();
tokenizer<char_separator<char> > tok(sstr, sep);
tokenizer<char_separator<char> > tok(ss.str(), sep);
vector<string> args;
copy(tok.begin(), tok.end(), back_inserter(args));
// Parse the file and store the options
@@ -88,7 +87,7 @@ int main(int ac, char* av[])
cout << "Magic value: " << vm["magic"].as<int>() << "\n";
}
}
catch (std::exception& e) {
catch(exception& e) {
cout << e.what() << "\n";
}
}

View File

@@ -3,8 +3,6 @@
// 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

View File

@@ -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 options is also configurable.
for short option is also configurable.
Option's value can be specified in the same token as name
Option's value can be specified in the same token as value
("--foo=bar"), or in the next token.
It's possible to introduce long options by the same character as
short options, see allow_long_disguise.
It's possible to introduce long option by the same character as
long option, see allow_long_disguise.
Finally, guessing (specifying only prefix of option) and case
insensitive processing are supported.
@@ -26,7 +26,7 @@ namespace boost { namespace program_options { namespace command_line_style {
enum style_t {
/// Allow "--long_name" style
allow_long = 1,
/// Allow "-<single character" style
/// Alow "-<single character" style
allow_short = allow_long << 1,
/// Allow "-" in short options
allow_dash_for_short = allow_short << 1,
@@ -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 next token for
/** Allow option parameter in the same token for
long options. */
long_allow_next = long_allow_adjacent << 1,
/** Allow option parameter in the same token for
@@ -59,22 +59,17 @@ 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 if guessing is in effect.
long option name is guessing is in effect.
*/
allow_guessing = allow_sticky << 1,
/** Ignore the difference in case for long options.
/** Ignore the difference in case for options.
@todo Should this apply to long options only?
*/
long_case_insensitive = allow_guessing << 1,
/** Ignore the difference in case for short options.
*/
short_case_insensitive = long_case_insensitive << 1,
/** Ignore the difference in case for all options.
*/
case_insensitive = (long_case_insensitive | short_case_insensitive),
case_insensitive = allow_guessing << 1,
/** Allow long options with single option starting character,
e.g <tt>-foo=10</tt>
*/
allow_long_disguise = short_case_insensitive << 1,
allow_long_disguise = case_insensitive << 1,
/** The more-or-less traditional unix style. */
unix_style = (allow_short | short_allow_adjacent | short_allow_next
| allow_long | long_allow_adjacent | long_allow_next

View File

@@ -22,11 +22,6 @@
#include <string>
#include <vector>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4251) // class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'boost::program_options::positional_options_description'
#endif
namespace boost { namespace program_options { namespace detail {
/** Command line parser class. Main requirements were:
@@ -113,15 +108,13 @@ namespace boost { namespace program_options { namespace detail {
void extra_style_parser(style_parser s);
void check_style(int style) const;
bool is_style_active(style_t style) const;
void init(const std::vector<std::string>& args);
void
finish_option(option& opt,
std::vector<std::string>& other_tokens,
const std::vector<style_parser>& style_parsers);
std::vector<std::string>& other_tokens);
// Copies of input.
std::vector<std::string> args;
@@ -139,9 +132,5 @@ namespace boost { namespace program_options { namespace detail {
}}}
#if defined(BOOST_MSVC)
# pragma warning (pop)
#endif
#endif

View File

@@ -70,8 +70,7 @@ 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,
bool allow_unregistered = false);
const std::set<std::string>& allowed_options);
virtual ~common_config_file_iterator() {}
@@ -104,7 +103,6 @@ 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>
@@ -118,8 +116,7 @@ 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,
bool allow_unregistered = false);
const std::set<std::string>& allowed_options);
private: // base overrides
@@ -142,9 +139,8 @@ 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,
bool allow_unregistered)
: common_config_file_iterator(allowed_options, allow_unregistered)
const std::set<std::string>& allowed_options)
: common_config_file_iterator(allowed_options)
{
this->is.reset(&is, null_deleter());
get();

View File

@@ -8,8 +8,6 @@
#include <boost/program_options/detail/convert.hpp>
#include <iterator>
namespace boost { namespace program_options {
namespace detail {
@@ -29,18 +27,18 @@ namespace boost { namespace program_options {
template<class charT>
basic_command_line_parser<charT>::
basic_command_line_parser(const std::vector<
std::basic_string<charT> >& xargs)
: detail::cmdline(to_internal(xargs))
std::basic_string<charT> >& args)
: detail::cmdline(to_internal(args))
{}
template<class charT>
basic_command_line_parser<charT>::
basic_command_line_parser(int argc, const charT* const argv[])
basic_command_line_parser(int argc, charT* argv[])
: 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, const charT* const*>(argv+1, argv+argc+!argc)))
to_internal(detail::make_vector<charT, charT**>(argv+1, argv+argc)))
{}
@@ -64,9 +62,9 @@ namespace boost { namespace program_options {
template<class charT>
basic_command_line_parser<charT>&
basic_command_line_parser<charT>::style(int xstyle)
basic_command_line_parser<charT>::style(int style)
{
detail::cmdline::style(xstyle);
detail::cmdline::style(style);
return *this;
}
@@ -78,24 +76,6 @@ 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()
@@ -111,7 +91,7 @@ namespace boost { namespace program_options {
template<class charT>
basic_parsed_options<charT>
parse_command_line(int argc, const charT* const argv[],
parse_command_line(int argc, charT* argv[],
const options_description& desc,
int style,
function1<std::pair<std::string, std::string>,
@@ -121,26 +101,6 @@ 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

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
// Copyright © 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"

View File

@@ -16,13 +16,7 @@ namespace boost { namespace program_options {
std::string
typed_value<T, charT>::name() const
{
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()) {
if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
return arg + " (=" + m_default_value_as_text + ")";
} else {
return arg;
@@ -33,7 +27,7 @@ namespace boost { namespace program_options {
void
typed_value<T, charT>::notify(const boost::any& value_store) const
{
const T* value = boost::any_cast<T>(&value_store);
const T* value = boost::any_cast<const T>(&value_store);
if (m_store_to) {
*m_store_to = *value;
}
@@ -55,12 +49,13 @@ namespace boost { namespace program_options {
{
static std::basic_string<charT> empty;
if (v.size() > 1)
boost::throw_exception(validation_error(validation_error::multiple_values_not_allowed));
else if (v.size() == 1)
throw validation_error("multiple values not allowed");
if (v.size() == 1)
return v.front();
else if (!allow_empty)
boost::throw_exception(validation_error(validation_error::at_least_one_value_required));
return empty;
else if (allow_empty)
return empty;
else
throw validation_error("at least one value required");
}
/* Throws multiple_occurrences if 'value' is not empty. */
@@ -139,14 +134,7 @@ namespace boost { namespace program_options {
for (unsigned i = 0; i < s.size(); ++i)
{
try {
/* 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> > cv;
cv.push_back(s[i]);
validate(a, cv, (T*)0, 0);
tv->push_back(boost::any_cast<T>(a));
tv->push_back(boost::lexical_cast<T>(s[i]));
}
catch(const bad_lexical_cast& /*e*/) {
boost::throw_exception(invalid_option_value(s[i]));
@@ -160,13 +148,7 @@ namespace boost { namespace program_options {
xparse(boost::any& value_store,
const std::vector<std::basic_string<charT> >& new_tokens) const
{
// 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);
validate(value_store, new_tokens, (T*)0, 0);
}
template<class T>

View File

@@ -13,110 +13,59 @@
#include <stdexcept>
#include <vector>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4275) // non dll-interface class 'std::logic_error' used as base for dll-interface class 'boost::program_options::error'
# pragma warning (disable:4251) // class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'boost::program_options::ambiguous_option'
#endif
namespace boost { namespace program_options {
/** Base class for all errors in the library. */
class BOOST_PROGRAM_OPTIONS_DECL error : public std::logic_error {
public:
error(const std::string& xwhat) : std::logic_error(xwhat) {}
error(const std::string& what) : std::logic_error(what) {}
};
class BOOST_PROGRAM_OPTIONS_DECL invalid_syntax : public error {
public:
enum kind_t {
long_not_allowed = 30,
long_adjacent_not_allowed,
short_adjacent_not_allowed,
empty_adjacent_parameter,
missing_parameter,
extra_parameter,
unrecognized_line
};
invalid_syntax(const std::string& tokens, kind_t kind);
invalid_syntax(const std::string& tokens, const std::string& msg)
: error(std::string(msg).append(" in '").append(tokens).append("'")),
tokens(tokens), msg(msg)
{}
// gcc says that throw specification on dtor is loosened
// without this line
~invalid_syntax() throw() {}
kind_t kind() const;
const std::string& tokens() const;
protected:
/** Used to convert kind_t to a related error text */
static std::string error_message(kind_t kind);
private:
// TODO: copy ctor might throw
std::string m_tokens;
kind_t m_kind;
std::string tokens, msg;
};
/** Class thrown when option name is not recognized. */
class BOOST_PROGRAM_OPTIONS_DECL unknown_option : public error {
public:
unknown_option(const std::string& name)
: error(std::string("unknown option ").append(name)),
m_option_name(name)
: error(std::string("unknown option ").append(name))
{}
// gcc says that throw specification on dtor is loosened
// without this line
~unknown_option() throw() {}
const std::string& get_option_name() const throw();
private:
std::string m_option_name;
};
/** Class thrown when there's ambiguity amoung several possible options. */
class BOOST_PROGRAM_OPTIONS_DECL ambiguous_option : public error {
public:
ambiguous_option(const std::string& name,
const std::vector<std::string>& xalternatives)
: error(std::string("ambiguous option ").append(name))
, m_alternatives(xalternatives)
, m_option_name(name)
const std::vector<std::string>& alternatives)
: error(std::string("ambiguous option ").append(name)),
alternatives(alternatives)
{}
~ambiguous_option() throw() {}
const std::string& get_option_name() const throw();
const std::vector<std::string>& alternatives() const throw();
private:
// TODO: copy ctor might throw
std::vector<std::string> m_alternatives;
std::string m_option_name;
std::vector<std::string> alternatives;
};
/** Class thrown when there are several option values, but
user called a method which cannot return them all. */
class BOOST_PROGRAM_OPTIONS_DECL multiple_values : public error {
public:
multiple_values()
: error("multiple values")
, m_option_name() {}
~multiple_values() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw();
private:
std::string m_option_name; // The name of the option which
// caused the exception.
multiple_values(const std::string& what) : error(what) {}
};
/** Class thrown when there are several occurrences of an
@@ -124,58 +73,22 @@ namespace boost { namespace program_options {
them all. */
class BOOST_PROGRAM_OPTIONS_DECL multiple_occurrences : public error {
public:
multiple_occurrences()
: error("multiple occurrences")
, m_option_name() {}
~multiple_occurrences() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw();
private:
std::string m_option_name; // The name of the option which
// caused the exception.
multiple_occurrences(const std::string& what) : error(what) {}
};
/** Class thrown when value of option is incorrect. */
class BOOST_PROGRAM_OPTIONS_DECL validation_error : public error {
public:
enum kind_t {
multiple_values_not_allowed = 30,
at_least_one_value_required,
invalid_bool_value,
invalid_option_value,
invalid_option
};
validation_error(kind_t kind,
const std::string& option_value = "",
const std::string& option_name = "");
validation_error(const std::string& what) : error(what) {}
~validation_error() throw() {}
void set_option_name(const std::string& option);
const std::string& get_option_name() const throw();
const char* what() const throw();
protected:
/** Used to convert kind_t to a related error text */
static std::string error_message(kind_t kind);
private:
kind_t m_kind;
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.
std::string m_option_value; // Optional: value of the option m_options_name
mutable std::string m_message; // For on-demand formatting in 'what'
const char* what() const throw();
};
/** Class thrown if there is an invalid option value givenn */
class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value
: public validation_error
{
@@ -186,23 +99,39 @@ namespace boost { namespace program_options {
#endif
};
/** Class thrown when there are too many positional options.
This is a programming error.
*/
/** Class thrown when there are too many positional options. */
class BOOST_PROGRAM_OPTIONS_DECL too_many_positional_options_error : public error {
public:
too_many_positional_options_error()
: error("too many positional options")
{}
too_many_positional_options_error(const std::string& what)
: error(what) {}
};
/** Class thrown when there are too few positional options. */
class BOOST_PROGRAM_OPTIONS_DECL too_few_positional_options_error : public error {
public:
too_few_positional_options_error(const std::string& what)
: error(what) {}
};
/** Class thrown when there are syntax errors in given command line */
class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_syntax : public invalid_syntax {
public:
enum kind_t {
long_not_allowed = 30,
long_adjacent_not_allowed,
short_adjacent_not_allowed,
empty_adjacent_parameter,
missing_parameter,
extra_parameter
};
invalid_command_line_syntax(const std::string& tokens, kind_t kind);
kind_t kind() const;
protected:
static std::string error_message(kind_t kind);
private:
kind_t m_kind;
};
/** Class thrown when there are programming error related to style */
class BOOST_PROGRAM_OPTIONS_DECL invalid_command_line_style : public error {
public:
invalid_command_line_style(const std::string& msg)
@@ -210,34 +139,7 @@ namespace boost { namespace program_options {
{}
};
/** Class thrown if config file can not be read */
class BOOST_PROGRAM_OPTIONS_DECL reading_file : public error {
public:
reading_file(const char* filename)
: error(std::string("can not read file ").append(filename))
{}
};
/** Class thrown when a required/mandatory option is missing */
class BOOST_PROGRAM_OPTIONS_DECL required_option : public error {
public:
required_option(const std::string& name)
: error(std::string("missing required option ").append(name))
, m_option_name(name)
{}
~required_option() throw() {}
const std::string& get_option_name() const throw();
private:
std::string m_option_name; // The name of the option which
// caused the exception.
};
}}
#if defined(BOOST_MSVC)
# pragma warning (pop)
#endif
#endif

View File

@@ -23,17 +23,10 @@ namespace boost { namespace program_options {
template<class charT>
class basic_option {
public:
basic_option()
: position_key(-1)
, unregistered(false)
, case_insensitive(false)
{}
basic_option(const std::string& xstring_key,
const std::vector< std::string> &xvalue)
: string_key(xstring_key)
, value(xvalue)
, unregistered(false)
, case_insensitive(false)
basic_option() : position_key(-1), unregistered(false) {}
basic_option(const std::string& string_key,
const std::vector< std::string> &value)
: string_key(string_key), value(value), unregistered(false)
{}
/** String key of this option. Intentionally independent of the template
@@ -48,19 +41,10 @@ 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. The original tokens can be
recovered from the "original_tokens" member.
*/
syntactic parsing of source. */
bool unregistered;
/** True if string_key has to be handled
case insensitive.
*/
bool case_insensitive;
};
typedef basic_option<char> option;
typedef basic_option<wchar_t> woption;

View File

@@ -25,12 +25,6 @@
#include <iosfwd>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4251) // class 'boost::shared_ptr<T>' needs to have dll-interface to be used by clients of class 'boost::program_options::option_description'
#endif
/** Boost namespace */
namespace boost {
/** Namespace for the library. */
@@ -71,7 +65,7 @@ namespace program_options {
The 'name' parameter is interpreted by the following rules:
- if there's no "," character in 'name', it specifies long name
- otherwise, the part before "," specifies long name and the part
after -- short name.
after -- long name.
*/
option_description(const char* name,
const value_semantic* s);
@@ -84,15 +78,12 @@ namespace program_options {
virtual ~option_description();
enum match_result { no_match, full_match, approximate_match };
/** Given 'option', specified in the input source,
returns 'true' if 'option' specifies *this.
return 'true' is 'option' specifies *this.
*/
match_result match(const std::string& option, bool approx,
bool long_ignore_case, bool short_ignore_case) const;
bool match(const std::string& option, bool approx) const;
/** Returns the key that should identify the option, in
/** Return the key that should identify the option, in
particular in the variables_map class.
The 'option' parameter is the option spelling from the
input source.
@@ -113,7 +104,7 @@ namespace program_options {
/// Returns the option name, formatted suitably for usage message.
std::string format_name() const;
/** Returns the parameter name and properties, formatted suitably for
/** Return the parameter name and properties, formatted suitably for
usage message. */
std::string format_parameter() const;
@@ -162,21 +153,15 @@ namespace program_options {
*/
class BOOST_PROGRAM_OPTIONS_DECL options_description {
public:
static const unsigned m_default_line_length;
static const unsigned m_default_line_length = 80;
/** Creates the instance. */
options_description(unsigned line_length = m_default_line_length,
unsigned min_description_length = m_default_line_length / 2);
options_description(unsigned line_length = m_default_line_length);
/** Creates the instance. The 'caption' parameter gives the name of
this 'options_description' instance. Primarily useful for output.
The 'description_length' specifies the number of columns that
should be reserved for the description text; if the option text
encroaches into this, then the description will start on the next
line.
*/
options_description(const std::string& caption,
unsigned line_length = m_default_line_length,
unsigned min_description_length = m_default_line_length / 2);
unsigned line_length = m_default_line_length);
/** Adds new variable description. Throws duplicate_variable_error if
either short or long name matches that of already present one.
*/
@@ -198,15 +183,11 @@ namespace program_options {
*/
options_description_easy_init add_options();
const option_description& find(const std::string& name,
bool approx,
bool long_ignore_case = false,
bool short_ignore_case = false) const;
const option_description& find(const std::string& name, bool approx)
const;
const option_description* find_nothrow(const std::string& name,
bool approx,
bool long_ignore_case = false,
bool short_ignore_case = false) const;
bool approx) const;
const std::vector< shared_ptr<option_description> >& options() const;
@@ -217,7 +198,7 @@ namespace program_options {
friend BOOST_PROGRAM_OPTIONS_DECL std::ostream& operator<<(std::ostream& os,
const options_description& desc);
/** Outputs 'desc' to the specified stream, calling 'f' to output each
/** Output 'desc' to the specified stream, calling 'f' to output each
option_description element. */
void print(std::ostream& os) const;
@@ -230,8 +211,6 @@ namespace program_options {
std::string m_caption;
const unsigned m_line_length;
const unsigned m_min_description_length;
// Data organization is chosen because:
// - there could be two names for one option
// - option_add_proxy needs to know the last added option
@@ -253,12 +232,8 @@ namespace program_options {
/** Class thrown when duplicate option description is found. */
class BOOST_PROGRAM_OPTIONS_DECL duplicate_option_error : public error {
public:
duplicate_option_error(const std::string& xwhat) : error(xwhat) {}
duplicate_option_error(const std::string& what) : error(what) {}
};
}}
#if defined(BOOST_MSVC)
# pragma warning (pop)
#endif
#endif

View File

@@ -17,11 +17,6 @@
#include <vector>
#include <utility>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4251) // class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'boost::program_options::basic_parsed_options<wchar_t>'
#endif
namespace boost { namespace program_options {
class options_description;
@@ -36,8 +31,8 @@ namespace boost { namespace program_options {
template<class charT>
class basic_parsed_options {
public:
explicit basic_parsed_options(const options_description* xdescription)
: description(xdescription) {}
explicit basic_parsed_options(const options_description* description)
: description(description) {}
/** Options found in the source. */
std::vector< basic_option<charT> > options;
/** Options description that was used for parsing.
@@ -78,16 +73,13 @@ namespace boost { namespace program_options {
/** Command line parser.
The class allows one to specify all the information needed for parsing
and to parse the command line. It is primarily needed to
and to parser the 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 {
@@ -98,9 +90,9 @@ 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 parameters should be the same as passed to 'main'.
list. The parameter should be the same as passes to 'main'.
*/
basic_command_line_parser(int argc, const charT* const argv[]);
basic_command_line_parser(int argc, charT* argv[]);
/** Sets options descriptions to use. */
basic_command_line_parser& options(const options_description& desc);
@@ -112,26 +104,8 @@ 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);
basic_parsed_options<charT> run();
private:
const options_description* m_desc;
};
@@ -144,7 +118,7 @@ namespace boost { namespace program_options {
*/
template<class charT>
basic_parsed_options<charT>
parse_command_line(int argc, const charT* const argv[],
parse_command_line(int argc, charT* argv[],
const options_description&,
int style = 0,
function1<std::pair<std::string, std::string>,
@@ -152,45 +126,13 @@ namespace boost { namespace program_options {
= ext_parser());
/** Parse a config file.
Read from given stream.
*/
template<class charT>
#if ! BOOST_WORKAROUND(__ICL, BOOST_TESTED_AT(700))
BOOST_PROGRAM_OPTIONS_DECL
#endif
basic_parsed_options<charT>
parse_config_file(std::basic_istream<charT>&, const options_description&,
bool allow_unregistered = false);
/** Parse a config file.
Read from file with the given name. The character type is
passed to the file stream.
*/
template<class charT>
#if ! BOOST_WORKAROUND(__ICL, BOOST_TESTED_AT(700))
BOOST_PROGRAM_OPTIONS_DECL
#endif
basic_parsed_options<charT>
parse_config_file(const char* filename, const options_description&,
bool allow_unregistered = false);
/** 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_config_file(std::basic_istream<charT>&, const options_description&);
/** Parse environment.
@@ -222,24 +164,6 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL parsed_options
parse_environment(const options_description&, const char* prefix);
/** Splits a given string to a collection of single strings which
can be passed to command_line_parser. The second parameter is
used to specify a collection of possible seperator chars used
for splitting. The seperator is defaulted to space " ".
Splitting is done in a unix style way, with respect to quotes '"'
and escape characters '\'
*/
BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string>
split_unix(const std::string& cmdline, const std::string& seperator = " \t",
const std::string& quote = "'\"", const std::string& escape = "\\");
#ifndef BOOST_NO_STD_WSTRING
/** @overload */
BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
split_unix(const std::wstring& cmdline, const std::wstring& seperator = L" \t",
const std::wstring& quote = L"'\"", const std::wstring& escape = L"\\");
#endif
#ifdef _WIN32
/** Parses the char* string which is passed to WinMain function on
windows. This function is provided for convenience, and because it's
@@ -256,7 +180,6 @@ namespace boost { namespace program_options {
split_winmain(const std::wstring& cmdline);
#endif
#endif
}}

View File

@@ -11,11 +11,6 @@
#include <vector>
#include <string>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4251) // class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'boost::program_options::positional_options_description'
#endif
namespace boost { namespace program_options {
/** Describes positional options.
@@ -42,11 +37,10 @@ namespace boost { namespace program_options {
No calls to 'add' can be made after call with 'max_value' equal to
'-1'.
*/
positional_options_description&
add(const char* name, int max_count);
void 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;
@@ -66,9 +60,5 @@ namespace boost { namespace program_options {
}}
#if defined(BOOST_MSVC)
# pragma warning (pop)
#endif
#endif

View File

@@ -14,9 +14,9 @@
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>
#include <typeinfo>
namespace boost { namespace program_options {
@@ -43,11 +43,6 @@ namespace boost { namespace program_options {
other sources are discarded.
*/
virtual bool is_composing() const = 0;
/** Returns true if value must be given. Non-optional value
*/
virtual bool is_required() const = 0;
/** Parses a group of tokens that specify a value of option.
Stores the result in 'value_store', using whatever representation
@@ -79,13 +74,6 @@ 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 {
@@ -99,13 +87,6 @@ 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 {
@@ -120,7 +101,6 @@ 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
@@ -136,8 +116,6 @@ namespace boost { namespace program_options {
unsigned max_tokens() const;
bool is_composing() const { return false; }
bool is_required() const { return false; }
/** If 'value_store' is already initialized, or new_tokens
has more than one elements, throws. Otherwise, assigns
@@ -156,36 +134,15 @@ 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>,
public typed_value_base
{
class typed_value : public value_semantic_codecvt_helper<charT> {
public:
/** Ctor. The 'store_to' parameter tells where to store
the value when it's known. The parameter can be NULL. */
typed_value(T* store_to)
: m_store_to(store_to), m_composing(false),
m_multitoken(false), m_zero_tokens(false),
m_required(false)
m_multitoken(false), m_zero_tokens(false)
{}
/** Specifies default value, which will be used
@@ -212,38 +169,6 @@ 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)
@@ -274,12 +199,6 @@ namespace boost { namespace program_options {
return this;
}
/** Specifies that the value must occur. */
typed_value* required()
{
m_required = true;
return this;
}
public: // value semantic overrides
@@ -289,7 +208,7 @@ namespace boost { namespace program_options {
unsigned min_tokens() const
{
if (m_zero_tokens || !m_implicit_value.empty()) {
if (m_zero_tokens) {
return 0;
} else {
return 1;
@@ -306,10 +225,9 @@ namespace boost { namespace program_options {
}
}
bool is_required() const { return m_required; }
/** Creates an instance of the 'validator' class and calls
its operator() to perform the actual conversion. */
its operator() to perform athe ctual conversion. */
void xparse(boost::any& value_store,
const std::vector< std::basic_string<charT> >& new_tokens)
const;
@@ -332,13 +250,6 @@ 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:
@@ -348,9 +259,7 @@ 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, m_required;
bool m_composing, m_implicit, m_multitoken, m_zero_tokens;
boost::function1<void, const T&> m_notifier;
};

View File

@@ -16,11 +16,6 @@
#include <map>
#include <set>
#if defined(BOOST_MSVC)
# pragma warning (push)
# pragma warning (disable:4251) // 'boost::program_options::variable_value::v' : class 'boost::any' needs to have dll-interface to be used by clients of class 'boost::program_options::variable_value
#endif
namespace boost { namespace program_options {
template<class charT>
@@ -29,50 +24,22 @@ 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.
*/
class BOOST_PROGRAM_OPTIONS_DECL variable_value {
public:
variable_value() : m_defaulted(false) {}
variable_value(const boost::any& xv, bool xdefaulted)
: v(xv), m_defaulted(xdefaulted)
variable_value(const boost::any& v, bool defaulted)
: v(v), m_defaulted(defaulted)
{}
/** If stored value if of type T, returns that value. Otherwise,
throws boost::bad_any_cast exception. */
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);
}
template<class T> const T& as() const;
/** @overload */
template<class T> T& as();
/// Returns true if no value is stored.
bool empty() const;
@@ -94,11 +61,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 BOOST_PROGRAM_OPTIONS_DECL
void store(const basic_parsed_options<char>& options,
friend void BOOST_PROGRAM_OPTIONS_DECL
store(const basic_parsed_options<char>& options,
variables_map& m, bool);
friend BOOST_PROGRAM_OPTIONS_DECL class variables_map;
friend void BOOST_PROGRAM_OPTIONS_DECL notify(variables_map& m);
};
/** Implements string->string mapping with convenient value casting
@@ -138,11 +104,7 @@ namespace boost { namespace program_options {
const abstract_variables_map* m_next;
};
/** 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.
*/
/** Concrete variables map which store variables in real map. */
class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map,
public std::map<std::string, variable_value>
{
@@ -153,8 +115,6 @@ namespace boost { namespace program_options {
// Resolve conflict between inherited operators.
const variable_value& operator[](const std::string& name) const
{ return abstract_variables_map::operator[](name); }
void notify();
private:
/** Implementation of abstract_variables_map::get
@@ -165,16 +125,30 @@ namespace boost { namespace program_options {
be changed by subsequence assignments. */
std::set<std::string> m_final;
friend BOOST_PROGRAM_OPTIONS_DECL
void store(const basic_parsed_options<char>& options,
friend void store(const basic_parsed_options<char>& options,
variables_map& xm,
bool utf8);
/** Names of required options, filled by parser which has
access to options_description. */
std::set<std::string> m_required;
};
/** 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
@@ -206,6 +180,18 @@ 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

View File

@@ -4,11 +4,6 @@
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
&nbsp;<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>
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
</body>
</html>
</html>

View File

@@ -23,7 +23,6 @@
#include <cassert>
#include <cstring>
#include <cctype>
#include <climits>
#include <cstdio>
@@ -34,18 +33,16 @@ namespace boost { namespace program_options {
using namespace std;
using namespace boost::program_options::command_line_style;
invalid_syntax::
invalid_syntax(const string& tokens, kind_t kind)
: error(error_message(kind).append(" in '").append(tokens).append("'"))
, m_tokens(tokens)
, m_kind(kind)
invalid_command_line_syntax::
invalid_command_line_syntax(const std::string& tokens, kind_t kind)
: invalid_syntax(tokens, error_message(kind)), m_kind(kind)
{}
string
invalid_syntax::error_message(kind_t kind)
std::string
invalid_command_line_syntax::error_message(kind_t kind)
{
// Initially, store the message in 'const char*' variable,
// to avoid conversion to string in all cases.
// to avoid conversion to std::string in all cases.
const char* msg;
switch(kind)
{
@@ -67,31 +64,18 @@ namespace boost { namespace program_options {
case extra_parameter:
msg = "extra parameter";
break;
case unrecognized_line:
msg = "unrecognized line";
break;
default:
msg = "unknown error";
}
return msg;
}
invalid_syntax::kind_t
invalid_syntax::kind() const
invalid_command_line_syntax::kind_t
invalid_command_line_syntax::kind() const
{
return m_kind;
}
const string&
invalid_syntax::tokens() const
{
return m_tokens;
}
invalid_command_line_syntax::
invalid_command_line_syntax(const string& tokens, kind_t kind)
: invalid_syntax(tokens, kind)
{}
}}
@@ -99,13 +83,13 @@ 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, < 1300)
#if BOOST_WORKAROUND(_MSC_VER, <= 1200)
using namespace std;
using namespace program_options;
#endif
cmdline::cmdline(const vector<string>& args)
cmdline::cmdline(const std::vector<std::string>& args)
{
init(args);
}
@@ -114,15 +98,15 @@ namespace boost { namespace program_options { namespace detail {
{
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
vector<string> args;
copy(argv+1, argv+argc+!argc, inserter(args, args.end()));
copy(argv+1, argv+argc, inserter(args, args.end()));
init(args);
#else
init(vector<string>(argv+1, argv+argc+!argc));
init(vector<string>(argv+1, argv+argc));
#endif
}
void
cmdline::init(const vector<string>& args)
cmdline::init(const std::vector<std::string>& args)
{
this->args = args;
m_style = command_line_style::default_style;
@@ -167,17 +151,11 @@ namespace boost { namespace program_options { namespace detail {
error = "style disallows all characters for short options";
if (error)
boost::throw_exception(invalid_command_line_style(error));
throw invalid_command_line_style(error);
// Need to check that if guessing and long disguise are enabled
// -f will mean the same as -foo
}
bool
cmdline::is_style_active(style_t style) const
{
return ((m_style & style) ? true : false);
}
void
cmdline::set_options_description(const options_description& desc)
@@ -217,24 +195,24 @@ namespace boost { namespace program_options { namespace detail {
if (m_additional_parser)
style_parsers.push_back(
boost::bind(&cmdline::handle_additional_parser, this, _1));
bind(&cmdline::handle_additional_parser, this, _1));
if (m_style & allow_long)
style_parsers.push_back(
boost::bind(&cmdline::parse_long_option, this, _1));
bind(&cmdline::parse_long_option, this, _1));
if ((m_style & allow_long_disguise))
style_parsers.push_back(
boost::bind(&cmdline::parse_disguised_long_option, this, _1));
bind(&cmdline::parse_disguised_long_option, this, _1));
if ((m_style & allow_short) && (m_style & allow_dash_for_short))
style_parsers.push_back(
boost::bind(&cmdline::parse_short_option, this, _1));
bind(&cmdline::parse_short_option, this, _1));
if ((m_style & allow_short) && (m_style & allow_slash_for_short))
style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1));
style_parsers.push_back(bind(&cmdline::parse_dos_option, this, _1));
style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1));
style_parsers.push_back(bind(&cmdline::parse_terminator, this, _1));
vector<option> result;
while(!args.empty())
@@ -251,12 +229,12 @@ namespace boost { namespace program_options { namespace detail {
{
vector<string> e;
for(unsigned k = 0; k < next.size()-1; ++k) {
finish_option(next[k], e, style_parsers);
finish_option(next[k], e);
}
// For the last option, pass the unparsed tokens
// so that they can be added to next.back()'s values
// if appropriate.
finish_option(next.back(), args, style_parsers);
finish_option(next.back(), args);
for (unsigned j = 0; j < next.size(); ++j)
result.push_back(next[j]);
}
@@ -270,70 +248,11 @@ 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());
}
}
/* If an key option is followed by a positional option,
can can consume more tokens (e.g. it's multitoke option),
give those tokens to it. */
vector<option> result2;
for (unsigned i = 0; i < result.size(); ++i)
{
result2.push_back(result[i]);
option& opt = result2.back();
if (opt.string_key.empty())
continue;
const option_description* xd =
m_desc->find_nothrow(opt.string_key,
is_style_active(allow_guessing),
is_style_active(long_case_insensitive),
is_style_active(short_case_insensitive));
if (!xd)
continue;
unsigned min_tokens = xd->semantic()->min_tokens();
unsigned max_tokens = xd->semantic()->max_tokens();
if (min_tokens < max_tokens && opt.value.size() < max_tokens)
{
// This option may grab some more tokens.
// We only allow to grab tokens that are not already
// recognized as key options.
int can_take_more = max_tokens - opt.value.size();
unsigned j = i+1;
for (; can_take_more && j < result.size(); --can_take_more, ++j)
{
option& opt2 = result[j];
if (!opt2.string_key.empty())
break;
if (opt2.position_key == INT_MAX)
{
// We use INT_MAX to mark positional options that
// were found after the '--' terminator and therefore
// should stay positional forever.
break;
}
assert(opt2.value.size() == 1);
opt.value.push_back(opt2.value[0]);
assert(opt2.original_tokens.size() == 1);
opt.original_tokens.push_back(opt2.original_tokens[0]);
}
i = j-1;
}
}
result.swap(result2);
// Assign position keys to positional options.
int position_key = 0;
for(unsigned i = 0; i < result.size(); ++i) {
@@ -349,45 +268,29 @@ namespace boost { namespace program_options { namespace detail {
if (opt.position_key != -1) {
if (position >= m_positional->max_total_count())
{
boost::throw_exception(too_many_positional_options_error());
throw too_many_positional_options_error(
"too many positional options");
}
opt.string_key = m_positional->name_for_position(position);
++position;
}
}
}
// set case sensitive flag
for (unsigned i = 0; i < result.size(); ++i) {
if (result[i].string_key.size() > 2 ||
(result[i].string_key.size() > 1 && result[i].string_key[0] != '-'))
{
// it is a long option
result[i].case_insensitive = is_style_active(long_case_insensitive);
}
else
{
// it is a short option
result[i].case_insensitive = is_style_active(short_case_insensitive);
}
}
return result;
}
void
cmdline::finish_option(option& opt,
vector<string>& other_tokens,
const vector<style_parser>& style_parsers)
{
vector<string>& other_tokens)
{
if (opt.string_key.empty())
return;
// First check that the option is valid, and get its description.
const option_description* xd = m_desc->find_nothrow(opt.string_key,
is_style_active(allow_guessing),
is_style_active(long_case_insensitive),
is_style_active(short_case_insensitive));
// TODO: case-sensitivity.
const option_description* xd =
m_desc->find_nothrow(opt.string_key, (m_style & allow_guessing));
if (!xd)
{
@@ -418,64 +321,32 @@ namespace boost { namespace program_options { namespace detail {
if (present_tokens >= min_tokens)
{
if (!opt.value.empty() && max_tokens == 0)
{
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::extra_parameter));
if (!opt.value.empty() && max_tokens == 0) {
throw invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::extra_parameter);
}
// If an option wants, at minimum, N tokens, we grab them there,
// when adding these tokens as values to current option we check
// if they look like options
if (opt.value.size() <= min_tokens)
{
min_tokens -= opt.value.size();
}
else
{
min_tokens = 0;
}
max_tokens -= opt.value.size();
// Everything's OK, move the values to the result.
for(;!other_tokens.empty() && min_tokens--; )
{
// check if extra parameter looks like a known option
// we use style parsers to check if it is syntactically an option,
// additionally we check if an option_description exists
vector<option> followed_option;
vector<string> next_token(1, other_tokens[0]);
for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i)
{
followed_option = style_parsers[i](next_token);
}
if (!followed_option.empty())
{
const option_description* od = m_desc->find_nothrow(other_tokens[0],
is_style_active(allow_guessing),
is_style_active(long_case_insensitive),
is_style_active(short_case_insensitive));
if (od)
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::missing_parameter));
}
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());
}
}
else
{
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::missing_parameter));
throw invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::missing_parameter);
}
}
vector<option>
cmdline::parse_long_option(vector<string>& args)
std::vector<option>
cmdline::parse_long_option(std::vector<string>& args)
{
vector<option> result;
const string& tok = args[0];
const std::string& tok = args[0];
if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-')
{
string name, adjacent;
@@ -486,8 +357,8 @@ namespace boost { namespace program_options { namespace detail {
name = tok.substr(2, p-2);
adjacent = tok.substr(p+1);
if (adjacent.empty())
boost::throw_exception( invalid_command_line_syntax(name,
invalid_command_line_syntax::empty_adjacent_parameter) );
throw invalid_command_line_syntax(name,
invalid_command_line_syntax::empty_adjacent_parameter);
}
else
{
@@ -497,7 +368,6 @@ 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());
}
@@ -505,10 +375,10 @@ namespace boost { namespace program_options { namespace detail {
}
vector<option>
cmdline::parse_short_option(vector<string>& args)
std::vector<option>
cmdline::parse_short_option(std::vector<string>& args)
{
const string& tok = args[0];
const std::string& tok = args[0];
if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-')
{
vector<option> result;
@@ -524,8 +394,7 @@ namespace boost { namespace program_options { namespace detail {
// option.
for(;;) {
const option_description* d
= m_desc->find_nothrow(name, false, false,
is_style_active(short_case_insensitive));
= m_desc->find_nothrow(name, false);
// FIXME: check for 'allow_sticky'.
if (d && (m_style & allow_sticky) &&
@@ -547,7 +416,6 @@ 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);
@@ -557,14 +425,14 @@ namespace boost { namespace program_options { namespace detail {
}
return result;
}
return vector<option>();
return std::vector<option>();
}
vector<option>
cmdline::parse_dos_option(vector<string>& args)
std::vector<option>
cmdline::parse_dos_option(std::vector<string>& args)
{
vector<option> result;
const string& tok = args[0];
const std::string& tok = args[0];
if (tok.size() >= 2 && tok[0] == '/')
{
string name = "-" + tok.substr(1,1);
@@ -574,26 +442,22 @@ 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());
}
return result;
}
vector<option>
cmdline::parse_disguised_long_option(vector<string>& args)
std::vector<option>
cmdline::parse_disguised_long_option(std::vector<string>& args)
{
const string& tok = args[0];
const std::string& tok = args[0];
if (tok.size() >= 2 &&
((tok[0] == '-' && tok[1] != '-') ||
((m_style & allow_slash_for_short) && tok[0] == '/')))
{
if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),
is_style_active(allow_guessing),
is_style_active(long_case_insensitive),
is_style_active(short_case_insensitive)))
{
m_style & allow_guessing)) {
args[0].insert(0, "-");
if (args[0][1] == '/')
args[0][1] = '-';
@@ -603,19 +467,17 @@ namespace boost { namespace program_options { namespace detail {
return vector<option>();
}
vector<option>
cmdline::parse_terminator(vector<string>& args)
std::vector<option>
cmdline::parse_terminator(std::vector<std::string>& args)
{
vector<option> result;
const string& tok = args[0];
const std::string& tok = args[0];
if (tok == "--")
{
for(unsigned i = 1; i < args.size(); ++i)
{
option opt;
opt.value.push_back(args[i]);
opt.original_tokens.push_back(args[i]);
opt.position_key = INT_MAX;
result.push_back(opt);
}
args.clear();
@@ -623,16 +485,15 @@ namespace boost { namespace program_options { namespace detail {
return result;
}
vector<option>
cmdline::handle_additional_parser(vector<string>& args)
std::vector<option>
cmdline::handle_additional_parser(std::vector<std::string>& args)
{
vector<option> result;
pair<string, string> r = m_additional_parser(args[0]);
if (!r.first.empty()) {
option next;
next.string_key = r.first;
if (!r.second.empty())
next.value.push_back(r.second);
next.value.push_back(r.second);
result.push_back(next);
args.erase(args.begin());
}

View File

@@ -21,10 +21,8 @@ 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,
bool allow_unregistered)
: allowed_options(allowed_options),
m_allow_unregistered(allow_unregistered)
const std::set<std::string>& allowed_options)
: allowed_options(allowed_options)
{
for(std::set<std::string>::const_iterator i = allowed_options.begin();
i != allowed_options.end();
@@ -102,22 +100,20 @@ 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));
bool registered = allowed_option(name);
if (!registered && !m_allow_unregistered)
if (!allowed_option(name))
boost::throw_exception(unknown_option(name));
if (value.empty())
boost::throw_exception(invalid_syntax(s, "no value given"));
found = true;
this->value().string_key = name;
this->value().value.clear();
this->value().value.push_back(value);
this->value().unregistered = !registered;
this->value().original_tokens.clear();
this->value().original_tokens.push_back(name);
this->value().original_tokens.push_back(value);
break;
} else {
boost::throw_exception(invalid_syntax(s, invalid_syntax::unrecognized_line));
boost::throw_exception(invalid_syntax(s, "unrecognized line"));
}
}
}

View File

@@ -43,7 +43,7 @@ namespace boost { namespace detail {
{
std::basic_string<ToChar> result;
std::mbstate_t state = std::mbstate_t();
std::mbstate_t state = {0};
const FromChar* from = s.data();
const FromChar* from_end = s.data() + s.size();

View File

@@ -8,7 +8,7 @@
#define BOOST_PROGRAM_OPTIONS_SOURCE
#include <boost/program_options/config.hpp>
#include <boost/program_options/options_description.hpp>
// FIXME: this is only to get multiple_occurences class
// FIXME: this is only to get multiple_occureces class
// should move that to a separate headers.
#include <boost/program_options/parsers.hpp>
@@ -23,27 +23,10 @@
#include <cstring>
#include <cstdarg>
#include <sstream>
#include <iterator>
using namespace std;
namespace boost { namespace program_options {
namespace {
template< class charT >
std::basic_string< charT > tolower_(const std::basic_string< charT >& str)
{
std::basic_string< charT > result;
for (typename std::basic_string< charT >::size_type i = 0; i < str.size(); ++i)
{
result.append(1, static_cast< charT >(std::tolower(str[i])));
}
return result;
}
} // unnamed namespace
option_description::option_description()
{
}
@@ -70,52 +53,35 @@ namespace boost { namespace program_options {
{
}
option_description::match_result
option_description::match(const std::string& option,
bool approx,
bool long_ignore_case,
bool short_ignore_case) const
bool
option_description::match(const std::string& option, bool approx) const
{
match_result result = no_match;
std::string local_long_name((long_ignore_case ? tolower_(m_long_name) : m_long_name));
if (!local_long_name.empty()) {
std::string local_option = (long_ignore_case ? tolower_(option) : option);
bool result = false;
if (!m_long_name.empty()) {
if (*local_long_name.rbegin() == '*')
if (*m_long_name.rbegin() == '*')
{
// The name ends with '*'. Any specified name with the given
// prefix is OK.
if (local_option.find(local_long_name.substr(0, local_long_name.length()-1))
if (option.find(m_long_name.substr(0, m_long_name.length()-1))
== 0)
result = approximate_match;
result = true;
}
if (local_long_name == local_option)
if (approx)
{
result = full_match;
if (m_long_name.find(option) == 0)
result = true;
}
else if (approx)
else
{
if (local_long_name.find(local_option) == 0)
{
result = approximate_match;
}
if (m_long_name == option)
result = true;
}
}
if (result != full_match)
{
std::string local_option(short_ignore_case ? tolower_(option) : option);
std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name);
if (local_short_name == local_option)
{
result = full_match;
}
}
if (m_short_name == option)
result = true;
return result;
}
@@ -231,28 +197,15 @@ namespace boost { namespace program_options {
return *this;
}
const unsigned options_description::m_default_line_length = 80;
options_description::options_description(unsigned line_length,
unsigned min_description_length)
options_description::options_description(unsigned line_length)
: m_line_length(line_length)
, m_min_description_length(min_description_length)
{
// we require a space between the option and description parts, so add 1.
assert(m_min_description_length < m_line_length - 1);
}
{}
options_description::options_description(const string& caption,
unsigned line_length)
: m_caption(caption), m_line_length(line_length)
{}
options_description::options_description(const std::string& caption,
unsigned line_length,
unsigned min_description_length)
: m_caption(caption)
, m_line_length(line_length)
, m_min_description_length(min_description_length)
{
// we require a space between the option and description parts, so add 1.
assert(m_min_description_length < m_line_length - 1);
}
void
options_description::add(shared_ptr<option_description> desc)
{
@@ -281,13 +234,9 @@ namespace boost { namespace program_options {
}
const option_description&
options_description::find(const std::string& name,
bool approx,
bool long_ignore_case,
bool short_ignore_case) const
options_description::find(const std::string& name, bool approx) const
{
const option_description* d = find_nothrow(name, approx,
long_ignore_case, short_ignore_case);
const option_description* d = find_nothrow(name, approx);
if (!d)
boost::throw_exception(unknown_option(name));
return *d;
@@ -299,57 +248,38 @@ namespace boost { namespace program_options {
return m_options;
}
const option_description*
const option_description*
options_description::find_nothrow(const std::string& name,
bool approx,
bool long_ignore_case,
bool short_ignore_case) const
bool approx) const
{
shared_ptr<option_description> found;
bool had_full_match = false;
vector<string> approximate_matches;
vector<string> full_matches;
int found = -1;
// 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.
for(unsigned i = 0; i < m_options.size(); ++i)
{
option_description::match_result r =
m_options[i]->match(name, approx, long_ignore_case, short_ignore_case);
if (r == option_description::no_match)
continue;
if (r == option_description::full_match)
{
full_matches.push_back(m_options[i]->key(name));
found = m_options[i];
had_full_match = true;
}
else
{
// FIXME: the use of 'key' here might not
// be the best approach.
approximate_matches.push_back(m_options[i]->key(name));
if (!had_full_match)
found = m_options[i];
if (m_options[i]->match(name, approx))
{
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 (full_matches.size() > 1)
boost::throw_exception(
ambiguous_option(name, full_matches));
// If we have a full match, 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.
if (full_matches.empty() && approximate_matches.size() > 1)
boost::throw_exception(
ambiguous_option(name, approximate_matches));
return found.get();
if (found != -1) {
return m_options[found].get();
} else {
return 0;
}
}
BOOST_PROGRAM_OPTIONS_DECL
@@ -361,26 +291,11 @@ 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 indent,
unsigned first_column_width,
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
@@ -404,16 +319,16 @@ namespace boost { namespace program_options {
// this assert may fail due to user error or
// environment conditions!
assert(par_indent < line_length);
assert(par_indent < (line_length - first_column_width));
// ignore tab if not on first line
if (par_indent >= line_length)
if (par_indent >= (line_length - first_column_width))
{
par_indent = 0;
}
}
if (par.size() < line_length)
if (par.size() < (line_length - first_column_width))
{
os << par;
}
@@ -422,16 +337,17 @@ 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!
bool first_line = true; // of current paragraph!
unsigned indent = first_column_width;
while (line_begin < par_end) // paragraph lines
{
if (!first_line)
{
// 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.
// trimm leading single spaces
// if (firstchar == ' ') &&
// ((exists(firstchar + 1) && (firstchar + 1 != ' '))
if ((*line_begin == ' ') &&
((line_begin + 1 < par_end) &&
(*(line_begin + 1) != ' ')))
@@ -440,31 +356,36 @@ namespace boost { namespace program_options {
}
}
// 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);
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);
}
// prevent chopped words
// Is line_end between two non-space characters?
// if (lastchar != ' ') &&
// ((exists(lastchar + 1) && (lastchar + 1 != ' '))
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),
reverse_iterator<string::const_iterator>(line_begin),
find(reverse_iterator<string::const_iterator>(line_end - 1),
reverse_iterator<string::const_iterator>(line_begin - 1),
' ')
.base();
if (last_space != line_begin)
if (last_space != line_begin - 1)
{
// is last_space within the second half ot the
// current line
if (static_cast<unsigned>(distance(last_space, line_end)) <
(line_length / 2))
if (unsigned(distance(last_space, line_end)) <
(line_length - indent) / 2)
{
line_end = last_space;
}
@@ -476,8 +397,7 @@ namespace boost { namespace program_options {
if (first_line)
{
indent += par_indent;
line_length -= par_indent; // there's less to work with now
indent = first_column_width + par_indent;
first_line = false;
}
@@ -516,7 +436,7 @@ namespace boost { namespace program_options {
assert(line_length > first_column_width);
// Note: can't use 'tokenizer' as name of typedef -- borland
// will consider uses of 'tokenizer' below as uses of
// will consider subsequence uses of 'tokenizer' as uses of
// boost::tokenizer, not typedef.
typedef boost::tokenizer<boost::char_separator<char> > tok;
@@ -558,18 +478,11 @@ namespace boost { namespace program_options {
if (!opt.description().empty())
{
if (ss.str().size() >= first_column_width)
for(unsigned pad = first_column_width - ss.str().size();
pad > 0;
--pad)
{
os.put('\n'); // first column is too long, lets put description in new line
for (unsigned pad = first_column_width; pad > 0; --pad)
{
os.put(' ');
}
} else {
for(unsigned pad = first_column_width - ss.str().size(); pad > 0; --pad)
{
os.put(' ');
}
os.put(' ');
}
format_description(os, opt.description(),
@@ -594,11 +507,6 @@ namespace boost { namespace program_options {
ss << " " << opt.format_name() << ' ' << opt.format_parameter();
width = (max)(width, static_cast<unsigned>(ss.str().size()));
}
/* this is the column were description should start, if first
column is longer, we go to a new line */
const unsigned start_of_description_column = m_line_length - m_min_description_length;
width = (min)(width, start_of_description_column-1);
/* add an additional space to improve readability */
++width;

View File

@@ -20,7 +20,6 @@
#include <boost/throw_exception.hpp>
#include <cctype>
#include <fstream>
#if !defined(__GNUC__) || __GNUC__ < 3
#include <iostream>
@@ -68,16 +67,10 @@ namespace boost { namespace program_options {
woption result;
result.string_key = opt.string_key;
result.position_key = opt.position_key;
result.unregistered = opt.unregistered;
std::transform(opt.value.begin(), opt.value.end(),
back_inserter(result.value),
boost::bind(from_utf8, _1));
std::transform(opt.original_tokens.begin(),
opt.original_tokens.end(),
back_inserter(result.original_tokens),
boost::bind(from_utf8, _1));
bind(from_utf8, _1));
return result;
}
}
@@ -95,8 +88,7 @@ namespace boost { namespace program_options {
template<class charT>
basic_parsed_options<charT>
parse_config_file(std::basic_istream<charT>& is,
const options_description& desc,
bool allow_unregistered)
const options_description& desc)
{
set<string> allowed_options;
@@ -114,8 +106,7 @@ namespace boost { namespace program_options {
// Parser return char strings
parsed_options result(&desc);
copy(detail::basic_config_file_iterator<charT>(
is, allowed_options, allow_unregistered),
copy(detail::basic_config_file_iterator<charT>(is, allowed_options),
detail::basic_config_file_iterator<charT>(),
back_inserter(result.options));
// Convert char strings into desired type.
@@ -125,46 +116,14 @@ 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,
bool allow_unregistered);
const options_description& desc);
#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,
bool allow_unregistered);
const options_description& desc);
#endif
template<class charT>
basic_parsed_options<charT>
parse_config_file(const char* filename,
const options_description& desc,
bool allow_unregistered)
{
// Parser return char strings
std::basic_ifstream< charT > strm(filename);
if (!strm)
{
boost::throw_exception(reading_file(filename));
}
return parse_config_file(strm, desc, allow_unregistered);
}
template
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
parse_config_file(const char* filename,
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(const char* filename,
const options_description& desc,
bool allow_unregistered);
#endif
// This versio, which accepts any options without validation, is disabled,
// in the hope that nobody will need it and we cant drop it altogether.
@@ -201,7 +160,7 @@ namespace boost { namespace program_options {
return result;
}
namespace detail {
namespace {
class prefix_name_mapper {
public:
prefix_name_mapper(const std::string& prefix)
@@ -230,7 +189,7 @@ namespace boost { namespace program_options {
parse_environment(const options_description& desc,
const std::string& prefix)
{
return parse_environment(desc, detail::prefix_name_mapper(prefix));
return parse_environment(desc, prefix_name_mapper(prefix));
}
BOOST_PROGRAM_OPTIONS_DECL parsed_options

View File

@@ -17,7 +17,7 @@ namespace boost { namespace program_options {
positional_options_description::positional_options_description()
{}
positional_options_description&
void
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

View File

@@ -1,62 +0,0 @@
// Copyright Sascha Ochsenknecht 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_PROGRAM_OPTIONS_SOURCE
#include <boost/program_options/parsers.hpp>
#include <boost/tokenizer.hpp>
#include <string>
#include <vector>
namespace boost { namespace program_options { namespace detail {
template< class charT >
std::vector<std::basic_string<charT> >
split_unix(
const std::basic_string<charT>& cmdline,
const std::basic_string<charT>& seperator,
const std::basic_string<charT>& quote,
const std::basic_string<charT>& escape)
{
typedef boost::tokenizer< boost::escaped_list_separator<charT>,
typename std::basic_string<charT>::const_iterator,
std::basic_string<charT> > tokenizerT;
tokenizerT tok(cmdline.begin(), cmdline.end(),
boost::escaped_list_separator< charT >(escape, seperator, quote));
std::vector< std::basic_string<charT> > result;
for (typename tokenizerT::iterator cur_token(tok.begin()), end_token(tok.end()); cur_token != end_token; ++cur_token) {
if (!cur_token->empty())
result.push_back(*cur_token);
}
return result;
}
}}} // namespace
namespace boost { namespace program_options {
// Take a command line string and splits in into tokens, according
// to the given collection of seperators chars.
BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string>
split_unix(const std::string& cmdline, const std::string& seperator,
const std::string& quote, const std::string& escape)
{
return detail::split_unix< char >(cmdline, seperator, quote, escape);
}
#ifndef BOOST_NO_STD_WSTRING
BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
split_unix(const std::wstring& cmdline, const std::wstring& seperator,
const std::wstring& quote, const std::wstring& escape)
{
return detail::split_unix< wchar_t >(cmdline, seperator, quote, escape);
}
#endif
}} // namespace

View File

@@ -97,9 +97,9 @@ namespace boost { namespace program_options {
{
if (!value_store.empty())
boost::throw_exception(
multiple_occurrences());
multiple_occurrences("multiple_occurrences"));
if (new_tokens.size() > 1)
boost::throw_exception(multiple_values());
boost::throw_exception(multiple_values("multiple_values"));
value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
}
@@ -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. The 'xs' vector can either be empty, in which
case the value is 'true', or can contain explicit value.
Case is ignored. Regardless of name passed, parameter will always
be optional.
*/
BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs,
bool*, int)
@@ -139,7 +139,8 @@ namespace boost { namespace program_options {
else if (s == "off" || s == "no" || s == "0" || s == "false")
v = any(false);
else
boost::throw_exception(validation_error(validation_error::invalid_bool_value, s));
boost::throw_exception(validation_error(
"'" + s + "' doesn't look like a bool value."));
}
// This is blatant copy-paste. However, templating this will cause a problem,
@@ -161,14 +162,19 @@ namespace boost { namespace program_options {
else if (s == L"off" || s == L"no" || s == L"0" || s == L"false")
v = any(false);
else
boost::throw_exception(validation_error(validation_error::invalid_bool_value));
boost::throw_exception(validation_error("invalid bool value"));
}
#endif
BOOST_PROGRAM_OPTIONS_DECL
void validate(any& v, const vector<string>& xs, std::string*, int)
{
check_first_occurrence(v);
v = any(get_single_string(xs));
string s(get_single_string(xs));
if (*s.begin() == '\'' && *s.rbegin() == '\'' ||
*s.begin() == '"' && *s.rbegin() == '"')
v = any(s.substr(1, s.size()-2));
else
v = any(s);
}
#if !defined(BOOST_NO_STD_WSTRING)
@@ -176,7 +182,12 @@ namespace boost { namespace program_options {
void validate(any& v, const vector<wstring>& xs, std::string*, int)
{
check_first_occurrence(v);
v = any(get_single_string(xs));
wstring s(get_single_string(xs));
if (*s.begin() == L'\'' && *s.rbegin() == L'\'' ||
*s.begin() == L'"' && *s.rbegin() == L'"')
v = any(s.substr(1, s.size()-2));
else
v = any(s);
}
#endif
@@ -187,17 +198,19 @@ namespace boost { namespace program_options {
{
if (!value.empty())
boost::throw_exception(
multiple_occurrences());
multiple_occurrences("multiple_occurrences"));
}
}
invalid_option_value::
invalid_option_value(const std::string& bad_value)
: validation_error(validation_error::invalid_option_value, bad_value)
: validation_error(string("invalid option value '")
.append(bad_value).append("'"))
{}
#ifndef BOOST_NO_STD_WSTRING
namespace
{
std::string convert_value(const std::wstring& s)
@@ -213,123 +226,35 @@ namespace boost { namespace program_options {
invalid_option_value::
invalid_option_value(const std::wstring& bad_value)
: validation_error(validation_error::invalid_option_value, convert_value(bad_value))
: validation_error(string("invalid option value '")
.append(convert_value(bad_value))
.append("'"))
{}
#endif
const std::string&
unknown_option::get_option_name() const throw()
{
return m_option_name;
}
#endif
const std::string&
ambiguous_option::get_option_name() const throw()
{
return m_option_name;
}
const std::vector<std::string>&
ambiguous_option::alternatives() const throw()
{
return m_alternatives;
}
void
multiple_values::set_option_name(const std::string& option_name)
void validation_error::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
const std::string&
multiple_values::get_option_name() const throw()
{
return m_option_name;
}
void
multiple_occurrences::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
const std::string&
multiple_occurrences::get_option_name() const throw()
{
return m_option_name;
}
validation_error::
validation_error(kind_t kind,
const std::string& option_value,
const std::string& option_name)
: error("")
, m_kind(kind)
, m_option_name(option_name)
, m_option_value(option_value)
, m_message(error_message(kind))
{
if (!option_value.empty())
{
m_message.append(std::string("'") + option_value + std::string("'"));
}
}
void
validation_error::set_option_name(const std::string& option_name)
{
m_option_name = option_name;
}
const std::string&
validation_error::get_option_name() const throw()
{
return m_option_name;
}
std::string
validation_error::error_message(kind_t kind)
{
// Initially, store the message in 'const char*' variable,
// to avoid conversion to std::string in all cases.
const char* msg;
switch(kind)
{
case multiple_values_not_allowed:
msg = "multiple values not allowed";
break;
case at_least_one_value_required:
msg = "at least one value required";
break;
case invalid_bool_value:
msg = "invalid bool value";
break;
case invalid_option_value:
msg = "invalid option value";
break;
case invalid_option:
msg = "invalid option";
break;
default:
msg = "unknown error";
}
return msg;
}
const char*
validation_error::what() const throw()
const char* validation_error::what() const throw()
{
if (!m_option_name.empty())
{
m_message = "in option '" + m_option_name + "': "
+ error_message(m_kind);
+ logic_error::what();
return m_message.c_str();
}
else
{
return logic_error::what();
}
return m_message.c_str();
}
const std::string&
required_option::get_option_name() const throw()
{
return m_option_name;
}
}}

View File

@@ -35,31 +35,24 @@ 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 (i = 0; i < options.options.size(); ++i) {
for (size_t 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;
const option_description& d = desc.find(name, false,
false, false);
// Ignore options which are not described
//TODO: consider this.
//if (desc.count(name) == 0)
// continue;
const option_description& d = desc.find(name, false);
variable_value& v = m[name];
if (v.defaulted()) {
@@ -70,23 +63,11 @@ namespace boost { namespace program_options {
try {
d.semantic()->parse(v.value(), options.options[i].value, utf8);
}
#ifndef BOOST_NO_EXCEPTIONS
catch(validation_error& e)
{
e.set_option_name(name);
throw;
}
catch(multiple_occurrences& e)
{
e.set_option_name(name);
throw;
}
catch(multiple_values& e)
{
e.set_option_name(name);
throw;
}
#endif
v.m_value_semantic = d.semantic();
// The option is not composing, and the value is explicitly
@@ -101,9 +82,9 @@ namespace boost { namespace program_options {
// Second, apply default values and store required options.
// Second, apply default values.
const vector<shared_ptr<option_description> >& all = desc.options();
for(i = 0; i < all.size(); ++i)
for(unsigned i = 0; i < all.size(); ++i)
{
const option_description& d = *all[i];
string key = d.key("");
@@ -123,12 +104,7 @@ namespace boost { namespace program_options {
m[key] = variable_value(def, true);
m[key].m_value_semantic = d.semantic();
}
}
// add empty value if this is an required option
if (d.semantic()->is_required()) {
xm.m_required.insert(key);
}
}
}
}
@@ -141,7 +117,13 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL
void notify(variables_map& vm)
{
vm.notify();
// Lastly, run notify actions.
for (map<string, variable_value>::iterator k = vm.begin();
k != vm.end();
++k)
{
k->second.m_value_semantic->notify(k->second.value());
}
}
abstract_variables_map::abstract_variables_map()
@@ -192,40 +174,4 @@ namespace boost { namespace program_options {
else
return i->second;
}
void
variables_map::notify()
{
// This checks if all required options occur
for (set<string>::const_iterator r = m_required.begin();
r != m_required.end();
++r)
{
const string& opt = *r;
map<string, variable_value>::const_iterator iter = find(opt);
if (iter == end() || iter->second.empty())
{
boost::throw_exception(required_option(opt));
}
}
// Lastly, run notify actions.
for (map<string, variable_value>::iterator k = begin();
k != end();
++k)
{
/* Users might wish to use variables_map to store their own values
that are not parsed, and therefore will not have value_semantics
defined. Do no crash on such values. In multi-module programs,
one module might add custom values, and the 'notify' function
will be called after that, so we check that value_sematics is
not NULL. See:
https://svn.boost.org/trac/boost/ticket/2782
*/
if (k->second.m_value_semantic)
k->second.m_value_semantic->notify(k->second.value());
}
}
}}

View File

@@ -10,27 +10,26 @@
#ifdef _WIN32
namespace boost { namespace program_options {
// 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
using namespace std;
// The rules for windows command line 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)
{
std::vector<std::string> result;
std::string::const_iterator i = input.begin(), e = input.end();
string::const_iterator i = input.begin(), e = input.end();
for(;i != e; ++i)
if (!isspace((unsigned char)*i))
if (!isspace(*i))
break;
if (i != e) {
std::string current;
bool inside_quoted = false;
bool empty_quote = false;
int backslash_count = 0;
for(; i != e; ++i) {
@@ -39,7 +38,6 @@ namespace boost { namespace program_options {
// n/2 backslashes and is a quoted block delimiter
if (backslash_count % 2 == 0) {
current.append(backslash_count / 2, '\\');
empty_quote = inside_quoted && current.empty();
inside_quoted = !inside_quoted;
// '"' preceded by odd number (n) of backslashes generates
// (n-1)/2 backslashes and is literal quote.
@@ -57,12 +55,11 @@ namespace boost { namespace program_options {
current.append(backslash_count, '\\');
backslash_count = 0;
}
if (isspace((unsigned char)*i) && !inside_quoted) {
if (isspace(*i) && !inside_quoted) {
// Space outside quoted section terminate the current argument
result.push_back(current);
current.resize(0);
empty_quote = false;
for(;i != e && isspace((unsigned char)*i); ++i)
for(;i != e && isspace(*i); ++i)
;
--i;
} else {
@@ -77,7 +74,7 @@ namespace boost { namespace program_options {
// If we have non-empty 'current' or we're still in quoted
// section (even if 'current' is empty), add the last token.
if (!current.empty() || inside_quoted || empty_quote)
if (!current.empty() || inside_quoted)
result.push_back(current);
}
return result;
@@ -87,9 +84,9 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
split_winmain(const std::wstring& cmdline)
{
std::vector<std::wstring> result;
std::vector<std::string> aux = split_winmain(to_internal(cmdline));
for (unsigned i = 0, e = aux.size(); i < e; ++i)
vector<wstring> result;
vector<string> aux = split_winmain(to_internal(cmdline));
for (unsigned i = 0, e = result.size(); i < e; ++i)
result.push_back(from_utf8(aux[i]));
return result;
}
@@ -97,4 +94,3 @@ namespace boost { namespace program_options {
}}
#endif

47
test/Jamfile Normal file
View File

@@ -0,0 +1,47 @@
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 ]
;

View File

@@ -2,36 +2,30 @@
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
;
rule po-test ( source : input-file ? )
rule po-test ( source )
{
return
[ run $(source) : : $(input-file) ]
[ run $(source) : : $(input-file)
: <link>shared <define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
: $(source:B)_dll ]
;
[ run $(source) ]
[ run $(source) : : : <link>shared : $(source:B)_dll ]
;
}
test-suite program_options :
[ po-test options_description_test.cpp ]
[ po-test parsers_test.cpp : config_test.cfg ]
[ po-test parsers_test.cpp ]
[ po-test variable_map_test.cpp ]
[ po-test cmdline_test.cpp ]
[ po-test positional_options_test.cpp ]
[ po-test unicode_test.cpp ]
[ po-test winmain.cpp ]
[ po-test exception_test.cpp ]
[ po-test split_test.cpp ]
[ po-test unrecognized_test.cpp ]
[ po-test required_test.cpp : required_test.cfg ]
;
exe test_convert : test_convert.cpp ;

View File

@@ -9,14 +9,15 @@
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.
*/
@@ -30,7 +31,6 @@ const int s_short_adjacent_not_allowed = 5;
const int s_empty_adjacent_parameter = 6;
const int s_missing_parameter = 7;
const int s_extra_parameter = 8;
const int s_unrecognized_line = 9;
int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k)
{
@@ -41,7 +41,6 @@ int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k)
invalid_command_line_syntax::empty_adjacent_parameter,
invalid_command_line_syntax::missing_parameter,
invalid_command_line_syntax::extra_parameter,
invalid_command_line_syntax::unrecognized_line
};
invalid_command_line_syntax::kind_t *b, *e, *i;
b = table;
@@ -185,7 +184,7 @@ void test_long_options()
{"--bar", s_missing_parameter, ""},
{"--bar=123", s_success, "bar:123"},
{0, 0, 0}
{0}
};
test_cmdline("foo bar=", style, test_cases1);
@@ -200,7 +199,7 @@ void test_long_options()
// considered a value, even though it looks like
// an option.
{"--bar --foo", s_success, "bar:--foo"},
{0, 0, 0}
{0}
};
test_cmdline("foo bar=", style, test_cases2);
style = cmdline::style_t(
@@ -210,7 +209,7 @@ void test_long_options()
test_case test_cases3[] = {
{"--bar=10", s_success, "bar:10"},
{"--bar 11", s_success, "bar:11"},
{0, 0, 0}
{0}
};
test_cmdline("foo bar=", style, test_cases3);
@@ -218,6 +217,8 @@ void test_long_options()
allow_long | long_allow_adjacent
| long_allow_next | case_insensitive);
// FIXME: restore
#if 0
// Test case insensitive style.
// Note that option names are normalized to lower case.
test_case test_cases4[] = {
@@ -226,9 +227,10 @@ void test_long_options()
{"--bar=Ab", s_success, "bar:Ab"},
{"--Bar=ab", s_success, "bar:ab"},
{"--giz", s_success, "Giz:"},
{0, 0, 0}
{0}
};
test_cmdline("foo bar= baz? Giz", style, test_cases4);
#endif
}
void test_short_options()
@@ -248,7 +250,7 @@ void test_short_options()
{"-f14", s_success, "-f:14"},
{"-g -f1", s_success, "-g: -f:1"},
{"-f", s_missing_parameter, ""},
{0, 0, 0}
{0}
};
test_cmdline(",d ,f= ,g", style, test_cases1);
@@ -261,8 +263,8 @@ void test_short_options()
{"-f -13", s_success, "-f:-13"},
{"-f", s_missing_parameter, ""},
{"-f /foo", s_success, "-f:/foo"},
{"-f -d", s_missing_parameter, ""},
{0, 0, 0}
{"-f -d", s_success, "-f:-d"},
{0}
};
test_cmdline(",d ,f=", style, test_cases2);
@@ -273,8 +275,8 @@ void test_short_options()
test_case test_cases3[] = {
{"-f10", s_success, "-f:10"},
{"-f 10", s_success, "-f:10"},
{"-f -d", s_missing_parameter, ""},
{0, 0, 0}
{"-f -d", s_success, "-f:-d"},
{0}
};
test_cmdline(",d ,f=", style, test_cases3);
@@ -290,7 +292,7 @@ void test_short_options()
//{"-d12", s_extra_parameter, ""},
{"-f12", s_success, "-f:12"},
{"-fe", s_success, "-f:e"},
{0, 0, 0}
{0}
};
test_cmdline(",d ,f= ,e", style, test_cases4);
@@ -312,7 +314,7 @@ void test_dos_options()
{"/d13", s_extra_parameter, ""},
{"/f14", s_success, "-f:14"},
{"/f", s_missing_parameter, ""},
{0, 0, 0}
{0}
};
test_cmdline(",d ,f=", style, test_cases1);
@@ -324,7 +326,7 @@ void test_dos_options()
test_case test_cases2[] = {
{"/de", s_extra_parameter, ""},
{"/fe", s_success, "-f:e"},
{0, 0, 0}
{0}
};
test_cmdline(",d ,f= ,e", style, test_cases2);
@@ -346,7 +348,7 @@ void test_disguised_long()
{"-foo -f", s_success, "foo: foo:"},
{"-goo=x -gy", s_success, "goo:x goo:y"},
{"-bee=x -by", s_success, "bee:x bee:y"},
{0, 0, 0}
{0}
};
test_cmdline("foo,f goo,g= bee,b?", style, test_cases1);
@@ -354,7 +356,7 @@ void test_disguised_long()
test_case test_cases2[] = {
{"/foo -f", s_success, "foo: foo:"},
{"/goo=x", s_success, "goo:x"},
{0, 0, 0}
{0}
};
test_cmdline("foo,f goo,g= bee,b?", style, test_cases2);
}
@@ -375,7 +377,7 @@ void test_guessing()
{"--opt", s_ambiguous_option, ""},
{"--f=1", s_success, "foo:1"},
{"-far", s_success, "foo:ar"},
{0, 0, 0}
{0}
};
test_cmdline("opt123 opt56 foo,f=", style, test_cases1);
}
@@ -393,7 +395,7 @@ void test_arguments()
test_case test_cases1[] = {
{"-f file -gx file2", s_success, "-f: file -g:x file2"},
{"-f - -gx - -- -e", s_success, "-f: - -g:x - -e"},
{0, 0, 0}
{0}
};
test_cmdline(",f ,g= ,e", style, test_cases1);
@@ -406,7 +408,7 @@ void test_arguments()
test_case test_cases2[] = {
{"-f - -gx - -- -e", s_success, "-f: - -g:x - -e"},
{0, 0, 0}
{0}
};
test_cmdline(",f ,g= ,e", style, test_cases2);
}
@@ -424,7 +426,7 @@ void test_prefix()
test_case test_cases1[] = {
{"--foo.bar=12", s_success, "foo.bar:12"},
{0, 0, 0}
{0}
};
test_cmdline("foo*=", style, test_cases1);
@@ -598,7 +600,7 @@ void test_unregistered()
// It's not clear yet, so I'm leaving the decision till later.
}
int main(int /*ac*/, char** /*av*/)
int test_main(int ac, char* av[])
{
test_long_options();
test_short_options();

View File

@@ -1,9 +0,0 @@
gv1 = 0#asd
empty_value =
plug3 = 7
b = true
[m1]
v1 = 1
v2 = 2

View File

@@ -1,164 +0,0 @@
// Copyright Sascha Ochsenknecht 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/cmdline.hpp>
using namespace boost::program_options;
#include <iostream>
#include <sstream>
#include <vector>
#include <cassert>
using namespace std;
#include "minitest.hpp"
void test_ambiguous()
{
options_description desc;
desc.add_options()
("cfgfile,c", value<string>()->multitoken(), "the config file")
("output,c", value<string>(), "the output file")
("output,o", value<string>(), "the output file")
;
const char* cmdline[] = {"program", "-c", "file", "-o", "anotherfile"};
variables_map vm;
try {
store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
const_cast<char**>(cmdline), desc), vm);
}
catch (ambiguous_option& e)
{
BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
BOOST_CHECK_EQUAL(e.get_option_name(), "-c");
BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
}
}
void test_unknown_option()
{
options_description desc;
desc.add_options()
("cfgfile,c", value<string>(), "the configfile")
;
const char* cmdline[] = {"program", "-c", "file", "-f", "anotherfile"};
variables_map vm;
try {
store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
const_cast<char**>(cmdline), desc), vm);
}
catch (unknown_option& e)
{
BOOST_CHECK_EQUAL(e.get_option_name(), "-f");
BOOST_CHECK_EQUAL(string(e.what()), "unknown option -f");
}
}
void test_multiple_values()
{
options_description desc;
desc.add_options()
("cfgfile,c", value<string>()->multitoken(), "the config file")
("output,o", value<string>(), "the output file")
;
const char* cmdline[] = { "program", "-o", "fritz", "hugo", "--cfgfile", "file", "c", "-o", "text.out" };
variables_map vm;
try {
store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
const_cast<char**>(cmdline), desc), vm);
notify(vm);
}
catch (validation_error& e)
{
// TODO: this is currently validation_error, shouldn't it be multiple_values ???
//
// multiple_values is thrown only at one place untyped_value::xparse(),
// but I think this can never be reached
// because: untyped_value always has one value and this is filtered before reach specific
// validation and parsing
//
BOOST_CHECK_EQUAL(e.get_option_name(), "cfgfile");
BOOST_CHECK_EQUAL(string(e.what()), "in option 'cfgfile': multiple values not allowed");
}
}
void test_multiple_occurrences()
{
options_description desc;
desc.add_options()
("cfgfile,c", value<string>(), "the configfile")
;
const char* cmdline[] = {"program", "--cfgfile", "file", "-c", "anotherfile"};
variables_map vm;
try {
store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
const_cast<char**>(cmdline), desc), vm);
notify(vm);
}
catch (multiple_occurrences& e)
{
BOOST_CHECK_EQUAL(e.get_option_name(), "cfgfile");
BOOST_CHECK_EQUAL(string(e.what()), "multiple occurrences");
}
}
void test_missing_value()
{
options_description desc;
desc.add_options()
("cfgfile,c", value<string>()->multitoken(), "the config file")
("output,o", value<string>(), "the output file")
;
// missing value for option '-c'
const char* cmdline[] = { "program", "-c", "-c", "output.txt"};
variables_map vm;
try {
store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
const_cast<char**>(cmdline), desc), vm);
notify(vm);
}
catch (invalid_command_line_syntax& e)
{
BOOST_CHECK_EQUAL(e.kind(), invalid_syntax::missing_parameter);
BOOST_CHECK_EQUAL(e.tokens(), "cfgfile");
}
}
int main(int /*ac*/, char** /*av*/)
{
test_ambiguous();
test_unknown_option();
test_multiple_values();
test_multiple_occurrences();
test_missing_value();
return 0;
}

View File

@@ -1,25 +0,0 @@
#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

View File

@@ -10,61 +10,21 @@ 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;
desc.add_options()
("foo", value<int>(), "")
("bar", value<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(string));
}
void test_approximation()
{
options_description desc;
desc.add_options()
("foo", new untyped_value())
("fee", new untyped_value())
("baz", new untyped_value())
("all-chroots", new untyped_value())
("all-sessions", new untyped_value())
("all", new untyped_value())
;
("foo", new untyped_value())
("fee", new untyped_value())
("baz", 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");
options_description desc2;
desc2.add_options()
("help", "display this message")
("config", value<string>(), "config file name")
("config-value", value<string>(), "single config value")
;
BOOST_CHECK_EQUAL(desc2.find("config", true).long_name(), "config");
BOOST_CHECK_EQUAL(desc2.find("config-value", true).long_name(),
"config-value");
// BOOST_CHECK(desc.count_approx("foo") == 1);
// set<string> a = desc.approximations("f");
// BOOST_CHECK(a.size() == 2);
@@ -72,172 +32,8 @@ void test_approximation()
// BOOST_CHECK(*(++a.begin()) == "foo");
}
void test_formatting()
int test_main(int, char* [])
{
// 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")
("list", new untyped_value(),
"a list:\n \t"
"item1, item2, item3, item4, item5, item6, item7, item8, item9, "
"item10, item11, item12, item13, item14, item15, item16, item17, item18")
("well_formated", new untyped_value(),
"As you can see this is a very well formatted option description.\n"
"You can do this for example:\n\n"
"Values:\n"
" Value1: \tdoes this and that, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
" Value2: \tdoes something else, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n\n"
" This paragraph has a first line indent only, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla")
;
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
" --test arg foo foo foo foo foo foo foo foo foo foo foo foo foo \n"
" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
" foo\n"
" --list arg a list:\n"
" item1, item2, item3, item4, item5, item6, item7, \n"
" item8, item9, item10, item11, item12, item13, \n"
" item14, item15, item16, item17, item18\n"
" --well_formated arg As you can see this is a very well formatted option \n"
" description.\n"
" You can do this for example:\n"
" \n"
" Values:\n"
" Value1: does this and that, bla bla bla bla bla bla \n"
" bla bla bla bla bla bla bla bla bla\n"
" Value2: does something else, bla bla bla bla bla bla \n"
" bla bla bla bla bla bla bla bla bla\n"
" \n"
" This paragraph has a first line indent only, bla \n"
" bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
);
}
void test_formatting_description_length()
{
{
options_description desc("",
options_description::m_default_line_length,
options_description::m_default_line_length / 2U);
desc.add_options()
("an-option-that-sets-the-max", new untyped_value(), // > 40 available for desc
"this description sits on the same line, but wrapping should still work correctly")
("a-long-option-that-would-leave-very-little-space-for-description", new untyped_value(),
"the description of the long opt, but placed on the next line\n"
" \talso ensure that the tabulation works correctly when a"
" description size has been set");
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
" --an-option-that-sets-the-max arg this description sits on the same line,\n"
" but wrapping should still work \n"
" correctly\n"
" --a-long-option-that-would-leave-very-little-space-for-description arg\n"
" the description of the long opt, but \n"
" placed on the next line\n"
" also ensure that the tabulation \n"
" works correctly when a description \n"
" size has been set\n");
}
{
// the default behaviour reserves 23 (+1 space) characters for the
// option column; this shows that the min_description_length does not
// breach that.
options_description desc("",
options_description::m_default_line_length,
options_description::m_default_line_length - 10U); // leaves < 23 (default option space)
desc.add_options()
("an-option-that-encroaches-description", new untyped_value(),
"this description should always be placed on the next line, and wrapping should continue as normal");
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
" --an-option-that-encroaches-description arg\n"
//123456789_123456789_
" this description should always be placed on the next line, and \n"
" wrapping should continue as normal\n");
}
}
void test_long_default_value()
{
options_description desc;
desc.add_options()
("cfgfile,c",
value<string>()->default_value("/usr/local/etc/myprogramXXXXXXXXX/configuration.conf"),
"the configfile")
;
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
" -c [ --cfgfile ] arg (=/usr/local/etc/myprogramXXXXXXXXX/configuration.conf)\n"
" the configfile\n"
);
}
void test_word_wrapping()
{
options_description desc("Supported options");
desc.add_options()
("help", "this is a sufficiently long text to require word-wrapping")
("prefix", value<string>()->default_value("/h/proj/tmp/dispatch"), "root path of the dispatch installation")
("opt1", "this_is_a_sufficiently_long_text_to_require_word-wrapping_but_cannot_be_wrapped")
("opt2", "this_is_a_sufficiently long_text_to_require_word-wrapping")
("opt3", "this_is_a sufficiently_long_text_to_require_word-wrapping_but_will_not_be_wrapped")
;
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
"Supported options:\n"
" --help this is a sufficiently long text to \n"
" require word-wrapping\n"
" --prefix arg (=/h/proj/tmp/dispatch) root path of the dispatch installation\n"
" --opt1 this_is_a_sufficiently_long_text_to_requ\n"
" ire_word-wrapping_but_cannot_be_wrapped\n"
" --opt2 this_is_a_sufficiently \n"
" long_text_to_require_word-wrapping\n"
" --opt3 this_is_a sufficiently_long_text_to_requ\n"
" ire_word-wrapping_but_will_not_be_wrappe\n"
" d\n"
);
}
void test_default_values()
{
options_description desc("Supported options");
desc.add_options()
("maxlength", value<double>()->default_value(.1, "0.1"), "Maximum edge length to keep.")
;
stringstream ss;
ss << desc;
BOOST_CHECK_EQUAL(ss.str(),
"Supported options:\n"
" --maxlength arg (=0.1) Maximum edge length to keep.\n"
);
}
int main(int, char* [])
{
test_type();
test_approximation();
test_formatting();
test_formatting_description_length();
test_long_default_value();
test_word_wrapping();
test_default_values();
return 0;
}

View File

@@ -6,7 +6,6 @@
#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;
@@ -14,17 +13,13 @@ 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 \
@@ -57,7 +52,7 @@ void check_value(const option& option, const char* name, const char* value)
BOOST_CHECK(option.value.front() == value);
}
vector<string> sv(const char* array[], unsigned size)
vector<string> sv(char* array[], unsigned size)
{
vector<string> r;
for (unsigned i = 0; i < size; ++i)
@@ -113,10 +108,10 @@ void test_command_line()
("baz", new untyped_value())
("plug*", new untyped_value())
;
const char* cmdline3_[] = { "--foo=12", "-f4", "--bar=11", "-b4",
char* cmdline3_[] = { "--foo=12", "-f4", "--bar=11", "-b4",
"--plug3=10"};
vector<string> cmdline3 = sv(cmdline3_,
sizeof(cmdline3_)/sizeof(const char*));
sizeof(cmdline3_)/sizeof(cmdline3_[0]));
vector<option> a3 =
command_line_parser(cmdline3).options(desc).run().options;
@@ -131,78 +126,21 @@ void test_command_line()
// Regression test: check that '0' as style is interpreted as
// 'default_style'
vector<option> a4 =
parse_command_line(sizeof(cmdline3_)/sizeof(const char*), cmdline3_,
desc, 0, additional_parser).options;
parse_command_line(5, cmdline3_, desc, 0, additional_parser).options;
BOOST_CHECK_EQUAL(a4.size(), 4u);
check_value(a4[0], "foo", "4");
check_value(a4[1], "bar", "11");
// Check that we don't crash on empty values of type 'string'
const char* cmdline4[] = {"", "--open", ""};
options_description desc2;
desc2.add_options()
("open", po::value<string>())
;
variables_map vm;
po::store(po::parse_command_line(sizeof(cmdline4)/sizeof(const char*), const_cast<char**>(cmdline4), desc2), vm);
const char* cmdline5[] = {"", "-p7", "-o", "1", "2", "3", "-x8"};
options_description desc3;
desc3.add_options()
(",p", po::value<string>())
(",o", po::value<string>()->multitoken())
(",x", po::value<string>())
;
vector<option> a5 =
parse_command_line(sizeof(cmdline5)/sizeof(const char*), const_cast<char**>(cmdline5),
desc3, 0, additional_parser).options;
BOOST_CHECK_EQUAL(a5.size(), 3u);
check_value(a5[0], "-p", "7");
BOOST_REQUIRE(a5[1].value.size() == 3);
BOOST_CHECK_EQUAL(a5[1].string_key, "-o");
BOOST_CHECK_EQUAL(a5[1].value[0], "1");
BOOST_CHECK_EQUAL(a5[1].value[1], "2");
BOOST_CHECK_EQUAL(a5[1].value[2], "3");
check_value(a5[2], "-x", "8");
po::options_description desc4( "" );
desc4.add_options()
( "multitoken,m",
po::value< std::vector< std::string > >()->multitoken(),
"values"
)
( "file",
po::value< std::string >(),
"the file to process"
)
;
po::positional_options_description p;
p.add( "file", 1 );
const char* cmdline6[] = {"", "-m", "token1", "token2", "--", "some_file"};
vector<option> a6 =
command_line_parser(sizeof(cmdline6)/sizeof(const char*), const_cast<char**>(cmdline6)).options(desc4).positional(p)
.run().options;
BOOST_CHECK_EQUAL(a6.size(), 2u);
BOOST_REQUIRE(a6[0].value.size() == 2);
BOOST_CHECK_EQUAL(a6[0].string_key, "multitoken");
BOOST_CHECK_EQUAL(a6[0].value[0], "token1");
BOOST_CHECK_EQUAL(a6[0].value[1], "token2");
BOOST_CHECK_EQUAL(a6[1].string_key, "file");
BOOST_REQUIRE(a6[1].value.size() == 1);
BOOST_CHECK_EQUAL(a6[1].value[0], "some_file");
}
void test_config_file(const char* config_file)
void test_config_file()
{
options_description desc;
desc.add_options()
("gv1", new untyped_value)
("gv2", new untyped_value)
("empty_value", new untyped_value)
("plug*", new untyped_value)
("m1.v1", new untyped_value)
("m1.v2", new untyped_value)
@@ -211,7 +149,6 @@ void test_config_file(const char* config_file)
const char content1[] =
" gv1 = 0#asd\n"
"empty_value = \n"
"plug3 = 7\n"
"b = true\n"
"[m1]\n"
@@ -222,23 +159,13 @@ void test_config_file(const char* config_file)
stringstream ss(content1);
vector<option> a1 = parse_config_file(ss, desc).options;
BOOST_REQUIRE(a1.size() == 6);
BOOST_REQUIRE(a1.size() == 5);
check_value(a1[0], "gv1", "0");
check_value(a1[1], "empty_value", "");
check_value(a1[2], "plug3", "7");
check_value(a1[3], "b", "true");
check_value(a1[4], "m1.v1", "1");
check_value(a1[5], "m1.v2", "2");
// same test, but now options come from file
vector<option> a2 = parse_config_file<char>(config_file, desc).options;
BOOST_REQUIRE(a2.size() == 6);
check_value(a2[0], "gv1", "0");
check_value(a2[1], "empty_value", "");
check_value(a2[2], "plug3", "7");
check_value(a2[3], "b", "true");
check_value(a2[4], "m1.v1", "1");
check_value(a2[5], "m1.v2", "2");
check_value(a1[1], "plug3", "7");
check_value(a1[2], "b", "true");
check_value(a1[3], "m1.v1", "1");
check_value(a1[4], "m1.v2", "2");
}
void test_environment()
@@ -252,7 +179,7 @@ void test_environment()
#if defined(_WIN32) && ! defined(__BORLANDC__)
_putenv("PO_TEST_FOO=1");
#else
putenv(const_cast<char*>("PO_TEST_FOO=1"));
putenv("PO_TEST_FOO=1");
#endif
parsed_options p = parse_environment(desc, "PO_TEST_");
@@ -265,63 +192,11 @@ void test_environment()
// which already has a value.
}
void test_unregistered()
{
options_description desc;
const char* cmdline1_[] = { "--foo=12", "--bar", "1"};
vector<string> cmdline1 = sv(cmdline1_,
sizeof(cmdline1_)/sizeof(const char*));
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);
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 main(int, char* av[])
int test_main(int, char* [])
{
test_command_line();
test_config_file(av[1]);
test_config_file();
test_environment();
test_unregistered();
return 0;
}

View File

@@ -12,8 +12,7 @@ namespace po = boost::program_options;
#include <boost/limits.hpp>
#include "minitest.hpp"
#include <boost/test/test_tools.hpp>
#include <vector>
using namespace std;
@@ -50,31 +49,28 @@ 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).add("some-other", 1);
p.add("input-file", 2);
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() == 5);
BOOST_REQUIRE(parsed.options.size() == 4);
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("file4");
args.push_back("file3");
// Check that excessive number of positional options is detected.
BOOST_CHECK_THROW(command_line_parser(args).options(desc).positional(p)
@@ -82,7 +78,7 @@ void test_parsing()
too_many_positional_options_error);
}
int main(int, char* [])
int test_main(int, char* [])
{
test_positional_options();
test_parsing();

View File

@@ -1 +0,0 @@
cfgfile = file.cfg

View File

@@ -1,97 +0,0 @@
// Copyright Sascha Ochsenknecht 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/program_options.hpp>
using namespace boost::program_options;
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
#include "minitest.hpp"
void required_throw_test()
{
options_description opts;
opts.add_options()
("cfgfile,c", value<string>()->required(), "the configfile")
("fritz,f", value<string>()->required(), "the output file")
;
variables_map vm;
bool throwed = false;
{
// This test must throw exception
string cmdline = "prg -f file.txt";
vector< string > tokens = split_unix(cmdline);
throwed = false;
try {
store(command_line_parser(tokens).options(opts).run(), vm);
notify(vm);
}
catch (required_option& e) {
throwed = true;
}
BOOST_CHECK(throwed);
}
{
// This test mustn't throw exception
string cmdline = "prg -c config.txt";
vector< string > tokens = split_unix(cmdline);
throwed = false;
try {
store(command_line_parser(tokens).options(opts).run(), vm);
notify(vm);
}
catch (required_option& e) {
throwed = true;
}
BOOST_CHECK(!throwed);
}
}
void simple_required_test(const char* config_file)
{
options_description opts;
opts.add_options()
("cfgfile,c", value<string>()->required(), "the configfile")
("fritz,f", value<string>()->required(), "the output file")
;
variables_map vm;
bool throwed = false;
{
// This test must throw exception
string cmdline = "prg -f file.txt";
vector< string > tokens = split_unix(cmdline);
throwed = false;
try {
// options coming from different sources
store(command_line_parser(tokens).options(opts).run(), vm);
store(parse_config_file<char>(config_file, opts), vm);
notify(vm);
}
catch (required_option& e) {
throwed = true;
}
BOOST_CHECK(!throwed);
}
}
int main(int /*argc*/, char* av[])
{
required_throw_test();
simple_required_test(av[1]);
return 0;
}

View File

@@ -1,189 +0,0 @@
// Copyright Sascha Ochsenknecht 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/cmdline.hpp>
using namespace boost::program_options;
#include <iostream>
#include <sstream>
#include <vector>
#include <cassert>
using namespace std;
#include "minitest.hpp"
void check_value(const string& option, const string& value)
{
BOOST_CHECK(option == value);
}
void split_whitespace(const options_description& description)
{
const char* cmdline = "prg --input input.txt \r --optimization 4 \t --opt \n option";
vector< string > tokens = split_unix(cmdline, " \t\n\r");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "option");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_equalsign(const options_description& description)
{
const char* cmdline = "prg --input=input.txt --optimization=4 --opt=option";
vector< string > tokens = split_unix(cmdline, "= ");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "option");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_semi(const options_description& description)
{
const char* cmdline = "prg;--input input.txt;--optimization 4;--opt option";
vector< string > tokens = split_unix(cmdline, "; ");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "option");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_quotes(const options_description& description)
{
const char* cmdline = "prg --input \"input.txt input.txt\" --optimization 4 --opt \"option1 option2\"";
vector< string > tokens = split_unix(cmdline, " ");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input.txt input.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "option1 option2");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_escape(const options_description& description)
{
const char* cmdline = "prg --input \\\"input.txt\\\" --optimization 4 --opt \\\"option1\\ option2\\\"";
vector< string > tokens = split_unix(cmdline, " ");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "\"input.txt\"");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "\"option1 option2\"");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_single_quote(const options_description& description)
{
const char* cmdline = "prg --input 'input.txt input.txt' --optimization 4 --opt 'option1 option2'";
vector< string > tokens = split_unix(cmdline, " ", "'");
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input.txt input.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "option1 option2");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
void split_defaults(const options_description& description)
{
const char* cmdline = "prg --input \t \'input file.txt\' \t --optimization 4 --opt \\\"option1\\ option2\\\"";
vector< string > tokens = split_unix(cmdline);
BOOST_REQUIRE(tokens.size() == 7);
check_value(tokens[0], "prg");
check_value(tokens[1], "--input");
check_value(tokens[2], "input file.txt");
check_value(tokens[3], "--optimization");
check_value(tokens[4], "4");
check_value(tokens[5], "--opt");
check_value(tokens[6], "\"option1 option2\"");
variables_map vm;
store(command_line_parser(tokens).options(description).run(), vm);
notify(vm);
}
int main(int /*ac*/, char** /*av*/)
{
options_description desc;
desc.add_options()
("input,i", value<string>(), "the input file")
("optimization,O", value<unsigned>(), "optimization level")
("opt,o", value<string>(), "misc option")
;
split_whitespace(desc);
split_equalsign(desc);
split_semi(desc);
split_quotes(desc);
split_escape(desc);
split_single_quote(desc);
split_defaults(desc);
return 0;
}

View File

@@ -3,12 +3,11 @@
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <cstring>
#include <cassert>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cassert>
#include <boost/progress.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
@@ -16,8 +15,6 @@
#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)
@@ -39,8 +36,8 @@ std::wstring from_8_bit_2(const std::string& s,
std::wstring result;
std::mbstate_t state = std::mbstate_t();
std::mbstate_t state = {0};
const char* from = s.data();
const char* from_end = s.data() + s.size();
// The interace of cvt is not really iterator-like, and it's
@@ -78,7 +75,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 facet;
boost::program_options::detail::utf8_codecvt_facet<wchar_t, char> facet;
std::wstring output;
{
@@ -97,7 +94,7 @@ void test_convert(const std::string& input,
facet);
}
BOOST_CHECK(output.size()*2 == expected_output.size());
assert(output.size()*2 == expected_output.size());
for(unsigned i = 0; i < output.size(); ++i) {
@@ -106,23 +103,23 @@ void test_convert(const std::string& input,
low &= 0xFF;
unsigned low2 = expected_output[2*i];
low2 &= 0xFF;
BOOST_CHECK(low == low2);
assert(low == low2);
}
{
unsigned high = output[i];
high >>= 8;
high &= 0xFF;
unsigned high2 = expected_output[2*i+1];
BOOST_CHECK(high == high2);
assert(high == high2);
}
}
string ref = boost::to_8_bit(output, facet);
BOOST_CHECK(ref == input);
assert(ref == input);
}
int main(int ac, char* av[])
int test_main(int ac, char* av[])
{
std::string input = file_content("utf8.txt");
std::string expected = file_content("ucs2.txt");

View File

@@ -15,11 +15,12 @@ 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()
@@ -34,13 +35,9 @@ void test_unicode_to_unicode()
args.push_back(L"--foo=\x044F");
variables_map vm;
basic_parsed_options<wchar_t> parsed =
wcommand_line_parser(args).options(desc).run();
store(parsed, vm);
store(wcommand_line_parser(args).options(desc).run(), vm);
BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
BOOST_CHECK(parsed.options[0].original_tokens.size() == 1);
BOOST_CHECK(parsed.options[0].original_tokens[0] == L"--foo=\x044F");
BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
}
// Test that unicode input is property converted into
@@ -88,7 +85,8 @@ void test_native_to_unicode()
BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
}
vector<wstring> sv(const wchar_t* array[], unsigned size)
vector<wstring> sv(wchar_t* array[], unsigned size)
{
vector<wstring> r;
for (unsigned i = 0; i < size; ++i)
@@ -114,7 +112,7 @@ void test_command_line()
("plug*", new untyped_value())
;
const wchar_t* cmdline4_[] = { L"--foo=1\u0FF52", L"-f4", L"--bar=11",
wchar_t* cmdline4_[] = { L"--foo=1\u0FF52", L"-f4", L"--bar=11",
L"-b4", L"--plug3=10"};
vector<wstring> cmdline4 = sv(cmdline4_,
sizeof(cmdline4_)/sizeof(cmdline4_[0]));
@@ -151,7 +149,7 @@ void test_config_file()
BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
}
int main(int, char* [])
int test_main(int, char* [])
{
test_unicode_to_unicode();
test_unicode_to_native();

View File

@@ -1,88 +0,0 @@
// Copyright Sascha Ochsenknecht 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/detail/cmdline.hpp>
using namespace boost::program_options;
using boost::program_options::detail::cmdline;
#include <iostream>
#include <sstream>
#include <vector>
#include <cassert>
using namespace std;
#include "minitest.hpp"
// Test free function collect_unrecognized()
//
// it collects the tokens of all not registered options. It can be used
// to pass them to an own parser implementation
void test_unrecognize_cmdline()
{
options_description desc;
string content = "prg --input input.txt --optimization 4 --opt option";
vector< string > tokens = split_unix(content);
cmdline cmd(tokens);
cmd.set_options_description(desc);
cmd.allow_unregistered();
vector< option > opts = cmd.run();
vector< string > result = collect_unrecognized(opts, include_positional);
BOOST_CHECK_EQUAL(result.size(), 7);
BOOST_CHECK_EQUAL(result[0], "prg");
BOOST_CHECK_EQUAL(result[1], "--input");
BOOST_CHECK_EQUAL(result[2], "input.txt");
BOOST_CHECK_EQUAL(result[3], "--optimization");
BOOST_CHECK_EQUAL(result[4], "4");
BOOST_CHECK_EQUAL(result[5], "--opt");
BOOST_CHECK_EQUAL(result[6], "option");
}
void test_unrecognize_config()
{
options_description desc;
string content =
" input = input.txt\n"
" optimization = 4\n"
" opt = option\n"
;
stringstream ss(content);
vector< option > opts = parse_config_file(ss, desc, true).options;
vector< string > result = collect_unrecognized(opts, include_positional);
BOOST_CHECK_EQUAL(result.size(), 6);
BOOST_CHECK_EQUAL(result[0], "input");
BOOST_CHECK_EQUAL(result[1], "input.txt");
BOOST_CHECK_EQUAL(result[2], "optimization");
BOOST_CHECK_EQUAL(result[3], "4");
BOOST_CHECK_EQUAL(result[4], "opt");
BOOST_CHECK_EQUAL(result[5], "option");
}
int main(int /*ac*/, char** /*av*/)
{
test_unrecognize_cmdline();
test_unrecognize_config();
return 0;
}

View File

@@ -15,12 +15,24 @@ 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"
#define TEST_CHECK_THROW(expression, exception, description) \
try \
{ \
expression; \
BOOST_ERROR(description);\
throw 10; \
} \
catch(exception &) \
{ \
}
vector<string> sv(const char* array[], unsigned size)
vector<string> sv(char* array[], unsigned size)
{
vector<string> r;
for (unsigned i = 0; i < size; ++i)
@@ -38,9 +50,9 @@ void test_variable_map()
("baz", new untyped_value())
("output,o", new untyped_value(), "")
;
const char* cmdline3_[] = { "--foo='12'", "--bar=11", "-z3", "-ofoo" };
char* cmdline3_[] = { "--foo='12'", "--bar=11", "-z3", "-ofoo" };
vector<string> cmdline3 = sv(cmdline3_,
sizeof(cmdline3_)/sizeof(const char*));
sizeof(cmdline3_)/sizeof(cmdline3_[0]));
parsed_options a3 = command_line_parser(cmdline3).options(desc).run();
variables_map vm;
store(a3, vm);
@@ -58,9 +70,9 @@ void test_variable_map()
("zak", po::value<int>(&i), "")
("opt", bool_switch(), "");
const char* cmdline4_[] = { "--zee", "--zak=13" };
char* cmdline4_[] = { "--zee", "--zak=13" };
vector<string> cmdline4 = sv(cmdline4_,
sizeof(cmdline4_)/sizeof(const char*));
sizeof(cmdline4_)/sizeof(cmdline4_[0]));
parsed_options a4 = command_line_parser(cmdline4).options(desc).run();
variables_map vm2;
@@ -78,9 +90,9 @@ void test_variable_map()
("voo", po::value<string>())
("iii", po::value<int>()->default_value(123))
;
const char* cmdline5_[] = { "--voo=1" };
char* cmdline5_[] = { "--voo=1" };
vector<string> cmdline5 = sv(cmdline5_,
sizeof(cmdline5_)/sizeof(const char*));
sizeof(cmdline5_)/sizeof(cmdline5_[0]));
parsed_options a5 = command_line_parser(cmdline5).options(desc2).run();
variables_map vm3;
@@ -90,28 +102,6 @@ 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))
("foo", po::value<int>())
;
/* The -m option is implicit. It does not have value in inside the token,
and we should not grab the next token. */
const char* cmdline6_[] = { "--imp=1", "-m", "--foo=1" };
vector<string> cmdline6 = sv(cmdline6_,
sizeof(cmdline6_)/sizeof(const char*));
parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
variables_map vm4;
store(a6, vm4);
notify(vm4);
BOOST_REQUIRE(vm4.size() == 4);
BOOST_CHECK(vm4["imp"].as<int>() == 1);
BOOST_CHECK(vm4["iim"].as<int>() == 201);
BOOST_CHECK(vm4["mmp"].as<int>() == 123);
}
int stored_value;
@@ -194,15 +184,15 @@ void test_priority()
("include", po::value< vector<int> >()->composing())
;
const char* cmdline1_[] = { "--first=1", "--aux=10", "--first=3", "--include=1" };
char* cmdline1_[] = { "--first=1", "--aux=10", "--first=3", "--include=1" };
vector<string> cmdline1 = sv(cmdline1_,
sizeof(cmdline1_)/sizeof(const char*));
sizeof(cmdline1_)/sizeof(cmdline1_[0]));
parsed_options p1 = command_line_parser(cmdline1).options(desc).run();
const char* cmdline2_[] = { "--first=12", "--second=7", "--include=7" };
char* cmdline2_[] = { "--first=12", "--second=7", "--include=7" };
vector<string> cmdline2 = sv(cmdline2_,
sizeof(cmdline2_)/sizeof(const char*));
sizeof(cmdline2_)/sizeof(cmdline2_[0]));
parsed_options p2 = command_line_parser(cmdline2).options(desc).run();
@@ -279,7 +269,7 @@ void test_multiple_assignments_with_different_option_description()
}
int main(int, char* [])
int test_main(int, char* [])
{
test_variable_map();
test_semantic_values();

View File

@@ -7,42 +7,26 @@
#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;
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/test/test_tools.hpp>
#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);\
check_equal(BOOST_PP_CAT(v, __LINE__), BOOST_PP_CAT(e, __LINE__),\
sizeof(BOOST_PP_CAT(e, __LINE__))/sizeof(char*));
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*));
// The following expectations were obtained in Win2000 shell:
TEST("1 ", {"1"});
@@ -61,13 +45,13 @@ void test_winmain()
TEST("1\\\\1 ", {"1\\\\1"});
}
int main(int, char*[])
int test_main(int, char*[])
{
test_winmain();
return 0;
}
#else
int main(int, char*[])
int test_main(int, char*[])
{
return 0;
}