[Libreoffice-commits] core.git: Branch 'feature/vba-export' - 6 commits - include/oox oox/Module_oox.mk oox/qa oox/source

Markus Mohrhard markus.mohrhard at googlemail.com
Fri Aug 14 16:27:43 PDT 2015


 include/oox/ole/vbaexport.hxx              |   68 ++++++++++++++
 oox/Module_oox.mk                          |    1 
 oox/qa/unit/data/vba/reference/simple1.bin |binary
 oox/qa/unit/data/vba/simple1.bin           |    1 
 oox/qa/unit/vba_compression.cxx            |   81 +++++++++++++++++
 oox/source/ole/vbaexport.cxx               |  134 ++++++++---------------------
 6 files changed, 191 insertions(+), 94 deletions(-)

New commits:
commit 442a3b29d9b1fcc4176e7a03a3ae32c1e12de839
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat Aug 15 01:25:37 2015 +0200

    write compressed stream to a temporary file
    
    Change-Id: I4791ec65961129475bb81491dcf681295fcfdea6

diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx
index 723824b..e2ec045 100644
--- a/oox/source/ole/vbaexport.cxx
+++ b/oox/source/ole/vbaexport.cxx
@@ -591,10 +591,21 @@ void VbaExport::exportVBA()
 {
     // start here with the VBA export
     const OUString aDirFileName("/tmp/vba_dir_out.bin");
-    SvFileStream aDirStream(aDirFileName, StreamMode::WRITE);
+    SvFileStream aDirStream(aDirFileName, STREAM_READWRITE);
 
     // export
     exportDirStream(aDirStream);
+
+    aDirStream.Seek(0);
+
+    SvMemoryStream aMemoryStream(4096, 4096);
+    OUString aCompressedFileName("/tmp/vba_dir_out_compressed.bin");
+    SvFileStream aCompressedStream(aCompressedFileName, STREAM_READWRITE);
+
+    aMemoryStream.WriteStream(aDirStream);
+
+    VBACompression aCompression(aCompressedStream, aMemoryStream);
+    aCompression.write();
 }
 
 css::uno::Reference<css::container::XNameContainer> VbaExport::getBasicLibrary()
commit e2dd215f404ea05153f5366c34acc4ecd026432b
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat Aug 15 01:22:34 2015 +0200

    add first vba compression test
    
    Change-Id: I9e3abebb0ac932b46f7fc96cd37d39023b783af2

diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx
index 146bb88..3217e1b 100644
--- a/include/oox/ole/vbaexport.hxx
+++ b/include/oox/ole/vbaexport.hxx
@@ -90,7 +90,7 @@ private:
     sal_uInt16 handleHeader(bool bCompressed);
 };
 
