Allow ostringsstreams to use same partition storage as ByteString.
Avoid overlapping easy-to-control streams with other kinds of
objects.
Change-Id: I977b837a6b18773289613ffb64a3e6b23b43d729
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/89171
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index a5c10fd..ffa1b60 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -175,6 +175,7 @@
"scoped_set_insertion_unittest.cpp",
"shared_copy_on_write_unittest.cpp",
"span_util_unittest.cpp",
+ "stl_util_unittest.cpp",
"string_pool_template_unittest.cpp",
"tree_node_unittest.cpp",
"unowned_ptr_unittest.cpp",
diff --git a/core/fxcrt/fx_memory_wrappers.h b/core/fxcrt/fx_memory_wrappers.h
index d7ccd89..d56b9de 100644
--- a/core/fxcrt/fx_memory_wrappers.h
+++ b/core/fxcrt/fx_memory_wrappers.h
@@ -73,4 +73,55 @@
bool operator!=(const FxAllocAllocator& that) { return false; }
};
+// Used to put backing store for std::string and std::ostringstream
+// into the string partition.
+// TODO(tsepez): de-duplicate with above if decide to keep this.
+template <class T>
+struct FxStringAllocator {
+ public:
+ using value_type = T;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ template <class U>
+ struct rebind {
+ using other = FxStringAllocator<U>;
+ };
+
+ FxStringAllocator() noexcept = default;
+ FxStringAllocator(const FxStringAllocator& other) noexcept = default;
+ ~FxStringAllocator() = default;
+
+ template <typename U>
+ FxStringAllocator(const FxStringAllocator<U>& other) noexcept {}
+
+ pointer address(reference x) const noexcept { return &x; }
+ const_pointer address(const_reference x) const noexcept { return &x; }
+ pointer allocate(size_type n, const void* hint = 0) {
+ return FX_StringAlloc(value_type, n);
+ }
+ void deallocate(pointer p, size_type n) { FX_Free(p); }
+ size_type max_size() const noexcept {
+ return std::numeric_limits<size_type>::max() / sizeof(value_type);
+ }
+
+ template <class U, class... Args>
+ void construct(U* p, Args&&... args) {
+ new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
+ }
+
+ template <class U>
+ void destroy(U* p) {
+ p->~U();
+ }
+
+ // There's no state, so they are all the same,
+ bool operator==(const FxStringAllocator& that) { return true; }
+ bool operator!=(const FxStringAllocator& that) { return false; }
+};
+
#endif // CORE_FXCRT_FX_MEMORY_WRAPPERS_H_
diff --git a/core/fxcrt/fx_memory_wrappers_unittest.cpp b/core/fxcrt/fx_memory_wrappers_unittest.cpp
index 0927683..f9bee32 100644
--- a/core/fxcrt/fx_memory_wrappers_unittest.cpp
+++ b/core/fxcrt/fx_memory_wrappers_unittest.cpp
@@ -5,6 +5,8 @@
#include "core/fxcrt/fx_memory_wrappers.h"
#include <memory>
+#include <sstream>
+#include <string>
#include <vector>
#include "build/build_config.h"
@@ -20,6 +22,7 @@
}
TEST(fxcrt, FxAllocAllocator) {
+ // Let ASAN sanity check some simple operations.
std::vector<int, FxAllocAllocator<int>> vec;
vec.push_back(42);
vec.reserve(100);
@@ -31,3 +34,15 @@
vec2.resize(0);
vec2.push_back(42);
}
+
+TEST(fxcrt, FxStringAllocator) {
+ // Let ASAN sanity check some simple operations.
+ std::basic_ostringstream<char, std::char_traits<char>,
+ FxStringAllocator<char>>
+ str;
+ str << 'B';
+ str << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ str << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ str << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+ str << 42.0f;
+}
diff --git a/core/fxcrt/stl_util.h b/core/fxcrt/stl_util.h
index 37156af..f4b0bdf 100644
--- a/core/fxcrt/stl_util.h
+++ b/core/fxcrt/stl_util.h
@@ -5,9 +5,12 @@
#ifndef CORE_FXCRT_STL_UTIL_H_
#define CORE_FXCRT_STL_UTIL_H_
+#include <iosfwd>
#include <memory>
+#include <string>
#include <vector>
+#include "core/fxcrt/fx_memory_wrappers.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "third_party/base/numerics/safe_math.h"
@@ -44,6 +47,10 @@
return std::vector<T, A>(safe_size.ValueOrDie());
}
+// Stringstream that uses PartitionAlloc for backing store.
+using ostringstream = std::
+ basic_ostringstream<char, std::char_traits<char>, FxStringAllocator<char>>;
+
} // namespace fxcrt
#endif // CORE_FXCRT_STL_UTIL_H_
diff --git a/core/fxcrt/stl_util_unittest.cpp b/core/fxcrt/stl_util_unittest.cpp
new file mode 100644
index 0000000..33b80f2
--- /dev/null
+++ b/core/fxcrt/stl_util_unittest.cpp
@@ -0,0 +1,13 @@
+// Copyright 2022 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxcrt/stl_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(STLUtil, OStringStream) {
+ fxcrt::ostringstream str;
+ str << 22 << "C is " << 71.6f << "F";
+ EXPECT_STREQ("22C is 71.6F", str.str().c_str());
+}