[Libreoffice-commits] core.git: 3 commits - sax/source sc/source

Michael Stahl mstahl at redhat.com
Wed Jun 5 07:58:18 PDT 2013


 sax/source/expatwrap/saxwriter.cxx  |   34 +++++++++++++++++++++++-
 sax/source/tools/fastserializer.cxx |   50 +++++++++++++++++++++++++++++++++++-
 sax/source/tools/fastserializer.hxx |    5 +++
 sc/source/filter/excel/xepage.cxx   |   17 +++++++++---
 sc/source/filter/excel/xerecord.cxx |   27 +++++++------------
 sc/source/filter/inc/xerecord.hxx   |   17 +++++-------
 sc/source/filter/inc/xestream.hxx   |    1 
 7 files changed, 118 insertions(+), 33 deletions(-)

New commits:
commit 830cc95abb7911f5f6f0ba8c71ef46f3ca8ef383
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Jun 5 16:50:50 2013 +0200

    sax: FastSaxSerializer: add well-formedness assertions
    
    In an --enable-dbgutil build, assert on the following XML
    well-formedness violations:
    
    * Element Type Match (-> start/end tag mismatch)
    * Unique Att Spec (-> duplicate attributes)
    
    Change-Id: I1d5c405b4316ba941be1db7df6cacf00b5837261

diff --git a/sax/source/tools/fastserializer.cxx b/sax/source/tools/fastserializer.cxx
index eba4548..a9b73ae 100644
--- a/sax/source/tools/fastserializer.cxx
+++ b/sax/source/tools/fastserializer.cxx
@@ -30,6 +30,7 @@
 
 #if OSL_DEBUG_LEVEL > 0
 #include <iostream>
+#include <set>
 #endif
 
 using ::comphelper::SequenceAsVector;
@@ -123,6 +124,25 @@ namespace sax_fastparser {
             writeBytes(mxFastTokenHandler->getUTF8Identifier(nElement));
     }
 
