Skip to content

Commit

Permalink
improve Arguments interface
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzziqersoftware committed Nov 23, 2023
1 parent afb1169 commit 6ec0926
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 36 deletions.
28 changes: 1 addition & 27 deletions src/Arguments.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,4 @@ void Arguments::parse(vector<string>&& args) {
}
}

const string& Arguments::get(const string& name, const string* default_value) {
try {
auto& arg = this->named.at(name);
arg.used = true;
return arg.text;
} catch (const out_of_range&) {
if (default_value) {
return *default_value;
} else {
throw out_of_range(exc_prefix(name) + "argument is missing");
}
}
}

const string& Arguments::get(size_t position, const string* default_value) {
try {
auto& arg = this->positional.at(position);
arg.used = true;
return arg.text;
} catch (const out_of_range&) {
if (default_value) {
return *default_value;
} else {
throw out_of_range(exc_prefix(position) + "argument is missing");
}
}
}
const string Arguments::empty_string;
41 changes: 36 additions & 5 deletions src/Arguments.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,46 @@ struct Arguments {
void assert_none_unused() const;

// Strings
const std::string& get(const string& name, const std::string* default_value = nullptr);
const std::string& get(size_t position, const std::string* default_value = nullptr);
static const std::string empty_string;

template <typename RetT>
requires(std::is_same_v<RetT, std::string>)
const RetT& get(const string& name, bool throw_if_missing = false) {
try {
auto& arg = this->named.at(name);
arg.used = true;
return arg.text;
} catch (const out_of_range&) {
if (throw_if_missing) {
throw out_of_range(Arguments::exc_prefix(name) + "argument is missing");
} else {
return empty_string;
}
}
}

template <typename RetT>
requires(std::is_same_v<RetT, std::string>)
const RetT& get(size_t position, bool throw_if_missing = true) {
try {
auto& arg = this->positional.at(position);
arg.used = true;
return arg.text;
} catch (const out_of_range&) {
if (throw_if_missing) {
throw out_of_range(Arguments::exc_prefix(position) + "argument is missing");
} else {
return empty_string;
}
}
}

// Booleans (named only)
template <typename RetT>
requires(std::is_same_v<RetT, bool>)
RetT get(const char* id) {
try {
this->get(id);
this->get<std::string>(id, true);
return true;
} catch (const std::out_of_range&) {
return false;
Expand All @@ -44,7 +75,7 @@ struct Arguments {
template <typename RetT, typename IdentT>
requires(std::is_integral_v<RetT>)
RetT get(const IdentT& id, IntFormat format = IntFormat::DEFAULT) {
return this->parse_int<RetT>(id, this->get(id), format);
return this->parse_int<RetT>(id, this->get<std::string>(id, true), format);
}

template <typename RetT, typename IdentT>
Expand All @@ -63,7 +94,7 @@ struct Arguments {
RetT get(const IdentT& id, std::optional<RetT> default_value = std::nullopt) {
const std::string* text;
try {
text = &this->get(id);
text = &this->get<std::string>(id);
} catch (const std::out_of_range&) {
if (default_value.has_value()) {
return *default_value;
Expand Down
8 changes: 4 additions & 4 deletions src/ArgumentsTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ int main(int, char**) {
});

// Positional arguments
expect_eq("pos0", string(a.get(0)));
expect_eq("300", string(a.get(1)));
expect_eq("pos0", a.get<string>(0));
expect_eq("300", a.get<string>(1));
expect_eq(300, a.get<int16_t>(1));
expect_eq(300, a.get<uint16_t>(1));
expect_raises<invalid_argument>([&]() {
Expand All @@ -26,7 +26,7 @@ int main(int, char**) {
expect_eq(4.0f, a.get<float>(2));
expect_eq(4.0, a.get<double>(2));
expect_raises<out_of_range>([&]() {
a.get(3);
a.get<string>(3);
});

expect_raises<invalid_argument>([&]() {
Expand All @@ -39,7 +39,7 @@ int main(int, char**) {
});
expect_eq(true, a.get<bool>("named1"));
expect_eq(false, a.get<bool>("missing"));
expect_eq("value2", string(a.get("named2")));
expect_eq("value2", a.get<string>("named2"));
expect_eq(40000, a.get<int32_t>("int3"));
expect_eq(40000, a.get<uint16_t>("int3"));
expect_raises<invalid_argument>([&]() {
Expand Down

0 comments on commit 6ec0926

Please sign in to comment.