include/tools/stream.hxx         |    3 --
 tools/CppunitTest_tools_test.mk  |    1 
 tools/qa/cppunit/test_stream.cxx |   40 +++++++++++++++++++++++++++++++++++++++
 tools/source/stream/stream.cxx   |   17 ++++++++++++----
 4 files changed, 55 insertions(+), 6 deletions(-)

New commits:
commit e7be4bb5a3a388e844b718fa843c7a66b5c286d1
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Oct 18 15:00:02 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Oct 22 09:32:54 2022 +0200

    Fix StartWritingUnicodeText
    
    Its comment in include/tools/stream.hxx tells:
      Switch to no endian swapping and write 0xfeff
    
    It was introduced in commit 3c2105e07d29b2069349e1a54e08463d359f988f
      Author Eike Rathke <e...@openoffice.org>
      Date   Fri Dec 22 00:19:05 2000 +0000
        new: read/write Unicode or Bytecode
    
    and included a call to SetEndianSwap( FALSE ). That call was dropped
    in commit 8130714148d58dd2bf1ef12dcc6dd6d5838be0d1
      Author Noel Grandin <n...@peralex.com>
      Date   Mon Jan 05 08:47:31 2015 +0200
        fdo#84938: replace NUMBERFORMAT_INT_ constants with 'enum class'
    
    (likely by accident).
    
    To simplify the fix, drop redundant m_nEndian: m_isSwap is enough.
    
    Change-Id: Ia9a0fe2d55563e7ba21bd4cf17c4ca999c6feaf7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141521
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/include/tools/stream.hxx b/include/tools/stream.hxx
index c0b920c1d20f..c56a3d44cef6 100644
--- a/include/tools/stream.hxx
+++ b/include/tools/stream.hxx
@@ -161,7 +161,6 @@ private:
     bool            m_isSwap;
     bool            m_isEof;
     ErrCode         m_nError;
-    SvStreamEndian  m_nEndian;
     SvStreamCompressFlags m_nCompressMode;
     LineEnd         m_eLineDelimiter;
     rtl_TextEncoding m_eStreamCharSet;
@@ -207,7 +206,7 @@ public:
     virtual void    ResetError();
 
     void            SetEndian( SvStreamEndian SvStreamEndian );
-    SvStreamEndian  GetEndian() const { return m_nEndian; }
+    SvStreamEndian  GetEndian() const;
     /// returns status of endian swap flag
     bool            IsEndianSwap() const { return m_isSwap; }
 
diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk
index 7f36ab8f8f02..9cf6c671fcef 100644
--- a/tools/CppunitTest_tools_test.mk
+++ b/tools/CppunitTest_tools_test.mk
@@ -63,6 +63,7 @@ $(eval $(call gb_CppunitTest_use_libraries,tools_test, \
     tl \
     test \
     unotest \
+    utl \
     vcl \
 ))
 
diff --git a/tools/qa/cppunit/test_stream.cxx b/tools/qa/cppunit/test_stream.cxx
index 9a97fb5c4671..5febc25abbc9 100644
--- a/tools/qa/cppunit/test_stream.cxx
+++ b/tools/qa/cppunit/test_stream.cxx
@@ -12,6 +12,7 @@
 #include <cppunit/TestFixture.h>
 #include <cppunit/extensions/HelperMacros.h>
 #include <tools/stream.hxx>
+#include <unotools/tempfile.hxx>
 #include <sstream>
 
 //Tests for eofbit/badbit/goodbit/failbit
@@ -28,6 +29,7 @@ namespace
         void test_read_pstring();
         void test_readline();
         void test_makereadonly();
+        void test_write_unicode();
 
         CPPUNIT_TEST_SUITE(Test);
         CPPUNIT_TEST(test_stdstream);
@@ -36,6 +38,7 @@ namespace
         CPPUNIT_TEST(test_read_pstring);
         CPPUNIT_TEST(test_readline);
         CPPUNIT_TEST(test_makereadonly);
