58 template <
typename TYPE>
80 command(
const std::string &shortname,
const std::string &longname,
const std::string &description, TYPE ¶meter) :
83 description(description),
133 template <
typename TYPE,
134 typename std::enable_if <std::is_same<TYPE, short>::value ||
135 std::is_same<TYPE, int>::value ||
136 std::is_same<TYPE, long>::value ||
137 std::is_same<TYPE, long long>::value>::type* =
nullptr>
140 if (parameter ==
nullptr)
142 messages <<
" Missing numeric parameter\n";
146 long long answer = strtoll(parameter, NULL, 0);
148 if (answer > (std::numeric_limits<TYPE>::max)())
149 messages << parameter <<
" Numeric overflow on parameter\n";
150 else if (answer < (std::numeric_limits<TYPE>::min)())
151 messages << parameter <<
" Numeric underflow on parameter\n";
153 element.
parameter =
static_cast<TYPE
>(answer);
167 template <
typename TYPE,
168 typename std::enable_if <std::is_same<TYPE, unsigned short>::value ||
169 std::is_same<TYPE, unsigned int>::value ||
170 std::is_same<TYPE, unsigned long>::value ||
171 std::is_same<TYPE, unsigned long long>::value>::type* =
nullptr>
174 if (parameter ==
nullptr)
176 messages <<
" Missing numeric parameter\n";
180 unsigned long long answer = strtoull(parameter, NULL, 0);
185 if constexpr (!std::is_same<TYPE, unsigned long long>::value)
186 if (answer > (std::numeric_limits<TYPE>::max)())
187 messages << parameter <<
" Numeric overflow on parameter\n";
189 element.
parameter =
static_cast<TYPE
>(answer);
203 template <
typename TYPE,
204 typename std::enable_if <std::is_same<TYPE, float>::value ||
205 std::is_same<TYPE, double>::value>::type* =
nullptr>
208 double answer = std::stod(parameter);
210 if (answer > (std::numeric_limits<TYPE>::max)())
211 messages << parameter <<
" Numeric overflow on parameter\n";
212 else if (answer < (std::numeric_limits<TYPE>::min)())
213 messages << parameter <<
" Numeric underflow on parameter\n";
215 element.
parameter =
static_cast<TYPE
>(answer);
243 template <
typename TYPE>
244 static void extract(std::ostringstream &messages,
const char *parameter, TYPE element)
246 messages << element.shortname <<
" (" << element.longname <<
") Unknown parameter type\n";
260 template<std::size_t I = 0,
typename... Tp>
261 inline typename std::enable_if<I ==
sizeof...(Tp),
void>::type
262 static for_each_parameter(std::ostringstream &messages,
size_t &arg,
const char *argv[], std::tuple<Tp...> &)
264 messages << argv[arg] <<
" Unknown parameter\n";
279 template<std::size_t I = 0,
typename... Tp>
280 inline typename std::enable_if<I <
sizeof...(Tp),
void>::type
281 static for_each_parameter(std::ostringstream &messages,
size_t &arg,
const char *argv[], std::tuple<Tp...> &tuple)
283 if (std::get<I>(tuple).shortname.size() == 0 || std::get<I>(tuple).longname.size() == 0)
284 for_each_parameter<I + 1, Tp...>(messages, arg, argv, tuple);
285 else if (strcmp(argv[arg], std::get<I>(tuple).shortname.c_str()) == 0)
287 extract(messages, argv[++arg], std::get<I>(tuple));
288 if (
typeid(std::get<I>(tuple).parameter) !=
typeid(
bool))
291 else if (strcmp(argv[arg], std::get<I>(tuple).longname.c_str()) == 0)
293 extract(messages, argv[++arg], std::get<I>(tuple));
294 if (
typeid(std::get<I>(tuple).parameter) !=
typeid(
bool))
297 else if (strncmp(argv[arg], std::get<I>(tuple).longname.c_str(), std::get<I>(tuple).longname.size()) == 0)
299 extract(messages, argv[arg] + std::get<I>(tuple).longname.size(), std::get<I>(tuple));
302 else if (strncmp(argv[arg], std::get<I>(tuple).shortname.c_str(), std::get<I>(tuple).shortname.size()) == 0)
304 extract(messages, argv[arg] + std::get<I>(tuple).shortname.size(), std::get<I>(tuple));
324 template<std::size_t I = 0,
typename... Tp>
325 inline typename std::enable_if<I ==
sizeof...(Tp),
void>::type
326 static for_each_usage_formatting(
size_t &width_of_shortname,
size_t &
width_of_longname,
const std::tuple<Tp...> &)
344 template<std::size_t I = 0,
typename... Tp>
345 inline typename std::enable_if<I <
sizeof...(Tp),
void>::type
346 static for_each_usage_formatting(
size_t &width_of_shortname,
size_t &width_of_longname,
const std::tuple<Tp...> &tuple)
348 if (std::get<I>(tuple).shortname.size() > width_of_shortname)
349 width_of_shortname = std::get<I>(tuple).shortname.size();
352 width_of_longname = std::get<I>(tuple).longname.size();
354 for_each_usage_formatting<I + 1, Tp...>(width_of_shortname,
width_of_longname, tuple);
368 template<std::size_t I = 0,
typename... Tp>
369 inline typename std::enable_if<I ==
sizeof...(Tp),
void>::type
370 static for_each_usage_print(std::ostream &out,
size_t width_of_shortname,
size_t width_of_longname,
const std::tuple<Tp...> &)
387 template<std::size_t I = 0,
typename... Tp>
388 inline typename std::enable_if<I <
sizeof...(Tp),
void>::type
389 static for_each_usage_print(std::ostream &out,
size_t width_of_shortname,
size_t width_of_longname,
const std::tuple<Tp...> &tuple)
394 std::ios state(NULL);
396 std::ios_base::fmtflags fmt(std::cout.flags());
400 if (std::get<I>(tuple).shortname.size() == 0)
401 out << std::left << std::get<I>(tuple).description <<
'\n';
404 out.width(width_of_shortname + 1);
405 out << std::left << std::get<I>(tuple).shortname;
406 out.width(width_of_longname + 1);
407 out << std::get<I>(tuple).longname;
408 out << std::get<I>(tuple).description <<
'\n';
414 std::cout.flags(fmt);
440 template <
typename TYPE>
441 static command<TYPE> parameter(
const std::string &shortname,
const std::string &longname,
const std::string &description, TYPE ¶meter)
443 return command<TYPE>(shortname, longname, description, parameter);
481 template <
typename... TYPE>
482 static bool parse(
int argc,
const char *argv[], std::tuple<TYPE...> &all_parameters, std::string &error)
484 std::ostringstream messages;
487 while (argument < static_cast<size_t>(argc))
490 error = messages.str();
503 template <
typename... TYPE>
504 static std::string usage(
const std::string &exename,
const std::tuple<TYPE...> &all_parameters)
506 size_t width_of_shortname = 0;
507 size_t width_of_longname = 0;
508 std::ostringstream answer;
513 for_each_usage_formatting(width_of_shortname, width_of_longname, all_parameters);
530 static void unittest(
void)
535 bool parameter_boolean =
false;
536 std::string parameter_string =
"Something";
537 int parameter_integer = 0;
538 unsigned int parameter_unsigned = 0;
539 unsigned long long parameter_unsigned_long_long;
540 long long parameter_long_long;
545 auto all_commands = std::make_tuple
547 commandline::note(
"PARAMETERS"),
548 commandline::parameter(
"-b",
"--boolean",
"Extract a boolean", parameter_boolean),
549 commandline::parameter(
"-s",
"--string",
"Extractr a string", parameter_string),
550 commandline::parameter(
"-i",
"--integer",
"Extract an integer", parameter_integer),
551 commandline::parameter(
"-u",
"--unsigned",
"Extract an unsigned integer", parameter_unsigned),
552 commandline::parameter(
"-h",
"--huge",
"Extract an unsigned ilong long nteger", parameter_unsigned_long_long),
553 commandline::parameter(
"-H",
"--Huge",
"Extract an long log integer", parameter_long_long)
560 const char *argv[] = {
"program",
"-b",
"-s",
"string",
"-i3",
"-u",
"4",
"-h0",
"-H0"};
566 auto success = commandline::parse(argc, argv, all_commands, error);
573 std::ostringstream results;
574 results << parameter_boolean << parameter_string << parameter_integer << parameter_unsigned << parameter_unsigned_long_long;
580 parameter_boolean =
false;
582 const char *argv2[] = {
"program",
"--boolean",
"--string",
"four",
"--integer5",
"--unsigned",
"6"};
583 success = commandline::parse(argc, argv2, all_commands, error);
585 std::ostringstream results2;
586 results2 << parameter_boolean << parameter_string << parameter_integer << parameter_unsigned;
596 auto error_commands = std::make_tuple
598 commandline::note(
"PARAMETERS"),
599 commandline::parameter(
"-b",
"--boolean",
"Extract a boolean", parameter_boolean),
600 commandline::parameter(
"-s",
"--string",
"Extractr a string", parameter_string),
601 commandline::parameter(
"-i",
"--integer",
"Extract an integer", parameter_integer),
602 commandline::parameter(
"-u",
"--unsigned",
"Extract an unsigned integer", parameter_unsigned),
603 commandline::parameter(
"-f",
"--funny",
"Extract an object", funny_object)
606 const char *argv3[] = {
"program",
"--integer",
"2147483648",
"--unsigned",
"4294967296",
"--integer",
"-2147483649",
"--nonexistant",
"--funny"};
607 success = commandline::parse(9, argv3, error_commands, error);
610 "2147483648 Numeric overflow on parameter\n" 611 "4294967296 Numeric overflow on parameter\n" 612 "-2147483649 Numeric underflow on parameter\n" 613 "--nonexistant Unknown parameter\n" 614 "-f (--funny) Unknown parameter type\n";
617 auto how_to = usage(
"exename", error_commands);
618 std::string how_to_use =
620 "-b --boolean Extract a boolean\n" 621 "-s --string Extractr a string\n" 622 "-i --integer Extract an integer\n" 623 "-u --unsigned Extract an unsigned integer\n" 624 "-f --funny Extract an object\n";
627 puts(
"commandline:PASSED");
static void extract(std::ostringstream &messages, const char *parameter, command< text_note > element)
Dummy for use with text embedded in the parameter lists.
Definition: commandline.h:102
A single command line parameter.
Definition: commandline.h:59
replacement for the C runtime library assert that also works in release.
static void extract(std::ostringstream &messages, const char *parameter, TYPE element)
Catch all for unknown types.
Definition: commandline.h:244
used to specify text strings to appear in the help.
Definition: commandline.h:46
static void extract(std::ostringstream &messages, const char *parameter, command< TYPE > element)
Extract an integer value of the parameter from the command line parameters.
Definition: commandline.h:138
#define JASS_assert(expression)
Drop in replacement for assert() that aborts in Release as well as Debug.
Definition: asserts.h:33
static void extract(std::ostringstream &messages, const char *parameter, command< bool > element)
Extract a boolean value of the parameter from the command line parameters.
Definition: commandline.h:117
static void extract(std::ostringstream &messages, const char *parameter, command< std::string > element)
Extract a string value of the parameter from the command line parameters.
Definition: commandline.h:228
Command line processor.
Definition: commandline.h:36
std::enable_if< I< sizeof...(Tp), void >::type static for_each_parameter(std::ostringstream &messages, size_t &arg, const char *argv[], std::tuple< Tp... > &tuple) { if(std::get< I >tuple).shortname.size()==0||std::get< I >tuple).longname.size()==0) for_each_parameter< I+1, Tp... >messages, arg, argv, tuple);else if(strcmp(argv[arg], std::get< I >tuple).shortname.c_str())==0) { extract(messages, argv[++arg], std::get< I >tuple));if(typeid(std::get< I >tuple).parameter) !=typeid(bool)) arg++;} else if(strcmp(argv[arg], std::get< I >tuple).longname.c_str())==0) { extract(messages, argv[++arg], std::get< I >tuple));if(typeid(std::get< I >tuple).parameter) !=typeid(bool)) arg++;} else if(strncmp(argv[arg], std::get< I >tuple).longname.c_str(), std::get< I >tuple).longname.size())==0) { extract(messages, argv[arg]+std::get< I >tuple).longname.size(), std::get< I >tuple));arg++;} else if(strncmp(argv[arg], std::get< I >tuple).shortname.c_str(), std::get< I >tuple).shortname.size())==0) { extract(messages, argv[arg]+std::get< I >tuple).shortname.size(), std::get< I >tuple));arg++;} else for_each_parameter< I+1, Tp... >messages, arg, argv, tuple);} template< std::size_t I=0, typename... Tp > inline typename std::enable_if< I==sizeof...(Tp), void >::type static for_each_usage_formatting(size_t &width_of_shortname, size_t &width_of_longname, const std::tuple< Tp... > &) { } template< std::size_t I=0, typename... Tp > inline typename std::enable_if< I< sizeof...(Tp), void >::type static for_each_usage_formatting(size_t &width_of_shortname, size_t &width_of_longname, const std::tuple< Tp... > &tuple) { if(std::get< I >tuple).shortname.size() > width_of_shortname) width_of_shortname=std::get< I >tuple).shortname.size();if(std::get< I >tuple).longname.size() > width_of_longname width_of_longname
Iterate over each parameter looking for one that matches.
Definition: commandline.h:352
static std::enable_if< I==sizeof...(Tp), void >::type for_each_usage_print(std::ostream &out, size_t width_of_shortname, size_t width_of_longname, const std::tuple< Tp... > &)
Iterate over each parameter printing the shortname, longname, and description.
Definition: commandline.h:370
command(const std::string &shortname, const std::string &longname, const std::string &description, TYPE ¶meter)
Build an object that represents a possible command line parameter.
Definition: commandline.h:80
TYPE & parameter
A reference to the external variable to set based on the command line.
Definition: commandline.h:65
static std::enable_if< I==sizeof...(Tp), void >::type for_each_parameter(std::ostringstream &messages, size_t &arg, const char *argv[], std::tuple< Tp... > &)
Iterate over each parameter looking for one that matches.
Definition: commandline.h:262
std::string shortname
The short name to match e.g. "-m".
Definition: commandline.h:62
Definition: compress_integer_elias_delta_simd.c:23
std::string longname
The long name to mathc e.g. "-mood".
Definition: commandline.h:63
std::string description
The descriptrion to show when the user asks for help e.g. "The users' mood".
Definition: commandline.h:64