MXVK Vulkan Framework 0.35.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
Argz< String > Class Template Reference

Template command-line argument parser. More...

#include <mxvk/include/mxvk/argz.hpp>

Public Member Functions

Argz< String > & addOptionDouble (const int &code, const String &value, const String &description)
 Register a flag-only long option (e.g.
Argz< String > & addOptionDoubleValue (const int &code, const String &value, const String &description)
 Register a long option that requires a value argument (e.g.
Argz< String > & addOptionSingle (const int &c, const String &description)
 Register a flag-only short option (e.g.
Argz< String > & addOptionSingleValue (const int &c, const String &description)
 Register a short option that requires a value argument (e.g.
 Argz ()=default
 Argz (Argz< String > &&a)
 Argz (const Argz< String > &a)
 Argz (int argc, char **argv)
 Construct and immediately ingest argv.
const size_t count () const
template<typename T>
void help (T &cout)
 Print all registered options to any ostream-like object.
Argz< String > & initArgs (int argc, char **argv)
 Ingest argc/argv, converting to the target String type.
int lookUpCode (const String &value) const
 Look up the integer code registered for a long option name.
Argz< String > & operator= (Argz< String > &&a)
Argz< String > & operator= (const Argz< String > &a)
int proc (Argument< String > &a)
 Advance the cursor and parse the next argument.
void reset ()
 Reset the internal parse cursor to the beginning of argv.
 ~Argz ()=default

Protected Attributes

ArgumentData< String > arg_data
std::unordered_map< int, Argument< String > > arg_info

Detailed Description

template<StringType String>
class Argz< String >

Template command-line argument parser.

Template Parameters
StringString type satisfying StringType (usually std::string or std::wstring).

Options are registered with addOption*() before parsing. Call proc() in a loop until it returns -1 to iterate over all arguments.

Definition at line 187 of file argz.hpp.

Constructor & Destructor Documentation

◆ ~Argz()

template<StringType String>
Argz< String >::~Argz ( )
default

◆ Argz() [1/4]

template<StringType String>
Argz< String >::Argz ( )
default

◆ Argz() [2/4]

template<StringType String>
Argz< String >::Argz ( int argc,
char ** argv )
inline

Construct and immediately ingest argv.

Parameters
argcArgument count from main().
argvArgument vector from main().

Definition at line 197 of file argz.hpp.

197{ initArgs(argc, argv); }
Template command-line argument parser.
Definition argz.hpp:187
Argz< String > & initArgs(int argc, char **argv)
Ingest argc/argv, converting to the target String type.
Definition argz.hpp:230

◆ Argz() [3/4]

template<StringType String>
Argz< String >::Argz ( const Argz< String > & a)
inline

Definition at line 198 of file argz.hpp.

198: arg_data{a.arg_data}, arg_info{a.arg_info}, index{a.index}, cindex{a.cindex} {}
std::unordered_map< int, Argument< String > > arg_info
Definition argz.hpp:570
ArgumentData< String > arg_data
Definition argz.hpp:569

◆ Argz() [4/4]

template<StringType String>
Argz< String >::Argz ( Argz< String > && a)
inline

Definition at line 211 of file argz.hpp.

211: arg_data{std::move(a.arg_data)}, arg_info{std::move(a.arg_info)}, index{a.index}, cindex{a.cindex} {}

Member Function Documentation

◆ addOptionDouble()

template<StringType String>
Argz< String > & Argz< String >::addOptionDouble ( const int & code,
const String & value,
const String & description )
inline

Register a flag-only long option (e.g.

--verbose).

Parameters
codeUnique integer code associated with this option.
valueLong option name string (without --).
descriptionHelp text.
Returns
Reference to *this for chaining.

Definition at line 305 of file argz.hpp.

305 {
307 a.arg_letter = code;
308 a.arg_type = ArgType::ARG_DOUBLE;
309 a.desc = description;
310 a.arg_name = value;
311 arg_info[code] = a;
312 return *this;
313 }

◆ addOptionDoubleValue()

template<StringType String>
Argz< String > & Argz< String >::addOptionDoubleValue ( const int & code,
const String & value,
const String & description )
inline

Register a long option that requires a value argument (e.g.

--output file).

Parameters
codeUnique integer code.
valueLong option name string.
descriptionHelp text.
Returns
Reference to *this for chaining.

Definition at line 322 of file argz.hpp.

322 {
324 a.arg_letter = code;
325 a.arg_type = ArgType::ARG_DOUBLE_VALUE;
326 a.desc = description;
327 a.arg_name = value;
328 arg_info[code] = a;
329 return *this;
330 }

◆ addOptionSingle()

template<StringType String>
Argz< String > & Argz< String >::addOptionSingle ( const int & c,
const String & description )
inline

Register a flag-only short option (e.g.

-v, -h).

Parameters
cShort option character code.
descriptionHelp text.
Returns
Reference to *this for chaining.

Definition at line 274 of file argz.hpp.

274 {
276 a.arg_letter = c;
277 a.arg_type = ArgType::ARG_SINGLE;
278 a.desc = description;
279 arg_info[c] = a;
280 return *this;
281 }

◆ addOptionSingleValue()

template<StringType String>
Argz< String > & Argz< String >::addOptionSingleValue ( const int & c,
const String & description )
inline

Register a short option that requires a value argument (e.g.

-o file).

Parameters
cShort option character code.
descriptionHelp text.
Returns
Reference to *this for chaining.

Definition at line 289 of file argz.hpp.

289 {
291 a.arg_letter = c;
292 a.arg_type = ArgType::ARG_SINGLE_VALUE;
293 a.desc = description;
294 arg_info[c] = a;
295 return *this;
296 }

◆ count()

template<StringType String>
const size_t Argz< String >::count ( ) const
inline
Returns
Number of argv entries consumed so far.

Definition at line 566 of file argz.hpp.

566{ return index; }

◆ help()

template<StringType String>
template<typename T>
void Argz< String >::help ( T & cout)
inline

Print all registered options to any ostream-like object.

Template Parameters
TOutput stream type (e.g. std::ostream, std::wostream).
Parameters
coutDestination stream.

Definition at line 495 of file argz.hpp.

495 {
497 const bool use_color = supportsColor(cout);
498 auto write_ansi = [&](const char *seq) {
499 if (!use_color) {
500 return;
501 }
502 if constexpr (std::is_same_v<char_type, char>) {
503 cout << seq;
504 } else if constexpr (std::is_same_v<char_type, wchar_t>) {
505 for (const char *p = seq; *p != '\0'; ++p) {
507 }
508 }
509 };
510 auto write_padding = [&](size_t count) {
511 for (size_t i = 0; i < count; ++i) {
513 }
514 };
515 struct HelpRow {
517 String desc;
518 bool is_short;
519 };
522 for (const auto &i : arg_info) {
523 if (i.second.arg_type == ArgType::ARG_SINGLE || i.second.arg_type == ArgType::ARG_SINGLE_VALUE)
524 v.push_back(i.second);
525 else if (i.second.arg_type == ArgType::ARG_DOUBLE || i.second.arg_type == ArgType::ARG_DOUBLE_VALUE)
526 v2.push_back(i.second);
527 }
531 rows.reserve(v.size() + v2.size());
532 for (const auto &a : v) {
534 token += static_cast<char_type>('-');
535 token += static_cast<char_type>(a.arg_letter);
536 rows.push_back(HelpRow{std::move(token), a.desc, true});
537 }
538 for (const auto &a : v2) {
540 token += static_cast<char_type>('-');
541 token += static_cast<char_type>('-');
542 token += a.arg_name;
543 rows.push_back(HelpRow{std::move(token), a.desc, false});
544 }
545 size_t token_width = 0;
546 for (const auto &row : rows) {
547 token_width = std::max(token_width, static_cast<size_t>(row.token.length()));
548 }
549 const size_t desc_column = token_width + 2;
550 for (const auto &row : rows) {
551 write_ansi(row.is_short ? "\x1b[1;36m" : "\x1b[1;35m");
552 cout << row.token;
553 write_ansi("\x1b[0m");
554 if (desc_column > row.token.length()) {
555 write_padding(desc_column - row.token.length());
556 } else {
557 write_padding(2);
558 }
559 write_ansi("\x1b[90m");
560 cout << row.desc;
561 write_ansi("\x1b[0m");
562 cout << '\n';
563 }
564 }
const size_t count() const
Definition argz.hpp:566

◆ initArgs()

template<StringType String>
Argz< String > & Argz< String >::initArgs ( int argc,
char ** argv )
inline

Ingest argc/argv, converting to the target String type.

Parameters
argcArgument count.
argvArgument vector.
Returns
Reference to *this for method chaining.

Definition at line 230 of file argz.hpp.

230 {
231 arg_data.argc = argc;
232 arg_data.args.clear();
233 if (argc > 1) {
234 arg_data.args.reserve(static_cast<size_t>(argc - 1));
235 }
237 for (int i = 1; i < argc; ++i) {
238 const char *a = (argv != nullptr) ? argv[i] : nullptr;
239 arg_data.args.emplace_back(a != nullptr ? a : "");
240 }
241 reset();
242 return *this;
243 }
245 for (int i = 1; i < argc; ++i) {
246 const char *a = (argv != nullptr) ? argv[i] : nullptr;
247 String data;
248 if (a != nullptr) {
249 for (size_t z = 0; a[z] != 0; ++z) {
250 data += static_cast<typename String::value_type>(a[z]);
251 }
252 }
253 arg_data.args.push_back(data);
254 }
255 reset();
256 return *this;
257 }
258 reset();
259 return *this;
260 }
void reset()
Reset the internal parse cursor to the beginning of argv.
Definition argz.hpp:263

◆ lookUpCode()

template<StringType String>
int Argz< String >::lookUpCode ( const String & value) const
inline

Look up the integer code registered for a long option name.

Parameters
valueLong option name (without --).
Returns
The registered code, or -1 if not found.

Definition at line 337 of file argz.hpp.

337 {
338 for (const auto &i : arg_info) {
339 if (i.second.arg_name == value) {
340 return i.second.arg_letter;
341 }
342 }
343 return -1;
344 }

◆ operator=() [1/2]

template<StringType String>
Argz< String > & Argz< String >::operator= ( Argz< String > && a)
inline

Definition at line 213 of file argz.hpp.

213 {
214 if (this == &a) {
215 return *this;
216 }
219 index = a.index;
220 cindex = a.cindex;
221 return *this;
222 }

◆ operator=() [2/2]

template<StringType String>
Argz< String > & Argz< String >::operator= ( const Argz< String > & a)
inline

Definition at line 200 of file argz.hpp.

200 {
201 if (this == &a) {
202 return *this;
203 }
206 index = a.index;
207 cindex = a.cindex;
208 return *this;
209 }

◆ proc()

template<StringType String>
int Argz< String >::proc ( Argument< String > & a)
inline

Advance the cursor and parse the next argument.

Parameters
aOutput: filled with the matched option details.
Returns
The option code on success; '-' for a positional argument; -1 when exhausted.
Exceptions
ArgException<String>On unrecognised options or missing values.

Definition at line 352 of file argz.hpp.

352 {
353 if (index < static_cast<int>(arg_data.args.size())) {
354 const String &type{arg_data.args[index]};
355 if (type.length() > 2 && type[0] == '-' && type[1] == '-') {
356 String name{};
358 const auto eq_pos = type.find(static_cast<typename String::value_type>('='));
359 const bool has_inline_value = (eq_pos != String::npos);
360 for (size_t z = 2; z < type.length(); ++z)
361 if (!has_inline_value || z < eq_pos) {
362 name += type[z];
363 } else if (z > eq_pos) {
364 inline_value += type[z];
365 }
366 int code = lookUpCode(name);
367 if (code != -1) {
368 auto pos = arg_info.find(code);
369 if (pos != arg_info.end()) {
370 if (pos->second.arg_type == ArgType::ARG_DOUBLE) {
371 if (has_inline_value) {
373 throw ArgException<String>("Invalid switch not found!");
374 }
376 throw ArgException<String>(L"Invalid switch not found!");
377 }
378 }
379 a = pos->second;
380 a.arg_name = name;
381 index++;
382 return code;
383 } else {
384 a = pos->second;
385 a.arg_name = name;
386 if (has_inline_value) {
387 if (inline_value.empty()) {
389 throw ArgException<String>("Expected Value");
390 }
392 throw ArgException<String>(L"Expected Value");
393 }
394 }
395 a.arg_value = inline_value;
396 index++;
397 return code;
398 }
399 if (++index < static_cast<int>(arg_data.args.size())) {
400 const String &s{arg_data.args[index]};
401 if (canUseAsOptionValue(s)) {
402 a.arg_name = name;
403 a.arg_value = s;
404 index++;
405 return code;
406 }
407 }
409 throw ArgException<String>("Expected Value");
410 }
412 throw ArgException<String>(L"Expected Value");
413 }
414 }
415 }
416 } else {
417 throwUnknownOption(type);
418 }
419 } else if (type.length() == 1 && type[0] == '-') {
421 throw ArgException<String>("Expected Value found -");
422 }
424 throw ArgException<String>(L"Expected Value found -");
425 }
426 } else if (type.length() > 1 && (type[0] == '-')) {
427 const int c{type[cindex]};
428 const auto pos{arg_info.find(c)};
429 cindex++;
430 if (cindex >= static_cast<int>(type.length())) {
431 cindex = 1;
432 index++;
433 }
435 name_val += static_cast<typename String::value_type>(c);
436 if (pos != arg_info.end()) {
437 if (pos->second.arg_type == ArgType::ARG_SINGLE) {
438 a = pos->second;
439 a.arg_name = name_val;
440 return c;
441 } else if (pos->second.arg_type == ArgType::ARG_SINGLE_VALUE) {
442 if (index < static_cast<int>(arg_data.args.size())) {
443 const String &s{arg_data.args[index]};
444 if (!canUseAsOptionValue(s)) {
446 throw ArgException<String>("Expected Value found -");
447 }
449 throw ArgException<String>(L"Expected Value found -");
450 }
451 }
452 if (s.length() > 0) {
453 a = pos->second;
454 a.arg_value = s;
455 a.arg_name = name_val;
456 index++;
457 return c;
458 }
459 } else {
461 throw ArgException<String>("Expected Value");
462 }
464 throw ArgException<String>(L"Expected Value");
465 }
466 }
467 } else {
469 throw ArgException<String>("Invalid switch not found!");
470 }
472 throw ArgException<String>(L"Invalid switch not found!");
473 }
474 }
475 } else {
476 throwUnknownOption(type);
477 }
478 } else {
480 a.arg_name = String{};
481 a.arg_type = ArgType::ARG_NONE;
482 a.arg_name = a.arg_value = arg_data.args.at(index);
483 index++;
484 return '-';
485 }
486 }
487 return -1;
488 }
ArgException()=default
int lookUpCode(const String &value) const
Look up the integer code registered for a long option name.
Definition argz.hpp:337
Argument()
Definition argz.hpp:120

◆ reset()

template<StringType String>
void Argz< String >::reset ( )
inline

Reset the internal parse cursor to the beginning of argv.

Definition at line 263 of file argz.hpp.

263 {
264 index = 0;
265 cindex = 1;
266 }

Member Data Documentation

◆ arg_data

template<StringType String>
ArgumentData<String> Argz< String >::arg_data
protected

Definition at line 569 of file argz.hpp.

◆ arg_info

template<StringType String>
std::unordered_map<int, Argument<String> > Argz< String >::arg_info
protected

Definition at line 570 of file argz.hpp.


The documentation for this class was generated from the following file: