Commit 628dc9202b4a0f0d8eb1fae357a452d85278a73b

Authored by Eyal Rozenberg
Committed by GitHub
1 parent 548d6196

Fixes #345, fixes #346: Exception code tweaks (#347)

* Fixes #345, fixes #346, regards #340: Put exceptions in a sub-namespace and renamed them accordingly.

* Also fixed some "loose ends" regarding namespace indentation which were missing in PR #350.

* Dropped `required_option_missing` as it is unused.
README.md
@@ -109,9 +109,9 @@ result.unmatched() @@ -109,9 +109,9 @@ result.unmatched()
109 109
110 Exceptional situations throw C++ exceptions. There are two types of 110 Exceptional situations throw C++ exceptions. There are two types of
111 exceptions: errors defining the options, and errors when parsing a list of 111 exceptions: errors defining the options, and errors when parsing a list of
112 -arguments. All exceptions derive from `cxxopts::OptionException`. Errors  
113 -defining options derive from `cxxopts::OptionSpecException` and errors  
114 -parsing arguments derive from `cxxopts::OptionParseException`. 112 +arguments. All exceptions derive from `cxxopts::exceptions::exception`. Errors
  113 +defining options derive from `cxxopts::exceptions::specification` and errors
  114 +parsing arguments derive from `cxxopts::exceptions::parsing`.
