Commit 2aed1ce41b90bcc6134d90c2060480c877f1708b

Authored by Hannah Rittich
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.
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(&quot;Integer overflow&quot;, &quot;[options]&quot;)
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 +
... ...