-class VBACompression
+class OOX_DLLPUBLIC VBACompression
 {
 public:
     VBACompression(SvStream& rCompressedStream,
diff --git a/oox/Module_oox.mk b/oox/Module_oox.mk
index 361054d..1c8edf0 100644
--- a/oox/Module_oox.mk
+++ b/oox/Module_oox.mk
@@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets,oox,\
 
 $(eval $(call gb_Module_add_check_targets,oox,\
 	CppunitTest_oox_tokenmap \
+	CppunitTest_oox_vba_compression \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/oox/qa/unit/data/vba/reference/simple1.bin b/oox/qa/unit/data/vba/reference/simple1.bin
new file mode 100644
index 0000000..bd55e2e
Binary files /dev/null and b/oox/qa/unit/data/vba/reference/simple1.bin differ
diff --git a/oox/qa/unit/data/vba/simple1.bin b/oox/qa/unit/data/vba/simple1.bin
new file mode 100644
index 0000000..61dbbeb
--- /dev/null
+++ b/oox/qa/unit/data/vba/simple1.bin
@@ -0,0 +1 @@
+00000000:0001 0203 0405 0607 0809 1011 1213       .
diff --git a/oox/qa/unit/vba_compression.cxx b/oox/qa/unit/vba_compression.cxx
new file mode 100644
index 0000000..b526a3c
--- /dev/null
+++ b/oox/qa/unit/vba_compression.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+
+#include <oox/ole/vbaexport.hxx>
+
+class TestVbaCompression : public test::BootstrapFixtureBase
+{
+public:
+
+    void testSimple1();
+
+    // avoid the BootstrapFixtureBase::setUp and tearDown
+    virtual void setUp() SAL_OVERRIDE;
+    virtual void tearDown() SAL_OVERRIDE;
+
+    CPPUNIT_TEST_SUITE(TestVbaCompression);
+    CPPUNIT_TEST(testSimple1);
+    CPPUNIT_TEST_SUITE_END();
+
+private:
+};
+
+void TestVbaCompression::testSimple1()
+{
+    OUString aTestFile = getPathFromSrc("/oox/qa/unit/data/vba/simple1.bin");
+    OUString aReference = getPathFromSrc("/oox/qa/unit/data/vba/reference/simple1.bin");
+
+    SvFileStream aInputStream(aTestFile, StreamMode::READ);
+    SvMemoryStream aInputMemoryStream(4096, 4096);
+    aInputMemoryStream.WriteStream(aInputStream);
+
+    SvMemoryStream aOutputMemoryStream(4096, 4096);
+    VBACompression aCompression(aOutputMemoryStream, aInputMemoryStream);
+    aCompression.write();
+
+    SvFileStream aReferenceStream(aReference, StreamMode::READ);
+    SvMemoryStream aReferenceMemoryStream(4096, 4096);
+    aReferenceMemoryStream.WriteStream(aReferenceStream);
+
+    aOutputMemoryStream.Seek(0);
+    SvFileStream aDebugStream("/tmp/vba_debug.bin", StreamMode::WRITE);
+    aDebugStream.WriteStream(aOutputMemoryStream);
+
+    // CPPUNIT_ASSERT_EQUAL(aReferenceMemoryStream.GetSize(), aOutputMemoryStream.GetSize());
+
+    const sal_uInt8* pReferenceData = (const sal_uInt8*) aReferenceMemoryStream.GetData();
+    const sal_uInt8* pData = (const sal_uInt8*)aOutputMemoryStream.GetData();
+
+    size_t nSize = std::min(aReferenceMemoryStream.GetSize(),
+            aOutputMemoryStream.GetSize());
+    for (size_t i = 0; i < nSize; ++i)
+    {
+        CPPUNIT_ASSERT_EQUAL((int)pReferenceData[i], (int)pData[i]);
+    }
+}
+
+void TestVbaCompression::setUp()
+{
+}
+
+void TestVbaCompression::tearDown()
+{
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TestVbaCompression);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f01f290942fd627bdb909c08c7b6a8565c5c03ed
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sat Aug 15 01:20:43 2015 +0200

    fix my horrible chunk header code
    
    Change-Id: Ic91c06dbe05180d97b0db5de497f26f14b2d4ec4

diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx
index 6993fe5..146bb88 100644
--- a/include/oox/ole/vbaexport.hxx
+++ b/include/oox/ole/vbaexport.hxx
@@ -66,9 +66,6 @@ private:
     // DecompressedEnd according to the spec
     sal_uInt64 mnDecompressedEnd;
 
-    // Start of the current decompressed chunk
-    sal_uInt64 mnChunkStart;
-
     void PackCompressedChunkSize(size_t nSize, sal_uInt16& rHeader);
 
     void PackCompressedChunkFlag(bool bCompressed, sal_uInt16& rHeader);
@@ -89,6 +86,8 @@ private:
             sal_uInt16& rBitCount, sal_uInt16& rMaximumLength);
 
     void writeRawChunk();
+
+    sal_uInt16 handleHeader(bool bCompressed);
 };
 
 class VBACompression
diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx
index ea364bc..723824b 100644
--- a/oox/source/ole/vbaexport.cxx
+++ b/oox/source/ole/vbaexport.cxx
@@ -55,13 +55,27 @@ VBACompressionChunk::VBACompressionChunk(SvStream& rCompressedStream, const sal_
 {
 }
 
+void setUInt16(sal_uInt8* pBuffer, size_t nPos, sal_uInt16 nVal)
+{
+    pBuffer[nPos] = nVal & 0xFF;
+    pBuffer[nPos+1] = (nVal & 0xFF00) >> 8;
+}
+
+sal_uInt16 VBACompressionChunk::handleHeader(bool bCompressed)
+{
+    // handle header bytes
+    size_t nSize = mnCompressedCurrent;
+    sal_uInt16 nHeader = 0;
+    PackCompressedChunkSize(nSize, nHeader);
+    PackCompressedChunkFlag(bCompressed, nHeader);
+    PackCompressedChunkSignature(nHeader);
+
+    return nHeader;
+}
+
 // section 2.4.1.3.7
 void VBACompressionChunk::write()
 {
-    mnChunkStart = mrCompressedStream.Tell();
-
-    // we need to fill these two bytes later
-    mrCompressedStream.WriteUInt16(0x0);
 
     mnDecompressedCurrent = 0;
     mnCompressedCurrent = 2;
@@ -80,30 +94,22 @@ void VBACompressionChunk::write()
         compressTokenSequence();
     }
 
-    bool bCompressedFlag = true;
     if (mnDecompressedCurrent < mnDecompressedEnd)
     {
+        sal_uInt64 nChunkStart = mrCompressedStream.Tell();
+        mrCompressedStream.WriteUInt16(0);
         writeRawChunk();
-        bCompressedFlag = false;
+        mrCompressedStream.Seek(nChunkStart);
+        sal_uInt16 nHeader = handleHeader(false);
+        mrCompressedStream.WriteUInt16(nHeader);
     }
     else
     {
+        sal_uInt16 nHeader = handleHeader(true);
+        setUInt16(pCompressedChunkStream, 0, nHeader);
         // copy the compressed stream to our output stream
         mrCompressedStream.Write(pCompressedChunkStream, mnCompressedCurrent);
     }
-
-    // handle header bytes
-    size_t nSize = mnCompressedCurrent;
-    sal_uInt16 nHeader = 0;
-    PackCompressedChunkSize(nSize, nHeader);
-    PackCompressedChunkFlag(bCompressedFlag, nHeader);
-    PackCompressedChunkSignature(nHeader);
-
-    // overwrite the two bytes
-    sal_uInt64 nEnd = mrCompressedStream.Tell();
-    mrCompressedStream.Seek(mnChunkStart);
-    mrCompressedStream.WriteUInt16(nHeader);
-    mrCompressedStream.Seek(nEnd);
 }
 
 // section 2.4.1.3.13
@@ -146,12 +152,6 @@ void VBACompressionChunk::compressTokenSequence()
     mpCompressedChunkStream[nFlagByteIndex] = nFlagByte;
 }
 
-void setUInt16(sal_uInt8* pBuffer, size_t nPos, sal_uInt16 nVal)
-{
-    pBuffer[nPos] = nVal & 0xFFFF;
-    pBuffer[nPos+1] = (nVal & 0xFFFF0000) >> 8;
-}
-
 // section 2.4.1.3.9
 void VBACompressionChunk::compressToken(size_t index, sal_uInt8& nFlagByte)
 {
commit 1e09c94faacc9746fbfd4a8b9ce01c88aab8a71f
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri Aug 14 23:48:49 2015 +0200

    also write the chunks to the compressed stream
    
    Change-Id: I4b079f0f5b83379e1c8c7c7d99a16b794ab36c11

diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx
index 904fbf9..ea364bc 100644
--- a/oox/source/ole/vbaexport.cxx
+++ b/oox/source/ole/vbaexport.cxx
@@ -297,6 +297,7 @@ void VBACompression::write()
     {
         sal_Size nChunkSize = nRemainingSize > 4096 ? 4096 : nRemainingSize;
         VBACompressionChunk aChunk(mrCompressedStream, &pData[nSize - nRemainingSize], nChunkSize);
+        aChunk.write();
 
         // update the uncompressed chunk start marker
         nRemainingSize -= nChunkSize;
commit 31757a223937007220615d2f4f2d41c029d9bb9a
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri Aug 14 23:47:28 2015 +0200

    extract compression methods to make them testable
    
    Change-Id: I2ad28134ef723872b9940c02657ee89758efa06f

diff --git a/include/oox/ole/vbaexport.hxx b/include/oox/ole/vbaexport.hxx
index 88a0561..6993fe5 100644
--- a/include/oox/ole/vbaexport.hxx
+++ b/include/oox/ole/vbaexport.hxx
@@ -11,6 +11,9 @@
 #define __INCLUDED_INCLUDE_OOX_OLE_VBAEXPORT_HXX__
 
 #include <com/sun/star/uno/XInterface.hpp>
+
+#include <tools/stream.hxx>
+
 #include <oox/dllapi.h>
 
 namespace com { namespace sun { namespace star {
@@ -35,6 +38,72 @@ private:
     OUString maProjectName;
 };
 
+class VBACompressionChunk
+{
+public:
+
+    VBACompressionChunk(SvStream& rCompressedStream, const sal_uInt8* pData, sal_Size nChunkSize);
+
+    void write();
+
+private:
+    SvStream& mrCompressedStream;
+    const sal_uInt8* mpUncompressedData;
+    sal_uInt8* mpCompressedChunkStream;
+
+    // same as DecompressedChunkEnd in the spec
+    sal_Size mnChunkSize;
+
+    // CompressedCurrent according to the spec
+    sal_uInt64 mnCompressedCurrent;
+
+    // CompressedEnd according to the spec
+    sal_uInt64 mnCompressedEnd;
+
+    // DecompressedCurrent according to the spec
+    sal_uInt64 mnDecompressedCurrent;
+
+    // DecompressedEnd according to the spec
+    sal_uInt64 mnDecompressedEnd;
+
+    // Start of the current decompressed chunk
+    sal_uInt64 mnChunkStart;
+
+    void PackCompressedChunkSize(size_t nSize, sal_uInt16& rHeader);
+
+    void PackCompressedChunkFlag(bool bCompressed, sal_uInt16& rHeader);
+
+    void PackCompressedChunkSignature(sal_uInt16& rHeader);
+
+    void compressTokenSequence();
+
+    void compressToken(size_t index, sal_uInt8& nFlagByte);
+
+    void SetFlagBit(size_t index, bool bVal, sal_uInt8& rFlag);
+
+    sal_uInt16 CopyToken(size_t nLength, size_t nOffset);
+
+    void match(size_t& rLength, size_t& rOffset);
+
+    void CopyTokenHelp(sal_uInt16& rLengthMask, sal_uInt16& rOffsetMask,
+            sal_uInt16& rBitCount, sal_uInt16& rMaximumLength);
+
+    void writeRawChunk();
+};
+
+class VBACompression
+{
+public:
+    VBACompression(SvStream& rCompressedStream,
+            SvMemoryStream& rUncompressedStream);
+
+    void write();
+
+private:
+    SvStream& mrCompressedStream;
+    SvMemoryStream& mrUncompressedStream;
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx
index 9d6d52a..904fbf9 100644
--- a/oox/source/ole/vbaexport.cxx
+++ b/oox/source/ole/vbaexport.cxx
@@ -46,58 +46,7 @@ void exportUTF16String(SvStream& rStrm, const OUString& rString)
     }
 }
 
-class VBACompressionChunk
-{
-public:
-
-    VBACompressionChunk(SvStream& rCompressedStream, const sal_uInt8* pData, sal_Size nChunkSize);
-
-    void write();
-
-private:
-    SvStream& mrCompressedStream;
-    const sal_uInt8* mpUncompressedData;
-    sal_uInt8* mpCompressedChunkStream;
-
-    // same as DecompressedChunkEnd in the spec
-    sal_Size mnChunkSize;
-
-    // CompressedCurrent according to the spec
-    sal_uInt64 mnCompressedCurrent;
-
-    // CompressedEnd according to the spec
-    sal_uInt64 mnCompressedEnd;
-
-    // DecompressedCurrent according to the spec
-    sal_uInt64 mnDecompressedCurrent;
-
-    // DecompressedEnd according to the spec
-    sal_uInt64 mnDecompressedEnd;
-
-    // Start of the current decompressed chunk
-    sal_uInt64 mnChunkStart;
-
-    void PackCompressedChunkSize(size_t nSize, sal_uInt16& rHeader);
-
-    void PackCompressedChunkFlag(bool bCompressed, sal_uInt16& rHeader);
-
-    void PackCompressedChunkSignature(sal_uInt16& rHeader);
-
-    void compressTokenSequence();
-
-    void compressToken(size_t index, sal_uInt8& nFlagByte);
-
-    void SetFlagBit(size_t index, bool bVal, sal_uInt8& rFlag);
-
-    sal_uInt16 CopyToken(size_t nLength, size_t nOffset);
-
-    void match(size_t& rLength, size_t& rOffset);
-
-    void CopyTokenHelp(sal_uInt16& rLengthMask, sal_uInt16& rOffsetMask,
-            sal_uInt16& rBitCount, sal_uInt16& rMaximumLength);
-
-    void writeRawChunk();
-};
+}
 
 VBACompressionChunk::VBACompressionChunk(SvStream& rCompressedStream, const sal_uInt8* pData, sal_Size nChunkSize):
     mrCompressedStream(rCompressedStream),
@@ -328,19 +277,6 @@ void VBACompressionChunk::writeRawChunk()
     }
 }
 
-class VBACompression
-{
-public:
-    VBACompression(SvStream& rCompressedStream,
-            SvMemoryStream& rUncompressedStream);
-
-    void write();
-
-private:
-    SvStream& mrCompressedStream;
-    SvMemoryStream& mrUncompressedStream;
-};
-
 VBACompression::VBACompression(SvStream& rCompressedStream,
         SvMemoryStream& rUncompressedStream):
     mrCompressedStream(rCompressedStream),
@@ -368,8 +304,6 @@ void VBACompression::write()
     }
 }
 
