#include "argparse.hpp" #include #include #include #include #include ArgParser::ArgParser(std::string program_name) : program_name_(std::move(program_name)) {} void ArgParser::addString(const std::string &name, const std::string &default_value, const std::string &help, bool required) { order_.push_back(name); meta_[name] = {OptionType::kString, help, required}; string_values_[name] = default_value; provided_[name] = false; } void ArgParser::addInt(const std::string &name, int default_value, const std::string &help, bool required) { order_.push_back(name); meta_[name] = {OptionType::kInt, help, required}; int_values_[name] = default_value; provided_[name] = false; } bool ArgParser::parse(int argc, char **argv, std::string *error) { for (int i = 1; i < argc; ++i) { std::string token(argv[i]); if (token == "--help" || token == "-h") { if (error) { *error = "help"; } return false; } if (token.rfind("--", 0) != 0) { if (error) { *error = "Unexpected positional argument: " + token; } return false; } std::string key; std::string value; size_t eq = token.find('='); if (eq == std::string::npos) { key = token.substr(2); if (i + 1 >= argc) { if (error) { *error = "Missing value for --" + key; } return false; } value = argv[++i]; } else { key = token.substr(2, eq - 2); value = token.substr(eq + 1); } auto m = meta_.find(key); if (m == meta_.end()) { if (error) { *error = "Unknown option: --" + key; } return false; } if (m->second.type == OptionType::kString) { string_values_[key] = value; provided_[key] = true; } else { errno = 0; char *endp = nullptr; long parsed = std::strtol(value.c_str(), &endp, 0); if (errno != 0 || endp == value.c_str() || *endp != '\0' || parsed < INT_MIN || parsed > INT_MAX) { if (error) { *error = "Invalid integer for --" + key + ": " + value; } return false; } int_values_[key] = static_cast(parsed); provided_[key] = true; } } for (const auto &key : order_) { auto m = meta_.find(key); if (m != meta_.end() && m->second.required && !has(key)) { if (error) { *error = "Missing required option: --" + key; } return false; } } return true; } bool ArgParser::has(const std::string &name) const { auto p = provided_.find(name); return p != provided_.end() && p->second; } std::string ArgParser::getString(const std::string &name) const { auto it = string_values_.find(name); if (it == string_values_.end()) { return std::string(); } return it->second; } int ArgParser::getInt(const std::string &name) const { auto it = int_values_.find(name); if (it == int_values_.end()) { return 0; } return it->second; } std::string ArgParser::helpText() const { std::ostringstream oss; oss << "Usage: " << program_name_ << " [options]\n\n"; oss << "Options:\n"; oss << " -h, --help Show this help\n"; for (const auto &key : order_) { auto m = meta_.find(key); if (m == meta_.end()) { continue; } oss << " --" << key << " "; if (m->second.required) { oss << " (required)"; } oss << "\n"; oss << " " << m->second.help; if (m->second.type == OptionType::kString) { auto s = string_values_.find(key); if (s != string_values_.end()) { oss << " [default: '" << s->second << "']"; } } else { auto iv = int_values_.find(key); if (iv != int_values_.end()) { oss << " [default: " << iv->second << "]"; } } oss << "\n"; } return oss.str(); }