Changed direct calls to strtod to use StringToNumber

StringToNumber will correctly use locale-insensitive functions
when available.

Change-Id: I6bde11039a541634186f8f791012af2eb0d86b8d
This commit is contained in:
Wouter van Oortmerssen 2020-01-09 11:47:02 -08:00
parent 718351831d
commit 55686100aa
3 changed files with 25 additions and 8 deletions

View File

@ -491,7 +491,11 @@ class Reference {
case FBT_INDIRECT_UINT: case FBT_INDIRECT_UINT:
return static_cast<double>(ReadUInt64(Indirect(), byte_width_)); return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
case FBT_NULL: return 0.0; case FBT_NULL: return 0.0;
case FBT_STRING: return strtod(AsString().c_str(), nullptr); case FBT_STRING: {
double d;
flatbuffers::StringToNumber(AsString().c_str(), &d);
return d;
}
case FBT_VECTOR: return static_cast<double>(AsVector().size()); case FBT_VECTOR: return static_cast<double>(AsVector().size());
case FBT_BOOL: case FBT_BOOL:
return static_cast<double>(ReadUInt64(data_, parent_width_)); return static_cast<double>(ReadUInt64(data_, parent_width_));

View File

@ -2764,10 +2764,13 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
builder->Int(StringToInt(attribute_.c_str())); builder->Int(StringToInt(attribute_.c_str()));
EXPECT(kTokenIntegerConstant); EXPECT(kTokenIntegerConstant);
break; break;
case kTokenFloatConstant: case kTokenFloatConstant: {
builder->Double(strtod(attribute_.c_str(), nullptr)); double d;
StringToNumber(attribute_.c_str(), &d);
builder->Double(d);
EXPECT(kTokenFloatConstant); EXPECT(kTokenFloatConstant);
break; break;
}
default: default:
if (IsIdent("true")) { if (IsIdent("true")) {
builder->Bool(true); builder->Bool(true);
@ -3220,13 +3223,14 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
auto docs__ = parser.opts.binary_schema_comments auto docs__ = parser.opts.binary_schema_comments
? builder->CreateVectorOfStrings(doc_comment) ? builder->CreateVectorOfStrings(doc_comment)
: 0; : 0;
double d;
StringToNumber(value.constant.c_str(), &d);
return reflection::CreateField( return reflection::CreateField(
*builder, name__, type__, id, value.offset, *builder, name__, type__, id, value.offset,
// Is uint64>max(int64) tested? // Is uint64>max(int64) tested?
IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0, IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
// result may be platform-dependent if underlying is float (not double) // result may be platform-dependent if underlying is float (not double)
IsFloat(value.type.base_type) ? strtod(value.constant.c_str(), nullptr) IsFloat(value.type.base_type) ? d : 0.0,
: 0.0,
deprecated, required, key, attr__, docs__); deprecated, required, key, attr__, docs__);
// TODO: value.constant is almost always "0", we could save quite a bit of // TODO: value.constant is almost always "0", we could save quite a bit of
// space by sharing it. Same for common values of value.type. // space by sharing it. Same for common values of value.type.

View File

@ -56,7 +56,13 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data) {
case reflection::String: { case reflection::String: {
auto s = auto s =
reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data); reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) + data);
return s ? strtod(s->c_str(), nullptr) : 0.0; if (s) {
double d;
StringToNumber(s->c_str(), &d);
return d;
} else {
return 0.0;
}
} }
default: return static_cast<double>(GetAnyValueI(type, data)); default: return static_cast<double>(GetAnyValueI(type, data));
} }
@ -149,9 +155,12 @@ void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) {
void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val) { void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val) {
switch (type) { switch (type) {
case reflection::Float: case reflection::Float:
case reflection::Double: case reflection::Double: {
SetAnyValueF(type, data, strtod(val, nullptr)); double d;
StringToNumber(val, &d);
SetAnyValueF(type, data, d);
break; break;
}
// TODO: support strings. // TODO: support strings.
default: SetAnyValueI(type, data, StringToInt(val)); break; default: SetAnyValueI(type, data, StringToInt(val)); break;
} }