Improve robustness of FloatToString.
When converting floats to string, we now enforce the "C" locale, so decimal points will be written as "." rather than the "," separator used natively in some European locales. Also, we now use operator>> to read back the number instead of std::stof. std::stof works in the system locale, and will fail to read back floats with the wrong decimal separator. (Also, std::stof will throw if the number is out of range and can't fit in the destination, which implies that the `if` check was probably never failing.) Skia encountered similar issues: see http://review.skia.org/587536 for the Skia implementation. Change-Id: I5aded6acc7cfcf2ad4d5b974bc30c3b645eaec51 Bug: dawn:1686 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104680 Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
8a833840d1
commit
761536d941
|
@ -30,13 +30,19 @@ std::string FloatToString(float f) {
|
||||||
// precision
|
// precision
|
||||||
std::stringstream fixed;
|
std::stringstream fixed;
|
||||||
fixed.flags(fixed.flags() | std::ios_base::showpoint | std::ios_base::fixed);
|
fixed.flags(fixed.flags() | std::ios_base::showpoint | std::ios_base::fixed);
|
||||||
|
fixed.imbue(std::locale::classic());
|
||||||
fixed.precision(9);
|
fixed.precision(9);
|
||||||
fixed << f;
|
fixed << f;
|
||||||
|
std::string str = fixed.str();
|
||||||
|
|
||||||
|
// If this string can be parsed without loss of information, use it.
|
||||||
|
// (Use double here to dodge a bug in older libc++ versions which
|
||||||
|
// would incorrectly read back FLT_MAX as INF.)
|
||||||
|
double roundtripped;
|
||||||
|
fixed >> roundtripped;
|
||||||
|
|
||||||
// If this string can be parsed without loss of information, use it
|
|
||||||
auto float_equal_no_warning = std::equal_to<float>();
|
auto float_equal_no_warning = std::equal_to<float>();
|
||||||
if (float_equal_no_warning(std::stof(fixed.str()), f)) {
|
if (float_equal_no_warning(f, static_cast<float>(roundtripped))) {
|
||||||
auto str = fixed.str();
|
|
||||||
while (str.length() >= 2 && str[str.size() - 1] == '0' && str[str.size() - 2] != '.') {
|
while (str.length() >= 2 && str[str.size() - 1] == '0' && str[str.size() - 2] != '.') {
|
||||||
str.pop_back();
|
str.pop_back();
|
||||||
}
|
}
|
||||||
|
@ -47,6 +53,7 @@ std::string FloatToString(float f) {
|
||||||
// Resort to scientific, with the minimum precision needed to preserve the
|
// Resort to scientific, with the minimum precision needed to preserve the
|
||||||
// whole float
|
// whole float
|
||||||
std::stringstream sci;
|
std::stringstream sci;
|
||||||
|
sci.imbue(std::locale::classic());
|
||||||
sci.precision(std::numeric_limits<float>::max_digits10);
|
sci.precision(std::numeric_limits<float>::max_digits10);
|
||||||
sci << f;
|
sci << f;
|
||||||
return sci.str();
|
return sci.str();
|
||||||
|
|
Loading…
Reference in New Issue