summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fxcrt/cfx_widestring.cpp9
-rw-r--r--core/fxcrt/cfx_widestring.h4
-rw-r--r--core/fxcrt/cfx_widestring_unittest.cpp108
3 files changed, 121 insertions, 0 deletions
diff --git a/core/fxcrt/cfx_widestring.cpp b/core/fxcrt/cfx_widestring.cpp
index ef6aaad931..46192de4ab 100644
--- a/core/fxcrt/cfx_widestring.cpp
+++ b/core/fxcrt/cfx_widestring.cpp
@@ -1049,3 +1049,12 @@ int CFX_WideString::GetInteger() const {
float CFX_WideString::GetFloat() const {
return m_pData ? FX_wtof(m_pData->m_String, m_pData->m_nDataLength) : 0.0f;
}
+
+std::wostream& operator<<(std::wostream& os, const CFX_WideString& str) {
+ return os.write(str.c_str(), str.GetLength());
+}
+
+std::ostream& operator<<(std::ostream& os, const CFX_WideString& str) {
+ os << str.UTF8Encode();
+ return os;
+}
diff --git a/core/fxcrt/cfx_widestring.h b/core/fxcrt/cfx_widestring.h
index 977114816d..3d69b0be55 100644
--- a/core/fxcrt/cfx_widestring.h
+++ b/core/fxcrt/cfx_widestring.h
@@ -228,6 +228,10 @@ inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) {
uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase);
+std::wostream& operator<<(std::wostream& os, const CFX_WideString& str);
+
+std::ostream& operator<<(std::ostream& os, const CFX_WideString& str);
+
namespace std {
template <>
diff --git a/core/fxcrt/cfx_widestring_unittest.cpp b/core/fxcrt/cfx_widestring_unittest.cpp
index 165b43add6..2578cb6429 100644
--- a/core/fxcrt/cfx_widestring_unittest.cpp
+++ b/core/fxcrt/cfx_widestring_unittest.cpp
@@ -1102,3 +1102,111 @@ TEST(fxcrt, WideStringAnyAllNoneOf) {
EXPECT_TRUE(pdfium::ContainsValue(str, L'b'));
EXPECT_FALSE(pdfium::ContainsValue(str, L'z'));
}
+
+TEST(fxcrt, OStreamWideStringOverload) {
+ std::ostringstream stream;
+
+ // Basic case, empty string
+ CFX_WideString str;
+ stream << str;
+ EXPECT_EQ("", stream.str());
+
+ // Basic case, wide character
+ str = L"\u20AC";
+ stream << str;
+ EXPECT_EQ("\u20AC", stream.str());
+
+ // Basic case, non-empty string
+ str = L"def";
+ stream.str("");
+ stream << "abc" << str << "ghi";
+ EXPECT_EQ("abcdefghi", stream.str());
+
+ // Changing the CFX_WideString does not change the stream it was written to.
+ str = L"123";
+ EXPECT_EQ("abcdefghi", stream.str());
+
+ // Writing it again to the stream will use the latest value.
+ stream.str("");
+ stream << "abc" << str << "ghi";
+ EXPECT_EQ("abc123ghi", stream.str());
+
+ wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'};
+
+ // Writing a CFX_WideString with nulls and no specified length treats it as
+ // a C-style null-terminated string.
+ str = CFX_WideString(stringWithNulls);
+ EXPECT_EQ(2, str.GetLength());
+ stream.str("");
+ stream << str;
+ EXPECT_EQ(2u, stream.tellp());
+
+ // Writing a CFX_WideString with nulls but specifying its length treats it as
+ // a C++-style string.
+ str = CFX_WideString(stringWithNulls, 4);
+ EXPECT_EQ(4, str.GetLength());
+ stream.str("");
+ stream << str;
+ EXPECT_EQ(4u, stream.tellp());
+
+ // << operators can be chained.
+ CFX_WideString str1(L"abc");
+ CFX_WideString str2(L"def");
+ stream.str("");
+ stream << str1 << str2;
+ EXPECT_EQ("abcdef", stream.str());
+}
+
+TEST(fxcrt, WideOStreamWideStringOverload) {
+ std::wostringstream stream;
+
+ // Basic case, empty string
+ CFX_WideString str;
+ stream << str;
+ EXPECT_EQ(L"", stream.str());
+
+ // Basic case, wide character
+ str = L"\u20AC";
+ stream << str;
+ EXPECT_EQ(L"\u20AC", stream.str());
+
+ // Basic case, non-empty string
+ str = L"def";
+ stream.str(L"");
+ stream << L"abc" << str << L"ghi";
+ EXPECT_EQ(L"abcdefghi", stream.str());
+
+ // Changing the CFX_WideString does not change the stream it was written to.
+ str = L"123";
+ EXPECT_EQ(L"abcdefghi", stream.str());
+
+ // Writing it again to the stream will use the latest value.
+ stream.str(L"");
+ stream << L"abc" << str << L"ghi";
+ EXPECT_EQ(L"abc123ghi", stream.str());
+
+ wchar_t stringWithNulls[]{'x', 'y', '\0', 'z'};
+
+ // Writing a CFX_WideString with nulls and no specified length treats it as
+ // a C-style null-terminated string.
+ str = CFX_WideString(stringWithNulls);
+ EXPECT_EQ(2, str.GetLength());
+ stream.str(L"");
+ stream << str;
+ EXPECT_EQ(2u, stream.tellp());
+
+ // Writing a CFX_WideString with nulls but specifying its length treats it as
+ // a C++-style string.
+ str = CFX_WideString(stringWithNulls, 4);
+ EXPECT_EQ(4, str.GetLength());
+ stream.str(L"");
+ stream << str;
+ EXPECT_EQ(4u, stream.tellp());
+
+ // << operators can be chained.
+ CFX_WideString str1(L"abc");
+ CFX_WideString str2(L"def");
+ stream.str(L"");
+ stream << str1 << str2;
+ EXPECT_EQ(L"abcdef", stream.str());
+}