-
David Flitney authoredDavid Flitney authored
options.cc 3.79 KiB
#include "options.h"
namespace Options {
void string_to_T(bool &b, const string& s) {
if(s == "NO ARG")
b = !b;
else
b = (s == "true");
}
void string_to_T(string& d, const string& s) {
d = s;
}
void string_to_T(int& i, const string& s) {
i = atoi(s.c_str());
}
void string_to_T(float& v, const string& s) {
v = atof(s.c_str());
}
bool BaseOption::matches(const string& arg)
{
string::size_type pos = 0, np;
while((np = key_.find(",", pos)) != string::npos) {
if(arg == key_.substr(pos, np - pos))
return true;
pos = np + 1;
}
if(arg == key_.substr(pos, string::npos))
return true;
return false;
}
ostream& operator<<(ostream &os, const BaseOption& o) {
return os <<
"\t" << o.key() <<
"\t" << o.help_text();
}
void OptionParser::usage()
{
cerr << endl << progname_ << endl << endl;
cerr << "Usage: " << endl << example_ << endl;
for(Options::iterator option = options_.begin(); option != options_.end();
option++)
{
if((*option)->compulsory()) {
static bool banner = true;
if(banner) {
cerr << endl << "Compulsory arguments (You MUST set one or more of):" << endl;
banner = false;
}
cerr << **option << endl;
}
}
for(Options::iterator option = options_.begin(); option != options_.end();
option++)
{
if(!(*option)->compulsory()) {
static bool banner = true;
if(banner) {
cerr << endl << "Optional arguments (You may optionally specify one or more of):" << endl;
banner = false;
}
cerr << **option << endl;
}
}
cerr << endl;
cerr << endl;
}
bool OptionParser::check_compulsory_arguments(bool verbose)
{
bool okay = true;
for(Options::iterator option = options_.begin();
option != options_.end();
option++) {
if((*option)->compulsory() && (*option)->unset()) {
if(okay) {
if(verbose) {
cerr << "***************************************************" << endl;
cerr << "The following COMPULSORY options have not been set:" << endl;
}
okay = false;
}
if(verbose)
cerr << **option << endl;
}
}
if(!okay && verbose)
cerr << "***************************************************" << endl;
return okay;
}
unsigned int OptionParser::parse_command_line(unsigned int argc,
char **argv)
throw(X_OptionError, X_UnknownOptions, X_MissingArguments)
{
unsigned int argcount = 1;
bool unknown_opts = false;
bool missing_args = false;
while(argcount < argc) {
unsigned int nmatches = 0;
unsigned int increments = 1;
string optstr(argv[argcount]), valstr;
if(argcount + 1 < argc)
valstr = string(argv[argcount+1]);
else
valstr = string("NO ARG");
if(optstr[0] != '-') // No more parsable options
break;
for(Options::iterator option = options_.begin();
option != options_.end();
option++) {
if((*option)->matches(optstr))
{
nmatches++;
if((*option)->required()) {
if(valstr != "NO ARG") {
(*option)->value(valstr);
increments = 2;
} else {
cerr << optstr << ": missing argument!" << endl;
missing_args = true;
}
} else if((*option)->optional()) {
if(valstr[0] != '-') {
(*option)->value(valstr);
increments = 2;
} else {
(*option)->value("NO ARG");
}
} else {
(*option)->value("NO ARG");
}
}
}
if(nmatches == 0) {
cerr << optstr << ": unknown option!" << endl;
unknown_opts = true;
}
argcount += increments;
}
if(unknown_opts && missing_args)
throw X_OptionError();
else if(unknown_opts)
throw X_UnknownOptions();
else if(missing_args)
throw X_MissingArguments();
return argcount; // User should process any remaining args
}
}