Move {Byte,Wide}String::Find() into StringTemplate<>

Change-Id: Ibd1697e8cb3109f759467f476604a266893948b9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/116674
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index 4516f81..9b8f539 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -332,48 +332,6 @@
   m_pData->m_String[index] = c;
 }
 
-std::optional<size_t> ByteString::Find(char ch, size_t start) const {
-  if (!m_pData)
-    return std::nullopt;
-
-  if (!IsValidIndex(start))
-    return std::nullopt;
-
-  const char* pStr = static_cast<const char*>(FXSYS_memchr(
-      m_pData->m_String + start, ch, m_pData->m_nDataLength - start));
-  return pStr ? std::optional<size_t>(
-                    static_cast<size_t>(pStr - m_pData->m_String))
-              : std::nullopt;
-}
-
-std::optional<size_t> ByteString::Find(ByteStringView subStr,
-                                       size_t start) const {
-  if (!m_pData) {
-    return std::nullopt;
-  }
-  if (!IsValidIndex(start)) {
-    return std::nullopt;
-  }
-  std::optional<size_t> result =
-      spanpos(m_pData->span().subspan(start), subStr.span());
-  if (!result.has_value()) {
-    return std::nullopt;
-  }
-  return start + result.value();
-}
-
-std::optional<size_t> ByteString::ReverseFind(char ch) const {
-  if (!m_pData)
-    return std::nullopt;
-
-  size_t nLength = m_pData->m_nDataLength;
-  while (nLength--) {
-    if (m_pData->m_String[nLength] == ch)
-      return nLength;
-  }
-  return std::nullopt;
-}
-
 void ByteString::MakeLower() {
   if (IsEmpty())
     return;
diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h
index 20de629..98d1019 100644
--- a/core/fxcrt/bytestring.h
+++ b/core/fxcrt/bytestring.h
@@ -109,18 +109,6 @@
   ByteString First(size_t count) const;
   ByteString Last(size_t count) const;
 
-  std::optional<size_t> Find(ByteStringView subStr, size_t start = 0) const;
-  std::optional<size_t> Find(char ch, size_t start = 0) const;
-  std::optional<size_t> ReverseFind(char ch) const;
-
-  bool Contains(ByteStringView lpszSub, size_t start = 0) const {
-    return Find(lpszSub, start).has_value();
-  }
-
-  bool Contains(char ch, size_t start = 0) const {
-    return Find(ch, start).has_value();
-  }
-
   void MakeLower();
   void MakeUpper();
 
diff --git a/core/fxcrt/string_template.cpp b/core/fxcrt/string_template.cpp
index 8eb95cf..9ec367b 100644
--- a/core/fxcrt/string_template.cpp
+++ b/core/fxcrt/string_template.cpp
@@ -139,6 +139,42 @@
 }
 
 template <typename T>
