Specify CFGAS_StringFormatter format at creation time.

Change-Id: I87915b8b09650ef7f8d23c75961849f2b5eb2cbc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/51873
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fgas/crt/cfgas_stringformatter.cpp b/xfa/fgas/crt/cfgas_stringformatter.cpp
index 5ce7d12..6b381e9 100644
--- a/xfa/fgas/crt/cfgas_stringformatter.cpp
+++ b/xfa/fgas/crt/cfgas_stringformatter.cpp
@@ -824,10 +824,11 @@
   return true;
 }
 
-CFGAS_StringFormatter::CFGAS_StringFormatter(LocaleMgrIface* pLocaleMgr)
-    : m_pLocaleMgr(pLocaleMgr) {}
+CFGAS_StringFormatter::CFGAS_StringFormatter(LocaleMgrIface* pLocaleMgr,
+                                             const WideString& wsPattern)
+    : m_pLocaleMgr(pLocaleMgr), m_wsPattern(wsPattern) {}
 
-CFGAS_StringFormatter::~CFGAS_StringFormatter() {}
+CFGAS_StringFormatter::~CFGAS_StringFormatter() = default;
 
 // static
 std::vector<WideString> CFGAS_StringFormatter::SplitOnBars(
@@ -849,10 +850,9 @@
   return wsPatterns;
 }
 
