python argParse like ArgParse class added

master
Denes Matetelki 13 years ago
parent dfe58dc4ce
commit 8a294bd0e7

@ -0,0 +1,105 @@
#ifndef ARGPARSE_HPP
#define ARGPARSE_HPP
#include <string>
#include <list>
#include <map>
#include <stdexcept>
// Aims for the functionality of Python argparse
// http://docs.python.org/library/argparse.html#module-argparse
class ArgParse
{
public:
enum ValueType {
TYPE_NONE,
TYPE_STRING,
TYPE_INT,
TYPE_DOUBLE,
TYPE_BOOL
};
enum ValueRequired {
OPTIONAL,
REQUIRED
};
ArgParse(const std::string description,
const std::string epilog = std::string(""),
const bool add_Help = true);
void addArgument(const std::string name, // "-f,--foo"
const std::string help,
const enum ValueType type = TYPE_NONE,
const enum ValueRequired valueRequired = REQUIRED,
const std::string valueName = std::string(""),
const std::string choices = std::string("")); // "yes,no" or range: [1..100]
bool parseArgs(const int argc,
const char* argv[]) throw(std::runtime_error);
bool parseArgs(const std::list<std::string> argList) throw(std::runtime_error);
// is this arg in the map of understood arguments?
bool isArg(const std::string arg) const;
// is this argument passed as a command line parameter?
bool foundArg(const std::string arg) const;
// argument is passed as a command line parameter, but has a value?
bool argHasValue(const std::string arg) const;
// return true is arg exists and the arg in &value
// arg need to be the same string as in addArgument ( "-h,--help" )
bool argAsString(const std::string arg, std::string &value) const;
bool argAsInt(const std::string arg, int &value) const;
bool argAsDouble(const std::string arg, double &value) const;
bool argAsBool(const std::string arg, bool &value) const;
std::string usage() const;
private:
struct Argument {
const std::string m_help;
const enum ValueType m_type;
const enum ValueRequired m_valueRequired;
const std::string m_valueName;
const std::string m_choices;
std::string m_value;
bool m_found;
bool m_valueHasBeenSet;
Argument (const std::string help,
const enum ValueType type = TYPE_NONE,
const enum ValueRequired valueRequired = REQUIRED,
const std::string valueName = std::string(""),
const std::string choices = std::string(""),
const std::string value = std::string(""))
: m_help(help)
, m_type(type)
, m_valueRequired(valueRequired)
, m_valueName(valueName)
, m_choices(choices)
, m_value(value)
, m_found(false)
, m_valueHasBeenSet(false) {};
};
// arg is just the shor or long form: "-h" or "--help"
std::map<std::string, Argument>::iterator findElement(const std::string param);
std::string m_description;
std::string m_epilog;
std::string m_programName;
std::map<std::string, Argument> m_params;
}; // class ArgParse
#endif // ARGPARSE_HPP