+#ifdef DBG_UTIL
+    OString SAL_CALL FastSaxSerializer::getId( ::sal_Int32 nElement )
+    {
+        if (HAS_NAMESPACE(nElement)) {
+            Sequence<sal_Int8> const ns(
+                mxFastTokenHandler->getUTF8Identifier(NAMESPACE(nElement)));
+            Sequence<sal_Int8> const name(
+                mxFastTokenHandler->getUTF8Identifier(TOKEN(nElement)));
+            return OString(reinterpret_cast<sal_Char const*>(ns.getConstArray()), ns.getLength())
+                 + OString(reinterpret_cast<sal_Char const*>(maColon.getConstArray()), maColon.getLength())
+                 + OString(reinterpret_cast<sal_Char const*>(name.getConstArray()), name.getLength());
+        } else {
+            Sequence<sal_Int8> const name(
+                mxFastTokenHandler->getUTF8Identifier(nElement));
+            return OString(reinterpret_cast<sal_Char const*>(name.getConstArray()), name.getLength());
+        }
+    }
+#endif
+
     void SAL_CALL FastSaxSerializer::startFastElement( ::sal_Int32 Element, const Reference< XFastAttributeList >& Attribs )
         throw (SAXException, RuntimeException)
     {
@@ -132,6 +152,10 @@ namespace sax_fastparser {
         if ( !maMarkStack.empty() )
             maMarkStack.top()->setCurrentElement( Element );
 
+#ifdef DBG_UTIL
+        m_DebugStartedElements.push(Element);
+#endif
+
         writeBytes(toUnoSequence(maOpeningBracket));
 
         writeId(Element);
@@ -146,6 +170,13 @@ namespace sax_fastparser {
         if (!mxOutputStream.is())
             return;
 
+#ifdef DBG_UTIL
+        assert(!m_DebugStartedElements.empty());
+        // Well-formedness constraint: Element Type Match
+        assert(Element == m_DebugStartedElements.top());
+        m_DebugStartedElements.pop();
+#endif
+
         writeBytes(toUnoSequence(maOpeningBracketAndSlash));
 
         writeId(Element);
@@ -193,6 +224,9 @@ namespace sax_fastparser {
     }
     void FastSaxSerializer::writeFastAttributeList( const Reference< XFastAttributeList >& Attribs )
     {
+#ifdef DBG_UTIL
+        ::std::set<OUString> DebugAttributes;
+#endif
         Sequence< Attribute > aAttrSeq = Attribs->getUnknownAttributes();
         const Attribute *pAttr = aAttrSeq.getConstArray();
         sal_Int32 nAttrLength = aAttrSeq.getLength();
@@ -200,7 +234,13 @@ namespace sax_fastparser {
         {
             writeBytes(toUnoSequence(maSpace));
 
-            write(pAttr[i].Name);
+            OUString const& rAttrName(pAttr[i].Name);
+#ifdef DBG_UTIL
+            // Well-formedness constraint: Unique Att Spec
+            assert(DebugAttributes.find(rAttrName) == DebugAttributes.end());
+            DebugAttributes.insert(rAttrName);
+#endif
+            write(rAttrName);
             writeBytes(toUnoSequence(maEqualSignAndQuote));
             write(escapeXml(pAttr[i].Value));
             writeBytes(toUnoSequence(maQuote));
@@ -216,6 +256,14 @@ namespace sax_fastparser {
             sal_Int32 nToken = pFastAttr[j].Token;
             writeId(nToken);
 
+#ifdef DBG_UTIL
+            // Well-formedness constraint: Unique Att Spec
+            OUString const name(OStringToOUString(getId(nToken),
+                                                  RTL_TEXTENCODING_UTF8));
+            assert(DebugAttributes.find(name) == DebugAttributes.end());
+            DebugAttributes.insert(name);
+#endif
+
             writeBytes(toUnoSequence(maEqualSignAndQuote));
 
             write(escapeXml(Attribs->getValue(pFastAttr[j].Token)));
diff --git a/sax/source/tools/fastserializer.hxx b/sax/source/tools/fastserializer.hxx
index 38c8e89..95ebb14 100644
--- a/sax/source/tools/fastserializer.hxx
+++ b/sax/source/tools/fastserializer.hxx
@@ -111,6 +111,7 @@ public:
 
     // C++ helpers
     void SAL_CALL writeId( ::sal_Int32 Element );
+    OString SAL_CALL getId( ::sal_Int32 Element );
 
     static OUString escapeXml( const OUString& s );
 
@@ -207,6 +208,10 @@ private:
     ::std::stack< boost::shared_ptr< ForMerge > > maMarkStack;
     ::std::stack< boost::shared_ptr< ForMerge > > maSavedMarkStack;
 
+#ifdef DBG_UTIL
+    ::std::stack<sal_Int32> m_DebugStartedElements;
+#endif
+
     void writeFastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs );
     void write( const OUString& s );
 
commit 96ee9884b78dce54223e83943a7c5c832ae78759
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Jun 5 16:48:37 2013 +0200

    sax: SaxWriter: add well-formedness assertions
    
    In an --enable-dbgutil build, assert on the following XML
    well-formedness violations:
    
    * Element Type Match (-> start/end tag mismatch)
    * Unique Att Spec (-> duplicate attributes)
    
    Change-Id: I1e32a9fd096463a418a197fcdb3174df79f7a785

diff --git a/sax/source/expatwrap/saxwriter.cxx b/sax/source/expatwrap/saxwriter.cxx
index 20660eb..f49b8c2 100644
--- a/sax/source/expatwrap/saxwriter.cxx
+++ b/sax/source/expatwrap/saxwriter.cxx
@@ -16,8 +16,12 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
+
 #include <string.h>
 
+#include <stack>
+#include <set>
+
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/util/XCloneable.hpp>
 #include <com/sun/star/xml/sax/XParser.hpp>
@@ -72,6 +76,12 @@ enum SaxInvalidCharacterError
 
 class SaxWriterHelper
 {
+#ifdef DBG_UTIL
+public:
+    ::std::stack<OUString> m_DebugStartedElements;
+#endif
+
+private:
     Reference< XOutputStream >  m_out;
     Sequence < sal_Int8 >       m_Sequence;
     sal_Int8*                   mp_Sequence;
@@ -80,7 +90,6 @@ class SaxWriterHelper
     sal_uInt32                  nCurrentPos;
     sal_Bool                    m_bStartElementFinished;
 
-
     inline sal_uInt32 writeSequence() throw( SAXException );
 
     // use only if to insert the bytes more space in the sequence is needed and
@@ -541,6 +550,12 @@ inline void SaxWriterHelper::startDocument() throw( SAXException )
 inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
 {
     FinishStartElement();
+
+#ifdef DBG_UTIL
+    m_DebugStartedElements.push(rName);
+    ::std::set<OUString> DebugAttributes;
+#endif
+
     mp_Sequence[nCurrentPos] = '<';
     nCurrentPos++;
     if (nCurrentPos == SEQUENCESIZE)
@@ -558,7 +573,13 @@ inline SaxInvalidCharacterError SaxWriterHelper::startElement(const OUString& rN
         if (nCurrentPos == SEQUENCESIZE)
             nCurrentPos = writeSequence();
 
-        if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False))
+        OUString const& rAttrName(xAttribs->getNameByIndex(i));
+#ifdef DBG_UTIL
+        // Well-formedness constraint: Unique Att Spec
+        assert(DebugAttributes.find(rAttrName) == DebugAttributes.end());
+        DebugAttributes.insert(rAttrName);
+#endif
+        if (!writeString(rAttrName, sal_False, sal_False))
             eRet = SAX_ERROR;
 
         mp_Sequence[nCurrentPos] = '=';
@@ -608,6 +629,7 @@ inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
 inline sal_Bool SaxWriterHelper::endElement(const OUString& rName) throw( SAXException )
 {
     FinishStartElement();
+
     mp_Sequence[nCurrentPos] = '<';
     nCurrentPos++;
     if (nCurrentPos == SEQUENCESIZE)
@@ -1160,6 +1182,14 @@ void SAXWriter::endElement(const OUString& aName)   throw (SAXException, Runtime
     }
     sal_Bool bRet(sal_True);
 
+    // check here because Helper's endElement is not always called
+#ifdef DBG_UTIL
+    assert(!mp_SaxWriterHelper->m_DebugStartedElements.empty());
+    // Well-formedness constraint: Element Type Match
+    assert(aName == mp_SaxWriterHelper->m_DebugStartedElements.top());
+    mp_SaxWriterHelper->m_DebugStartedElements.pop();
+#endif
+
     if( mp_SaxWriterHelper->FinishEmptyElement() )
         m_bForceLineBreak = sal_False;
     else
commit 350534aba8f82d57782ec22fa4f6b776509beb2d
Author: Michael Stahl <mstahl at redhat.com>
Date:   Wed Jun 5 16:44:26 2013 +0200

    sc: XLSX export: remove mpAttributes crack:
    
    When there are attributes, XclExpXmlStartElementRecord::SaveXml() would
    not call startElement() but instead write the XML element all by itself,
    which means there will be an endElement() for which no previous
    startElement() was called, which makes checking that these match hard.
    
    Since this silly mpAttributes over-engineering is only used in one place
    anyway, give that a separate subclass and use startElement().
    
    There is still an issue with various WriteAttribute methods; if those
    are used it's probably not possible to check that for well-formedness.
    
    Change-Id: Id842f000a6fecd77211836705545d58031ebd0f8

diff --git a/sc/source/filter/excel/xepage.cxx b/sc/source/filter/excel/xepage.cxx
index 8e1ffb1..3701887 100644
--- a/sc/source/filter/excel/xepage.cxx
+++ b/sc/source/filter/excel/xepage.cxx
@@ -332,17 +332,26 @@ XclExpPageSettings::XclExpPageSettings( const XclExpRoot& rRoot ) :
         maData.maVerPageBreaks.push_back(*itr);
 }
 
-static void lcl_WriteHeaderFooter( XclExpXmlStream& rStrm )
+class XclExpXmlStartHeaderFooterElementRecord : public XclExpXmlElementRecord
+{
+public:
+    explicit XclExpXmlStartHeaderFooterElementRecord(sal_Int32 const nElement)
+         : XclExpXmlElementRecord(nElement) {}
+
+    virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+};
+
+void XclExpXmlStartHeaderFooterElementRecord::SaveXml(XclExpXmlStream& rStrm)
 {
     // OOXTODO: we currently only emit oddHeader/oddFooter elements, and
     //          do not support the first/even/odd page distinction.
-    rStrm.WriteAttributes(
+    sax_fastparser::FSHelperPtr& rStream = rStrm.GetCurrentStream();
+    rStream->startElement( mnElement,
             // OOXTODO: XML_alignWithMargins,
             XML_differentFirst,     "false",    // OOXTODO
             XML_differentOddEven,   "false",    // OOXTODO
             // OOXTODO: XML_scaleWithDoc
             FSEND );
-    rStrm.GetCurrentStream()->write( ">" );
 }
 
 void XclExpPageSettings::Save( XclExpStream& rStrm )
@@ -388,7 +397,7 @@ void XclExpPageSettings::SaveXml( XclExpXmlStream& rStrm )
 
     XclExpSetup( maData ).SaveXml( rStrm );
 
-    XclExpXmlStartElementRecord( XML_headerFooter, lcl_WriteHeaderFooter ).SaveXml( rStrm );
+    XclExpXmlStartHeaderFooterElementRecord(XML_headerFooter).SaveXml(rStrm);
     XclExpHeaderFooter( EXC_ID_HEADER, maData.maHeader ).SaveXml( rStrm );
     XclExpHeaderFooter( EXC_ID_FOOTER, maData.maFooter ).SaveXml( rStrm );
     XclExpXmlEndElementRecord( XML_headerFooter ).SaveXml( rStrm );
diff --git a/sc/source/filter/excel/xerecord.cxx b/sc/source/filter/excel/xerecord.cxx
index b7f2f8e..4c1c5e0 100644
--- a/sc/source/filter/excel/xerecord.cxx
+++ b/sc/source/filter/excel/xerecord.cxx
@@ -57,8 +57,8 @@ void XclExpDelegatingRecord::SaveXml( XclExpXmlStream& rStrm )
 
 // ----------------------------------------------------------------------------
 
-XclExpXmlElementRecord::XclExpXmlElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) )
-    : mnElement( nElement ), mpAttributes( pAttributes )
+XclExpXmlElementRecord::XclExpXmlElementRecord(sal_Int32 const nElement)
+    : mnElement( nElement )
 {
 }
 
@@ -68,8 +68,8 @@ XclExpXmlElementRecord::~XclExpXmlElementRecord()
 
 // ----------------------------------------------------------------------------
 
-XclExpXmlStartElementRecord::XclExpXmlStartElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) )
-    : XclExpXmlElementRecord( nElement, pAttributes )
+XclExpXmlStartElementRecord::XclExpXmlStartElementRecord(sal_Int32 const nElement)
+    : XclExpXmlElementRecord(nElement)
 {
 }
 
@@ -80,15 +80,9 @@ XclExpXmlStartElementRecord::~XclExpXmlStartElementRecord()
 void XclExpXmlStartElementRecord::SaveXml( XclExpXmlStream& rStrm )
 {
     sax_fastparser::FSHelperPtr& rStream = rStrm.GetCurrentStream();
-    if( ! mpAttributes )
-    {
-        rStream->startElement( mnElement, FSEND );
-    }
-    else
-    {
-        rStream->write( "<" )->writeId( mnElement );
-        (*mpAttributes)( rStrm );
-    }
+    // TODO: no generic way to add attributes here, but it appears to
+    // not be needed yet
+    rStream->startElement( mnElement, FSEND );
 }
 
 // ----------------------------------------------------------------------------
@@ -109,8 +103,9 @@ void XclExpXmlEndElementRecord::SaveXml( XclExpXmlStream& rStrm )
 
 // ----------------------------------------------------------------------------
 
-XclExpXmlStartSingleElementRecord::XclExpXmlStartSingleElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) )
-    : XclExpXmlElementRecord( nElement, pAttributes )
+XclExpXmlStartSingleElementRecord::XclExpXmlStartSingleElementRecord(
+            sal_Int32 const nElement)
+    : XclExpXmlElementRecord( nElement )
 {
 }
 
@@ -122,8 +117,6 @@ void XclExpXmlStartSingleElementRecord::SaveXml( XclExpXmlStream& rStrm )
 {
     sax_fastparser::FSHelperPtr& rStream = rStrm.GetCurrentStream();
     rStream->write( "<" )->writeId( mnElement );
-    if( mpAttributes )
-        (*mpAttributes)( rStrm );
 }
 
 // ----------------------------------------------------------------------------
diff --git a/sc/source/filter/inc/xerecord.hxx b/sc/source/filter/inc/xerecord.hxx
index 27f272e..78241e8 100644
--- a/sc/source/filter/inc/xerecord.hxx
+++ b/sc/source/filter/inc/xerecord.hxx
@@ -61,12 +61,11 @@ private:
 class XclExpXmlElementRecord : public XclExpRecordBase
 {
 public:
-                        XclExpXmlElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) = NULL );
+    explicit            XclExpXmlElementRecord(sal_Int32 nElement);
     virtual             ~XclExpXmlElementRecord();
 
 protected:
     sal_Int32           mnElement;
-    void                (*mpAttributes)( XclExpXmlStream& rStrm );
 };
 
 // ----------------------------------------------------------------------------
