Avoid some WideString construction inside FX_ParseDateUsingFormat().

Be smarter about parsing month strings and avoid code paths when it is
obvious the matching will never succeed. Remove ParseStringString() in
the process, but keep the useful bits as FindSubWordLength().

BUG=chromium:935241

Change-Id: Iab35feaa4d035959cdcc98ba6c9d022a3cf9f26e
Reviewed-on: https://pdfium-review.googlesource.com/c/51191
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
diff --git a/fxjs/fx_date_helpers.cpp b/fxjs/fx_date_helpers.cpp
index 9feda50..15f762d 100644
--- a/fxjs/fx_date_helpers.cpp
+++ b/fxjs/fx_date_helpers.cpp
@@ -164,16 +164,11 @@
   }
 }
 
-// TODO(thestig): Consider returning a WideStringView to make this even faster.
-WideString ParseStringString(const WideString& str,
-                             size_t nStart,
-                             size_t* pSkip) {
+size_t FindSubWordLength(const WideString& str, size_t nStart) {
   size_t i = nStart;
   while (i < str.GetLength() && std::iswalnum(str[i]))
     ++i;
-
-  *pSkip = i - nStart;
-  return str.Mid(nStart, *pSkip);
+  return i - nStart;
 }
 
 }  // namespace
@@ -187,6 +182,9 @@
                                         L"July",    L"August",   L"September",
                                         L"October", L"November", L"December"};
 
+static constexpr size_t KMonthAbbreviationLength = 3;  // Anything in |kMonths|.
+static constexpr size_t kLongestFullMonthLength = 9;   // September
+
 double FX_GetDateTime() {
   if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
     return 0;
@@ -438,15 +436,18 @@
         } else if (remaining == 2 || format[i + 3] != c) {
           switch (c) {
             case 'm': {
-              WideString sMonth = ParseStringString(value, j, &nSkip);
               bool bFind = false;
-              for (size_t m = 0; m < FX_ArraySize(kMonths); ++m) {
-                if (sMonth.CompareNoCase(kMonths[m]) == 0) {
-                  nMonth = m + 1;
-                  i += 3;
-                  j += nSkip;
-                  bFind = true;
-                  break;
+              nSkip = FindSubWordLength(value, j);
+              if (nSkip == KMonthAbbreviationLength) {
+                WideString sMonth = value.Mid(j, KMonthAbbreviationLength);
+                for (size_t m = 0; m < FX_ArraySize(kMonths); ++m) {
+                  if (sMonth.CompareNoCase(kMonths[m]) == 0) {
+                    nMonth = m + 1;
+                    i += 3;
+                    j += nSkip;
+                    bFind = true;
+                    break;
+                  }
                 }
               }
 
@@ -472,18 +473,20 @@
               break;
             case 'm': {
               bool bFind = false;
-
-              WideString sMonth = ParseStringString(value, j, &nSkip);
-              sMonth.MakeLower();
-              for (size_t m = 0; m < FX_ArraySize(kFullMonths); ++m) {
-                WideString sFullMonths = WideString(kFullMonths[m]);
-                sFullMonths.MakeLower();
-                if (sFullMonths.Contains(sMonth.c_str())) {
-                  nMonth = m + 1;
-                  i += 4;
-                  j += nSkip;
-                  bFind = true;
-                  break;
+              nSkip = FindSubWordLength(value, j);
+              if (nSkip <= kLongestFullMonthLength) {
+                WideString sMonth = value.Mid(j, nSkip);
+                sMonth.MakeLower();
+                for (size_t m = 0; m < FX_ArraySize(kFullMonths); ++m) {
+                  WideString sFullMonths = WideString(kFullMonths[m]);
+                  sFullMonths.MakeLower();
+                  if (sFullMonths.Contains(sMonth.c_str())) {
+                    nMonth = m + 1;
+                    i += 4;
+                    j += nSkip;
+                    bFind = true;
+                    break;
+                  }
                 }
               }