Skip to content

Commit 1028153

Browse files
committed
Make ReadDouble locale-independent
1 parent 0981d44 commit 1028153

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

include/mp/nl.h

+36-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <cstdlib>
5050
#include <limits>
5151
#include <string>
52+
#include <locale.h>
5253

5354
namespace mp {
5455

@@ -920,6 +921,33 @@ class NLHandler {
920921

921922
namespace internal {
922923

924+
// TODO: test
925+
class Locale {
926+
private:
927+
locale_t locale_;
928+
929+
locale_t dup() const {
930+
locale_t copy = duplocale(locale_);
931+
if (!copy)
932+
throw fmt::SystemError(errno, "cannot duplicate locale");
933+
return copy;
934+
}
935+
936+
public:
937+
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", NULL)) {
938+
if (!locale_)
939+
throw fmt::SystemError(errno, "cannot create locale");
940+
}
941+
Locale(const Locale &other) : locale_(other.dup()) {}
942+
Locale &operator=(const Locale &other) {
943+
locale_ = other.dup();
944+
return *this;
945+
}
946+
~Locale() { freelocale(locale_); }
947+
948+
locale_t get() const { return locale_; }
949+
};
950+
923951
class ReaderBase {
924952
protected:
925953
const char *ptr_, *start_, *end_;
@@ -947,6 +975,7 @@ class TextReader : public ReaderBase {
947975
private:
948976
const char *line_start_;
949977
int line_;
978+
Locale locale_;
950979

951980
// Reads an integer without a sign.
952981
// Int: signed or unsigned integer type.
@@ -1058,11 +1087,14 @@ class TextReader : public ReaderBase {
10581087

10591088
double ReadDouble() {
10601089
SkipSpace();
1061-
char *end = 0;
1090+
const char *end = ptr_;
10621091
double value = 0;
1063-
if (*ptr_ != '\n')
1064-
value = std::strtod(ptr_, &end);
1065-
if (!end || ptr_ == end)
1092+
if (*ptr_ != '\n') {
1093+
char *mut_end = 0;
1094+
value = strtod_l(ptr_, &mut_end, locale_.get());
1095+
end = mut_end;
1096+
}
1097+
if (ptr_ == end)
10661098
ReportError("expected double");
10671099
ptr_ = end;
10681100
return value;

0 commit comments

Comments
 (0)