De-virtualize IFX_WriteStream::WriteString()

Given a virtual WriteBlock() method, there's no need to have N
identical virtual implementations of WriteString(). Similarly, move
the other write methods from IFX_ArchiveStream to here, and
de-virtualize.

This requires a change to StringWriteStream, which was never actually
seekable, to subclass IFX_RetainableWriteStream, to avoid being called
with a non-zero offset via the consolidated IFX_SeekableWriteStream
method.

In turn, this required changing the arguments to some functions to
be retainable write streams (just as well since they were never
seeked).

Change-Id: I65eb32649b812f6e931635bcecfc4885339446ac
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82971
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index 87ca911..3dc2de2 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -40,10 +40,6 @@
   ~CFX_FileBufferArchive() override;
 
   bool WriteBlock(const void* pBuf, size_t size) override;
-  bool WriteByte(uint8_t byte) override;
-  bool WriteDWord(uint32_t i) override;
-  bool WriteString(ByteStringView str) override;
-
   FX_FILESIZE CurrentOffset() const override { return offset_; }
 
  private:
@@ -103,20 +99,6 @@
   return true;
 }
 
-bool CFX_FileBufferArchive::WriteByte(uint8_t byte) {
-  return WriteBlock(&byte, 1);
-}
-
-bool CFX_FileBufferArchive::WriteDWord(uint32_t i) {
-  char buf[32];
-  FXSYS_itoa(i, buf, 10);
-  return WriteBlock(buf, strlen(buf));
-}
-
-bool CFX_FileBufferArchive::WriteString(ByteStringView str) {
-  return WriteBlock(str.raw_str(), str.GetLength());
-}
-
 ByteString GenerateFileID(uint32_t dwSeed1, uint32_t dwSeed2) {
   uint32_t buffer[4];
   void* pContext1 = FX_Random_MT_Start(dwSeed1);
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
index 9cb1336..1577b87 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
@@ -13,16 +13,6 @@
 
 CPDF_StringArchiveStream::~CPDF_StringArchiveStream() = default;
 
-bool CPDF_StringArchiveStream::WriteByte(uint8_t byte) {
-  NOTREACHED();
-  return false;
-}
-
-bool CPDF_StringArchiveStream::WriteDWord(uint32_t i) {
-  NOTREACHED();
-  return false;
-}
-
 FX_FILESIZE CPDF_StringArchiveStream::CurrentOffset() const {
   NOTREACHED();
   return false;
@@ -32,8 +22,3 @@
   stream_->write(static_cast<const char*>(pData), size);
   return true;
 }
-
-bool CPDF_StringArchiveStream::WriteString(ByteStringView str) {
-  stream_->write(str.unterminated_c_str(), str.GetLength());
-  return true;
-}
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.h b/core/fpdfapi/edit/cpdf_stringarchivestream.h
index 59d168f..b1b5f72 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.h
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.h
@@ -12,12 +12,9 @@
   explicit CPDF_StringArchiveStream(std::ostringstream* stream);
   ~CPDF_StringArchiveStream() override;
 
-  // IFX_ArchiveStream
-  bool WriteByte(uint8_t byte) override;
-  bool WriteDWord(uint32_t i) override;
-  FX_FILESIZE CurrentOffset() const override;
+  // IFX_ArchiveStream:
   bool WriteBlock(const void* pData, size_t size) override;
-  bool WriteString(ByteStringView str) override;
+  FX_FILESIZE CurrentOffset() const override;
 
  private:
   std::ostringstream* stream_;
diff --git a/core/fxcrt/fx_stream.cpp b/core/fxcrt/fx_stream.cpp
index 54ab02c..c2c5cc4 100644
--- a/core/fxcrt/fx_stream.cpp
+++ b/core/fxcrt/fx_stream.cpp
@@ -69,6 +69,20 @@
 
 }  // namespace
 
