1919
2020#include < algorithm>
2121#include < cctype>
22+ #include < cstring>
2223#include < iomanip>
2324#include < iostream>
2425#include < locale>
2526#include < numeric>
26- #include < regex>
2727#include < sstream>
2828#include < stdexcept>
2929#include < string>
@@ -61,8 +61,8 @@ class ArgumentParser {
6161
6262 bool is_help () { return _help; }
6363
64- void print_help (char *f ) {
65- std::cout << " Usage: " << f << " [options]" << std::endl;
64+ void print_help () {
65+ std::cout << " Usage: " << _bin << " [options]" << std::endl;
6666 std::cout << " Options:" << std::endl;
6767 for (auto &a : _arguments) {
6868 std::string name = a._name ;
@@ -74,28 +74,44 @@ class ArgumentParser {
7474 }
7575
7676 void parse (int argc, char *argv[]) {
77+ _bin = argv[0 ];
7778 if (argc > 1 ) {
78- std::vector<std::string> argsvec (argv + 1 , argv + argc);
79- std::string argstr =
80- std::accumulate (argsvec.begin (), argsvec.end (), std::string (),
81- [](std::string a, std::string b) {
82- return a + " " + std::string (b);
83- });
84- std::vector<std::string> split_args = _split (argstr, " ^-|\\ s-" );
85- std::vector<std::string> arg_parts;
8679 std::string name;
87- for (auto &split_arg : split_args) {
88- std::vector<std::string> arg_parts = _split (split_arg, " \\ s+" );
89- name = _trim_copy (arg_parts[0 ]);
90- if (name.empty ()) continue ;
91- if (name[0 ] == ' -' ) {
92- _add_variable (name, arg_parts, argv);
80+ std::vector<std::string> arg_parts;
81+ std::vector<std::string> free_args;
82+ auto push_arg = [&name, &arg_parts, this ]() {
83+ if (!name.empty ()) {
84+ if (name[0 ] == ' -' ) {
85+ _add_variable (name, arg_parts);
86+ } else {
87+ for (char c : name) {
88+ _add_variable (std::string (1 , c), arg_parts);
89+ }
90+ }
91+ arg_parts.clear ();
92+ }
93+ };
94+ for (int i = 1 ; i < argc; i++) {
95+ if (std::strlen (argv[i]) == 0 ) {
96+ continue ;
97+ } else if (argv[i][0 ] == ' -' ) {
98+ push_arg ();
99+ if (i == argc - 1 ) {
100+ name = &(argv[i][1 ]);
101+ push_arg ();
102+ } else {
103+ name = &(argv[i][1 ]);
104+ }
105+ } else if (name.empty ()) {
106+ free_args.push_back (argv[i]);
93107 } else {
94- for (auto c : name) {
95- _add_variable (std::string (1 , c), arg_parts, argv);
108+ arg_parts.push_back (argv[i]);
109+ if (i == argc - 1 ) {
110+ push_arg ();
96111 }
97112 }
98113 }
114+ _add_variable (" " , free_args);
99115 }
100116 if (!_help) {
101117 for (auto &a : _arguments) {
@@ -116,11 +132,14 @@ class ArgumentParser {
116132
117133 template <typename T>
118134 std::vector<T> getv (const std::string &name) {
119- std::string argstr = get <std::string>(name);
135+ std::vector<std:: string> argstr = getv <std::string>(name);
120136 std::vector<T> v;
121- std::istringstream in (argstr);
122- std::copy (std::istream_iterator<T>(in), std::istream_iterator<T>(),
123- std::back_inserter (v));
137+ for (auto &s : argstr) {
138+ std::istringstream in (s);
139+ T t;
140+ in >> t;
141+ v.push_back (t);
142+ }
124143 return v;
125144 }
126145
@@ -145,24 +164,15 @@ class ArgumentParser {
145164 bool _required;
146165 };
147166 inline void _add_variable (std::string name,
148- std::vector<std::string> &arg_parts, char *argv[] ) {
167+ std::vector<std::string> &arg_parts) {
149168 if (name == " h" || name == " -help" ) {
150169 _help = true ;
151- print_help (argv[ 0 ] );
170+ print_help ();
152171 }
153172 _ltrim (name, [](int c) { return c != (int )' -' ; });
154173 name = _delimit (name);
155174 if (_pairs.find (name) != _pairs.end ()) name = _pairs[name];
156- std::string val;
157- if (arg_parts.size () > 1 ) {
158- val = std::accumulate (arg_parts.begin () + 1 , arg_parts.end (),
159- std::string (), [](std::string a, std::string b) {
160- return _trim_copy (a) + " " + _trim_copy (b);
161- });
162- } else {
163- val = " " ;
164- }
165- _variables[name] = val;
175+ _variables[name] = arg_parts;
166176 }
167177 static std::string _delimit (const std::string &name) {
168178 return std::string (std::min (name.size (), (size_t )2 ), ' -' ).append (name);
@@ -184,13 +194,6 @@ class ArgumentParser {
184194 out = std::string (" \" " ).append (out).append (" \" " );
185195 return out;
186196 }
187- static std::vector<std::string> _split (const std::string &input,
188- const std::string ®ex) {
189- // passing -1 as the submatch index parameter performs splitting
190- std::regex re (regex);
191- std::sregex_token_iterator first{input.begin (), input.end (), re, -1 }, last;
192- return {first, last};
193- }
194197 static bool _not_space (int ch) { return !std::isspace (ch); }
195198 static inline void _ltrim (std::string &s, bool (*f)(int ) = _not_space) {
196199 s.erase (s.begin (), std::find_if (s.begin (), s.end (), f));
@@ -219,17 +222,22 @@ class ArgumentParser {
219222 }
220223
221224 std::string _desc;
225+ std::string _bin;
222226 bool _help;
223227 std::vector<Argument> _arguments;
224- std::unordered_map<std::string, std::string> _variables;
228+ std::unordered_map<std::string, std::vector<std:: string> > _variables;
225229 std::unordered_map<std::string, std::string> _pairs;
226230};
227231template <>
228232inline std::string ArgumentParser::get<std::string>(const std::string &name) {
229233 std::string t = _delimit (name);
230234 if (_pairs.find (t) != _pairs.end ()) t = _pairs[t];
231235 auto v = _variables.find (t);
232- if (v != _variables.end ()) return v->second ;
236+ if (v != _variables.end ()) {
237+ return std::accumulate (
238+ v->second .begin (), v->second .end (), std::string (),
239+ [](std::string a, std::string b) { return a + " " + b; });
240+ }
233241 return " " ;
234242}
235243template <>
@@ -239,7 +247,12 @@ inline bool ArgumentParser::get<bool>(const std::string &name) {
239247template <>
240248inline std::vector<std::string> ArgumentParser::getv<std::string>(
241249 const std::string &name) {
242- std::string argstr = get<std::string>(name);
243- return _split (argstr, " \\ s" );
250+ std::string t = _delimit (name);
251+ if (_pairs.find (t) != _pairs.end ()) t = _pairs[t];
252+ auto v = _variables.find (t);
253+ if (v != _variables.end ()) {
254+ return v->second ;
255+ }
256+ return std::vector<std::string>();
244257}
245258#endif
0 commit comments