diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2018-05-14 18:24:40 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-05-14 18:24:40 +0000 |
commit | 77c223be193b303b833053a757a2f1f2534da610 (patch) | |
tree | 6616209c2e4b804169708185cd50428662db359c /core/fxcrt | |
parent | ff3d00d703dd0273922fbae12d0ee50a14667657 (diff) | |
download | pdfium-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>
Diffstat (limited to 'core/fxcrt')
-rw-r--r-- | core/fxcrt/fx_extension.cpp | 32 | ||||
-rw-r--r-- | core/fxcrt/fx_extension_unittest.cpp | 37 |
2 files changed, 69 insertions, 0 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); +} |