Bump cxxopts from 2.2.0 to 2.2.1 (#602)
authorChristian Menges <christian.menges@tum.de>
Sun, 9 May 2021 09:00:57 +0000 (11:00 +0200)
committerGitHub <noreply@github.com>
Sun, 9 May 2021 09:00:57 +0000 (10:00 +0100)
example/cxxopts.hpp

index 6fd170d095cdd022db43fff2665e0008bea623cb..80b695a95582c970d6a3f9271758637840e0cd16 100644 (file)
@@ -29,6 +29,7 @@ THE SOFTWARE.
 #include <cctype>
 #include <exception>
 #include <iostream>
+#include <limits>
 #include <map>
 #include <memory>
 #include <regex>
@@ -43,9 +44,13 @@ THE SOFTWARE.
 #define CXXOPTS_HAS_OPTIONAL
 #endif
 
+#ifndef CXXOPTS_VECTOR_DELIMITER
+#define CXXOPTS_VECTOR_DELIMITER ','
+#endif
+
 #define CXXOPTS__VERSION_MAJOR 2
 #define CXXOPTS__VERSION_MINOR 2
-#define CXXOPTS__VERSION_PATCH 0
+#define CXXOPTS__VERSION_PATCH 1
 
 namespace cxxopts
 {
@@ -309,6 +314,9 @@ namespace cxxopts
     virtual std::shared_ptr<Value>
     implicit_value(const std::string& value) = 0;
 
+    virtual std::shared_ptr<Value>
+    no_implicit_value() = 0;
+
     virtual bool
     is_boolean() const = 0;
   };
@@ -354,7 +362,7 @@ namespace cxxopts
   {
     public:
     option_exists_error(const std::string& option)
-    : OptionSpecException(u8"Option " + LQUOTE + option + RQUOTE + u8" already exists")
+    : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists")
     {
     }
   };
@@ -363,7 +371,7 @@ namespace cxxopts
   {
     public:
     invalid_option_format_error(const std::string& format)
-    : OptionSpecException(u8"Invalid option format " + LQUOTE + format + RQUOTE)
+    : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE)
     {
     }
   };
@@ -371,8 +379,8 @@ namespace cxxopts
   class option_syntax_exception : public OptionParseException {
     public:
     option_syntax_exception(const std::string& text)
-    : OptionParseException(u8"Argument " + LQUOTE + text + RQUOTE +
-        u8" starts with a - but has incorrect syntax")
+    : OptionParseException("Argument " + LQUOTE + text + RQUOTE +
+        " starts with a - but has incorrect syntax")
     {
     }
   };
@@ -381,7 +389,7 @@ namespace cxxopts
   {
     public:
     option_not_exists_exception(const std::string& option)
-    : OptionParseException(u8"Option " + LQUOTE + option + RQUOTE + u8" does not exist")
+    : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist")
     {
     }
   };
@@ -391,7 +399,7 @@ namespace cxxopts
     public:
     missing_argument_exception(const std::string& option)
     : OptionParseException(
-        u8"Option " + LQUOTE + option + RQUOTE + u8" is missing an argument"
+        "Option " + LQUOTE + option + RQUOTE + " is missing an argument"
       )
     {
     }
@@ -402,7 +410,7 @@ namespace cxxopts
     public:
     option_requires_argument_exception(const std::string& option)
     : OptionParseException(
-        u8"Option " + LQUOTE + option + RQUOTE + u8" requires an argument"
+        "Option " + LQUOTE + option + RQUOTE + " requires an argument"
       )
     {
     }
@@ -417,8 +425,8 @@ namespace cxxopts
       const std::string& arg
     )
     : OptionParseException(
-        u8"Option " + LQUOTE + option + RQUOTE +
-        u8" does not take an argument, but argument " +
+        "Option " + LQUOTE + option + RQUOTE +
+        " does not take an argument, but argument " +
         LQUOTE + arg + RQUOTE + " given"
       )
     {
@@ -429,7 +437,7 @@ namespace cxxopts
   {
     public:
     option_not_present_exception(const std::string& option)
-    : OptionParseException(u8"Option " + LQUOTE + option + RQUOTE + u8" not present")
+    : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present")
     {
     }
   };
@@ -442,7 +450,7 @@ namespace cxxopts
       const std::string& arg
     )
     : OptionParseException(
-        u8"Argument " + LQUOTE + arg + RQUOTE + u8" failed to parse"
+        "Argument " + LQUOTE + arg + RQUOTE + " failed to parse"
       )
     {
     }