+bool IFX_WriteStream::WriteString(ByteStringView str) {
+  return WriteBlock(str.unterminated_c_str(), str.GetLength());
+}
+
+bool IFX_WriteStream::WriteByte(uint8_t byte) {
+  return WriteBlock(&byte, 1);
+}
+
+bool IFX_WriteStream::WriteDWord(uint32_t i) {
+  char buf[32];
+  FXSYS_itoa(i, buf, 10);
+  return WriteBlock(buf, strlen(buf));
+}
+
 // static
 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
     const char* filename,
@@ -115,10 +129,6 @@
   return WriteBlockAtOffset(buffer, GetSize(), size);
 }
 
-bool IFX_SeekableStream::WriteString(ByteStringView str) {
-  return WriteBlock(str.unterminated_c_str(), str.GetLength());
-}
-
 FX_FolderHandle* FX_OpenFolder(const char* path) {
   auto handle = std::make_unique<FX_FolderHandle>();
 #if defined(OS_WIN)
diff --git a/core/fxcrt/fx_stream.h b/core/fxcrt/fx_stream.h
index 65480f0..576efb6 100644
--- a/core/fxcrt/fx_stream.h
+++ b/core/fxcrt/fx_stream.h
@@ -34,7 +34,10 @@
 class IFX_WriteStream {
  public:
   virtual bool WriteBlock(const void* pData, size_t size) = 0;
-  virtual bool WriteString(ByteStringView str) = 0;
+
+  bool WriteString(ByteStringView str);
+  bool WriteByte(uint8_t byte);
+  bool WriteDWord(uint32_t i);
 
  protected:
   virtual ~IFX_WriteStream() = default;
@@ -42,8 +45,6 @@
 
 class IFX_ArchiveStream : public IFX_WriteStream {
  public:
-  virtual bool WriteByte(uint8_t byte) = 0;
-  virtual bool WriteDWord(uint32_t i) = 0;
   virtual FX_FILESIZE CurrentOffset() const = 0;
 };
 
@@ -94,7 +95,6 @@
 
   // IFX_SeekableWriteStream:
   bool WriteBlock(const void* buffer, size_t size) override;
-  bool WriteString(ByteStringView str) override;
 };
 
 #endif  // CORE_FXCRT_FX_STREAM_H_
diff --git a/core/fxcrt/xml/cfx_xmlchardata.cpp b/core/fxcrt/xml/cfx_xmlchardata.cpp
index 1d42bd0..53af635 100644
--- a/core/fxcrt/xml/cfx_xmlchardata.cpp
+++ b/core/fxcrt/xml/cfx_xmlchardata.cpp
@@ -22,7 +22,7 @@
 }
 
 void CFX_XMLCharData::Save(
-    const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) {
+    const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) {
   pXMLStream->WriteString("<![CDATA[");
   pXMLStream->WriteString(GetText().ToUTF8().AsStringView());
   pXMLStream->WriteString("]]>");
diff --git a/core/fxcrt/xml/cfx_xmlchardata.h b/core/fxcrt/xml/cfx_xmlchardata.h
index 4d3a7f0..80df483 100644
--- a/core/fxcrt/xml/cfx_xmlchardata.h
+++ b/core/fxcrt/xml/cfx_xmlchardata.h
@@ -20,7 +20,7 @@
   // CFX_XMLNode
   Type GetType() const override;
   CFX_XMLNode* Clone(CFX_XMLDocument* doc) override;
-  void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override;
+  void Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) override;
 };
 
 inline CFX_XMLCharData* ToXMLCharData(CFX_XMLNode* pNode) {
diff --git a/core/fxcrt/xml/cfx_xmlelement.cpp b/core/fxcrt/xml/cfx_xmlelement.cpp
index 58863bc..868057c 100644
--- a/core/fxcrt/xml/cfx_xmlelement.cpp
+++ b/core/fxcrt/xml/cfx_xmlelement.cpp
@@ -79,7 +79,7 @@
 }
 
 void CFX_XMLElement::Save(
-    const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) {
+    const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) {
   ByteString bsNameEncoded = name_.ToUTF8();
 
   pXMLStream->WriteString("<");
diff --git a/core/fxcrt/xml/cfx_xmlelement.h b/core/fxcrt/xml/cfx_xmlelement.h
index efc9fbb..89a1a3b 100644
--- a/core/fxcrt/xml/cfx_xmlelement.h
+++ b/core/fxcrt/xml/cfx_xmlelement.h
@@ -22,7 +22,7 @@
   // CFX_XMLNode
   Type GetType() const override;
   CFX_XMLNode* Clone(CFX_XMLDocument* doc) override;
-  void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override;
+  void Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) override;
 
   const WideString& GetName() const { return name_; }
 
