[Libreoffice-commits] core.git: Branch 'libreoffice-4-2' - 15 commits - include/oox include/sax oox/Library_oox.mk oox/source sax/Library_fastsax.mk sax/source writerfilter/Library_writerfilter.mk writerfilter/source

Kohei Yoshida kohei.yoshida at collabora.com
Wed Dec 4 08:40:23 PST 2013


 include/oox/core/fastparser.hxx                     |   12 
 include/oox/core/fasttokenhandler.hxx               |    7 
 include/oox/core/xmlfilterbase.hxx                  |    2 
 include/oox/token/tokenmap.hxx                      |   22 
 include/sax/fastattribs.hxx                         |   15 
 include/sax/fastparser.hxx                          |   80 ++
 include/sax/fastsaxdllapi.h                         |   33 +
 oox/Library_oox.mk                                  |    1 
 oox/source/core/fastparser.cxx                      |   17 
 oox/source/core/fasttokenhandler.cxx                |    5 
 oox/source/core/fragmenthandler2.cxx                |    6 
 oox/source/core/xmlfilterbase.cxx                   |    5 
 oox/source/helper/attributelist.cxx                 |   13 
 oox/source/token/tokenmap.cxx                       |   12 
 sax/Library_fastsax.mk                              |    5 
 sax/source/fastparser/facreg.cxx                    |   81 --
 sax/source/fastparser/fastparser.cxx                |  584 ++++++++++++++++----
 sax/source/fastparser/fastparser.hxx                |  232 -------
 sax/source/tools/fastattribs.cxx                    |   39 -
 writerfilter/Library_writerfilter.mk                |    1 
 writerfilter/source/ooxml/OOXMLFastTokenHandler.cxx |   23 
 writerfilter/source/ooxml/OOXMLFastTokenHandler.hxx |    7 
 22 files changed, 736 insertions(+), 466 deletions(-)

New commits:
commit 0e209b7a7bbd234d77f617e70cc4971d4f0dbb41
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Dec 4 11:41:15 2013 -0500

    Get it to build.
    
    Change-Id: Ib1cb82d46322bd7c6791fa9a8937492ef27ec370

diff --git a/include/sax/fastattribs.hxx b/include/sax/fastattribs.hxx
index bb1b93d..f59188d 100644
--- a/include/sax/fastattribs.hxx
+++ b/include/sax/fastattribs.hxx
@@ -52,9 +52,10 @@ typedef std::vector< UnknownAttribute > UnknownAttributeList;
 /// A native C++ interface to tokenisation
 class SAX_DLLPUBLIC FastTokenHandlerBase
 {
-    public:
-        virtual ~FastTokenHandlerBase();
-        virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const = 0;
+public:
+    FastTokenHandlerBase();
+    virtual ~FastTokenHandlerBase();
+    virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const = 0;
 };
 
 /// avoid constantly allocating and freeing sequences.
diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx
index 595c736..ed50505 100644
--- a/sax/source/tools/fastattribs.cxx
+++ b/sax/source/tools/fastattribs.cxx
@@ -32,6 +32,10 @@ FastTokenHandlerBase::FastTokenHandlerBase()
 {
 }
 
