diff --git a/.gitmodules b/.gitmodules index cca396a16..dc334d825 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "external/googletest"] path = external/googletest url = https://github.com/google/googletest.git +[submodule "external/cxxopts"] + path = external/cxxopts + url = https://github.com/jarro2783/cxxopts.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 5590fc545..1891ddc08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,6 +254,7 @@ if(SUBMODULE_CHECK) check_submodule(external/abseil-cpp) check_submodule(external/nlohmann) check_submodule(external/googletest) + check_submodule(external/cxxopts) endif() endif() @@ -270,8 +271,7 @@ endif() add_subdirectory(external/abseil-cpp EXCLUDE_FROM_ALL) set(JSON_BuildTests OFF CACHE INTERNAL "") add_subdirectory(external/nlohmann EXCLUDE_FROM_ALL) - -add_subdirectory(vendor/cxxopts) +add_subdirectory(external/cxxopts) if(ANDROID) list(APPEND LIBS log) diff --git a/external/cxxopts b/external/cxxopts new file mode 160000 index 000000000..6fa46a748 --- /dev/null +++ b/external/cxxopts @@ -0,0 +1 @@ +Subproject commit 6fa46a748838d5544ff8e9ab058906ba2c4bc0f3 diff --git a/vendor/cxxopts/.gitignore b/vendor/cxxopts/.gitignore deleted file mode 100644 index e91cd408c..000000000 --- a/vendor/cxxopts/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.swp -build* -CMakeCache.txt -Makefile -CMakeFiles/ -Testing/ -CTestTestfile.cmake -cmake_install.cmake diff --git a/vendor/cxxopts/.travis.yml b/vendor/cxxopts/.travis.yml deleted file mode 100644 index 87c78a7ea..000000000 --- a/vendor/cxxopts/.travis.yml +++ /dev/null @@ -1,70 +0,0 @@ -sudo: required -dist: trusty -language: cpp -os: - - linux -matrix: - include: - - os: linux - env: COMPILER=g++-4.9 - addons: - apt: - packages: - - g++-4.9 - sources: &sources - - llvm-toolchain-trusty-3.8 - - llvm-toolchain-trusty-5.0 - - ubuntu-toolchain-r-test - - os: linux - env: COMPILER=g++-4.9 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes - addons: - apt: - packages: - - g++-4.9 - sources: *sources - - os: linux - env: COMPILER=g++-5 - addons: - apt: - packages: - - g++-5 - sources: *sources - - os: linux - env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes - addons: - apt: - packages: - - g++-5 - sources: *sources - - os: linux - env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++ - addons: - apt: - packages: - - clang-3.8 - - libc++-dev - sources: *sources - - os: linux - env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++ UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes - addons: - apt: - packages: - - clang-3.8 - - libc++-dev - sources: *sources - - os: linux - env: COMPILER=clang++-5.0 CMAKE_OPTIONS=-DCXXOPTS_CXX_STANDARD=17 - addons: - apt: - packages: - - clang-5.0 - - g++-5 - sources: *sources -script: > - cmake -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER - -DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS $CMAKE_OPTIONS . - && make && make ARGS=--output-on-failure test - -before_install: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install icu4c; fi diff --git a/vendor/cxxopts/CHANGELOG.md b/vendor/cxxopts/CHANGELOG.md deleted file mode 100644 index bd0eed198..000000000 --- a/vendor/cxxopts/CHANGELOG.md +++ /dev/null @@ -1,96 +0,0 @@ -# Changelog - -This is the changelog for `cxxopts`, a C++11 library for parsing command line -options. The project adheres to semantic versioning. - -## Next version - -### Changed - -* Only search for a C++ compiler in CMakeLists.txt. -* Allow for exceptions to be disabled. -* Fix duplicate default options when there is a short and long option. -* Add `CXXOPTS_NO_EXCEPTIONS` to disable exceptions. - -## 2.2 - -### Changed - -* Allow integers to have leading zeroes. -* Build the tests by default. -* Don't check for container when showing positional help. - -### Added - -* Iterator inputs to `parse_positional`. -* Throw an exception if the option in `parse_positional` doesn't exist. -* Parse a delimited list in a single argument for vector options. -* Add an option to disable implicit value on booleans. - -### Bug Fixes - -* Fix a warning about possible loss of data. -* Fix version numbering in CMakeLists.txt -* Remove unused declaration of the undefined `ParseResult::get_option`. -* Throw on invalid option syntax when beginning with a `-`. -* Throw in `as` when option wasn't present. -* Fix catching exceptions by reference. -* Fix out of bounds errors parsing integers. - -## 2.1.1 - -### Bug Fixes - -* Revert the change adding `const` type for `argv`, because most users expect - to pass a non-const `argv` from `main`. - -## 2.1 - -### Changed - -* Options with implicit arguments now require the `--option=value` form if - they are to be specified with an option. This is to remove the ambiguity - when a positional argument could follow an option with an implicit value. - For example, `--foo value`, where `foo` has an implicit value, will be - parsed as `--foo=implicit` and a positional argument `value`. -* Boolean values are no longer special, but are just an option with a default - and implicit value. - -### Added - -* Added support for `std::optional` as a storage type. -* Allow the help string to be customised. -* Use `const` for the type in the `argv` parameter, since the contents of the - arguments is never modified. - -### Bug Fixes - -* Building against GCC 4.9 was broken due to overly strict shadow warnings. -* Fixed an ambiguous overload in the `parse_positional` function when an - `initializer_list` was directly passed. -* Fixed precedence in the Boolean value regex. - -## 2.0 - -### Changed - -* `Options::parse` returns a ParseResult rather than storing the parse - result internally. -* Options with default values now get counted as appearing once if they - were not specified by the user. - -### Added - -* A new `ParseResult` object that is the immutable result of parsing. It - responds to the same `count` and `operator[]` as `Options` of 1.x did. -* The function `ParseResult::arguments` returns a vector of the parsed - arguments to iterate through in the order they were provided. -* The symbol `cxxopts::version` for the version of the library. -* Booleans can be specified with various strings and explicitly set false. - -## 1.x - -The 1.x series was the first major version of the library, with release numbers -starting to follow semantic versioning, after 0.x being unstable. It never had -a changelog maintained for it. Releases mostly contained bug fixes, with the -occasional feature added. diff --git a/vendor/cxxopts/CMakeLists.txt b/vendor/cxxopts/CMakeLists.txt deleted file mode 100644 index 98cc56ccc..000000000 --- a/vendor/cxxopts/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (c) 2014 Jarryd Beck -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -cmake_minimum_required(VERSION 3.1) - -# parse the current version from the cxxopts header -file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/cxxopts.hpp" cxxopts_version_defines - REGEX "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH)") -foreach(ver ${cxxopts_version_defines}) - if(ver MATCHES "#define CXXOPTS__VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") - set(CXXOPTS__VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") - endif() -endforeach() -set(VERSION ${CXXOPTS__VERSION_MAJOR}.${CXXOPTS__VERSION_MINOR}.${CXXOPTS__VERSION_PATCH}) -message(STATUS "cxxopts version ${VERSION}") - -project(cxxopts VERSION "${VERSION}" LANGUAGES CXX) - -enable_testing() - -option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON) -option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" ON) -option(CXXOPTS_ENABLE_INSTALL "Generate the install target" OFF) - -# request c++11 without gnu extension for the whole project and enable more warnings -if (CXXOPTS_CXX_STANDARD) - set(CMAKE_CXX_STANDARD ${CXXOPTS_CXX_STANDARD}) -else() - set(CMAKE_CXX_STANDARD 11) -endif() - -set(CMAKE_CXX_EXTENSIONS OFF) - -if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2") -elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -Wshadow") -endif() - -add_library(cxxopts INTERFACE) -add_library(cxxopts::cxxopts ALIAS cxxopts) - -# optionally, enable unicode support using the ICU library -set(CXXOPTS_USE_UNICODE_HELP FALSE CACHE BOOL "Use ICU Unicode library") -if(CXXOPTS_USE_UNICODE_HELP) - find_package(PkgConfig) - pkg_check_modules(ICU REQUIRED icu-uc) - - target_link_libraries(cxxopts INTERFACE ${ICU_LDFLAGS}) - target_compile_options(cxxopts INTERFACE ${ICU_CFLAGS}) - target_compile_definitions(cxxopts INTERFACE CXXOPTS_USE_UNICODE) -endif() - -target_include_directories(cxxopts INTERFACE - $ - $ - ) - -if(CXXOPTS_ENABLE_INSTALL) - include(CMakePackageConfigHelpers) - set(CXXOPTS_CMAKE_DIR "lib/cmake/cxxopts" CACHE STRING - "Installation directory for cmake files, relative to ${CMAKE_INSTALL_PREFIX}.") - set(version_config "${PROJECT_BINARY_DIR}/cxxopts-config-version.cmake") - set(project_config "${PROJECT_BINARY_DIR}/cxxopts-config.cmake") - set(targets_export_name cxxopts-targets) - - # Generate the version, config and target files into the build directory. - write_basic_package_version_file( - ${version_config} - VERSION ${VERSION} - COMPATIBILITY AnyNewerVersion) - configure_package_config_file( - ${PROJECT_SOURCE_DIR}/cxxopts-config.cmake.in - ${project_config} - INSTALL_DESTINATION ${CXXOPTS_CMAKE_DIR}) - export(TARGETS cxxopts NAMESPACE cxxopts:: - FILE ${PROJECT_BINARY_DIR}/${targets_export_name}.cmake) - - # Install version, config and target files. - install( - FILES ${project_config} ${version_config} - DESTINATION ${CXXOPTS_CMAKE_DIR}) - install(EXPORT ${targets_export_name} DESTINATION ${CXXOPTS_CMAKE_DIR} - NAMESPACE cxxopts::) - - # Install the header file and export the target - install(TARGETS cxxopts EXPORT ${targets_export_name} DESTINATION lib) - install(FILES ${PROJECT_SOURCE_DIR}/include/cxxopts.hpp DESTINATION include) -endif() - -add_subdirectory(src) -add_subdirectory(test) diff --git a/vendor/cxxopts/INSTALL b/vendor/cxxopts/INSTALL deleted file mode 100644 index 3e1c6f3da..000000000 --- a/vendor/cxxopts/INSTALL +++ /dev/null @@ -1,23 +0,0 @@ -== System installation == - -This library is header only. So you can either copy `include/cxxopts.hpp` to `/usr/include` or `/usr/local/include`, or add `include` to your search path. - -== Building the examples and tests == - -It is preferable to build out of source. Make a build directory somewhere, and then -do the following, where `${CXXOPTS_DIR}` is the path that you checked out `cxxopts` -to: - - cmake ${CXXOPTS_DIR} - make - -You can use another build tool, such as ninja. - - cmake -G Ninja ${CXXOPTS_DIR} - ninja - - -To run the tests, you have to configure `cxxopts` with another flag: - cmake -D CXXOPTS_BUILD_TESTS=On ${CXXOPTS_DIR} - make - make test diff --git a/vendor/cxxopts/LICENSE b/vendor/cxxopts/LICENSE deleted file mode 100644 index 324a20358..000000000 --- a/vendor/cxxopts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014 Jarryd Beck - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/cxxopts/README.md b/vendor/cxxopts/README.md deleted file mode 100644 index 93dcf3b10..000000000 --- a/vendor/cxxopts/README.md +++ /dev/null @@ -1,148 +0,0 @@ -[![Build Status](https://travis-ci.org/jarro2783/cxxopts.svg?branch=master)](https://travis-ci.org/jarro2783/cxxopts) - -# Release versions - -Note that `master` is generally a work in progress, and you probably want to use a -tagged release version. - -# Quick start - -This is a lightweight C++ option parser library, supporting the standard GNU -style syntax for options. - -Options can be given as: - - --long - --long=argument - --long argument - -a - -ab - -abc argument - -where c takes an argument, but a and b do not. - -Additionally, anything after `--` will be parsed as a positional argument. - -## Basics - - #include - -Create a cxxopts::Options instance. - - cxxopts::Options options("MyProgram", "One line description of MyProgram"); - -Then use `add_options`. - - options.add_options() - ("d,debug", "Enable debugging") - ("f,file", "File name", cxxopts::value()) - ; - -Options are declared with a long and an optional short option. A description -must be provided. The third argument is the value, if omitted it is boolean. -Any type can be given as long as it can be parsed, with operator>>. - -To parse the command line do: - - auto result = options.parse(argc, argv); - -To retrieve an option use `result.count("option")` to get the number of times -it appeared, and - - result["opt"].as() - -to get its value. If "opt" doesn't exist, or isn't of the right type, then an -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. - -## Exceptions - -Exceptional situations throw C++ exceptions. There are two types of -exceptions: errors defining the options, and errors when parsing a list of -arguments. All exceptions derive from `cxxopts::OptionException`. Errors -defining options derive from `cxxopts::OptionSpecException` and errors -parsing arguments derive from `cxxopts::OptionParseException`. - -All exceptions define a `what()` function to get a printable string -explaining the error. - -## Help groups - -Options can be placed into groups for the purposes of displaying help messages. -To place options in a group, pass the group as a string to `add_options`. Then, -when displaying the help, pass the groups that you would like displayed as a -vector to the `help` function. - -## Positional Arguments - -Positional arguments can be optionally parsed into one or more options. -To set up positional arguments, call - - options.parse_positional({"first", "second", "last"}) - -where "last" should be the name of an option with a container type, and the -others should have a single value. - -## Default and implicit values - -An option can be declared with a default or an implicit value, or both. - -A default value is the value that an option takes when it is not specified -on the command line. The following specifies a default value for an option: - - cxxopts::value()->default_value("value") - -An implicit value is the value that an option takes when it is given on the -command line without an argument. The following specifies an implicit value: - - cxxopts::value()->implicit_value("implicit") - -If an option had both, then not specifying it would give the value `"value"`, -writing it on the command line as `--option` would give the value `"implicit"`, -and writing `--option=another` would give it the value `"another"`. - -Note that the default and implicit value is always stored as a string, -regardless of the type that you want to store it in. It will be parsed as -though it was given on the command line. - -## Boolean values - -Boolean options have a default implicit value of `"true"`, which can be -overridden. The effect is that writing `-o` by itself will set option `o` to -`true`. However, they can also be written with various strings using `=value`. -There is no way to disambiguate positional arguments from the value following -a boolean, so we have chosen that they will be positional arguments, and -therefore, `-o false` does not work. - -## `std::vector` values - -Parsing of list of values in form of an `std::vector` is also supported, as long as `T` -can be parsed. To separate single values in a list the definition `CXXOPTS_VECTOR_DELIMITER` -is used, which is ',' by default. Ensure that you use no whitespaces between values because -those would be interpreted as the next command line option. Example for a command line option -that can be parsed as a `std::vector`: - -~~~ ---my_list=1,-2.1,3,4.5 -~~~ - -## Custom help - -The string after the program name on the first line of the help can be -completely replaced by calling `options.custom_help`. Note that you might -also want to override the positional help by calling `options.positional_help`. - -# Linking - -This is a header only library. - -# Requirements - -The only build requirement is a C++ compiler that supports C++11 regular -expressions. For example GCC >= 4.9 or clang with libc++. - -# TODO list - -* Allow unrecognised options. diff --git a/vendor/cxxopts/cxxopts-config.cmake.in b/vendor/cxxopts/cxxopts-config.cmake.in deleted file mode 100644 index c9efaf14b..000000000 --- a/vendor/cxxopts/cxxopts-config.cmake.in +++ /dev/null @@ -1,4 +0,0 @@ -@PACKAGE_INIT@ - -include(${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake) -check_required_components(cxxopts) diff --git a/vendor/cxxopts/include/cxxopts.hpp b/vendor/cxxopts/include/cxxopts.hpp deleted file mode 100644 index 9cde72d6b..000000000 --- a/vendor/cxxopts/include/cxxopts.hpp +++ /dev/null @@ -1,2196 +0,0 @@ -/* - -Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ - -#ifndef CXXOPTS_HPP_INCLUDED -#define CXXOPTS_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cpp_lib_optional -#include -#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 - -namespace cxxopts -{ - static constexpr struct { - uint8_t major, minor, patch; - } version = { - CXXOPTS__VERSION_MAJOR, - CXXOPTS__VERSION_MINOR, - CXXOPTS__VERSION_PATCH - }; -} - -//when we ask cxxopts to use Unicode, help strings are processed using ICU, -//which results in the correct lengths being computed for strings when they -//are formatted for the help output -//it is necessary to make sure that can be found by the -//compiler, and that icu-uc is linked in to the binary. - -#ifdef CXXOPTS_USE_UNICODE -#include - -namespace cxxopts -{ - typedef icu::UnicodeString String; - - inline - String - toLocalString(std::string s) - { - return icu::UnicodeString::fromUTF8(std::move(s)); - } - - class UnicodeStringIterator : public - std::iterator - { - public: - - UnicodeStringIterator(const icu::UnicodeString* string, int32_t pos) - : s(string) - , i(pos) - { - } - - value_type - operator*() const - { - return s->char32At(i); - } - - bool - operator==(const UnicodeStringIterator& rhs) const - { - return s == rhs.s && i == rhs.i; - } - - bool - operator!=(const UnicodeStringIterator& rhs) const - { - return !(*this == rhs); - } - - UnicodeStringIterator& - operator++() - { - ++i; - return *this; - } - - UnicodeStringIterator - operator+(int32_t v) - { - return UnicodeStringIterator(s, i + v); - } - - private: - const icu::UnicodeString* s; - int32_t i; - }; - - inline - String& - stringAppend(String&s, String a) - { - return s.append(std::move(a)); - } - - inline - String& - stringAppend(String& s, int n, UChar32 c) - { - for (int i = 0; i != n; ++i) - { - s.append(c); - } - - return s; - } - - template - String& - stringAppend(String& s, Iterator begin, Iterator end) - { - while (begin != end) - { - s.append(*begin); - ++begin; - } - - return s; - } - - inline - size_t - stringLength(const String& s) - { - return s.length(); - } - - inline - std::string - toUTF8String(const String& s) - { - std::string result; - s.toUTF8String(result); - - return result; - } - - inline - bool - empty(const String& s) - { - return s.isEmpty(); - } -} - -namespace std -{ - inline - cxxopts::UnicodeStringIterator - begin(const icu::UnicodeString& s) - { - return cxxopts::UnicodeStringIterator(&s, 0); - } - - inline - cxxopts::UnicodeStringIterator - end(const icu::UnicodeString& s) - { - return cxxopts::UnicodeStringIterator(&s, s.length()); - } -} - -//ifdef CXXOPTS_USE_UNICODE -#else - -namespace cxxopts -{ - typedef std::string String; - - template - T - toLocalString(T&& t) - { - return std::forward(t); - } - - inline - size_t - stringLength(const String& s) - { - return s.length(); - } - - inline - String& - stringAppend(String&s, String a) - { - return s.append(std::move(a)); - } - - inline - String& - stringAppend(String& s, size_t n, char c) - { - return s.append(n, c); - } - - template - String& - stringAppend(String& s, Iterator begin, Iterator end) - { - return s.append(begin, end); - } - - template - std::string - toUTF8String(T&& t) - { - return std::forward(t); - } - - inline - bool - empty(const std::string& s) - { - return s.empty(); - } -} - -//ifdef CXXOPTS_USE_UNICODE -#endif - -namespace cxxopts -{ - namespace - { -#ifdef _WIN32 - const std::string LQUOTE("\'"); - const std::string RQUOTE("\'"); -#else - const std::string LQUOTE("‘"); - const std::string RQUOTE("’"); -#endif - } - - class Value : public std::enable_shared_from_this - { - public: - - virtual ~Value() = default; - - virtual - std::shared_ptr - clone() const = 0; - - virtual void - parse(const std::string& text) const = 0; - - virtual void - parse() const = 0; - - virtual bool - has_default() const = 0; - - virtual bool - is_container() const = 0; - - virtual bool - has_implicit() const = 0; - - virtual std::string - get_default_value() const = 0; - - virtual std::string - get_implicit_value() const = 0; - - virtual std::shared_ptr - default_value(const std::string& value) = 0; - - virtual std::shared_ptr - implicit_value(const std::string& value) = 0; - - virtual std::shared_ptr - no_implicit_value() = 0; - - virtual bool - is_boolean() const = 0; - }; - - class OptionException : public std::exception - { - public: - OptionException(const std::string& message) - : m_message(message) - { - } - - virtual const char* - what() const noexcept - { - return m_message.c_str(); - } - - private: - std::string m_message; - }; - - class OptionSpecException : public OptionException - { - public: - - OptionSpecException(const std::string& message) - : OptionException(message) - { - } - }; - - class OptionParseException : public OptionException - { - public: - OptionParseException(const std::string& message) - : OptionException(message) - { - } - }; - - class option_exists_error : public OptionSpecException - { - public: - option_exists_error(const std::string& option) - : OptionSpecException("Option " + LQUOTE + option + RQUOTE + " already exists") - { - } - }; - - class invalid_option_format_error : public OptionSpecException - { - public: - invalid_option_format_error(const std::string& format) - : OptionSpecException("Invalid option format " + LQUOTE + format + RQUOTE) - { - } - }; - - class option_syntax_exception : public OptionParseException { - public: - option_syntax_exception(const std::string& text) - : OptionParseException("Argument " + LQUOTE + text + RQUOTE + - " starts with a - but has incorrect syntax") - { - } - }; - - class option_not_exists_exception : public OptionParseException - { - public: - option_not_exists_exception(const std::string& option) - : OptionParseException("Option " + LQUOTE + option + RQUOTE + " does not exist") - { - } - }; - - class missing_argument_exception : public OptionParseException - { - public: - missing_argument_exception(const std::string& option) - : OptionParseException( - "Option " + LQUOTE + option + RQUOTE + " is missing an argument" - ) - { - } - }; - - class option_requires_argument_exception : public OptionParseException - { - public: - option_requires_argument_exception(const std::string& option) - : OptionParseException( - "Option " + LQUOTE + option + RQUOTE + " requires an argument" - ) - { - } - }; - - class option_not_has_argument_exception : public OptionParseException - { - public: - option_not_has_argument_exception - ( - const std::string& option, - const std::string& arg - ) - : OptionParseException( - "Option " + LQUOTE + option + RQUOTE + - " does not take an argument, but argument " + - LQUOTE + arg + RQUOTE + " given" - ) - { - } - }; - - class option_not_present_exception : public OptionParseException - { - public: - option_not_present_exception(const std::string& option) - : OptionParseException("Option " + LQUOTE + option + RQUOTE + " not present") - { - } - }; - - class argument_incorrect_type : public OptionParseException - { - public: - argument_incorrect_type - ( - const std::string& arg - ) - : OptionParseException( - "Argument " + LQUOTE + arg + RQUOTE + " failed to parse" - ) - { - } - }; - - class option_required_exception : public OptionParseException - { - public: - option_required_exception(const std::string& option) - : OptionParseException( - "Option " + LQUOTE + option + RQUOTE + " is required but not present" - ) - { - } - }; - - template - void throw_or_mimic(const std::string& text) - { - static_assert(std::is_base_of::value, - "throw_or_mimic only works on std::exception and " - "deriving classes"); - -#ifndef CXXOPTS_NO_EXCEPTIONS - // If CXXOPTS_NO_EXCEPTIONS is not defined, just throw - throw T{text}; -#else - // Otherwise manually instantiate the exception, print what() to stderr, - // and abort - T exception{text}; - std::cerr << exception.what() << std::endl; - std::cerr << "Aborting (exceptions disabled)..." << std::endl; - std::abort(); -#endif - } - - namespace values - { - namespace - { - std::basic_regex integer_pattern - ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)"); - std::basic_regex truthy_pattern - ("(t|T)(rue)?|1"); - std::basic_regex falsy_pattern - ("(f|F)(alse)?|0"); - } - - namespace detail - { - template - struct SignedCheck; - - template - struct SignedCheck - { - template - void - operator()(bool negative, U u, const std::string& text) - { - if (negative) - { - if (u > static_cast((std::numeric_limits::min)())) - { - throw_or_mimic(text); - } - } - else - { - if (u > static_cast((std::numeric_limits::max)())) - { - throw_or_mimic(text); - } - } - } - }; - - template - struct SignedCheck - { - template - void - operator()(bool, U, const std::string&) {} - }; - - template - void - check_signed_range(bool negative, U value, const std::string& text) - { - SignedCheck::is_signed>()(negative, value, text); - } - } - - template - R - checked_negate(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(t-1)-1; - } - - template - T - checked_negate(T&& t, const std::string& text, std::false_type) - { - throw_or_mimic(text); - return t; - } - - template - void - integer_parser(const std::string& text, T& value) - { - std::smatch match; - std::regex_match(text, match, integer_pattern); - - if (match.length() == 0) - { - throw_or_mimic(text); - } - - if (match.length(4) > 0) - { - value = 0; - return; - } - - using US = typename std::make_unsigned::type; - - constexpr bool is_signed = std::numeric_limits::is_signed; - const bool negative = match.length(1) > 0; - const uint8_t base = match.length(2) > 0 ? 16 : 10; - - auto value_match = match[3]; - - US result = 0; - - for (auto iter = value_match.first; iter != value_match.second; ++iter) - { - US digit = 0; - - if (*iter >= '0' && *iter <= '9') - { - digit = static_cast(*iter - '0'); - } - else if (base == 16 && *iter >= 'a' && *iter <= 'f') - { - digit = static_cast(*iter - 'a' + 10); - } - else if (base == 16 && *iter >= 'A' && *iter <= 'F') - { - digit = static_cast(*iter - 'A' + 10); - } - else - { - throw_or_mimic(text); - } - - US next = result * base + digit; - if (result > next) - { - throw_or_mimic(text); - } - - result = next; - } - - detail::check_signed_range(negative, result, text); - - if (negative) - { - value = checked_negate(result, - text, - std::integral_constant()); - } - else - { - value = static_cast(result); - } - } - - template - void stringstream_parser(const std::string& text, T& value) - { - std::stringstream in(text); - in >> value; - if (!in) { - throw_or_mimic(text); - } - } - - inline - void - parse_value(const std::string& text, uint8_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, int8_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, uint16_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, int16_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, uint32_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, int32_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, uint64_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, int64_t& value) - { - integer_parser(text, value); - } - - inline - void - parse_value(const std::string& text, bool& value) - { - std::smatch result; - std::regex_match(text, result, truthy_pattern); - - if (!result.empty()) - { - value = true; - return; - } - - std::regex_match(text, result, falsy_pattern); - if (!result.empty()) - { - value = false; - return; - } - - throw_or_mimic(text); - } - - inline - void - parse_value(const std::string& text, std::string& value) - { - value = text; - } - - // The fallback parser. It uses the stringstream parser to parse all types - // that have not been overloaded explicitly. It has to be placed in the - // source code before all other more specialized templates. - template - void - parse_value(const std::string& text, T& value) { - stringstream_parser(text, value); - } - - template - void - parse_value(const std::string& text, std::vector& value) - { - 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 - template - void - parse_value(const std::string& text, std::optional& value) - { - T result; - parse_value(text, result); - value = std::move(result); - } -#endif - - template - struct type_is_container - { - static constexpr bool value = false; - }; - - template - struct type_is_container> - { - static constexpr bool value = true; - }; - - template - class abstract_value : public Value - { - using Self = abstract_value; - - public: - abstract_value() - : m_result(std::make_shared()) - , m_store(m_result.get()) - { - } - - abstract_value(T* t) - : m_store(t) - { - } - - virtual ~abstract_value() = default; - - abstract_value(const abstract_value& rhs) - { - if (rhs.m_result) - { - m_result = std::make_shared(); - m_store = m_result.get(); - } - else - { - m_store = rhs.m_store; - } - - m_default = rhs.m_default; - m_implicit = rhs.m_implicit; - m_default_value = rhs.m_default_value; - m_implicit_value = rhs.m_implicit_value; - } - - void - parse(const std::string& text) const - { - parse_value(text, *m_store); - } - - bool - is_container() const - { - return type_is_container::value; - } - - void - parse() const - { - parse_value(m_default_value, *m_store); - } - - bool - has_default() const - { - return m_default; - } - - bool - has_implicit() const - { - return m_implicit; - } - - std::shared_ptr - default_value(const std::string& value) - { - m_default = true; - m_default_value = value; - return shared_from_this(); - } - - std::shared_ptr - implicit_value(const std::string& value) - { - m_implicit = true; - m_implicit_value = value; - return shared_from_this(); - } - - std::shared_ptr - no_implicit_value() - { - m_implicit = false; - return shared_from_this(); - } - - std::string - get_default_value() const - { - return m_default_value; - } - - std::string - get_implicit_value() const - { - return m_implicit_value; - } - - bool - is_boolean() const - { - return std::is_same::value; - } - - const T& - get() const - { - if (m_store == nullptr) - { - return *m_result; - } - else - { - return *m_store; - } - } - - protected: - std::shared_ptr m_result; - T* m_store; - - bool m_default = false; - bool m_implicit = false; - - std::string m_default_value; - std::string m_implicit_value; - }; - - template - class standard_value : public abstract_value - { - public: - using abstract_value::abstract_value; - - std::shared_ptr - clone() const - { - return std::make_shared>(*this); - } - }; - - template <> - class standard_value : public abstract_value - { - public: - ~standard_value() = default; - - standard_value() - { - set_default_and_implicit(); - } - - standard_value(bool* b) - : abstract_value(b) - { - set_default_and_implicit(); - } - - std::shared_ptr - clone() const - { - return std::make_shared>(*this); - } - - private: - - void - set_default_and_implicit() - { - m_default = true; - m_default_value = "false"; - m_implicit = true; - m_implicit_value = "true"; - } - }; - } - - template - std::shared_ptr - value() - { - return std::make_shared>(); - } - - template - std::shared_ptr - value(T& t) - { - return std::make_shared>(&t); - } - - class OptionAdder; - - class OptionDetails - { - public: - OptionDetails - ( - const std::string& short_, - const std::string& long_, - const String& desc, - std::shared_ptr val - ) - : m_short(short_) - , m_long(long_) - , m_desc(desc) - , m_value(val) - , m_count(0) - { - } - - OptionDetails(const OptionDetails& rhs) - : m_desc(rhs.m_desc) - , m_count(rhs.m_count) - { - m_value = rhs.m_value->clone(); - } - - OptionDetails(OptionDetails&& rhs) = default; - - const String& - description() const - { - return m_desc; - } - - const Value& value() const { - return *m_value; - } - - std::shared_ptr - make_storage() const - { - return m_value->clone(); - } - - const std::string& - short_name() const - { - return m_short; - } - - const std::string& - long_name() const - { - return m_long; - } - - private: - std::string m_short; - std::string m_long; - String m_desc; - std::shared_ptr m_value; - int m_count; - }; - - struct HelpOptionDetails - { - std::string s; - std::string l; - String desc; - bool has_default; - std::string default_value; - bool has_implicit; - std::string implicit_value; - std::string arg_help; - bool is_container; - bool is_boolean; - }; - - struct HelpGroupDetails - { - std::string name; - std::string description; - std::vector options; - }; - - class OptionValue - { - public: - void - parse - ( - std::shared_ptr details, - const std::string& text - ) - { - ensure_value(details); - ++m_count; - m_value->parse(text); - } - - void - parse_default(std::shared_ptr details) - { - ensure_value(details); - m_default = true; - m_value->parse(); - } - - size_t - 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 - const T& - as() const - { - if (m_value == nullptr) { - throw_or_mimic("No value"); - } - -#ifdef CXXOPTS_NO_RTTI - return static_cast&>(*m_value).get(); -#else - return dynamic_cast&>(*m_value).get(); -#endif - } - - private: - void - ensure_value(std::shared_ptr details) - { - if (m_value == nullptr) - { - m_value = details->make_storage(); - } - } - - std::shared_ptr m_value; - size_t m_count = 0; - bool m_default = false; - }; - - class KeyValue - { - public: - KeyValue(std::string key_, std::string value_) - : m_key(std::move(key_)) - , m_value(std::move(value_)) - { - } - - const - std::string& - key() const - { - return m_key; - } - - const - std::string& - value() const - { - return m_value; - } - - template - T - as() const - { - T result; - values::parse_value(m_value, result); - return result; - } - - private: - std::string m_key; - std::string m_value; - }; - - class ParseResult - { - public: - - ParseResult( - const std::shared_ptr< - std::unordered_map> - >, - std::vector, - bool allow_unrecognised, - int&, char**&); - - size_t - count(const std::string& o) const - { - auto iter = m_options->find(o); - if (iter == m_options->end()) - { - return 0; - } - - auto riter = m_results.find(iter->second); - - return riter->second.count(); - } - - const OptionValue& - operator[](const std::string& option) const - { - auto iter = m_options->find(option); - - if (iter == m_options->end()) - { - throw_or_mimic(option); - } - - auto riter = m_results.find(iter->second); - - return riter->second; - } - - const std::vector& - arguments() const - { - 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(std::string a); - - void - parse_option - ( - std::shared_ptr value, - const std::string& name, - const std::string& arg = "" - ); - - void - parse_default(std::shared_ptr details); - - void - checked_parse_arg - ( - int argc, - char* argv[], - int& current, - std::shared_ptr value, - const std::string& name - ); - - const std::shared_ptr< - std::unordered_map> - > m_options; - std::vector m_positional; - std::vector::iterator m_next_positional; - std::unordered_set m_positional_set; - std::unordered_map, OptionValue> m_results; - - bool m_allow_unrecognised; - - std::vector m_sequential; - }; - - struct Option - { - Option - ( - const std::string& opts, - const std::string& desc, - const std::shared_ptr& value = ::cxxopts::value(), - const std::string& arg_help = "" - ) - : opts_(opts) - , desc_(desc) - , value_(value) - , arg_help_(arg_help) - { - } - - std::string opts_; - std::string desc_; - std::shared_ptr value_; - std::string arg_help_; - }; - - class Options - { - typedef std::unordered_map> - OptionMap; - public: - - Options(std::string program, std::string help_string = "") - : m_program(std::move(program)) - , m_help_string(toLocalString(std::move(help_string))) - , m_custom_help("[OPTION...]") - , m_positional_help("positional parameters") - , m_show_positional(false) - , m_allow_unrecognised(false) - , m_options(std::make_shared()) - , m_next_positional(m_positional.end()) - { - } - - Options& - positional_help(std::string help_text) - { - m_positional_help = std::move(help_text); - return *this; - } - - Options& - custom_help(std::string help_text) - { - m_custom_help = std::move(help_text); - return *this; - } - - Options& - show_positional_help() - { - m_show_positional = true; - return *this; - } - - Options& - allow_unrecognised_options() - { - m_allow_unrecognised = true; - return *this; - } - - ParseResult - parse(int& argc, char**& argv); - - OptionAdder - add_options(std::string group = ""); - - void - add_options - ( - const std::string& group, - std::initializer_list