diff options
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/vespa/vespalib/data/slime/json_format.cpp | 4 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/locale/c.cpp | 18 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/locale/c.h | 4 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/stllike/asciistream.cpp | 26 |
4 files changed, 28 insertions, 24 deletions
diff --git a/vespalib/src/vespa/vespalib/data/slime/json_format.cpp b/vespalib/src/vespa/vespalib/data/slime/json_format.cpp index e97786888e8..d2f953b38c8 100644 --- a/vespalib/src/vespa/vespalib/data/slime/json_format.cpp +++ b/vespalib/src/vespa/vespalib/data/slime/json_format.cpp @@ -434,7 +434,7 @@ JsonDecoder::decodeNumber(Inserter &inserter) default: char *endp; int errorCode = insertNumber(inserter, isLong, value, &endp); - if (endp == value.c_str()) { + if ((endp == value.c_str()) || (errorCode != 0)) { std::stringstream ss; ss << "error inserting number " << value << ". error code: " << errorCode << ". endp - value: " << (endp - value.c_str()); in.fail(ss.str()); @@ -454,7 +454,7 @@ insertNumber(Inserter &inserter, bool isLong, const vespalib::string & value, ch errorCode = errno; inserter.insertLong(val); } else { - double val = locale::c::strtod(value.c_str(), endp); + double val = locale::c::strtod_au(value.c_str(), endp); errorCode = errno; inserter.insertDouble(val); } diff --git a/vespalib/src/vespa/vespalib/locale/c.cpp b/vespalib/src/vespa/vespalib/locale/c.cpp index af228ce55c3..74e7485f158 100644 --- a/vespalib/src/vespa/vespalib/locale/c.cpp +++ b/vespalib/src/vespa/vespalib/locale/c.cpp @@ -3,6 +3,7 @@ #include "c.h" #include "locale.h" #include <cstdlib> +#include <errno.h> namespace vespalib::locale::c { @@ -20,5 +21,22 @@ float strtof(const char *startp, char **endp) { return strtof_l(startp, endp, _G_C_Locale.get()); } +double strtod_au(const char *startp, char **endp) { + int was = errno; + double v = strtod_l(startp, endp, _G_C_Locale.get()); + if (errno == ERANGE) { + if ((-1.0 < v) && (v < 1.0)) errno = was; + } + return v; } +float strtof_au(const char *startp, char **endp) { + int was = errno; + float v = strtof_l(startp, endp, _G_C_Locale.get()); + if (errno == ERANGE) { + if ((-1.0 < v) && (v < 1.0)) errno = was; + } + return v; +} + +} diff --git a/vespalib/src/vespa/vespalib/locale/c.h b/vespalib/src/vespa/vespalib/locale/c.h index ff7d0c18639..08cf6185e7f 100644 --- a/vespalib/src/vespa/vespalib/locale/c.h +++ b/vespalib/src/vespa/vespalib/locale/c.h @@ -7,6 +7,10 @@ namespace vespalib::locale::c { double strtod(const char *nptr, char **endptr); float strtof(const char *nptr, char **endptr); +// allow underflow variants +double strtod_au(const char *nptr, char **endptr); +float strtof_au(const char *nptr, char **endptr); + inline double atof(const char *nptr) { return strtod(nptr, nullptr); } } diff --git a/vespalib/src/vespa/vespalib/stllike/asciistream.cpp b/vespalib/src/vespa/vespalib/stllike/asciistream.cpp index 499171dc6e7..7d585cf1cf6 100644 --- a/vespalib/src/vespa/vespalib/stllike/asciistream.cpp +++ b/vespalib/src/vespa/vespalib/stllike/asciistream.cpp @@ -172,17 +172,8 @@ int getValue(double & val, const char *buf) { char *ebuf; errno = 0; - val = locale::c::strtod(buf, &ebuf); - bool failed = (buf == ebuf); - if (errno != 0) { - if (errno == ERANGE) { - if (val == HUGE_VAL) failed = true; - if (val == -HUGE_VAL) failed = true; - } else { - failed = true; - } - } - if (failed) { + val = locale::c::strtod_au(buf, &ebuf); + if ((errno != 0) || (buf == ebuf)) { throwInputError(errno, "double", buf); } return ebuf - buf; @@ -192,17 +183,8 @@ int getValue(float & val, const char *buf) { char *ebuf; errno = 0; - val = locale::c::strtof(buf, &ebuf); - bool failed = (buf == ebuf); - if (errno != 0) { - if (errno == ERANGE) { - if (val == HUGE_VALF) failed = true; - if (val == -HUGE_VALF) failed = true; - } else { - failed = true; - } - } - if (failed) { + val = locale::c::strtof_au(buf, &ebuf); + if ((errno != 0) || (buf == ebuf)) { throwInputError(errno, "float", buf); } return ebuf - buf; |