115 115
116 All exceptions define a `what()` function to get a printable string 116 All exceptions define a `what()` function to get a printable string
117 explaining the error. 117 explaining the error.
include/cxxopts.hpp
@@ -227,6 +227,7 @@ empty(const String& s) @@ -227,6 +227,7 @@ empty(const String& s)
227 } // namespace cxxopts 227 } // namespace cxxopts
228 228
229 namespace std { 229 namespace std {
  230 +
230 inline 231 inline
231 cxxopts::UnicodeStringIterator 232 cxxopts::UnicodeStringIterator
232 begin(const icu::UnicodeString& s) 233 begin(const icu::UnicodeString& s)
@@ -304,6 +305,7 @@ empty(const std::string& s) @@ -304,6 +305,7 @@ empty(const std::string& s)
304 #endif 305 #endif
305 306
306 namespace cxxopts { 307 namespace cxxopts {
  308 +
307 namespace { 309 namespace {
308 #ifdef _WIN32 310 #ifdef _WIN32
309 const std::string LQUOTE("\'"); 311 const std::string LQUOTE("\'");
@@ -368,164 +370,155 @@ class Value : public std::enable_shared_from_this<Value> @@ -368,164 +370,155 @@ class Value : public std::enable_shared_from_this<Value>
368 #if defined(__GNUC__) 370 #if defined(__GNUC__)
369 #pragma GCC diagnostic pop 371 #pragma GCC diagnostic pop
370 #endif 372 #endif
371 -class OptionException : public std::exception  
372 -{  
373 - public:  
374 - explicit OptionException(std::string message)  
375 - : m_message(std::move(message))  
376 - {  
377 - }  
378 -  
379 - CXXOPTS_NODISCARD  
380 - const char*  
381 - what() const noexcept override 373 +namespace exceptions {
  374 + class exception : public std::exception
382 { 375 {
383 - return m_message.c_str();  
384 - } 376 + public:
  377 + explicit exception(std::string message)
  378 + : m_message(std::move(message))
  379 + {
  380 + }
385 381
386 - private:  
387 - std::string m_message;  
388 -}; 382 + CXXOPTS_NODISCARD
  383 + const char*
  384 + what() const noexcept override
  385 + {
  386 + return m_message.c_str();
  387 + }
389 388
390 -class OptionSpecException : public OptionException  
391 -{  
392 - public: 389 + private:
  390 + std::string m_message;
  391 + };
393 392
394 - explicit OptionSpecException(const std::string& message)  
395 - : OptionException(message) 393 + class specification : public exception
396 { 394 {
397 - }  
398 -}; 395 + public:
399 396
400 -class OptionParseException : public OptionException  
401 -{  
402 - public:  
403 - explicit OptionParseException(const std::string& message)  
404 - : OptionException(message)  
405 - {  
406 - }  
407 -}; 397 + explicit specification(const std::string& message)
  398 + : exception(message)
  399 + {
  400 + }
  401 + };
408 402
409 -class option_exists_error : public OptionSpecException  
410 -{  
411 - public:  
412 - explicit option_exists_error(const std::string& option)  
413 - : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists") 403 + class parsing : public exception
414 { 404 {
415 - }  
416 -}; 405 + public:
  406 + explicit parsing(const std::string& message)
  407 + : exception(message)
  408 + {
  409 + }
  410 + };
417 411
418 -class invalid_option_format_error : public OptionSpecException  
419 -{  
420 - public:  
421 - explicit invalid_option_format_error(const std::string& format)  
422 - : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE) 412 + class option_already_exists : public specification
423 { 413 {
424 - }  
425 -}; 414 + public:
  415 + explicit option_already_exists(const std::string& option)
  416 + : specification("Option " + LQUOTE + option + RQUOTE + " already exists")
  417 + {
  418 + }
  419 + };
426 420
427 -class option_syntax_exception : public OptionParseException {  
428 - public:  
429 - explicit option_syntax_exception(const std::string& text)  
430 - : OptionParseException("Argument " + LQUOTE + text + RQUOTE +  
431 - " starts with a - but has incorrect syntax") 421 + class invalid_option_format : public specification
432 { 422 {
433 - }  
434 -}; 423 + public:
  424 + explicit invalid_option_format(const std::string& format)
  425 + : specification("Invalid option format " + LQUOTE + format + RQUOTE)
  426 + {
  427 + }
  428 + };
435 429
436 -class option_not_exists_exception : public OptionParseException  
437 -{  
438 - public:  
439 - explicit option_not_exists_exception(const std::string& option)  
440 - : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist")  
441 - {  
442 - }  
443 -}; 430 + class invalid_option_syntax : public parsing {
  431 + public:
  432 + explicit invalid_option_syntax(const std::string& text)
  433 + : parsing("Argument " + LQUOTE + text + RQUOTE +
  434 + " starts with a - but has incorrect syntax")
  435 + {
  436 + }
  437 + };
444 438
445 -class missing_argument_exception : public OptionParseException  
446 -{  
447 - public:  
448 - explicit missing_argument_exception(const std::string& option)  
449 - : OptionParseException(  
450 - "Option " + LQUOTE + option + RQUOTE + " is missing an argument"  
451 - ) 439 + class no_such_option : public parsing
452 { 440 {
453 - }  
454 -}; 441 + public:
  442 + explicit no_such_option(const std::string& option)
  443 + : parsing("Option " + LQUOTE + option + RQUOTE + " does not exist")
  444 + {
  445 + }
  446 + };
455 447
456 -class option_requires_argument_exception : public OptionParseException  
457 -{  
458 - public:  
459 - explicit option_requires_argument_exception(const std::string& option)  
460 - : OptionParseException(  
461 - "Option " + LQUOTE + option + RQUOTE + " requires an argument"  
462 - ) 448 + class missing_argument : public parsing
463 { 449 {
464 - }  
465 -}; 450 + public:
  451 + explicit missing_argument(const std::string& option)
  452 + : parsing(
  453 + "Option " + LQUOTE + option + RQUOTE + " is missing an argument"
  454 + )
  455 + {
  456 + }
  457 + };
466 458
467 -class option_not_has_argument_exception : public OptionParseException  
468 -{  
469 - public:  
470 - option_not_has_argument_exception  
471 - (  
472 - const std::string& option,  
473 - const std::string& arg  
474 - )  
475 - : OptionParseException(  
476 - "Option " + LQUOTE + option + RQUOTE +  
477 - " does not take an argument, but argument " +  
478 - LQUOTE + arg + RQUOTE + " given"  
479 - ) 459 + class option_requires_argument : public parsing
480 { 460 {
481 - }  
482 -}; 461 + public:
  462 + explicit option_requires_argument(const std::string& option)
  463 + : parsing(
  464 + "Option " + LQUOTE + option + RQUOTE + " requires an argument"
  465 + )
  466 + {
  467 + }
  468 + };
483 469
484 -class option_not_present_exception : public OptionParseException  
485 -{  
486 - public:  
487 - explicit option_not_present_exception(const std::string& option)  
488 - : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present") 470 + class gratuitous_argument_for_option : public parsing
489 { 471 {
490 - }  
491 -}; 472 + public:
  473 + gratuitous_argument_for_option
  474 + (
  475 + const std::string& option,
  476 + const std::string& arg
  477 + )
  478 + : parsing(
  479 + "Option " + LQUOTE + option + RQUOTE +
  480 + " does not take an argument, but argument " +
  481 + LQUOTE + arg + RQUOTE + " given"
  482 + )
  483 + {
  484 + }
  485 + };
492 486
493 -class option_has_no_value_exception : public OptionException  
494 -{  
495 - public:  
496 - explicit option_has_no_value_exception(const std::string& option)  
497 - : OptionException(  
498 - !option.empty() ?  
499 - ("Option " + LQUOTE + option + RQUOTE + " has no value") :  
500 - "Option has no value") 487 + class requested_option_not_present : public parsing
501 { 488 {
502 - }  
503 -}; 489 + public:
  490 + explicit requested_option_not_present(const std::string& option)
  491 + : parsing("Option " + LQUOTE + option + RQUOTE + " not present")
  492 + {
  493 + }
  494 + };
504 495
505 -class argument_incorrect_type : public OptionParseException  
506 -{  
507 - public:  
508 - explicit argument_incorrect_type  
509 - (  
510 - const std::string& arg  
511 - )  
512 - : OptionParseException(  
513 - "Argument " + LQUOTE + arg + RQUOTE + " failed to parse"  
514 - ) 496 + class option_has_no_value : public exception
515 { 497 {
516 - }  
517 -}; 498 + public:
  499 + explicit option_has_no_value(const std::string& option)
  500 + : exception(
  501 + !option.empty() ?
  502 + ("Option " + LQUOTE + option + RQUOTE + " has no value") :
  503 + "Option has no value")
  504 + {
  505 + }
  506 + };
518 507
519 -class option_required_exception : public OptionParseException  
520 -{  
521 - public:  
522 - explicit option_required_exception(const std::string& option)  
523 - : OptionParseException(  
524 - "Option " + LQUOTE + option + RQUOTE + " is required but not present"  
525 - ) 508 + class incorrect_argument_type : public parsing
526 { 509 {
527 - }  
528 -}; 510 + public:
  511 + explicit incorrect_argument_type
  512 + (
  513 + const std::string& arg
  514 + )
  515 + : parsing(
  516 + "Argument " + LQUOTE + arg + RQUOTE + " failed to parse"
  517 + )
  518 + {
  519 + }
  520 + };
  521 +}
529 522
530 template <typename T> 523 template <typename T>
531 void throw_or_mimic(const std::string& text) 524 void throw_or_mimic(const std::string& text)
@@ -547,7 +540,9 @@ void throw_or_mimic(const std::string&amp; text) @@ -547,7 +540,9 @@ void throw_or_mimic(const std::string&amp; text)
547 } 540 }
548 541
549 namespace values { 542 namespace values {
  543 +
550 namespace parser_tool { 544 namespace parser_tool {
  545 +
551 struct IntegerDesc 546 struct IntegerDesc
552 { 547 {
553 std::string negative = ""; 548 std::string negative = "";
@@ -560,12 +555,13 @@ struct ArguDesc { @@ -560,12 +555,13 @@ struct ArguDesc {
560 bool set_value = false; 555 bool set_value = false;
561 std::string value = ""; 556 std::string value = "";
562 }; 557 };
  558 +
563 #ifdef CXXOPTS_NO_REGEX 559 #ifdef CXXOPTS_NO_REGEX
564 inline IntegerDesc SplitInteger(const std::string &text) 560 inline IntegerDesc SplitInteger(const std::string &text)
565 { 561 {
566 if (text.empty()) 562 if (text.empty())
567 { 563 {
568 - throw_or_mimic<argument_incorrect_type>(text); 564 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
569 } 565 }
570 IntegerDesc desc; 566 IntegerDesc desc;
571 const char *pdata = text.c_str(); 567 const char *pdata = text.c_str();
@@ -585,7 +581,7 @@ inline IntegerDesc SplitInteger(const std::string &amp;text) @@ -585,7 +581,7 @@ inline IntegerDesc SplitInteger(const std::string &amp;text)
585 } 581 }
586 else 582 else
587 { 583 {
588 - throw_or_mimic<argument_incorrect_type>(text); 584 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
589 } 585 }
590 return desc; 586 return desc;
591 } 587 }
@@ -644,7 +640,7 @@ inline std::pair&lt;std::string, std::string&gt; SplitSwitchDef(const std::string &amp;tex @@ -644,7 +640,7 @@ inline std::pair&lt;std::string, std::string&gt; SplitSwitchDef(const std::string &amp;tex
644 if (*pdata == '\0') { 640 if (*pdata == '\0') {
645 long_sw = std::string(store, pdata - store); 641 long_sw = std::string(store, pdata - store);
646 } else { 642 } else {
647 - throw_or_mimic<invalid_option_format_error>(text); 643 + throw_or_mimic<exceptions::invalid_option_format>(text);
648 } 644 }
649 } 645 }
650 return std::pair<std::string, std::string>(short_sw, long_sw); 646 return std::pair<std::string, std::string>(short_sw, long_sw);
@@ -725,7 +721,7 @@ inline IntegerDesc SplitInteger(const std::string &amp;text) @@ -725,7 +721,7 @@ inline IntegerDesc SplitInteger(const std::string &amp;text)
725 721
726 if (match.length() == 0) 722 if (match.length() == 0)
727 { 723 {
728 - throw_or_mimic<argument_incorrect_type>(text); 724 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
729 } 725 }
730 726
731 IntegerDesc desc; 727 IntegerDesc desc;
@@ -741,7 +737,6 @@ inline IntegerDesc SplitInteger(const std::string &amp;text) @@ -741,7 +737,6 @@ inline IntegerDesc SplitInteger(const std::string &amp;text)
741 } 737 }
742 738
743 return desc; 739 return desc;
744 -  
745 } 740 }
746 741
747 inline bool IsTrueText(const std::string &text) 742 inline bool IsTrueText(const std::string &text)
@@ -764,7 +759,7 @@ inline std::pair&lt;std::string, std::string&gt; SplitSwitchDef(const std::string &amp;tex @@ -764,7 +759,7 @@ inline std::pair&lt;std::string, std::string&gt; SplitSwitchDef(const std::string &amp;tex
764 std::regex_match(text.c_str(), result, option_specifier); 759 std::regex_match(text.c_str(), result, option_specifier);
765 if (result.empty()) 760 if (result.empty())
766 { 761 {
767 - throw_or_mimic<invalid_option_format_error>(text); 762 + throw_or_mimic<exceptions::invalid_option_format>(text);
768 } 763 }
769 764
770 const std::string& short_sw = result[2]; 765 const std::string& short_sw = result[2];
@@ -799,6 +794,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &amp;matched) @@ -799,6 +794,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &amp;matched)
799 } // namespace parser_tool 794 } // namespace parser_tool
800 795
801 namespace detail { 796 namespace detail {
  797 +
802 template <typename T, bool B> 798 template <typename T, bool B>
803 struct SignedCheck; 799 struct SignedCheck;
804 800
@@ -813,14 +809,14 @@ struct SignedCheck&lt;T, true&gt; @@ -813,14 +809,14 @@ struct SignedCheck&lt;T, true&gt;
813 { 809 {
814 if (u > static_cast<U>((std::numeric_limits<T>::min)())) 810 if (u > static_cast<U>((std::numeric_limits<T>::min)()))
815 { 811 {
816 - throw_or_mimic<argument_incorrect_type>(text); 812 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
817 } 813 }
818 } 814 }
819 else 815 else
820 { 816 {
821 if (u > static_cast<U>((std::numeric_limits<T>::max)())) 817 if (u > static_cast<U>((std::numeric_limits<T>::max)()))
822 { 818 {
823 - throw_or_mimic<argument_incorrect_type>(text); 819 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
824 } 820 }
825 } 821 }
826 } 822 }
@@ -857,7 +853,7 @@ template &lt;typename R, typename T&gt; @@ -857,7 +853,7 @@ template &lt;typename R, typename T&gt;
857 void 853 void
858 checked_negate(R&, T&&, const std::string& text, std::false_type) 854 checked_negate(R&, T&&, const std::string& text, std::false_type)
859 { 855 {
860 - throw_or_mimic<argument_incorrect_type>(text); 856 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
861 } 857 }
862 858
863 template <typename T> 859 template <typename T>
@@ -893,13 +889,13 @@ integer_parser(const std::string&amp; text, T&amp; value) @@ -893,13 +889,13 @@ integer_parser(const std::string&amp; text, T&amp; value)
893 } 889 }
894 else 890 else
895 { 891 {
896 - throw_or_mimic<argument_incorrect_type>(text); 892 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
897 } 893 }
898 894
899 const US next = static_cast<US>(result * base + digit); 895 const US next = static_cast<US>(result * base + digit);
900 if (result > next) 896 if (result > next)
901 { 897 {
902 - throw_or_mimic<argument_incorrect_type>(text); 898 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
903 } 899 }
904 900
905 result = next; 901 result = next;
@@ -923,7 +919,7 @@ void stringstream_parser(const std::string&amp; text, T&amp; value) @@ -923,7 +919,7 @@ void stringstream_parser(const std::string&amp; text, T&amp; value)
923 std::stringstream in(text); 919 std::stringstream in(text);
924 in >> value; 920 in >> value;
925 if (!in) { 921 if (!in) {
926 - throw_or_mimic<argument_incorrect_type>(text); 922 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
927 } 923 }
928 } 924 }
929 925
@@ -951,7 +947,7 @@ parse_value(const std::string&amp; text, bool&amp; value) @@ -951,7 +947,7 @@ parse_value(const std::string&amp; text, bool&amp; value)
951 return; 947 return;
952 } 948 }
953 949
954 - throw_or_mimic<argument_incorrect_type>(text); 950 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
955 } 951 }
956 952
957 inline 953 inline
@@ -1007,7 +1003,7 @@ void parse_value(const std::string&amp; text, char&amp; c) @@ -1007,7 +1003,7 @@ void parse_value(const std::string&amp; text, char&amp; c)
1007 { 1003 {
1008 if (text.length() != 1) 1004 if (text.length() != 1)
1009 { 1005 {
1010 - throw_or_mimic<argument_incorrect_type>(text); 1006 + throw_or_mimic<exceptions::incorrect_argument_type>(text);
1011 } 1007 }
1012 1008
1013 c = text[0]; 1009 c = text[0];
@@ -1204,6 +1200,7 @@ class standard_value&lt;bool&gt; : public abstract_value&lt;bool&gt; @@ -1204,6 +1200,7 @@ class standard_value&lt;bool&gt; : public abstract_value&lt;bool&gt;
1204 m_implicit_value = "true"; 1200 m_implicit_value = "true";
1205 } 1201 }
1206 }; 1202 };
  1203 +