@@ -453,7 +461,7 @@ namespace cxxopts
     public:
     option_required_exception(const std::string& option)
     : OptionParseException(
-        u8"Option " + LQUOTE + option + RQUOTE + u8" is required but not present"
+        "Option " + LQUOTE + option + RQUOTE + " is required but not present"
       )
     {
     }
@@ -466,9 +474,9 @@ namespace cxxopts
       std::basic_regex<char> integer_pattern
         ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)");
       std::basic_regex<char> truthy_pattern
-        ("(t|T)(rue)?");
+        ("(t|T)(rue)?|1");
       std::basic_regex<char> falsy_pattern
-        ("((f|F)(alse)?)?");
+        ("(f|F)(alse)?|0");
     }
 
     namespace detail
@@ -485,14 +493,14 @@ namespace cxxopts
         {
           if (negative)
           {
-            if (u > static_cast<U>(-std::numeric_limits<T>::min()))
+            if (u > static_cast<U>((std::numeric_limits<T>::min)()))
             {
               throw argument_incorrect_type(text);
             }
           }
           else
           {
-            if (u > static_cast<U>(std::numeric_limits<T>::max()))
+            if (u > static_cast<U>((std::numeric_limits<T>::max)()))
             {
               throw argument_incorrect_type(text);
             }
@@ -523,7 +531,7 @@ namespace cxxopts
       // if we got to here, then `t` is a positive number that fits into
       // `R`. So to avoid MSVC C4146, we first cast it to `R`.
       // See https://github.com/jarro2783/cxxopts/issues/62 for more details.
-      return -static_cast<R>(t);
+      return -static_cast<R>(t-1)-1;
     }
 
     template <typename R, typename T>
@@ -553,7 +561,6 @@ namespace cxxopts
 
       using US = typename std::make_unsigned<T>::type;
 
-      constexpr auto umax = std::numeric_limits<US>::max();
       constexpr bool is_signed = std::numeric_limits<T>::is_signed;
       const bool negative = match.length(1) > 0;
       const uint8_t base = match.length(2) > 0 ? 16 : 10;
@@ -568,27 +575,28 @@ namespace cxxopts
 
         if (*iter >= '0' && *iter <= '9')
         {
-          digit = *iter - '0';
+          digit = static_cast<US>(*iter - '0');
         }
         else if (base == 16 && *iter >= 'a' && *iter <= 'f')
         {
-          digit = *iter - 'a' + 10;
+          digit = static_cast<US>(*iter - 'a' + 10);
         }
         else if (base == 16 && *iter >= 'A' && *iter <= 'F')
         {
-          digit = *iter - 'A' + 10;
+          digit = static_cast<US>(*iter - 'A' + 10);
         }
         else
         {
           throw argument_incorrect_type(text);
         }
 
-        if (umax - digit < result * base)
+        US next = result * base + digit;
+        if (result > next)
         {
           throw argument_incorrect_type(text);
         }
 
-        result = result * base + digit;
+        result = next;
       }
 
       detail::check_signed_range<T>(negative, result, text);
@@ -601,7 +609,7 @@ namespace cxxopts
       }
       else
       {
-        value = result;
+        value = static_cast<T>(result);
       }
     }
 
@@ -714,9 +722,13 @@ namespace cxxopts
     void
     parse_value(const std::string& text, std::vector<T>& value)
     {
-      T v;
-      parse_value(text, v);
-      value.push_back(v);
+      std::stringstream in(text);
+      std::string token;
+      while(in.eof() == false && std::getline(in, token, CXXOPTS_VECTOR_DELIMITER)) {
+        T v;
+        parse_value(token, v);
+        value.emplace_back(std::move(v));
+      }
     }
 
 #ifdef CXXOPTS_HAS_OPTIONAL
@@ -825,6 +837,13 @@ namespace cxxopts
         return shared_from_this();
       }
 