diff --git a/core/fxcrt/xml/cfx_xmlinstruction.cpp b/core/fxcrt/xml/cfx_xmlinstruction.cpp
index 9514f13..0eb856a 100644
--- a/core/fxcrt/xml/cfx_xmlinstruction.cpp
+++ b/core/fxcrt/xml/cfx_xmlinstruction.cpp
@@ -38,7 +38,7 @@
 }
 
 void CFX_XMLInstruction::Save(
-    const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) {
+    const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) {
   if (name_.EqualsASCIINoCase("xml")) {
     pXMLStream->WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
     return;
diff --git a/core/fxcrt/xml/cfx_xmlinstruction.h b/core/fxcrt/xml/cfx_xmlinstruction.h
index f4ba112..1a75bbd 100644
--- a/core/fxcrt/xml/cfx_xmlinstruction.h
+++ b/core/fxcrt/xml/cfx_xmlinstruction.h
@@ -22,7 +22,7 @@
   // CFX_XMLNode
   Type GetType() const override;
   CFX_XMLNode* Clone(CFX_XMLDocument* doc) override;
-  void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override;
+  void Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) override;
 
   bool IsOriginalXFAVersion() const;
   bool IsAcrobat() const;
diff --git a/core/fxcrt/xml/cfx_xmlnode.h b/core/fxcrt/xml/cfx_xmlnode.h
index 283fa71..57706a0 100644
--- a/core/fxcrt/xml/cfx_xmlnode.h
+++ b/core/fxcrt/xml/cfx_xmlnode.h
@@ -28,7 +28,7 @@
 
   virtual Type GetType() const = 0;
   virtual CFX_XMLNode* Clone(CFX_XMLDocument* doc) = 0;
-  virtual void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) = 0;
+  virtual void Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) = 0;
 
   CFX_XMLNode* GetRoot();
   void InsertChildNode(CFX_XMLNode* pNode, int32_t index);
diff --git a/core/fxcrt/xml/cfx_xmltext.cpp b/core/fxcrt/xml/cfx_xmltext.cpp
index 0790b15..320a4e0 100644
--- a/core/fxcrt/xml/cfx_xmltext.cpp
+++ b/core/fxcrt/xml/cfx_xmltext.cpp
@@ -20,6 +20,6 @@
   return doc->CreateNode<CFX_XMLText>(text_);
 }
 
-void CFX_XMLText::Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) {
+void CFX_XMLText::Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) {
   pXMLStream->WriteString(GetText().EncodeEntities().ToUTF8().AsStringView());
 }
diff --git a/core/fxcrt/xml/cfx_xmltext.h b/core/fxcrt/xml/cfx_xmltext.h
index 72ca242..378191b 100644
--- a/core/fxcrt/xml/cfx_xmltext.h
+++ b/core/fxcrt/xml/cfx_xmltext.h
@@ -20,7 +20,7 @@
   // CFX_XMLNode
   Type GetType() const override;
   CFX_XMLNode* Clone(CFX_XMLDocument* doc) override;
-  void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override;
+  void Save(const RetainPtr<IFX_RetainableWriteStream>& pXMLStream) override;
 
   const WideString& GetText() const { return text_; }
   void SetText(const WideString& wsText) { text_ = wsText; }
diff --git a/core/fxge/win32/cpsoutput.cpp b/core/fxge/win32/cpsoutput.cpp
index 4170db1..5b39f10 100644
--- a/core/fxge/win32/cpsoutput.cpp
+++ b/core/fxge/win32/cpsoutput.cpp
@@ -36,7 +36,3 @@
   }
   return true;
 }
