Support 'const char**' arguments in Options::parse (#250)

`cxxopts` doesn't modify the contents of the argv strings. This changes
the parse function to take a reference to a `const char**`.
This commit is contained in:
Kjetil Andresen 2020-08-11 00:01:29 +02:00 committed by GitHub
parent 07f5cb24f1
commit 15e8a74e95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 40 deletions

View File

@ -12,6 +12,7 @@ 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**`.
## 2.2

View File

@ -1211,7 +1211,7 @@ namespace cxxopts
>,
std::vector<std::string>,
bool allow_unrecognised,
int&, char**&);
int&, const char**&);
size_t
count(const std::string& o) const
@ -1251,7 +1251,7 @@ namespace cxxopts
private:
void
parse(int& argc, char**& argv);
parse(int& argc, const char**& argv);
void
add_to_option(const std::string& option, const std::string& arg);
@ -1274,7 +1274,7 @@ namespace cxxopts
checked_parse_arg
(
int argc,
char* argv[],
const char* argv[],
int& current,
const std::shared_ptr<OptionDetails>& value,
const std::string& name
@ -1361,7 +1361,7 @@ namespace cxxopts
}
ParseResult
parse(int& argc, char**& argv);
parse(int& argc, const char**& argv);
OptionAdder
add_options(std::string group = "");
@ -1620,7 +1620,7 @@ ParseResult::ParseResult
> options,
std::vector<std::string> positional,
bool allow_unrecognised,
int& argc, char**& argv
int& argc, const char**& argv
)
: m_options(std::move(options))
, m_positional(std::move(positional))
@ -1734,7 +1734,7 @@ void
ParseResult::checked_parse_arg
(
int argc,
char* argv[],
const char* argv[],
int& current,
const std::shared_ptr<OptionDetails>& value,
const std::string& name
@ -1835,7 +1835,7 @@ Options::parse_positional(std::initializer_list<std::string> options)
inline
ParseResult
Options::parse(int& argc, char**& argv)
Options::parse(int& argc, const char**& argv)
{
ParseResult result(m_options, m_positional, m_allow_unrecognised, argc, argv);
return result;
@ -1843,7 +1843,7 @@ Options::parse(int& argc, char**& argv)
inline
void
ParseResult::parse(int& argc, char**& argv)
ParseResult::parse(int& argc, const char**& argv)
{
int current = 1;

View File

@ -27,7 +27,7 @@ THE SOFTWARE.
#include "cxxopts.hpp"
void
parse(int argc, char* argv[])
parse(int argc, const char* argv[])
{
try
{
@ -160,7 +160,7 @@ parse(int argc, char* argv[])
}
}
int main(int argc, char* argv[])
int main(int argc, const char* argv[])
{
parse(argc, argv);

View File

@ -8,7 +8,7 @@ class Argv {
public:
Argv(std::initializer_list<const char*> args)
: m_argv(new char*[args.size()])
: m_argv(new const char*[args.size()])
, m_argc(static_cast<int>(args.size()))
{
int i = 0;
@ -26,7 +26,7 @@ class Argv {
}
}
char** argv() const {
const char** argv() const {
return m_argv.get();
}
@ -37,7 +37,7 @@ class Argv {
private:
std::vector<std::unique_ptr<char[]>> m_args;
std::unique_ptr<char*[]> m_argv;
std::unique_ptr<const char*[]> m_argv;
int m_argc;
};
@ -69,7 +69,7 @@ TEST_CASE("Basic options", "[options]")
"--space",
});
char** actual_argv = argv.argv();
auto** actual_argv = argv.argv();
auto argc = argv.argc();
auto result = options.parse(argc, actual_argv);
@ -125,7 +125,7 @@ TEST_CASE("No positional", "[positional]")
Argv av({"tester", "a", "b", "def"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -177,7 +177,7 @@ TEST_CASE("Some positional explicit", "[positional]")
Argv av({"tester", "--output", "a", "b", "c", "d"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -203,7 +203,7 @@ TEST_CASE("No positional with extras", "[positional]")
Argv av({"extras", "--", "a", "b", "c", "d"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto old_argv = argv;
@ -226,7 +226,7 @@ TEST_CASE("Positional not valid", "[positional]") {
Argv av({"foobar", "bar", "baz"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
@ -241,7 +241,7 @@ TEST_CASE("Empty with implicit value", "[implicit]")
Argv av({"implicit", "--implicit="});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -260,7 +260,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION("When no value provided") {
Argv av({"no_implicit", "--bool"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::missing_argument_exception&);
@ -269,7 +269,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION("With equal-separated true") {
Argv av({"no_implicit", "--bool=true"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -280,7 +280,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION("With equal-separated false") {
Argv av({"no_implicit", "--bool=false"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -291,7 +291,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION("With space-separated true") {
Argv av({"no_implicit", "--bool", "true"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -302,7 +302,7 @@ TEST_CASE("Boolean without implicit value", "[implicit]")
SECTION("With space-separated false") {
Argv av({"no_implicit", "--bool", "false"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -323,7 +323,7 @@ TEST_CASE("Default values", "[default]")
SECTION("Sets defaults") {
Argv av({"implicit"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -339,7 +339,7 @@ TEST_CASE("Default values", "[default]")
SECTION("When values provided") {
Argv av({"implicit", "--default", "5"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -374,7 +374,7 @@ TEST_CASE("Integers", "[options]")
Argv av({"ints", "--", "5", "6", "-6", "0", "0xab", "0xAf", "0x0"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
@ -401,7 +401,7 @@ TEST_CASE("Leading zero integers", "[options]")
Argv av({"ints", "--", "05", "06", "0x0ab", "0x0001"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
@ -425,7 +425,7 @@ TEST_CASE("Unsigned integers", "[options]")
Argv av({"ints", "--", "-2"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
@ -504,7 +504,7 @@ TEST_CASE("Floats", "[options]")
Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
@ -529,7 +529,7 @@ TEST_CASE("Invalid integers", "[integer]") {
Argv av({"ints", "--", "Ae"});
char **argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse_positional("positional");
@ -554,7 +554,7 @@ TEST_CASE("Booleans", "[boolean]") {
Argv av({"booleans", "--bool=false", "--debug=true", "--timing", "--verbose=1", "--dry-run=0", "extra"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
auto result = options.parse(argc, argv);
@ -588,7 +588,7 @@ TEST_CASE("std::vector", "[vector]") {
Argv av({"vector", "--vector", "1,-2.1,3,4.5"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse(argc, argv);
@ -609,7 +609,7 @@ TEST_CASE("std::optional", "[optional]") {
Argv av({"optional", "--optional", "foo"});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
options.parse(argc, argv);
@ -634,7 +634,7 @@ TEST_CASE("Unrecognised options", "[options]") {
"--another_unknown",
});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
SECTION("Default behaviour") {
@ -661,7 +661,7 @@ TEST_CASE("Allow bad short syntax", "[options]") {
"-some_bad_short",
});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
SECTION("Default behaviour") {
@ -684,7 +684,7 @@ TEST_CASE("Invalid option syntax", "[options]") {
"--a",
});
char** argv = av.argv();
auto** argv = av.argv();
auto argc = av.argc();
SECTION("Default behaviour") {
@ -704,7 +704,7 @@ TEST_CASE("Options empty", "[options]") {
"--unknown"
});
auto argc = argv_.argc();
char** argv = argv_.argv();
auto** argv = argv_.argv();
CHECK(options.groups().empty());
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
@ -733,7 +733,7 @@ TEST_CASE("Initializer list with group", "[options]") {
"8000",
"-t",
});
char** actual_argv = argv.argv();
auto** actual_argv = argv.argv();
auto argc = argv.argc();
auto result = options.parse(argc, actual_argv);
@ -763,7 +763,7 @@ TEST_CASE("Option add with add_option(string, Option)", "[options]") {
"4"
});
auto argc = argv_.argc();
char** argv = argv_.argv();
auto** argv = argv_.argv();
auto result = options.parse(argc, argv);
CHECK(result.arguments().size()==2);