summaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2017-06-14 16:39:42 +0200
committerHenning Baldersheim <balder@yahoo-inc.com>2017-06-19 14:32:59 +0200
commita0b7b206752e54118ef0b0ce88987e88ddb2d689 (patch)
tree54d2f955d097ab72afbe6ce85b6c5def3076a08e /config
parent86e346744713ce715b94ae70a0233f46c4ab61c4 (diff)
Make double parsing independent of locale.
Diffstat (limited to 'config')
-rw-r--r--config/src/tests/configparser/configparser.cpp8
-rw-r--r--config/src/vespa/config/common/configparser.cpp28
2 files changed, 32 insertions, 4 deletions
diff --git a/config/src/tests/configparser/configparser.cpp b/config/src/tests/configparser/configparser.cpp
index f361a4b8162..23dbc77488b 100644
--- a/config/src/tests/configparser/configparser.cpp
+++ b/config/src/tests/configparser/configparser.cpp
@@ -108,6 +108,14 @@ TEST("require that escaped values are properly unescaped") {
ASSERT_EQUAL("a\nb\rc\\d\"eBg", value);
}
+IGNORE_TEST("verify that locale does not affect double parsing") { // Failing on some CentOS based environments
+ std::vector<vespalib::string> payload;
+ setlocale(LC_NUMERIC, "nb_NO.UTF-8");
+ payload.push_back("foo 3,14");
+ ASSERT_EXCEPTION(ConfigParser::parse<double>("foo", payload), InvalidConfigException, "Value 3,14 is not a legal double");
+ setlocale(LC_NUMERIC, "C");
+}
+
TEST("require that maps can be parsed")
{
writeFile("foo.cfg", "\nfooValue \"a\"\nfooMap{\"foo\"} 1336\nfooMap{\"bar\"} 1337\n");
diff --git a/config/src/vespa/config/common/configparser.cpp b/config/src/vespa/config/common/configparser.cpp
index cc3cfd26374..1f303c49871 100644
--- a/config/src/vespa/config/common/configparser.cpp
+++ b/config/src/vespa/config/common/configparser.cpp
@@ -4,6 +4,7 @@
#include "exceptions.h"
#include "misc.h"
#include <vespa/vespalib/stllike/asciistream.h>
+#include <cassert>
namespace config {
@@ -338,6 +339,25 @@ ConfigParser::convert<int64_t>(const vsvector & config)
return ret;
}
+namespace {
+
+class Locale {
+public:
+ Locale() : Locale(LC_ALL_MASK, "C") { }
+ Locale(int category, const char *locale) : _locale(newlocale(category, locale, nullptr))
+ {
+ perror("newlocale failed");
+ assert(_locale != nullptr);
+ }
+ ~Locale() { freelocale(_locale); }
+ locale_t get() const { return _locale; }
+private:
+ locale_t _locale;
+};
+
+Locale _G_C_Locale;
+}
+
template<>
double
ConfigParser::convert<double>(const vsvector & config)
@@ -351,11 +371,11 @@ ConfigParser::convert<double>(const vsvector & config)
const char *startp = value.c_str();
char *endp;
errno = 0;
- double ret = strtod(startp, &endp);
+ double ret = strtod_l(startp, &endp, _G_C_Locale.get());
int err = errno;
- if (err == ERANGE || (*endp != '\0'))
- throw InvalidConfigException("Value " + value + " is not a legal double",
- VESPA_STRLOC);
+ if (err == ERANGE || (*endp != '\0')) {
+ throw InvalidConfigException("Value " + value + " is not a legal double", VESPA_STRLOC);
+ }
return ret;
}