Put GetBuffer() and ReleaseBuffer() in StringBaseTemplate

Change-Id: I5a9af6da308d28bfd3093507d8eb07c4f9255011
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/116430
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index bff4b3c..2dae0d0 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -302,56 +302,10 @@
   return true;
 }
 
-void ByteString::ReleaseBuffer(size_t nNewLength) {
-  if (!m_pData)
-    return;
-
-  nNewLength = std::min(nNewLength, m_pData->m_nAllocLength);
-  if (nNewLength == 0) {
-    clear();
-    return;
-  }
-
-  DCHECK_EQ(m_pData->m_nRefs, 1);
-  m_pData->m_nDataLength = nNewLength;
-  m_pData->m_String[nNewLength] = 0;
-  if (m_pData->m_nAllocLength - nNewLength >= 32) {
-    // Over arbitrary threshold, so pay the price to relocate.  Force copy to
-    // always occur by holding a second reference to the string.
-    ByteString preserve(*this);
-    ReallocBeforeWrite(nNewLength);
-  }
-}
-
 void ByteString::Reserve(size_t len) {
   GetBuffer(len);
 }
 
-pdfium::span<char> ByteString::GetBuffer(size_t nMinBufLength) {
-  if (!m_pData) {
-    if (nMinBufLength == 0) {
-      return pdfium::span<char>();
-    }
-    m_pData = StringData::Create(nMinBufLength);
-    m_pData->m_nDataLength = 0;
-    m_pData->m_String[0] = 0;
-    return pdfium::span<char>(m_pData->m_String, m_pData->m_nAllocLength);
-  }
-
-  if (m_pData->CanOperateInPlace(nMinBufLength))
-    return pdfium::span<char>(m_pData->m_String, m_pData->m_nAllocLength);
-
-  nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength);
-  if (nMinBufLength == 0)
-    return pdfium::span<char>();
-
-  RetainPtr<StringData> pNewData = StringData::Create(nMinBufLength);
-  pNewData->CopyContents(*m_pData);
-  pNewData->m_nDataLength = m_pData->m_nDataLength;
-  m_pData = std::move(pNewData);
-  return pdfium::span<char>(m_pData->m_String, m_pData->m_nAllocLength);
-}
-
 size_t ByteString::Delete(size_t index, size_t count) {
   if (!m_pData)
     return 0;
diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h
index a5a33dc..e698773 100644
--- a/core/fxcrt/bytestring.h
+++ b/core/fxcrt/bytestring.h
@@ -166,17 +166,6 @@
 
   void Reserve(size_t len);
 
-  // Increase the backing store of the string so that it is capable of storing
-  // at least `nMinBufLength` chars. Returns a span to the entire buffer,
-  // which may be larger than `nMinBufLength` due to rounding by allocators.
-  // Note: any modification of the string (including ReleaseBuffer()) may
-  // invalidate the span, which must not outlive its buffer.
-  pdfium::span<char> GetBuffer(size_t nMinBufLength);
-
-  // Sets the size of the string to `nNewLength` chars. Call this after a call
-  // to GetBuffer(), to indicate how much of the buffer was actually used.
-  void ReleaseBuffer(size_t nNewLength);
-
   ByteString Substr(size_t offset) const;
   ByteString Substr(size_t first, size_t count) const;
   ByteString First(size_t count) const;
diff --git a/core/fxcrt/string_template.cpp b/core/fxcrt/string_template.cpp
index 85fd480..ec77706 100644
--- a/core/fxcrt/string_template.cpp
+++ b/core/fxcrt/string_template.cpp
@@ -17,6 +17,52 @@
 namespace fxcrt {
 
 template <typename T>
+pdfium::span<T> StringTemplate<T>::GetBuffer(size_t nMinBufLength) {
+  if (!m_pData) {
+    if (nMinBufLength == 0) {
+      return pdfium::span<T>();
+    }
+    m_pData = StringData::Create(nMinBufLength);
+    m_pData->m_nDataLength = 0;
+    m_pData->m_String[0] = 0;
+    return pdfium::span<T>(m_pData->m_String, m_pData->m_nAllocLength);
+  }
+  if (m_pData->CanOperateInPlace(nMinBufLength)) {
+    return pdfium::span<T>(m_pData->m_String, m_pData->m_nAllocLength);
+  }
+  nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength);
+  if (nMinBufLength == 0) {
+    return pdfium::span<T>();
+  }
+  RetainPtr<StringData> pNewData = StringData::Create(nMinBufLength);
+  pNewData->CopyContents(*m_pData);
+  pNewData->m_nDataLength = m_pData->m_nDataLength;
+  m_pData = std::move(pNewData);
+  return pdfium::span<T>(m_pData->m_String, m_pData->m_nAllocLength);
+}
+
+template <typename T>
+void StringTemplate<T>::ReleaseBuffer(size_t nNewLength) {
+  if (!m_pData) {
+    return;
+  }
+  nNewLength = std::min(nNewLength, m_pData->m_nAllocLength);
+  if (nNewLength == 0) {
+    clear();
+    return;
+  }
+  DCHECK_EQ(m_pData->m_nRefs, 1);
+  m_pData->m_nDataLength = nNewLength;
+  m_pData->m_String[nNewLength] = 0;
+  if (m_pData->m_nAllocLength - nNewLength >= 32) {
+    // Over arbitrary threshold, so pay the price to relocate.  Force copy to
+    // always occur by holding a second reference to the string.
+    StringTemplate preserve(*this);
+    ReallocBeforeWrite(nNewLength);
+  }
+}
+
+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 51be807..c479332 100644
--- a/core/fxcrt/string_template.h
+++ b/core/fxcrt/string_template.h
@@ -28,6 +28,17 @@
   // to force immediate release if desired.
   void clear();
 
+  // Increase the backing store of the string so that it is capable of storing
+  // at least `nMinBufLength` chars. Returns a span to the entire buffer,
+  // which may be larger than `nMinBufLength` due to rounding by allocators.
+  // Note: any modification of the string (including ReleaseBuffer()) may
+  // invalidate the span, which must not outlive its buffer.
+  pdfium::span<T> GetBuffer(size_t nMinBufLength);
+
+  // Sets the size of the string to `nNewLength` chars. Call this after a call
+  // to GetBuffer(), to indicate how much of the buffer was actually used.
+  void ReleaseBuffer(size_t nNewLength);
+
  protected:
   using StringView = StringViewTemplate<T>;
   using StringData = StringDataTemplate<T>;
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index a9cd10b..314c10e 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -557,56 +557,10 @@
   return Compare(other) < 0;
 }
 