1207 } // namespace values 1204 } // namespace values
1208 1205
1209 template <typename T> 1206 template <typename T>
@@ -1388,7 +1385,7 @@ class OptionValue @@ -1388,7 +1385,7 @@ class OptionValue
1388 as() const 1385 as() const
1389 { 1386 {
1390 if (m_value == nullptr) { 1387 if (m_value == nullptr) {
1391 - throw_or_mimic<option_has_no_value_exception>( 1388 + throw_or_mimic<exceptions::option_has_no_value>(
1392 m_long_name == nullptr ? "" : *m_long_name); 1389 m_long_name == nullptr ? "" : *m_long_name);
1393 } 1390 }
1394 1391
@@ -1576,14 +1573,14 @@ class ParseResult @@ -1576,14 +1573,14 @@ class ParseResult
1576 1573
1577 if (iter == m_keys.end()) 1574 if (iter == m_keys.end())
1578 { 1575 {
1579 - throw_or_mimic<option_not_present_exception>(option); 1576 + throw_or_mimic<exceptions::requested_option_not_present>(option);
1580 } 1577 }
1581 1578
1582 auto viter = m_values.find(iter->second); 1579 auto viter = m_values.find(iter->second);
1583 1580
1584 if (viter == m_values.end()) 1581 if (viter == m_values.end())
1585 { 1582 {
1586 - throw_or_mimic<option_not_present_exception>(option); 1583 + throw_or_mimic<exceptions::requested_option_not_present>(option);
1587 } 1584 }
1588 1585
1589 return viter->second; 1586 return viter->second;
@@ -1898,184 +1895,186 @@ class OptionAdder @@ -1898,184 +1895,186 @@ class OptionAdder
1898 }; 1895 };
1899 1896
1900 namespace { 1897 namespace {
1901 - constexpr size_t OPTION_LONGEST = 30;  
1902 - constexpr size_t OPTION_DESC_GAP = 2;  
1903 1898
1904 - String  
1905 - format_option  
1906 - (  
1907 - const HelpOptionDetails& o  
1908 - ) 1899 +constexpr size_t OPTION_LONGEST = 30;
  1900 +constexpr size_t OPTION_DESC_GAP = 2;
  1901 +
  1902 +String
  1903 +format_option
  1904 +(
  1905 + const HelpOptionDetails& o
  1906 +)
  1907 +{
  1908 + const auto& s = o.s;
  1909 + const auto& l = o.l;
  1910 +
  1911 + String result = " ";
  1912 +
  1913 + if (!s.empty())
  1914 + {
  1915 + result += "-" + toLocalString(s);
  1916 + if (!l.empty())
  1917 + {
  1918 + result += ",";
  1919 + }
  1920 + }
  1921 + else
  1922 + {
  1923 + result += " ";
  1924 + }
  1925 +
  1926 + if (!l.empty())
1909 { 1927 {
1910 - const auto& s = o.s;  
1911 - const auto& l = o.l; 1928 + result += " --" + toLocalString(l);
  1929 + }
1912 1930
1913 - String result = " "; 1931 + auto arg = !o.arg_help.empty() ? toLocalString(o.arg_help) : "arg";
1914 1932
1915 - if (!s.empty()) 1933 + if (!o.is_boolean)
  1934 + {
  1935 + if (o.has_implicit)
1916 { 1936 {
1917 - result += "-" + toLocalString(s);  
1918 - if (!l.empty())  
1919 - {  
1920 - result += ",";  
1921 - } 1937 + result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";
1922 } 1938 }
1923 else 1939 else
1924 { 1940 {
1925 - result += " "; 1941 + result += " " + arg;
1926 } 1942 }
  1943 + }
1927 1944
1928 - if (!l.empty())  
1929 - {  
1930 - result += " --" + toLocalString(l);  
1931 - } 1945 + return result;
  1946 +}
1932 1947
1933 - auto arg = !o.arg_help.empty() ? toLocalString(o.arg_help) : "arg"; 1948 +String
  1949 +format_description
  1950 +(
  1951 + const HelpOptionDetails& o,
  1952 + size_t start,
  1953 + size_t allowed,
  1954 + bool tab_expansion
  1955 +)
  1956 +{
  1957 + auto desc = o.desc;
1934 1958
1935 - if (!o.is_boolean) 1959 + if (o.has_default && (!o.is_boolean || o.default_value != "false"))
  1960 + {
  1961 + if(!o.default_value.empty())
1936 { 1962 {
1937 - if (o.has_implicit)  
1938 - {  
1939 - result += " [=" + arg + "(=" + toLocalString(o.implicit_value) + ")]";  
1940 - }  
1941 - else  
1942 - {  
1943 - result += " " + arg;  
1944 - } 1963 + desc += toLocalString(" (default: " + o.default_value + ")");
  1964 + }
  1965 + else
  1966 + {
  1967 + desc += toLocalString(" (default: \"\")");
1945 } 1968 }
1946 -  
1947 - return result;  
1948 } 1969 }
1949 1970
1950 - String  
1951 - format_description  
1952 - (  
1953 - const HelpOptionDetails& o,  
1954 - size_t start,  
1955 - size_t allowed,  
1956 - bool tab_expansion  
1957 - )  
1958 - {  
1959 - auto desc = o.desc; 1971 + String result;
1960 1972
1961 - if (o.has_default && (!o.is_boolean || o.default_value != "false")) 1973 + if (tab_expansion)
  1974 + {
  1975 + String desc2;
  1976 + auto size = size_t{ 0 };
  1977 + for (auto c = std::begin(desc); c != std::end(desc); ++c)
1962 { 1978 {
1963 - if(!o.default_value.empty()) 1979 + if (*c == '\n')
1964 { 1980 {
1965 - desc += toLocalString(" (default: " + o.default_value + ")"); 1981 + desc2 += *c;
  1982 + size = 0;
1966 } 1983 }
1967 - else 1984 + else if (*c == '\t')
1968 { 1985 {
1969 - desc += toLocalString(" (default: \"\")"); 1986 + auto skip = 8 - size % 8;
  1987 + stringAppend(desc2, skip, ' ');
  1988 + size += skip;
1970 } 1989 }
1971 - }  
1972 -  
1973 - String result;  
1974 -  
1975 - if (tab_expansion)  
1976 - {  
1977 - String desc2;  
1978 - auto size = size_t{ 0 };  
1979 - for (auto c = std::begin(desc); c != std::end(desc); ++c) 1990 + else
1980 { 1991 {
1981 - if (*c == '\n')  
1982 - {  
1983 - desc2 += *c;  
1984 - size = 0;  
1985 - }  
1986 - else if (*c == '\t')  
1987 - {  
1988 - auto skip = 8 - size % 8;  
1989 - stringAppend(desc2, skip, ' ');  
1990 - size += skip;  
1991 - }  
1992 - else  
1993 - {  
1994 - desc2 += *c;  
1995 - ++size;  
1996 - } 1992 + desc2 += *c;
  1993 + ++size;
1997 } 1994 }
1998 - desc = desc2;  
1999 } 1995 }
  1996 + desc = desc2;
  1997 + }
2000 1998
2001 - desc += " "; 1999 + desc += " ";
2002 2000
2003 - auto current = std::begin(desc);  
2004 - auto previous = current;  
2005 - auto startLine = current;  
2006 - auto lastSpace = current; 2001 + auto current = std::begin(desc);
  2002 + auto previous = current;
  2003 + auto startLine = current;
  2004 + auto lastSpace = current;
2007 2005
2008 - auto size = size_t{}; 2006 + auto size = size_t{};
2009 2007
2010 - bool appendNewLine;  
2011 - bool onlyWhiteSpace = true; 2008 + bool appendNewLine;
  2009 + bool onlyWhiteSpace = true;
2012 2010
2013 - while (current != std::end(desc)) 2011 + while (current != std::end(desc))
  2012 + {
  2013 + appendNewLine = false;
  2014 +
  2015 + if (std::isblank(*previous))
2014 { 2016 {
2015 - appendNewLine = false; 2017 + lastSpace = current;
  2018 + }
2016 2019
2017 - if (std::isblank(*previous))  
2018 - {  
2019 - lastSpace = current;  
2020 - } 2020 + if (!std::isblank(*current))
  2021 + {
  2022 + onlyWhiteSpace = false;
  2023 + }
2021 2024
2022 - if (!std::isblank(*current))  
2023 - {  
2024 - onlyWhiteSpace = false;  
2025 - } 2025 + while (*current == '\n')
  2026 + {
  2027 + previous = current;
  2028 + ++current;
  2029 + appendNewLine = true;
  2030 + }
2026 2031
2027 - while (*current == '\n') 2032 + if (!appendNewLine && size >= allowed)
  2033 + {
  2034 + if (lastSpace != startLine)
2028 { 2035 {
  2036 + current = lastSpace;
2029 previous = current; 2037 previous = current;
2030 - ++current;  
2031 - appendNewLine = true;  
2032 } 2038 }
  2039 + appendNewLine = true;
  2040 + }
2033 2041
2034 - if (!appendNewLine && size >= allowed)  
2035 - {  
2036 - if (lastSpace != startLine)  
2037 - {  
2038 - current = lastSpace;  
2039 - previous = current;  
2040 - }  
2041 - appendNewLine = true;  
2042 - } 2042 + if (appendNewLine)
  2043 + {
  2044 + stringAppend(result, startLine, current);
  2045 + startLine = current;
  2046 + lastSpace = current;
2043 2047
2044 - if (appendNewLine) 2048 + if (*previous != '\n')
2045 { 2049 {
2046 - stringAppend(result, startLine, current);  
2047 - startLine = current;  
2048 - lastSpace = current;  
2049 -  
2050 - if (*previous != '\n')  
2051 - {  
2052 - stringAppend(result, "\n");  
2053 - }  
2054 -  
2055 - stringAppend(result, start, ' '); 2050 + stringAppend(result, "\n");
  2051 + }
2056 2052
2057 - if (*previous != '\n')  
2058 - {  
2059 - stringAppend(result, lastSpace, current);  
2060 - } 2053 + stringAppend(result, start, ' ');
2061 2054
2062 - onlyWhiteSpace = true;  
2063 - size = 0; 2055 + if (*previous != '\n')
  2056 + {
  2057 + stringAppend(result, lastSpace, current);
2064 } 2058 }
2065 2059
2066 - previous = current;  
2067 - ++current;  
2068 - ++size; 2060 + onlyWhiteSpace = true;
  2061 + size = 0;
2069 } 2062 }
2070 2063
2071 - //append whatever is left but ignore whitespace  
2072 - if (!onlyWhiteSpace)  
2073 - {  
2074 - stringAppend(result, startLine, previous);  
2075 - } 2064 + previous = current;
  2065 + ++current;
  2066 + ++size;
  2067 + }
2076 2068
2077 - return result; 2069 + //append whatever is left but ignore whitespace
  2070 + if (!onlyWhiteSpace)
  2071 + {
  2072 + stringAppend(result, startLine, previous);
2078 } 2073 }
  2074 +
  2075 + return result;
  2076 +}
  2077 +
2079 } // namespace 2078 } // namespace
2080 2079
2081 inline 2080 inline
@@ -2115,11 +2114,11 @@ OptionAdder::operator() @@ -2115,11 +2114,11 @@ OptionAdder::operator()
2115 2114
2116 if (!short_sw.length() && !long_sw.length()) 2115 if (!short_sw.length() && !long_sw.length())
2117 { 2116 {
2118 - throw_or_mimic<invalid_option_format_error>(opts); 2117 + throw_or_mimic<exceptions::invalid_option_format>(opts);
2119 } 2118 }
2120 else if (long_sw.length() == 1 && short_sw.length()) 2119 else if (long_sw.length() == 1 && short_sw.length())
2121 { 2120 {
2122 - throw_or_mimic<invalid_option_format_error>(opts); 2121 + throw_or_mimic<exceptions::invalid_option_format>(opts);
2123 } 2122 }
2124 2123
2125 auto option_names = [] 2124 auto option_names = []
@@ -2201,7 +2200,7 @@ OptionParser::checked_parse_arg @@ -2201,7 +2200,7 @@ OptionParser::checked_parse_arg
2201 } 2200 }
2202 else 2201 else
2203 { 2202 {
2204 - throw_or_mimic<missing_argument_exception>(name); 2203 + throw_or_mimic<exceptions::missing_argument>(name);
2205 } 2204 }
2206 } 2205 }
2207 else 2206 else
@@ -2249,7 +2248,7 @@ OptionParser::consume_positional(const std::string&amp; a, PositionalListIterator&amp; n @@ -2249,7 +2248,7 @@ OptionParser::consume_positional(const std::string&amp; a, PositionalListIterator&amp; n
2249 add_to_option(iter, *next, a); 2248 add_to_option(iter, *next, a);
2250 return true; 2249 return true;
2251 } 2250 }
2252 - throw_or_mimic<option_not_exists_exception>(*next); 2251 + throw_or_mimic<exceptions::no_such_option>(*next);
2253 } 2252 }
2254 2253
2255 return false; 2254 return false;
@@ -2315,7 +2314,7 @@ OptionParser::parse(int argc, const char* const* argv) @@ -2315,7 +2314,7 @@ OptionParser::parse(int argc, const char* const* argv)
2315 // but if it starts with a `-`, then it's an error 2314 // but if it starts with a `-`, then it's an error
2316 if (argv[current][0] == '-' && argv[current][1] != '\0') { 2315 if (argv[current][0] == '-' && argv[current][1] != '\0') {
2317 if (!m_allow_unrecognised) { 2316 if (!m_allow_unrecognised) {
2318 - throw_or_mimic<option_syntax_exception>(argv[current]); 2317 + throw_or_mimic<exceptions::invalid_option_syntax>(argv[current]);
2319 } 2318 }
2320 } 2319 }
2321 2320
@@ -2350,7 +2349,7 @@ OptionParser::parse(int argc, const char* const* argv) @@ -2350,7 +2349,7 @@ OptionParser::parse(int argc, const char* const* argv)
2350 continue; 2349 continue;
2351 } 2350 }
2352 //error 2351 //error
2353 - throw_or_mimic<option_not_exists_exception>(name); 2352 + throw_or_mimic<exceptions::no_such_option>(name);
2354 } 2353 }
2355 2354
2356 auto value = iter->second; 2355 auto value = iter->second;
@@ -2373,7 +2372,7 @@ OptionParser::parse(int argc, const char* const* argv) @@ -2373,7 +2372,7 @@ OptionParser::parse(int argc, const char* const* argv)
2373 else 2372 else
2374 { 2373 {
2375 //error 2374 //error
2376 - throw_or_mimic<option_requires_argument_exception>(name); 2375 + throw_or_mimic<exceptions::option_requires_argument>(name);
2377 } 2376 }
2378 } 2377 }
2379 } 2378 }
@@ -2393,7 +2392,7 @@ OptionParser::parse(int argc, const char* const* argv) @@ -2393,7 +2392,7 @@ OptionParser::parse(int argc, const char* const* argv)
2393 continue; 2392 continue;
2394 } 2393 }
2395 //error 2394 //error
2396 - throw_or_mimic<option_not_exists_exception>(name); 2395 + throw_or_mimic<exceptions::no_such_option>(name);
2397 } 2396 }
2398 2397
2399 auto opt = iter->second; 2398 auto opt = iter->second;
@@ -2531,7 +2530,7 @@ Options::add_one_option @@ -2531,7 +2530,7 @@ Options::add_one_option
2531 2530
2532 if (!in.second) 2531 if (!in.second)
2533 { 2532 {
2534 - throw_or_mimic<option_exists_error>(option); 2533 + throw_or_mimic<exceptions::option_already_exists>(option);
2535 } 2534 }
2536 } 2535 }
2537 2536
src/example.cpp
@@ -182,7 +182,7 @@ parse(int argc, const char* argv[]) @@ -182,7 +182,7 @@ parse(int argc, const char* argv[])
182 } 182 }
183 std::cout << std::endl; 183 std::cout << std::endl;
184 } 184 }
185 - catch (const cxxopts::OptionException& e) 185 + catch (const cxxopts::exceptions::exception& e)
186 { 186 {
187 std::cout << "error parsing options: " << e.what() << std::endl; 187 std::cout << "error parsing options: " << e.what() << std::endl;
188 return false; 188 return false;
test/catch.hpp
@@ -9188,7 +9188,7 @@ namespace Catch { @@ -9188,7 +9188,7 @@ namespace Catch {
9188 // And... Print a result applicable to each result type. 9188 // And... Print a result applicable to each result type.
9189 switch( assertionResult.getResultType() ) { 9189 switch( assertionResult.getResultType() ) {
9190 case ResultWas::ThrewException: 9190 case ResultWas::ThrewException:
9191 - m_xml.scopedElement( "Exception" ) 9191 + m_xml.scopedElement( "exception" )
9192 .writeAttribute( "filename", assertionResult.getSourceInfo().file ) 9192 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9193 .writeAttribute( "line", assertionResult.getSourceInfo().line ) 9193 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9194 .writeText( assertionResult.getMessage() ); 9194 .writeText( assertionResult.getMessage() );
test/options.cpp
@@ -94,7 +94,7 @@ TEST_CASE(&quot;Basic options&quot;, &quot;[options]&quot;) @@ -94,7 +94,7 @@ TEST_CASE(&quot;Basic options&quot;, &quot;[options]&quot;)
94 CHECK(arguments[2].key() == "value"); 94 CHECK(arguments[2].key() == "value");
95 CHECK(arguments[3].key() == "av"); 95 CHECK(arguments[3].key() == "av");
96 96
97 - CHECK_THROWS_AS(result["nothing"].as<std::string>(), cxxopts::option_has_no_value_exception&); 97 + CHECK_THROWS_AS(result["nothing"].as<std::string>(), cxxopts::exceptions::option_has_no_value&);
98 98
99 CHECK(options.program() == "tester"); 99 CHECK(options.program() == "tester");
100 } 100 }
@@ -122,7 +122,7 @@ TEST_CASE(&quot;Short options&quot;, &quot;[options]&quot;) @@ -122,7 +122,7 @@ TEST_CASE(&quot;Short options&quot;, &quot;[options]&quot;)
122 CHECK(arguments[0].value() == "value"); 122 CHECK(arguments[0].value() == "value");
123 123
124 REQUIRE_THROWS_AS(options.add_options()("", "nothing option"), 124 REQUIRE_THROWS_AS(options.add_options()("", "nothing option"),
125 - cxxopts::invalid_option_format_error&); 125 + cxxopts::exceptions::invalid_option_format&);
126 } 126 }
127 127
128 TEST_CASE("No positional", "[positional]") 128 TEST_CASE("No positional", "[positional]")
@@ -235,7 +235,7 @@ TEST_CASE(&quot;Positional not valid&quot;, &quot;[positional]&quot;) { @@ -235,7 +235,7 @@ TEST_CASE(&quot;Positional not valid&quot;, &quot;[positional]&quot;) {
235 auto** argv = av.argv(); 235 auto** argv = av.argv();
236 auto argc = av.argc(); 236 auto argc = av.argc();
237 237
238 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&); 238 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
239 } 239 }
240 240
241 TEST_CASE("Positional with empty arguments", "[positional]") { 241 TEST_CASE("Positional with empty arguments", "[positional]") {
@@ -294,7 +294,7 @@ TEST_CASE(&quot;Boolean without implicit value&quot;, &quot;[implicit]&quot;) @@ -294,7 +294,7 @@ TEST_CASE(&quot;Boolean without implicit value&quot;, &quot;[implicit]&quot;)
294 auto** argv = av.argv(); 294 auto** argv = av.argv();
295 auto argc = av.argc(); 295 auto argc = av.argc();
296 296
297 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::missing_argument_exception&); 297 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::missing_argument&);
298 } 298 }
299 299
300 SECTION("With equal-separated true") { 300 SECTION("With equal-separated true") {
@@ -460,7 +460,7 @@ TEST_CASE(&quot;Unsigned integers&quot;, &quot;[options]&quot;) @@ -460,7 +460,7 @@ TEST_CASE(&quot;Unsigned integers&quot;, &quot;[options]&quot;)
460 auto argc = av.argc(); 460 auto argc = av.argc();
461 461
462 options.parse_positional("positional"); 462 options.parse_positional("positional");
463 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&); 463 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
464 } 464 }
465 465
466 TEST_CASE("Integer bounds", "[integer]") 466 TEST_CASE("Integer bounds", "[integer]")
@@ -497,12 +497,12 @@ TEST_CASE(&quot;Overflow on boundary&quot;, &quot;[integer]&quot;) @@ -497,12 +497,12 @@ TEST_CASE(&quot;Overflow on boundary&quot;, &quot;[integer]&quot;)
497 int8_t si; 497 int8_t si;
498 uint8_t ui; 498 uint8_t ui;
499 499
500 - CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::argument_incorrect_type&);  
501 - CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::argument_incorrect_type&);  
502 - CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::argument_incorrect_type&);  
503 - CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::argument_incorrect_type&);  
504 - CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::argument_incorrect_type&);  
505 - CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::argument_incorrect_type&); 500 + CHECK_THROWS_AS((integer_parser("128", si)), cxxopts::exceptions::incorrect_argument_type&);
  501 + CHECK_THROWS_AS((integer_parser("-129", si)), cxxopts::exceptions::incorrect_argument_type&);
  502 + CHECK_THROWS_AS((integer_parser("256", ui)), cxxopts::exceptions::incorrect_argument_type&);
  503 + CHECK_THROWS_AS((integer_parser("-0x81", si)), cxxopts::exceptions::incorrect_argument_type&);
  504 + CHECK_THROWS_AS((integer_parser("0x80", si)), cxxopts::exceptions::incorrect_argument_type&);
  505 + CHECK_THROWS_AS((integer_parser("0x100", ui)), cxxopts::exceptions::incorrect_argument_type&);
