13 #include <unordered_map>
20 Arg(
char shortName,
const std::string &longName,
const std::string &value,
bool required)
21 : shortName{ shortName }
22 , longName{ longName }
24 , required { required } {
40 void addArgument(
const std::string &shortName,
const std::string &longName, T value,
bool required =
false) {
41 std::string v = std::to_string(value);
42 addArgument<std::string>(shortName, longName, v, required);
45 bool parse(
int argc,
char **argv) {
46 appName = std::string(argv[0]);
47 for (
int i = 1; i < argc; i++) {
48 if (!isValidShort(argv[i]) && !isValidLong(argv[i])) {
49 fprintf(stderr,
"[WARNING] Unparsed argument: \"%s\"\n", argv[i]);
53 std::string longName =
"";
54 if (isValidShort(argv[i])) {
55 const auto &it = short2long.find(parseShort(argv[i]));
56 if (it == short2long.cend()) {
57 fprintf(stderr,
"[WARNING] Unknown flag %s!\n", argv[i]);
60 longName = it->second;
62 longName = parseLong(argv[i]);
65 if (table.find(longName) != table.cend()) {
66 values[longName] = std::string(argv[i + 1]);
73 for (
const auto &arg : args) {
75 const auto it = values.find(arg.longName);
76 if (it == values.cend()) {
78 fprintf(stderr,
"Required argument \"%s\" is not specified!\n", arg.longName.c_str());
86 std::string helpText() {
91 for (
const auto &arg : args) {
93 ss << (
"--" + arg.longName) <<
" " << toUpper(arg.longName) <<
" ";
98 for (
const auto &arg : args) {
100 ss <<
"[" << (
"--" + arg.longName) <<
" " << toUpper(arg.longName) <<
"] ";
107 int getInt(
const std::string &name)
const {
108 const auto &it = values.find(name);
109 if (it == values.cend()) {
110 fprintf(stderr,
"Unknown name: %s!\n", name.c_str());
113 return std::atoi(it->second.c_str());
116 double getDouble(
const std::string &name)
const {
117 const auto &it = values.find(name);
118 if (it == values.cend()) {
119 fprintf(stderr,
"Unknown name: %s!\n", name.c_str());
122 return std::atof(it->second.c_str());
125 bool getBool(
const std::string &name)
const {
126 const auto &it = values.find(name);
127 if (it == values.cend()) {
128 fprintf(stderr,
"Unknown name: %s!\n", name.c_str());
132 std::string value = it->second;
133 if (value ==
"True" || value ==
"true" || value ==
"Yes" || value ==
"yes") {
137 if (value ==
"False" || value ==
"false" || value ==
"No" || value ==
"no") {
141 throw std::runtime_error(
"Cannot parse spacified option to bool!");
144 std::string getString(
const std::string &name)
const {
145 const auto &it = values.find(name);
146 if (it == values.cend()) {
147 fprintf(stderr,
"Unknown name: %s!\n", name.c_str());
155 static bool isValidShort(
const std::string &name) {
156 return name.length() == 2 && name[0] ==
'-';
159 static bool isValidLong(
const std::string &name) {
160 return name.length() > 2 && name[0] ==
'-' && name[1] ==
'-';
163 static char parseShort(
const std::string &name) {
164 if (!isValidShort(name)) {
165 throw std::runtime_error(
"Short name must be a single charactor with a hyphen!");
170 static std::string parseLong(
const std::string &name) {
171 if (!isValidLong(name)) {
172 throw std::runtime_error(
"Long name must begin with two hyphens!");
174 return name.substr(2);
177 static std::string toUpper(
const std::string &value) {
178 std::string ret = value;
179 std::transform(ret.begin(), ret.end(), ret.begin(), toupper);
185 std::vector<Arg> args;
186 std::unordered_map<std::string, uint32_t> table;
187 std::unordered_map<char, std::string> short2long;
188 std::unordered_map<std::string, std::string> values;
196 void ArgumentParser::addArgument<std::string>(
const std::string &shortName,
const std::string &longName,
197 std::string value,
bool required) {
198 const char sname = parseShort(shortName);
199 const std::string lname = parseLong(longName);
200 short2long.insert(std::make_pair(sname, lname));
201 table.insert(std::make_pair(lname, args.size()));
202 args.emplace_back(sname, lname, value, required);
204 values.insert(std::make_pair(lname, value));
209 void ArgumentParser::addArgument<const char*>(
const std::string &shortName,
const std::string &longName,
210 const char *value,
bool required) {
211 addArgument<std::string>(shortName, longName, std::string(value), required);
216 #endif // _ARG_PARSER_H_
Definition: argparse.h:17