Commit 51a395ec9fd6341fdca3d7728e34b48c58730c94

Authored by christos
Committed by Henry Schreiner
1 parent a8d597da

Handle float type in positive number (CLIUtils#328) (#342)

* fix https://github.com/CLIUtils/CLI11/issues/328

 * use same assumptions about the size (ie double is enough) as in Number validator

* fix spelling in error message

* fix class description comment

* PositiveNumber accepts now >0 while NonNegative >=0

* update README for PositiveNumber and NonNegativeNumber

* spelling
README.md
@@ -381,7 +381,8 @@ CLI11 has several Validators built-in that perform some common checks @@ -381,7 +381,8 @@ CLI11 has several Validators built-in that perform some common checks
381 - `CLI::NonexistentPath`: Requires that the path does not exist. 381 - `CLI::NonexistentPath`: Requires that the path does not exist.
382 - `CLI::Range(min,max)`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0. 382 - `CLI::Range(min,max)`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0.
383 - `CLI::Bounded(min,max)`: ๐Ÿ†• Modify the input such that it is always between min and max (make sure to use floating point if needed). Min defaults to 0. Will produce an error if conversion is not possible. 383 - `CLI::Bounded(min,max)`: ๐Ÿ†• Modify the input such that it is always between min and max (make sure to use floating point if needed). Min defaults to 0. Will produce an error if conversion is not possible.
384 -- `CLI::PositiveNumber`: ๐Ÿ†• Requires the number be greater or equal to 0 384 +- `CLI::PositiveNumber`: ๐Ÿ†• Requires the number be greater than 0
  385 +- `CLI::NonNegativeNumber`: ๐Ÿ†• Requires the number be greater or equal to 0
385 - `CLI::Number`: ๐Ÿ†• Requires the input be a number. 386 - `CLI::Number`: ๐Ÿ†• Requires the input be a number.
386 - `CLI::ValidIPV4`: ๐Ÿ†• Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`. 387 - `CLI::ValidIPV4`: ๐Ÿ†• Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`.
387 388
@@ -404,7 +405,7 @@ will produce a check to ensure a value is between 0 and 10 or 20 and 30. @@ -404,7 +405,7 @@ will produce a check to ensure a value is between 0 and 10 or 20 and 30.
404 ->check(!CLI::PositiveNumber); 405 ->check(!CLI::PositiveNumber);
405 ``` 406 ```
406 407
407 -will produce a check for a number less than 0. 408 +will produce a check for a number less than or equal to 0.
408 409
409 ##### Transforming Validators 410 ##### Transforming Validators
410 There are a few built in Validators that let you transform values if used with the `transform` function. If they also do some checks then they can be used `check` but some may do nothing in that case. 411 There are a few built in Validators that let you transform values if used with the `transform` function. If they also do some checks then they can be used `check` but some may do nothing in that case.
include/CLI/Validators.hpp
@@ -391,24 +391,40 @@ class IPV4Validator : public Validator { @@ -391,24 +391,40 @@ class IPV4Validator : public Validator {
391 } 391 }
392 }; 392 };
393 393
394 -/// Validate the argument is a number and greater than or equal to 0 394 +/// Validate the argument is a number and greater than 0
395 class PositiveNumber : public Validator { 395 class PositiveNumber : public Validator {
396 public: 396 public:
397 PositiveNumber() : Validator("POSITIVE") { 397 PositiveNumber() : Validator("POSITIVE") {
398 func_ = [](std::string &number_str) { 398 func_ = [](std::string &number_str) {
399 - int number; 399 + double number;
  400 + if(!detail::lexical_cast(number_str, number)) {
  401 + return "Failed parsing number: (" + number_str + ')';
  402 + }
  403 + if(number <= 0) {
  404 + return "Number less or equal to 0: (" + number_str + ')';
  405 + }
  406 + return std::string();
  407 + };
  408 + }
  409 +};
  410 +/// Validate the argument is a number and greater than or equal to 0
  411 +class NonNegativeNumber : public Validator {
  412 + public:
  413 + NonNegativeNumber() : Validator("NONNEGATIVE") {
  414 + func_ = [](std::string &number_str) {
  415 + double number;
400 if(!detail::lexical_cast(number_str, number)) { 416 if(!detail::lexical_cast(number_str, number)) {
401 return "Failed parsing number: (" + number_str + ')'; 417 return "Failed parsing number: (" + number_str + ')';
402 } 418 }
403 if(number < 0) { 419 if(number < 0) {
404 - return "Number less then 0: (" + number_str + ')'; 420 + return "Number less than 0: (" + number_str + ')';
405 } 421 }
406 return std::string(); 422 return std::string();
407 }; 423 };
408 } 424 }
409 }; 425 };
410 426
411 -/// Validate the argument is a number and greater than or equal to 0 427 +/// Validate the argument is a number
412 class Number : public Validator { 428 class Number : public Validator {
413 public: 429 public:
414 Number() : Validator("NUMBER") { 430 Number() : Validator("NUMBER") {
@@ -444,6 +460,9 @@ const detail::IPV4Validator ValidIPV4; @@ -444,6 +460,9 @@ const detail::IPV4Validator ValidIPV4;
444 /// Check for a positive number 460 /// Check for a positive number
445 const detail::PositiveNumber PositiveNumber; 461 const detail::PositiveNumber PositiveNumber;
446 462
  463 +/// Check for a non-negative number
  464 +const detail::NonNegativeNumber NonNegativeNumber;
  465 +
447 /// Check for a number 466 /// Check for a number
448 const detail::Number Number; 467 const detail::Number Number;
449 468
tests/HelpersTest.cpp
@@ -311,13 +311,36 @@ TEST(Validators, PositiveValidator) { @@ -311,13 +311,36 @@ TEST(Validators, PositiveValidator) {
311 num = "10000"; 311 num = "10000";
312 EXPECT_TRUE(CLI::PositiveNumber(num).empty()); 312 EXPECT_TRUE(CLI::PositiveNumber(num).empty());
313 num = "0"; 313 num = "0";
  314 + EXPECT_FALSE(CLI::PositiveNumber(num).empty());
  315 + num = "+0.5";
314 EXPECT_TRUE(CLI::PositiveNumber(num).empty()); 316 EXPECT_TRUE(CLI::PositiveNumber(num).empty());
315 num = "-1"; 317 num = "-1";
316 EXPECT_FALSE(CLI::PositiveNumber(num).empty()); 318 EXPECT_FALSE(CLI::PositiveNumber(num).empty());
  319 + num = "-1.5";
  320 + EXPECT_FALSE(CLI::PositiveNumber(num).empty());
317 num = "a"; 321 num = "a";
318 EXPECT_FALSE(CLI::PositiveNumber(num).empty()); 322 EXPECT_FALSE(CLI::PositiveNumber(num).empty());
319 } 323 }
320 324
  325 +TEST(Validators, NonNegativeValidator) {
  326 + std::string num = "1.1.1.1";
  327 + EXPECT_FALSE(CLI::NonNegativeNumber(num).empty());
  328 + num = "1";
  329 + EXPECT_TRUE(CLI::NonNegativeNumber(num).empty());
  330 + num = "10000";
  331 + EXPECT_TRUE(CLI::NonNegativeNumber(num).empty());
  332 + num = "0";
  333 + EXPECT_TRUE(CLI::NonNegativeNumber(num).empty());
  334 + num = "+0.5";
  335 + EXPECT_TRUE(CLI::NonNegativeNumber(num).empty());
  336 + num = "-1";
  337 + EXPECT_FALSE(CLI::NonNegativeNumber(num).empty());
  338 + num = "-1.5";
  339 + EXPECT_FALSE(CLI::NonNegativeNumber(num).empty());
  340 + num = "a";
  341 + EXPECT_FALSE(CLI::NonNegativeNumber(num).empty());
  342 +}
  343 +
321 TEST(Validators, NumberValidator) { 344 TEST(Validators, NumberValidator) {
322 std::string num = "1.1.1.1"; 345 std::string num = "1.1.1.1";
323 EXPECT_FALSE(CLI::Number(num).empty()); 346 EXPECT_FALSE(CLI::Number(num).empty());