|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r58273 - in trunk: boost/program_options libs/program_options/src libs/program_options/test
From: s.ochsenknecht_at_[hidden]
Date: 2009-12-10 15:25:54
Author: s_ochsenknecht
Date: 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
New Revision: 58273
URL: http://svn.boost.org/trac/boost/changeset/58273
Log:
reactive case_insensitive style for cmdline
Text files modified:
trunk/boost/program_options/cmdline.hpp | 13 ++++--
trunk/boost/program_options/option.hpp | 18 +++++++--
trunk/boost/program_options/options_description.hpp | 13 ++++--
trunk/libs/program_options/src/cmdline.cpp | 43 ++++++++++++++++++---
trunk/libs/program_options/src/options_description.cpp | 76 ++++++++++++++++++++++++++++-----------
trunk/libs/program_options/src/variables_map.cpp | 8 +---
trunk/libs/program_options/test/cmdline_test.cpp | 3 -
7 files changed, 125 insertions(+), 49 deletions(-)
Modified: trunk/boost/program_options/cmdline.hpp
==============================================================================
--- trunk/boost/program_options/cmdline.hpp (original)
+++ trunk/boost/program_options/cmdline.hpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -62,14 +62,19 @@
long option name if guessing is in effect.
*/
allow_guessing = allow_sticky << 1,
- /** Ignore the difference in case for options.
- @todo Should this apply to long options only?
+ /** Ignore the difference in case for long options.
*/
- case_insensitive = allow_guessing << 1,
+ 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),
/** Allow long options with single option starting character,
e.g <tt>-foo=10</tt>
*/
- allow_long_disguise = case_insensitive << 1,
+ allow_long_disguise = short_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
Modified: trunk/boost/program_options/option.hpp
==============================================================================
--- trunk/boost/program_options/option.hpp (original)
+++ trunk/boost/program_options/option.hpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -23,10 +23,17 @@
template<class charT>
class basic_option {
public:
- basic_option() : position_key(-1), unregistered(false) {}
+ basic_option()
+ : position_key(-1)
+ , unregistered(false)
+ , case_insensitive(false)
+ {}
basic_option(const std::string& string_key,
- const std::vector< std::string> &value)
- : string_key(string_key), value(value), unregistered(false)
+ const std::vector< std::string> &value)
+ : string_key(string_key)
+ , value(value)
+ , unregistered(false)
+ , case_insensitive(false)
{}
/** String key of this option. Intentionally independent of the template
@@ -50,7 +57,10 @@
recovered from the "original_tokens" member.
*/
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;
Modified: trunk/boost/program_options/options_description.hpp
==============================================================================
--- trunk/boost/program_options/options_description.hpp (original)
+++ trunk/boost/program_options/options_description.hpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -83,7 +83,8 @@
/** Given 'option', specified in the input source,
return 'true' is 'option' specifies *this.
*/
- match_result match(const std::string& option, bool approx) const;
+ match_result match(const std::string& option, bool approx,
+ bool long_ignore_case, bool short_ignore_case) const;
/** Return the key that should identify the option, in
particular in the variables_map class.
@@ -191,11 +192,15 @@
*/
options_description_easy_init add_options();
- const option_description& find(const std::string& name, bool approx)
- const;
+ 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_nothrow(const std::string& name,
- bool approx) const;
+ bool approx,
+ bool long_ignore_case = false,
+ bool short_ignore_case = false) const;
const std::vector< shared_ptr<option_description> >& options() const;
Modified: trunk/libs/program_options/src/cmdline.cpp
==============================================================================
--- trunk/libs/program_options/src/cmdline.cpp (original)
+++ trunk/libs/program_options/src/cmdline.cpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -172,6 +172,12 @@
// 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)
@@ -284,7 +290,9 @@
const option_description* xd =
m_desc->find_nothrow(opt.string_key,
- (m_style & allow_guessing));
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive));
if (!xd)
continue;
@@ -348,6 +356,21 @@
}
}
}
+
+ // 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;
}
@@ -361,9 +384,10 @@
return;
// First check that the option is valid, and get its description.
- // TODO: case-sensitivity.
const option_description* xd = m_desc->find_nothrow(opt.string_key,
- (m_style & allow_guessing) ? true : false);
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive));
if (!xd)
{
@@ -427,7 +451,9 @@
if (!followed_option.empty())
{
const option_description* od = m_desc->find_nothrow(other_tokens[0],
- (m_style & allow_guessing) ? true : false);
+ 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));
@@ -461,7 +487,7 @@
adjacent = tok.substr(p+1);
if (adjacent.empty())
boost::throw_exception( invalid_command_line_syntax(name,
- invalid_command_line_syntax::empty_adjacent_parameter));
+ invalid_command_line_syntax::empty_adjacent_parameter) );
}
else
{
@@ -498,7 +524,8 @@
// option.
for(;;) {
const option_description* d
- = m_desc->find_nothrow(name, false);
+ = m_desc->find_nothrow(name, false, false,
+ is_style_active(short_case_insensitive));
// FIXME: check for 'allow_sticky'.
if (d && (m_style & allow_sticky) &&
@@ -563,7 +590,9 @@
((m_style & allow_slash_for_short) && tok[0] == '/')))
{
if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),
- (m_style & allow_guessing) ? true : false))
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive)))
{
args[0].insert(0, "-");
if (args[0][1] == '/')
Modified: trunk/libs/program_options/src/options_description.cpp
==============================================================================
--- trunk/libs/program_options/src/options_description.cpp (original)
+++ trunk/libs/program_options/src/options_description.cpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -28,6 +28,22 @@
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()
{
}
@@ -55,39 +71,51 @@
}
option_description::match_result
- option_description::match(const std::string& option, bool approx) const
+ option_description::match(const std::string& option,
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
{
- match_result result = no_match;
- if (!m_long_name.empty()) {
+ 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);
- if (*m_long_name.rbegin() == '*')
+ if (*local_long_name.rbegin() == '*')
{
// The name ends with '*'. Any specified name with the given
// prefix is OK.
- if (option.find(m_long_name.substr(0, m_long_name.length()-1))
+ if (local_option.find(local_long_name.substr(0, local_long_name.length()-1))
== 0)
result = approximate_match;
}
- if (approx)
+ if (local_long_name == local_option)
+ {
+ result = full_match;
+ }
+ else if (approx)
{
- if (m_long_name.find(option) == 0)
+ if (local_long_name.find(local_option) == 0)
{
- if (m_long_name == option)
- result = full_match;
- else
- result = approximate_match;
+ result = approximate_match;
}
}
- else
+ }
+
+ 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)
{
- if (m_long_name == option)
- result = full_match;
+ result = full_match;
}
}
-
- if (m_short_name == option)
- result = full_match;
return result;
}
@@ -253,9 +281,13 @@
}
const option_description&
- options_description::find(const std::string& name, bool approx) const
+ options_description::find(const std::string& name,
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
{
- const option_description* d = find_nothrow(name, approx);
+ const option_description* d = find_nothrow(name, approx,
+ long_ignore_case, short_ignore_case);
if (!d)
boost::throw_exception(unknown_option(name));
return *d;
@@ -269,7 +301,9 @@
const option_description*
options_description::find_nothrow(const std::string& name,
- bool approx) const
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
{
shared_ptr<option_description> found;
vector<string> approximate_matches;
@@ -281,7 +315,7 @@
for(unsigned i = 0; i < m_options.size(); ++i)
{
option_description::match_result r =
- m_options[i]->match(name, approx);
+ m_options[i]->match(name, approx, long_ignore_case, short_ignore_case);
if (r == option_description::no_match)
continue;
Modified: trunk/libs/program_options/src/variables_map.cpp
==============================================================================
--- trunk/libs/program_options/src/variables_map.cpp (original)
+++ trunk/libs/program_options/src/variables_map.cpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -58,12 +58,8 @@
if (xm.m_final.count(name))
continue;
- // Ignore options which are not described
- //TODO: consider this.
- //if (desc.count(name) == 0)
- // continue;
-
- const option_description& d = desc.find(name, false);
+ const option_description& d = desc.find(name, false,
+ false, false);
variable_value& v = m[name];
if (v.defaulted()) {
Modified: trunk/libs/program_options/test/cmdline_test.cpp
==============================================================================
--- trunk/libs/program_options/test/cmdline_test.cpp (original)
+++ trunk/libs/program_options/test/cmdline_test.cpp 2009-12-10 15:25:53 EST (Thu, 10 Dec 2009)
@@ -218,8 +218,6 @@
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[] = {
@@ -231,7 +229,6 @@
{0, 0, 0}
};
test_cmdline("foo bar= baz? Giz", style, test_cases4);
-#endif
}
void test_short_options()
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk