|
|
@@ -28,6 +28,53 @@
|
|
|
|
|
|
#include "../DebugNew.h"
|
|
|
|
|
|
+
|
|
|
+// The built-in strtod() function uses the current locale for parsing strings. On certain
|
|
|
+// locales (German, Swedish, ...) a comma is used as decimal separator. For portable XMLs,
|
|
|
+// we need to parse floating point values the same way on all platforms no matter what
|
|
|
+// locale is set. The strtod_c_locale() is a workaround using the "C" locale explicitly,
|
|
|
+// which uses a dot as decimal separator.
|
|
|
+
|
|
|
+#include <locale.h>
|
|
|
+#ifdef __APPLE__
|
|
|
+#include <xlocale.h>
|
|
|
+#endif
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+
|
|
|
+static
|
|
|
+_locale_t get_c_locale()
|
|
|
+{
|
|
|
+ static _locale_t loc = _create_locale(LC_ALL, "C");
|
|
|
+ return loc;
|
|
|
+}
|
|
|
+
|
|
|
+static
|
|
|
+double strtod_c_locale(const char* nptr, char** endptr)
|
|
|
+{
|
|
|
+ return _strtod_l(nptr, endptr, get_c_locale());
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+static
|
|
|
+locale_t get_c_locale()
|
|
|
+{
|
|
|
+ static locale_t loc = newlocale(LC_ALL_MASK, "C", NULL);
|
|
|
+ return loc;
|
|
|
+}
|
|
|
+
|
|
|
+static
|
|
|
+double strtod_c_locale(const char* nptr, char** endptr)
|
|
|
+{
|
|
|
+ return strtod_l(nptr, endptr, get_c_locale());
|
|
|
+}
|
|
|
+
|
|
|
+#endif // _WIN32
|
|
|
+
|
|
|
+
|
|
|
namespace Atomic
|
|
|
{
|
|
|
|
|
|
@@ -146,7 +193,7 @@ float ToFloat(const char* source)
|
|
|
if (!source)
|
|
|
return 0;
|
|
|
|
|
|
- return (float)strtod(source, 0);
|
|
|
+ return (float)strtod_c_locale(source, 0);
|
|
|
}
|
|
|
|
|
|
double ToDouble(const String& source)
|
|
|
@@ -159,7 +206,7 @@ double ToDouble(const char* source)
|
|
|
if (!source)
|
|
|
return 0;
|
|
|
|
|
|
- return strtod(source, 0);
|
|
|
+ return strtod_c_locale(source, 0);
|
|
|
}
|
|
|
|
|
|
Color ToColor(const String& source)
|
|
|
@@ -176,11 +223,11 @@ Color ToColor(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.r_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.g_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.b_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.r_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.g_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.b_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
if (elements > 3)
|
|
|
- ret.a_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.a_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -241,10 +288,10 @@ Rect ToRect(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.min_.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.min_.y_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.max_.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.max_.y_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.min_.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.min_.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.max_.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.max_.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -265,9 +312,9 @@ Quaternion ToQuaternion(const char* source)
|
|
|
{
|
|
|
// 3 coords specified: conversion from Euler angles
|
|
|
float x, y, z;
|
|
|
- x = (float)strtod(ptr, &ptr);
|
|
|
- y = (float)strtod(ptr, &ptr);
|
|
|
- z = (float)strtod(ptr, &ptr);
|
|
|
+ x = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ y = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ z = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return Quaternion(x, y, z);
|
|
|
}
|
|
|
@@ -275,10 +322,10 @@ Quaternion ToQuaternion(const char* source)
|
|
|
{
|
|
|
// 4 coords specified: full quaternion
|
|
|
Quaternion ret;
|
|
|
- ret.w_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.y_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.z_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.w_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.z_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -298,8 +345,8 @@ Vector2 ToVector2(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.y_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -318,9 +365,9 @@ Vector3 ToVector3(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.y_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.z_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.z_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -342,23 +389,23 @@ Vector4 ToVector4(const char* source, bool allowMissingCoords)
|
|
|
if (elements < 4)
|
|
|
return ret;
|
|
|
|
|
|
- ret.x_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.y_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.z_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.w_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.z_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.w_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (elements > 0)
|
|
|
- ret.x_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.x_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
if (elements > 1)
|
|
|
- ret.y_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.y_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
if (elements > 2)
|
|
|
- ret.z_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.z_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
if (elements > 3)
|
|
|
- ret.w_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.w_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -426,15 +473,15 @@ Matrix3 ToMatrix3(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.m00_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m01_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m02_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m10_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m11_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m12_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m20_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m21_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m22_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.m00_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m01_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m02_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m10_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m11_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m12_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m20_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m21_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m22_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -453,18 +500,18 @@ Matrix3x4 ToMatrix3x4(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.m00_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m01_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m02_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m03_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m10_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m11_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m12_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m13_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m20_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m21_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m22_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m23_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.m00_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m01_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m02_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m03_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m10_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m11_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m12_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m13_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m20_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m21_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m22_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m23_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -483,22 +530,22 @@ Matrix4 ToMatrix4(const char* source)
|
|
|
return ret;
|
|
|
|
|
|
char* ptr = (char*)source;
|
|
|
- ret.m00_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m01_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m02_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m03_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m10_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m11_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m12_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m13_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m20_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m21_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m22_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m23_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m30_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m31_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m32_ = (float)strtod(ptr, &ptr);
|
|
|
- ret.m33_ = (float)strtod(ptr, &ptr);
|
|
|
+ ret.m00_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m01_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m02_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m03_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m10_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m11_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m12_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m13_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m20_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m21_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m22_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m23_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m30_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m31_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m32_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
+ ret.m33_ = (float)strtod_c_locale(ptr, &ptr);
|
|
|
|
|
|
return ret;
|
|
|
}
|