From e3589af56a00468815835b99e16a150856c36b31 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Nov 2017 23:35:49 +0100 Subject: [PATCH] Fix wxStringOutputStream position when using external string Initialize m_pos correctly when using an existing, and hence possibly not empty, string (and not the internal one which is always empty initially). The old code was totally wrong as it divided the string length by the size of wxChar instead of multiplying by it, but doing this could have been wrong too with UTF-16 and surrogates, so use the conversion object to compute the real length of the string representation in the corresponding encoding. Add a simple unit test checking that this works as intended. Closes #17985. --- src/common/sstream.cpp | 9 ++++++++- tests/streams/sstream.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/common/sstream.cpp b/src/common/sstream.cpp index 1ed54f5c9d..a67cd23152 100644 --- a/src/common/sstream.cpp +++ b/src/common/sstream.cpp @@ -135,7 +135,14 @@ wxStringOutputStream::wxStringOutputStream(wxString *pString, wxMBConv& conv) #endif // wxUSE_UNICODE { m_str = pString ? pString : &m_strInternal; - m_pos = m_str->length() / sizeof(wxChar); + +#if wxUSE_UNICODE_WCHAR + m_pos = m_conv.FromWChar(NULL, 0, m_str->wc_str(), m_str->length()); +#elif wxUSE_UNICODE_UTF8 + m_pos = m_str->utf8_length(); +#else // !wxUSE_UNICODE + m_pos = m_str->length(); +#endif // wxUSE_UNICODE/!wxUSE_UNICODE } // ---------------------------------------------------------------------------- diff --git a/tests/streams/sstream.cpp b/tests/streams/sstream.cpp index f421b8f4e2..6b2903b2ff 100644 --- a/tests/streams/sstream.cpp +++ b/tests/streams/sstream.cpp @@ -119,3 +119,32 @@ void strStream::Output_Check() // Register the stream sub suite, by using some stream helper macro. STREAM_TEST_SUBSUITE_NAMED_REGISTRATION(strStream) + +TEST_CASE("wxStringOutputStream::Tell", "[stream]") +{ + wxStringOutputStream ss; + CHECK( ss.TellO() == 0 ); + + const char* const s = "Hello world"; + const wxFileOffset len = strlen(s); + + ss.Write(s, len); + CHECK( ss.TellO() == len ); + + wxString str(s); + CHECK( wxStringOutputStream(&str).TellO() == len ); + + + wxMBConvUTF16 convUTF16; + wxStringOutputStream ss16(NULL, convUTF16); + CHECK( ss16.TellO() == 0 ); + + const wxCharBuffer s16 = convUTF16.cWC2MB(wxWCharBuffer(str.wc_str())); + ss16.Write(s16, s16.length()); + CHECK( ss16.TellO() == 2*len ); + CHECK( wxStringOutputStream(&str, convUTF16).TellO() == 2*len ); + + // The U+2070D character is represented by a surrogate pair in UTF-16. + wxString u2070D = wxString::FromUTF8("\xF0\xA0\x9C\x8D"); + CHECK( wxStringOutputStream(&u2070D, convUTF16).TellO() == 4 ); +}