aboutsummaryrefslogtreecommitdiff
path: root/third-party
diff options
context:
space:
mode:
authorMatthew Sloyan <matthew.sloyan@arm.com>2020-10-06 16:06:07 +0100
committerColm Donelan <colm.donelan@arm.com>2020-10-06 19:38:08 +0000
commit84dc8430432c0a65c2fdc8946e06d307d18df28d (patch)
treec82fd792db0d2549d4c602aff97571915216ccbb /third-party
parentb524ca0303ccaf452c3d59d66fa5cbb12975f4a8 (diff)
downloadarmnn-84dc8430432c0a65c2fdc8946e06d307d18df28d.tar.gz
IVGCVSW-4488 Update cxxopts to version 3.0
* Required to fix issue in TfLiteMobilenetQuantized-Armnn.cpp Signed-off-by: Matthew Sloyan <matthew.sloyan@arm.com> Change-Id: I3a465f62e3d656c9626113da6223e4fa26b535a6
Diffstat (limited to 'third-party')
-rw-r--r--third-party/cxxopts/CHANGELOG.md9
-rw-r--r--third-party/cxxopts/README.md52
-rw-r--r--third-party/cxxopts/cxxopts.hpp429
3 files changed, 322 insertions, 168 deletions
diff --git a/third-party/cxxopts/CHANGELOG.md b/third-party/cxxopts/CHANGELOG.md
index 4bddcff1ff..df0e110995 100644
--- a/third-party/cxxopts/CHANGELOG.md
+++ b/third-party/cxxopts/CHANGELOG.md
@@ -3,7 +3,7 @@
This is the changelog for `cxxopts`, a C++11 library for parsing command line
options. The project adheres to semantic versioning.
-## Next version
+## 3.0
### Changed
@@ -12,6 +12,13 @@ options. The project adheres to semantic versioning.
* Fix duplicate default options when there is a short and long option.
* Add `CXXOPTS_NO_EXCEPTIONS` to disable exceptions.
* Fix char parsing for space and check for length.
+* Change argument type in `Options::parse` from `char**` to `const char**`.
+* Refactor parser to not change its arguments.
+* `ParseResult` doesn't depend on a reference to the parser.
+
+### Added
+
+* A list of unmatched arguments is available in `ParseResult`.
## 2.2
diff --git a/third-party/cxxopts/README.md b/third-party/cxxopts/README.md
index f157052bae..9517993d04 100644
--- a/third-party/cxxopts/README.md
+++ b/third-party/cxxopts/README.md
@@ -5,6 +5,25 @@
Note that `master` is generally a work in progress, and you probably want to use a
tagged release version.
+## Version 3 breaking changes
+
+If you have used version 2, there are a couple of breaking changes in (the as
+yet unreleased, current master) version 3 that you should be aware of. If you are new to
+`cxxopts` you can skip this section.
+
+The parser no longer modifies its arguments, so you can pass a const `argc` and
+`argv` and expect them not to be changed.
+
+The `ParseResult` object no longer depends on the parser. So it can be returned
+from a scope outside the parser and still work. Now that the inputs are not
+modified, `ParseResult` stores a list of the unmatched arguments. These are
+retrieved like follows:
+
+```cpp
+auto result = options.parse(argc, argv);
+result.unmatched(); // get the unmatched arguments
+```
+
# Quick start
This is a lightweight C++ option parser library, supporting the standard GNU
@@ -69,6 +88,23 @@ exception will be thrown.
Note that the result of `options.parse` should only be used as long as the
`options` object that created it is in scope.
+## Unrecognised arguments
+
+You can allow unrecognised arguments to be skipped. This applies to both
+positional arguments that are not parsed into another option, and `--`
+arguments that do not match an argument that you specify. This is done by
+calling:
+
+```cpp
+options.allow_unrecognised_options();
+```
+
+and in the result object they are retrieved with:
+
+```cpp
+result.unmatched()
+```
+
## Exceptions
Exceptional situations throw C++ exceptions. There are two types of
@@ -146,6 +182,22 @@ that can be parsed as a `std::vector<double>`:
--my_list=1,-2.1,3,4.5
~~~
+## Options specified multiple times
+
+The same option can be specified several times, with different arguments, which will all
+be recorded in order of appearance. An example:
+
+~~~
+--use train --use bus --use ferry
+~~~
+
+this is supported through the use of a vector of value for the option:
+
+~~~
+options.add_options()
+ ("use", "Usable means of transport", cxxopts::value<std::vector<std::string>>())
+~~~
+
## Custom help
The string after the program name on the first line of the help can be
diff --git a/third-party/cxxopts/cxxopts.hpp b/third-party/cxxopts/cxxopts.hpp
index 97381a96d4..88e8a020df 100644
--- a/third-party/cxxopts/cxxopts.hpp
+++ b/third-party/cxxopts/cxxopts.hpp
@@ -30,6 +30,7 @@ THE SOFTWARE.
#include <exception>
#include <iostream>
#include <limits>
+#include <list>
#include <map>
#include <memory>
#include <regex>
@@ -45,12 +46,18 @@ THE SOFTWARE.
#define CXXOPTS_HAS_OPTIONAL
#endif
+#if __cplusplus >= 201603L
+#define CXXOPTS_NODISCARD [[nodiscard]]
+#else
+#define CXXOPTS_NODISCARD
+#endif
+
#ifndef CXXOPTS_VECTOR_DELIMITER
#define CXXOPTS_VECTOR_DELIMITER ','
#endif
-#define CXXOPTS__VERSION_MAJOR 2
-#define CXXOPTS__VERSION_MINOR 2
+#define CXXOPTS__VERSION_MAJOR 3
+#define CXXOPTS__VERSION_MINOR 0
#define CXXOPTS__VERSION_PATCH 0
namespace cxxopts
@@ -140,9 +147,9 @@ namespace cxxopts
inline
String&
- stringAppend(String& s, int n, UChar32 c)
+ stringAppend(String& s, size_t n, UChar32 c)
{
- for (int i = 0; i != n; ++i)
+ for (size_t i = 0; i != n; ++i)
{
s.append(c);
}
@@ -278,6 +285,13 @@ namespace cxxopts
#endif
} // namespace
+#if defined(__GNUC__)
+// GNU GCC with -Weffc++ will issue a warning regarding the upcoming class, we want to silence it:
+// warning: base class 'class std::enable_shared_from_this<cxxopts::Value>' has accessible non-virtual destructor
+#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
+#pragma GCC diagnostic push
+// This will be ignored under other compilers like LLVM clang.
+#endif
class Value : public std::enable_shared_from_this<Value>
{
public:
@@ -321,7 +335,9 @@ namespace cxxopts
virtual bool
is_boolean() const = 0;
};
-
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
class OptionException : public std::exception
{
public:
@@ -330,6 +346,7 @@ namespace cxxopts
{
}
+ CXXOPTS_NODISCARD
const char*
what() const noexcept override
{
@@ -443,6 +460,18 @@ namespace cxxopts
}
};
+ class option_has_no_value_exception : public OptionException
+ {
+ public:
+ explicit option_has_no_value_exception(const std::string& option)
+ : OptionException(
+ option.empty() ?
+ ("Option " + LQUOTE + option + RQUOTE + " has no value") :
+ "Option has no value")
+ {
+ }
+ };
+
class argument_incorrect_type : public OptionParseException
{
public:
@@ -545,21 +574,20 @@ namespace cxxopts
} // namespace detail
template <typename R, typename T>
- R
- checked_negate(T&& t, const std::string&, std::true_type)
+ void
+ checked_negate(R& r, T&& t, const std::string&, std::true_type)
{
// 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>(-static_cast<R>(t-1)-1);
+ r = static_cast<R>(-static_cast<R>(t-1)-1);
}
template <typename R, typename T>
- T
- checked_negate(T&& t, const std::string& text, std::false_type)
+ void
+ checked_negate(R&, T&&, const std::string& text, std::false_type)
{
throw_or_mimic<argument_incorrect_type>(text);
- return t;
}
template <typename T>
@@ -624,9 +652,7 @@ namespace cxxopts
if (negative)
{
- value = checked_negate<T>(result,
- text,
- std::integral_constant<bool, is_signed>());
+ checked_negate<T>(value, result, text, std::integral_constant<bool, is_signed>());
}
else
{
@@ -805,6 +831,8 @@ namespace cxxopts
~abstract_value() override = default;
+ abstract_value& operator=(const abstract_value&) = default;
+
abstract_value(const abstract_value& rhs)
{
if (rhs.m_result)
@@ -905,14 +933,14 @@ namespace cxxopts
}
protected:
- std::shared_ptr<T> m_result;
- T* m_store;
+ std::shared_ptr<T> m_result{};
+ T* m_store{};
bool m_default = false;
bool m_implicit = false;
- std::string m_default_value;
- std::string m_implicit_value;
+ std::string m_default_value{};
+ std::string m_implicit_value{};
};
template <typename T>
@@ -921,6 +949,7 @@ namespace cxxopts
public:
using abstract_value<T>::abstract_value;
+ CXXOPTS_NODISCARD
std::shared_ptr<Value>
clone() const
{
@@ -996,6 +1025,7 @@ namespace cxxopts
, m_value(std::move(val))
, m_count(0)
{
+ m_hash = std::hash<std::string>{}(m_long + m_short);
}
OptionDetails(const OptionDetails& rhs)
@@ -1007,40 +1037,54 @@ namespace cxxopts
OptionDetails(OptionDetails&& rhs) = default;
+ CXXOPTS_NODISCARD
const String&
description() const
{
return m_desc;
}
- const Value& value() const {
+ CXXOPTS_NODISCARD
+ const Value&
+ value() const {
return *m_value;
}
+ CXXOPTS_NODISCARD
std::shared_ptr<Value>
make_storage() const
{
return m_value->clone();
}
+ CXXOPTS_NODISCARD
const std::string&
short_name() const
{
return m_short;
}
+ CXXOPTS_NODISCARD
const std::string&
long_name() const
{
return m_long;
}
+ size_t
+ hash() const
+ {
+ return m_hash;
+ }
+
private:
- std::string m_short;
- std::string m_long;
- String m_desc;
- std::shared_ptr<const Value> m_value;
+ std::string m_short{};
+ std::string m_long{};
+ String m_desc{};
+ std::shared_ptr<const Value> m_value{};
int m_count;
+
+ size_t m_hash{};
};
struct HelpOptionDetails
@@ -1059,9 +1103,9 @@ namespace cxxopts
struct HelpGroupDetails
{
- std::string name;
- std::string description;
- std::vector<HelpOptionDetails> options;
+ std::string name{};
+ std::string description{};
+ std::vector<HelpOptionDetails> options{};
};
class OptionValue
@@ -1077,6 +1121,7 @@ namespace cxxopts
ensure_value(details);
++m_count;
m_value->parse(text);
+ m_long_name = &details->long_name();
}
void
@@ -1084,9 +1129,11 @@ namespace cxxopts
{
ensure_value(details);
m_default = true;
+ m_long_name = &details->long_name();
m_value->parse();
}
+ CXXOPTS_NODISCARD
size_t
count() const noexcept
{
@@ -1094,6 +1141,7 @@ namespace cxxopts
}
// TODO: maybe default options should count towards the number of arguments
+ CXXOPTS_NODISCARD
bool
has_default() const noexcept
{
@@ -1105,7 +1153,8 @@ namespace cxxopts
as() const
{
if (m_value == nullptr) {
- throw_or_mimic<std::domain_error>("No value");
+ throw_or_mimic<option_has_no_value_exception>(
+ m_long_name == nullptr ? "" : *m_long_name);
}
#ifdef CXXOPTS_NO_RTTI
@@ -1125,7 +1174,11 @@ namespace cxxopts
}
}
- std::shared_ptr<Value> m_value;
+
+ const std::string* m_long_name = nullptr;
+ // Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
+ // where the key has the string we point to.
+ std::shared_ptr<Value> m_value{};
size_t m_count = 0;
bool m_default = false;
};
@@ -1139,15 +1192,15 @@ namespace cxxopts
{
}
- const
- std::string&
+ CXXOPTS_NODISCARD
+ const std::string&
key() const
{
return m_key;
}
- const
- std::string&
+ CXXOPTS_NODISCARD
+ const std::string&
value() const
{
return m_value;
@@ -1167,45 +1220,65 @@ namespace cxxopts
std::string m_value;
};
+ using ParsedHashMap = std::unordered_map<size_t, OptionValue>;
+ using NameHashMap = std::unordered_map<std::string, size_t>;
+
class ParseResult
{
public:
- ParseResult(
- std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
- >,
- std::vector<std::string>,
- bool allow_unrecognised,
- int&, char**&);
+ ParseResult() {}
+
+ ParseResult(const ParseResult&) = default;
+
+ ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential, std::vector<std::string>&& unmatched_args)
+ : m_keys(std::move(keys))
+ , m_values(std::move(values))
+ , m_sequential(std::move(sequential))
+ , m_unmatched(std::move(unmatched_args))
+ {
+ }
+
+ ParseResult& operator=(ParseResult&&) = default;
+ ParseResult& operator=(const ParseResult&) = default;
size_t
count(const std::string& o) const
{
- auto iter = m_options->find(o);
- if (iter == m_options->end())
+ auto iter = m_keys.find(o);
+ if (iter == m_keys.end())
{
return 0;
}
- auto riter = m_results.find(iter->second);
+ auto viter = m_values.find(iter->second);
+
+ if (viter == m_values.end())
+ {
+ return 0;
+ }
- return riter->second.count();
+ return viter->second.count();
}
const OptionValue&
operator[](const std::string& option) const
{
- auto iter = m_options->find(option);
+ auto iter = m_keys.find(option);
- if (iter == m_options->end())
+ if (iter == m_keys.end())
{
throw_or_mimic<option_not_present_exception>(option);
}
- auto riter = m_results.find(iter->second);
+ auto viter = m_values.find(iter->second);
- return riter->second;
+ if (viter == m_values.end())
+ {
+ throw_or_mimic<option_not_present_exception>(option);
+ }
+
+ return viter->second;
}
const std::vector<KeyValue>&
@@ -1214,49 +1287,17 @@ namespace cxxopts
return m_sequential;
}
- private:
-
- void
- parse(int& argc, char**& argv);
-
- void
- add_to_option(const std::string& option, const std::string& arg);
-
- bool
- consume_positional(const std::string& a);
-
- void
- parse_option
- (
- const std::shared_ptr<OptionDetails>& value,
- const std::string& name,
- const std::string& arg = ""
- );
-
- void
- parse_default(const std::shared_ptr<OptionDetails>& details);
-
- void
- checked_parse_arg
- (
- int argc,
- char* argv[],
- int& current,
- const std::shared_ptr<OptionDetails>& value,
- const std::string& name
- );
-
- const std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
- > m_options;
- std::vector<std::string> m_positional;
- std::vector<std::string>::iterator m_next_positional;
- std::unordered_set<std::string> m_positional_set;
- std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results;
-
- bool m_allow_unrecognised;
+ const std::vector<std::string>&
+ unmatched() const
+ {
+ return m_unmatched;
+ }
- std::vector<KeyValue> m_sequential;
+ private:
+ NameHashMap m_keys{};
+ ParsedHashMap m_values{};
+ std::vector<KeyValue> m_sequential{};
+ std::vector<std::string> m_unmatched{};
};
struct Option
@@ -1281,9 +1322,66 @@ namespace cxxopts
std::string arg_help_;
};
+ using OptionMap = std::unordered_map<std::string, std::shared_ptr<OptionDetails>>;
+ using PositionalList = std::vector<std::string>;
+ using PositionalListIterator = PositionalList::const_iterator;
+
+ class OptionParser
+ {
+ public:
+ OptionParser(const OptionMap& options, const PositionalList& positional, bool allow_unrecognised)
+ : m_options(options)
+ , m_positional(positional)
+ , m_allow_unrecognised(allow_unrecognised)
+ {
+ }
+
+ ParseResult
+ parse(int argc, const char* const* argv);
+
+ bool
+ consume_positional(const std::string& a, PositionalListIterator& next);
+
+ void
+ checked_parse_arg
+ (
+ int argc,
+ const char* const* argv,
+ int& current,
+ const std::shared_ptr<OptionDetails>& value,
+ const std::string& name
+ );
+
+ void
+ add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg);
+
+ void
+ parse_option
+ (
+ const std::shared_ptr<OptionDetails>& value,
+ const std::string& name,
+ const std::string& arg = ""
+ );
+
+ void
+ parse_default(const std::shared_ptr<OptionDetails>& details);
+
+ private:
+
+ void finalise_aliases();
+
+ const OptionMap& m_options;
+ const PositionalList& m_positional;
+
+ std::vector<KeyValue> m_sequential{};
+ bool m_allow_unrecognised;
+
+ ParsedHashMap m_parsed{};
+ NameHashMap m_keys{};
+ };
+
class Options
{
- using OptionMap = std::unordered_map<std::string, std::shared_ptr<OptionDetails>>;
public:
explicit Options(std::string program, std::string help_string = "")
@@ -1294,7 +1392,6 @@ namespace cxxopts
, m_show_positional(false)
, m_allow_unrecognised(false)
, m_options(std::make_shared<OptionMap>())
- , m_next_positional(m_positional.end())
{
}
@@ -1327,7 +1424,7 @@ namespace cxxopts
}
ParseResult
- parse(int& argc, char**& argv);
+ parse(int argc, const char* const* argv);
OptionAdder
add_options(std::string group = "");
@@ -1404,20 +1501,22 @@ namespace cxxopts
void
generate_all_groups_help(String& result) const;
- std::string m_program;
- String m_help_string;
- std::string m_custom_help;
- std::string m_positional_help;
+ std::string m_program{};
+ String m_help_string{};
+ std::string m_custom_help{};
+ std::string m_positional_help{};
bool m_show_positional;
bool m_allow_unrecognised;
std::shared_ptr<OptionMap> m_options;
- std::vector<std::string> m_positional;
- std::vector<std::string>::iterator m_next_positional;
- std::unordered_set<std::string> m_positional_set;
+ std::vector<std::string> m_positional{};
+ std::unordered_set<std::string> m_positional_set{};
//mapping from groups to help options
- std::map<std::string, HelpGroupDetails> m_help;
+ std::map<std::string, HelpGroupDetails> m_help{};
+
+ std::list<OptionDetails> m_option_list{};
+ std::unordered_map<std::string, decltype(m_option_list)::iterator> m_option_map{};
};
class OptionAdder
@@ -1579,24 +1678,6 @@ namespace cxxopts
} // namespace
inline
-ParseResult::ParseResult
-(
- std::shared_ptr<
- std::unordered_map<std::string, std::shared_ptr<OptionDetails>>
- > options,
- std::vector<std::string> positional,
- bool allow_unrecognised,
- int& argc, char**& argv
-)
-: m_options(std::move(options))
-, m_positional(std::move(positional))
-, m_next_positional(m_positional.begin())
-, m_allow_unrecognised(allow_unrecognised)
-{
- parse(argc, argv);
-}
-
-inline
void
Options::add_options
(
@@ -1675,21 +1756,24 @@ OptionAdder::operator()
inline
void
-ParseResult::parse_default(const std::shared_ptr<OptionDetails>& details)
+OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details)
{
- m_results[details].parse_default(details);
+ // TODO: remove the duplicate code here
+ auto& store = m_parsed[details->hash()];
+ store.parse_default(details);
}
inline
void
-ParseResult::parse_option
+OptionParser::parse_option
(
const std::shared_ptr<OptionDetails>& value,
const std::string& /*name*/,
const std::string& arg
)
{
- auto& result = m_results[value];
+ auto hash = value->hash();
+ auto& result = m_parsed[hash];
result.parse(value, arg);
m_sequential.emplace_back(value->long_name(), arg);
@@ -1697,10 +1781,10 @@ ParseResult::parse_option
inline
void
-ParseResult::checked_parse_arg
+OptionParser::checked_parse_arg
(
int argc,
- char* argv[],
+ const char* const* argv,
int& current,
const std::shared_ptr<OptionDetails>& value,
const std::string& name
@@ -1733,43 +1817,36 @@ ParseResult::checked_parse_arg
inline
void
-ParseResult::add_to_option(const std::string& option, const std::string& arg)
+OptionParser::add_to_option(OptionMap::const_iterator iter, const std::string& option, const std::string& arg)
{
- auto iter = m_options->find(option);
-
- if (iter == m_options->end())
- {
- throw_or_mimic<option_not_exists_exception>(option);
- }
-
parse_option(iter->second, option, arg);
}
inline
bool
-ParseResult::consume_positional(const std::string& a)
+OptionParser::consume_positional(const std::string& a, PositionalListIterator& next)
{
- while (m_next_positional != m_positional.end())
+ while (next != m_positional.end())
{
- auto iter = m_options->find(*m_next_positional);
- if (iter != m_options->end())
+ auto iter = m_options.find(*next);
+ if (iter != m_options.end())
{
- auto& result = m_results[iter->second];
+ auto& result = m_parsed[iter->second->hash()];
if (!iter->second->value().is_container())
{
if (result.count() == 0)
{
- add_to_option(*m_next_positional, a);
- ++m_next_positional;
+ add_to_option(iter, *next, a);
+ ++next;
return true;
}
- ++m_next_positional;
+ ++next;
continue;
}
- add_to_option(*m_next_positional, a);
+ add_to_option(iter, *next, a);
return true;
}
- throw_or_mimic<option_not_exists_exception>(*m_next_positional);
+ throw_or_mimic<option_not_exists_exception>(*next);
}
return false;
@@ -1787,7 +1864,6 @@ void
Options::parse_positional(std::vector<std::string> options)
{
m_positional = std::move(options);
- m_next_positional = m_positional.begin();
m_positional_set.insert(m_positional.begin(), m_positional.end());
}
@@ -1801,21 +1877,21 @@ Options::parse_positional(std::initializer_list<std::string> options)
inline
ParseResult
-Options::parse(int& argc, char**& argv)
+Options::parse(int argc, const char* const* argv)
{
- ParseResult result(m_options, m_positional, m_allow_unrecognised, argc, argv);
- return result;
+ OptionParser parser(*m_options, m_positional, m_allow_unrecognised);
+
+ return parser.parse(argc, argv);
}
-inline
-void
-ParseResult::parse(int& argc, char**& argv)
+inline ParseResult
+OptionParser::parse(int argc, const char* const* argv)
{
int current = 1;
-
- int nextKeep = 1;
-
bool consume_remaining = false;
+ PositionalListIterator next_positional = m_positional.begin();
+
+ std::vector<std::string> unmatched;
while (current != argc)
{
@@ -1842,13 +1918,12 @@ ParseResult::parse(int& argc, char**& argv)
//if true is returned here then it was consumed, otherwise it is
//ignored
- if (consume_positional(argv[current]))
+ if (consume_positional(argv[current], next_positional))
{
}
else
{
- argv[nextKeep] = argv[current];
- ++nextKeep;
+ unmatched.push_back(argv[current]);
}
//if we return from here then it was parsed successfully, so continue
}
@@ -1862,9 +1937,9 @@ ParseResult::parse(int& argc, char**& argv)
for (std::size_t i = 0; i != s.size(); ++i)
{
std::string name(1, s[i]);
- auto iter = m_options->find(name);
+ auto iter = m_options.find(name);
- if (iter == m_options->end())
+ if (iter == m_options.end())
{
if (m_allow_unrecognised)
{
@@ -1896,15 +1971,14 @@ ParseResult::parse(int& argc, char**& argv)
{
const std::string& name = result[1];
- auto iter = m_options->find(name);
+ auto iter = m_options.find(name);
- if (iter == m_options->end())
+ if (iter == m_options.end())
{
if (m_allow_unrecognised)
{
// keep unrecognised options in argument list, skip to next argument
- argv[nextKeep] = argv[current];
- ++nextKeep;
+ unmatched.push_back(argv[current]);
++current;
continue;
}
@@ -1933,12 +2007,12 @@ ParseResult::parse(int& argc, char**& argv)
++current;
}
- for (auto& opt : *m_options)
+ for (auto& opt : m_options)
{
auto& detail = opt.second;
const auto& value = detail->value();
- auto& store = m_results[detail];
+ auto& store = m_parsed[detail->hash()];
if(value.has_default() && !store.count() && !store.has_default()){
parse_default(detail);
@@ -1949,7 +2023,7 @@ ParseResult::parse(int& argc, char**& argv)
{
while (current < argc)
{
- if (!consume_positional(argv[current])) {
+ if (!consume_positional(argv[current], next_positional)) {
break;
}
++current;
@@ -1957,14 +2031,30 @@ ParseResult::parse(int& argc, char**& argv)
//adjust argv for any that couldn't be swallowed
while (current != argc) {
- argv[nextKeep] = argv[current];
- ++nextKeep;
+ unmatched.push_back(argv[current]);
++current;
}
}
- argc = nextKeep;
+ finalise_aliases();
+ ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(unmatched));
+ return parsed;
+}
+
+inline
+void
+OptionParser::finalise_aliases()
+{
+ for (auto& option: m_options)
+ {
+ auto& detail = *option.second;
+ auto hash = detail.hash();
+ m_keys[detail.short_name()] = hash;
+ m_keys[detail.long_name()] = hash;
+
+ m_parsed.emplace(hash, OptionValue());
+ }
}
inline
@@ -2003,6 +2093,11 @@ Options::add_option
add_one_option(l, option);
}
+ m_option_list.push_front(*option.get());
+ auto iter = m_option_list.begin();
+ m_option_map[s] = iter;
+ m_option_map[l] = iter;
+
//add the help details
auto& options = m_help[group];