|
1 | 1 | #include "args.h"
|
2 | 2 |
|
3 |
| -std::string arg::help_text() { |
4 |
| - std::string htxt = full_name; |
5 |
| - if (abbreviation != "") { |
6 |
| - htxt += " (" + abbreviation + ")"; |
| 3 | +#include <iostream> |
| 4 | +#include <sstream> |
| 5 | + |
| 6 | +void arg::print_help() const { |
| 7 | + cout << "--" << full_name; |
| 8 | + if (*abbreviation) { |
| 9 | + cout << " (-" << abbreviation << ")"; |
7 | 10 | }
|
8 |
| - htxt += ":\n "; |
9 |
| - if (description != "") { |
10 |
| - htxt += description + "\n"; |
| 11 | + if (*description) { |
| 12 | + cout << (required ? ":\n (REQUIRED) " : ":\n (OPTIONAL) ") << description << ".\n"; |
11 | 13 | } else {
|
12 |
| - htxt += "is a " + (std::string)(required ? "required " : "optional ") + "parameter.\n"; |
| 14 | + cout << (required ? " is a required parameter.\n" : " is an optional parameter.\n"); |
13 | 15 | }
|
14 |
| - return htxt; |
15 | 16 | }
|
16 | 17 |
|
17 |
| -int string_arg::parse(int argc, const char ** argv) { |
| 18 | +void arg::parse(span<str> & argv) { |
18 | 19 | required = false;
|
19 |
| - value.assign(argv[0]); |
20 |
| - return 1; |
21 |
| -} |
22 |
| - |
23 |
| -int int_arg::parse(int argc, const char ** argv) { |
24 |
| - if (required) { |
25 |
| - required = false; |
| 20 | + if (const auto bool_param{get_if<bool>(&value)}) { |
| 21 | + *bool_param = true; |
| 22 | + return; |
| 23 | + } |
| 24 | + if (argv.empty()) { |
| 25 | + fprintf(stderr, "The option '--%s' requires an argument\n", full_name); |
| 26 | + exit(1); |
| 27 | + } |
| 28 | + const str a = argv[0]; |
| 29 | + argv = argv.subspan(1); |
| 30 | + if (const auto string_param{get_if<str>(&value)}) { |
| 31 | + *string_param = a; |
| 32 | + } else if (const auto int_param{get_if<int>(&value)}) { |
| 33 | + istringstream{a} >> *int_param; |
| 34 | + } else if (const auto float_param{get_if<float>(&value)}) { |
| 35 | + istringstream{a} >> *float_param; |
26 | 36 | }
|
27 |
| - int val = atoi(argv[0]); |
28 |
| - *value = val; |
29 |
| - return 1; |
30 | 37 | }
|
31 | 38 |
|
32 |
| -int float_arg::parse(int argc, const char ** argv) { |
33 |
| - if (required) { |
34 |
| - required = false; |
35 |
| - } |
36 |
| - float val = strtof(argv[0], nullptr); |
37 |
| - *value = val; |
38 |
| - return 1; |
39 |
| -} |
40 |
| - |
41 |
| -void arg_list::help() { |
42 |
| - std::string help_text = ""; |
43 |
| - for (auto arg : fargs) { |
44 |
| - help_text += arg.help_text(); |
45 |
| - } |
46 |
| - for (auto arg : iargs) { |
47 |
| - help_text += arg.help_text(); |
48 |
| - |
49 |
| - } |
50 |
| - for (auto arg : bargs) { |
51 |
| - help_text += arg.help_text(); |
52 |
| - |
53 |
| - } |
54 |
| - for (auto arg : sargs) { |
55 |
| - help_text += arg.help_text(); |
56 |
| - |
57 |
| - } |
58 |
| - fprintf(stdout, "%s", help_text.c_str()); |
59 |
| -} |
60 |
| - |
61 |
| -void arg_list::validate() { |
62 |
| - for (auto arg : fargs) { |
63 |
| - if (arg.required) { |
64 |
| - fprintf(stderr, "argument '%s' is required.\n", arg.full_name.c_str()); |
| 39 | +void arg_list::parse(int argc, str argv_[]) { |
| 40 | + TTS_ASSERT(argc); |
| 41 | + span<str> argv{argv_, static_cast<size_t>(argc)}; |
| 42 | + argv = argv.subspan(1); |
| 43 | + while (!argv.empty()) { |
| 44 | + str name{argv[0]}; |
| 45 | + if (*name != '-') { |
| 46 | + fprintf(stderr, "Only named arguments are supported\n"); |
65 | 47 | exit(1);
|
66 | 48 | }
|
67 |
| - } |
68 |
| - for (auto arg : iargs) { |
69 |
| - if (arg.required) { |
70 |
| - fprintf(stderr, "argument '%s' is required.\n", arg.full_name.c_str()); |
71 |
| - exit(1); |
| 49 | + ++name; |
| 50 | + const map<sv, size_t> * lookup = &abbreviations; |
| 51 | + if (*name == '-') { |
| 52 | + ++name; |
| 53 | + lookup = &full_names; |
| 54 | + if (name == "help"sv) { |
| 55 | + for (const size_t i : full_names | views::values) { |
| 56 | + args[i].print_help(); |
| 57 | + } |
| 58 | + exit(0); |
| 59 | + } |
72 | 60 | }
|
73 |
| - } |
74 |
| - for (auto arg : bargs) { |
75 |
| - if (arg.required) { |
76 |
| - fprintf(stderr, "argument '%s' is required.\n", arg.full_name.c_str()); |
| 61 | + const auto found = lookup->find(sv{name}); |
| 62 | + if (found == lookup->end()) { |
| 63 | + fprintf(stderr, "argument '%s' is not a valid argument. " |
| 64 | + "Call '--help' for information on all valid arguments.\n", argv[0]); |
77 | 65 | exit(1);
|
78 | 66 | }
|
| 67 | + argv = argv.subspan(1); |
| 68 | + args[found->second].parse(argv); |
79 | 69 | }
|
80 |
| - for (auto arg : sargs) { |
81 |
| - if (arg.required) { |
82 |
| - fprintf(stderr, "argument '%s' is required.\n", arg.full_name.c_str()); |
| 70 | + for (const arg & x : args) { |
| 71 | + if (x.required) { |
| 72 | + fprintf(stderr, "argument '--%s' is required.\n", x.full_name); |
83 | 73 | exit(1);
|
84 | 74 | }
|
85 | 75 | }
|
86 | 76 | }
|
87 |
| - |
88 |
| -void arg_list::parse(int argc, const char ** argv) { |
89 |
| - int current_arg = 1; |
90 |
| - while (current_arg < argc) { |
91 |
| - std::string name(argv[current_arg]); |
92 |
| - if (name == "--help") { |
93 |
| - for_help = true; |
94 |
| - return; |
95 |
| - } |
96 |
| - current_arg += 1; |
97 |
| - current_arg += find_and_parse(name, argc - current_arg, argv + current_arg); |
98 |
| - } |
99 |
| -} |
100 |
| - |
101 |
| -int arg_list::find_and_parse(std::string name, int argc, const char ** argv) { |
102 |
| - for (int i = 0; i < fargs.size(); i++) { |
103 |
| - if (fargs[i].full_name == name || fargs[i].abbreviation == name) { |
104 |
| - return fargs[i].parse(argc, argv); |
105 |
| - } |
106 |
| - } |
107 |
| - for (int i = 0; i < iargs.size(); i++) { |
108 |
| - if (iargs[i].full_name == name || iargs[i].abbreviation == name) { |
109 |
| - return iargs[i].parse(argc, argv); |
110 |
| - } |
111 |
| - } |
112 |
| - for (int i = 0; i < bargs.size(); i++) { |
113 |
| - if (bargs[i].full_name == name || bargs[i].abbreviation == name) { |
114 |
| - bargs[i].value = !bargs[i].value; |
115 |
| - bargs[i].required = false; |
116 |
| - return 0; |
117 |
| - } |
118 |
| - |
119 |
| - } |
120 |
| - for (int i = 0; i < sargs.size(); i++) { |
121 |
| - if (sargs[i].full_name == name || sargs[i].abbreviation == name) { |
122 |
| - return sargs[i].parse(argc, argv); |
123 |
| - } |
124 |
| - } |
125 |
| - fprintf(stderr, "argument '%s' is not a valid argument. Call '--help' for information on all valid arguments.\n", name.c_str()); |
126 |
| - exit(1); |
127 |
| -} |
128 |
| - |
129 |
| -std::string arg_list::get_string_param(std::string full_name) { |
130 |
| - for (auto arg : sargs) { |
131 |
| - if (arg.full_name == full_name) { |
132 |
| - return arg.value; |
133 |
| - } |
134 |
| - } |
135 |
| - return ""; |
136 |
| -} |
137 |
| - |
138 |
| -int * arg_list::get_int_param(std::string full_name) { |
139 |
| - for (auto arg : iargs) { |
140 |
| - if (arg.full_name == full_name) { |
141 |
| - return arg.value; |
142 |
| - } |
143 |
| - } |
144 |
| - return nullptr; |
145 |
| -} |
146 |
| - |
147 |
| -float * arg_list::get_float_param(std::string full_name) { |
148 |
| - for (auto arg : fargs) { |
149 |
| - if (arg.full_name == full_name) { |
150 |
| - return arg.value; |
151 |
| - } |
152 |
| - } |
153 |
| - return nullptr; |
154 |
| -} |
155 |
| - |
156 |
| -bool arg_list::get_bool_param(std::string full_name) { |
157 |
| - for (auto arg : bargs) { |
158 |
| - if (arg.full_name == full_name) { |
159 |
| - return arg.value; |
160 |
| - } |
161 |
| - } |
162 |
| - return false; |
163 |
| -} |
164 |
| - |
0 commit comments