+        CPPUNIT_TEST(test_write_unicode);
         CPPUNIT_TEST_SUITE_END();
     };
 
@@ -308,6 +311,43 @@ namespace
         CPPUNIT_ASSERT_EQUAL(sal_Int64(21), res);
     }
 
+    void Test::test_write_unicode()
+    {
+        const OUString write("abc");
+        utl::TempFileNamed aTempFile(u"test_write_unicode");
+        aTempFile.EnableKillingFile();
+        {
+            SvStream& s = *aTempFile.GetStream(StreamMode::WRITE);
+            s.SetEndian(SvStreamEndian::BIG);
+            if (!s.IsEndianSwap())
+                s.SetEndian(SvStreamEndian::LITTLE);
+            CPPUNIT_ASSERT(s.IsEndianSwap());
+            // StartWritingUnicodeText must switch to no endian swapping and 
write 0xfeff
+            s.StartWritingUnicodeText();
+            // Without the fix in place, this would fail
+            CPPUNIT_ASSERT(!s.IsEndianSwap());
+            s.WriteUnicodeOrByteText(write, RTL_TEXTENCODING_UNICODE);
+            aTempFile.CloseStream();
+        }
+        {
+            SvStream& s = *aTempFile.GetStream(StreamMode::READ);
+            s.SetEndian(SvStreamEndian::BIG);
+            if (!s.IsEndianSwap())
+                s.SetEndian(SvStreamEndian::LITTLE);
+            CPPUNIT_ASSERT(s.IsEndianSwap());
+            s.StartReadingUnicodeText(RTL_TEXTENCODING_DONTKNOW);
+            CPPUNIT_ASSERT(!s.IsEndianSwap());
+            CPPUNIT_ASSERT_EQUAL(sal_uInt64(2), s.Tell()); // after BOM
+            OUString read;
+            CPPUNIT_ASSERT(s.ReadUniOrByteStringLine(read, 
RTL_TEXTENCODING_UNICODE));
+            // Without the fix in place, this would fail with
+            // - Expected: abc
+            // - Actual  : 愀戀挀
+            CPPUNIT_ASSERT_EQUAL(write, read);
+            aTempFile.CloseStream();
+        }
+    }
+
     CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 }
 
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
index f2aed5da6174..f6d703423828 100644
--- a/tools/source/stream/stream.cxx
+++ b/tools/source/stream/stream.cxx
@@ -361,11 +361,19 @@ void SvStream::SetError( ErrCode nErrorCode )
 
 void SvStream::SetEndian( SvStreamEndian nNewFormat )
 {
-    m_nEndian = nNewFormat;
 #ifdef OSL_BIGENDIAN
-    m_isSwap = m_nEndian == SvStreamEndian::LITTLE;
+    m_isSwap = nNewFormat == SvStreamEndian::LITTLE;
 #else
-    m_isSwap = m_nEndian == SvStreamEndian::BIG;
+    m_isSwap = nNewFormat == SvStreamEndian::BIG;
+#endif
+}
+
+SvStreamEndian SvStream::GetEndian() const
+{
+#ifdef OSL_BIGENDIAN
+    return m_isSwap ? SvStreamEndian::LITTLE : SvStreamEndian::BIG;
+#else
+    return m_isSwap ? SvStreamEndian::BIG : SvStreamEndian::LITTLE;
 #endif
 }
 
@@ -709,10 +717,11 @@ bool SvStream::WriteUniOrByteChar( sal_Unicode ch, 
rtl_TextEncoding eDestCharSet
 
 void SvStream::StartWritingUnicodeText()
 {
+    m_isSwap = false; // Switch to no endian swapping
     // BOM, Byte Order Mark, U+FEFF, see
     // http://www.unicode.org/faq/utf_bom.html#BOM
     // Upon read: 0xfeff(-257) => no swap; 0xfffe(-2) => swap
-    writeNumberWithoutSwap(sal_uInt16(0xfeff)); // write native format
+    WriteUInt16(0xfeff);
 }
 
 void SvStream::StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet )

Reply via email to