-}
-
 VbaExport::VbaExport(css::uno::Reference<css::frame::XModel> xModel):
     mxModel(xModel)
 {
commit 8c53aa1fb0a056f724092268ce042f723a3368e0
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri Aug 14 21:30:36 2015 +0200

    fix small glitch
    
    Change-Id: I8c219db7aa3eb53c82232469e8334b6a47489cb2

diff --git a/oox/source/ole/vbaexport.cxx b/oox/source/ole/vbaexport.cxx
index 93c228f..9d6d52a 100644
--- a/oox/source/ole/vbaexport.cxx
+++ b/oox/source/ole/vbaexport.cxx
@@ -634,7 +634,7 @@ void writePROJECTMODULES(SvStream& rStrm)
     rStrm.WriteUInt16(count); // Count
     writePROJECTCOOKIE(rStrm);
     writePROJECTMODULE(rStrm, "Module1", "Module1", 0x00000379, "procedure");
-    writePROJECTMODULE(rStrm, "ThisWorkbook", "ThisWorkbook", 0x000004BD, "other");
+    writePROJECTMODULE(rStrm, "ThisWorkbook", "ThisWorkbook", 0x00000325, "other");
     writePROJECTMODULE(rStrm, "Sheet1", "Sheet1", 0x00000325, "other");
     writePROJECTMODULE(rStrm, "Sheet2", "Sheet2", 0x00000325, "other");
     writePROJECTMODULE(rStrm, "Sheet3", "Sheet3", 0x00000325, "other");


More information about the Libreoffice-commits mailing list