Remove FXSYS_wcstof in favor of system wcstof().
Currently, this always copies, but we can avoid this in many (not all)
cases with a subsequent CL. There is a slight difference with large
numbers, so this is a check that thing still render properly.
Change-Id: Id4c9d061ed69ca59c5fed0e31cd5feb4574c5e6f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117331
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp
index e44879c..8a12e8f 100644
--- a/core/fxcrt/fx_extension.cpp
+++ b/core/fxcrt/fx_extension.cpp
@@ -6,12 +6,12 @@
#include "core/fxcrt/fx_extension.h"
-#include <algorithm>
-#include <limits>
+#include <wchar.h>
#include "core/fxcrt/check.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/utf16.h"
+#include "core/fxcrt/widestring.h"
namespace {
@@ -29,98 +29,16 @@
} // namespace
float FXSYS_wcstof(const wchar_t* pwsStr, size_t nLength, size_t* pUsedLen) {
- // SAFETY: TODO(tsepez): This is an enormous unsafe block, pretty hard to
- // explain its soundness.
- UNSAFE_BUFFERS({
- DCHECK(pwsStr);
- if (nLength == 0) {
- return 0.0f;
- }
-
- size_t nUsedLen = 0;
- bool bNegtive = false;
- switch (pwsStr[nUsedLen]) {
- case '-':
- bNegtive = true;
- [[fallthrough]];
- case '+':
- nUsedLen++;
- break;
- }
-
- double dValue = 0.0f;
- while (nUsedLen < nLength) {
- wchar_t wch = pwsStr[nUsedLen];
- if (!FXSYS_IsDecimalDigit(wch))
- break;
-
- dValue = dValue * 10.0f + (wch - L'0');
- nUsedLen++;
- }
-
- if (nUsedLen < nLength && pwsStr[nUsedLen] == L'.') {
- float fPrecise = 0.1f;
- while (++nUsedLen < nLength) {
- wchar_t wch = pwsStr[nUsedLen];
- if (!FXSYS_IsDecimalDigit(wch)) {
- break;
- }
-
- dValue += (wch - L'0') * fPrecise;
- fPrecise *= 0.1f;
- }
- }
-
- if (nUsedLen < nLength &&
- (pwsStr[nUsedLen] == 'e' || pwsStr[nUsedLen] == 'E')) {
- ++nUsedLen;
-
- bool negative_exponent = false;
- if (nUsedLen < nLength &&
- (pwsStr[nUsedLen] == '-' || pwsStr[nUsedLen] == '+')) {
- negative_exponent = pwsStr[nUsedLen] == '-';
- ++nUsedLen;
- }
-
- int32_t exp_value = 0;
- while (nUsedLen < nLength) {
- wchar_t wch = pwsStr[nUsedLen];
- if (!FXSYS_IsDecimalDigit(wch)) {
- break;
- }
-
- exp_value = exp_value * 10.0f + (wch - L'0');
- // Exponent is outside the valid range, fail.
- if ((negative_exponent &&
- -exp_value < std::numeric_limits<float>::min_exponent10) ||
- (!negative_exponent &&
- exp_value > std::numeric_limits<float>::max_exponent10)) {
- if (pUsedLen) {
- *pUsedLen = 0;
- }
- return 0.0f;
- }
-
- ++nUsedLen;
- }
-
- for (size_t i = exp_value; i > 0; --i) {
- if (exp_value > 0) {
- if (negative_exponent) {
- dValue /= 10;
- } else {
- dValue *= 10;
- }
- }
- }
- }
-
- if (pUsedLen) {
- *pUsedLen = nUsedLen;
- }
-
- return static_cast<float>(bNegtive ? -dValue : dValue);
- });
+ WideString copied(pwsStr, nLength);
+ wchar_t* endptr = nullptr;
+ float result = wcstof(copied.c_str(), &endptr);
+ if (result != result) {
+ result = 0.0f; // Convert NAN to 0.0f;
+ }
+ if (pUsedLen) {
+ *pUsedLen = endptr - copied.c_str();
+ }
+ return result;
}
wchar_t* FXSYS_wcsncpy(wchar_t* dstStr, const wchar_t* srcStr, size_t count) {
diff --git a/core/fxcrt/fx_extension_unittest.cpp b/core/fxcrt/fx_extension_unittest.cpp
index 8f503c2..809c77e 100644
--- a/core/fxcrt/fx_extension_unittest.cpp
+++ b/core/fxcrt/fx_extension_unittest.cpp
@@ -136,10 +136,38 @@
EXPECT_EQ(3u, used_len);
used_len = 0;
+ EXPECT_FLOAT_EQ(12.0f, FXSYS_wcstof(L"+12", 3, &used_len));
+ EXPECT_EQ(3u, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(123.0f, FXSYS_wcstof(L" 123", 4, &used_len));
+ EXPECT_EQ(4u, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(123.0f, FXSYS_wcstof(L" 123 ", 5, &used_len));
+ EXPECT_EQ(4u, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(1.0f, FXSYS_wcstof(L" 1 2 3 ", 7, &used_len));
+ EXPECT_EQ(2u, used_len);
+
+ used_len = 0;
EXPECT_FLOAT_EQ(1.5362f, FXSYS_wcstof(L"1.5362", 6, &used_len));
EXPECT_EQ(6u, used_len);
used_len = 0;
+ EXPECT_FLOAT_EQ(1.0f, FXSYS_wcstof(L"1 .5362", 7, &used_len));
+ EXPECT_EQ(1u, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(1.0f, FXSYS_wcstof(L"1. 5362", 7, &used_len));
+ EXPECT_EQ(2u, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(1.5f, FXSYS_wcstof(L"1.5.3.6.2", 9, &used_len));
+ EXPECT_EQ(3u, used_len);
+
+ used_len = 0;
EXPECT_FLOAT_EQ(0.875f, FXSYS_wcstof(L"0.875", 5, &used_len));
EXPECT_EQ(5u, used_len);
@@ -152,12 +180,12 @@
EXPECT_EQ(8u, used_len);
used_len = 0;
- EXPECT_FLOAT_EQ(0.0f, FXSYS_wcstof(L"1.234E100000000000000", 21, &used_len));
- EXPECT_EQ(0u, used_len);
+ EXPECT_TRUE(isinf(FXSYS_wcstof(L"1.234E100000000000000", 21, &used_len)));
+ EXPECT_EQ(21u, used_len);
used_len = 0;
EXPECT_FLOAT_EQ(0.0f, FXSYS_wcstof(L"1.234E-128", 10, &used_len));
- EXPECT_EQ(0u, used_len);
+ EXPECT_EQ(10u, used_len);
// TODO(dsinclair): This should round as per IEEE 64-bit values.
// EXPECT_EQ(L"123456789.01234567", FXSYS_wcstof(L"123456789.012345678"));