164 lines
5.8 KiB
C++
164 lines
5.8 KiB
C++
#ifndef INCLUDE_ARGPARSER_ARGPARSER_HPP_
|
|
#define INCLUDE_ARGPARSER_ARGPARSER_HPP_
|
|
|
|
#include <argparse.h>
|
|
#include <cstring>
|
|
#include <plog/Log.h>
|
|
#include <string>
|
|
#include <typeinfo>
|
|
#include <vector>
|
|
|
|
/**
|
|
* @class ArgumentParser
|
|
* @brief A class to handle command line arguments.
|
|
*
|
|
* This class provides methods to add, get and manage known arguments from the command line. It users
|
|
* (Argparse)[https://github.com/cofyc/argparse] under the hood
|
|
*/
|
|
class ArgumentParser {
|
|
public:
|
|
/**
|
|
* Constructor with application name, description and requirement of arguments.
|
|
*
|
|
* @param application_name Name of the application.
|
|
* @param description Description of the application.
|
|
* @param require_arguments Whether the application requires arguments or not.
|
|
*/
|
|
ArgumentParser(const std::string &application_name, const std::string &description, bool require_arguments = false,
|
|
std::vector<std::vector<std::string>> allowed_arguments = {})
|
|
: application_name_(application_name), description_(description), require_arguments_(require_arguments),
|
|
allowed_arguments_(allowed_arguments) {};
|
|
|
|
/**
|
|
* Destructor for ArgumentParser.
|
|
*/
|
|
~ArgumentParser();
|
|
|
|
/**
|
|
* Adds a flag to the list of flags.
|
|
*
|
|
* @tparam T Type of the flag value (int, float, bool or std::string).
|
|
* @param short_name Short name of the flag.
|
|
* @param long_name Long name of the flag.
|
|
* @param value Pointer to the flag value.
|
|
* @param description Description of the flag.
|
|
* \todo Support callbacks for flags as in
|
|
* https://github.com/cofyc/argparse/blob/682d4520b4bc2b646cdfcf078b2fed00b3d2da30/tests/basic.c#L34
|
|
* \todo Implement logic to allow only to choose from a specific set of choices for a variable
|
|
*/
|
|
template <typename T> void add_flag(char short_name, const std::string &long_name, T *value, const std::string &description) {
|
|
const std::type_info &flag_type = typeid(T);
|
|
|
|
// Clone strings so we dont lose reference to it
|
|
char *long_name_local = new char[long_name.size() + 1];
|
|
std::strncpy(long_name_local, long_name.c_str(), long_name.size());
|
|
long_name_local[long_name.size()] = '\0';
|
|
PLOG_VERBOSE << "Adding flag " << long_name_local << " to the list of flags" << std::endl;
|
|
|
|
char *description_local = new char[description.size() + 1];
|
|
std::strncpy(description_local, description.c_str(), description.size());
|
|
description_local[description.size()] = '\0';
|
|
|
|
struct argparse_option flag_opt = {ARGPARSE_OPT_END, short_name, long_name_local, value, description_local, NULL, 0, 0};
|
|
|
|
if (flag_type == typeid(int)) {
|
|
flag_opt.type = ARGPARSE_OPT_INTEGER;
|
|
PLOG_VERBOSE << "Flag " << long_name_local << " is of type int" << std::endl;
|
|
}
|
|
|
|
if (flag_type == typeid(uint)) {
|
|
flag_opt.type = ARGPARSE_OPT_INTEGER;
|
|
PLOG_VERBOSE << "Flag " << long_name_local << " is of type unsigned int" << std::endl;
|
|
}
|
|
|
|
else if (flag_type == typeid(float)) {
|
|
flag_opt.type = ARGPARSE_OPT_FLOAT;
|
|
PLOG_VERBOSE << "Flag " << long_name_local << " is of type float" << std::endl;
|
|
}
|
|
|
|
else if (flag_type == typeid(bool)) {
|
|
flag_opt.type = ARGPARSE_OPT_BOOLEAN;
|
|
flag_opt.value = NULL;
|
|
flag_opt.callback = opt_boolean_callback;
|
|
flag_opt.data = reinterpret_cast<intptr_t>(value);
|
|
PLOG_VERBOSE << "Flag " << long_name_local << " is of type bool" << std::endl;
|
|
}
|
|
|
|
else if (flag_type == typeid(std::string)) {
|
|
flag_opt.type = ARGPARSE_OPT_STRING;
|
|
flag_opt.value = NULL;
|
|
flag_opt.callback = opt_string_callback;
|
|
flag_opt.data = reinterpret_cast<intptr_t>(value);
|
|
PLOG_VERBOSE << "Flag " << long_name_local << " is of type str" << std::endl;
|
|
}
|
|
|
|
options_.push_back(flag_opt);
|
|
}
|
|
|
|
/**
|
|
* Parses the command line arguments.
|
|
*
|
|
* @param argc Number of command line arguments, including binary name.
|
|
* @param argv Array of command line arguments, including binary name at argv[0].
|
|
* @return True if parsing is successful, false otherwise.
|
|
*/
|
|
bool parse(int argc, const char **argv);
|
|
|
|
/**
|
|
* @brief Displays the usage message from argparse.
|
|
*
|
|
* This inline function calls `argparse_usage` with no arguments, printing the
|
|
* usage message to stdout.
|
|
*
|
|
* @note The output is not redirected or buffered; it will be printed directly to the console.
|
|
*/
|
|
inline void show_usage() { argparse_usage(&argparse_); };
|
|
|
|
/**
|
|
* @brief Returns a copy of the vector of command-line arguments.
|
|
*
|
|
* This method returns a copy of the internal `arguments_` vector, which is used to store
|
|
* the command-line arguments passed to the program. The returned vector is not modified.
|
|
*
|
|
* @return A copy of the `arguments_` vector.
|
|
*/
|
|
inline std::vector<std::string> get_arguments() const { return arguments_; };
|
|
|
|
private:
|
|
/**
|
|
* Vector of argparse options. Stores all flags/arguments added through add_flag
|
|
*/
|
|
std::vector<struct argparse_option> options_ = {OPT_HELP()};
|
|
|
|
/**
|
|
* List of command line arguments. Thing that are not flags, i.e. do not begin with -, will be stored here
|
|
*/
|
|
std::vector<std::string> arguments_;
|
|
|
|
std::string application_name_;
|
|
std::string description_;
|
|
bool require_arguments_;
|
|
struct argparse argparse_;
|
|
std::vector<std::vector<std::string>> allowed_arguments_;
|
|
|
|
/**
|
|
* Callback function for string options.
|
|
*
|
|
* @param parser Argument parser object.
|
|
* @param flag Argument option structure.
|
|
* @return 0 on success, non-zero otherwise.
|
|
*/
|
|
static int opt_string_callback(struct argparse *, const struct argparse_option *);
|
|
|
|
/**
|
|
* Callback function for boolean options.
|
|
*
|
|
* @param parser Argument parser object.
|
|
* @param flag Argument option structure.
|
|
* @return 0 on success, non-zero otherwise.
|
|
*/
|
|
static int opt_boolean_callback(struct argparse *, const struct argparse_option *);
|
|
};
|
|
|
|
#endif // INCLUDE_ARGPARSER_ARGPARSER_HPP_
|