Commit 2aed1ce41b90bcc6134d90c2060480c877f1708b
Committed by
jarro2783
1 parent
da9210d4
Added parsing of general types. (#63)
Adds generic parsing of types using `operator>>`, in particular allows parsing of floats and doubles.
Showing
3 changed files
with
53 additions
and
0 deletions
include/cxxopts.hpp
| ... | ... | @@ -533,6 +533,16 @@ namespace cxxopts |
| 533 | 533 | } |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | + template <typename T> | |
| 537 | + void stringstream_parser(const std::string& text, T& value) | |
| 538 | + { | |
| 539 | + std::stringstream in(text); | |
| 540 | + in >> value; | |
| 541 | + if (!in) { | |
| 542 | + throw argument_incorrect_type(text); | |
| 543 | + } | |
| 544 | + } | |
| 545 | + | |
| 536 | 546 | inline |
| 537 | 547 | void |
| 538 | 548 | parse_value(const std::string& text, uint8_t& value) |
| ... | ... | @@ -605,6 +615,15 @@ namespace cxxopts |
| 605 | 615 | value = text; |
| 606 | 616 | } |
| 607 | 617 | |
| 618 | + // The fallback parser. It uses the stringstream parser to parse all types | |
| 619 | + // that have not been overloaded explicitly. It has to be placed in the | |
| 620 | + // source code before all other more specialized templates. | |
| 621 | + template <typename T> | |
| 622 | + void | |
| 623 | + parse_value(const std::string& text, T& value) { | |
| 624 | + stringstream_parser(text, value); | |
| 625 | + } | |
| 626 | + | |
| 608 | 627 | template <typename T> |
| 609 | 628 | void |
| 610 | 629 | parse_value(const std::string& text, std::vector<T>& value) | ... | ... |
src/example.cpp
| ... | ... | @@ -49,6 +49,7 @@ int main(int argc, char* argv[]) |
| 49 | 49 | "thisisareallylongwordthattakesupthewholelineandcannotbebrokenataspace") |
| 50 | 50 | ("help", "Print help") |
| 51 | 51 | ("int", "An integer", cxxopts::value<int>(), "N") |
| 52 | + ("float", "A floating point number", cxxopts::value<float>()) | |
| 52 | 53 | ("option_that_is_too_long_for_the_help", "A very long option") |
| 53 | 54 | #ifdef CXXOPTS_USE_UNICODE |
| 54 | 55 | ("unicode", u8"A help option with non-ascii: à. Here the size of the" |
| ... | ... | @@ -118,6 +119,11 @@ int main(int argc, char* argv[]) |
| 118 | 119 | std::cout << "int = " << options["int"].as<int>() << std::endl; |
| 119 | 120 | } |
| 120 | 121 | |
| 122 | + if (options.count("float")) | |
| 123 | + { | |
| 124 | + std::cout << "float = " << options["float"].as<float>() << std::endl; | |
| 125 | + } | |
| 126 | + | |
| 121 | 127 | std::cout << "Arguments remain = " << argc << std::endl; |
| 122 | 128 | |
| 123 | 129 | } catch (const cxxopts::OptionException& e) | ... | ... |
test/options.cpp
| ... | ... | @@ -336,3 +336,31 @@ TEST_CASE("Integer overflow", "[options]") |
| 336 | 336 | options.parse_positional("positional"); |
| 337 | 337 | CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::argument_incorrect_type); |
| 338 | 338 | } |
| 339 | + | |
| 340 | +TEST_CASE("Floats", "[options]") | |
| 341 | +{ | |
| 342 | + cxxopts::Options options("parses_floats", "parses floats correctly"); | |
| 343 | + options.add_options() | |
| 344 | + ("double", "Double precision", cxxopts::value<double>()) | |
| 345 | + ("positional", "Floats", cxxopts::value<std::vector<float>>()); | |
| 346 | + | |
| 347 | + Argv av({"floats", "--double", "0.5", "--", "4", "-4", "1.5e6", "-1.5e6"}); | |
| 348 | + | |
| 349 | + char** argv = av.argv(); | |
| 350 | + auto argc = av.argc(); | |
| 351 | + | |
| 352 | + options.parse_positional("positional"); | |
| 353 | + options.parse(argc, argv); | |
| 354 | + | |
| 355 | + REQUIRE(options.count("double") == 1); | |
| 356 | + REQUIRE(options.count("positional") == 4); | |
| 357 | + | |
| 358 | + CHECK(options["double"].as<double>() == 0.5); | |
| 359 | + | |
| 360 | + auto& positional = options["positional"].as<std::vector<float>>(); | |
| 361 | + CHECK(positional[0] == 4); | |
| 362 | + CHECK(positional[1] == -4); | |
| 363 | + CHECK(positional[2] == 1.5e6); | |
| 364 | + CHECK(positional[3] == -1.5e6); | |
| 365 | +} | |
| 366 | + | ... | ... |