-
-bool CPSOutput::WriteString(ByteStringView str) {
-  return WriteBlock(str.unterminated_c_str(), str.GetLength());
-}
diff --git a/core/fxge/win32/cpsoutput.h b/core/fxge/win32/cpsoutput.h
index 939f4cc..f5a9999 100644
--- a/core/fxge/win32/cpsoutput.h
+++ b/core/fxge/win32/cpsoutput.h
@@ -19,9 +19,8 @@
   CPSOutput(HDC hDC, OutputMode mode);
   ~CPSOutput() override;
 
-  // IFX_Writestream
+  // IFX_Writestream:
   bool WriteBlock(const void* str, size_t len) override;
-  bool WriteString(ByteStringView str) override;
 
  private:
   const HDC m_hDC;
diff --git a/fpdfsdk/cpdfsdk_filewriteadapter.cpp b/fpdfsdk/cpdfsdk_filewriteadapter.cpp
index f0cbacf..bf144ba 100644
--- a/fpdfsdk/cpdfsdk_filewriteadapter.cpp
+++ b/fpdfsdk/cpdfsdk_filewriteadapter.cpp
@@ -18,7 +18,3 @@
 bool CPDFSDK_FileWriteAdapter::WriteBlock(const void* data, size_t size) {
   return file_write_->WriteBlock(file_write_.Get(), data, size) != 0;
 }
-
-bool CPDFSDK_FileWriteAdapter::WriteString(ByteStringView str) {
-  return WriteBlock(str.unterminated_c_str(), str.GetLength());
-}
diff --git a/fpdfsdk/cpdfsdk_filewriteadapter.h b/fpdfsdk/cpdfsdk_filewriteadapter.h
index 0a05422..85b9d15 100644
--- a/fpdfsdk/cpdfsdk_filewriteadapter.h
+++ b/fpdfsdk/cpdfsdk_filewriteadapter.h
@@ -18,7 +18,6 @@
 
   // IFX_WriteStream:
   bool WriteBlock(const void* data, size_t size) override;
-  bool WriteString(ByteStringView str) override;
 
  private:
   explicit CPDFSDK_FileWriteAdapter(FPDF_FILEWRITE* file_write);
diff --git a/testing/string_write_stream.cpp b/testing/string_write_stream.cpp
index 98cf4f7..f35930b 100644
--- a/testing/string_write_stream.cpp
+++ b/testing/string_write_stream.cpp
@@ -12,23 +12,7 @@
 
 StringWriteStream::~StringWriteStream() = default;
 
-FX_FILESIZE StringWriteStream::GetSize() {
-  return stream_.tellp();
-}
-
-bool StringWriteStream::Flush() {
-  return true;
-}
-
-bool StringWriteStream::WriteBlockAtOffset(const void* pData,
-                                           FX_FILESIZE offset,
-                                           size_t size) {
-  DCHECK_EQ(offset, 0);
+bool StringWriteStream::WriteBlock(const void* pData, size_t size) {
   stream_.write(static_cast<const char*>(pData), size);
   return true;
 }
-
-bool StringWriteStream::WriteString(ByteStringView str) {
-  stream_.write(str.unterminated_c_str(), str.GetLength());
-  return true;
-}
diff --git a/testing/string_write_stream.h b/testing/string_write_stream.h
index 08a2174..a664ac4 100644
--- a/testing/string_write_stream.h
+++ b/testing/string_write_stream.h
@@ -10,18 +10,13 @@
 
 #include "core/fxcrt/fx_stream.h"
 
-class StringWriteStream final : public IFX_SeekableWriteStream {
+class StringWriteStream final : public IFX_RetainableWriteStream {
  public:
   StringWriteStream();
   ~StringWriteStream() override;
 
-  // IFX_SeekableWriteStream
-  FX_FILESIZE GetSize() override;
-  bool Flush() override;
-  bool WriteBlockAtOffset(const void* pData,
-                          FX_FILESIZE offset,
-                          size_t size) override;
-  bool WriteString(ByteStringView str) override;
+  // IFX_WriteStream:
+  bool WriteBlock(const void* pData, size_t size) override;
 
   std::string ToString() const { return stream_.str(); }