+std::optional<size_t> StringTemplate<T>::Find(T ch, size_t start) const {
+  return Find(StringView(ch), start);
+}
+
+template <typename T>
+std::optional<size_t> StringTemplate<T>::Find(StringView str,
+                                              size_t start) const {
+  if (!m_pData) {
+    return std::nullopt;
+  }
+  if (!IsValidIndex(start)) {
+    return std::nullopt;
+  }
+  std::optional<size_t> result =
+      spanpos(m_pData->span().subspan(start), str.span());
+  if (!result.has_value()) {
+    return std::nullopt;
+  }
+  return start + result.value();
+}
+
+template <typename T>
+std::optional<size_t> StringTemplate<T>::ReverseFind(T ch) const {
+  if (!m_pData) {
+    return std::nullopt;
+  }
+  size_t nLength = m_pData->m_nDataLength;
+  while (nLength--) {
+    if (m_pData->m_String[nLength] == ch) {
+      return nLength;
+    }
+  }
+  return std::nullopt;
+}
+
+template <typename T>
 void StringTemplate<T>::ReallocBeforeWrite(size_t nNewLength) {
   if (m_pData && m_pData->CanOperateInPlace(nNewLength)) {
     return;
@@ -147,7 +183,6 @@
     clear();
     return;
   }
-
   RetainPtr<StringData> pNewData = StringData::Create(nNewLength);
   if (m_pData) {
     size_t nCopyLength = std::min(m_pData->m_nDataLength, nNewLength);
diff --git a/core/fxcrt/string_template.h b/core/fxcrt/string_template.h
index 4df22ce..fd850ad 100644
--- a/core/fxcrt/string_template.h
+++ b/core/fxcrt/string_template.h
@@ -24,6 +24,7 @@
  public:
   using CharType = T;
   using UnsignedType = typename std::make_unsigned<CharType>::type;
+  using StringView = StringViewTemplate<T>;
   using const_iterator = T*;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 
@@ -37,11 +38,9 @@
                    : nullptr;
   }
 
-  // Explicit conversion to ByteStringView.
+  // Explicit conversion to StringView.
   // Note: Any subsequent modification of |this| will invalidate the result.
-  StringViewTemplate<CharType> AsStringView() const {
-    return StringViewTemplate<CharType>(raw_str(), GetLength());
-  }
+  StringView AsStringView() const { return StringView(raw_str(), GetLength()); }
 
   // Explicit conversion to span.
   // Note: Any subsequent modification of |this| will invalidate the result.
@@ -115,8 +114,19 @@
   // Returns size of the string following deletion.
   size_t Delete(size_t index, size_t count = 1);
 
+  // Returns the index within in the string when found.
+  std::optional<size_t> Find(StringView str, size_t start = 0) const;
+  std::optional<size_t> Find(T ch, size_t start = 0) const;
+  std::optional<size_t> ReverseFind(T ch) const;
+
+  bool Contains(StringView str, size_t start = 0) const {
+    return Find(str, start).has_value();
+  }
+  bool Contains(T ch, size_t start = 0) const {
+    return Find(ch, start).has_value();
+  }
+
  protected:
-  using StringView = StringViewTemplate<T>;
   using StringData = StringDataTemplate<T>;
 
   StringTemplate() = default;
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index cdbf47d..6f14a26 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -647,48 +647,6 @@
   return Substr(GetLength() - count, count);
 }
 
-std::optional<size_t> WideString::Find(wchar_t ch, size_t start) const {
-  if (!m_pData)
-    return std::nullopt;
-
-  if (!IsValidIndex(start))
-    return std::nullopt;
-
-  const wchar_t* pStr = FXSYS_wmemchr(m_pData->m_String + start, ch,
-                                      m_pData->m_nDataLength - start);
-  return pStr ? std::optional<size_t>(
-                    static_cast<size_t>(pStr - m_pData->m_String))
-              : std::nullopt;
-}
-
-std::optional<size_t> WideString::Find(WideStringView subStr,
-                                       size_t start) const {
-  if (!m_pData) {
-    return std::nullopt;
-  }
-  if (!IsValidIndex(start)) {
-    return std::nullopt;
-  }
-  std::optional<size_t> result =
-      spanpos(m_pData->span().subspan(start), subStr.span());
-  if (!result.has_value()) {
-    return std::nullopt;
-  }
-  return start + result.value();
-}
-
-std::optional<size_t> WideString::ReverseFind(wchar_t ch) const {
-  if (!m_pData)
-    return std::nullopt;
-
-  size_t nLength = m_pData->m_nDataLength;
-  while (nLength--) {
-    if (m_pData->m_String[nLength] == ch)
-      return nLength;
-  }
-  return std::nullopt;
-}
-
 void WideString::MakeLower() {
   if (IsEmpty())
     return;
diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h
index 8c18b00..479e1be 100644
--- a/core/fxcrt/widestring.h
+++ b/core/fxcrt/widestring.h
@@ -135,18 +135,6 @@
 
   int GetInteger() const;
 
-  std::optional<size_t> Find(WideStringView subStr, size_t start = 0) const;
-  std::optional<size_t> Find(wchar_t ch, size_t start = 0) const;
-  std::optional<size_t> ReverseFind(wchar_t ch) const;
-
-  bool Contains(WideStringView lpszSub, size_t start = 0) const {
-    return Find(lpszSub, start).has_value();
-  }
-
-  bool Contains(char ch, size_t start = 0) const {
-    return Find(ch, start).has_value();
-  }
-
   size_t Replace(WideStringView pOld, WideStringView pNew);
 
   bool IsASCII() const { return AsStringView().IsASCII(); }