506 } 506 }
507 507
508 TEST_CASE("Integer overflow", "[options]") 508 TEST_CASE("Integer overflow", "[options]")
@@ -519,11 +519,11 @@ TEST_CASE(&quot;Integer overflow&quot;, &quot;[options]&quot;) @@ -519,11 +519,11 @@ TEST_CASE(&quot;Integer overflow&quot;, &quot;[options]&quot;)
519 auto argc = av.argc(); 519 auto argc = av.argc();
520 520
521 options.parse_positional("positional"); 521 options.parse_positional("positional");
522 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&); 522 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
523 523
524 int integer = 0; 524 int integer = 0;
525 - CHECK_THROWS_AS((integer_parser("23423423423", integer)), cxxopts::argument_incorrect_type&);  
526 - CHECK_THROWS_AS((integer_parser("234234234234", integer)), cxxopts::argument_incorrect_type&); 525 + CHECK_THROWS_AS((integer_parser("23423423423", integer)), cxxopts::exceptions::incorrect_argument_type&);
  526 + CHECK_THROWS_AS((integer_parser("234234234234", integer)), cxxopts::exceptions::incorrect_argument_type&);
527 } 527 }
528 528
529 TEST_CASE("Floats", "[options]") 529 TEST_CASE("Floats", "[options]")
@@ -564,7 +564,7 @@ TEST_CASE(&quot;Invalid integers&quot;, &quot;[integer]&quot;) { @@ -564,7 +564,7 @@ TEST_CASE(&quot;Invalid integers&quot;, &quot;[integer]&quot;) {
564 auto argc = av.argc(); 564 auto argc = av.argc();
565 565
566 options.parse_positional("positional"); 566 options.parse_positional("positional");
567 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type&); 567 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::incorrect_argument_type&);
568 } 568 }
569 569
570 TEST_CASE("Booleans", "[boolean]") { 570 TEST_CASE("Booleans", "[boolean]") {
@@ -670,7 +670,7 @@ TEST_CASE(&quot;Unrecognised options&quot;, &quot;[options]&quot;) { @@ -670,7 +670,7 @@ TEST_CASE(&quot;Unrecognised options&quot;, &quot;[options]&quot;) {
670 auto argc = av.argc(); 670 auto argc = av.argc();
671 671
672 SECTION("Default behaviour") { 672 SECTION("Default behaviour") {
673 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&); 673 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
674 } 674 }
675 675
676 SECTION("After allowing unrecognised options") { 676 SECTION("After allowing unrecognised options") {
@@ -697,7 +697,7 @@ TEST_CASE(&quot;Allow bad short syntax&quot;, &quot;[options]&quot;) { @@ -697,7 +697,7 @@ TEST_CASE(&quot;Allow bad short syntax&quot;, &quot;[options]&quot;) {
697 auto argc = av.argc(); 697 auto argc = av.argc();
698 698
699 SECTION("Default behaviour") { 699 SECTION("Default behaviour") {
700 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&); 700 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::invalid_option_syntax&);
701 } 701 }
702 702
703 SECTION("After allowing unrecognised options") { 703 SECTION("After allowing unrecognised options") {
@@ -720,7 +720,7 @@ TEST_CASE(&quot;Invalid option syntax&quot;, &quot;[options]&quot;) { @@ -720,7 +720,7 @@ TEST_CASE(&quot;Invalid option syntax&quot;, &quot;[options]&quot;) {
720 auto argc = av.argc(); 720 auto argc = av.argc();
721 721
722 SECTION("Default behaviour") { 722 SECTION("Default behaviour") {
723 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&); 723 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::invalid_option_syntax&);
724 } 724 }
725 } 725 }
726 726
@@ -739,7 +739,7 @@ TEST_CASE(&quot;Options empty&quot;, &quot;[options]&quot;) { @@ -739,7 +739,7 @@ TEST_CASE(&quot;Options empty&quot;, &quot;[options]&quot;) {
739 auto** argv = argv_.argv(); 739 auto** argv = argv_.argv();
740 740
741 CHECK(options.groups().empty()); 741 CHECK(options.groups().empty());
742 - CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&); 742 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::exceptions::no_such_option&);
743 } 743 }
744 744
745 TEST_CASE("Initializer list with group", "[options]") { 745 TEST_CASE("Initializer list with group", "[options]") {