Validate string to double using std::isfinite
This commit is contained in:
parent
239396fec8
commit
75dd033cb0
3 changed files with 26 additions and 16 deletions
|
@ -23,8 +23,11 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <ctype.h>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
|
@ -35,8 +38,26 @@
|
|||
#define strncasecmp(a, b, n) _strnicmp(a, b, n)
|
||||
#endif
|
||||
|
||||
// Convert a string to double, returning true or false depending on susccess
|
||||
bool str_to_double(const std::string& input, double &value);
|
||||
/*
|
||||
* Converts a string to a finite number (such as float or double).
|
||||
* Returns the number or quiet_NaN, if it could not be parsed.
|
||||
* This function does not attemp to capture exceptions that may
|
||||
* be thrown from std::stod(...)
|
||||
*/
|
||||
template<typename T>
|
||||
T to_finite(const std::string& input) {
|
||||
T result = std::numeric_limits<T>::quiet_NaN();
|
||||
size_t bytes_read = 0;
|
||||
try {
|
||||
const double interim = std::stod(input, &bytes_read);
|
||||
if (!input.empty() && bytes_read == input.size())
|
||||
result = static_cast<T>(interim);
|
||||
}
|
||||
// handle exceptions that stod may throw
|
||||
catch (std::invalid_argument e) {}
|
||||
catch (std::out_of_range e) {}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the filename with the prior path stripped.
|
||||
// Works with both \ and / directory delimeters.
|
||||
|
|
|
@ -83,15 +83,15 @@ bool AUTOTYPE::ReadDoubleArg(const std::string &name,
|
|||
std::string str_value;
|
||||
// Is the user trying to set this flag?
|
||||
if (cmd->FindString(flag, str_value, true)) {
|
||||
double user_value;
|
||||
|
||||
// Can the user's value be parsed?
|
||||
if (str_to_double(str_value, user_value)) {
|
||||
const double user_value = to_finite<double>(str_value);
|
||||
if (std::isfinite(user_value)) {
|
||||
result = true;
|
||||
// Clamp the user's value if needed
|
||||
value = clamp(user_value, min_value, max_value);
|
||||
|
||||
// If we had to clamp the users value, then inform them
|
||||
// Inform them if we had to clamp their value
|
||||
if (std::fabs(user_value - value) > std::numeric_limits<double>::epsilon())
|
||||
WriteOut("AUTOTYPE: bounding %s value of %.2f to %.2f\n",
|
||||
name.c_str(), user_value, value);
|
||||
|
|
|
@ -35,17 +35,6 @@
|
|||
#include "support.h"
|
||||
#include "video.h"
|
||||
|
||||
bool str_to_double(const std::string& input, double &value) {
|
||||
bool result = false;
|
||||
size_t bytes_read = 0;
|
||||
try {
|
||||
value = std::stod(input, &bytes_read);
|
||||
if (bytes_read == input.size())
|
||||
result = true;
|
||||
} catch (std::invalid_argument &) {}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string get_basename(const std::string& filename) {
|
||||
// Guard against corner cases: '', '/', '\', 'a'
|
||||
if (filename.length() <= 1)
|
||||
|
|
Loading…
Add table
Reference in a new issue