19 #ifndef IRCCD_OPTIONS_HPP
20 #define IRCCD_OPTIONS_HPP
27 #include <initializer_list>
30 #include <string_view>
32 #include <unordered_map>
43 using pack = std::tuple<
44 std::vector<std::string>,
45 std::unordered_multimap<char, std::string>
82 template <
typename InputIt>
83 inline auto parse(InputIt&& it, InputIt&& end, std::string_view fmt) ->
pack
87 for (; it != end; ++it) {
88 const std::string_view token(*it);
95 for (++it; it != end; ++it)
96 std::get<0>(result).push_back(std::string(*it));
101 if (token.compare(0U, 1U,
"-") != 0) {
103 if (fmt.find(
'!') != std::string_view::npos)
106 std::get<0>(result).push_back(std::string(token));
110 const auto sub = token.substr(1);
112 for (std::size_t i = 0U; i < sub.size(); ++i) {
113 const auto idx = fmt.find(sub[i]);
115 if (idx == std::string_view::npos)
116 throw std::runtime_error(
"invalid option");
119 if (fmt.compare(idx + 1U, 1U,
":") != 0) {
120 std::get<1>(result).emplace(sub[i],
"");
128 if (i + 1U < sub.size()) {
129 std::get<1>(result).emplace(sub[i], std::string(sub.substr(i + 1)));
134 if (++it == end || std::string_view(*it).compare(0U, 1U,
"-") == 0)
135 throw std::runtime_error(
"option require a value");
137 std::get<1>(result).emplace(sub[i], std::string(*it));
152 template <
typename String>
153 inline auto parse(std::initializer_list<String> args, std::string_view fmt) ->
pack
155 auto begin = args.begin();
156 auto end = args.end();
158 return parse(begin, end, fmt);
169 inline auto parse(
int argc,
char** argv, std::string_view fmt) ->
pack
171 std::vector<std::string_view> args(argc);
173 for (
int i = 0; i < argc; ++i)
176 auto begin = args.begin();
177 auto end = args.end();
179 return parse(begin, end, fmt);
185 #endif // !IRCCD_OPTIONS_HPP