Use string view internally in GuessSizeForVSWPrintf()

Inside core/fxcrt/widestring.cpp, change GuessSizeForVSWPrintf() to stop
dealing with pointers. Instead, immediately take the pointer input and
convert it to a string view and then do the equivalent work using string
view APIs.

Bug: 42271176
Change-Id: Ia6f679cb10c79fcc28a866ae0320bbb93f9f51eb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126015
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index a4bdde4..745303b 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -15,11 +15,11 @@
 
 #include "core/fxcrt/check.h"
 #include "core/fxcrt/check_op.h"
-#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/fx_codepage.h"
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_memcpy_wrappers.h"
 #include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/numerics/safe_math.h"
 #include "core/fxcrt/span_util.h"
@@ -59,198 +59,199 @@
 std::optional<size_t> GuessSizeForVSWPrintf(const wchar_t* pFormat,
                                             va_list argList) {
   size_t nMaxLen = 0;
-  UNSAFE_TODO({
-    for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) {
-      if (*pStr != '%' || *(pStr = pStr + 1) == '%') {
-        ++nMaxLen;
-        continue;
-      }
-      int iWidth = 0;
-      for (; *pStr != 0; pStr++) {
-        if (*pStr == '#') {
-          nMaxLen += 2;
-        } else if (*pStr == '*') {
-          iWidth = va_arg(argList, int);
-        } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' &&
-                   *pStr != ' ') {
-          break;
-        }
-      }
-      if (iWidth == 0) {
-        iWidth = FXSYS_wtoi(pStr);
-        while (FXSYS_IsDecimalDigit(*pStr))
-          ++pStr;
-      }
-      if (iWidth < 0 || iWidth > 128 * 1024) {
-        return std::nullopt;
-      }
-      uint32_t nWidth = static_cast<uint32_t>(iWidth);
-      int iPrecision = 0;
-      if (*pStr == '.') {
-        pStr++;
-        if (*pStr == '*') {
-          iPrecision = va_arg(argList, int);
-          pStr++;
-        } else {
-          iPrecision = FXSYS_wtoi(pStr);
-          while (FXSYS_IsDecimalDigit(*pStr)) {
-            ++pStr;
-          }
-        }
-      }
-      if (iPrecision < 0 || iPrecision > 128 * 1024) {
-        return std::nullopt;
-      }
-      uint32_t nPrecision = static_cast<uint32_t>(iPrecision);
-      int nModifier = 0;
-      if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') {
-        pStr += 3;
-        nModifier = FORCE_INT64;
-      } else {
-        switch (*pStr) {
-          case 'h':
-            nModifier = FORCE_ANSI;
-            pStr++;
-            break;
-          case 'l':
-            nModifier = FORCE_UNICODE;
-            pStr++;
-            break;
-          case 'F':
-          case 'N':
-          case 'L':
-            pStr++;
-            break;
-        }
-      }
-      size_t nItemLen = 0;
-      switch (*pStr | nModifier) {
-        case 'c':
-        case 'C':
-          nItemLen = 2;
-          va_arg(argList, int);
-          break;
-        case 'c' | FORCE_ANSI:
-        case 'C' | FORCE_ANSI:
-          nItemLen = 2;
-          va_arg(argList, int);
-          break;
-        case 'c' | FORCE_UNICODE:
-        case 'C' | FORCE_UNICODE:
-          nItemLen = 2;
-          va_arg(argList, int);
-          break;
-        case 's': {
-          const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*);
-          if (pstrNextArg) {
-            nItemLen = wcslen(pstrNextArg);
-            if (nItemLen < 1) {
-              nItemLen = 1;
-            }
-          } else {
-            nItemLen = 6;
-          }
-        } break;
-        case 'S': {
-          const char* pstrNextArg = va_arg(argList, const char*);
-          if (pstrNextArg) {
-            nItemLen = strlen(pstrNextArg);
-            if (nItemLen < 1) {
-              nItemLen = 1;
-            }
-          } else {
-            nItemLen = 6;
-          }
-        } break;
-        case 's' | FORCE_ANSI:
-        case 'S' | FORCE_ANSI: {
-          const char* pstrNextArg = va_arg(argList, const char*);
-          if (pstrNextArg) {
-            nItemLen = strlen(pstrNextArg);
-            if (nItemLen < 1) {
-              nItemLen = 1;
-            }
-          } else {
-            nItemLen = 6;
-          }
-        } break;
-        case 's' | FORCE_UNICODE:
-        case 'S' | FORCE_UNICODE: {
-          const wchar_t* pstrNextArg = va_arg(argList, wchar_t*);
-          if (pstrNextArg) {
-            nItemLen = wcslen(pstrNextArg);
-            if (nItemLen < 1) {
-              nItemLen = 1;
-            }
-          } else {
-            nItemLen = 6;
-          }
-        } break;
-      }
-      if (nItemLen != 0) {
-        if (nPrecision != 0 && nItemLen > nPrecision) {
-          nItemLen = nPrecision;
-        }
-        if (nItemLen < nWidth) {
-          nItemLen = nWidth;
-        }
-      } else {
-        switch (*pStr) {
-          case 'd':
-          case 'i':
-          case 'u':
-          case 'x':
-          case 'X':
-          case 'o':
-            if (nModifier & FORCE_INT64) {
-              va_arg(argList, int64_t);
-            } else {
-              va_arg(argList, int);
-            }
-            nItemLen = 32;
-            if (nItemLen < nWidth + nPrecision) {
-              nItemLen = nWidth + nPrecision;
-            }
-            break;
-          case 'a':
-          case 'A':
-          case 'e':
-          case 'E':
-          case 'g':
-          case 'G':
-            va_arg(argList, double);
-            nItemLen = 128;
-            if (nItemLen < nWidth + nPrecision) {
-              nItemLen = nWidth + nPrecision;
-            }
-            break;
-          case 'f':
-            if (nWidth + nPrecision > 100) {
-              nItemLen = nPrecision + nWidth + 128;
-            } else {
-              double f;
-              char pszTemp[256];
-              f = va_arg(argList, double);
-              FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth,
-                             nPrecision + 6, f);
-              nItemLen = strlen(pszTemp);
-            }
-            break;
-          case 'p':
-            va_arg(argList, void*);
-            nItemLen = 32;
-            if (nItemLen < nWidth + nPrecision) {
-              nItemLen = nWidth + nPrecision;
-            }
-            break;
-          case 'n':
-            va_arg(argList, int*);
-            break;
-        }
-      }
-      nMaxLen += nItemLen;
+  for (WideStringView view(pFormat); !view.IsEmpty(); view = view.Substr(1u)) {
+    if (view.Front() != '%' ||
+        (view.GetLength() > 1 && view.CharAt(1u) == '%')) {
+      ++nMaxLen;
+      continue;
     }
-  });
+    int iWidth = 0;
+    for (; !view.IsEmpty(); view = view.Substr(1u)) {
+      const wchar_t c = view.Front();
+      if (c == '#') {
+        nMaxLen += 2;
+      } else if (c == '*') {
+        iWidth = va_arg(argList, int);
+      } else if (c != '-' && c != '+' && c != '0' && c != ' ') {
+        break;
+      }
+      view = view.Substr(1u);
+    }
+    if (iWidth == 0) {
+      iWidth = StringToInt(view);
+      while (FXSYS_IsDecimalDigit(static_cast<wchar_t>(view.Front()))) {
+        view = view.Substr(1u);
+      }
+    }
+    if (iWidth < 0 || iWidth > 128 * 1024) {
+      return std::nullopt;
+    }
+    uint32_t nWidth = static_cast<uint32_t>(iWidth);
+    int iPrecision = 0;
+    if (view.Front() == '.') {
+      view = view.Substr(1u);
+      if (view.Front() == '*') {
+        iPrecision = va_arg(argList, int);
+        view = view.Substr(1u);
+      } else {
+        iPrecision = StringToInt(view);
+        while (FXSYS_IsDecimalDigit(static_cast<wchar_t>(view.Front()))) {
+          view = view.Substr(1u);
+        }
+      }
+    }
+    if (iPrecision < 0 || iPrecision > 128 * 1024) {
+      return std::nullopt;
+    }
+    uint32_t nPrecision = static_cast<uint32_t>(iPrecision);
+    int nModifier = 0;
+    if (view.First(3u) == L"I64") {
+      view = view.Substr(3u);
+      nModifier = FORCE_INT64;
+    } else {
+      switch (view.Front()) {
+        case 'h':
+          nModifier = FORCE_ANSI;
+          view = view.Substr(1u);
+          break;
+        case 'l':
+          nModifier = FORCE_UNICODE;
+          view = view.Substr(1u);
+          break;
+        case 'F':
+        case 'N':
+        case 'L':
+          view = view.Substr(1u);
+          break;
+      }
+    }
+    size_t nItemLen = 0;
+    switch (view.Front() | nModifier) {
+      case 'c':
+      case 'C':
+        nItemLen = 2;
+        va_arg(argList, int);
+        break;
+      case 'c' | FORCE_ANSI:
+      case 'C' | FORCE_ANSI:
+        nItemLen = 2;
+        va_arg(argList, int);
+        break;
+      case 'c' | FORCE_UNICODE:
+      case 'C' | FORCE_UNICODE:
+        nItemLen = 2;
+        va_arg(argList, int);
+        break;
+      case 's': {
+        const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*);
+        if (pstrNextArg) {
+          nItemLen = wcslen(pstrNextArg);
+          if (nItemLen < 1) {
+            nItemLen = 1;
+          }
+        } else {
+          nItemLen = 6;
+        }
+      } break;
+      case 'S': {
+        const char* pstrNextArg = va_arg(argList, const char*);
+        if (pstrNextArg) {
+          nItemLen = strlen(pstrNextArg);
+          if (nItemLen < 1) {
+            nItemLen = 1;
+          }
+        } else {
+          nItemLen = 6;
+        }
+      } break;
+      case 's' | FORCE_ANSI:
+      case 'S' | FORCE_ANSI: {
+        const char* pstrNextArg = va_arg(argList, const char*);
+        if (pstrNextArg) {
+          nItemLen = strlen(pstrNextArg);
+          if (nItemLen < 1) {
+            nItemLen = 1;
+          }
+        } else {
+          nItemLen = 6;
+        }
+      } break;
+      case 's' | FORCE_UNICODE:
+      case 'S' | FORCE_UNICODE: {
+        const wchar_t* pstrNextArg = va_arg(argList, wchar_t*);
+        if (pstrNextArg) {
+          nItemLen = wcslen(pstrNextArg);
+          if (nItemLen < 1) {
+            nItemLen = 1;
+          }
+        } else {
+          nItemLen = 6;
+        }
+      } break;
+    }
+    if (nItemLen != 0) {
+      if (nPrecision != 0 && nItemLen > nPrecision) {
+        nItemLen = nPrecision;
+      }
+      if (nItemLen < nWidth) {
+        nItemLen = nWidth;
+      }
+    } else {
+      switch (view.Front()) {
+        case 'd':
+        case 'i':
+        case 'u':
+        case 'x':
+        case 'X':
+        case 'o':
+          if (nModifier & FORCE_INT64) {
+            va_arg(argList, int64_t);
+          } else {
+            va_arg(argList, int);
+          }
+          nItemLen = 32;
+          if (nItemLen < nWidth + nPrecision) {
+            nItemLen = nWidth + nPrecision;
+          }
+          break;
+        case 'a':
+        case 'A':
+        case 'e':
+        case 'E':
+        case 'g':
+        case 'G':
+          va_arg(argList, double);
+          nItemLen = 128;
+          if (nItemLen < nWidth + nPrecision) {
+            nItemLen = nWidth + nPrecision;
+          }
+          break;
+        case 'f':
+          if (nWidth + nPrecision > 100) {
+            nItemLen = nPrecision + nWidth + 128;
+          } else {
+            double f;
+            char pszTemp[256];
+            f = va_arg(argList, double);
+            FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth,
+                           nPrecision + 6, f);
+            nItemLen = strlen(pszTemp);
+          }
+          break;
+        case 'p':
+          va_arg(argList, void*);
+          nItemLen = 32;
+          if (nItemLen < nWidth + nPrecision) {
+            nItemLen = nWidth + nPrecision;
+          }
+          break;
+        case 'n':
+          va_arg(argList, int*);
+          break;
+      }
+    }
+    nMaxLen += nItemLen;
+  }
   nMaxLen += 32;  // Fudge factor.
   return nMaxLen;
 }