summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorArne Juul <arnej@yahoo-inc.com>2019-06-12 14:41:07 +0000
committerArne Juul <arnej@yahoo-inc.com>2019-06-12 14:41:07 +0000
commite38433e8cf5104bc3c3f4df1b9c5e5ec64b95cce (patch)
tree914e1e12f13b8702c2ddda1ffb2544e2573eabe1 /vespalib
parent67e0571b901e63dde4514a24d881d169abe463b1 (diff)
make allow-underflow common code
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/vespa/vespalib/data/slime/json_format.cpp4
-rw-r--r--vespalib/src/vespa/vespalib/locale/c.cpp18
-rw-r--r--vespalib/src/vespa/vespalib/locale/c.h4
-rw-r--r--vespalib/src/vespa/vespalib/stllike/asciistream.cpp26
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;