Fix sscanf/wcstod parsing of NaNs.
The parsefloat routines -- which let us pass NaNs and infinities on to
strto(f|d|ld) -- come from NetBSD.
Also fix LP64's strtold to return a NaN, and fix all the architectures
to return quiet NaNs.
Also fix wcstof/wcstod/wcstold to use parsefloat so they support hex
floats.
Lots of new tests.
Bug: http://b/31101647
Change-Id: Id7d46ac2d8acb8770b5e8c445e87cfabfde6f111
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 000dc98..db51c08 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -22,6 +22,8 @@
#include <stdint.h>
#include <wchar.h>
+#include "math_data_test.h"
+
#define NUM_WCHARS(num_bytes) ((num_bytes)/sizeof(wchar_t))
TEST(wchar, sizeof_wchar_t) {
@@ -389,14 +391,6 @@
ASSERT_EQ('\x20', *invalid);
}
-TEST(wchar, wcstod) {
- ASSERT_DOUBLE_EQ(1.23, wcstod(L"1.23", NULL));
-}
-
-TEST(wchar, wcstof) {
- ASSERT_FLOAT_EQ(1.23f, wcstof(L"1.23", NULL));
-}
-
TEST(wchar, wcstol) {
ASSERT_EQ(123L, wcstol(L"123", NULL, 0));
}
@@ -405,10 +399,6 @@
ASSERT_EQ(123LL, wcstol(L"123", NULL, 0));
}
-TEST(wchar, wcstold) {
- ASSERT_DOUBLE_EQ(1.23L, wcstold(L"1.23", NULL));
-}
-
TEST(wchar, wcstoul) {
ASSERT_EQ(123UL, wcstoul(L"123", NULL, 0));
}
@@ -672,3 +662,64 @@
wchar_t dst[6];
ASSERT_EQ(&dst[4], wmempcpy(dst, L"hello", 4));
}
+
+template <typename T>
+static void CheckWcsToFloat(T fn(const wchar_t* s, wchar_t** end)) {
+ FpUlpEq<0, T> pred;
+
+ EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"9.0", nullptr));
+ EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0.9e1", nullptr));
+ EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0x1.2p3", nullptr));
+
+ EXPECT_TRUE(isnan(fn(L"+nan", nullptr)));
+ EXPECT_TRUE(isnan(fn(L"nan", nullptr)));
+ EXPECT_TRUE(isnan(fn(L"-nan", nullptr)));
+
+ EXPECT_TRUE(isnan(fn(L"+nan(0xff)", nullptr)));
+ EXPECT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
+ EXPECT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
+
+ wchar_t* p;
+ EXPECT_TRUE(isnan(fn(L"+nanny", &p)));
+ EXPECT_STREQ(L"ny", p);
+ EXPECT_TRUE(isnan(fn(L"nanny", &p)));
+ EXPECT_STREQ(L"ny", p);
+ EXPECT_TRUE(isnan(fn(L"-nanny", &p)));
+ EXPECT_STREQ(L"ny", p);
+
+ EXPECT_EQ(0, fn(L"muppet", &p));
+ EXPECT_STREQ(L"muppet", p);
+ EXPECT_EQ(0, fn(L" muppet", &p));
+ EXPECT_STREQ(L" muppet", p);
+
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+inf", nullptr));
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"inf", nullptr));
+ EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-inf", nullptr));
+
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinity", nullptr));
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinity", nullptr));
+ EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinity", nullptr));
+
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"+infinitude", &p));
+ EXPECT_STREQ(L"initude", p);
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"infinitude", &p));
+ EXPECT_STREQ(L"initude", p);
+ EXPECT_EQ(-std::numeric_limits<T>::infinity(), fn(L"-infinitude", &p));
+ EXPECT_STREQ(L"initude", p);
+
+ // Check case-insensitivity.
+ EXPECT_EQ(std::numeric_limits<T>::infinity(), fn(L"InFiNiTy", nullptr));
+ EXPECT_TRUE(isnan(fn(L"NaN", nullptr)));
+}
+
+TEST(wchar, wcstod) {
+ CheckWcsToFloat(wcstod);
+}
+
+TEST(wchar, wcstof) {
+ CheckWcsToFloat(wcstof);
+}
+
+TEST(wchar, wcstold) {
+ CheckWcsToFloat(wcstold);
+}