+      std::shared_ptr<Value>
+      no_implicit_value()
+      {
+        m_implicit = false;
+        return shared_from_this();
+      }
+
       std::string
       get_default_value() const
       {
@@ -1035,19 +1054,31 @@ namespace cxxopts
     parse_default(std::shared_ptr<const OptionDetails> details)
     {
       ensure_value(details);
+      m_default = true;
       m_value->parse();
     }
 
     size_t
-    count() const
+    count() const noexcept
     {
       return m_count;
     }
 
+    // TODO: maybe default options should count towards the number of arguments
+    bool
+    has_default() const noexcept
+    {
+      return m_default;
+    }
+
     template <typename T>
     const T&
     as() const
     {
+      if (m_value == nullptr) {
+        throw std::domain_error("No value");
+      }
+
 #ifdef CXXOPTS_NO_RTTI
       return static_cast<const values::standard_value<T>&>(*m_value).get();
 #else
@@ -1067,6 +1098,7 @@ namespace cxxopts
 
     std::shared_ptr<Value> m_value;
     size_t m_count = 0;
+    bool m_default = false;
   };
 
   class KeyValue
@@ -1085,7 +1117,8 @@ namespace cxxopts
       return m_key;
     }
 
-    const std::string
+    const
+    std::string&
     value() const
     {
       return m_value;
@@ -1277,7 +1310,7 @@ namespace cxxopts
     }
 
     std::string
-    help(const std::vector<std::string>& groups = {""}) const;
+    help(const std::vector<std::string>& groups = {}) const;
 
     const std::vector<std::string>
     groups() const;
@@ -1451,6 +1484,7 @@ namespace cxxopts
             stringAppend(result, "\n");
             stringAppend(result, start, ' ');
             startLine = lastSpace + 1;
+            lastSpace = startLine;
           }
           size = 0;
         }
@@ -1654,7 +1688,10 @@ ParseResult::consume_positional(std::string a)
         return true;
       }
     }
-    ++m_next_positional;
+    else
+    {
+      throw option_not_exists_exception(*m_next_positional);
+    }
   }
 
   return false;
@@ -1719,8 +1756,10 @@ ParseResult::parse(int& argc, char**& argv)
       //not a flag
 
       // but if it starts with a `-`, then it's an error
-      if (argv[current][0] == '-') {
-        throw option_syntax_exception(argv[current]);
+      if (argv[current][0] == '-' && argv[current][1] != '\0') {
+        if (!m_allow_unrecognised) {
+          throw option_syntax_exception(argv[current]);
+        }
       }
 
       //if true is returned here then it was consumed, otherwise it is
@@ -1829,7 +1868,7 @@ ParseResult::parse(int& argc, char**& argv)
 
     auto& store = m_results[detail];
 
-    if(!store.count() && value.has_default()){
+    if(value.has_default() && !store.count() && !store.has_default()){
       parse_default(detail);
     }
   }
@@ -1933,19 +1972,18 @@ Options::help_one_group(const std::string& g) const
 
   for (const auto& o : group->second.options)
   {
-    if (o.is_container &&
-        m_positional_set.find(o.l) != m_positional_set.end() &&
+    if (m_positional_set.find(o.l) != m_positional_set.end() &&
         !m_show_positional)
     {
       continue;
     }
 
     auto s = format_option(o);
-    longest = std::max(longest, stringLength(s));
+    longest = (std::max)(longest, stringLength(s));
     format.push_back(std::make_pair(s, String()));
   }
 
-  longest = std::min(longest, static_cast<size_t>(OPTION_LONGEST));
+  longest = (std::min)(longest, static_cast<size_t>(OPTION_LONGEST));
 
   //widest allowed description
   auto allowed = size_t{76} - longest - OPTION_DESC_GAP;
@@ -1953,8 +1991,7 @@ Options::help_one_group(const std::string& g) const
   auto fiter = format.begin();
   for (const auto& o : group->second.options)
   {
-    if (o.is_container &&
-        m_positional_set.find(o.l) != m_positional_set.end() &&
+    if (m_positional_set.find(o.l) != m_positional_set.end() &&
         !m_show_positional)
     {
       continue;