@@ -74,11 +73,11 @@ protected:
 class XclExpXmlStartElementRecord : public XclExpXmlElementRecord
 {
 public:
-                        XclExpXmlStartElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) = NULL );
+    explicit            XclExpXmlStartElementRecord(sal_Int32 nElement);
     virtual             ~XclExpXmlStartElementRecord();
 
     /** Starts the element nElement */
-    virtual void        SaveXml( XclExpXmlStream& rStrm );
+    virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
 // ----------------------------------------------------------------------------
@@ -86,11 +85,11 @@ public:
 class XclExpXmlEndElementRecord : public XclExpXmlElementRecord
 {
 public:
-                        XclExpXmlEndElementRecord( sal_Int32 nElement );
+    explicit            XclExpXmlEndElementRecord(sal_Int32 nElement);
     virtual             ~XclExpXmlEndElementRecord();
 
     /** Ends the element nElement */
-    virtual void        SaveXml( XclExpXmlStream& rStrm );
+    virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
 // ----------------------------------------------------------------------------
@@ -98,11 +97,11 @@ public:
 class XclExpXmlStartSingleElementRecord : public XclExpXmlElementRecord
 {
 public:
-                        XclExpXmlStartSingleElementRecord( sal_Int32 nElement, void (*pAttributes)( XclExpXmlStream& rStrm) = NULL );
+    explicit            XclExpXmlStartSingleElementRecord(sal_Int32 nElement);
     virtual             ~XclExpXmlStartSingleElementRecord();
 
     /** Starts the single element nElement */
-    virtual void        SaveXml( XclExpXmlStream& rStrm );
+    virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
 // ----------------------------------------------------------------------------
@@ -114,7 +113,7 @@ public:
     virtual             ~XclExpXmlEndSingleElementRecord();
 
     /** Ends the single element nElement */
-    virtual void        SaveXml( XclExpXmlStream& rStrm );
+    virtual void        SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 0ac31d4..4b37a68 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -313,6 +313,7 @@ public:
 
     sax_fastparser::FSHelperPtr     GetStreamForPath( const OUString& rPath );
 
+    // FIXME: if written through this cannot be checked for well-formedness
     sax_fastparser::FSHelperPtr&    WriteAttributes( sal_Int32 nAttribute, const char* value, FSEND_t )
         { return WriteAttributesInternal( nAttribute, value, FSEND_internal ); }
     sax_fastparser::FSHelperPtr&    WriteAttributes( sal_Int32 nAttribute, const OString& value, FSEND_t )


More information about the Libreoffice-commits mailing list