jtag memory interface working
This commit is contained in:
158
tools/argparse.cpp
Normal file
158
tools/argparse.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "argparse.hpp"
|
||||
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
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<int>(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 << " <value>";
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user