You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
5.6 KiB

#ifndef ARGPARSE_HPP
#define ARGPARSE_HPP
#include <string>
#include <list>
#include <map>
#include <set>
/** @brief Aim to achieve the functionality of Python argparse
*
* http://docs.python.org/library/argparse.html#module-argparse
*/
class ArgParse
{
public:
enum ValueType {
NONE,
STRING,
INT,
FLOAT,
BOOL
};
enum Required {
OPTIONAL,
REQUIRED
};
/** @param description Exmplanation of the purpose of the program,
* before the usage lines.
* @param epilog Lines after the usage and options. Usually contact e-mail.
* @param addHelp Add a "-h,--help" option.
*/
ArgParse(const std::string description,
const std::string epilog = std::string(""),
const bool addHelp = true);
/** @brief Adds an argument which the object will accept.
*
* @param name short and/or long form: "-f,--foo"
* The value can be retreived with this string passed to the argAs... functions.
* @param help Description of the argument, printed when --help is given.
* @param valueType Type of the paramterer, required by the argument.
* @param valueRequired Parameter requiered/optional after the argument.
* @param argRequired Argument is required or optional.
* It's a bad practice to have a required argument,
* "options", shall be optional.
* @param valueName Default is the type. But some short text can be better.
* @param choices Comma separeted list of strings without whitespaces:
* "yes,no,maybe"
* or a range accepted numbers: "INT..INT", "DOUBLE..DOUBLE"
*/
void addArgument(const std::string name,
const std::string help,
const ValueType valueType = NONE,
const Required valueRequired = REQUIRED,
const Required argRequired = OPTIONAL,
const std::string valueName = std::string(""),
const std::string choices = std::string(""));
/** @brief Parse command line arguments according to the accepted arguments.
*
* Wrapper around the list<string> version of parseArgs.
*
* @param argc Argumetn counter of the main function.
* @param argv Argument vector of the main function.
* @throw std::runtime_error When the command line args are bad.
* Shall be cought be the client code!
* @throw std::logic_error If the addArgument was bad.
*/
void parseArgs(int argc,
const char* argv[]);
void parseArgs(const std::list<std::string> argList);
// 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 argAsFloat(const std::string arg, float &value) const;
bool argAsBool(const std::string arg, bool &value) const;
std::string usage() const;
private:
bool thereAreOptionalArgs() const;
bool thereAreRequiredArgs() const;
std::string printArgs(const Required argRequired) const;
void checkRequiredArgsFound() const;
void validateValue(const ArgParse::ValueType type,
const std::string name,
const std::string choices,
const std::string value) const;
void validateString( const std::string name,
const std::string choices,
const std::string value) const;
void validateInt( const std::string name,
const std::string choices,
const std::string value) const;
void validateFloat( const std::string name,
const std::string choices,
const std::string value) const;
void validateBool( const std::string name,
const std::string choices,
const std::string value) const;
struct Argument {
const std::string m_help;
const ValueType m_type;
const Required m_valueRequired;
const Required m_argRequired;
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 ValueType type = NONE,
const Required valueRequired = REQUIRED,
const Required argRequired = OPTIONAL,
const std::string valueName = std::string(""),
const std::string choices = std::string(""),
const std::string value = std::string(""));
};
class argCompare {
public:
// short and long arg shall be compared with same amount of dashes
// this is needed at the usage, so the order of the params is ok,
// even when a param has short/long/booth name
bool operator()(const std::string a,const std::string b) const;
};
typedef std::map<std::string, Argument, argCompare> ArgMap;
// arg is just the shor or long form: "-h" or "--help"
ArgMap::iterator findKeyinArgMap(const std::string param);
std::set<std::string> choicesStringToSet(const std::string s) const;
/** @return with valueName if specified,
or the string version of the type enum otherwise */
std::string typeToString(const ValueType type,
const std::string valueName) const;
std::string m_description;
std::string m_epilog;
std::string m_programName;
ArgMap m_params;
}; // class ArgParse
#endif // ARGPARSE_HPP