Move {Byte,Wide}String::Delete() into StringTemplate<T>.

Introduce a helper method to give the entire capacity of the allocated
string buffer, and use it with spanmove() to accomplish the deletion.

Change-Id: Ife87e5c50c5e860287ed100eab7dfd6ff4eee892
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/116573
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index f1c5dec..2b17975 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -298,27 +298,6 @@
   GetBuffer(len);
 }
 
-size_t ByteString::Delete(size_t index, size_t count) {
-  if (!m_pData)
-    return 0;
-
-  size_t old_length = m_pData->m_nDataLength;
-  if (count == 0 || index != std::clamp<size_t>(index, 0, old_length)) {
-    return old_length;
-  }
-
-  size_t removal_length = index + count;
-  if (removal_length > old_length)
-    return old_length;
-
-  ReallocBeforeWrite(old_length);
-  size_t chars_to_copy = old_length - removal_length + 1;
-  FXSYS_memmove(m_pData->m_String + index, m_pData->m_String + removal_length,
-                chars_to_copy);
-  m_pData->m_nDataLength = old_length - count;
-  return m_pData->m_nDataLength;
-}
-
 intptr_t ByteString::ReferenceCountForTesting() const {
   return m_pData ? m_pData->m_nRefs : 0;
 }
diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h
index 1269010..b985adc 100644
--- a/core/fxcrt/bytestring.h
+++ b/core/fxcrt/bytestring.h
@@ -105,7 +105,6 @@
   size_t Insert(size_t index, char ch);
   size_t InsertAtFront(char ch) { return Insert(0, ch); }
   size_t InsertAtBack(char ch) { return Insert(GetLength(), ch); }
-  size_t Delete(size_t index, size_t count = 1);
 
   void Reserve(size_t len);
 
diff --git a/core/fxcrt/string_data_template.h b/core/fxcrt/string_data_template.h
index b827a81..d2661a3 100644
--- a/core/fxcrt/string_data_template.h
+++ b/core/fxcrt/string_data_template.h
@@ -39,6 +39,14 @@
     return pdfium::make_span(m_String, m_nDataLength);
   }
 
+  // Includes the terminating NUL not included in lengths.
+  pdfium::span<CharType> capacity_span() {
+    return pdfium::make_span(m_String, m_nAllocLength + 1);
+  }
+  pdfium::span<const CharType> capacity_span() const {
+    return pdfium::make_span(m_String, m_nAllocLength + 1);
+  }
+
   // Unlike std::string::front(), this is always safe and returns a
   // NUL char when the string is empty.
   CharType Front() const { return !span().empty() ? span().front() : 0; }
diff --git a/core/fxcrt/string_template.cpp b/core/fxcrt/string_template.cpp
index 0fb8b3b..f2be1ee 100644
--- a/core/fxcrt/string_template.cpp
+++ b/core/fxcrt/string_template.cpp
@@ -101,6 +101,29 @@
 }
 
 template <typename T>
+size_t StringTemplate<T>::Delete(size_t index, size_t count) {
+  if (!m_pData) {
+    return 0;
+  }
+  size_t old_length = m_pData->m_nDataLength;
+  if (count == 0 || index != std::clamp<size_t>(index, 0, old_length)) {
+    return old_length;
+  }
+  size_t removal_length = index + count;
+  if (removal_length > old_length) {
+    return old_length;
+  }
+  ReallocBeforeWrite(old_length);
+  // Include the NUL char not accounted for in lengths.
+  size_t chars_to_copy = old_length - removal_length + 1;
+  fxcrt::spanmove(
+      m_pData->capacity_span().subspan(index),
+      m_pData->capacity_span().subspan(removal_length, chars_to_copy));
+  m_pData->m_nDataLength = old_length - count;
+  return m_pData->m_nDataLength;
+}
+
+template <typename T>
 void StringTemplate<T>::ReallocBeforeWrite(size_t nNewLength) {
   if (m_pData && m_pData->CanOperateInPlace(nNewLength)) {
     return;
diff --git a/core/fxcrt/string_template.h b/core/fxcrt/string_template.h
index 137b0ff..b81aaef 100644
--- a/core/fxcrt/string_template.h
+++ b/core/fxcrt/string_template.h
@@ -104,8 +104,12 @@
   // to GetBuffer(), to indicate how much of the buffer was actually used.
   void ReleaseBuffer(size_t nNewLength);
 
+  // Returns number of instances of `ch` removed.
   size_t Remove(T ch);
 
+  // Returns size of the string following deletion.
+  size_t Delete(size_t index, size_t count = 1);
+
  protected:
   using StringView = StringViewTemplate<T>;
   using StringData = StringDataTemplate<T>;
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index 46ad6cb..79ffa10 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -553,27 +553,6 @@
   GetBuffer(len);
 }
 
-size_t WideString::Delete(size_t index, size_t count) {
-  if (!m_pData)
-    return 0;
-
-  size_t old_length = m_pData->m_nDataLength;
-  if (count == 0 || index != std::clamp<size_t>(index, 0, old_length)) {
-    return old_length;
-  }
-
-  size_t removal_length = index + count;
-  if (removal_length > old_length)
-    return old_length;
-
-  ReallocBeforeWrite(old_length);
-  size_t chars_to_copy = old_length - removal_length + 1;
-  wmemmove(m_pData->m_String + index, m_pData->m_String + removal_length,
-           chars_to_copy);
-  m_pData->m_nDataLength = old_length - count;
-  return m_pData->m_nDataLength;
-}
-
 intptr_t WideString::ReferenceCountForTesting() const {
   return m_pData ? m_pData->m_nRefs : 0;
 }
diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h
index eac1d50..e671dd1 100644
--- a/core/fxcrt/widestring.h
+++ b/core/fxcrt/widestring.h
@@ -119,7 +119,6 @@
   size_t Insert(size_t index, wchar_t ch);
   size_t InsertAtFront(wchar_t ch) { return Insert(0, ch); }
   size_t InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); }
-  size_t Delete(size_t index, size_t count = 1);
 
   void MakeLower();
   void MakeUpper();