Revert "Cleanup CJS_PublicMethods::ParseNumber"

This reverts commit 4cd5b80e70e5fc50d8bd805cfa3c7b54878a0a35.
Reason for revert: broke tests on windows

TBR=tombergan@chromium.org
TBR=thestig@chromium.org

Review URL: https://codereview.chromium.org/1573243016 .
diff --git a/fpdfsdk/src/javascript/Field.cpp b/fpdfsdk/src/javascript/Field.cpp
index ebd3d33..959e8dc 100644
--- a/fpdfsdk/src/javascript/Field.cpp
+++ b/fpdfsdk/src/javascript/Field.cpp
@@ -2741,8 +2741,13 @@
         CFX_WideString swValue = pFormField->GetValue();
 
         double dRet;
-        if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) {
-          vp << dRet;
+        FX_BOOL bDot;
+        if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet,
+                                                     bDot)) {
+          if (bDot)
+            vp << dRet;
+          else
+            vp << dRet;
         } else {
           vp << swValue;
         }
@@ -2764,8 +2769,13 @@
           CFX_WideString swValue = pFormField->GetValue();
 
           double dRet;
-          if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) {
-            vp << dRet;
+          FX_BOOL bDot;
+          if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet,
+                                                       bDot)) {
+            if (bDot)
+              vp << dRet;
+            else
+              vp << dRet;
           } else {
             vp << swValue;
           }
@@ -2780,7 +2790,9 @@
 
           CFX_WideString swValue = pFormField->GetControl(i)->GetExportValue();
           double dRet;
-          if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) {
+          FX_BOOL bDotDummy;
+          if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet,
+                                                       bDotDummy)) {
             vp << dRet;
           } else {
             vp << swValue;
diff --git a/fpdfsdk/src/javascript/PublicMethods.cpp b/fpdfsdk/src/javascript/PublicMethods.cpp
index 9e5ad5d..d2f7fb0 100644
--- a/fpdfsdk/src/javascript/PublicMethods.cpp
+++ b/fpdfsdk/src/javascript/PublicMethods.cpp
@@ -194,38 +194,147 @@
   return StrRTrim(StrLTrim(pStr));
 }
 
-FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource,
-                                                 double& dRet) {
-  CFX_ByteString sDigits = CFX_WideString(swSource).UTF8Encode();
+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;
 
-  // Always interpret "," as "." independent of the locale.
-  for (FX_STRSIZE k = 0; k < sDigits.GetLength(); k++) {
-    if (sDigits[k] == ',')
-      sDigits.SetAt(k, '.');
+  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++;
   }
 
-  // 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 (!pStart) {
+    bAllDigits = FALSE;
+    return 0;
   }
-  for (; *pEnd; pEnd++) {
-    if (!isspace(*pEnd)) {
-      dRet = 0;
-      return FALSE;
+
+  while (pEnd != pStart) {
+    if (*pEnd == L' ')
+      pEnd--;
+    else
+      break;
+  }
+
+  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++;
+  }
+
+  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);
+      }
     }
   }
 
-  return TRUE;
+  return dRet;
 }
 
 double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) {
-  double dRet;
-  ConvertStringToNumber(swSource, dRet);
-  return dRet;
+  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;
 }
 
 CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime,
diff --git a/fpdfsdk/src/javascript/PublicMethods.h b/fpdfsdk/src/javascript/PublicMethods.h
index 0172cba..013c4ce 100644
--- a/fpdfsdk/src/javascript/PublicMethods.h
+++ b/fpdfsdk/src/javascript/PublicMethods.h
@@ -144,11 +144,18 @@
                                 bool* bWrongFormat);
   static CFX_WideString MakeFormatDate(double dDate,
                                        const CFX_WideString& format);
-  static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource, double& dRet);
+  static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource,
+                                       double& dRet,
+                                       FX_BOOL& bDot);
   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);
diff --git a/testing/resources/javascript/bug_361_expected.txt b/testing/resources/javascript/bug_361_expected.txt
index da92562..f7f7a56 100644
--- a/testing/resources/javascript/bug_361_expected.txt
+++ b/testing/resources/javascript/bug_361_expected.txt
@@ -12,31 +12,31 @@
 Alert: Answer for "4 3 2 1" is: string 4 3 2 1
 Alert: Answer for "-4" is: number -4
 Alert: Answer for "23.00000001" is: number 23.00000001
-Alert: Answer for "23.00000000000000001" is: number 23
+Alert: Answer for "23.00000000000000001" is: number 0
 Alert: Answer for "4e+25" is: number 4e+25
-Alert: Answer for "40000000000000000000000000" is: number 4e+25
+Alert: Answer for "40000000000000000000000000" is: number 0
 Alert: Answer for "25,5" is: number 25.5
 Alert: Answer for "1e+5" is: number 100000
-Alert: Answer for "1e5" is: number 100000
+Alert: Answer for "1e5" is: number 1
 Alert: Answer for "1e-5" is: number 0.00001
 Alert: Answer for "-1e-5" is: number -0.00001
-Alert: Answer for "1.2e5" is: number 120000
-Alert: Answer for "Infinity" is: number Infinity
-Alert: Answer for "Infinity" is: number Infinity
-Alert: Answer for "INFINITY" is: number Infinity
-Alert: Answer for "INF" is: number Infinity
-Alert: Answer for "NaN" is: number NaN
-Alert: Answer for "NaN" is: number NaN
-Alert: Answer for "NAN" is: number NaN
-Alert: Answer for "0x100" is: number 256
-Alert: Answer for "0x100.1" is: number 256.0625
-Alert: Answer for "0x100,1" is: number 256.0625
+Alert: Answer for "1.2e5" is: number 1.2
+Alert: Answer for "Infinity" is: string Infinity
+Alert: Answer for "Infinity" is: string Infinity
+Alert: Answer for "INFINITY" is: string INFINITY
+Alert: Answer for "INF" is: string INF
+Alert: Answer for "NaN" is: string NaN
+Alert: Answer for "NaN" is: string NaN
+Alert: Answer for "NAN" is: string NAN
+Alert: Answer for "0x100" is: string 0x100
+Alert: Answer for "0x100.1" is: string 0x100.1
+Alert: Answer for "0x100,1" is: string 0x100,1
 Alert: Answer for "0x100x1" is: string 0x100x1
 Alert: Answer for "123x6" is: string 123x6
 Alert: Answer for "123xy6" is: string 123xy6
 Alert: Answer for "123.y6" is: string 123.y6
-Alert: Answer for "1,000,000" is: string 1,000,000
-Alert: Answer for "1.2.3" is: string 1.2.3
+Alert: Answer for "1,000,000" is: number 1
+Alert: Answer for "1.2.3" is: number 1.2
 Alert: Answer for "1-3" is: string 1-3
 Alert: Answer for "1+3" is: string 1+3
 Alert: Answer for "1.-3" is: string 1.-3