+FastTokenHandlerBase::~FastTokenHandlerBase()
+{
+}
+
 UnknownAttribute::UnknownAttribute( const OUString& rNamespaceURL, const OString& rName, const sal_Char* pValue )
     : maNamespaceURL( rNamespaceURL ), maName( rName ), maValue( pValue )
 {
diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk
index b9b2932..ea20556 100644
--- a/writerfilter/Library_writerfilter.mk
+++ b/writerfilter/Library_writerfilter.mk
@@ -60,6 +60,7 @@ $(eval $(call gb_Library_use_libraries,writerfilter,\
     msfilter \
     oox \
     sal \
+    sax \
     sfx \
     sot \
     svt \
commit 8de38bfe0d5cf6300601a2e53c6d5a1ed783422f
Author: Michael Stahl <mstahl at redhat.com>
Date:   Tue Dec 3 13:16:24 2013 +0100

    sax: stop using SAX_DLLIMPLEMENTATION for both sax and fastsax
    
    Change-Id: I243ec20015beec6b98ee0af55eb7c387008f32f1

diff --git a/include/sax/fastparser.hxx b/include/sax/fastparser.hxx
index 578b114..afd5add 100644
--- a/include/sax/fastparser.hxx
+++ b/include/sax/fastparser.hxx
@@ -24,7 +24,7 @@
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <cppuhelper/implbase2.hxx>
 
-#include "saxdllapi.h"
+#include <sax/fastsaxdllapi.h>
 
 namespace com { namespace sun { namespace star { namespace xml { namespace sax {
 
@@ -41,7 +41,10 @@ namespace sax_fastparser {
 class FastSaxParserImpl;
 
 // This class implements the external Parser interface
-class SAX_DLLPUBLIC FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastParser, ::com::sun::star::lang::XServiceInfo >
+class FASTSAX_DLLPUBLIC FastSaxParser
+    : public ::cppu::WeakImplHelper2<
+                ::com::sun::star::xml::sax::XFastParser,
+                ::com::sun::star::lang::XServiceInfo >
 {
     FastSaxParserImpl* mpImpl;
 
diff --git a/include/sax/fastsaxdllapi.h b/include/sax/fastsaxdllapi.h
new file mode 100644
index 0000000..e532dd2
--- /dev/null
+++ b/include/sax/fastsaxdllapi.h
@@ -0,0 +1,33 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAX_FASTSAXDLLAPI_H
+#define INCLUDED_SAX_FASTSAXDLLAPI_H
+
+#include <sal/types.h>
+
+#if defined FASTSAX_DLLIMPLEMENTATION
+#define FASTSAX_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define FASTSAX_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sax/Library_fastsax.mk b/sax/Library_fastsax.mk
index 4f98820..1fcb503 100644
--- a/sax/Library_fastsax.mk
+++ b/sax/Library_fastsax.mk
@@ -17,7 +17,7 @@ $(eval $(call gb_Library_set_include,fastsax,\
 ))
 
 $(eval $(call gb_Library_add_defs,fastsax,\
-    -DSAX_DLLIMPLEMENTATION \
+    -DFASTSAX_DLLIMPLEMENTATION \
 ))
 
 $(eval $(call gb_Library_use_sdk_api,fastsax))
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 3bff430..4f835d5 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -83,7 +83,7 @@ struct Event
     CallbackType maType;
 };
 
-struct SAX_DLLPUBLIC NameWithToken
+struct NameWithToken
 {
     OUString msName;
     sal_Int32 mnToken;
commit 27d32776940db1845b26bc84d582ef24b81a7026
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Dec 3 05:56:47 2013 +0100

    we need to pass the variable to get correct dll linkage
    
    Change-Id: I447218101e1791375273580a313dd54708303d7a

diff --git a/sax/Library_fastsax.mk b/sax/Library_fastsax.mk
index 863336f..4f98820 100644
--- a/sax/Library_fastsax.mk
+++ b/sax/Library_fastsax.mk
@@ -16,6 +16,10 @@ $(eval $(call gb_Library_set_include,fastsax,\
     $$(INCLUDE) \
 ))
 
+$(eval $(call gb_Library_add_defs,fastsax,\
+    -DSAX_DLLIMPLEMENTATION \
+))
+
 $(eval $(call gb_Library_use_sdk_api,fastsax))
 
 $(eval $(call gb_Library_use_externals,fastsax,\
commit 56ea41af88e3538ed256c20464c8b2fef15c376a
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Dec 3 05:38:59 2013 +0100

    no inheritance so no virtual needed
    
    Change-Id: Ia6c481bbf5353db4c2801a53ae1455534c6978bd

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 2746164..3bff430 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -194,25 +194,25 @@ class FastSaxParserImpl
 {
 public:
     FastSaxParserImpl( FastSaxParser* pFront );
-    virtual ~FastSaxParserImpl();
+    ~FastSaxParserImpl();
 
     // The implementation details
     static ::com::sun::star::uno::Sequence< OUString > getSupportedServiceNames_Static(void);
 
     // XFastParser
-    void SAL_CALL parseStream( const ::com::sun::star::xml::sax::InputSource& aInputSource ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
-    void SAL_CALL setFastDocumentHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
-    void SAL_CALL setTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
-    void SAL_CALL registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
-    OUString SAL_CALL getNamespaceURL( const OUString& rPrefix ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
-    void SAL_CALL setErrorHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
-    void SAL_CALL setEntityResolver( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >& Resolver ) throw (::com::sun::star::uno::RuntimeException);
-    void SAL_CALL setLocale( const ::com::sun::star::lang::Locale& rLocale ) throw (::com::sun::star::uno::RuntimeException);
+    void parseStream( const ::com::sun::star::xml::sax::InputSource& aInputSource ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+    void setFastDocumentHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void setTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+    OUString getNamespaceURL( const OUString& rPrefix ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+    void setErrorHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void setEntityResolver( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >& Resolver ) throw (::com::sun::star::uno::RuntimeException);
+    void setLocale( const ::com::sun::star::lang::Locale& rLocale ) throw (::com::sun::star::uno::RuntimeException);
 
     // XServiceInfo
-    virtual OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
-    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
-    virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);
+    OUString getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
+    sal_Bool supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+    ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);
 
     // called by the C callbacks of the expat parser
     void callbackStartElement( const XML_Char* name, const XML_Char** atts );
@@ -824,13 +824,13 @@ void FastSaxParserImpl::setFastDocumentHandler( const Reference< XFastDocumentHa
     maData.mxDocumentHandler = Handler;
 }
 
-void SAL_CALL FastSaxParserImpl::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
+void FastSaxParserImpl::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
 {
     maData.mxTokenHandler = xHandler;
     maData.mpTokenHandler = dynamic_cast< FastTokenHandlerBase *>( xHandler.get() );
 }
 
-void SAL_CALL FastSaxParserImpl::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
+void FastSaxParserImpl::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
 {
     if( NamespaceToken >= FastToken::NAMESPACE )
     {
@@ -843,7 +843,7 @@ void SAL_CALL FastSaxParserImpl::registerNamespace( const OUString& NamespaceURL
     throw IllegalArgumentException();
 }
 
-OUString SAL_CALL FastSaxParserImpl::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
+OUString FastSaxParserImpl::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
 {
     try
     {
commit e3882d242f98072e90499ae5b929f9408f7c65fe
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Dec 2 23:02:05 2013 -0500

    Hide the implementation.
    
    Change-Id: Ibfd9bf626a40c3ec4eb18d09944e8943163595c8

diff --git a/include/sax/fastparser.hxx b/include/sax/fastparser.hxx
index 217893c..578b114 100644
--- a/include/sax/fastparser.hxx
+++ b/include/sax/fastparser.hxx
@@ -20,91 +20,31 @@
 #ifndef INCLUDED_SAX_FASTPARSER_HXX
 #define INCLUDED_SAX_FASTPARSER_HXX
 
-#include <queue>
-#include <vector>
-#include <stack>
-#include <boost/optional.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/unordered_map.hpp>
-#include <osl/conditn.hxx>
-#include <rtl/ref.hxx>
-#include <com/sun/star/xml/sax/XFastContextHandler.hpp>
-#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
 #include <com/sun/star/xml/sax/XFastParser.hpp>
-#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <cppuhelper/implbase2.hxx>
 
-#include <expat.h>
 #include "saxdllapi.h"
 
-#include <sax/fastattribs.hxx>
+namespace com { namespace sun { namespace star { namespace xml { namespace sax {
 
-namespace sax_fastparser {
-
-struct Event;
-class FastLocatorImpl;
-struct NamespaceDefine;
-struct Entity;
-
-typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
-
-typedef ::boost::unordered_map< OUString, sal_Int32,
-        OUStringHash, ::std::equal_to< OUString > > NamespaceMap;
-
-struct SAX_DLLPUBLIC NameWithToken
-{
-    OUString msName;
-    sal_Int32 mnToken;
-
-    NameWithToken(const OUString& sName, const sal_Int32& nToken);
-};
+class XFastContextHandler;
+class XFastDocumentHandler;
+class XFastTokenHandler;
 
-typedef std::vector<Event> EventList;
+}}}}}
 
-enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION };
-
-struct Event
-{
-    OUString msChars;
-    sal_Int32 mnElementToken;
-    OUString msNamespace;
-    OUString msElementName;
-    rtl::Reference< FastAttributeList > mxAttributes;
-    CallbackType maType;
-};
-
-// --------------------------------------------------------------------
-
-struct SaxContext
-{
-    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > mxContext;
-    sal_Int32                   mnElementToken;
-    boost::optional< OUString > maNamespace;
-    boost::optional< OUString > maElementName;
-    SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName );
-};
+namespace sax_fastparser {
 
 // --------------------------------------------------------------------
 
-struct SAX_DLLPUBLIC ParserData
-{
-    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
-    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >    mxTokenHandler;
-    FastTokenHandlerBase *mpTokenHandler;
-    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >        mxErrorHandler;
-    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >      mxEntityResolver;
-    ::com::sun::star::lang::Locale          maLocale;
-
-    ParserData();
-    ~ParserData();
-};
-
-// --------------------------------------------------------------------
+class FastSaxParserImpl;
 
 // This class implements the external Parser interface
 class SAX_DLLPUBLIC FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastParser, ::com::sun::star::lang::XServiceInfo >
 {
+    FastSaxParserImpl* mpImpl;
+
 public:
     FastSaxParser();
     virtual ~FastSaxParser();
@@ -127,50 +67,7 @@ public:
     virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
     virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);
 
-    // called by the C callbacks of the expat parser
-    void callbackStartElement( const XML_Char* name, const XML_Char** atts );
-    void callbackEndElement( const XML_Char* name );
-    void callbackCharacters( const XML_Char* s, int nLen );
-    int  callbackExternalEntityRef( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId);
-    void callbackEntityDecl(const XML_Char *entityName, int is_parameter_entity,
-            const XML_Char *value, int value_length, const XML_Char *base,
-            const XML_Char *systemId, const XML_Char *publicId,
-            const XML_Char *notationName);
-
-    void pushEntity( const Entity& rEntity );
-    void popEntity();
-    Entity& getEntity();
-    const Entity& getEntity() const;
-    void parse();
-    void produce( CallbackType aType );
-
     bool hasNamespaceURL( const OUString& rPrefix ) const;
-
-private:
-    bool consume(EventList *);
-    void deleteUsedEvents();
-
-    sal_Int32 GetToken( const sal_Char* pToken, sal_Int32 nTokenLen = 0 );
-    sal_Int32 GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (::com::sun::star::xml::sax::SAXException);
-    OUString GetNamespaceURL( const OString& rPrefix ) throw (::com::sun::star::xml::sax::SAXException);
-    OUString GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw (::com::sun::star::xml::sax::SAXException);
-    sal_Int32 GetNamespaceToken( const OUString& rNamespaceURL );
-    sal_Int32 GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen );
-    void DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL );
-
-    void pushContext();
-    void popContext();
-
-    void splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen );
-
-private:
-    osl::Mutex maMutex; ///< Protecting whole parseStream() execution
-    ::rtl::Reference< FastLocatorImpl >     mxDocumentLocator;
-    NamespaceMap                            maNamespaceMap;
-
-    ParserData maData;                      /// Cached parser configuration for next call of parseStream().
-    ::std::stack< Entity > maEntities;      /// Entity stack for each call of parseStream().
-    FastTokenLookup maTokenLookup;
 };
 
 }
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 9535902..2746164 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -17,23 +17,33 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#include <boost/scoped_ptr.hpp>
-
-#include <osl/diagnose.h>
-#include <rtl/ustrbuf.hxx>
-#include <salhelper/thread.hxx>
+#include "sax/fastparser.hxx"
+#include "sax/fastattribs.hxx"
+#include "xml2utf.hxx"
 
 #include <com/sun/star/lang/DisposedException.hpp>
-#include <com/sun/star/xml/sax/SAXParseException.hpp>
 #include <com/sun/star/xml/sax/FastToken.hpp>
-#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/xml/sax/XFastContextHandler.hpp>
+#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
 #include <cppuhelper/factory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/conditn.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <salhelper/thread.hxx>
 
-#include "sax/fastparser.hxx"
-
-#include "xml2utf.hxx"
-
-#include <string.h>
+#include <boost/optional.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/unordered_map.hpp>
+#include <stack>
+#include <vector>
+#include <queue>
+#include <cstring>
+#include <expat.h>
 
 #define PARSER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastParser"
 #define PARSER_SERVICE_NAME        "com.sun.star.xml.sax.FastParser"
@@ -45,62 +55,74 @@ using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::xml::sax;
 using namespace ::com::sun::star::io;
+using namespace com::sun::star;
 
-extern "C" {
+namespace sax_fastparser {
 
-static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
-{
-    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
-    pFastParser->callbackStartElement( name, atts );
-}
+struct Event;
+class FastLocatorImpl;
+struct NamespaceDefine;
+struct Entity;
 
-static void call_callbackEndElement(void *userData, const XML_Char *name)
-{
-    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
-    pFastParser->callbackEndElement( name );
-}
+typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
 
-static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
-{
-    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
-    pFastParser->callbackCharacters( s, nLen );
-}
+typedef ::boost::unordered_map< OUString, sal_Int32,
+        OUStringHash, ::std::equal_to< OUString > > NamespaceMap;
 
-static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
-        int is_parameter_entity, const XML_Char *value, int value_length,
-        const XML_Char *base, const XML_Char *systemId,
-        const XML_Char *publicId, const XML_Char *notationName)
-{
-    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>(userData);
-    pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
-            value_length, base, systemId, publicId, notationName);
-}
+typedef std::vector<Event> EventList;
 
-static int call_callbackExternalEntityRef( XML_Parser parser,
-        const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
-{
-    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( XML_GetUserData( parser ) );
-    return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
-}
+enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION };
 
-} // extern "C"
+struct Event
+{
+    OUString msChars;
+    sal_Int32 mnElementToken;
+    OUString msNamespace;
+    OUString msElementName;
+    rtl::Reference< FastAttributeList > mxAttributes;
+    CallbackType maType;
+};
 
-namespace sax_fastparser {
+struct SAX_DLLPUBLIC NameWithToken
+{
+    OUString msName;
+    sal_Int32 mnToken;
 
-NameWithToken::NameWithToken(const OUString& sName, const sal_Int32& nToken) :
-    msName(sName), mnToken(nToken) {}
+    NameWithToken(const OUString& sName, const sal_Int32& nToken) :
+        msName(sName), mnToken(nToken) {}
+};
 
-SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
-        mnElementToken(nElementToken)
+struct SaxContext
 {
-    if (nElementToken == FastToken::DONTKNOW)
+    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > mxContext;
+    sal_Int32                   mnElementToken;
+    boost::optional< OUString > maNamespace;
+    boost::optional< OUString > maElementName;
+
+    SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
+            mnElementToken(nElementToken)
     {
-        maNamespace = aNamespace;
-        maElementName = aElementName;
+        if (nElementToken == FastToken::DONTKNOW)
+        {
+            maNamespace = aNamespace;
+            maElementName = aElementName;
+        }
     }
-}
+};
 
-// --------------------------------------------------------------------
+
+struct ParserData
+{
+    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
+    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >    mxTokenHandler;
+    FastTokenHandlerBase *mpTokenHandler;
+    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >        mxErrorHandler;
+    ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >      mxEntityResolver;
+    ::com::sun::star::lang::Locale          maLocale;
+
+    ParserData();
+    ~ParserData();
+};
 
 struct NamespaceDefine
 {
@@ -164,11 +186,87 @@ struct Entity : public ParserData
     Event& getEvent( CallbackType aType );
 };
 
+// --------------------------------------------------------------------
+// FastSaxParser implementation
+// --------------------------------------------------------------------
+
+class FastSaxParserImpl
+{
+public:
+    FastSaxParserImpl( FastSaxParser* pFront );
+    virtual ~FastSaxParserImpl();
+
+    // The implementation details
+    static ::com::sun::star::uno::Sequence< OUString > getSupportedServiceNames_Static(void);
+
+    // XFastParser
+    void SAL_CALL parseStream( const ::com::sun::star::xml::sax::InputSource& aInputSource ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+    void SAL_CALL setFastDocumentHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void SAL_CALL setTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void SAL_CALL registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+    OUString SAL_CALL getNamespaceURL( const OUString& rPrefix ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+    void SAL_CALL setErrorHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
+    void SAL_CALL setEntityResolver( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >& Resolver ) throw (::com::sun::star::uno::RuntimeException);
+    void SAL_CALL setLocale( const ::com::sun::star::lang::Locale& rLocale ) throw (::com::sun::star::uno::RuntimeException);
+
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
+    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+    virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);
+
+    // called by the C callbacks of the expat parser
+    void callbackStartElement( const XML_Char* name, const XML_Char** atts );
+    void callbackEndElement( const XML_Char* name );
+    void callbackCharacters( const XML_Char* s, int nLen );
+    int  callbackExternalEntityRef( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId);
+    void callbackEntityDecl(const XML_Char *entityName, int is_parameter_entity,
+            const XML_Char *value, int value_length, const XML_Char *base,
+            const XML_Char *systemId, const XML_Char *publicId,
+            const XML_Char *notationName);
+
+    void pushEntity( const Entity& rEntity );
+    void popEntity();
+    Entity& getEntity();
+    const Entity& getEntity() const;
+    void parse();
+    void produce( CallbackType aType );
+
+    bool hasNamespaceURL( const OUString& rPrefix ) const;
+
+private:
+    bool consume(EventList *);
+    void deleteUsedEvents();
+
+    sal_Int32 GetToken( const sal_Char* pToken, sal_Int32 nTokenLen = 0 );
+    sal_Int32 GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (::com::sun::star::xml::sax::SAXException);
+    OUString GetNamespaceURL( const OString& rPrefix ) throw (::com::sun::star::xml::sax::SAXException);
+    OUString GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw (::com::sun::star::xml::sax::SAXException);
+    sal_Int32 GetNamespaceToken( const OUString& rNamespaceURL );
+    sal_Int32 GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen );
+    void DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL );
+
+    void pushContext();
+    void popContext();
+
+    void splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen );
+
+private:
+    FastSaxParser* mpFront;
+
+    osl::Mutex maMutex; ///< Protecting whole parseStream() execution
+    ::rtl::Reference< FastLocatorImpl >     mxDocumentLocator;
+    NamespaceMap                            maNamespaceMap;
+
+    ParserData maData;                      /// Cached parser configuration for next call of parseStream().
+    ::std::stack< Entity > maEntities;      /// Entity stack for each call of parseStream().
+    FastTokenLookup maTokenLookup;
+};
+
 class ParserThread: public salhelper::Thread
 {
-    FastSaxParser *mpParser;
+    FastSaxParserImpl *mpParser;
 public:
-    ParserThread(FastSaxParser *pParser): Thread("Parser"), mpParser(pParser) {}
+    ParserThread(FastSaxParserImpl *pParser): Thread("Parser"), mpParser(pParser) {}
 private:
     virtual void execute()
     {
@@ -184,16 +282,57 @@ private:
     }
 };
 
+}
+
+extern "C" {
+
+static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
+{
+    sax_fastparser::FastSaxParserImpl* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParserImpl*>( userData );
+    pFastParser->callbackStartElement( name, atts );
+}
+
+static void call_callbackEndElement(void *userData, const XML_Char *name)
+{
+    sax_fastparser::FastSaxParserImpl* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParserImpl*>( userData );
+    pFastParser->callbackEndElement( name );
+}
+
+static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
+{
+    sax_fastparser::FastSaxParserImpl* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParserImpl*>( userData );
+    pFastParser->callbackCharacters( s, nLen );
+}
+
+static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
+        int is_parameter_entity, const XML_Char *value, int value_length,
+        const XML_Char *base, const XML_Char *systemId,
+        const XML_Char *publicId, const XML_Char *notationName)
+{
+    sax_fastparser::FastSaxParserImpl* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParserImpl*>(userData);
+    pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
+            value_length, base, systemId, publicId, notationName);
+}
+
+static int call_callbackExternalEntityRef( XML_Parser parser,
+        const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
+{
+    sax_fastparser::FastSaxParserImpl* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParserImpl*>( XML_GetUserData( parser ) );
+    return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
+}
+
+}
+
+namespace sax_fastparser {
+
 // --------------------------------------------------------------------
 // FastLocatorImpl
 // --------------------------------------------------------------------
 
-class FastSaxParser;
-
 class FastLocatorImpl : public WeakImplHelper1< XLocator >
 {
 public:
-    FastLocatorImpl( FastSaxParser *p ) : mpParser(p) {}
+    FastLocatorImpl( FastSaxParserImpl *p ) : mpParser(p) {}
 
     void dispose() { mpParser = 0; }
     void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
@@ -205,7 +344,7 @@ public:
     virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException);
 
 private:
-    FastSaxParser *mpParser;
+    FastSaxParserImpl *mpParser;
 };
 
 // --------------------------------------------------------------------
@@ -407,18 +546,14 @@ Event& Entity::getEvent( CallbackType aType )
     return rEvent;
 }
 
-// --------------------------------------------------------------------
-// FastSaxParser implementation
-// --------------------------------------------------------------------
-
-FastSaxParser::FastSaxParser()
+FastSaxParserImpl::FastSaxParserImpl( FastSaxParser* pFront ) : mpFront(pFront)
 {
     mxDocumentLocator.set( new FastLocatorImpl( this ) );
 }
 
 // --------------------------------------------------------------------
 
-FastSaxParser::~FastSaxParser()
+FastSaxParserImpl::~FastSaxParserImpl()
 {
     if( mxDocumentLocator.is() )
         mxDocumentLocator->dispose();
@@ -426,7 +561,7 @@ FastSaxParser::~FastSaxParser()
 
 // --------------------------------------------------------------------
 
-void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
+void FastSaxParserImpl::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
 {
     Entity& rEntity = getEntity();
     assert(!rEntity.maNamespaceCount.empty()); // need a context!
@@ -444,7 +579,7 @@ void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNa
 
 // --------------------------------------------------------------------
 
-sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
+sal_Int32 FastSaxParserImpl::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
 {
     return maTokenLookup.getTokenFromChars( getEntity().mxTokenHandler,
                                             getEntity().mpTokenHandler,
@@ -453,7 +588,7 @@ sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0
 
 // --------------------------------------------------------------------
 
-sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
+sal_Int32 FastSaxParserImpl::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
 {
     sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
 
@@ -485,7 +620,7 @@ sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefix
 
 // --------------------------------------------------------------------
 
-sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
+sal_Int32 FastSaxParserImpl::GetNamespaceToken( const OUString& rNamespaceURL )
 {
     NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
     if( aIter != maNamespaceMap.end() )
@@ -496,7 +631,7 @@ sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
 
 // --------------------------------------------------------------------
 
-OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
+OUString FastSaxParserImpl::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
 {
     Entity& rEntity = getEntity();
     if( !rEntity.maNamespaceCount.empty() )
@@ -510,7 +645,7 @@ OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXExce
     throw SAXException(); // prefix that has no defined namespace url
 }
 
-OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
+OUString FastSaxParserImpl::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
 {
     Entity& rEntity = getEntity();
     if( pPrefix && !rEntity.maNamespaceCount.empty() )
@@ -532,7 +667,7 @@ OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen
 
 // --------------------------------------------------------------------
 
-sal_Int32 FastSaxParser::GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen )
+sal_Int32 FastSaxParserImpl::GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen )
 {
     if( nNamespaceToken != FastToken::DONTKNOW )
     {
@@ -546,7 +681,7 @@ sal_Int32 FastSaxParser::GetTokenWithContextNamespace( sal_Int32 nNamespaceToken
 
 // --------------------------------------------------------------------
 
-void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
+void FastSaxParserImpl::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
 {
     XML_Char *p;
     for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
@@ -579,7 +714,7 @@ void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix
 * the file-specific initialization work. (During a parser run, external files may be opened)
 *
 ****************/
-void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
+void FastSaxParserImpl::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
 {
     // Only one text at one time
     MutexGuard guard( maMutex );
@@ -684,18 +819,18 @@ void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXEx
     XML_ParserFree( entity.mpParser );
 }
 
-void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
+void FastSaxParserImpl::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
 {
     maData.mxDocumentHandler = Handler;
 }
 
-void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
+void SAL_CALL FastSaxParserImpl::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
 {
     maData.mxTokenHandler = xHandler;
     maData.mpTokenHandler = dynamic_cast< FastTokenHandlerBase *>( xHandler.get() );
 }
 
-void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
+void SAL_CALL FastSaxParserImpl::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
 {
     if( NamespaceToken >= FastToken::NAMESPACE )
     {
@@ -708,7 +843,7 @@ void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sa
     throw IllegalArgumentException();
 }
 
-OUString SAL_CALL FastSaxParser::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
+OUString SAL_CALL FastSaxParserImpl::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
 {
     try
     {
@@ -720,22 +855,22 @@ OUString SAL_CALL FastSaxParser::getNamespaceURL( const OUString& rPrefix ) thro
     throw IllegalArgumentException();
 }
 
-void FastSaxParser::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
+void FastSaxParserImpl::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
 {
     maData.mxErrorHandler = Handler;
 }
 
-void FastSaxParser::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
+void FastSaxParserImpl::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
 {
     maData.mxEntityResolver = Resolver;
 }
 
-void FastSaxParser::setLocale( const Locale & Locale ) throw (RuntimeException)
+void FastSaxParserImpl::setLocale( const Locale & Locale ) throw (RuntimeException)
 {
     maData.maLocale = Locale;
 }
 
-Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
+Sequence< OUString > FastSaxParserImpl::getSupportedServiceNames_Static(void)
 {
     Sequence<OUString> aRet(1);
     aRet.getArray()[0] = OUString( PARSER_SERVICE_NAME );
@@ -743,19 +878,19 @@ Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
 }
 
 // XServiceInfo
-OUString FastSaxParser::getImplementationName() throw (RuntimeException)
+OUString FastSaxParserImpl::getImplementationName() throw (RuntimeException)
 {
     return OUString( PARSER_IMPLEMENTATION_NAME );
 }
 
 // XServiceInfo
-sal_Bool FastSaxParser::supportsService(const OUString& ServiceName) throw (RuntimeException)
+sal_Bool FastSaxParserImpl::supportsService(const OUString& ServiceName) throw (RuntimeException)
 {
-    return cppu::supportsService(this, ServiceName);
+    return cppu::supportsService(mpFront, ServiceName);
 }
 
 // XServiceInfo
-Sequence< OUString > FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException)
+Sequence< OUString > FastSaxParserImpl::getSupportedServiceNames(void) throw (RuntimeException)
 {
 
     Sequence<OUString> seq(1);
@@ -815,7 +950,7 @@ OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int3
 
 } // namespace
 
-void FastSaxParser::deleteUsedEvents()
+void FastSaxParserImpl::deleteUsedEvents()
 {
     Entity& rEntity = getEntity();
     osl::ResettableMutexGuard aGuard(rEntity.maEventProtector);
@@ -833,7 +968,7 @@ void FastSaxParser::deleteUsedEvents()
     }
 }
 
-void FastSaxParser::produce( CallbackType aType )
+void FastSaxParserImpl::produce( CallbackType aType )
 {
     Entity& rEntity = getEntity();
     if (aType == DONE ||
@@ -859,7 +994,7 @@ void FastSaxParser::produce( CallbackType aType )
     }
 }
 
-bool FastSaxParser::hasNamespaceURL( const OUString& rPrefix ) const
+bool FastSaxParserImpl::hasNamespaceURL( const OUString& rPrefix ) const
 {
     const Entity& rEntity = getEntity();
 
@@ -877,7 +1012,7 @@ bool FastSaxParser::hasNamespaceURL( const OUString& rPrefix ) const
     return false;
 }
 
-bool FastSaxParser::consume(EventList *pEventList)
+bool FastSaxParserImpl::consume(EventList *pEventList)
 {
     Entity& rEntity = getEntity();
     for (EventList::iterator aEventIt = pEventList->begin();
@@ -927,28 +1062,28 @@ bool FastSaxParser::consume(EventList *pEventList)
     return true;
 }
 
-void FastSaxParser::pushEntity( const Entity& rEntity )
+void FastSaxParserImpl::pushEntity( const Entity& rEntity )
 {
     maEntities.push( rEntity );
 }
 
-void FastSaxParser::popEntity()
+void FastSaxParserImpl::popEntity()
 {
     maEntities.pop();
 }
 
-Entity& FastSaxParser::getEntity()
+Entity& FastSaxParserImpl::getEntity()
 {
     return maEntities.top();
 }
 
-const Entity& FastSaxParser::getEntity() const
+const Entity& FastSaxParserImpl::getEntity() const
 {
     return maEntities.top();
 }
 
 // starts parsing with actual parser !
-void FastSaxParser::parse()
+void FastSaxParserImpl::parse()
 {
     const int BUFFER_SIZE = 16 * 1024;
     Sequence< sal_Int8 > seqOut( BUFFER_SIZE );
@@ -1005,7 +1140,7 @@ void FastSaxParser::parse()
 //
 //-----------------------------------------
 
-void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
+void FastSaxParserImpl::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
 {
     Entity& rEntity = getEntity();
     if( rEntity.maNamespaceCount.empty() )
@@ -1134,7 +1269,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
     }
 }
 
-void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
+void FastSaxParserImpl::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
 {
     Entity& rEntity = getEntity();
     assert( !rEntity.maNamespaceCount.empty() );
@@ -1153,7 +1288,7 @@ void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
 }
 
 
-void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
+void FastSaxParserImpl::callbackCharacters( const XML_Char* s, int nLen )
 {
     Entity& rEntity = getEntity();
     Event& rEvent = rEntity.getEvent( CHARACTERS );
@@ -1164,7 +1299,7 @@ void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
         rEntity.characters( rEvent.msChars );
 }
 
-void FastSaxParser::callbackEntityDecl(
+void FastSaxParserImpl::callbackEntityDecl(
     SAL_UNUSED_PARAMETER const XML_Char * /*entityName*/,
     SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
     const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
@@ -1178,7 +1313,7 @@ void FastSaxParser::callbackEntityDecl(
         XML_StopParser(getEntity().mpParser, XML_FALSE);
         getEntity().maSavedException <<= SAXParseException(
             "FastSaxParser: internal entity declaration, stopping",
-            static_cast<OWeakObject*>(this), Any(),
+            static_cast<OWeakObject*>(mpFront), Any(),
             mxDocumentLocator->getPublicId(),
             mxDocumentLocator->getSystemId(),
             mxDocumentLocator->getLineNumber(),
@@ -1188,7 +1323,7 @@ void FastSaxParser::callbackEntityDecl(
     }
 }
 
-int FastSaxParser::callbackExternalEntityRef(
+int FastSaxParserImpl::callbackExternalEntityRef(
     XML_Parser parser, const XML_Char *context,
     SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
     const XML_Char *publicId )
@@ -1262,6 +1397,89 @@ int FastSaxParser::callbackExternalEntityRef(
     return bOK;
 }
 
+FastSaxParser::FastSaxParser() : mpImpl(new FastSaxParserImpl(this)) {}
+
+FastSaxParser::~FastSaxParser()
+{
+    delete mpImpl;
+}
+
+uno::Sequence<OUString> FastSaxParser::getSupportedServiceNames_Static()
+{
+    return FastSaxParserImpl::getSupportedServiceNames_Static();
+}
+
+void FastSaxParser::parseStream( const xml::sax::InputSource& aInputSource )
+    throw (xml::sax::SAXException, io::IOException, uno::RuntimeException)
+{
+    mpImpl->parseStream(aInputSource);
+}
+
+void FastSaxParser::setFastDocumentHandler( const uno::Reference<xml::sax::XFastDocumentHandler>& Handler )
+    throw (uno::RuntimeException)
+{
+    mpImpl->setFastDocumentHandler(Handler);
+}
+
+void FastSaxParser::setTokenHandler( const uno::Reference<xml::sax::XFastTokenHandler>& Handler )
+    throw (uno::RuntimeException)
+{
+    mpImpl->setTokenHandler(Handler);
+}
+
+void FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken )
+    throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+    mpImpl->registerNamespace(NamespaceURL, NamespaceToken);
+}
+
+OUString FastSaxParser::getNamespaceURL( const OUString& rPrefix )
+    throw(lang::IllegalArgumentException, uno::RuntimeException)
+{
+    return mpImpl->getNamespaceURL(rPrefix);
+}
+
+void FastSaxParser::setErrorHandler( const uno::Reference< xml::sax::XErrorHandler >& Handler )
+    throw (uno::RuntimeException)
+{
+    mpImpl->setErrorHandler(Handler);
+}
+
+void FastSaxParser::setEntityResolver( const uno::Reference< xml::sax::XEntityResolver >& Resolver )
+    throw (uno::RuntimeException)
+{
+    mpImpl->setEntityResolver(Resolver);
+}
+
+void FastSaxParser::setLocale( const lang::Locale& rLocale )
+    throw (uno::RuntimeException)
+{
+    mpImpl->setLocale(rLocale);
+}
+
+OUString FastSaxParser::getImplementationName()
+    throw (uno::RuntimeException)
+{
+    return mpImpl->getImplementationName();
+}
+
+sal_Bool FastSaxParser::supportsService( const OUString& ServiceName )
+    throw (uno::RuntimeException)
+{
+    return mpImpl->supportsService(ServiceName);
+}
+
+uno::Sequence<OUString> FastSaxParser::getSupportedServiceNames()
+    throw (uno::RuntimeException)
+{
+    return mpImpl->getSupportedServiceNames();
+}
+
+bool FastSaxParser::hasNamespaceURL( const OUString& rPrefix ) const
+{
+    return mpImpl->hasNamespaceURL(rPrefix);
+}
+
 } // namespace sax_fastparser
 
 Reference< XInterface > SAL_CALL FastSaxParser_CreateInstance(
@@ -1292,7 +1510,7 @@ SAL_DLLPUBLIC_EXPORT void * SAL_CALL fastsax_component_getFactory(
             xRet = createSingleFactory(
                 xSMgr, aImplementationName,
                 FastSaxParser_CreateInstance,
-                sax_fastparser::FastSaxParser::getSupportedServiceNames_Static() );
+                sax_fastparser::FastSaxParserImpl::getSupportedServiceNames_Static() );
         }
 
         if (xRet.is())
commit 83dcb7e23a832e2e8b25daeba3a280649df3ce3c
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Dec 2 19:20:59 2013 -0500

    Add a means to check if a namespace exists.
    
    Useful when we just need to check if the stream has a certain namespace
    defined. Calling getNamespaceURL() may throw SAXException in such case.
    
    Change-Id: Ib2b7b202492390158270d87bab95d1793c9d8a70

diff --git a/include/oox/core/fastparser.hxx b/include/oox/core/fastparser.hxx
index fd98241..a673217 100644
--- a/include/oox/core/fastparser.hxx
+++ b/include/oox/core/fastparser.hxx
@@ -75,10 +75,12 @@ public:
     void                parseStream( StorageBase& rStorage, const OUString& rStreamName, bool bCloseStream = false )
                             throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException );
 
-     OUString getNamespaceURL( const OUString& rPrefix )
+    OUString getNamespaceURL( const OUString& rPrefix )
                         throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException );
 
-     sal_Int32 getNamespaceId( const OUString& aUrl );
+    bool hasNamespaceURL( const OUString& rPrefix ) const;
+
+    sal_Int32 getNamespaceId( const OUString& aUrl );
 
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >
                getTokenHandler() const { return mxTokenHandler; }
diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx
index 76eb091..604f220 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -227,6 +227,8 @@ public:
 
     OUString getNamespaceURL( const OUString& rPrefix );
 
+    bool hasNamespaceURL( const OUString& rPrefix ) const;
+
     sal_Int32 getNamespaceId( const OUString& rUrl );
 
     void importDocumentProperties();
diff --git a/include/sax/fastparser.hxx b/include/sax/fastparser.hxx
index 3a8ae53..217893c 100644
--- a/include/sax/fastparser.hxx
+++ b/include/sax/fastparser.hxx
@@ -140,9 +140,12 @@ public:
     void pushEntity( const Entity& rEntity );
     void popEntity();
     Entity& getEntity();
+    const Entity& getEntity() const;
     void parse();
     void produce( CallbackType aType );
 
+    bool hasNamespaceURL( const OUString& rPrefix ) const;
+
 private:
     bool consume(EventList *);
     void deleteUsedEvents();
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index 7bd3710..f9ac63e 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -40,6 +40,7 @@ $(eval $(call gb_Library_use_libraries,oox,\
     cppuhelper \
     editeng \
     drawinglayer \
+    fastsax \
     msfilter \
     sal \
 	i18nlangtag \
diff --git a/oox/source/core/fastparser.cxx b/oox/source/core/fastparser.cxx
index 03fd60a..70e12a8 100644
--- a/oox/source/core/fastparser.cxx
+++ b/oox/source/core/fastparser.cxx
@@ -25,6 +25,8 @@
 #include "oox/helper/storagebase.hxx"
 #include "oox/token/namespacemap.hxx"
 
+#include "sax/fastparser.hxx"
+
 namespace oox {
 namespace core {
 
@@ -66,11 +68,13 @@ InputStreamCloseGuard::~InputStreamCloseGuard()
 // ============================================================================
 
 FastParser::FastParser( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
-    mrNamespaceMap( StaticNamespaceMap::get() )
+    mrNamespaceMap( StaticNamespaceMap::get() ),
+    mpParser(NULL)
 {
     // create a fast parser instance
     Reference< XMultiComponentFactory > xFactory( rxContext->getServiceManager(), UNO_SET_THROW );
     mxParser.set( xFactory->createInstanceWithContext( "com.sun.star.xml.sax.FastParser", rxContext ), UNO_QUERY_THROW );
+    mpParser = dynamic_cast<sax_fastparser::FastSaxParser*>(mxParser.get());
 
     // create the fast tokenhandler
     mxTokenHandler.set( new FastTokenHandler );
@@ -131,6 +135,17 @@ OUString FastParser::getNamespaceURL( const OUString& rPrefix ) throw( IllegalAr
     return mxParser->getNamespaceURL( rPrefix );
 }
 
+bool FastParser::hasNamespaceURL( const OUString& rPrefix ) const
+{
+    if (!mxParser.is())
+        throw RuntimeException();
+
+    if (!mpParser)
+        return false;
+
+    return mpParser->hasNamespaceURL(rPrefix);
+}
+
 sal_Int32 FastParser::getNamespaceId( const OUString& rUrl )
 {
     for( NamespaceMap::const_iterator aIt = mrNamespaceMap.begin(), aEnd = mrNamespaceMap.end(); aIt != aEnd; ++aIt )
diff --git a/oox/source/core/fragmenthandler2.cxx b/oox/source/core/fragmenthandler2.cxx
index 668eb7f..8133b73 100644
--- a/oox/source/core/fragmenthandler2.cxx
+++ b/oox/source/core/fragmenthandler2.cxx
@@ -67,6 +67,12 @@ bool FragmentHandler2::prepareMceContext( sal_Int32 nElement, const AttributeLis
         case MCE_TOKEN( Choice ):
             {
                 OUString aRequires = rAttribs.getString( ( XML_Requires ), OUString("none") );
+                if (!getFilter().hasNamespaceURL(aRequires))
+                    // Check to see if we have this namespace defined first,
+                    // because calling getNamespaceURL() would throw if the
+                    // namespace doesn't exist.
+                    return false;
+
                 aRequires = getFilter().getNamespaceURL( aRequires );
                 if( getFilter().getNamespaceId( aRequires ) > 0 && !aMceState.empty() && aMceState.back() == MCE_STARTED )
                     aMceState.back() = MCE_FOUND_CHOICE;
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index d1ae6a5..2ef319e 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -303,6 +303,11 @@ OUString XmlFilterBase::getNamespaceURL( const OUString& rPrefix )
     return mxImpl->maFastParser.getNamespaceURL( rPrefix );
 }
 
+bool XmlFilterBase::hasNamespaceURL( const OUString& rPrefix ) const
+{
+    return mxImpl->maFastParser.hasNamespaceURL(rPrefix);
+}
+
 sal_Int32 XmlFilterBase::getNamespaceId( const OUString& rUrl )
 {
      return mxImpl->maFastParser.getNamespaceId( rUrl );
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 9f60b72..9535902 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -859,6 +859,24 @@ void FastSaxParser::produce( CallbackType aType )
     }
 }
 
+bool FastSaxParser::hasNamespaceURL( const OUString& rPrefix ) const
+{
+    const Entity& rEntity = getEntity();
+
+    if (rEntity.maNamespaceCount.empty())
+        return false;
+
+    OString aPrefix = OUStringToOString(rPrefix, RTL_TEXTENCODING_UTF8);
+    sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
+    while (nNamespace--)
+    {
+        if (rEntity.maNamespaceDefines[nNamespace]->maPrefix == aPrefix)
+            return true;
+    }
+
+    return false;
+}
+
 bool FastSaxParser::consume(EventList *pEventList)
 {
     Entity& rEntity = getEntity();
@@ -924,6 +942,11 @@ Entity& FastSaxParser::getEntity()
     return maEntities.top();
 }
 
+const Entity& FastSaxParser::getEntity() const
+{
+    return maEntities.top();
+}
+
 // starts parsing with actual parser !
 void FastSaxParser::parse()
 {
commit cd4183a57fd603a7a603514d69cbd50aa19651b4
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Dec 2 18:32:42 2013 -0500

    Move this header out into a public place.
    
    Change-Id: I356b26947d1018276d8a9ff6012fdad3ca2c0fd8

diff --git a/include/oox/core/fastparser.hxx b/include/oox/core/fastparser.hxx
index b454caf..fd98241 100644
--- a/include/oox/core/fastparser.hxx
+++ b/include/oox/core/fastparser.hxx
@@ -28,6 +28,10 @@ namespace oox {
     class StorageBase;
 }
 
+namespace sax_fastparser {
+    class FastSaxParser;
+}
+
 namespace oox {
 namespace core {
 
@@ -85,6 +89,8 @@ private:
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >
                         mxTokenHandler;
     const NamespaceMap& mrNamespaceMap;
+
+    sax_fastparser::FastSaxParser* mpParser;
 };
 
 // ============================================================================
diff --git a/sax/source/fastparser/fastparser.hxx b/include/sax/fastparser.hxx
similarity index 75%
rename from sax/source/fastparser/fastparser.hxx
rename to include/sax/fastparser.hxx
index 2943509..3a8ae53 100644
--- a/sax/source/fastparser/fastparser.hxx
+++ b/include/sax/fastparser.hxx
@@ -17,8 +17,8 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#ifndef _SAX_FASTPARSER_HXX_
-#define _SAX_FASTPARSER_HXX_
+#ifndef INCLUDED_SAX_FASTPARSER_HXX
+#define INCLUDED_SAX_FASTPARSER_HXX
 
 #include <queue>
 #include <vector>
@@ -36,25 +36,23 @@
 #include <cppuhelper/implbase2.hxx>
 
 #include <expat.h>
-#include "xml2utf.hxx"
+#include "saxdllapi.h"
 
 #include <sax/fastattribs.hxx>
 
-#define PARSER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastParser"
-#define PARSER_SERVICE_NAME        "com.sun.star.xml.sax.FastParser"
-
 namespace sax_fastparser {
 
 struct Event;
 class FastLocatorImpl;
 struct NamespaceDefine;
+struct Entity;
 
 typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
 
 typedef ::boost::unordered_map< OUString, sal_Int32,
         OUStringHash, ::std::equal_to< OUString > > NamespaceMap;
 
-struct NameWithToken
+struct SAX_DLLPUBLIC NameWithToken
 {
     OUString msName;
     sal_Int32 mnToken;
@@ -66,7 +64,8 @@ typedef std::vector<Event> EventList;
 
 enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION };
 
-struct Event {
+struct Event
+{
     OUString msChars;
     sal_Int32 mnElementToken;
     OUString msNamespace;
@@ -88,7 +87,7 @@ struct SaxContext
 
 // --------------------------------------------------------------------
 
-struct ParserData
+struct SAX_DLLPUBLIC ParserData
 {
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >    mxTokenHandler;
@@ -103,63 +102,8 @@ struct ParserData
 
 // --------------------------------------------------------------------
 
-// Entity binds all information needed for a single file | single call of parseStream
-struct Entity : public ParserData
-{
-    // Amount of work producer sends to consumer in one iteration:
-    static const size_t mnEventListSize = 1000;
-
-    // unique for each Entity instance:
-
-    // Number of valid events in mpProducedEvents:
-    size_t mnProducedEventsSize;
-    EventList *mpProducedEvents;
-    std::queue< EventList * > maPendingEvents;
-    std::queue< EventList * > maUsedEvents;
-    osl::Mutex maEventProtector;
-
-    static const size_t mnEventLowWater = 4;
-    static const size_t mnEventHighWater = 8;
-    osl::Condition maConsumeResume;
-    osl::Condition maProduceResume;
-    // Event we use to store data if threading is disabled:
-    Event maSharedEvent;
-
-    // copied in copy constructor:
-
-    // Allow to disable threading for small documents:
-    bool                                    mbEnableThreads;
-    ::com::sun::star::xml::sax::InputSource maStructSource;
-    XML_Parser                              mpParser;
-    ::sax_expatwrap::XMLFile2UTFConverter   maConverter;
-
-    // Exceptions cannot be thrown through the C-XmlParser (possible resource leaks),
-    // therefore the exception must be saved somewhere.
-    ::com::sun::star::uno::Any              maSavedException;
-
-    ::std::stack< NameWithToken >           maNamespaceStack;
-    /* Context for main thread consuming events.
-     * startElement() stores the data, which characters() and endElement() uses
-     */
-    ::std::stack< SaxContext>               maContextStack;
-    // Determines which elements of maNamespaceDefines are valid in current context
-    ::std::stack< sal_uInt32 >              maNamespaceCount;
-    ::std::vector< NamespaceDefineRef >     maNamespaceDefines;
-
-    explicit Entity( const ParserData& rData );
-    Entity( const Entity& rEntity );
-    ~Entity();
-    void startElement( Event *pEvent );
-    void characters( const OUString& sChars );
-    void endElement();
-    EventList* getEventList();
-    Event& getEvent( CallbackType aType );
-};
-
-// --------------------------------------------------------------------
-
 // This class implements the external Parser interface
-class FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastParser, ::com::sun::star::lang::XServiceInfo >
+class SAX_DLLPUBLIC FastSaxParser : public ::cppu::WeakImplHelper2< ::com::sun::star::xml::sax::XFastParser, ::com::sun::star::lang::XServiceInfo >
 {
 public:
     FastSaxParser();
diff --git a/sax/Library_fastsax.mk b/sax/Library_fastsax.mk
index ab0c4e6..863336f 100644
--- a/sax/Library_fastsax.mk
+++ b/sax/Library_fastsax.mk
@@ -38,7 +38,6 @@ $(eval $(call gb_Library_use_static_libraries,fastsax,\
 ))
 
 $(eval $(call gb_Library_add_exception_objects,fastsax,\
-	sax/source/fastparser/facreg \
 	sax/source/fastparser/fastparser \
 ))
 
diff --git a/sax/source/fastparser/facreg.cxx b/sax/source/fastparser/facreg.cxx
deleted file mode 100644
index fbf746f..0000000
--- a/sax/source/fastparser/facreg.cxx
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <cppuhelper/factory.hxx>
-#include <cppuhelper/weak.hxx>
-#include <cppuhelper/implbase2.hxx>
-
-#include "fastparser.hxx"
-
-using namespace sax_fastparser;
-using namespace ::cppu;
-using namespace ::com::sun::star::uno;
-using namespace ::com::sun::star::registry;
-using namespace ::com::sun::star::lang;
-
-namespace sax_fastparser
-{
-
-Reference< XInterface > SAL_CALL FastSaxParser_CreateInstance(
-    SAL_UNUSED_PARAMETER const Reference< XMultiServiceFactory > & )
-    throw(Exception)
-{
-    FastSaxParser *p = new FastSaxParser;
-    return Reference< XInterface > ( (OWeakObject * ) p );
-}
-
-}
-
-extern "C"
-{
-
-SAL_DLLPUBLIC_EXPORT void * SAL_CALL fastsax_component_getFactory(
-    const sal_Char * pImplName, void * pServiceManager,
-    SAL_UNUSED_PARAMETER void * /*pRegistryKey*/ )
-{
-    void * pRet = 0;
-
-    if (pServiceManager )
-    {
-        Reference< XSingleServiceFactory > xRet;
-        Reference< XMultiServiceFactory > xSMgr( reinterpret_cast< XMultiServiceFactory * > ( pServiceManager ) );
-
-        OUString aImplementationName( OUString::createFromAscii( pImplName ) );
-
-        if ( aImplementationName == PARSER_IMPLEMENTATION_NAME  )
-        {
-            xRet = createSingleFactory( xSMgr, aImplementationName,
-                                        FastSaxParser_CreateInstance,
-                                        FastSaxParser::getSupportedServiceNames_Static() );
-        }
-
-        if (xRet.is())
-        {
-            xRet->acquire();
-            pRet = xRet.get();
-        }
-    }
-
-    return pRet;
-}
-
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 75974b8..9f60b72 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -27,11 +27,17 @@
 #include <com/sun/star/xml/sax/SAXParseException.hpp>
 #include <com/sun/star/xml/sax/FastToken.hpp>
 #include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/factory.hxx>
 
-#include "fastparser.hxx"
+#include "sax/fastparser.hxx"
+
+#include "xml2utf.hxx"
 
 #include <string.h>
 
+#define PARSER_IMPLEMENTATION_NAME "com.sun.star.comp.extensions.xml.sax.FastParser"
+#define PARSER_SERVICE_NAME        "com.sun.star.xml.sax.FastParser"
+
 using namespace ::std;
 using namespace ::osl;
 using namespace ::cppu;
@@ -105,6 +111,59 @@ struct NamespaceDefine
     NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
 };
 
+// Entity binds all information needed for a single file | single call of parseStream
+struct Entity : public ParserData
+{
+    // Amount of work producer sends to consumer in one iteration:
+    static const size_t mnEventListSize = 1000;
+
+    // unique for each Entity instance:
+
+    // Number of valid events in mpProducedEvents:
+    size_t mnProducedEventsSize;
+    EventList *mpProducedEvents;
+    std::queue< EventList * > maPendingEvents;
+    std::queue< EventList * > maUsedEvents;
+    osl::Mutex maEventProtector;
+
+    static const size_t mnEventLowWater = 4;
+    static const size_t mnEventHighWater = 8;
+    osl::Condition maConsumeResume;
+    osl::Condition maProduceResume;
+    // Event we use to store data if threading is disabled:
+    Event maSharedEvent;
+
+    // copied in copy constructor:
+
+    // Allow to disable threading for small documents:
+    bool                                    mbEnableThreads;
+    ::com::sun::star::xml::sax::InputSource maStructSource;
+    XML_Parser                              mpParser;
+    ::sax_expatwrap::XMLFile2UTFConverter   maConverter;
+
+    // Exceptions cannot be thrown through the C-XmlParser (possible resource leaks),
+    // therefore the exception must be saved somewhere.
+    ::com::sun::star::uno::Any              maSavedException;
+
+    ::std::stack< NameWithToken >           maNamespaceStack;
+    /* Context for main thread consuming events.
+     * startElement() stores the data, which characters() and endElement() uses
+     */
+    ::std::stack< SaxContext>               maContextStack;
+    // Determines which elements of maNamespaceDefines are valid in current context
+    ::std::stack< sal_uInt32 >              maNamespaceCount;
+    ::std::vector< NamespaceDefineRef >     maNamespaceDefines;
+
+    explicit Entity( const ParserData& rData );
+    Entity( const Entity& rEntity );
+    ~Entity();
+    void startElement( Event *pEvent );
+    void characters( const OUString& sChars );
+    void endElement();
+    EventList* getEventList();
+    Event& getEvent( CallbackType aType );
+};
+
 class ParserThread: public salhelper::Thread
 {
     FastSaxParser *mpParser;
@@ -1182,4 +1241,47 @@ int FastSaxParser::callbackExternalEntityRef(
 
 } // namespace sax_fastparser
 
+Reference< XInterface > SAL_CALL FastSaxParser_CreateInstance(
+    SAL_UNUSED_PARAMETER const Reference< XMultiServiceFactory > & )
+    throw(Exception)
+{
+    sax_fastparser::FastSaxParser *p = new sax_fastparser::FastSaxParser;
+    return Reference< XInterface > ( (OWeakObject * ) p );
+}
+
+extern "C" {
+
+SAL_DLLPUBLIC_EXPORT void * SAL_CALL fastsax_component_getFactory(
+    const sal_Char * pImplName, void * pServiceManager,
+    SAL_UNUSED_PARAMETER void * /*pRegistryKey*/ )
+{
+    void * pRet = 0;
+
+    if (pServiceManager )
+    {
+        Reference< XSingleServiceFactory > xRet;
+        Reference< XMultiServiceFactory > xSMgr( reinterpret_cast< XMultiServiceFactory * > ( pServiceManager ) );
+
+        OUString aImplementationName( OUString::createFromAscii( pImplName ) );
+
+        if ( aImplementationName == PARSER_IMPLEMENTATION_NAME  )
+        {
+            xRet = createSingleFactory(
+                xSMgr, aImplementationName,
+                FastSaxParser_CreateInstance,
+                sax_fastparser::FastSaxParser::getSupportedServiceNames_Static() );
+        }
+
+        if (xRet.is())
+        {
+            xRet->acquire();
+            pRet = xRet.get();
+        }
+    }
+
+    return pRet;
+}
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit a45b87dde5a7ba3ca0baba40b00b162e428475bb
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Dec 2 17:22:14 2013 -0500

    Remove inline methods from the header.
    
    Change-Id: Ie2cff194c1db5eaa992c4bcaaa06ec9a419d85a7

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index caf4ec1..75974b8 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -81,6 +81,9 @@ static int call_callbackExternalEntityRef( XML_Parser parser,
 
 namespace sax_fastparser {
 
+NameWithToken::NameWithToken(const OUString& sName, const sal_Int32& nToken) :
+    msName(sName), mnToken(nToken) {}
+
 SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
         mnElementToken(nElementToken)
 {
@@ -847,6 +850,21 @@ bool FastSaxParser::consume(EventList *pEventList)
     return true;
 }
 
+void FastSaxParser::pushEntity( const Entity& rEntity )
+{
+    maEntities.push( rEntity );
+}
+
+void FastSaxParser::popEntity()
+{
+    maEntities.pop();
+}
+
+Entity& FastSaxParser::getEntity()
+{
+    return maEntities.top();
+}
+
 // starts parsing with actual parser !
 void FastSaxParser::parse()
 {
diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx
index 6888cef..2943509 100644
--- a/sax/source/fastparser/fastparser.hxx
+++ b/sax/source/fastparser/fastparser.hxx
@@ -58,8 +58,8 @@ struct NameWithToken
 {
     OUString msName;
     sal_Int32 mnToken;
-    NameWithToken(const OUString& sName, const sal_Int32& nToken):
-        msName(sName), mnToken(nToken) {}
+
+    NameWithToken(const OUString& sName, const sal_Int32& nToken);
 };
 
 typedef std::vector<Event> EventList;
@@ -193,9 +193,9 @@ public:
             const XML_Char *systemId, const XML_Char *publicId,
             const XML_Char *notationName);
 
-    void pushEntity( const Entity& rEntity ) { maEntities.push( rEntity ); }
-    void popEntity()                         { maEntities.pop(); }
-    Entity& getEntity()                             { return maEntities.top(); }
+    void pushEntity( const Entity& rEntity );
+    void popEntity();
+    Entity& getEntity();
     void parse();
     void produce( CallbackType aType );
 
commit 2fff625c608eff5960d4c7e68e3d671580716bec
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Dec 2 17:19:49 2013 -0500

    Move this out of the namespace scope.
    
    Change-Id: I4aec1d45edb47ea16adaa8d2ac23340b8f421bae

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index afe9454..caf4ec1 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -40,6 +40,45 @@ using namespace ::com::sun::star::lang;
 using namespace ::com::sun::star::xml::sax;
 using namespace ::com::sun::star::io;
 
+extern "C" {
+
+static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
+{
+    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
+    pFastParser->callbackStartElement( name, atts );
+}
+
+static void call_callbackEndElement(void *userData, const XML_Char *name)
+{
+    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
+    pFastParser->callbackEndElement( name );
+}
+
+static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
+{
+    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( userData );
+    pFastParser->callbackCharacters( s, nLen );
+}
+
+static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
+        int is_parameter_entity, const XML_Char *value, int value_length,
+        const XML_Char *base, const XML_Char *systemId,
+        const XML_Char *publicId, const XML_Char *notationName)
+{
+    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>(userData);
+    pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
+            value_length, base, systemId, publicId, notationName);
+}
+
+static int call_callbackExternalEntityRef( XML_Parser parser,
+        const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
+{
+    sax_fastparser::FastSaxParser* pFastParser = reinterpret_cast<sax_fastparser::FastSaxParser*>( XML_GetUserData( parser ) );
+    return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
+}
+
+} // extern "C"
+
 namespace sax_fastparser {
 
 SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
@@ -115,44 +154,6 @@ private:
 // the implementation part
 //---------------------------------------------
 
-extern "C" {
-
-static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
-{
-    FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
-    pFastParser->callbackStartElement( name, atts );
-}
-
-static void call_callbackEndElement(void *userData, const XML_Char *name)
-{
-    FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
-    pFastParser->callbackEndElement( name );
-}
-
-static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
-{
-    FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
-    pFastParser->callbackCharacters( s, nLen );
-}
-
-static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
-        int is_parameter_entity, const XML_Char *value, int value_length,
-        const XML_Char *base, const XML_Char *systemId,
-        const XML_Char *publicId, const XML_Char *notationName)
-{
-    FastSaxParser* pFastParser = reinterpret_cast<FastSaxParser*>(userData);
-    pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
-            value_length, base, systemId, publicId, notationName);
-}
-
-static int call_callbackExternalEntityRef( XML_Parser parser,
-        const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
-{
-    FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( XML_GetUserData( parser ) );
-    return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
-}
-
-} // extern "C"
 
 // --------------------------------------------------------------------
 // FastLocatorImpl implementation
diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx
index d2bf1a7..6888cef 100644
--- a/sax/source/fastparser/fastparser.hxx
+++ b/sax/source/fastparser/fastparser.hxx
@@ -193,8 +193,8 @@ public:
             const XML_Char *systemId, const XML_Char *publicId,
             const XML_Char *notationName);
 
-    inline void pushEntity( const Entity& rEntity ) { maEntities.push( rEntity ); }
-    inline void popEntity()                         { maEntities.pop(); }
+    void pushEntity( const Entity& rEntity ) { maEntities.push( rEntity ); }
+    void popEntity()                         { maEntities.pop(); }
     Entity& getEntity()                             { return maEntities.top(); }
     void parse();
     void produce( CallbackType aType );
commit eb82f53912cd8fa7866c23c3fd5cd4a5b7b791f8
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Wed Nov 27 09:47:40 2013 +0000

    fastparser: Outline virtual destructor to please MSVC++.
    
    Change-Id: I8368698e80e5ebe339b822a9e0e767e8ba867e07

diff --git a/include/sax/fastattribs.hxx b/include/sax/fastattribs.hxx
index f1f64dd..bb1b93d 100644
--- a/include/sax/fastattribs.hxx
+++ b/include/sax/fastattribs.hxx
@@ -53,7 +53,7 @@ typedef std::vector< UnknownAttribute > UnknownAttributeList;
 class SAX_DLLPUBLIC FastTokenHandlerBase
 {
     public:
-        virtual ~FastTokenHandlerBase() {}
+        virtual ~FastTokenHandlerBase();
         virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const = 0;
 };
 
diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx
index bc63b3e..595c736 100644
--- a/sax/source/tools/fastattribs.cxx
+++ b/sax/source/tools/fastattribs.cxx
@@ -27,6 +27,11 @@ using namespace ::com::sun::star::xml::sax;
 namespace sax_fastparser
 {
 
+// wasteage to keep MSVC happy vs. an in-line {}
+FastTokenHandlerBase::FastTokenHandlerBase()
+{
+}
+
 UnknownAttribute::UnknownAttribute( const OUString& rNamespaceURL, const OString& rName, const sal_Char* pValue )
     : maNamespaceURL( rNamespaceURL ), maName( rName ), maValue( pValue )
 {
commit 581686cd0f07b7ae6c6fb8b42c25d459f1c86402
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Nov 26 17:39:26 2013 +0000

    fastparser: strncmp needs a length.
    
    Conflicts:
    	sax/source/fastparser/fastparser.cxx
    
    Change-Id: I11a92d59ca5e973ed79e6a799a2ca5fa532a2b65

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 1bfb15e..afe9454 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -950,7 +950,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
             assert(awAttributes[i+1]);
 
             if( awAttributes[i][0] != 'x' ||
-                strncmp( awAttributes[i], "xmlns") != 0 )
+                strncmp( awAttributes[i], "xmlns", 5) != 0 )
                 continue;
 
             splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
commit b5b9a664f5fc04229a657167d7143bb9d3d7d899
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Nov 26 17:26:01 2013 +0000

    oox: accelerate common case boolean reading.

diff --git a/oox/source/helper/attributelist.cxx b/oox/source/helper/attributelist.cxx
index 2efc3a3..8f0707a 100644
--- a/oox/source/helper/attributelist.cxx
+++ b/oox/source/helper/attributelist.cxx
@@ -201,6 +201,19 @@ OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const
 
 OptValue< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const
 {
+    const char *pAttr;
+
+    // catch the common cases as quickly as possible first
+    bool bHasAttr = getAttribList()->getAsChar( nAttrToken, pAttr );
+    if( !bHasAttr )
+        return OptValue< bool >();
+    if( !strcmp( pAttr, "false" ) )
+        return OptValue< bool >( false );
+    if( !strcmp( pAttr, "true" ) )
+        return OptValue< bool >( true );
+
+    // now for all the crazy stuff
+
     // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0"
     switch( getToken( nAttrToken, XML_TOKEN_INVALID ) )
     {
commit b9c38039f44861801ce3221f6383517a5c342f6e
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Nov 26 17:25:37 2013 +0000

    fastparser: special case xmlns more sensibly.

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 4c75e0c..1bfb15e 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -949,6 +949,10 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
         {
             assert(awAttributes[i+1]);
 
+            if( awAttributes[i][0] != 'x' ||
+                strncmp( awAttributes[i], "xmlns") != 0 )
+                continue;
+
             splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
             if( nPrefixLen )
             {
commit 16a38eb854d2303e9a723651c3ab66897efe03d0
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Nov 26 16:26:12 2013 +0000

    fastparser: Avoid copying all tokens into a sequence.

diff --git a/include/oox/core/fasttokenhandler.hxx b/include/oox/core/fasttokenhandler.hxx
index b79472c..fb4e0e1 100644
--- a/include/oox/core/fasttokenhandler.hxx
+++ b/include/oox/core/fasttokenhandler.hxx
@@ -23,6 +23,7 @@
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
 #include <cppuhelper/implbase2.hxx>
+#include <sax/fastattribs.hxx>
 
 namespace oox { class TokenMap; }
 
@@ -36,7 +37,8 @@ typedef ::cppu::WeakImplHelper2< ::com::sun::star::lang::XServiceInfo, ::com::su
 /** Wrapper implementing the com.sun.star.xml.sax.XFastTokenHandler API interface
     that provides access to the tokens generated from the internal token name list.
  */
-class FastTokenHandler : public FastTokenHandler_BASE
+class FastTokenHandler : public FastTokenHandler_BASE,
+                         public sax_fastparser::FastTokenHandlerBase
 {
 public:
     explicit            FastTokenHandler();
@@ -53,6 +55,9 @@ public:
     virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getUTF8Identifier( sal_Int32 nToken ) throw (::com::sun::star::uno::RuntimeException);
     virtual sal_Int32 SAL_CALL getTokenFromUTF8( const ::com::sun::star::uno::Sequence< sal_Int8 >& Identifier ) throw (::com::sun::star::uno::RuntimeException);
 
+    // Much faster direct C++ shortcut to the method that matters
+    virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const;
+
 private:
     const TokenMap&     mrTokenMap;     ///< Reference to global token map singleton.
 };
diff --git a/include/oox/token/tokenmap.hxx b/include/oox/token/tokenmap.hxx
index 495fa2d..bddc0ce 100644
--- a/include/oox/token/tokenmap.hxx
+++ b/include/oox/token/tokenmap.hxx
@@ -47,9 +47,29 @@ public:
 
     /** Returns the token identifier for the passed UTF8 token name. */
     sal_Int32           getTokenFromUtf8(
-                            const ::com::sun::star::uno::Sequence< sal_Int8 >& rUtf8Name ) const;
+                            const ::com::sun::star::uno::Sequence< sal_Int8 >& rUtf8Name ) const
+    {
+        return getTokenFromUTF8( reinterpret_cast< const char * >(
+                                rUtf8Name.getConstArray() ),
+                             rUtf8Name.getLength() );
+    }
+
+    /** Returns the token identifier for a UTF8 string passed in pToken */
+    sal_Int32 getTokenFromUTF8( const char *pToken, sal_Int32 nLength ) const
+    {
+        // 50% of OOXML tokens are primarily 1 lower-case character, a-z
+        if( nLength == 1)
+        {
+            sal_Char c = pToken[0];
+            if (c >= 'a' && c <= 'z')
+                return mnAlphaTokens[ c - 'a' ];
+        }
+        return getTokenPerfectHash( pToken, nLength );
+    }
 
 private:
+    sal_Int32 getTokenPerfectHash( const char *pToken, sal_Int32 nLength ) const;
+
     struct TokenName
     {
         OUString maUniName;
diff --git a/include/sax/fastattribs.hxx b/include/sax/fastattribs.hxx
index 42b285c..f1f64dd 100644
--- a/include/sax/fastattribs.hxx
+++ b/include/sax/fastattribs.hxx
@@ -49,6 +49,14 @@ struct UnknownAttribute
 
 typedef std::vector< UnknownAttribute > UnknownAttributeList;
 
+/// A native C++ interface to tokenisation
+class SAX_DLLPUBLIC FastTokenHandlerBase
+{
+    public:
+        virtual ~FastTokenHandlerBase() {}
+        virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const = 0;
+};
+
 /// avoid constantly allocating and freeing sequences.
 class SAX_DLLPUBLIC FastTokenLookup
 {
@@ -58,13 +66,15 @@ public:
     FastTokenLookup();
     sal_Int32 getTokenFromChars(
         const ::css::uno::Reference< ::css::xml::sax::XFastTokenHandler > &mxTokenHandler,
+        FastTokenHandlerBase *pTokenHandler,
         const char *pStr, size_t nLength = 0 );
 };
 
 class SAX_DLLPUBLIC FastAttributeList : public ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastAttributeList >
 {
 public:
-    FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler );
+    FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler,
+                       FastTokenHandlerBase *pOptHandlerBase = NULL );
     virtual ~FastAttributeList();
 
     void clear();
@@ -100,6 +110,8 @@ private:
     std::vector< sal_Int32 > maAttributeTokens;
     UnknownAttributeList maUnknownAttributes;
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler > mxTokenHandler;
+    FastTokenHandlerBase *mpTokenHandler;
+
     FastTokenLookup maTokenLookup;
 };
 
diff --git a/oox/source/core/fasttokenhandler.cxx b/oox/source/core/fasttokenhandler.cxx
index f57739c..5102408 100644
--- a/oox/source/core/fasttokenhandler.cxx
+++ b/oox/source/core/fasttokenhandler.cxx
@@ -92,6 +92,11 @@ sal_Int32 FastTokenHandler::getTokenFromUTF8( const Sequence< sal_Int8 >& rIdent
     return mrTokenMap.getTokenFromUtf8( rIdentifier );
 }
 
+sal_Int32 FastTokenHandler::getTokenDirect( const char *pToken, sal_Int32 nLength ) const
+{
+    return mrTokenMap.getTokenFromUTF8( pToken, nLength );
+}
+
 // ============================================================================
 
 } // namespace core
diff --git a/oox/source/token/tokenmap.cxx b/oox/source/token/tokenmap.cxx
index ea3e621e..7728b26 100644
--- a/oox/source/token/tokenmap.cxx
+++ b/oox/source/token/tokenmap.cxx
@@ -113,17 +113,9 @@ Sequence< sal_Int8 > TokenMap::getUtf8TokenName( sal_Int32 nToken ) const
     return Sequence< sal_Int8 >();
 }
 
-sal_Int32 TokenMap::getTokenFromUtf8( const Sequence< sal_Int8 >& rUtf8Name ) const
+sal_Int32 TokenMap::getTokenPerfectHash( const char *pStr, sal_Int32 nLength ) const
 {
-    // 50% of OOXML tokens are primarily 1 lower-case character, a-z
-    if( rUtf8Name.getLength() == 1)
-    {
-        sal_Char c = rUtf8Name[0];
-        if (c >= 'a' && c <= 'z')
-            return mnAlphaTokens[ c - 'a' ];
-    }
-    struct xmltoken* pToken = Perfect_Hash::in_word_set(
-        reinterpret_cast< const char* >( rUtf8Name.getConstArray() ), rUtf8Name.getLength() );
+    struct xmltoken* pToken = Perfect_Hash::in_word_set( pStr, nLength );
     return pToken ? pToken->nToken : XML_TOKEN_INVALID;
 }
 
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 415747c..4c75e0c 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -190,6 +190,7 @@ OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException)
 // --------------------------------------------------------------------
 
 ParserData::ParserData()
+    : mpTokenHandler( NULL )
 {}
 
 ParserData::~ParserData()
@@ -382,7 +383,9 @@ void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNa
 
 sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
 {
-    return maTokenLookup.getTokenFromChars( getEntity().mxTokenHandler, pToken, nLen );
+    return maTokenLookup.getTokenFromChars( getEntity().mxTokenHandler,
+                                            getEntity().mpTokenHandler,
+                                            pToken, nLen );
 }
 
 // --------------------------------------------------------------------
@@ -623,9 +626,10 @@ void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandle
     maData.mxDocumentHandler = Handler;
 }
 
-void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& Handler ) throw (RuntimeException)
+void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
 {
-    maData.mxTokenHandler = Handler;
+    maData.mxTokenHandler = xHandler;
+    maData.mpTokenHandler = dynamic_cast< FastTokenHandlerBase *>( xHandler.get() );
 }
 
 void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
@@ -918,7 +922,9 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
     if (rEvent.mxAttributes.is())
         rEvent.mxAttributes->clear();
     else
-        rEvent.mxAttributes.set( new FastAttributeList( rEntity.mxTokenHandler ) );
+        rEvent.mxAttributes.set(
+                new FastAttributeList( rEntity.mxTokenHandler,
+                                       rEntity.mpTokenHandler ) );
 
     sal_Int32 nNameLen, nPrefixLen;
     const XML_Char *pName;
diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx
index 35deb0c..d2bf1a7 100644
--- a/sax/source/fastparser/fastparser.hxx
+++ b/sax/source/fastparser/fastparser.hxx
@@ -92,6 +92,7 @@ struct ParserData
 {
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >    mxTokenHandler;
+    FastTokenHandlerBase *mpTokenHandler;
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >        mxErrorHandler;
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >      mxEntityResolver;
     ::com::sun::star::lang::Locale          maLocale;
diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx
index ee65cc6..bc63b3e 100644
--- a/sax/source/tools/fastattribs.cxx
+++ b/sax/source/tools/fastattribs.cxx
@@ -47,8 +47,10 @@ void UnknownAttribute::FillAttribute( Attribute* pAttrib ) const
     }
 }
 
-FastAttributeList::FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler )
-: mxTokenHandler( xTokenHandler )
+FastAttributeList::FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler,
+                                      sax_fastparser::FastTokenHandlerBase *pTokenHandler)
+: mxTokenHandler( xTokenHandler ),
+  mpTokenHandler( pTokenHandler )
 {
     // random initial size of buffer to store attribute values
     mnChunkLength = 58;
@@ -114,7 +116,7 @@ sal_Int32 FastAttributeList::getValueToken( ::sal_Int32 Token ) throw (SAXExcept
 {
     for (size_t i = 0; i < maAttributeTokens.size(); ++i)
         if (maAttributeTokens[i] == Token)
-            return maTokenLookup.getTokenFromChars( mxTokenHandler,
+            return maTokenLookup.getTokenFromChars( mxTokenHandler, mpTokenHandler,
                                                     mpChunk + maAttributeValues[ i ],
                                                     AttributeValueLength( i ) );
 
@@ -125,7 +127,7 @@ sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int
 {
     for (size_t i = 0; i < maAttributeTokens.size(); ++i)
         if (maAttributeTokens[i] == Token)
-            return maTokenLookup.getTokenFromChars( mxTokenHandler,
+            return maTokenLookup.getTokenFromChars( mxTokenHandler, mpTokenHandler,
                                                     mpChunk + maAttributeValues[ i ],
                                                     AttributeValueLength( i ) );
 
@@ -227,6 +229,7 @@ FastTokenLookup::FastTokenLookup()
  */
 sal_Int32 FastTokenLookup::getTokenFromChars(
         const ::css::uno::Reference< ::css::xml::sax::XFastTokenHandler > &xTokenHandler,
+        FastTokenHandlerBase *pTokenHandler,
         const char *pToken, size_t nLen /* = 0 */ )
 {
     sal_Int32 nRet;
@@ -234,23 +237,12 @@ sal_Int32 FastTokenLookup::getTokenFromChars(
     if( !nLen )
         nLen = strlen( pToken );
 
-    if ( static_cast<sal_Int32>(nLen) < mnUtf8BufferSize )
-    {
-        // Get intimate with the underlying sequence cf. sal/types.h
-        sal_Sequence *pSeq = maUtf8Buffer.get();
-
-        sal_Int32 nPreRefCount = pSeq->nRefCount;
-
-        pSeq->nElements = nLen;
-        memcpy( pSeq->elements, pToken, nLen );
-        nRet = xTokenHandler->getTokenFromUTF8( maUtf8Buffer );
-
-        (void)nPreRefCount; // for non-debug mode.
-        assert( pSeq->nRefCount == nPreRefCount ); // callee must not take ref
-    }
+    if( pTokenHandler )
+        nRet = pTokenHandler->getTokenDirect( pToken, (sal_Int32) nLen );
     else
     {
-        Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen ); // heap allocate & free
+        // heap allocate, copy & then free
+        Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen );
         nRet = xTokenHandler->getTokenFromUTF8( aSeq );
     }
 
diff --git a/writerfilter/source/ooxml/OOXMLFastTokenHandler.cxx b/writerfilter/source/ooxml/OOXMLFastTokenHandler.cxx
index 096de7f..4cf32f5 100644
--- a/writerfilter/source/ooxml/OOXMLFastTokenHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastTokenHandler.cxx
@@ -108,23 +108,16 @@ css::uno::Sequence< ::sal_Int8 > SAL_CALL OOXMLFastTokenHandler::getUTF8Identifi
 #endif
 }
 
-::sal_Int32 SAL_CALL OOXMLFastTokenHandler::getTokenFromUTF8
-(const css::uno::Sequence< ::sal_Int8 > & Identifier) throw (css::uno::RuntimeException)
+::sal_Int32 SAL_CALL OOXMLFastTokenHandler::getTokenDirect( const char *pStr, sal_Int32 nLength ) const
 {
-    ::sal_Int32 nResult = OOXML_FAST_TOKENS_END;
-
     struct tokenmap::token * pToken =
-        tokenmap::Perfect_Hash::in_word_set
-        (reinterpret_cast<const char *>(Identifier.getConstArray()),
-         Identifier.getLength());
+        tokenmap::Perfect_Hash::in_word_set( pStr, nLength );
 
-    if (pToken != NULL)
-        nResult = pToken->nToken;
+    sal_Int32 nResult = pToken != NULL ? pToken->nToken : OOXML_FAST_TOKENS_END;
 
 #ifdef DEBUG_TOKEN
     clog << "getTokenFromUTF8: "
-         << string(reinterpret_cast<const char *>
-                   (Identifier.getConstArray()), Identifier.getLength())
+         << string(pStr, nLength)
          << ", " << nResult
          << (pToken == NULL ? ", failed" : "") << endl;
 #endif
@@ -132,6 +125,14 @@ css::uno::Sequence< ::sal_Int8 > SAL_CALL OOXMLFastTokenHandler::getUTF8Identifi
     return nResult;
 }
 
+::sal_Int32 SAL_CALL OOXMLFastTokenHandler::getTokenFromUTF8
+(const css::uno::Sequence< ::sal_Int8 > & Identifier) throw (css::uno::RuntimeException)
+{
+    return getTokenDirect(reinterpret_cast<const char *>
+                          (Identifier.getConstArray()),
+                          Identifier.getLength());
+}
+
 }}
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/ooxml/OOXMLFastTokenHandler.hxx b/writerfilter/source/ooxml/OOXMLFastTokenHandler.hxx
index 120c4e7..ddb5b50 100644
--- a/writerfilter/source/ooxml/OOXMLFastTokenHandler.hxx
+++ b/writerfilter/source/ooxml/OOXMLFastTokenHandler.hxx
@@ -24,6 +24,7 @@
 #include "com/sun/star/uno/XComponentContext.hpp"
 #include "cppuhelper/implbase1.hxx"
 #include "com/sun/star/xml/sax/XFastTokenHandler.hpp"
+#include "sax/fastattribs.hxx"
 
 namespace writerfilter {
 namespace ooxml
@@ -31,7 +32,8 @@ namespace ooxml
 
 class OOXMLFastTokenHandler:
     public ::cppu::WeakImplHelper1<
-        css::xml::sax::XFastTokenHandler>
+        css::xml::sax::XFastTokenHandler>,
+    public sax_fastparser::FastTokenHandlerBase
 {
 public:
     explicit OOXMLFastTokenHandler(css::uno::Reference< css::uno::XComponentContext > const & context);
@@ -42,6 +44,9 @@ public:
     virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getUTF8Identifier(::sal_Int32 Token) throw (css::uno::RuntimeException);
     virtual ::sal_Int32 SAL_CALL getTokenFromUTF8(const css::uno::Sequence< ::sal_Int8 > & Identifier) throw (css::uno::RuntimeException);
 
+    // Much faster direct C++ shortcut to the method that matters
+    virtual sal_Int32 getTokenDirect( const char *pToken, sal_Int32 nLength ) const;
+
 private:
     OOXMLFastTokenHandler(OOXMLFastTokenHandler &); // not defined
     void operator =(OOXMLFastTokenHandler &); // not defined
commit 0e652adef5bda6438d1b9084397fc5c43e5dd21a
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Nov 26 13:11:44 2013 +0000

    fastparser: don't waste cycles churning reference counts.

diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index da224d0..415747c 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -227,18 +227,20 @@ void Entity::startElement( Event *pEvent )
     const sal_Int32& nElementToken = pEvent->mnElementToken;
     const OUString& aNamespace = pEvent->msNamespace;
     const OUString& aElementName = pEvent->msElementName;
-    Reference< XFastContextHandler > xParentContext;
+
+    // Use un-wrapped pointers to avoid significant acquire/release overhead
+    XFastContextHandler *pParentContext = NULL;
     if( !maContextStack.empty() )
     {
-        xParentContext = maContextStack.top().mxContext;
-        if (!xParentContext.is())
+        pParentContext = maContextStack.top().mxContext.get();
+        if( !pParentContext )
         {
             maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
             return;
         }
     }
 
-    maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
+    maContextStack.push( SaxContext( nElementToken, aNamespace, aElementName ) );
 
     try
     {
@@ -246,8 +248,8 @@ void Entity::startElement( Event *pEvent )
         Reference< XFastContextHandler > xContext;
         if( nElementToken == FastToken::DONTKNOW )
         {
-            if( xParentContext.is() )
-                xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
+            if( pParentContext )
+                xContext = pParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
             else if( mxDocumentHandler.is() )
                 xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
 
@@ -258,17 +260,17 @@ void Entity::startElement( Event *pEvent )
         }
         else
         {
-            if( xParentContext.is() )
-                xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
+            if( pParentContext )
+                xContext = pParentContext->createFastChildContext( nElementToken, xAttr );
             else if( mxDocumentHandler.is() )
                 xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
 
             if( xContext.is() )
-            {
                 xContext->startFastElement( nElementToken, xAttr );
-            }
         }
-        maContextStack.top().mxContext = xContext;
+        // swap the reference we own in to avoid referencing thrash.
+        maContextStack.top().mxContext.set( static_cast<XFastContextHandler *>( xContext.get() ) );
+        xContext.set( NULL, UNO_REF_NO_ACQUIRE );
     }
     catch (const Exception& e)
     {


More information about the Libreoffice-commits mailing list