@ -0,0 +1,243 @@
#include "../include/ArgParse.hpp"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <stdio.h>
ArgParse::ArgParse(const std::string description,
const std::string epilog,
const bool add_Help)
: m_description(description)
, m_epilog(epilog)
, m_programName()
, m_params()
{
if (add_Help)
addArgument("-h,--help", "Prints this help message");
}
void ArgParse::addArgument(const std::string arg,
const std::string help,
const ValueType type,
const ValueRequired valueRequired,
const std::string valueName,
const std::string choices)
{
Argument argument(help, type, valueRequired, valueName, choices, "");
m_params.insert(std::pair<std::string, Argument>(arg, argument));
}
bool ArgParse::parseArgs(const int argc,
const char* argv[]) throw(std::runtime_error)
{
std::list<std::string> argList;
for (int i = 0; i < argc; ++i )
argList.push_back(argv[i]);
return parseArgs(argList);
}
bool ArgParse::parseArgs(const std::list<std::string> argList) throw(std::runtime_error)
{
m_programName = argList.front();
// the wrok.
std::list<std::string>::const_iterator it = argList.begin();
for (++it; it != argList.end(); ++it ) {
if ( (*it).at(0) != '-' )
throw std::runtime_error(std::string(*it).append(" shall start with a dash."));
// inspect each arument
std::map<std::string, Argument>::iterator it2 = findElement(*it);
if ( it2 == m_params.end() )
throw std::runtime_error(std::string(*it).append(" is not known."));
if ( (*it2).second.m_found )
throw std::runtime_error(std::string(*it).append(" has been given before."));
(*it2).second.m_found = true;
if ( (*it2).second.m_type == TYPE_NONE )
continue;
std::list<std::string>::const_iterator next = it;
next++;
if ( next == argList.end() ) {
if ( (*it2).second.m_valueRequired == REQUIRED )
throw std::runtime_error(std::string(*it).append(" requires a parameter."));
if ( (*it2).second.m_valueRequired == OPTIONAL )
continue;
}
if ( (*it2).second.m_valueRequired == OPTIONAL && findElement( *next ) != m_params.end() )
continue;
switch ( (*it2).second.m_type ) {
case TYPE_INT : {
int temp;
if ( sscanf( next->c_str(), "%d", &temp ) == 0 )
throw std::runtime_error(std::string( *next ).
append(" is not an integer, required by ").append(*it));
break;
}
case TYPE_DOUBLE : {
double temp;
if ( sscanf( next->c_str(), "%f", &temp ) == 0 )
throw std::runtime_error(std::string( *next ).
append(" is not a double, required by ").append(*it));
break;
}
case TYPE_BOOL : {
std::string temp = *next;
std::transform(temp.begin(), temp.end(),temp.begin(), ::toupper);
if ( temp != "TRUE" && temp != "FALSE" )
throw std::runtime_error(std::string( *next ).
append(" is not a boolean, required by ").append(*it));
break;
}
default:
break;
}
(*it2).second.m_value = *next;
(*it2).second.m_valueHasBeenSet = true;
++it;
}
return true;
}
bool ArgParse::isArg(const std::string arg) const
{
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
return it != m_params.end();
}
bool ArgParse::foundArg(const std::string arg) const
{
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
return it != m_params.end() && (*it).second.m_found == true;
}
bool ArgParse::argHasValue(const std::string arg) const
{
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
return it != m_params.end() &&
(*it).second.m_found == true &&
(*it).second.m_valueHasBeenSet;
}
bool ArgParse::argAsString(const std::string arg, std::string &value) const
{
if ( !argHasValue(arg) )
return false;
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
value = (*it).second.m_value;
return true;
}
bool ArgParse::argAsInt(const std::string arg, int &value) const
{
if ( !argHasValue(arg) )
return false;
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
value = atoi((*it).second.m_value.c_str());
return true;
}
bool ArgParse::argAsDouble(const std::string arg, double &value) const
{
if ( !argHasValue(arg) )
return false;
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
value = atof((*it).second.m_value.c_str());
return true;
}
bool ArgParse::argAsBool(const std::string arg, bool &value) const
{
if ( !argHasValue(arg) )
return false;
std::map<std::string, Argument>::const_iterator it = m_params.find(arg);
std::string temp = (*it).second.m_value;
std::transform(temp.begin(), temp.end(),temp.begin(), ::toupper);
value = temp == "TRUE";
return true;
}
std::string ArgParse::usage() const
{
std::stringstream ss;
ss << m_description << std::endl << std::endl;
ss << "usage: " << m_programName;
if (!m_params.empty()) {
ss << " [OPTION]" << std::endl << std::endl;
ss << "Options:" << std::endl;
int length;
std::map<std::string, Argument>::const_iterator it;
for ( it = m_params.begin(); it != m_params.end(); it++ ) {
ss << (*it).first;
length = (*it).first.length();
if ( (*it).second.m_type != TYPE_NONE ) {
if ((*it).second.m_valueRequired == REQUIRED ) {
ss << "=" << (*it).second.m_valueName;
length += (*it).second.m_valueName.length()+1;
} else {
ss << "[=" << (*it).second.m_valueName << "]";
length += (*it).second.m_valueName.length() + 3;
}
}
ss << std::string(30-length, ' ');
ss << (*it).second.m_help << std::endl;
}
}
ss << std::endl;
ss << m_epilog << std::endl;
return ss.str();;
}
std::map<std::string, ArgParse::Argument>::iterator
ArgParse::findElement(const std::string param)
{
std::map<std::string, Argument>::iterator it;
for( it = m_params.begin(); it != m_params.end(); ++it) {
// if it's the short param at the beginning
if ( (*it).first.find(param) == 0 )
return it;
// or is it the long after the comma?
size_t commaPos = (*it).first.find(",");
if ( commaPos != std::string::npos &&
(*it).first.find( param, commaPos+1 ) != std::string::npos )
return it;
}
return m_params.end();
}
Loading…
Cancel
Save