48 bool repeated_ =
false;
52 Argument(
char key,
const std::string& longkey,
const std::string& keytype,
53 const std::string& desc,
bool required)
54 : key_(key), longkey_(longkey), keytype_(keytype), desc_(desc),
55 required_(required) { }
58 virtual ~Argument() =
default;
61 virtual const char * type_name()
const = 0;
64 virtual bool process(
int& argc,
const char*
const*& argv) = 0;
67 virtual void print_value(std::ostream& os)
const = 0;
70 std::string param_text()
const {
71 std::string s = longkey_;
72 if (!keytype_.empty()) {
79 std::string option_text()
const {
82 s +=
'-', s += key_, s +=
", ";
87 s +=
"--", s += longkey_;
88 if (!keytype_.empty()) {
105 ArgumentBool(
char key,
const std::string& longkey,
106 const std::string& keytype,
const std::string& desc,
107 bool required,
bool& dest)
108 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
110 const char * type_name() const final {
return "bool"; }
113 bool process(
int& argc,
const char*
const*& argv)
final {
119 void print_value(std::ostream& os)
const final {
120 os << (dest_ ?
"true" :
"false");
133 ArgumentInt(
char key,
const std::string& longkey,
134 const std::string& keytype,
const std::string& desc,
135 bool required,
int& dest)
136 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
138 const char * type_name() const final {
return "integer"; }
141 bool process(
int& argc,
const char*
const*& argv)
final {
145 long x = strtol(argv[0], &endptr, 10);
146 if (endptr !=
nullptr && *endptr == 0 &&
147 x <= std::numeric_limits<int>::max()) {
149 dest_ =
static_cast<int>(x);
157 void print_value(std::ostream& os)
const final { os << dest_; }
169 ArgumentUnsigned(
char key,
const std::string& longkey,
170 const std::string& keytype,
const std::string& desc,
171 bool required,
unsigned int& dest)
172 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
174 const char * type_name() const final {
return "unsigned"; }
177 bool process(
int& argc,
const char*
const*& argv)
final {
181 unsigned long x = strtoul(argv[0], &endptr, 10);
182 if (endptr !=
nullptr && *endptr == 0 &&
183 x <= std::numeric_limits<unsigned int>::max()) {
185 dest_ =
static_cast<unsigned int>(x);
193 void print_value(std::ostream& os)
const final { os << dest_; }
205 ArgumentSizeT(
char key,
const std::string& longkey,
206 const std::string& keytype,
const std::string& desc,
207 bool required,
size_t& dest)
208 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
210 const char * type_name() const final {
return "size_t"; }
213 bool process(
int& argc,
const char*
const*& argv)
final {
217 unsigned long long x = strtoull(argv[0], &endptr, 10);
218 if (endptr !=
nullptr && *endptr == 0 &&
219 x <= std::numeric_limits<size_t>::max()) {
229 void print_value(std::ostream& os)
const final { os << dest_; }
241 ArgumentFloat(
char key,
const std::string& longkey,
242 const std::string& keytype,
const std::string& desc,
243 bool required,
float& dest)
244 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
246 const char * type_name() const final {
return "float"; }
249 bool process(
int& argc,
const char*
const*& argv)
final {
253 dest_ = strtof(argv[0], &endptr);
254 if (endptr !=
nullptr && *endptr == 0) {
263 void print_value(std::ostream& os)
const final { os << dest_; }
274 ArgumentDouble(
char key,
const std::string& longkey,
275 const std::string& keytype,
const std::string& desc,
276 bool required,
double& dest)
277 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
279 const char * type_name() const final {
return "double"; }
282 bool process(
int& argc,
const char*
const*& argv)
final {
286 dest_ = strtod(argv[0], &endptr);
287 if (endptr !=
nullptr && *endptr == 0) {
296 void print_value(std::ostream& os)
const final { os << dest_; }
309 ArgumentBytes32(
char key,
const std::string& longkey,
310 const std::string& keytype,
const std::string& desc,
311 bool required, uint32_t& dest)
312 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
314 const char * type_name() const final {
return "bytes"; }
317 bool process(
int& argc,
const char*
const*& argv)
final {
322 static_cast<uint64_t
>(
323 dest_ =
static_cast<uint32_t
>(dest)) == dest) {
332 void print_value(std::ostream& os)
const final { os << dest_; }
344 ArgumentBytes64(
char key,
const std::string& longkey,
345 const std::string& keytype,
const std::string& desc,
346 bool required, uint64_t& dest)
347 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
349 const char * type_name() const final {
return "bytes"; }
352 bool process(
int& argc,
const char*
const*& argv)
final {
364 void print_value(std::ostream& os)
const final { os << dest_; }
376 ArgumentString(
char key,
const std::string& longkey,
377 const std::string& keytype,
const std::string& desc,
378 bool required, std::string& dest)
379 : Argument(key, longkey, keytype, desc, required), dest_(dest) { }
381 const char * type_name() const final {
return "string"; }
384 bool process(
int& argc,
const char*
const*& argv)
final {
392 void print_value(std::ostream& os)
const final {
393 os <<
'"' << dest_ <<
'"';
402 std::vector<std::string>& dest_;
406 ArgumentStringlist(
char key,
const std::string& longkey,
407 const std::string& keytype,
const std::string& desc,
408 bool required, std::vector<std::string>& dest)
409 : Argument(key, longkey, keytype, desc, required), dest_(dest) {
413 const char * type_name() const final {
return "string list"; }
416 bool process(
int& argc,
const char*
const*& argv)
final {
419 dest_.emplace_back(argv[0]);
424 void print_value(std::ostream& os)
const final {
426 for (
size_t i = 0; i < dest_.size(); ++i) {
429 os <<
'"' << dest_[i] <<
'"';
450 std::ostream& os,
const std::string& text,
451 size_t wraplen,
size_t indent_first,
size_t indent_rest,
size_t current,
452 size_t indent_newline) {
454 std::string::size_type t = 0;
455 size_t indent = indent_first;
457 while (t != text.size()) {
458 std::string::size_type to = t, lspace = t;
461 while (to != text.size() && to + current + indent < t + wraplen &&
469 if (to != text.size() && text[to] !=
'\n' && lspace != t)
473 os << std::string(indent,
' ') << text.substr(t, to - t) << std::endl;
476 indent = indent_rest;
479 if (to != text.size() && text[to] ==
'\n') {
480 indent = indent_newline;
517 const std::string& keytype,
bool& dest,
518 const std::string& desc) {
520 new ArgumentBool(key, longkey, keytype, desc,
false, dest));
525 const std::string& keytype,
bool& dest,
526 const std::string& desc) {
527 return add_bool(key, longkey, keytype, dest, desc);
531 const std::string& keytype,
int& dest,
532 const std::string& desc) {
534 new ArgumentInt(key, longkey, keytype, desc,
false, dest));
539 const std::string& keytype,
unsigned int& dest,
540 const std::string& desc) {
547 const std::string& keytype,
unsigned int& dest,
548 const std::string& desc) {
553 const std::string& keytype,
size_t& dest,
554 const std::string& desc) {
556 new ArgumentSizeT(key, longkey, keytype, desc,
false, dest));
561 const std::string& keytype,
float& dest,
562 const std::string& desc) {
564 new ArgumentFloat(key, longkey, keytype, desc,
false, dest));
569 const std::string& keytype,
double& dest,
570 const std::string& desc) {
577 const std::string& keytype, uint32_t& dest,
578 const std::string& desc) {
585 const std::string& keytype, uint64_t& dest,
586 const std::string& desc) {
593 const std::string& keytype, std::string& dest,
594 const std::string& desc) {
601 char key,
const std::string& longkey,
602 const std::string& keytype, std::vector<std::string>& dest,
603 const std::string& desc) {
613 char key,
const std::string& longkey,
bool& dest,
const std::string& desc) {
614 return add_bool(key, longkey,
"", dest, desc);
618 char key,
const std::string& longkey,
bool& dest,
const std::string& desc) {
619 return add_bool(key, longkey, dest, desc);
623 char key,
const std::string& longkey,
int& dest,
const std::string& desc) {
624 return add_int(key, longkey,
"", dest, desc);
628 unsigned int& dest,
const std::string& desc) {
633 unsigned int& dest,
const std::string& desc) {
638 size_t& dest,
const std::string& desc) {
639 return add_size_t(key, longkey,
"", dest, desc);
643 float& dest,
const std::string& desc) {
644 return add_float(key, longkey,
"", dest, desc);
648 double& dest,
const std::string& desc) {
649 return add_double(key, longkey,
"", dest, desc);
653 uint32_t& dest,
const std::string& desc) {
654 return add_bytes(key, longkey,
"", dest, desc);
658 uint64_t& dest,
const std::string& desc) {
659 return add_bytes(key, longkey,
"", dest, desc);
663 std::string& dest,
const std::string& desc) {
664 return add_string(key, longkey,
"", dest, desc);
668 char key,
const std::string& longkey,
669 std::vector<std::string>& dest,
const std::string& desc) {
676 const std::string& longkey,
bool& dest,
const std::string& desc) {
677 return add_bool(0, longkey,
"", dest, desc);
681 const std::string& longkey,
bool& dest,
const std::string& desc) {
682 return add_bool(0, longkey, dest, desc);
686 const std::string& longkey,
int& dest,
const std::string& desc) {
687 return add_int(0, longkey,
"", dest, desc);
691 unsigned int& dest,
const std::string& desc) {
696 unsigned int& dest,
const std::string& desc) {
701 size_t& dest,
const std::string& desc) {
702 return add_size_t(0, longkey,
"", dest, desc);
706 float& dest,
const std::string& desc) {
707 return add_float(0, longkey,
"", dest, desc);
711 double& dest,
const std::string& desc) {
712 return add_double(0, longkey,
"", dest, desc);
716 uint32_t& dest,
const std::string& desc) {
717 return add_bytes(0, longkey,
"", dest, desc);
721 uint64_t& dest,
const std::string& desc) {
722 return add_bytes(0, longkey,
"", dest, desc);
726 std::string& dest,
const std::string& desc) {
727 return add_string(0, longkey,
"", dest, desc);
731 const std::string& longkey,
732 std::vector<std::string>& dest,
const std::string& desc) {
739 const std::string& name,
int& dest,
const std::string& desc) {
745 const std::string& name,
unsigned int& dest,
const std::string& desc) {
752 const std::string& name,
unsigned int& dest,
const std::string& desc) {
757 const std::string& name,
size_t& dest,
const std::string& desc) {
763 const std::string& name,
float& dest,
const std::string& desc) {
769 const std::string& name,
double& dest,
const std::string& desc) {
775 const std::string& name, uint32_t& dest,
const std::string& desc) {
782 const std::string& name, uint64_t& dest,
const std::string& desc) {
789 const std::string& name, std::string& dest,
const std::string& desc) {
795 const std::string& name, std::vector<std::string>& dest,
796 const std::string& desc) {
805 const std::string& name,
int& dest,
const std::string& desc) {
811 const std::string& name,
unsigned int& dest,
const std::string& desc) {
818 const std::string& name,
unsigned int& dest,
const std::string& desc) {
823 const std::string& name,
size_t& dest,
const std::string& desc) {
829 const std::string& name,
float& dest,
const std::string& desc) {
835 const std::string& name,
double& dest,
const std::string& desc) {
842 const std::string& name, uint32_t& dest,
const std::string& desc) {
849 const std::string& name, uint64_t& dest,
const std::string& desc) {
856 const std::string& name, std::string& dest,
const std::string& desc) {
863 const std::string& name, std::vector<std::string>& dest,
864 const std::string& desc) {
875 return a->longkey_ < b->longkey_;
881 std::ios::fmtflags flags(os.flags());
886 for (ArgumentList::const_iterator it =
param_list_.begin();
890 os << (arg->required_ ?
" <" :
" [") << arg->longkey_
891 << (arg->repeated_ ?
" ..." :
"") << (arg->required_ ?
'>' :
']');
901 os <<
"Author: " <<
author_ << std::endl;
908 os <<
"Parameters:" << std::endl;
910 for (ArgumentList::const_iterator it =
param_list_.begin();
915 << std::left << arg->param_text();
922 os <<
"Options:" << std::endl;
924 for (ArgumentList::const_iterator it =
option_list_.begin();
929 << std::left << arg->option_text();
943 int argc,
const char*
const* argv,
const Argument* arg, std::ostream& os) {
944 os <<
"Error: argument ";
946 os <<
'"' << argv[0] <<
'"';
948 os <<
" for " << arg->type_name() <<
" option " << arg->option_text()
949 << (argc == 0 ?
" is missing!" :
" is invalid!") << std::endl
956 int argc,
const char*
const* argv,
const Argument* arg, std::ostream& os) {
957 os <<
"Error: argument ";
959 os <<
'"' << argv[0] <<
'"';
961 os <<
" for " << arg->type_name() <<
" parameter " << arg->param_text()
962 << (argc == 0 ?
" is missing!" :
" is invalid!") << std::endl
969 int argc,
const char*
const* argv, std::ostream& os) {
974 for (
int i = 0; i < argc; ++i) {
975 if (strcmp(argv[i],
"-h") == 0 || strcmp(argv[i],
"--help") == 0) {
983 bool end_optlist =
false;
986 const char* arg = argv[0];
988 if (arg[0] ==
'-' && !end_optlist) {
999 if ((arg + 2) == (*oi)->longkey_) {
1000 if (!(*oi)->process(argc, argv)) {
1005 os <<
"Option " << (*oi)->option_text()
1007 (*oi)->print_value(os);
1008 os <<
'.' << std::endl;
1014 os <<
"Error: unknown option \"" << arg <<
"\"."
1015 << std::endl << std::endl;
1024 os <<
"Invalid option \"" << arg <<
"\"." << std::endl;
1027 size_t offset = 1, arg_length = strlen(arg);
1028 int old_argc = argc;
1031 while (offset < arg_length && argc == old_argc) {
1032 ArgumentList::const_iterator oi =
option_list_.begin();
1034 if (arg[offset] == (*oi)->key_) {
1036 if (!(*oi)->process(argc, argv)) {
1042 << (*oi)->option_text()
1044 (*oi)->print_value(os);
1045 os <<
'.' << std::endl;
1051 os <<
"Error: unknown option \"";
1052 if (arg_length > 2) {
1054 os <<
"-" << arg[offset]
1055 <<
"\" at position " << offset
1056 <<
" in option sequence \"";
1058 os << arg <<
"\"." << std::endl << std::endl;
1068 if (!(*argi)->process(argc, argv)) {
1073 os <<
"Parameter " << (*argi)->param_text() <<
" set to ";
1074 (*argi)->print_value(os);
1075 os <<
'.' << std::endl;
1077 (*argi)->found_ =
true;
1078 if (!(*argi)->repeated_)
1082 os <<
"Error: unexpected extra argument "
1083 <<
"\"" << argv[0] <<
"\"." << std::endl << std::endl;
1093 for (ArgumentList::const_iterator it =
param_list_.begin();
1095 if ((*it)->required_ && !(*it)->found_) {
1096 os <<
"Error: argument for parameter " << (*it)->longkey_
1097 <<
" is required!" << std::endl;
1111 return process(argc, argv, std::cout);
1115 std::ios::fmtflags flags(os.flags());
1120 os <<
"Parameters:" << std::endl;
1126 os <<
" " << std::setw(
static_cast<int>(maxlong))
1127 << std::left << arg->param_text();
1129 std::string typestr =
"(" + std::string(arg->type_name()) +
")";
1132 arg->print_value(os);
1139 os <<
"Options:" << std::endl;
1141 for (ArgumentList::const_iterator it =
option_list_.begin();
1145 os <<
" " << std::setw(
static_cast<int>(maxlong))
1146 << std::left << arg->option_text();
1148 std::string typestr =
"(" + std::string(arg->type_name()) +
")";
1151 arg->print_value(os);