18void check_next_arg(
const char **&argv)
21 std::cerr <<
"missing argument" << std::endl;
22 std::exit(EXIT_FAILURE);
29void help_parse(
const char **&argv,
const std::function<
void(T)> &callback)
36 if constexpr (std::same_as<T, int>)
38 if constexpr (std::same_as<T, long>)
40 if constexpr (std::same_as<T, long long>)
41 i = std::stoll(*argv);
43 if constexpr (std::same_as<T, unsigned>) {
44 const unsigned long v = std::stoul(*argv);
45 if (v > std::numeric_limits<unsigned>::max())
46 throw std::out_of_range(
"input exceeds range of type unsigned int");
49 if constexpr (std::same_as<T, unsigned long>)
50 i = std::stoul(*argv);
51 if constexpr (std::same_as<T, unsigned long long>)
52 i = std::stoull(*argv);
56 catch(std::invalid_argument ex) {
57 std::cerr <<
"not a valid integer" << std::endl;
58 std::exit(EXIT_FAILURE);
59 }
catch (std::out_of_range ex) {
60 std::cerr <<
"value out of range" << std::endl;
61 std::exit(EXIT_FAILURE);
70requires std::floating_point<T>
71void help_parse(
const char **&argv,
const std::function<
void(T)> &callback)
77 if constexpr (std::same_as<T, float>)
78 fp = std::stof(*argv);
79 if constexpr (std::same_as<T, double>)
80 fp = std::stod(*argv);
81 if constexpr (std::same_as<T, long double>)
82 fp = std::stold(*argv);
86 catch (std::invalid_argument) {
87 std::cerr <<
"not a valid floating-point number" << std::endl;
88 std::exit(EXIT_FAILURE);
89 }
catch (std::out_of_range) {
90 std::cerr <<
"value out of range" << std::endl;
91 std::exit(EXIT_FAILURE);
101template<> void ArgParser::OptionImpl<TYPE>::parse(const char **&argv) const { help_parse<TYPE>(argv, callback); }
123 check_next_arg(argv);
131 check_next_arg(argv);
133 std::vector<std::string_view>
args;
134 std::string_view sv(*argv);
137 callback(std::move(
args));
141 std::string_view::size_type begin = 0;
143 auto end = sv.find(
',', begin);
144 args.emplace_back(sv.substr(begin, end - begin));
145 if (end == std::string_view::npos)
150 callback(std::move(
args));
160 auto print = [
this, &out](
const char *Short,
const char *Long,
const char *Descr) {
162 << Short << std::setw(
short_len_ - strlen(Short)) <<
""
164 << Long << std::setw(
long_len_ - strlen(Long)) <<
""
172 print(opt->short_name.has_value() ? *opt->short_name :
"",
173 opt->long_name.has_value() ? *opt->long_name :
"",
177 out << grp.first <<
":\n";
178 for (
auto &opt : grp.second)
179 print(opt->short_name.has_value() ? *opt->short_name :
"",
180 opt->long_name.has_value() ? *opt->long_name :
"",
187 for (++argv; *argv; ++argv) {
188 if (
streq(*argv,
"--"))
192 it->second.get().parse(argv);
194 if (
strneq(*argv,
"--", 2))
195 std::cerr <<
"warning: ignore unknown option " << *argv << std::endl;
197 args_.emplace_back(*argv);
204 for (++argv; *argv; ++argv)
205 args_.emplace_back(*argv);
std::unordered_map< PooledString, std::reference_wrapper< const Option > > key_map_
maps the option name to the option object
std::size_t short_len_
the deducted maximum length of all short options
void print_args() const
Prints a list of all options to std::cout.
StringPool pool_
pool of internalized strings
void parse_args(int argc, const char **argv)
Parses the arguments from argv.
std::vector< const char * > args_
positional arguments
options_t general_options_
general options
std::size_t long_len_
the deducted maximum length of all long options
std::unordered_map< PooledString, options_t > grouped_options_
group options
bool streq(const char *first, const char *second)
bool strneq(const char *first, const char *second, std::size_t n)
void parse(const char **&argv) const override