From b39ddef7723ca51d81bb66f2011a9119697ebfd7 Mon Sep 17 00:00:00 2001 From: gen740 Date: Wed, 13 Dec 2023 16:27:43 +0900 Subject: [PATCH] Support for number of short hand flag: eg. "-1" --- Argo/ArgoMetaLookup.cc | 17 +++++++++++++ Argo/ArgoParserImpl.cc | 6 ++--- README.md | 8 +++--- include/Argo/Argo.hh | 57 +++++++++++++++++++++++++++++------------- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/Argo/ArgoMetaLookup.cc b/Argo/ArgoMetaLookup.cc index 270c908..592bf63 100644 --- a/Argo/ArgoMetaLookup.cc +++ b/Argo/ArgoMetaLookup.cc @@ -61,6 +61,23 @@ consteval auto SearchIndexFromShortName() { return value; } +/*! + * Index Search meta function + */ +template +ARGO_ALWAYS_INLINE constexpr auto SearchIndexFromShortName(char c) { + int value = -1; + if (![&value, &c](type_sequence) ARGO_ALWAYS_INLINE { + return ((value++, + (T::name.shortName >= '0' and T::name.shortName <= '9') and + (c == T::name.shortName)) || + ...); + }(make_type_sequence_t())) { + return -1; + } + return value; +} + }; // namespace Argo // generator end here diff --git a/Argo/ArgoParserImpl.cc b/Argo/ArgoParserImpl.cc index 2ad5a60..291caaa 100644 --- a/Argo/ArgoParserImpl.cc +++ b/Argo/ArgoParserImpl.cc @@ -94,9 +94,9 @@ constexpr auto Parser::parse(int argc, [[maybe_unused]] string_view key{}; vector short_keys{}; - short_keys.reserve(10); + short_keys.reserve(8); vector values{}; - values.reserve(10); + values.reserve(8); assert(this->info_); // this->info_ cannot be nullptr if (!this->info_->program_name) { @@ -125,7 +125,7 @@ constexpr auto Parser::parse(int argc, arg = argv[i]; is_flag = arg.starts_with('-'); if (arg.size() > 1 and arg.at(1) >= '0' and arg.at(1) <= '9') { - is_flag = false; + is_flag = SearchIndexFromShortName(arg.at(1)) != -1; } } else { is_flag = true; diff --git a/README.md b/README.md index 94db77f..f4ef3c4 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ import std; // suppose ./main --arg1 42 --arg3 "Hello,World" auto main(int argc, char* argv[]) -> int { - auto parser = Argo::Parser() // - .addArg<"arg1", int>() - .addArg<"arg2", float>(Argo::explicitDefault(12.34)) - .addArg<"arg3", std::string>(); + auto parser = Argo::Parser() // + .addArg<"arg1", int>() + .addArg<"arg2", float>(Argo::explicitDefault(12.34)) + .addArg<"arg3", std::string>(); parser.parse(argc, argv); diff --git a/include/Argo/Argo.hh b/include/Argo/Argo.hh index f655f29..b6d7e94 100644 --- a/include/Argo/Argo.hh +++ b/include/Argo/Argo.hh @@ -917,6 +917,23 @@ consteval auto SearchIndexFromShortName() { return value; } +/*! + * Index Search meta function + */ +template +ARGO_ALWAYS_INLINE constexpr auto SearchIndexFromShortName(char c) { + int value = -1; + if (![&value, &c](type_sequence) ARGO_ALWAYS_INLINE { + return ((value++, + (T::name.shortName >= '0' and T::name.shortName <= '9') and + (c == T::name.shortName)) || + ...); + }(make_type_sequence_t())) { + return -1; + } + return value; +} + }; // namespace Argo @@ -1130,7 +1147,7 @@ ARGO_ALWAYS_INLINE constexpr auto Assigner(string_view key, if (key.empty()) { if constexpr (!is_same_v>) { if (!PArgAssigner(values)) { - throw InvalidArgument(format("Duplicated positional argument")); + throw InvalidArgument("Duplicated positional argument"); } return; } else { @@ -1546,7 +1563,7 @@ namespace Argo { using namespace std; -inline auto splitStringView(string_view str, char delimeter) +ARGO_ALWAYS_INLINE auto splitStringView(string_view str, char delimeter) -> vector { vector ret; while (str.contains(delimeter)) { @@ -1567,7 +1584,8 @@ constexpr auto Parser::resetArgs() -> void { template requires(is_tuple_v && is_tuple_v) constexpr auto Parser::setArg( - string_view key, span val) const -> void { + [[maybe_unused]] string_view key, + [[maybe_unused]] span val) const -> void { if constexpr (!is_same_v) { if (key == HArg::name) { std::cout << formatHelp() << '\n'; @@ -1580,7 +1598,8 @@ constexpr auto Parser::setArg( template requires(is_tuple_v && is_tuple_v) constexpr auto Parser::setArg( - span key, span val) const -> void { + [[maybe_unused]] span key, + [[maybe_unused]] span val) const -> void { if constexpr (!is_same_v) { for (const auto& i : key) { if constexpr (HArg::name.shortName != '\0') { @@ -1596,8 +1615,9 @@ constexpr auto Parser::setArg( template requires(is_tuple_v && is_tuple_v) -inline constexpr auto Parser::parse( - int argc, char* argv[]) -> void { +constexpr auto Parser::parse(int argc, + char* argv[]) + -> void { if (this->parsed_) [[unlikely]] { throw ParseError("Cannot parse twice"); } @@ -1612,11 +1632,11 @@ inline constexpr auto Parser::parse( throw ParseError(format("keys {} already assigned", assigned_keys)); } - string_view key{}; + [[maybe_unused]] string_view key{}; vector short_keys{}; - short_keys.reserve(10); + short_keys.reserve(8); vector values{}; - values.reserve(10); + values.reserve(8); assert(this->info_); // this->info_ cannot be nullptr if (!this->info_->program_name) { @@ -1637,17 +1657,20 @@ inline constexpr auto Parser::parse( } } } - bool flag = false; - string_view arg; + [[maybe_unused]] bool is_flag = false; + [[maybe_unused]] string_view arg; for (int i = 1; i < cmd_end_pos + 1; i++) { if (i != cmd_end_pos) { arg = argv[i]; - flag = arg.starts_with('-'); + is_flag = arg.starts_with('-'); + if (arg.size() > 1 and arg.at(1) >= '0' and arg.at(1) <= '9') { + is_flag = SearchIndexFromShortName(arg.at(1)) != -1; + } } else { - flag = true; + is_flag = true; } - if (i != 1 and flag) { + if (i != 1 and is_flag) { if (!key.empty()) { this->setArg(key, values); key = ""; @@ -1665,16 +1688,16 @@ inline constexpr auto Parser::parse( } } } - if (i == cmd_end_pos) { + if (i == cmd_end_pos) [[unlikely]] { break; } - if (flag) { + if (is_flag) { if (arg.size() > 1 and arg.at(1) == '-') { if (arg.contains('=')) [[unlikely]] { auto equal_pos = arg.find('='); key = arg.substr(2, equal_pos - 2); values.push_back(arg.substr(equal_pos + 1)); - flag = true; + is_flag = true; } else { key = arg.substr(2); }