summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2018-05-14 18:24:40 +0000
committerChromium commit bot <commit-bot@chromium.org>2018-05-14 18:24:40 +0000
commit77c223be193b303b833053a757a2f1f2534da610 (patch)
tree6616209c2e4b804169708185cd50428662db359c
parentff3d00d703dd0273922fbae12d0ee50a14667657 (diff)
downloadpdfium-77c223be193b303b833053a757a2f1f2534da610.tar.xz
Use internal wcstof instead of system wcstod in formcalc lexer
This CL switches the usage of wcstod to use the FXSYS_wcstof to determine if a given string is a valid floating point number. Using the internal method makes linux slightly slower (10's of ms) makes mac a lot faster 900ms to 60ms for the test case in the bug. The FXSYS_wcstof method has been extended to handle the parsing of float exponents. Unittests were added for FXSYS_wcstof. Bug: chromium:813646 Change-Id: Ie68287a336e3b95a0c0b845d5bf39db6fc82b39c Reviewed-on: https://pdfium-review.googlesource.com/32510 Reviewed-by: Ryan Harrison <rharrison@chromium.org> Commit-Queue: dsinclair <dsinclair@chromium.org>
-rw-r--r--core/fxcrt/fx_extension.cpp32
-rw-r--r--core/fxcrt/fx_extension_unittest.cpp37
-rw-r--r--xfa/fxfa/fm2js/cxfa_fmlexer.cpp8
3 files changed, 74 insertions, 3 deletions
diff --git a/core/fxcrt/fx_extension.cpp b/core/fxcrt/fx_extension.cpp
index 83aee86316..b1f2a95d62 100644
--- a/core/fxcrt/fx_extension.cpp
+++ b/core/fxcrt/fx_extension.cpp
@@ -50,6 +50,38 @@ float FXSYS_wcstof(const wchar_t* pwsStr, int32_t iLength, int32_t* pUsedLen) {
fPrecise *= 0.1f;
}
}
+
+ if (iUsedLen < iLength &&
+ (pwsStr[iUsedLen] == 'e' || pwsStr[iUsedLen] == 'E')) {
+ ++iUsedLen;
+
+ bool negative_exponent = false;
+ if (iUsedLen < iLength &&
+ (pwsStr[iUsedLen] == '-' || pwsStr[iUsedLen] == '+')) {
+ negative_exponent = pwsStr[iUsedLen] == '-';
+ ++iUsedLen;
+ }
+
+ size_t exp_value = 0;
+ while (iUsedLen < iLength) {
+ wchar_t wch = pwsStr[iUsedLen];
+ if (!std::iswdigit(wch))
+ break;
+
+ exp_value = exp_value * 10.0f + (wch - L'0');
+ ++iUsedLen;
+ }
+
+ for (size_t i = exp_value; i > 0; --i) {
+ if (exp_value > 0) {
+ if (negative_exponent)
+ fValue /= 10;
+ else
+ fValue *= 10;
+ }
+ }
+ }
+
if (pUsedLen)
*pUsedLen = iUsedLen;
diff --git a/core/fxcrt/fx_extension_unittest.cpp b/core/fxcrt/fx_extension_unittest.cpp
index 0500a14b6f..f7e07c7c65 100644
--- a/core/fxcrt/fx_extension_unittest.cpp
+++ b/core/fxcrt/fx_extension_unittest.cpp
@@ -112,3 +112,40 @@ TEST(fxcrt, GetBits32) {
}
}
}
+
+TEST(fxcrt, FXSYS_wcstof) {
+ int32_t used_len = 0;
+ EXPECT_FLOAT_EQ(-12.0f, FXSYS_wcstof(L"-12", 3, &used_len));
+ EXPECT_EQ(3, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(1.5362f, FXSYS_wcstof(L"1.5362", 6, &used_len));
+ EXPECT_EQ(6, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(0.875f, FXSYS_wcstof(L"0.875", 5, &used_len));
+ EXPECT_EQ(5, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(5.56e-2f, FXSYS_wcstof(L"5.56e-2", 7, &used_len));
+ EXPECT_EQ(7, used_len);
+
+ used_len = 0;
+ EXPECT_FLOAT_EQ(1.234e10f, FXSYS_wcstof(L"1.234E10", 8, &used_len));
+ EXPECT_EQ(8, used_len);
+
+ // TODO(dsinclair): This should round as per IEEE 64-bit values.
+ // EXPECT_EQ(L"123456789.01234567", FXSYS_wcstof(L"123456789.012345678"));
+ used_len = 0;
+ EXPECT_FLOAT_EQ(123456789.012345678f,
+ FXSYS_wcstof(L"123456789.012345678", 19, &used_len));
+ EXPECT_EQ(19, used_len);
+
+ // TODO(dsinclair): This is spec'd as rounding when > 16 significant digits
+ // prior to the exponent.
+ // EXPECT_EQ(100000000000000000, FXSYS_wcstof(L"99999999999999999"));
+ used_len = 0;
+ EXPECT_FLOAT_EQ(99999999999999999.0f,
+ FXSYS_wcstof(L"99999999999999999", 17, &used_len));
+ EXPECT_EQ(17, used_len);
+}
diff --git a/xfa/fxfa/fm2js/cxfa_fmlexer.cpp b/xfa/fxfa/fm2js/cxfa_fmlexer.cpp
index 32e29575c5..3a694675b7 100644
--- a/xfa/fxfa/fm2js/cxfa_fmlexer.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmlexer.cpp
@@ -303,10 +303,12 @@ CXFA_FMToken CXFA_FMLexer::NextToken() {
CXFA_FMToken CXFA_FMLexer::AdvanceForNumber() {
// This will set end to the character after the end of the number.
- wchar_t* end = nullptr;
+ int32_t used_length = 0;
if (m_cursor)
- wcstod(const_cast<wchar_t*>(m_cursor), &end);
- if (!end || FXSYS_iswalpha(*end)) {
+ FXSYS_wcstof(const_cast<wchar_t*>(m_cursor), -1, &used_length);
+
+ const wchar_t* end = m_cursor + used_length;
+ if (used_length == 0 || !end || FXSYS_iswalpha(*end)) {
RaiseError();
return CXFA_FMToken();
}