diff options
author | Tom Sepez <tsepez@chromium.org> | 2016-01-14 17:25:08 -0800 |
---|---|---|
committer | Tom Sepez <tsepez@chromium.org> | 2016-01-14 17:25:08 -0800 |
commit | 4cd5b80e70e5fc50d8bd805cfa3c7b54878a0a35 (patch) | |
tree | cb9465e37aa1495d01adbed07d351ab36930e8e2 /fpdfsdk | |
parent | 5b2bc895384749493f2ec2ca818c485797448cae (diff) | |
download | pdfium-4cd5b80e70e5fc50d8bd805cfa3c7b54878a0a35.tar.xz |
Cleanup CJS_PublicMethods::ParseNumber
Original patch by tombergan.
The old version of this function was basically strtod with a few quirks:
1. It always interpreted ',' as '.' independent of locale. I kept this
behavior, to be conservative.
2. It interpreted the first non-number character as a decimal point,
unless there was a prior decimal point, in which case all characters
up to that point are ignored. This would parse "123z4" as "123.4"
and "123xy6" as "6". I did not keep this behavior -- in the new code,
these examples all fail to parse.
The new ParseNumber was inlined into ConvertStringToNumber, which
returns true on success and (false, 0) on failure.
BUG=pdfium:361
R=tsepez@chromium.org
Review URL: https://codereview.chromium.org/1582013002 .
Diffstat (limited to 'fpdfsdk')
-rw-r--r-- | fpdfsdk/src/javascript/Field.cpp | 22 | ||||
-rw-r--r-- | fpdfsdk/src/javascript/PublicMethods.cpp | 153 | ||||
-rw-r--r-- | fpdfsdk/src/javascript/PublicMethods.h | 9 |
3 files changed, 28 insertions, 156 deletions
diff --git a/fpdfsdk/src/javascript/Field.cpp b/fpdfsdk/src/javascript/Field.cpp index 959e8dcadd..ebd3d331f5 100644 --- a/fpdfsdk/src/javascript/Field.cpp +++ b/fpdfsdk/src/javascript/Field.cpp @@ -2741,13 +2741,8 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetValue(); double dRet; - FX_BOOL bDot; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, - bDot)) { - if (bDot) - vp << dRet; - else - vp << dRet; + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { + vp << dRet; } else { vp << swValue; } @@ -2769,13 +2764,8 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetValue(); double dRet; - FX_BOOL bDot; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, - bDot)) { - if (bDot) - vp << dRet; - else - vp << dRet; + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { + vp << dRet; } else { vp << swValue; } @@ -2790,9 +2780,7 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetControl(i)->GetExportValue(); double dRet; - FX_BOOL bDotDummy; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, - bDotDummy)) { + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { vp << dRet; } else { vp << swValue; diff --git a/fpdfsdk/src/javascript/PublicMethods.cpp b/fpdfsdk/src/javascript/PublicMethods.cpp index d2f7fb09ac..9e5ad5d182 100644 --- a/fpdfsdk/src/javascript/PublicMethods.cpp +++ b/fpdfsdk/src/javascript/PublicMethods.cpp @@ -194,147 +194,38 @@ CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) { return StrRTrim(StrLTrim(pStr)); } -double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource, - FX_BOOL& bAllDigits, - FX_BOOL& bDot, - FX_BOOL& bSign, - FX_BOOL& bKXJS) { - bDot = FALSE; - bSign = FALSE; - bKXJS = FALSE; - - FX_BOOL bDigitExist = FALSE; - - const FX_WCHAR* p = swSource; - wchar_t c; - - const FX_WCHAR* pStart = NULL; - const FX_WCHAR* pEnd = NULL; - - while ((c = *p)) { - if (!pStart && c != L' ') { - pStart = p; - } - - pEnd = p; - p++; - } - - if (!pStart) { - bAllDigits = FALSE; - return 0; - } +FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource, + double& dRet) { + CFX_ByteString sDigits = CFX_WideString(swSource).UTF8Encode(); - while (pEnd != pStart) { - if (*pEnd == L' ') - pEnd--; - else - break; + // Always interpret "," as "." independent of the locale. + for (FX_STRSIZE k = 0; k < sDigits.GetLength(); k++) { + if (sDigits[k] == ',') + sDigits.SetAt(k, '.'); } - double dRet = 0; - p = pStart; - bAllDigits = TRUE; - CFX_WideString swDigits; - - while (p <= pEnd) { - c = *p; - - if (FXSYS_iswdigit(c)) { - swDigits += c; - bDigitExist = TRUE; - } else { - switch (c) { - case L' ': - bAllDigits = FALSE; - break; - case L'.': - case L',': - if (!bDot) { - if (bDigitExist) { - swDigits += L'.'; - } else { - swDigits += L'0'; - swDigits += L'.'; - bDigitExist = TRUE; - } - - bDot = TRUE; - break; - } - case 'e': - case 'E': - if (!bKXJS) { - p++; - c = *p; - if (c == '+' || c == '-') { - bKXJS = TRUE; - swDigits += 'e'; - swDigits += c; - } - break; - } - case L'-': - if (!bDigitExist && !bSign) { - swDigits += c; - bSign = TRUE; - break; - } - default: - bAllDigits = FALSE; - - if (p != pStart && !bDot && bDigitExist) { - swDigits += L'.'; - bDot = TRUE; - } else { - bDot = FALSE; - bDigitExist = FALSE; - swDigits = L""; - } - break; - } - } - - p++; + // Parse a number, ignoring leading and trailing whitespace. + // Fail if there is trailing garbage. + const char* pStart = sDigits.c_str(); + const char* pEnd = NULL; + dRet = strtod(pStart, const_cast<char**>(&pEnd)); + if (pEnd == pStart) { + return FALSE; } - - if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) { - CFX_ByteString sDigits = swDigits.UTF8Encode(); - - if (bKXJS) { - dRet = atof(sDigits); - } else { - if (bDot) { - char* pStopString; - dRet = ::strtod(sDigits, &pStopString); - } else { - dRet = atol(sDigits); - } + for (; *pEnd; pEnd++) { + if (!isspace(*pEnd)) { + dRet = 0; + return FALSE; } } - return dRet; + return TRUE; } double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) { - FX_BOOL bAllDigits = FALSE; - FX_BOOL bDot = FALSE; - FX_BOOL bSign = FALSE; - FX_BOOL bKXJS = FALSE; - - return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS); -} - -FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource, - double& dRet, - FX_BOOL& bDot) { - FX_BOOL bAllDigits = FALSE; - FX_BOOL bSign = FALSE; - FX_BOOL bKXJS = FALSE; - - dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS); - - return bAllDigits; + double dRet; + ConvertStringToNumber(swSource, dRet); + return dRet; } CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime, diff --git a/fpdfsdk/src/javascript/PublicMethods.h b/fpdfsdk/src/javascript/PublicMethods.h index 013c4ce1a4..0172cbafb8 100644 --- a/fpdfsdk/src/javascript/PublicMethods.h +++ b/fpdfsdk/src/javascript/PublicMethods.h @@ -144,18 +144,11 @@ class CJS_PublicMethods : public CJS_Object { bool* bWrongFormat); static CFX_WideString MakeFormatDate(double dDate, const CFX_WideString& format); - static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource, - double& dRet, - FX_BOOL& bDot); + static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource, double& dRet); static double ParseStringToNumber(const FX_WCHAR* swSource); static double ParseNormalDate(const CFX_WideString& value, bool* bWrongFormat); static double MakeInterDate(CFX_WideString strValue); - static double ParseNumber(const FX_WCHAR* swSource, - FX_BOOL& bAllDigits, - FX_BOOL& bDot, - FX_BOOL& bSign, - FX_BOOL& bKXJS); public: static CFX_WideString StrLTrim(const FX_WCHAR* pStr); |