Convert some std::ostringstream to fxcrt::ostringstream.

Allocate buffers from Partition Alloc. The remaining usage should
all be in tests only.

Change-Id: I86dafe3377c1e3b0b041228154be9b09c8266f94
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/89133
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index d6ab0b0..149e743 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -9,6 +9,7 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <sstream>
 #include <tuple>
 #include <utility>
 
@@ -73,7 +74,7 @@
   UpdateContentStreams(GenerateModifiedStreams());
 }
 
-std::map<int32_t, std::ostringstream>
+std::map<int32_t, fxcrt::ostringstream>
 CPDF_PageContentGenerator::GenerateModifiedStreams() {
   // Make sure default graphics are created.
   GetOrCreateDefaultGraphics();
@@ -89,14 +90,14 @@
                            marked_dirty_streams.end());
 
   // Start regenerating dirty streams.
-  std::map<int32_t, std::ostringstream> streams;
+  std::map<int32_t, fxcrt::ostringstream> streams;
   std::set<int32_t> empty_streams;
   std::unique_ptr<const CPDF_ContentMarks> empty_content_marks =
       std::make_unique<CPDF_ContentMarks>();
   std::map<int32_t, const CPDF_ContentMarks*> current_content_marks;
 
   for (int32_t dirty_stream : all_dirty_streams) {
-    std::ostringstream buf;
+    fxcrt::ostringstream buf;
 
     // Set the default graphic state values
     buf << "q\n";
@@ -116,7 +117,7 @@
     if (it == streams.end())
       continue;
 
-    std::ostringstream* buf = &it->second;
+    fxcrt::ostringstream* buf = &it->second;
     empty_streams.erase(stream_index);
     current_content_marks[stream_index] = ProcessContentMarks(
         buf, pPageObj.Get(), current_content_marks[stream_index]);
@@ -125,7 +126,7 @@
 
   // Finish dirty streams.
   for (int32_t dirty_stream : all_dirty_streams) {
-    std::ostringstream* buf = &streams[dirty_stream];
+    fxcrt::ostringstream* buf = &streams[dirty_stream];
     if (pdfium::Contains(empty_streams, dirty_stream)) {
       // Clear to show that this stream needs to be deleted.
       buf->str("");
@@ -141,7 +142,7 @@
 }
 
 void CPDF_PageContentGenerator::UpdateContentStreams(
-    std::map<int32_t, std::ostringstream>&& new_stream_data) {
+    std::map<int32_t, fxcrt::ostringstream>&& new_stream_data) {
   // If no streams were regenerated or removed, nothing to do here.
   if (new_stream_data.empty())
     return;
@@ -150,7 +151,7 @@
 
   for (auto& pair : new_stream_data) {
     int32_t stream_index = pair.first;
-    std::ostringstream* buf = &pair.second;
+    fxcrt::ostringstream* buf = &pair.second;
 
     if (stream_index == CPDF_PageObject::kNoContentStream) {
       int new_stream_index = page_content_manager.AddStream(buf);
@@ -200,7 +201,7 @@
   return name;
 }
 
-bool CPDF_PageContentGenerator::ProcessPageObjects(std::ostringstream* buf) {
+bool CPDF_PageContentGenerator::ProcessPageObjects(fxcrt::ostringstream* buf) {
   bool bDirty = false;
   std::unique_ptr<const CPDF_ContentMarks> empty_content_marks =
       std::make_unique<CPDF_ContentMarks>();
@@ -227,7 +228,7 @@
 }
 
 const CPDF_ContentMarks* CPDF_PageContentGenerator::ProcessContentMarks(
-    std::ostringstream* buf,
+    fxcrt::ostringstream* buf,
     const CPDF_PageObject* pPageObj,
     const CPDF_ContentMarks* pPrev) {
   const CPDF_ContentMarks* pNext = pPageObj->GetContentMarks();
@@ -278,7 +279,7 @@
 }
 
 void CPDF_PageContentGenerator::FinishMarks(
-    std::ostringstream* buf,
+    fxcrt::ostringstream* buf,
     const CPDF_ContentMarks* pContentMarks) {
   // Technically we should iterate backwards to close from the top to the
   // bottom, but since the EMC operators do not identify which mark they are
@@ -287,7 +288,7 @@
     *buf << "EMC\n";
 }
 
-void CPDF_PageContentGenerator::ProcessPageObject(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessPageObject(fxcrt::ostringstream* buf,
                                                   CPDF_PageObject* pPageObj) {
   if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
     ProcessImage(buf, pImageObject);
@@ -300,7 +301,7 @@
   pPageObj->SetDirty(false);
 }
 
-void CPDF_PageContentGenerator::ProcessImage(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessImage(fxcrt::ostringstream* buf,
                                              CPDF_ImageObject* pImageObj) {
   if ((pImageObj->matrix().a == 0 && pImageObj->matrix().b == 0) ||
       (pImageObj->matrix().c == 0 && pImageObj->matrix().d == 0)) {
@@ -330,7 +331,7 @@
   *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
 }
 
-void CPDF_PageContentGenerator::ProcessForm(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessForm(fxcrt::ostringstream* buf,
                                             CPDF_FormObject* pFormObj) {
   if ((pFormObj->form_matrix().a == 0 && pFormObj->form_matrix().b == 0) ||
       (pFormObj->form_matrix().c == 0 && pFormObj->form_matrix().d == 0)) {
@@ -355,7 +356,7 @@
 // points as the Bezier control points
 // Note: "l", "c" change the current point
 // "h" closes the subpath (appends a line from current to starting point)
-void CPDF_PageContentGenerator::ProcessPathPoints(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessPathPoints(fxcrt::ostringstream* buf,
                                                   CPDF_Path* pPath) {
   pdfium::span<const CFX_Path::Point> points = pPath->GetPoints();
   if (pPath->IsRect()) {
@@ -397,7 +398,7 @@
 // Path painting operators: "S", "n", "B", "f", "B*", "f*", depending on
 // the filling mode and whether we want stroking the path or not.
 // "Q" restores the graphics state imposed by the ProcessGraphics method.
-void CPDF_PageContentGenerator::ProcessPath(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessPath(fxcrt::ostringstream* buf,
                                             CPDF_PathObject* pPathObj) {
   ProcessGraphics(buf, pPathObj);
 
@@ -423,7 +424,7 @@
 // "W" and "W*" modify the clipping path using the nonzero winding rule and
 // even-odd rules, respectively.
 // "q" saves the graphics state, so that the settings can later be reversed
-void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessGraphics(fxcrt::ostringstream* buf,
                                                 CPDF_PageObject* pPageObj) {
   *buf << "q ";
   float fillColor[3];
@@ -503,7 +504,7 @@
 }
 
 void CPDF_PageContentGenerator::ProcessDefaultGraphics(
-    std::ostringstream* buf) {
+    fxcrt::ostringstream* buf) {
   *buf << "0 0 0 RG 0 0 0 rg 1 w "
        << static_cast<int>(CFX_GraphStateData::LineCap::kButt) << " J "
        << static_cast<int>(CFX_GraphStateData::LineJoin::kMiter) << " j\n";
@@ -537,7 +538,7 @@
 // Tf sets the font name (from Font in Resources) and font size.
 // Tr sets the text rendering mode.
 // Tj sets the actual text, <####...> is used when specifying charcodes.
-void CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf,
+void CPDF_PageContentGenerator::ProcessText(fxcrt::ostringstream* buf,
                                             CPDF_TextObject* pTextObj) {
   ProcessGraphics(buf, pTextObj);
   *buf << "BT " << pTextObj->GetTextMatrix() << " Tm ";
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index 80ed01f..dfcd700 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -10,10 +10,10 @@
 #include <stdint.h>
 
 #include <map>
-#include <sstream>
 #include <vector>
 
 #include "core/fxcrt/bytestring.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxcrt/unowned_ptr.h"
 
 class CPDF_ContentMarks;
@@ -33,35 +33,35 @@
   ~CPDF_PageContentGenerator();
 
   void GenerateContent();
-  bool ProcessPageObjects(std::ostringstream* buf);
+  bool ProcessPageObjects(fxcrt::ostringstream* buf);
 
  private:
   friend class CPDF_PageContentGeneratorTest;
 
-  void ProcessPageObject(std::ostringstream* buf, CPDF_PageObject* pPageObj);
-  void ProcessPathPoints(std::ostringstream* buf, CPDF_Path* pPath);
-  void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj);
-  void ProcessForm(std::ostringstream* buf, CPDF_FormObject* pFormObj);
-  void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj);
-  void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);
-  void ProcessDefaultGraphics(std::ostringstream* buf);
-  void ProcessText(std::ostringstream* buf, CPDF_TextObject* pTextObj);
+  void ProcessPageObject(fxcrt::ostringstream* buf, CPDF_PageObject* pPageObj);
+  void ProcessPathPoints(fxcrt::ostringstream* buf, CPDF_Path* pPath);
+  void ProcessPath(fxcrt::ostringstream* buf, CPDF_PathObject* pPathObj);
+  void ProcessForm(fxcrt::ostringstream* buf, CPDF_FormObject* pFormObj);
+  void ProcessImage(fxcrt::ostringstream* buf, CPDF_ImageObject* pImageObj);
+  void ProcessGraphics(fxcrt::ostringstream* buf, CPDF_PageObject* pPageObj);
+  void ProcessDefaultGraphics(fxcrt::ostringstream* buf);
+  void ProcessText(fxcrt::ostringstream* buf, CPDF_TextObject* pTextObj);
   ByteString GetOrCreateDefaultGraphics() const;
   ByteString RealizeResource(const CPDF_Object* pResource,
                              const ByteString& bsType) const;
-  const CPDF_ContentMarks* ProcessContentMarks(std::ostringstream* buf,
+  const CPDF_ContentMarks* ProcessContentMarks(fxcrt::ostringstream* buf,
                                                const CPDF_PageObject* pPageObj,
                                                const CPDF_ContentMarks* pPrev);
-  void FinishMarks(std::ostringstream* buf,
+  void FinishMarks(fxcrt::ostringstream* buf,
                    const CPDF_ContentMarks* pContentMarks);
 
   // Returns a map from content stream index to new stream data. Unmodified
   // streams are not touched.
-  std::map<int32_t, std::ostringstream> GenerateModifiedStreams();
+  std::map<int32_t, fxcrt::ostringstream> GenerateModifiedStreams();
 
   // Add buffer as a stream in page's 'Contents'
   void UpdateContentStreams(
-      std::map<int32_t, std::ostringstream>&& new_stream_data);
+      std::map<int32_t, fxcrt::ostringstream>&& new_stream_data);
 
   // Set the stream index of all page objects with stream index ==
   // |CPDF_PageObject::kNoContentStream|. These are new objects that had not
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index c9eb746..d28f93a 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -34,7 +34,7 @@
   void TearDown() override { CPDF_PageModule::Destroy(); }
 
   void TestProcessPath(CPDF_PageContentGenerator* pGen,
-                       std::ostringstream* buf,
+                       fxcrt::ostringstream* buf,
                        CPDF_PathObject* pPathObj) {
     pGen->ProcessPath(buf, pPathObj);
   }
@@ -47,7 +47,7 @@
   }
 
   void TestProcessText(CPDF_PageContentGenerator* pGen,
-                       std::ostringstream* buf,
+                       fxcrt::ostringstream* buf,
                        CPDF_TextObject* pTextObj) {
     pGen->ProcessText(buf, pTextObj);
   }
@@ -63,7 +63,7 @@
   auto pTestPage =
       pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
   CPDF_PageContentGenerator generator(pTestPage.Get());
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
   EXPECT_EQ("q 1 0 0 1 0 0 cm 10 5 3 25 re B* Q\n", ByteString(buf));
 
@@ -102,7 +102,7 @@
     auto pTestPage =
         pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
     CPDF_PageContentGenerator generator(pTestPage.Get());
-    std::ostringstream buf;
+    fxcrt::ostringstream buf;
     TestProcessPath(&generator, &buf, pPathObj.get());
     EXPECT_EQ(
         "q 0 0.701961 0.34902 rg 0 0.701961 0.34902 RG 200000000000000000000 w"
@@ -136,7 +136,7 @@
     auto pTestPage =
         pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
     CPDF_PageContentGenerator generator(pTestPage.Get());
-    std::ostringstream buf;
+    fxcrt::ostringstream buf;
 
     TestProcessPath(&generator, &buf, pPathObj.get());
     EXPECT_EQ(
@@ -176,7 +176,7 @@
   auto pTestPage =
       pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
   CPDF_PageContentGenerator generator(pTestPage.Get());
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
   EXPECT_EQ(
       "q 1 0 0 1 0 0 cm 3.102 4.6700001 m 5.4499998 .28999999 l 4.2399998 "
@@ -213,7 +213,7 @@
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
   auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
   CPDF_PageContentGenerator generator(pTestPage.Get());
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
   ByteString pathString(buf);
 
@@ -273,7 +273,7 @@
   pTextObj->m_GeneralState.SetStrokeAlpha(0.8f);
   pTextObj->Transform(CFX_Matrix(1, 0, 0, 1, 100, 100));
   pTextObj->SetText("Hello World");
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   TestProcessText(&generator, &buf, pTextObj.get());
   ByteString textString(buf);
   auto firstResourceAt = textString.Find('/');
@@ -326,7 +326,7 @@
   auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
   CPDF_PageContentGenerator generator(pTestPage.Get());
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   {
     // Set the text object font and text
     auto pTextObj = std::make_unique<CPDF_TextObject>();
@@ -412,7 +412,7 @@
 
   // The generated stream for the empty form should be an empty string.
   CPDF_PageContentGenerator generator(pTestForm.get());
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   generator.ProcessPageObjects(&buf);
   EXPECT_EQ("", ByteString(buf));
 }
@@ -440,7 +440,7 @@
             pTestForm->GetParseState());
 
   CPDF_PageContentGenerator generator(pTestForm.get());
-  std::ostringstream process_buf;
+  fxcrt::ostringstream process_buf;
   generator.ProcessPageObjects(&process_buf);
   EXPECT_STREQ(
       "q 1 0 0 1 0 0 cm 3.102 4.6700001 m 5.4500012 .28999999 l 4.2399998 3.14"
diff --git a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
index 6563820..9cb9f31 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentmanager.cpp
@@ -61,7 +61,7 @@
   return nullptr;
 }
 
-size_t CPDF_PageContentManager::AddStream(std::ostringstream* buf) {
+size_t CPDF_PageContentManager::AddStream(fxcrt::ostringstream* buf) {
   CPDF_Stream* new_stream = doc_->NewIndirect<CPDF_Stream>();
   new_stream->SetDataFromStringstream(buf);
 
diff --git a/core/fpdfapi/edit/cpdf_pagecontentmanager.h b/core/fpdfapi/edit/cpdf_pagecontentmanager.h
index 1552957..0249d18 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentmanager.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentmanager.h
@@ -5,10 +5,10 @@
 #ifndef CORE_FPDFAPI_EDIT_CPDF_PAGECONTENTMANAGER_H_
 #define CORE_FPDFAPI_EDIT_CPDF_PAGECONTENTMANAGER_H_
 
-#include <iosfwd>
 #include <set>
 
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxcrt/unowned_ptr.h"
 
 class CPDF_Array;
@@ -27,7 +27,7 @@
 
   // Adds a new Content stream. Its index in the array will be returned, or 0
   // if Contents is not an array, but only a single stream.
-  size_t AddStream(std::ostringstream* buf);
+  size_t AddStream(fxcrt::ostringstream* buf);
 
   // Schedule the removal of the Content stream at a given index. It will be
   // removed when ExecuteScheduledRemovals() is called.
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
index 1577b87..237b5d2 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.cpp
@@ -8,7 +8,7 @@
 
 #include "third_party/base/notreached.h"
 
-CPDF_StringArchiveStream::CPDF_StringArchiveStream(std::ostringstream* stream)
+CPDF_StringArchiveStream::CPDF_StringArchiveStream(fxcrt::ostringstream* stream)
     : stream_(stream) {}
 
 CPDF_StringArchiveStream::~CPDF_StringArchiveStream() = default;
diff --git a/core/fpdfapi/edit/cpdf_stringarchivestream.h b/core/fpdfapi/edit/cpdf_stringarchivestream.h
index 4107122..0b0a489 100644
--- a/core/fpdfapi/edit/cpdf_stringarchivestream.h
+++ b/core/fpdfapi/edit/cpdf_stringarchivestream.h
@@ -5,13 +5,12 @@
 #ifndef CORE_FPDFAPI_EDIT_CPDF_STRINGARCHIVESTREAM_H_
 #define CORE_FPDFAPI_EDIT_CPDF_STRINGARCHIVESTREAM_H_
 
-#include <iosfwd>
-
 #include "core/fxcrt/fx_stream.h"
+#include "core/fxcrt/stl_util.h"
 
 class CPDF_StringArchiveStream final : public IFX_ArchiveStream {
  public:
-  explicit CPDF_StringArchiveStream(std::ostringstream* stream);
+  explicit CPDF_StringArchiveStream(fxcrt::ostringstream* stream);
   ~CPDF_StringArchiveStream() override;
 
   // IFX_ArchiveStream:
@@ -19,7 +18,7 @@
   FX_FILESIZE CurrentOffset() const override;
 
  private:
-  std::ostringstream* stream_;
+  fxcrt::ostringstream* stream_;
 };
 
 #endif  // CORE_FPDFAPI_EDIT_CPDF_STRINGARCHIVESTREAM_H_
diff --git a/core/fpdfapi/parser/cfdf_document.cpp b/core/fpdfapi/parser/cfdf_document.cpp
index 8e5c9d9..6f2f541 100644
--- a/core/fpdfapi/parser/cfdf_document.cpp
+++ b/core/fpdfapi/parser/cfdf_document.cpp
@@ -14,6 +14,7 @@
 #include "core/fpdfapi/parser/cpdf_syntax_parser.h"
 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
 #include "core/fxcrt/cfx_readonlymemorystream.h"
+#include "core/fxcrt/stl_util.h"
 #include "third_party/base/span.h"
 
 CFDF_Document::CFDF_Document() = default;
@@ -78,7 +79,7 @@
   if (!m_pRootDict)
     return ByteString();
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << "%FDF-1.2\r\n";
   for (const auto& pair : *this)
     buf << pair.first << " 0 obj\r\n"
diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp
index a98ba2e..bc20a22 100644
--- a/core/fpdfapi/parser/cpdf_stream.cpp
+++ b/core/fpdfapi/parser/cpdf_stream.cpp
@@ -123,7 +123,7 @@
 }
 
 void CPDF_Stream::SetDataFromStringstreamAndRemoveFilter(
-    std::ostringstream* stream) {
+    fxcrt::ostringstream* stream) {
   if (stream->tellp() <= 0) {
     SetDataAndRemoveFilter({});
     return;
@@ -155,7 +155,7 @@
   m_pDict->SetNewFor<CPDF_Number>("Length", static_cast<int>(size));
 }
 
-void CPDF_Stream::SetDataFromStringstream(std::ostringstream* stream) {
+void CPDF_Stream::SetDataFromStringstream(fxcrt::ostringstream* stream) {
   if (stream->tellp() <= 0) {
     SetData({});
     return;
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
index 37d2854..bb61f8c 100644
--- a/core/fpdfapi/parser/cpdf_stream.h
+++ b/core/fpdfapi/parser/cpdf_stream.h
@@ -7,7 +7,6 @@
 #ifndef CORE_FPDFAPI_PARSER_CPDF_STREAM_H_
 #define CORE_FPDFAPI_PARSER_CPDF_STREAM_H_
 
-#include <iosfwd>
 #include <memory>
 #include <set>
 
@@ -15,6 +14,7 @@
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_stream.h"
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/stl_util.h"
 
 class CPDF_Stream final : public CPDF_Object {
  public:
@@ -44,12 +44,12 @@
 
   void TakeData(std::unique_ptr<uint8_t, FxFreeDeleter> pData, uint32_t size);
 
-  void SetDataFromStringstream(std::ostringstream* stream);
+  void SetDataFromStringstream(fxcrt::ostringstream* stream);
 
   // Set data and remove "Filter" and "DecodeParms" fields from stream
   // dictionary.
   void SetDataAndRemoveFilter(pdfium::span<const uint8_t> pData);
-  void SetDataFromStringstreamAndRemoveFilter(std::ostringstream* stream);
+  void SetDataFromStringstreamAndRemoveFilter(fxcrt::ostringstream* stream);
 
   void InitStream(pdfium::span<const uint8_t> pData,
                   RetainPtr<CPDF_Dictionary> pDict);
diff --git a/core/fpdfapi/render/cpdf_windowsrenderdevice.cpp b/core/fpdfapi/render/cpdf_windowsrenderdevice.cpp
index 65b4745..1d9cb4e 100644
--- a/core/fpdfapi/render/cpdf_windowsrenderdevice.cpp
+++ b/core/fpdfapi/render/cpdf_windowsrenderdevice.cpp
@@ -6,6 +6,8 @@
 
 #include "core/fpdfapi/render/cpdf_windowsrenderdevice.h"
 
+#include <sstream>
+
 #include "core/fxcodec/basic/basicmodule.h"
 #include "core/fxcodec/fax/faxmodule.h"
 #include "core/fxcodec/flate/flatemodule.h"
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp
index 0e1c481..766d77b 100644
--- a/core/fpdfdoc/cpdf_generateap.cpp
+++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -33,6 +33,7 @@
 #include "core/fpdfdoc/cpvt_fontmap.h"
 #include "core/fpdfdoc/cpvt_variabletext.h"
 #include "core/fpdfdoc/cpvt_word.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxge/cfx_renderdevice.h"
 
 namespace {
@@ -84,7 +85,7 @@
 ByteString GetFontSetString(IPVT_FontMap* pFontMap,
                             int32_t nFontIndex,
                             float fFontSize) {
-  std::ostringstream sRet;
+  fxcrt::ostringstream sRet;
   if (pFontMap) {
     ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
     if (sFontAlias.GetLength() > 0 && fFontSize > 0)
@@ -98,8 +99,8 @@
                           const CFX_PointF& ptOffset,
                           bool bContinuous,
                           uint16_t SubWord) {
-  std::ostringstream sEditStream;
-  std::ostringstream sLineStream;
+  fxcrt::ostringstream sEditStream;
+  fxcrt::ostringstream sLineStream;
   CFX_PointF ptOld;
   CFX_PointF ptNew;
   int32_t nCurFontIndex = -1;
@@ -175,7 +176,7 @@
 }
 
 ByteString GenerateColorAP(const CFX_Color& color, PaintOperation nOperation) {
-  std::ostringstream sColorStream;
+  fxcrt::ostringstream sColorStream;
   switch (color.nColorType) {
     case CFX_Color::Type::kRGB:
       sColorStream << color.fColor1 << " " << color.fColor2 << " "
@@ -207,7 +208,7 @@
                             const CFX_Color& crRightBottom,
                             BorderStyle nStyle,
                             const CPVT_Dash& dash) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sColor;
   float fLeft = rect.left;
   float fRight = rect.right;
@@ -354,7 +355,7 @@
 
   // Support maximum of ten elements in the dash array.
   size_t pDashArrayCount = std::min<size_t>(pDashArray->size(), 10);
-  std::ostringstream sDashStream;
+  fxcrt::ostringstream sDashStream;
 
   sDashStream << "[";
   for (size_t i = 0; i < pDashArrayCount; ++i)
@@ -420,7 +421,7 @@
 }
 
 ByteString GenerateTextSymbolAP(const CFX_FloatRect& rect) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   sAppStream << GenerateColorAP(CFX_Color(CFX_Color::Type::kRGB, 1, 1, 0),
                                 PaintOperation::kFill);
   sAppStream << GenerateColorAP(CFX_Color(CFX_Color::Type::kRGB, 0, 0, 0),
@@ -504,7 +505,7 @@
 
 void GenerateAndSetAPDict(CPDF_Document* pDoc,
                           CPDF_Dictionary* pAnnotDict,
-                          std::ostringstream* psAppStream,
+                          fxcrt::ostringstream* psAppStream,
                           RetainPtr<CPDF_Dictionary> pResourceDict,
                           bool bIsTextMarkupAnnotation) {
   CPDF_Stream* pNormalStream = pDoc->NewIndirect<CPDF_Stream>();
@@ -530,7 +531,7 @@
 }
 
 bool GenerateCircleAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -603,7 +604,7 @@
 }
 
 bool GenerateHighlightAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -645,7 +646,7 @@
   if (!pInkList || pInkList->IsEmpty())
     return false;
 
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -688,7 +689,7 @@
 }
 
 bool GenerateTextAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -710,7 +711,7 @@
 }
 
 bool GenerateUnderlineAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -741,7 +742,7 @@
 }
 
 bool GeneratePopupAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs\n";
 
@@ -781,7 +782,7 @@
 }
 
 bool GenerateSquareAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -828,7 +829,7 @@
 }
 
 bool GenerateSquigglyAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -878,7 +879,7 @@
 }
 
 bool GenerateStrikeOutAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sExtGSDictName = "GS";
   sAppStream << "/" << sExtGSDictName << " gs ";
 
@@ -1043,7 +1044,7 @@
     if (pArray)
       crBG = fpdfdoc::CFXColorFromArray(*pArray);
   }
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sBG = GenerateColorAP(crBG, PaintOperation::kFill);
   if (sBG.GetLength() > 0) {
     sAppStream << "q\n"
@@ -1244,7 +1245,7 @@
           ToArray(CPDF_FormField::GetFieldAttr(pAnnotDict, "I"));
       CPDF_Object* pTi = CPDF_FormField::GetFieldAttr(pAnnotDict, "TI");
       int32_t nTop = pTi ? pTi->GetInteger() : 0;
-      std::ostringstream sBody;
+      fxcrt::ostringstream sBody;
       if (pOpts) {
         float fy = rcBody.top;
         for (size_t i = nTop, sz = pOpts->size(); i < sz; i++) {
@@ -1355,7 +1356,7 @@
   auto pResourceDict =
       GenerateResourceDict(pDoc, std::move(pExtGStateDict), nullptr);
 
-  std::ostringstream sStream;
+  fxcrt::ostringstream sStream;
   GenerateAndSetAPDict(pDoc, pAnnotDict, &sStream, std::move(pResourceDict),
                        false);
 }
diff --git a/core/fxcrt/bytestring.cpp b/core/fxcrt/bytestring.cpp
index 5de9b8d..dce2a0b 100644
--- a/core/fxcrt/bytestring.cpp
+++ b/core/fxcrt/bytestring.cpp
@@ -181,8 +181,8 @@
   }
 }
 
-ByteString::ByteString(const std::ostringstream& outStream) {
-  std::string str = outStream.str();
+ByteString::ByteString(const fxcrt::ostringstream& outStream) {
+  auto str = outStream.str();
   if (str.length() > 0)
     m_pData.Reset(StringData::Create(str.c_str(), str.length()));
 }
diff --git a/core/fxcrt/bytestring.h b/core/fxcrt/bytestring.h
index 234e210..830c50b 100644
--- a/core/fxcrt/bytestring.h
+++ b/core/fxcrt/bytestring.h
@@ -18,6 +18,7 @@
 #include <utility>
 
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxcrt/string_data_template.h"
 #include "core/fxcrt/string_view_template.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -63,7 +64,7 @@
   explicit ByteString(ByteStringView bstrc);
   ByteString(ByteStringView str1, ByteStringView str2);
   ByteString(const std::initializer_list<ByteStringView>& list);
-  explicit ByteString(const std::ostringstream& outStream);
+  explicit ByteString(const fxcrt::ostringstream& outStream);
 
   ~ByteString();
 
diff --git a/core/fxcrt/stl_util.h b/core/fxcrt/stl_util.h
index f4b0bdf..d4ffde0 100644
--- a/core/fxcrt/stl_util.h
+++ b/core/fxcrt/stl_util.h
@@ -47,7 +47,7 @@
   return std::vector<T, A>(safe_size.ValueOrDie());
 }
 
-// Stringstream that uses PartitionAlloc for backing store.
+// String stream that uses PartitionAlloc for backing store.
 using ostringstream = std::
     basic_ostringstream<char, std::char_traits<char>, FxStringAllocator<char>>;
 
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index 9cca4c7..55c1ad5 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -12,7 +12,6 @@
 #include <algorithm>
 #include <array>
 #include <memory>
-#include <sstream>
 #include <string>
 #include <utility>
 
@@ -60,7 +59,7 @@
 
   // Each byte is written as 2 ASCIIHex characters, so really 64 chars per line.
   constexpr size_t kMaxBytesPerLine = 32;
-  std::ostringstream output;
+  fxcrt::ostringstream output;
   output << "/" << psname << "_sfnts [\n<\n";
   size_t bytes_per_line = 0;
   char buf[2];
@@ -100,7 +99,7 @@
       (num_glyphs + glyphs_per_descendant_font - 1) /
       glyphs_per_descendant_font;
 
-  std::ostringstream output;
+  fxcrt::ostringstream output;
   for (size_t i = 0; i < descendant_font_count; ++i) {
     output << "8 dict begin\n";
     output << "/FontType 42 def\n";
@@ -257,14 +256,14 @@
   if (preamble_pos > 0) {
     m_pStream->WriteBlock(m_PreambleOutput.str().c_str(),
                           pdfium::base::checked_cast<size_t>(preamble_pos));
-    m_PreambleOutput.str(std::string());
+    m_PreambleOutput.str("");
   }
 
   // Flush `m_Output`. It's never empty because of the WriteString() call above.
   m_pStream->WriteBlock(
       m_Output.str().c_str(),
       pdfium::base::checked_cast<size_t>(std::streamoff(m_Output.tellp())));
-  m_Output.str(std::string());
+  m_Output.str("");
 }
 
 void CFX_PSRenderer::SaveState() {
@@ -291,7 +290,7 @@
 
 void CFX_PSRenderer::OutputPath(const CFX_Path& path,
                                 const CFX_Matrix* pObject2Device) {
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   size_t size = path.GetPoints().size();
 
   for (size_t i = 0; i < size; i++) {
@@ -358,7 +357,7 @@
   StartRendering();
   SetGraphState(pGraphState);
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
       << pObject2Device->c << " " << pObject2Device->d << " "
       << pObject2Device->e << " " << pObject2Device->f << "]cm ";
@@ -391,7 +390,7 @@
   if (stroke_alpha) {
     SetGraphState(pGraphState);
     if (pObject2Device) {
-      std::ostringstream buf;
+      fxcrt::ostringstream buf;
       buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
           << pObject2Device->c << " " << pObject2Device->d << " "
           << pObject2Device->e << " " << pObject2Device->f << "]cm ";
@@ -429,7 +428,7 @@
 }
 
 void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) {
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   if (!m_bGraphStateSet ||
       m_CurGraphState.m_LineCap != pGraphState->m_LineCap) {
     buf << static_cast<int>(pGraphState->m_LineCap) << " J\n";
@@ -498,7 +497,7 @@
 
   WriteString("q\n");
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << "[" << matrix.a << " " << matrix.b << " " << matrix.c << " "
       << matrix.d << " " << matrix.e << " " << matrix.f << "]cm ";
 
@@ -622,7 +621,7 @@
   if (m_bColorSet && m_LastColor == color)
     return;
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << FXARGB_R(color) / 255.0 << " " << FXARGB_G(color) / 255.0 << " "
       << FXARGB_B(color) / 255.0 << " rg\n";
   m_bColorSet = true;
@@ -663,7 +662,7 @@
       pdfium::base::checked_cast<int>((m_PSFontList.size() - 1) / 256);
   *ps_glyphindex = (m_PSFontList.size() - 1) % 256;
   if (*ps_glyphindex == 0) {
-    std::ostringstream buf;
+    fxcrt::ostringstream buf;
     buf << "8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n"
            "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding "
            "exch/.notdef put}for\n"
@@ -698,7 +697,7 @@
   if (charpos.m_bGlyphAdjust)
     TransformedPath.Transform(matrix);
 
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << "/X" << *ps_fontnum << " Ff/CharProcs get begin/" << *ps_glyphindex
       << "{n ";
   for (size_t p = 0; p < TransformedPath.GetPoints().size(); p++) {
@@ -732,7 +731,7 @@
                                          const TextCharPos* char_pos,
                                          CFX_Font* font,
                                          float font_size,
-                                         std::ostringstream& buf) {
+                                         fxcrt::ostringstream& buf) {
   CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
   RetainPtr<CFX_GlyphCache> pGlyphCache = pCache->GetGlyphCache(font);
   int last_fontnum = -1;
@@ -755,7 +754,7 @@
                                           const TextCharPos* char_pos,
                                           CFX_Font* font,
                                           float font_size,
-                                          std::ostringstream& buf) {
+                                          fxcrt::ostringstream& buf) {
   if (m_Level != RenderingLevel::kLevel3Type42 || !CanEmbed(font))
     return false;
 
@@ -808,7 +807,7 @@
     return false;
 
   SetColor(color);
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   buf << "q[" << mtObject2Device.a << " " << mtObject2Device.b << " "
       << mtObject2Device.c << " " << mtObject2Device.d << " "
       << mtObject2Device.e << " " << mtObject2Device.f << "]cm\n";
@@ -891,7 +890,7 @@
   }
 }
 
-void CFX_PSRenderer::WriteStream(std::ostringstream& stream) {
+void CFX_PSRenderer::WriteStream(fxcrt::ostringstream& stream) {
   std::streamoff output_pos = stream.tellp();
   if (output_pos > 0) {
     m_Output.write(stream.str().c_str(),
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 4271ea4..49d3542 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -19,6 +19,7 @@
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_stream.h"
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -135,12 +136,12 @@
                            const TextCharPos* char_pos,
                            CFX_Font* font,
                            float font_size,
-                           std::ostringstream& buf);
+                           fxcrt::ostringstream& buf);
   bool DrawTextAsType42Font(int char_count,
                             const TextCharPos* char_pos,
                             CFX_Font* font,
                             float font_size,
-                            std::ostringstream& buf);
+                            fxcrt::ostringstream& buf);
   bool FaxCompressData(std::unique_ptr<uint8_t, FxFreeDeleter> src_buf,
                        int width,
                        int height,
@@ -153,7 +154,7 @@
                       const char** filter) const;
   void WritePreambleString(ByteStringView str);
   void WritePSBinary(pdfium::span<const uint8_t> data);
-  void WriteStream(std::ostringstream& stream);
+  void WriteStream(fxcrt::ostringstream& stream);
   void WriteString(ByteStringView str);
 
   bool m_bInited = false;
@@ -167,8 +168,8 @@
   UnownedPtr<const EncoderIface> const m_pEncoderIface;
   RetainPtr<IFX_RetainableWriteStream> m_pStream;
   std::vector<std::unique_ptr<Glyph>> m_PSFontList;
-  std::ostringstream m_PreambleOutput;
-  std::ostringstream m_Output;
+  fxcrt::ostringstream m_PreambleOutput;
+  fxcrt::ostringstream m_Output;
   std::vector<FX_RECT> m_ClipBoxStack;
 };
 
diff --git a/core/fxge/win32/cgdi_plus_ext.cpp b/core/fxge/win32/cgdi_plus_ext.cpp
index 4db571b..7dffd0e 100644
--- a/core/fxge/win32/cgdi_plus_ext.cpp
+++ b/core/fxge/win32/cgdi_plus_ext.cpp
@@ -18,6 +18,7 @@
 #include "core/fxcrt/fx_memory.h"
 #include "core/fxcrt/fx_string.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxge/cfx_fillrenderoptions.h"
 #include "core/fxge/cfx_gemodule.h"
 #include "core/fxge/cfx_graphstatedata.h"
@@ -530,7 +531,7 @@
  private:
   LONG m_RefCount = 1;
   std::streamoff m_ReadPos = 0;
-  std::ostringstream m_InterStream;
+  fxcrt::ostringstream m_InterStream;
 };
 
 }  // namespace
diff --git a/core/fxge/win32/cps_printer_driver.cpp b/core/fxge/win32/cps_printer_driver.cpp
index e7ff871..7aae0f8 100644
--- a/core/fxge/win32/cps_printer_driver.cpp
+++ b/core/fxge/win32/cps_printer_driver.cpp
@@ -8,6 +8,7 @@
 
 #include <stdint.h>
 
+#include <sstream>
 #include <vector>
 
 #include "core/fxcrt/fx_system.h"
diff --git a/fpdfsdk/cpdfsdk_appstream.cpp b/fpdfsdk/cpdfsdk_appstream.cpp
index 3d68836..8e884e9 100644
--- a/fpdfsdk/cpdfsdk_appstream.cpp
+++ b/fpdfsdk/cpdfsdk_appstream.cpp
@@ -85,7 +85,7 @@
 
 class AutoClosedCommand {
  public:
-  AutoClosedCommand(std::ostringstream* stream,
+  AutoClosedCommand(fxcrt::ostringstream* stream,
                     ByteString open,
                     ByteString close)
       : stream_(stream), close_(close) {
@@ -95,21 +95,20 @@
   virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; }
 
  private:
-  UnownedPtr<std::ostringstream> const stream_;
+  UnownedPtr<fxcrt::ostringstream> const stream_;
   ByteString close_;
 };
 
 class AutoClosedQCommand final : public AutoClosedCommand {
  public:
-  explicit AutoClosedQCommand(std::ostringstream* stream)
+  explicit AutoClosedQCommand(fxcrt::ostringstream* stream)
       : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {}
   ~AutoClosedQCommand() override = default;
 };
 
 ByteString GetColorAppStream(const CFX_Color& color,
                              const bool& bFillOrStroke) {
-  std::ostringstream sColorStream;
-
+  fxcrt::ostringstream sColorStream;
   switch (color.nColorType) {
     case CFX_Color::Type::kTransparent:
       break;
@@ -165,7 +164,7 @@
     }
   }
 
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
   csAP << pts[0][0].x << " " << pts[0][0].y << " " << kMoveToOperator << "\n";
 
   for (size_t i = 0; i < pdfium::size(pts); ++i) {
@@ -187,7 +186,7 @@
 }
 
 ByteString GetAP_Circle(const CFX_FloatRect& crBBox) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   float fWidth = crBBox.Width();
   float fHeight = crBBox.Height();
@@ -231,7 +230,7 @@
 }
 
 ByteString GetAP_Cross(const CFX_FloatRect& crBBox) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
   csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator
@@ -243,7 +242,7 @@
 }
 
 ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   float fWidth = crBBox.Width();
   float fHeight = crBBox.Height();
@@ -263,7 +262,7 @@
 }
 
 ByteString GetAP_Square(const CFX_FloatRect& crBBox) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
   csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n";
@@ -276,7 +275,7 @@
 }
 
 ByteString GetAP_Star(const CFX_FloatRect& crBBox) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   float fRadius = (crBBox.top - crBBox.bottom) / (1 + cosf(FXSYS_PI / 5.0f));
   CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f,
@@ -303,7 +302,7 @@
 }
 
 ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) {
-  std::ostringstream csAP;
+  fxcrt::ostringstream csAP;
 
   float fWidth = crBBox.Width();
   float fHeight = crBBox.Height();
@@ -340,7 +339,7 @@
 
 ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox,
                               const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << GetColorAppStream(crText, true) << GetAP_Check(rcBBox)
@@ -351,7 +350,7 @@
 
 ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox,
                                const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << GetColorAppStream(crText, true) << GetAP_Circle(rcBBox)
@@ -362,7 +361,7 @@
 
 ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox,
                               const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << GetColorAppStream(crText, false) << GetAP_Cross(rcBBox)
@@ -373,7 +372,7 @@
 
 ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
                                 const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << "1 " << kSetLineWidthOperator << "\n"
@@ -385,7 +384,7 @@
 
 ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox,
                                const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << GetColorAppStream(crText, true) << GetAP_Square(rcBBox)
@@ -396,7 +395,7 @@
 
 ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox,
                              const CFX_Color& crText) {
-  std::ostringstream sAP;
+  fxcrt::ostringstream sAP;
   {
     AutoClosedQCommand q(&sAP);
     sAP << GetColorAppStream(crText, true) << GetAP_Star(rcBBox)
@@ -407,7 +406,7 @@
 
 ByteString GetCircleFillAppStream(const CFX_FloatRect& rect,
                                   const CFX_Color& color) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sColor = GetColorAppStream(color, true);
   if (sColor.GetLength() > 0) {
     AutoClosedQCommand q(&sAppStream);
@@ -423,7 +422,7 @@
                                     const CFX_Color& crRightBottom,
                                     BorderStyle nStyle,
                                     const CPWL_Dash& dash) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sColor;
 
   if (fWidth > 0.0f) {
@@ -574,7 +573,7 @@
   if (sFontAlias.GetLength() <= 0 || fFontSize <= 0)
     return ByteString();
 
-  std::ostringstream sRet;
+  fxcrt::ostringstream sRet;
   sRet << "/" << sFontAlias << " " << fFontSize << " "
        << kSetTextFontAndSizeOperator << "\n";
   return ByteString(sRet);
@@ -593,7 +592,7 @@
   CPWL_EditImpl::Iterator* pIterator = pEdit->GetIterator();
   pIterator->SetAt(0);
 
-  std::ostringstream sEditStream;
+  fxcrt::ostringstream sEditStream;
   int32_t nCurFontIndex = -1;
   CFX_PointF ptOld;
   CFX_PointF ptNew;
@@ -669,7 +668,7 @@
   if (!sWords.IsEmpty())
     sEditStream << GetWordRenderString(sWords.AsStringView());
 
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   if (sEditStream.tellp() > 0) {
     sAppStream << sEditStream.str();
   }
@@ -701,7 +700,7 @@
   const CFX_VectorF scale = fit.GetScale(image_size, rcPlate);
   const CFX_VectorF offset = fit.GetImageOffset(image_size, scale, rcPlate);
 
-  std::ostringstream str;
+  fxcrt::ostringstream str;
   {
     AutoClosedQCommand q(&str);
     str << rcPlate.left << " " << rcPlate.bottom << " "
@@ -886,7 +885,7 @@
       break;
   }
 
-  std::ostringstream sTemp;
+  fxcrt::ostringstream sTemp;
   sTemp << GenerateIconAppStream(IconFit, pIconStream, rcIcon);
 
   if (!rcLabel.IsEmpty()) {
@@ -903,7 +902,7 @@
   if (sTemp.tellp() <= 0)
     return ByteString();
 
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   {
     AutoClosedQCommand q(&sAppStream);
     sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
@@ -923,7 +922,7 @@
                                       const CFX_Color& crRightBottom,
                                       BorderStyle nStyle,
                                       const CPWL_Dash& dash) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sColor;
 
   float fLeft = rect.left;
@@ -1041,7 +1040,7 @@
   if (rcBBox.IsEmpty())
     return ByteString();
 
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   {
     AutoClosedQCommand q(&sAppStream);
     sAppStream << GetColorAppStream(
@@ -1084,7 +1083,7 @@
 
 ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
                                 const CFX_Color& color) {
-  std::ostringstream sAppStream;
+  fxcrt::ostringstream sAppStream;
   ByteString sColor = GetColorAppStream(color, true);
   if (sColor.GetLength() > 0) {
     AutoClosedQCommand q(&sAppStream);
@@ -1517,7 +1516,7 @@
 void CPDFSDK_AppStream::SetAsComboBox(absl::optional<WideString> sValue) {
   CPDF_FormControl* pControl = widget_->GetFormControl();
   CPDF_FormField* pField = pControl->GetField();
-  std::ostringstream sBody;
+  fxcrt::ostringstream sBody;
 
   CFX_FloatRect rcClient = widget_->GetClientRect();
   CFX_FloatRect rcButton = rcClient;
@@ -1589,7 +1588,7 @@
   CPDF_FormControl* pControl = widget_->GetFormControl();
   CPDF_FormField* pField = pControl->GetField();
   CFX_FloatRect rcClient = widget_->GetClientRect();
-  std::ostringstream sBody;
+  fxcrt::ostringstream sBody;
 
   // Font map must outlive |pEdit|.
   CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
@@ -1604,7 +1603,7 @@
   pEdit->SetFontSize(FXSYS_IsFloatZero(fFontSize) ? 12.0f : fFontSize);
   pEdit->Initialize();
 
-  std::ostringstream sList;
+  fxcrt::ostringstream sList;
   float fy = rcClient.top;
 
   int32_t nTop = pField->GetTopVisibleIndex();
@@ -1673,8 +1672,8 @@
 void CPDFSDK_AppStream::SetAsTextField(absl::optional<WideString> sValue) {
   CPDF_FormControl* pControl = widget_->GetFormControl();
   CPDF_FormField* pField = pControl->GetField();
-  std::ostringstream sBody;
-  std::ostringstream sLines;
+  fxcrt::ostringstream sBody;
+  fxcrt::ostringstream sLines;
 
   // Font map must outlive |pEdit|.
   CPDF_BAFontMap font_map(widget_->GetPDFPage()->GetDocument(),
diff --git a/fpdfsdk/cpdfsdk_interactiveform.cpp b/fpdfsdk/cpdfsdk_interactiveform.cpp
index 84fffe4..892954e 100644
--- a/fpdfsdk/cpdfsdk_interactiveform.cpp
+++ b/fpdfsdk/cpdfsdk_interactiveform.cpp
@@ -23,6 +23,7 @@
 #include "core/fpdfdoc/cpdf_formcontrol.h"
 #include "core/fpdfdoc/cpdf_interactiveform.h"
 #include "core/fxcrt/autorestorer.h"
+#include "core/fxcrt/stl_util.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_path.h"
 #include "fpdfsdk/cpdfsdk_actionhandler.h"
@@ -83,7 +84,7 @@
   if (!pFields)
     return false;
 
-  std::ostringstream fdfEncodedData;
+  fxcrt::ostringstream fdfEncodedData;
   for (uint32_t i = 0; i < pFields->size(); i++) {
     CPDF_Dictionary* pField = pFields->GetDictAt(i);
     if (!pField)
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 803e274..1feead8 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -5,6 +5,7 @@
 #include "public/fpdf_annot.h"
 
 #include <memory>
+#include <sstream>
 #include <utility>
 #include <vector>
 
@@ -170,7 +171,7 @@
   DCHECK(pStream);
 
   CPDF_PageContentGenerator generator(pForm);
-  std::ostringstream buf;
+  fxcrt::ostringstream buf;
   generator.ProcessPageObjects(&buf);
   pStream->SetDataFromStringstreamAndRemoveFilter(&buf);
 }
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 3578e76..3f84e09 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -145,7 +145,7 @@
     "end\n"
     "end\n";
 
-void AddCharcode(std::ostringstream* pBuffer, uint32_t number) {
+void AddCharcode(fxcrt::ostringstream* pBuffer, uint32_t number) {
   DCHECK(number <= 0xFFFF);
   *pBuffer << "<";
   char ans[4];
@@ -157,7 +157,7 @@
 
 // PDF spec 1.7 Section 5.9.2: "Unicode character sequences as expressed in
 // UTF-16BE encoding." See https://en.wikipedia.org/wiki/UTF-16#Description
-void AddUnicode(std::ostringstream* pBuffer, uint32_t unicode) {
+void AddUnicode(fxcrt::ostringstream* pBuffer, uint32_t unicode) {
   if (unicode >= 0xD800 && unicode <= 0xDFFF)
     unicode = 0;
 
@@ -234,7 +234,7 @@
     }
     map_range[std::make_pair(firstCharcode, curCharcode)] = firstUnicode;
   }
-  std::ostringstream buffer;
+  fxcrt::ostringstream buffer;
   buffer << ToUnicodeStart;
   // Add maps to buffer
   buffer << static_cast<uint32_t>(char_to_uni.size()) << " beginbfchar\n";
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index 9fd244c..348a325 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -28,6 +28,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfdoc/cpdf_annot.h"
+#include "core/fxcrt/stl_util.h"
 #include "fpdfsdk/cpdfsdk_helpers.h"
 #include "third_party/base/notreached.h"
 
@@ -414,7 +415,7 @@
     CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix);
     m.b = 0;
     m.c = 0;
-    std::ostringstream buf;
+    fxcrt::ostringstream buf;
     buf << m;
     ByteString str(buf);
     sStream += ByteString::Format("q %s cm /%s Do Q\n", str.c_str(),
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index 861bc8e..1a7531c 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -584,7 +584,7 @@
   matrix.Scale(settings.scale, settings.scale);
   matrix.Translate(settings.subPageStartPoint.x, settings.subPageStartPoint.y);
 
-  std::ostringstream contentStream;
+  fxcrt::ostringstream contentStream;
   contentStream << "q\n"
                 << matrix.a << " " << matrix.b << " " << matrix.c << " "
                 << matrix.d << " " << matrix.e << " " << matrix.f << " cm\n"
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index 45625ad..e142166 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -63,7 +63,7 @@
   return pPageDict->GetDirectObjectFor(pdfium::page_object::kContents);
 }
 
-void OutputPath(std::ostringstream& buf, CPDF_Path path) {
+void OutputPath(fxcrt::ostringstream& buf, CPDF_Path path) {
   const CFX_Path* pPath = path.GetObject();
   if (!pPath)
     return;
@@ -215,7 +215,7 @@
   if (!pDoc)
     return false;
 
-  std::ostringstream text_buf;
+  fxcrt::ostringstream text_buf;
   text_buf << "q ";
 
   if (clipRect) {
@@ -388,7 +388,7 @@
   if (!pContentObj)
     return;
 
-  std::ostringstream strClip;
+  fxcrt::ostringstream strClip;
   CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clipPath);
   for (size_t i = 0; i < pClipPath->GetPathCount(); ++i) {
     CPDF_Path path = pClipPath->GetPath(i);