-FX_LOCALECATEGORY CFGAS_StringFormatter::GetCategory(
-    const WideString& wsPattern) const {
+FX_LOCALECATEGORY CFGAS_StringFormatter::GetCategory() const {
   FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
-  pdfium::span<const wchar_t> spPattern = wsPattern.AsSpan();
+  pdfium::span<const wchar_t> spPattern = m_wsPattern.AsSpan();
   size_t ccf = 0;
   bool bBraceOpen = false;
   WideStringView wsConstChars(gs_wsConstChars);
@@ -904,10 +904,9 @@
 }
 
 WideString CFGAS_StringFormatter::GetTextFormat(
-    const WideString& wsPattern,
     WideStringView wsCategory) const {
   size_t ccf = 0;
-  pdfium::span<const wchar_t> spPattern = wsPattern.AsSpan();
+  pdfium::span<const wchar_t> spPattern = m_wsPattern.AsSpan();
   bool bBrackOpen = false;
   WideStringView wsConstChars(gs_wsConstChars);
   WideString wsPurgePattern;
@@ -946,22 +945,21 @@
     ccf++;
   }
   if (!bBrackOpen)
-    wsPurgePattern = wsPattern;
+    wsPurgePattern = m_wsPattern;
 
   return wsPurgePattern;
 }
 
 LocaleIface* CFGAS_StringFormatter::GetNumericFormat(
-    const WideString& wsPattern,
     size_t* iDotIndex,
     uint32_t* dwStyle,
     WideString* wsPurgePattern) const {
   *dwStyle = 0;
   LocaleIface* pLocale = nullptr;
   size_t ccf = 0;
-  pdfium::span<const wchar_t> spPattern = wsPattern.AsSpan();
   bool bFindDot = false;
   bool bBrackOpen = false;
+  pdfium::span<const wchar_t> spPattern = m_wsPattern.AsSpan();
   WideStringView wsConstChars(gs_wsConstChars);
   while (ccf < spPattern.size()) {
     if (spPattern[ccf] == '\'') {
@@ -1057,13 +1055,12 @@
 }
 
 bool CFGAS_StringFormatter::ParseText(const WideString& wsSrcText,
-                                      const WideString& wsPattern,
                                       WideString* wsValue) const {
   wsValue->clear();
-  if (wsSrcText.IsEmpty() || wsPattern.IsEmpty())
+  if (wsSrcText.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"text");
+  WideString wsTextFormat = GetTextFormat(L"text");
   if (wsTextFormat.IsEmpty())
     return false;
 
@@ -1129,17 +1126,16 @@
 }
 
 bool CFGAS_StringFormatter::ParseNum(const WideString& wsSrcNum,
-                                     const WideString& wsPattern,
                                      WideString* wsValue) const {
   wsValue->clear();
-  if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty())
+  if (wsSrcNum.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
-  size_t dot_index_f = wsPattern.GetLength();
+  size_t dot_index_f = m_wsPattern.GetLength();
   uint32_t dwFormatStyle = 0;
   WideString wsNumFormat;
   LocaleIface* pLocale =
-      GetNumericFormat(wsPattern, &dot_index_f, &dwFormatStyle, &wsNumFormat);
+      GetNumericFormat(&dot_index_f, &dwFormatStyle, &wsNumFormat);
   if (!pLocale || wsNumFormat.IsEmpty())
     return false;
 
@@ -1543,7 +1539,6 @@
 }
 
 FX_DATETIMETYPE CFGAS_StringFormatter::GetDateTimeFormat(
-    const WideString& wsPattern,
     LocaleIface** pLocale,
     WideString* wsDatePattern,
     WideString* wsTimePattern) const {
@@ -1551,7 +1546,7 @@
   WideString wsTempPattern;
   FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
   size_t ccf = 0;
-  pdfium::span<const wchar_t> spPattern = wsPattern.AsSpan();
+  pdfium::span<const wchar_t> spPattern = m_wsPattern.AsSpan();
   int32_t iFindCategory = 0;
   bool bBraceOpen = false;
   WideStringView wsConstChars(gs_wsConstChars);
@@ -1568,8 +1563,8 @@
       while (ccf < spPattern.size() && spPattern[ccf] != '{' &&
              spPattern[ccf] != '.' && spPattern[ccf] != '(') {
         if (spPattern[ccf] == 'T') {
-          *wsDatePattern = wsPattern.Left(ccf);
-          *wsTimePattern = wsPattern.Right(wsPattern.GetLength() - ccf);
+          *wsDatePattern = m_wsPattern.Left(ccf);
+          *wsTimePattern = m_wsPattern.Right(m_wsPattern.GetLength() - ccf);
           wsTimePattern->SetAt(0, ' ');
           if (!*pLocale)
             *pLocale = m_pLocaleMgr->GetDefLocale();
@@ -1674,24 +1669,23 @@
     *pLocale = m_pLocaleMgr->GetDefLocale();
   if (!iFindCategory) {
     wsTimePattern->clear();
-    *wsDatePattern = wsPattern;
+    *wsDatePattern = m_wsPattern;
   }
   return (FX_DATETIMETYPE)iFindCategory;
 }
 
 bool CFGAS_StringFormatter::ParseDateTime(const WideString& wsSrcDateTime,
-                                          const WideString& wsPattern,
                                           FX_DATETIMETYPE eDateTimeType,
                                           CFX_DateTime* dtValue) const {
   dtValue->Reset();
-  if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty())
+  if (wsSrcDateTime.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
   WideString wsDatePattern;
   WideString wsTimePattern;
   LocaleIface* pLocale = nullptr;
   FX_DATETIMETYPE eCategory =
-      GetDateTimeFormat(wsPattern, &pLocale, &wsDatePattern, &wsTimePattern);
+      GetDateTimeFormat(&pLocale, &wsDatePattern, &wsTimePattern);
   if (!pLocale)
     return false;
   if (eCategory == FX_DATETIMETYPE_Unknown)
@@ -1724,9 +1718,8 @@
   return true;
 }
 
-bool CFGAS_StringFormatter::ParseZero(const WideString& wsSrcText,
-                                      const WideString& wsPattern) const {
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"zero");
+bool CFGAS_StringFormatter::ParseZero(const WideString& wsSrcText) const {
+  WideString wsTextFormat = GetTextFormat(L"zero");
   pdfium::span<const wchar_t> spSrcText = wsSrcText.AsSpan();
   pdfium::span<const wchar_t> spTextFormat = wsTextFormat.AsSpan();
 
@@ -1753,9 +1746,8 @@
   return iPattern == spTextFormat.size() && iText == spSrcText.size();
 }
 
-bool CFGAS_StringFormatter::ParseNull(const WideString& wsSrcText,
-                                      const WideString& wsPattern) const {
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"null");
+bool CFGAS_StringFormatter::ParseNull(const WideString& wsSrcText) const {
+  WideString wsTextFormat = GetTextFormat(L"null");
   pdfium::span<const wchar_t> spSrcText = wsSrcText.AsSpan();
   pdfium::span<const wchar_t> spTextFormat = wsTextFormat.AsSpan();
 
@@ -1783,12 +1775,11 @@
 }
 
 bool CFGAS_StringFormatter::FormatText(const WideString& wsSrcText,
-                                       const WideString& wsPattern,
                                        WideString* wsOutput) const {
-  if (wsPattern.IsEmpty() || wsSrcText.IsEmpty())
+  if (wsSrcText.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"text");
+  WideString wsTextFormat = GetTextFormat(L"text");
   pdfium::span<const wchar_t> spSrcText = wsSrcText.AsSpan();
   pdfium::span<const wchar_t> spTextFormat = wsTextFormat.AsSpan();
 
@@ -1842,16 +1833,15 @@
 }
 
 bool CFGAS_StringFormatter::FormatNum(const WideString& wsInputNum,
-                                      const WideString& wsPattern,
                                       WideString* wsOutput) const {
-  if (wsInputNum.IsEmpty() || wsPattern.IsEmpty())
+  if (wsInputNum.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
-  size_t dot_index_f = wsPattern.GetLength();
+  size_t dot_index_f = m_wsPattern.GetLength();
   uint32_t dwNumStyle = 0;
   WideString wsNumFormat;
   LocaleIface* pLocale =
-      GetNumericFormat(wsPattern, &dot_index_f, &dwNumStyle, &wsNumFormat);
+      GetNumericFormat(&dot_index_f, &dwNumStyle, &wsNumFormat);
   if (!pLocale || wsNumFormat.IsEmpty())
     return false;
 
@@ -2188,17 +2178,16 @@
 }
 
 bool CFGAS_StringFormatter::FormatDateTime(const WideString& wsSrcDateTime,
-                                           const WideString& wsPattern,
                                            FX_DATETIMETYPE eDateTimeType,
                                            WideString* wsOutput) const {
-  if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty())
+  if (wsSrcDateTime.IsEmpty() || m_wsPattern.IsEmpty())
     return false;
 
   WideString wsDatePattern;
   WideString wsTimePattern;
   LocaleIface* pLocale = nullptr;
   FX_DATETIMETYPE eCategory =
-      GetDateTimeFormat(wsPattern, &pLocale, &wsDatePattern, &wsTimePattern);
+      GetDateTimeFormat(&pLocale, &wsDatePattern, &wsTimePattern);
   if (!pLocale)
     return false;
 
@@ -2245,12 +2234,11 @@
   return false;
 }
 
-bool CFGAS_StringFormatter::FormatZero(const WideString& wsPattern,
-                                       WideString* wsOutput) const {
-  if (wsPattern.IsEmpty())
+bool CFGAS_StringFormatter::FormatZero(WideString* wsOutput) const {
+  if (m_wsPattern.IsEmpty())
     return false;
 
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"zero");
+  WideString wsTextFormat = GetTextFormat(L"zero");
   pdfium::span<const wchar_t> spTextFormat = wsTextFormat.AsSpan();
   for (size_t iPattern = 0; iPattern < spTextFormat.size(); ++iPattern) {
     if (spTextFormat[iPattern] == '\'') {
@@ -2262,12 +2250,11 @@
   return true;
 }
 
-bool CFGAS_StringFormatter::FormatNull(const WideString& wsPattern,
-                                       WideString* wsOutput) const {
-  if (wsPattern.IsEmpty())
+bool CFGAS_StringFormatter::FormatNull(WideString* wsOutput) const {
+  if (m_wsPattern.IsEmpty())
     return false;
 
-  WideString wsTextFormat = GetTextFormat(wsPattern, L"null");
+  WideString wsTextFormat = GetTextFormat(L"null");
   pdfium::span<const wchar_t> spTextFormat = wsTextFormat.AsSpan();
   for (size_t iPattern = 0; iPattern < spTextFormat.size(); ++iPattern) {
     if (spTextFormat[iPattern] == '\'') {
diff --git a/xfa/fgas/crt/cfgas_stringformatter.h b/xfa/fgas/crt/cfgas_stringformatter.h
index ed18828..538a783 100644
--- a/xfa/fgas/crt/cfgas_stringformatter.h
+++ b/xfa/fgas/crt/cfgas_stringformatter.h
@@ -22,54 +22,45 @@
 
 class CFGAS_StringFormatter {
  public:
-  explicit CFGAS_StringFormatter(LocaleMgrIface* pLocaleMgr);
+  CFGAS_StringFormatter(LocaleMgrIface* pLocaleMgr,
+                        const WideString& wsPattern);
   ~CFGAS_StringFormatter();
 
   static std::vector<WideString> SplitOnBars(const WideString& wsFormatString);
 
-  FX_LOCALECATEGORY GetCategory(const WideString& wsPattern) const;
+  FX_LOCALECATEGORY GetCategory() const;
 
   bool ParseText(const WideString& wsSrcText,
-                 const WideString& wsPattern,
                  WideString* wsValue) const;
   bool ParseNum(const WideString& wsSrcNum,
-                const WideString& wsPattern,
                 WideString* wsValue) const;
   bool ParseDateTime(const WideString& wsSrcDateTime,
-                     const WideString& wsPattern,
                      FX_DATETIMETYPE eDateTimeType,
                      CFX_DateTime* dtValue) const;
-  bool ParseZero(const WideString& wsSrcText,
-                 const WideString& wsPattern) const;
-  bool ParseNull(const WideString& wsSrcText,
-                 const WideString& wsPattern) const;
+  bool ParseZero(const WideString& wsSrcText) const;
+  bool ParseNull(const WideString& wsSrcText) const;
 
   bool FormatText(const WideString& wsSrcText,
-                  const WideString& wsPattern,
                   WideString* wsOutput) const;
   bool FormatNum(const WideString& wsSrcNum,
-                 const WideString& wsPattern,
                  WideString* wsOutput) const;
   bool FormatDateTime(const WideString& wsSrcDateTime,
-                      const WideString& wsPattern,
                       FX_DATETIMETYPE eDateTimeType,
                       WideString* wsOutput) const;
-  bool FormatZero(const WideString& wsPattern, WideString* wsOutput) const;
-  bool FormatNull(const WideString& wsPattern, WideString* wsOutput) const;
+  bool FormatZero(WideString* wsOutput) const;
+  bool FormatNull(WideString* wsOutput) const;
 
  private:
-  WideString GetTextFormat(const WideString& wsPattern,
-                           WideStringView wsCategory) const;
-  LocaleIface* GetNumericFormat(const WideString& wsPattern,
-                                size_t* iDotIndex,
+  WideString GetTextFormat(WideStringView wsCategory) const;
+  LocaleIface* GetNumericFormat(size_t* iDotIndex,
                                 uint32_t* dwStyle,
                                 WideString* wsPurgePattern) const;
-  FX_DATETIMETYPE GetDateTimeFormat(const WideString& wsPattern,
-                                    LocaleIface** pLocale,
+  FX_DATETIMETYPE GetDateTimeFormat(LocaleIface** pLocale,
                                     WideString* wsDatePattern,
                                     WideString* wsTimePattern) const;
 
   UnownedPtr<LocaleMgrIface> const m_pLocaleMgr;
+  const WideString m_wsPattern;
 };
 
 #endif  // XFA_FGAS_CRT_CFGAS_STRINGFORMATTER_H_
diff --git a/xfa/fgas/crt/cfgas_stringformatter_unittest.cpp b/xfa/fgas/crt/cfgas_stringformatter_unittest.cpp
index b0acfaf..f96ef59 100644
--- a/xfa/fgas/crt/cfgas_stringformatter_unittest.cpp
+++ b/xfa/fgas/crt/cfgas_stringformatter_unittest.cpp
@@ -42,10 +42,11 @@
 
   // Note, this re-creates the fmt on each call. If you need to multiple
   // times store it locally.
-  CFGAS_StringFormatter* fmt(const WideString& locale) {
+  CFGAS_StringFormatter* fmt(const WideString& locale,
+                             const WideString& pattern) {
     fmt_.reset();  // Can't outlive |mgr_|.
     mgr_ = pdfium::MakeUnique<CXFA_LocaleMgr>(nullptr, locale);
-    fmt_ = pdfium::MakeUnique<CFGAS_StringFormatter>(mgr_.get());
+    fmt_ = pdfium::MakeUnique<CFGAS_StringFormatter>(mgr_.get(), pattern);
     return fmt_.get();
   }
 
@@ -113,9 +114,9 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->FormatDateTime(tests[i].input, tests[i].pattern,
-                                     FX_DATETIMETYPE_Date, &result));
+    EXPECT_TRUE(
+        fmt(tests[i].locale, tests[i].pattern)
+            ->FormatDateTime(tests[i].input, FX_DATETIMETYPE_Date, &result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
@@ -162,9 +163,9 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->FormatDateTime(tests[i].input, tests[i].pattern,
-                                     FX_DATETIMETYPE_Time, &result));
+    EXPECT_TRUE(
+        fmt(tests[i].locale, tests[i].pattern)
+            ->FormatDateTime(tests[i].input, FX_DATETIMETYPE_Time, &result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 
@@ -192,9 +193,9 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->FormatDateTime(tests[i].input, tests[i].pattern,
-                                     FX_DATETIMETYPE_TimeDate, &result));
+    EXPECT_TRUE(fmt(tests[i].locale, tests[i].pattern)
+                    ->FormatDateTime(tests[i].input, FX_DATETIMETYPE_TimeDate,
+                                     &result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
@@ -253,9 +254,9 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     CFX_DateTime result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->ParseDateTime(tests[i].input, tests[i].pattern,
-                                    FX_DATETIMETYPE_Date, &result));
+    EXPECT_TRUE(
+        fmt(tests[i].locale, tests[i].pattern)
+            ->ParseDateTime(tests[i].input, FX_DATETIMETYPE_Date, &result));
     EXPECT_EQ(tests[i].output, result) << " TEST: " << i;
   }
 }
@@ -436,7 +437,7 @@
 
   for (const auto& test : tests) {
     WideString result;
-    EXPECT_TRUE(fmt(test.locale)->ParseNum(test.input, test.pattern, &result))
+    EXPECT_TRUE(fmt(test.locale, test.pattern)->ParseNum(test.input, &result))
         << " TEST: " << test.input << ", " << test.pattern;
     EXPECT_STREQ(test.output, result.c_str())
         << " TEST: " << test.input << ", " << test.pattern;
@@ -444,7 +445,7 @@
 
   for (const auto& test : failures) {
     WideString result;
-    EXPECT_FALSE(fmt(test.locale)->ParseNum(test.input, test.pattern, &result))
+    EXPECT_FALSE(fmt(test.locale, test.pattern)->ParseNum(test.input, &result))
         << " TEST: " << test.input << ", " << test.pattern;
   }
 }
@@ -558,7 +559,7 @@
 
   for (const auto& test : tests) {
     WideString result;
-    EXPECT_TRUE(fmt(test.locale)->FormatNum(test.input, test.pattern, &result))
+    EXPECT_TRUE(fmt(test.locale, test.pattern)->FormatNum(test.input, &result))
         << " TEST: " << test.input << ", " << test.pattern;
     EXPECT_STREQ(test.output, result.c_str())
         << " TEST: " << test.input << ", " << test.pattern;
@@ -584,8 +585,8 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->ParseText(tests[i].input, tests[i].pattern, &result));
+    EXPECT_TRUE(fmt(tests[i].locale, tests[i].pattern)
+                    ->ParseText(tests[i].input, &result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
@@ -593,7 +594,7 @@
 TEST_F(CFGAS_StringFormatterTest, InvalidTextParse) {
   // Input does not match mask.
   WideString result;
-  EXPECT_FALSE(fmt(L"en")->ParseText(L"123-4567-8", L"AAA-9999-X", &result));
+  EXPECT_FALSE(fmt(L"en", L"AAA-9999-X")->ParseText(L"123-4567-8", &result));
 }
 
 TEST_F(CFGAS_StringFormatterTest, TextFormat) {
@@ -614,8 +615,8 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)
-                    ->FormatText(tests[i].input, tests[i].pattern, &result));
+    EXPECT_TRUE(fmt(tests[i].locale, tests[i].pattern)
+                    ->FormatText(tests[i].input, &result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
@@ -632,7 +633,7 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     EXPECT_TRUE(
-        fmt(tests[i].locale)->ParseNull(tests[i].input, tests[i].pattern))
+        fmt(tests[i].locale, tests[i].pattern)->ParseNull(tests[i].input))
         << " TEST: " << i;
   }
 }
@@ -646,7 +647,7 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(fmt(tests[i].locale)->FormatNull(tests[i].pattern, &result));
+    EXPECT_TRUE(fmt(tests[i].locale, tests[i].pattern)->FormatNull(&result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
@@ -662,7 +663,7 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     EXPECT_TRUE(
-        fmt(tests[i].locale)->ParseZero(tests[i].input, tests[i].pattern))
+        fmt(tests[i].locale, tests[i].pattern)->ParseZero(tests[i].input))
         << " TEST: " << i;
   }
 }
@@ -682,26 +683,26 @@
 
   for (size_t i = 0; i < FX_ArraySize(tests); ++i) {
     WideString result;
-    EXPECT_TRUE(
-        fmt(tests[i].locale)
-            ->FormatZero(/* tests[i].input,*/ tests[i].pattern, &result));
+    EXPECT_TRUE(fmt(tests[i].locale, tests[i].pattern)->FormatZero(&result));
     EXPECT_STREQ(tests[i].output, result.c_str()) << " TEST: " << i;
   }
 }
 
 TEST_F(CFGAS_StringFormatterTest, GetCategory) {
-  CFGAS_StringFormatter* f = fmt(L"en");
-
-  EXPECT_EQ(FX_LOCALECATEGORY_Unknown, f->GetCategory(L"'just text'"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Null, f->GetCategory(L"null{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Zero, f->GetCategory(L"zero{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Num, f->GetCategory(L"num{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Text, f->GetCategory(L"text{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"datetime{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Time, f->GetCategory(L"time{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Date, f->GetCategory(L"date{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"time{} date{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_DateTime, f->GetCategory(L"date{} time{}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Num, f->GetCategory(L"num(en_GB){}"));
-  EXPECT_EQ(FX_LOCALECATEGORY_Date, f->GetCategory(L"date.long{}"));
+  EXPECT_EQ(FX_LOCALECATEGORY_Unknown,
+            fmt(L"en", L"'just text'")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Null, fmt(L"en", L"null{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Zero, fmt(L"en", L"zero{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Num, fmt(L"en", L"num{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Text, fmt(L"en", L"text{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_DateTime,
+            fmt(L"en", L"datetime{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Time, fmt(L"en", L"time{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Date, fmt(L"en", L"date{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_DateTime,
+            fmt(L"en", L"time{} date{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_DateTime,
+            fmt(L"en", L"date{} time{}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Num, fmt(L"en", L"num(en_GB){}")->GetCategory());
+  EXPECT_EQ(FX_LOCALECATEGORY_Date, fmt(L"en", L"date.long{}")->GetCategory());
 }
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index 04f70ec..fe62e81 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -127,70 +127,68 @@
   if (!m_pLocaleMgr)
     return false;
 
+  ScopedLocale scoped_locale(m_pLocaleMgr.Get(), pLocale);
   std::vector<WideString> wsPatterns =
       CFGAS_StringFormatter::SplitOnBars(wsPattern);
 
   WideString wsOutput;
-  ScopedLocale scoped_locale(m_pLocaleMgr.Get(), pLocale);
-  auto pFormat = pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get());
   bool bRet = false;
   size_t i = 0;
   for (; !bRet && i < wsPatterns.size(); i++) {
     const WideString& wsFormat = wsPatterns[i];
-    switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) {
+    auto pFormat =
+        pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get(), wsFormat);
+    switch (ValueCategory(pFormat->GetCategory(), m_dwType)) {
       case FX_LOCALECATEGORY_Null:
-        bRet = pFormat->ParseNull(wsValue, wsFormat);
+        bRet = pFormat->ParseNull(wsValue);
         if (!bRet)
           bRet = wsValue.IsEmpty();
         break;
       case FX_LOCALECATEGORY_Zero:
-        bRet = pFormat->ParseZero(wsValue, wsFormat);
+        bRet = pFormat->ParseZero(wsValue);
         if (!bRet)
           bRet = wsValue.EqualsASCII("0");
         break;
       case FX_LOCALECATEGORY_Num: {
         WideString fNum;
-        bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum);
+        bRet = pFormat->ParseNum(wsValue, &fNum);
         if (!bRet)
-          bRet = pFormat->FormatNum(wsValue, wsFormat, &wsOutput);
+          bRet = pFormat->FormatNum(wsValue, &wsOutput);
         break;
       }
       case FX_LOCALECATEGORY_Text:
-        bRet = pFormat->ParseText(wsValue, wsFormat, &wsOutput);
+        bRet = pFormat->ParseText(wsValue, &wsOutput);
         wsOutput.clear();
         if (!bRet)
-          bRet = pFormat->FormatText(wsValue, wsFormat, &wsOutput);
+          bRet = pFormat->FormatText(wsValue, &wsOutput);
         break;
       case FX_LOCALECATEGORY_Date: {
         CFX_DateTime dt;
         bRet = ValidateCanonicalDate(wsValue, &dt);
         if (!bRet) {
-          bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
-                                        &dt);
+          bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_Date, &dt);
           if (!bRet) {
-            bRet = pFormat->FormatDateTime(wsValue, wsFormat,
-                                           FX_DATETIMETYPE_Date, &wsOutput);
+            bRet = pFormat->FormatDateTime(wsValue, FX_DATETIMETYPE_Date,
+                                           &wsOutput);
           }
         }
         break;
       }
       case FX_LOCALECATEGORY_Time: {
         CFX_DateTime dt;
-        bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time,
-                                      &dt);
+        bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_Time, &dt);
         if (!bRet) {
-          bRet = pFormat->FormatDateTime(wsValue, wsFormat,
-                                         FX_DATETIMETYPE_Time, &wsOutput);
+          bRet =
+              pFormat->FormatDateTime(wsValue, FX_DATETIMETYPE_Time, &wsOutput);
         }
         break;
       }
       case FX_LOCALECATEGORY_DateTime: {
         CFX_DateTime dt;
-        bRet = pFormat->ParseDateTime(wsValue, wsFormat,
-                                      FX_DATETIMETYPE_DateTime, &dt);
+        bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_DateTime, &dt);
         if (!bRet) {
-          bRet = pFormat->FormatDateTime(wsValue, wsFormat,
-                                         FX_DATETIMETYPE_DateTime, &wsOutput);
+          bRet = pFormat->FormatDateTime(wsValue, FX_DATETIMETYPE_DateTime,
+                                         &wsOutput);
         }
         break;
       }
@@ -280,35 +278,35 @@
 
   wsResult.clear();
   bool bRet = false;
-  auto pFormat = pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get());
-  FX_LOCALECATEGORY eCategory =
-      ValueCategory(pFormat->GetCategory(wsFormat), m_dwType);
+  auto pFormat =
+      pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get(), wsFormat);
+  FX_LOCALECATEGORY eCategory = ValueCategory(pFormat->GetCategory(), m_dwType);
   switch (eCategory) {
     case FX_LOCALECATEGORY_Null:
       if (m_wsValue.IsEmpty())
-        bRet = pFormat->FormatNull(wsFormat, &wsResult);
+        bRet = pFormat->FormatNull(&wsResult);
       break;
     case FX_LOCALECATEGORY_Zero:
       if (m_wsValue.EqualsASCII("0"))
-        bRet = pFormat->FormatZero(wsFormat, &wsResult);
+        bRet = pFormat->FormatZero(&wsResult);
       break;
     case FX_LOCALECATEGORY_Num:
-      bRet = pFormat->FormatNum(m_wsValue, wsFormat, &wsResult);
+      bRet = pFormat->FormatNum(m_wsValue, &wsResult);
       break;
     case FX_LOCALECATEGORY_Text:
-      bRet = pFormat->FormatText(m_wsValue, wsFormat, &wsResult);
+      bRet = pFormat->FormatText(m_wsValue, &wsResult);
       break;
     case FX_LOCALECATEGORY_Date:
-      bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Date,
-                                     &wsResult);
+      bRet =
+          pFormat->FormatDateTime(m_wsValue, FX_DATETIMETYPE_Date, &wsResult);
       break;
     case FX_LOCALECATEGORY_Time:
-      bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Time,
-                                     &wsResult);
+      bRet =
+          pFormat->FormatDateTime(m_wsValue, FX_DATETIMETYPE_Time, &wsResult);
       break;
     case FX_LOCALECATEGORY_DateTime:
-      bRet = pFormat->FormatDateTime(m_wsValue, wsFormat,
-                                     FX_DATETIMETYPE_DateTime, &wsResult);
+      bRet = pFormat->FormatDateTime(m_wsValue, FX_DATETIMETYPE_DateTime,
+                                     &wsResult);
       break;
     default:
       wsResult = m_wsValue;
@@ -546,37 +544,37 @@
       CFGAS_StringFormatter::SplitOnBars(wsPattern);
 
   ScopedLocale scoped_locale(m_pLocaleMgr.Get(), pLocale);
-  auto pFormat = pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get());
   bool bRet = false;
   for (size_t i = 0; !bRet && i < wsPatterns.size(); i++) {
     const WideString& wsFormat = wsPatterns[i];
-    switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) {
+    auto pFormat =
+        pdfium::MakeUnique<CFGAS_StringFormatter>(m_pLocaleMgr.Get(), wsFormat);
+    switch (ValueCategory(pFormat->GetCategory(), m_dwType)) {
       case FX_LOCALECATEGORY_Null:
-        bRet = pFormat->ParseNull(wsValue, wsFormat);
+        bRet = pFormat->ParseNull(wsValue);
         if (bRet)
           m_wsValue.clear();
         break;
       case FX_LOCALECATEGORY_Zero:
-        bRet = pFormat->ParseZero(wsValue, wsFormat);
+        bRet = pFormat->ParseZero(wsValue);
         if (bRet)
           m_wsValue = L"0";
         break;
       case FX_LOCALECATEGORY_Num: {
         WideString fNum;
-        bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum);
+        bRet = pFormat->ParseNum(wsValue, &fNum);
         if (bRet)
           m_wsValue = std::move(fNum);
         break;
       }
       case FX_LOCALECATEGORY_Text:
-        bRet = pFormat->ParseText(wsValue, wsFormat, &m_wsValue);
+        bRet = pFormat->ParseText(wsValue, &m_wsValue);
         break;
       case FX_LOCALECATEGORY_Date: {
         CFX_DateTime dt;
         bRet = ValidateCanonicalDate(wsValue, &dt);
         if (!bRet) {
-          bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
-                                        &dt);
+          bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_Date, &dt);
         }
         if (bRet)
           SetDate(dt);
@@ -584,16 +582,14 @@
       }
       case FX_LOCALECATEGORY_Time: {
         CFX_DateTime dt;
-        bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time,
-                                      &dt);
+        bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_Time, &dt);
         if (bRet)
           SetTime(dt);
         break;
       }
       case FX_LOCALECATEGORY_DateTime: {
         CFX_DateTime dt;
-        bRet = pFormat->ParseDateTime(wsValue, wsFormat,
-                                      FX_DATETIMETYPE_DateTime, &dt);
+        bRet = pFormat->ParseDateTime(wsValue, FX_DATETIMETYPE_DateTime, &dt);
         if (bRet)
           SetDateTime(dt);
         break;