-void WideString::ReleaseBuffer(size_t nNewLength) {
-  if (!m_pData)
-    return;
-
-  nNewLength = std::min(nNewLength, m_pData->m_nAllocLength);
-  if (nNewLength == 0) {
-    clear();
-    return;
-  }
-
-  DCHECK_EQ(m_pData->m_nRefs, 1);
-  m_pData->m_nDataLength = nNewLength;
-  m_pData->m_String[nNewLength] = 0;
-  if (m_pData->m_nAllocLength - nNewLength >= 32) {
-    // Over arbitrary threshold, so pay the price to relocate.  Force copy to
-    // always occur by holding a second reference to the string.
-    WideString preserve(*this);
-    ReallocBeforeWrite(nNewLength);
-  }
-}
-
 void WideString::Reserve(size_t len) {
   GetBuffer(len);
 }
 
-pdfium::span<wchar_t> WideString::GetBuffer(size_t nMinBufLength) {
-  if (!m_pData) {
-    if (nMinBufLength == 0)
-      return pdfium::span<wchar_t>();
-
-    m_pData = StringData::Create(nMinBufLength);
-    m_pData->m_nDataLength = 0;
-    m_pData->m_String[0] = 0;
-    return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength);
-  }
-
-  if (m_pData->CanOperateInPlace(nMinBufLength))
-    return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength);
-
-  nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength);
-  if (nMinBufLength == 0)
-    return pdfium::span<wchar_t>();
-
-  RetainPtr<StringData> pNewData = StringData::Create(nMinBufLength);
-  pNewData->CopyContents(*m_pData);
-  pNewData->m_nDataLength = m_pData->m_nDataLength;
-  m_pData = std::move(pNewData);
-  return pdfium::span<wchar_t>(m_pData->m_String, m_pData->m_nAllocLength);
-}
-
 size_t WideString::Delete(size_t index, size_t count) {
   if (!m_pData)
     return 0;
diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h
index 3d199fd..8cdb69d 100644
--- a/core/fxcrt/widestring.h
+++ b/core/fxcrt/widestring.h
@@ -184,17 +184,6 @@
 
   void Reserve(size_t len);
 
-  // Increase the backing store of the string so that it is capable of storing
-  // at least `nMinBufLength` wchars. Returns a span to the entire buffer,
-  // which may be larger than `nMinBufLength` due to rounding by allocators.
-  // Note: any modification of the string (including ReleaseBuffer()) may
-  // invalidate the span, which must not outlive its buffer.
-  pdfium::span<wchar_t> GetBuffer(size_t nMinBufLength);
-
-  // Sets the size of the string to `nNewLength` wchars. Call this after a call
-  // to GetBuffer(), to indicate how much of the buffer was actually used.
-  void ReleaseBuffer(size_t nNewLength);
-
   int GetInteger() const;
 
   std::optional<size_t> Find(WideStringView subStr, size_t start = 0) const;