summaryrefslogtreecommitdiff
path: root/qpid/cpp/src/qpid/Options.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/src/qpid/Options.cpp')
-rw-r--r--qpid/cpp/src/qpid/Options.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/qpid/cpp/src/qpid/Options.cpp b/qpid/cpp/src/qpid/Options.cpp
index 4b13e349f5..499fb71bc3 100644
--- a/qpid/cpp/src/qpid/Options.cpp
+++ b/qpid/cpp/src/qpid/Options.cpp
@@ -30,6 +30,23 @@ namespace qpid {
using namespace std;
+/*
+ * ---------------------------------------------
+ * Explanation for Boost 103200 conditional code
+ * ---------------------------------------------
+ *
+ * Please see large comment in Options.h .
+ *
+ */
+
+#if ( BOOST_VERSION == 103200 )
+std::vector<std::string> Options::long_names;
+std::vector<std::string> Options::short_names;
+#endif
+
+
+
+
namespace {
struct EnvOptMapper {
@@ -52,11 +69,49 @@ struct EnvOptMapper {
static const std::string prefix("QPID_");
if (envVar.substr(0, prefix.size()) == prefix) {
string env = envVar.substr(prefix.size());
+#if (BOOST_VERSION >= 103300)
typedef const std::vector< boost::shared_ptr<po::option_description> > OptDescs;
OptDescs::const_iterator i =
find_if(opts.options().begin(), opts.options().end(), boost::bind(matchStr, env, _1));
if (i != opts.options().end())
return (*i)->long_name();
+#else
+ /*
+ * For Boost version 103200 and below.
+ *
+ * In Boost version 103200, the options_description::options member,
+ * used above, is private. So what I will do here is use the
+ * count() funtion, which returns a 1 or 0 indicating presence or
+ * absence of the environment variable.
+ *
+ * If it is present, I will return its name. Env vars do not have
+ * short and long forms, so the name is synonymous with the long
+ * name. (This would not work for command line args.)
+ * And if it's absent -- an empty string.
+ */
+
+
+ /*
+ * The env vars come in unaltered, i.e. QPID_FOO, but the
+ * options are stored normalized as "qpid-foo". Change the
+ * local variable "env" so it can be found by "opts".
+ */
+ for (std::string::iterator i = env.begin(); i != env.end(); ++i)
+ {
+ *i = (*i == '_')
+ ? '-'
+ : ::tolower(*i);
+ }
+
+ if ( opts.count(env.c_str()) > 0 )
+ {
+ return env.c_str();
+ }
+ else
+ {
+ return string();
+ }
+#endif
}
return string();
}
@@ -111,6 +166,10 @@ std::string prettyArg(const std::string& name, const std::string& value) {
Options::Options(const string& name) :
po::options_description(name)
+
+#if ( BOOST_VERSION == 103200 )
+ , m_less_easy(this, this)
+#endif
{
}
@@ -127,6 +186,7 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
parsing="command line options";
if (argc > 0 && argv != 0) {
if (allowUnknown) {
+#if (BOOST_VERSION >= 103300)
// This hideous workaround is required because boost 1.33 has a bug
// that causes 'allow_unregistered' to not work.
po::command_line_parser clp = po::command_line_parser(argc, const_cast<char**>(argv)).
@@ -140,6 +200,113 @@ void Options::parse(int argc, char const* const* argv, const std::string& config
filtopts.options.push_back (*i);
po::store(filtopts, vm);
+#elif ( BOOST_VERSION == 103200 )
+
+ /*
+ * "Tokenize" the argv to get rid of equals signs.
+ */
+ vector<string> tokenized_argv;
+ vector<string>::iterator iter;
+
+ for ( int i = 0; i < argc; ++ i )
+ {
+ string s = argv[i];
+ size_t equals_pos = s.find_first_of ( '=' );
+
+ if ( string::npos == equals_pos ) // There's no equals sign. This is a token.
+ {
+ tokenized_argv.push_back(s);
+ }
+ else
+ {
+ // Two tokens -- before and after the equals position.
+ tokenized_argv.push_back ( s.substr(0, equals_pos) );
+ tokenized_argv.push_back ( s.substr(equals_pos+1) );
+ }
+ }
+
+
+ /*
+ * Now "filter" the tokenized argv, to get rid of all
+ * unrecognized options. Because Boost 103200 has no
+ * facility for dealing gracefully with "unregistered"
+ * options.
+ */
+ vector<string> filtered_argv;
+ vector<string>::iterator the_end = tokenized_argv.end();
+
+ // The program-name gets in for free...
+ iter = tokenized_argv.begin();
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // ...but all other args get checked.
+ while ( iter < the_end )
+ {
+ /*
+ * If this is an argument that is registered,
+ * copy it to filtered_argv and also copy all
+ * of its arguments.
+ */
+ if ( is_registered_option ( * iter ) )
+ {
+ // Store this recognized arg.
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Args are tokens that do not start with a minus.
+ while ( (iter < the_end) && ((* iter)[0] != '-') )
+ {
+ filtered_argv.push_back ( * iter );
+ ++ iter;
+ }
+ }
+ else
+ {
+ // Skip this unrecognized arg.
+ ++ iter;
+
+ // Copy all values for the above arg.
+ // Values are tokens that do not start with a minus.
+ while ( (iter < the_end) && ( '-' != (*iter)[0] ) )
+ {
+ ++ iter;
+ }
+ }
+ }
+
+ // Make an array of temporary C strings, because
+ // the interface I can use wants it that way.
+ int new_argc = filtered_argv.size();
+ char ** new_argv = new char * [ new_argc ];
+ int i = 0;
+
+ // cout << "NEW ARGV: |";
+ for ( iter = filtered_argv.begin();
+ iter < filtered_argv.end();
+ ++ iter, ++ i
+ )
+ {
+ new_argv[i] = strdup( (* iter).c_str() );
+ // cout << " " << new_argv[i] ;
+ }
+ // cout << "|\n";
+
+
+ // Use the array of C strings.
+ po::basic_parsed_options<char> bpo = po::parse_command_line(new_argc, const_cast<char**>(new_argv), *this);
+ po::store(bpo, vm);
+
+
+ // Now free the temporary C strings.
+ for ( i = 0; i < new_argc; ++ i )
+ {
+ free ( new_argv[i] );
+ }
+ delete[] new_argv;
+
+#endif
}
else
po::store(po::parse_command_line(argc, const_cast<char**>(argv), *this), vm);
@@ -196,5 +363,107 @@ CommonOptions::CommonOptions(const string& name, const string& configfile)
}
+
+
+#if ( BOOST_VERSION == 103200 )
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ char const * description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, description );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(char const * name,
+ const po::value_semantic* s)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s );
+ return * this;
+}
+
+
+options_description_less_easy_init&
+options_description_less_easy_init::operator()(const char* name,
+ const po::value_semantic* s,
+ const char* description)
+{
+ // Snoop on the arguments....
+ owner->register_names ( name );
+ // ... then call parent function explicitly.
+ po::options_description_easy_init::operator() ( name, s, description );
+ return * this;
+}
+
+
+
+
+
+void
+Options::register_names ( std::string s )
+{
+
+ std::string::size_type comma_pos = s.find_first_of ( ',' );
+
+ if ( std::string::npos == comma_pos )
+ {
+ // There is no short-name.
+ long_names.push_back ( s );
+ }
+ else
+ {
+ std::string long_name = s.substr(0, comma_pos),
+ short_name = s.substr(comma_pos+1);
+ long_names .push_back ( long_name );
+ short_names.push_back ( short_name );
+ }
+
+ /*
+ * There is no way to tell when the adding of new options is finished,
+ * so I re-sort after each one.
+ */
+ std::sort ( long_names .begin(), long_names .end() );
+ std::sort ( short_names.begin(), short_names.end() );
+}
+
+
+
+
+
+bool
+Options::is_registered_option ( std::string s )
+{
+ std::string without_dashes = s.substr ( s.find_first_not_of ( '-' ) );
+ std::vector<std::string>::iterator i;
+
+ // Look among the long names.
+ i = std::find ( long_names.begin(),
+ long_names.end(),
+ without_dashes
+ );
+ if ( i != long_names.end() )
+ return true;
+
+ // Look among the short names.
+ i = std::find ( short_names.begin(),
+ short_names.end(),
+ without_dashes
+ );
+ if ( i != short_names.end() )
+ return true;
+
+
+ return false;
+}
+#endif
+
+
} // namespace qpid