LCOV - code coverage report
Current view: top level - sax/source/fastparser - fastparser.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 457 612 74.7 %
Date: 2014-11-03 Functions: 73 93 78.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "sax/fastparser.hxx"
      21             : #include "sax/fastattribs.hxx"
      22             : #include "xml2utf.hxx"
      23             : 
      24             : #include <com/sun/star/lang/DisposedException.hpp>
      25             : #include <com/sun/star/uno/XComponentContext.hpp>
      26             : #include <com/sun/star/xml/sax/FastToken.hpp>
      27             : #include <com/sun/star/xml/sax/SAXParseException.hpp>
      28             : #include <com/sun/star/xml/sax/XFastContextHandler.hpp>
      29             : #include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
      30             : #include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
      31             : #include <cppuhelper/supportsservice.hxx>
      32             : #include <osl/conditn.hxx>
      33             : #include <osl/diagnose.h>
      34             : #include <rtl/ref.hxx>
      35             : #include <rtl/ustrbuf.hxx>
      36             : #include <salhelper/thread.hxx>
      37             : 
      38             : #include <boost/optional.hpp>
      39             : #include <boost/scoped_ptr.hpp>
      40             : #include <boost/shared_ptr.hpp>
      41             : #include <boost/unordered_map.hpp>
      42             : #include <stack>
      43             : #include <vector>
      44             : #include <queue>
      45             : #include <cassert>
      46             : #include <cstring>
      47             : #include <expat.h>
      48             : 
      49             : using namespace ::std;
      50             : using namespace ::osl;
      51             : using namespace ::cppu;
      52             : using namespace ::com::sun::star::uno;
      53             : using namespace ::com::sun::star::lang;
      54             : using namespace ::com::sun::star::xml::sax;
      55             : using namespace ::com::sun::star::io;
      56             : using namespace com::sun::star;
      57             : using namespace sax_fastparser;
      58             : 
      59             : namespace {
      60             : 
      61             : struct Event;
      62             : class FastLocatorImpl;
      63             : struct NamespaceDefine;
      64             : struct Entity;
      65             : 
      66             : typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
      67             : 
      68             : typedef ::boost::unordered_map< OUString, sal_Int32,
      69             :         OUStringHash, ::std::equal_to< OUString > > NamespaceMap;
      70             : 
      71             : typedef std::vector<Event> EventList;
      72             : 
      73             : enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION };
      74             : 
      75     6321480 : struct Event
      76             : {
      77             :     CallbackType maType;
      78             :     sal_Int32 mnElementToken;
      79             :     OUString msNamespace;
      80             :     OUString msElementName;
      81             :     rtl::Reference< FastAttributeList > mxAttributes;
      82             :     OUString msChars;
      83             : };
      84             : 
      85    13347300 : struct NameWithToken
      86             : {
      87             :     OUString msName;
      88             :     sal_Int32 mnToken;
      89             : 
      90     4449099 :     NameWithToken(const OUString& sName, const sal_Int32& nToken) :
      91     4449099 :         msName(sName), mnToken(nToken) {}
      92             : };
      93             : 
      94    13347298 : struct SaxContext
      95             : {
      96             :     Reference< XFastContextHandler > mxContext;
      97             :     sal_Int32 mnElementToken;
      98             :     OUString  maNamespace;
      99             :     OUString  maElementName;
     100             : 
     101     4449099 :     SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
     102     4449099 :             mnElementToken(nElementToken)
     103             :     {
     104     4449099 :         if (nElementToken == FastToken::DONTKNOW)
     105             :         {
     106       14070 :             maNamespace = aNamespace;
     107       14070 :             maElementName = aElementName;
     108             :         }
     109     4449099 :     }
     110             : };
     111             : 
     112             : 
     113       77740 : struct ParserData
     114             : {
     115             :     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
     116             :     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >    mxTokenHandler;
     117             :     FastTokenHandlerBase *mpTokenHandler;
     118             :     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >        mxErrorHandler;
     119             :     ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >      mxEntityResolver;
     120             :     ::com::sun::star::lang::Locale          maLocale;
     121             : 
     122             :     ParserData();
     123             :     ~ParserData();
     124             : };
     125             : 
     126      191984 : struct NamespaceDefine
     127             : {
     128             :     OString     maPrefix;
     129             :     sal_Int32   mnToken;
     130             :     OUString    maNamespaceURL;
     131             : 
     132      191984 :     NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
     133             : };
     134             : 
     135             : // Entity binds all information needed for a single file | single call of parseStream
     136             : struct Entity : public ParserData
     137             : {
     138             :     // Amount of work producer sends to consumer in one iteration:
     139             :     static const size_t mnEventListSize = 1000;
     140             : 
     141             :     // unique for each Entity instance:
     142             : 
     143             :     // Number of valid events in mpProducedEvents:
     144             :     size_t mnProducedEventsSize;
     145             :     EventList *mpProducedEvents;
     146             :     std::queue< EventList * > maPendingEvents;
     147             :     std::queue< EventList * > maUsedEvents;
     148             :     osl::Mutex maEventProtector;
     149             : 
     150             :     static const size_t mnEventLowWater = 4;
     151             :     static const size_t mnEventHighWater = 8;
     152             :     osl::Condition maConsumeResume;
     153             :     osl::Condition maProduceResume;
     154             :     // Event we use to store data if threading is disabled:
     155             :     Event maSharedEvent;
     156             : 
     157             :     // copied in copy constructor:
     158             : 
     159             :     // Allow to disable threading for small documents:
     160             :     bool                                    mbEnableThreads;
     161             :     ::com::sun::star::xml::sax::InputSource maStructSource;
     162             :     XML_Parser                              mpParser;
     163             :     ::sax_expatwrap::XMLFile2UTFConverter   maConverter;
     164             : 
     165             :     // Exceptions cannot be thrown through the C-XmlParser (possible
     166             :     // resource leaks), therefore any exception thrown by a UNO callback
     167             :     // must be saved somewhere until the C-XmlParser is stopped.
     168             :     ::com::sun::star::uno::Any maSavedException;
     169             :     void saveException( const Exception &e );
     170             :     void throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
     171             :                          bool mbDuringParse );
     172             : 
     173             :     ::std::stack< NameWithToken >           maNamespaceStack;
     174             :     /* Context for main thread consuming events.
     175             :      * startElement() stores the data, which characters() and endElement() uses
     176             :      */
     177             :     ::std::stack< SaxContext>               maContextStack;
     178             :     // Determines which elements of maNamespaceDefines are valid in current context
     179             :     ::std::stack< sal_uInt32 >              maNamespaceCount;
     180             :     ::std::vector< NamespaceDefineRef >     maNamespaceDefines;
     181             : 
     182             :     explicit Entity( const ParserData& rData );
     183             :     Entity( const Entity& rEntity );
     184             :     ~Entity();
     185             :     void startElement( Event *pEvent );
     186             :     void characters( const OUString& sChars );
     187             :     void endElement();
     188             :     EventList* getEventList();
     189             :     Event& getEvent( CallbackType aType );
     190             : };
     191             : 
     192             : } // namespace
     193             : 
     194             : namespace sax_fastparser {
     195             : 
     196             : class FastSaxParserImpl
     197             : {
     198             : public:
     199             :     FastSaxParserImpl( FastSaxParser* pFront );
     200             :     ~FastSaxParserImpl();
     201             : 
     202             :     // XFastParser
     203             :     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, std::exception);
     204             :     void setFastDocumentHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
     205             :     void setTokenHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
     206             :     void registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
     207             :     OUString getNamespaceURL( const OUString& rPrefix ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
     208             :     void setErrorHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XErrorHandler >& Handler ) throw (::com::sun::star::uno::RuntimeException);
     209             :     void setEntityResolver( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XEntityResolver >& Resolver ) throw (::com::sun::star::uno::RuntimeException);
     210             :     void setLocale( const ::com::sun::star::lang::Locale& rLocale ) throw (::com::sun::star::uno::RuntimeException);
     211             : 
     212             :     // called by the C callbacks of the expat parser
     213             :     void callbackStartElement( const XML_Char* name, const XML_Char** atts );
     214             :     void callbackEndElement( const XML_Char* name );
     215             :     void callbackCharacters( const XML_Char* s, int nLen );
     216             :     bool callbackExternalEntityRef( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId);
     217             :     void callbackEntityDecl(const XML_Char *entityName, int is_parameter_entity,
     218             :             const XML_Char *value, int value_length, const XML_Char *base,
     219             :             const XML_Char *systemId, const XML_Char *publicId,
     220             :             const XML_Char *notationName);
     221             : 
     222             :     void pushEntity( const Entity& rEntity );
     223             :     void popEntity();
     224    46018919 :     Entity& getEntity()             { return *mpTop; }
     225           0 :     const Entity& getEntity() const { return *mpTop; }
     226             :     void parse();
     227             :     void produce( bool bForceFlush = false );
     228             : 
     229             :     bool hasNamespaceURL( const OUString& rPrefix ) const;
     230             : 
     231             : private:
     232             :     bool consume(EventList *);
     233             :     void deleteUsedEvents();
     234             : 
     235             :     sal_Int32 GetToken( const sal_Char* pToken, sal_Int32 nTokenLen = 0 );
     236             :     sal_Int32 GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (::com::sun::star::xml::sax::SAXException);
     237             :     OUString GetNamespaceURL( const OString& rPrefix ) throw (::com::sun::star::xml::sax::SAXException);
     238             :     OUString GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw (::com::sun::star::xml::sax::SAXException);
     239             :     sal_Int32 GetNamespaceToken( const OUString& rNamespaceURL );
     240             :     sal_Int32 GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen );
     241             :     void DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL );
     242             : 
     243             :     void splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen );
     244             : 
     245             : private:
     246             :     FastSaxParser* mpFront;
     247             : 
     248             :     osl::Mutex maMutex; ///< Protecting whole parseStream() execution
     249             :     ::rtl::Reference< FastLocatorImpl >     mxDocumentLocator;
     250             :     NamespaceMap                            maNamespaceMap;
     251             : 
     252             :     ParserData maData;                      /// Cached parser configuration for next call of parseStream().
     253             : 
     254             :     Entity *mpTop;                          /// std::stack::top() is amazingly slow => cache this.
     255             :     ::std::stack< Entity > maEntities;      /// Entity stack for each call of parseStream().
     256             : };
     257             : 
     258             : } // namespace sax_fastparser
     259             : 
     260             : namespace {
     261             : 
     262        5716 : class ParserThread: public salhelper::Thread
     263             : {
     264             :     FastSaxParserImpl *mpParser;
     265             : public:
     266        2858 :     ParserThread(FastSaxParserImpl *pParser): Thread("Parser"), mpParser(pParser) {}
     267             : private:
     268        2858 :     virtual void execute() SAL_OVERRIDE
     269             :     {
     270             :         try
     271             :         {
     272        2858 :             mpParser->parse();
     273             :         }
     274           0 :         catch (const Exception &)
     275             :         {
     276           0 :             Entity &rEntity = mpParser->getEntity();
     277           0 :             rEntity.getEvent( EXCEPTION );
     278           0 :             mpParser->produce( true );
     279             :         }
     280        2858 :     }
     281             : };
     282             : 
     283             : extern "C" {
     284             : 
     285     4449100 : static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
     286             : {
     287     4449100 :     FastSaxParserImpl* pFastParser = reinterpret_cast<FastSaxParserImpl*>( userData );
     288     4449100 :     pFastParser->callbackStartElement( name, atts );
     289     4449100 : }
     290             : 
     291     4449074 : static void call_callbackEndElement(void *userData, const XML_Char *name)
     292             : {
     293     4449074 :     FastSaxParserImpl* pFastParser = reinterpret_cast<FastSaxParserImpl*>( userData );
     294     4449074 :     pFastParser->callbackEndElement( name );
     295     4449074 : }
     296             : 
     297      432284 : static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
     298             : {
     299      432284 :     FastSaxParserImpl* pFastParser = reinterpret_cast<FastSaxParserImpl*>( userData );
     300      432284 :     pFastParser->callbackCharacters( s, nLen );
     301      432284 : }
     302             : 
     303           0 : static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
     304             :         int is_parameter_entity, const XML_Char *value, int value_length,
     305             :         const XML_Char *base, const XML_Char *systemId,
     306             :         const XML_Char *publicId, const XML_Char *notationName)
     307             : {
     308           0 :     FastSaxParserImpl* pFastParser = reinterpret_cast<FastSaxParserImpl*>(userData);
     309             :     pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
     310           0 :             value_length, base, systemId, publicId, notationName);
     311           0 : }
     312             : 
     313           0 : static int call_callbackExternalEntityRef( XML_Parser parser,
     314             :         const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
     315             : {
     316           0 :     FastSaxParserImpl* pFastParser = reinterpret_cast<FastSaxParserImpl*>( XML_GetUserData( parser ) );
     317           0 :     return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
     318             : }
     319             : 
     320             : }
     321             : 
     322      105944 : class FastLocatorImpl : public WeakImplHelper1< XLocator >
     323             : {
     324             : public:
     325       52972 :     FastLocatorImpl( FastSaxParserImpl *p ) : mpParser(p) {}
     326             : 
     327       52972 :     void dispose() { mpParser = 0; }
     328          72 :     void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
     329             : 
     330             :     //XLocator
     331             :     virtual sal_Int32 SAL_CALL getColumnNumber(void) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     332             :     virtual sal_Int32 SAL_CALL getLineNumber(void) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     333             :     virtual OUString SAL_CALL getPublicId(void) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     334             :     virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException, std::exception) SAL_OVERRIDE;
     335             : 
     336             : private:
     337             :     FastSaxParserImpl *mpParser;
     338             : };
     339             : 
     340          12 : sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException, std::exception)
     341             : {
     342          12 :     checkDispose();
     343          12 :     return XML_GetCurrentColumnNumber( mpParser->getEntity().mpParser );
     344             : }
     345             : 
     346          24 : sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber(void) throw (RuntimeException, std::exception)
     347             : {
     348          24 :     checkDispose();
     349          24 :     return XML_GetCurrentLineNumber( mpParser->getEntity().mpParser );
     350             : }
     351             : 
     352          12 : OUString SAL_CALL FastLocatorImpl::getPublicId(void) throw (RuntimeException, std::exception)
     353             : {
     354          12 :     checkDispose();
     355          12 :     return mpParser->getEntity().maStructSource.sPublicId;
     356             : }
     357             : 
     358          24 : OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException, std::exception)
     359             : {
     360          24 :     checkDispose();
     361          24 :     return mpParser->getEntity().maStructSource.sSystemId;
     362             : }
     363             : 
     364       52972 : ParserData::ParserData()
     365       52972 :     : mpTokenHandler( NULL )
     366       52972 : {}
     367             : 
     368      130712 : ParserData::~ParserData()
     369      130712 : {}
     370             : 
     371       39050 : Entity::Entity(const ParserData& rData)
     372             :     : ParserData(rData)
     373             :     , mnProducedEventsSize(0)
     374             :     , mpProducedEvents(NULL)
     375             :     , mbEnableThreads(false)
     376       39050 :     , mpParser(NULL)
     377             : {
     378       39050 : }
     379             : 
     380       38690 : Entity::Entity(const Entity& e)
     381             :     : ParserData(e)
     382             :     , mnProducedEventsSize(0)
     383             :     , mpProducedEvents(NULL)
     384             :     , mbEnableThreads(e.mbEnableThreads)
     385             :     , maStructSource(e.maStructSource)
     386             :     , mpParser(e.mpParser)
     387             :     , maConverter(e.maConverter)
     388             :     , maSavedException(e.maSavedException)
     389             :     , maNamespaceStack(e.maNamespaceStack)
     390             :     , maContextStack(e.maContextStack)
     391             :     , maNamespaceCount(e.maNamespaceCount)
     392       38690 :     , maNamespaceDefines(e.maNamespaceDefines)
     393             : {
     394       38690 : }
     395             : 
     396       77740 : Entity::~Entity()
     397             : {
     398       77740 : }
     399             : 
     400     4449100 : void Entity::startElement( Event *pEvent )
     401             : {
     402     4449100 :     const sal_Int32& nElementToken = pEvent->mnElementToken;
     403     4449100 :     const OUString& aNamespace = pEvent->msNamespace;
     404     4449100 :     const OUString& aElementName = pEvent->msElementName;
     405             : 
     406             :     // Use un-wrapped pointers to avoid significant acquire/release overhead
     407     4449100 :     XFastContextHandler *pParentContext = NULL;
     408     4449100 :     if( !maContextStack.empty() )
     409             :     {
     410     4410410 :         pParentContext = maContextStack.top().mxContext.get();
     411     4410409 :         if( !pParentContext )
     412             :         {
     413      155940 :             maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
     414     4605040 :             return;
     415             :         }
     416             :     }
     417             : 
     418     4293159 :     maContextStack.push( SaxContext( nElementToken, aNamespace, aElementName ) );
     419             : 
     420             :     try
     421             :     {
     422     4293159 :         Reference< XFastAttributeList > xAttr( pEvent->mxAttributes.get() );
     423     8586320 :         Reference< XFastContextHandler > xContext;
     424     4293160 :         if( nElementToken == FastToken::DONTKNOW )
     425             :         {
     426       12618 :             if( pParentContext )
     427       11640 :                 xContext = pParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
     428         978 :             else if( mxDocumentHandler.is() )
     429         974 :                 xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
     430             : 
     431       12618 :             if( xContext.is() )
     432             :             {
     433       12100 :                 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
     434             :             }
     435             :         }
     436             :         else
     437             :         {
     438     4280542 :             if( pParentContext )
     439     4242830 :                 xContext = pParentContext->createFastChildContext( nElementToken, xAttr );
     440       37712 :             else if( mxDocumentHandler.is() )
     441       37712 :                 xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
     442             : 
     443     4280540 :             if( xContext.is() )
     444     4170128 :                 xContext->startFastElement( nElementToken, xAttr );
     445             :         }
     446             :         // swap the reference we own in to avoid referencing thrash.
     447     4293158 :         maContextStack.top().mxContext.set( static_cast<XFastContextHandler *>( xContext.get() ) );
     448     8586318 :         xContext.set( NULL, UNO_REF_NO_ACQUIRE );
     449             :     }
     450           2 :     catch (const Exception& e)
     451             :     {
     452           2 :         saveException( e );
     453             :     }
     454             : }
     455             : 
     456      432284 : void Entity::characters( const OUString& sChars )
     457             : {
     458      432284 :     const Reference< XFastContextHandler >& xContext( maContextStack.top().mxContext );
     459      432284 :     if( xContext.is() ) try
     460             :     {
     461      416342 :         xContext->characters( sChars );
     462             :     }
     463           0 :     catch (const Exception& e)
     464             :     {
     465           0 :         saveException( e );
     466             :     }
     467      432284 : }
     468             : 
     469     4449074 : void Entity::endElement()
     470             : {
     471     4449074 :     if (maContextStack.empty())
     472             :     {
     473             :         // Malformed XML stream !?
     474     4449074 :         return;
     475             :     }
     476             : 
     477     4449074 :     const SaxContext& aContext = maContextStack.top();
     478     4449074 :     const Reference< XFastContextHandler >& xContext( aContext.mxContext );
     479     4449074 :     if( xContext.is() ) try
     480             :     {
     481     4182204 :         sal_Int32 nElementToken = aContext.mnElementToken;
     482     4182204 :         if( nElementToken != FastToken::DONTKNOW )
     483     4170104 :             xContext->endFastElement( nElementToken );
     484             :         else
     485       12100 :             xContext->endUnknownElement( aContext.maNamespace, aContext.maElementName );
     486             :     }
     487          14 :     catch (const Exception& e)
     488             :     {
     489          14 :         saveException( e );
     490             :     }
     491     4449074 :     maContextStack.pop();
     492             : }
     493             : 
     494     2125336 : EventList* Entity::getEventList()
     495             : {
     496     2125336 :     if (!mpProducedEvents)
     497             :     {
     498        3500 :         osl::ResettableMutexGuard aGuard(maEventProtector);
     499        3500 :         if (!maUsedEvents.empty())
     500             :         {
     501         417 :             mpProducedEvents = maUsedEvents.front();
     502         417 :             maUsedEvents.pop();
     503         417 :             aGuard.clear(); // unlock
     504         417 :             mnProducedEventsSize = 0;
     505             :         }
     506        3500 :         if (!mpProducedEvents)
     507             :         {
     508        3083 :             mpProducedEvents = new EventList();
     509        3083 :             mpProducedEvents->resize(mnEventListSize);
     510        3083 :             mnProducedEventsSize = 0;
     511        3500 :         }
     512             :     }
     513     2125336 :     return mpProducedEvents;
     514             : }
     515             : 
     516     9369135 : Event& Entity::getEvent( CallbackType aType )
     517             : {
     518     9369135 :     if (!mbEnableThreads)
     519     7243799 :         return maSharedEvent;
     520             : 
     521     2125336 :     EventList* pEventList = getEventList();
     522     2125336 :     Event& rEvent = (*pEventList)[mnProducedEventsSize++];
     523     2125336 :     rEvent.maType = aType;
     524     2125336 :     return rEvent;
     525             : }
     526             : 
     527          12 : OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine )
     528             : {
     529          12 :     const sal_Char* pMessage = "";
     530          12 :     switch( xmlE )
     531             :     {
     532           6 :         case XML_ERROR_NONE:                            pMessage = "No";                                    break;
     533           0 :         case XML_ERROR_NO_MEMORY:                       pMessage = "no memory";                             break;
     534           0 :         case XML_ERROR_SYNTAX:                          pMessage = "syntax";                                break;
     535           0 :         case XML_ERROR_NO_ELEMENTS:                     pMessage = "no elements";                           break;
     536           0 :         case XML_ERROR_INVALID_TOKEN:                   pMessage = "invalid token";                         break;
     537           0 :         case XML_ERROR_UNCLOSED_TOKEN:                  pMessage = "unclosed token";                        break;
     538           0 :         case XML_ERROR_PARTIAL_CHAR:                    pMessage = "partial char";                          break;
     539           6 :         case XML_ERROR_TAG_MISMATCH:                    pMessage = "tag mismatch";                          break;
     540           0 :         case XML_ERROR_DUPLICATE_ATTRIBUTE:             pMessage = "duplicate attribute";                   break;
     541           0 :         case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:          pMessage = "junk after doc element";                break;
     542           0 :         case XML_ERROR_PARAM_ENTITY_REF:                pMessage = "parameter entity reference";            break;
     543           0 :         case XML_ERROR_UNDEFINED_ENTITY:                pMessage = "undefined entity";                      break;
     544           0 :         case XML_ERROR_RECURSIVE_ENTITY_REF:            pMessage = "recursive entity reference";            break;
     545           0 :         case XML_ERROR_ASYNC_ENTITY:                    pMessage = "async entity";                          break;
     546           0 :         case XML_ERROR_BAD_CHAR_REF:                    pMessage = "bad char reference";                    break;
     547           0 :         case XML_ERROR_BINARY_ENTITY_REF:               pMessage = "binary entity reference";               break;
     548           0 :         case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:   pMessage = "attribute external entity reference";   break;
     549           0 :         case XML_ERROR_MISPLACED_XML_PI:                pMessage = "misplaced xml processing instruction";  break;
     550           0 :         case XML_ERROR_UNKNOWN_ENCODING:                pMessage = "unknown encoding";                      break;
     551           0 :         case XML_ERROR_INCORRECT_ENCODING:              pMessage = "incorrect encoding";                    break;
     552           0 :         case XML_ERROR_UNCLOSED_CDATA_SECTION:          pMessage = "unclosed cdata section";                break;
     553           0 :         case XML_ERROR_EXTERNAL_ENTITY_HANDLING:        pMessage = "external entity reference";             break;
     554           0 :         case XML_ERROR_NOT_STANDALONE:                  pMessage = "not standalone";                        break;
     555             :         default:;
     556             :     }
     557             : 
     558          12 :     OUStringBuffer aBuffer( '[' );
     559          12 :     aBuffer.append( sSystemId );
     560          12 :     aBuffer.append( " line " );
     561          12 :     aBuffer.append( nLine );
     562          12 :     aBuffer.append( "]: " );
     563          12 :     aBuffer.appendAscii( pMessage );
     564          12 :     aBuffer.append( " error" );
     565          12 :     return aBuffer.makeStringAndClear();
     566             : }
     567             : 
     568             : // throw an exception, but avoid callback if
     569             : // during a threaded produce
     570          12 : void Entity::throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
     571             :                              bool mbDuringParse )
     572             : {
     573             :     // Error during parsing !
     574             :     SAXParseException aExcept(
     575             :         lclGetErrorMessage( XML_GetErrorCode( mpParser ),
     576          12 :                             xDocumentLocator->getSystemId(),
     577          12 :                             xDocumentLocator->getLineNumber() ),
     578             :         Reference< XInterface >(),
     579          12 :         Any( &maSavedException, getCppuType( &maSavedException ) ),
     580          12 :         xDocumentLocator->getPublicId(),
     581          12 :         xDocumentLocator->getSystemId(),
     582          12 :         xDocumentLocator->getLineNumber(),
     583          12 :         xDocumentLocator->getColumnNumber()
     584          84 :     );
     585             : 
     586             :     // error handler is set, it may throw the exception
     587          12 :     if( !mbDuringParse || !mbEnableThreads )
     588             :     {
     589          12 :         if (mxErrorHandler.is() )
     590           0 :             mxErrorHandler->fatalError( Any( aExcept ) );
     591             :     }
     592             : 
     593             :     // error handler has not thrown, but parsing must stop => throw ourselves
     594          12 :     throw aExcept;
     595             : }
     596             : 
     597             : // In the single threaded case we emit events via our C
     598             : // callbacks, so any exception caught must be queued up until
     599             : // we can safely re-throw it from our C++ parent of parse()
     600             : 
     601             : // If multi-threaded, we need to push an EXCEPTION event, at
     602             : // which point we transfer ownership of maSavedException to
     603             : // the consuming thread.
     604          16 : void Entity::saveException( const Exception &e )
     605             : {
     606             :     // fdo#81214 - allow the parser to run on after an exception,
     607             :     // unexpectedly some 'startElements' produce an UNO_QUERY_THROW
     608             :     // for XComponent; and yet expect to continue parsing.
     609             :     SAL_WARN("sax", "Unexpected exception from XML parser " << e.Message);
     610          16 :     maSavedException <<= e;
     611          16 : }
     612             : 
     613             : } // namespace
     614             : 
     615             : namespace sax_fastparser {
     616             : 
     617       52972 : FastSaxParserImpl::FastSaxParserImpl( FastSaxParser* pFront ) :
     618             :     mpFront(pFront),
     619       52972 :     mpTop(NULL)
     620             : {
     621       52972 :     mxDocumentLocator.set( new FastLocatorImpl( this ) );
     622       52972 : }
     623             : 
     624      105944 : FastSaxParserImpl::~FastSaxParserImpl()
     625             : {
     626       52972 :     if( mxDocumentLocator.is() )
     627       52972 :         mxDocumentLocator->dispose();
     628       52972 : }
     629             : 
     630      191984 : void FastSaxParserImpl::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
     631             : {
     632      191984 :     Entity& rEntity = getEntity();
     633             :     assert(!rEntity.maNamespaceCount.empty()); // need a context!
     634      191984 :     if( !rEntity.maNamespaceCount.empty() )
     635             :     {
     636      191984 :         sal_uInt32 nOffset = rEntity.maNamespaceCount.top()++;
     637             : 
     638      191984 :         if( rEntity.maNamespaceDefines.size() <= nOffset )
     639       38690 :             rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 );
     640             : 
     641      191984 :         const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 );
     642      191984 :         rEntity.maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) );
     643             :     }
     644      191984 : }
     645             : 
     646    10449917 : sal_Int32 FastSaxParserImpl::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
     647             : {
     648    10449917 :     return FastTokenHandlerBase::getTokenFromChars( getEntity().mxTokenHandler,
     649    10449917 :                                                     getEntity().mpTokenHandler,
     650    31349751 :                                                     pToken, nLen );
     651             : }
     652             : 
     653     8892472 : sal_Int32 FastSaxParserImpl::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
     654             : {
     655     8892472 :     sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
     656             : 
     657     8892472 :     Entity& rEntity = getEntity();
     658     8892472 :     if (rEntity.maNamespaceCount.empty())
     659           0 :         return nNamespaceToken;
     660             : 
     661     8892472 :     sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
     662    40308584 :     while( nNamespace-- )
     663             :     {
     664    31416112 :         const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
     665    41321984 :         if( (rPrefix.getLength() == nPrefixLen) &&
     666     9905872 :             (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
     667             :         {
     668     8892472 :             nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
     669     8892472 :             break;
     670             :         }
     671             : 
     672    22523640 :         if( !nNamespace )
     673           0 :             throw SAXException(); // prefix that has no defined namespace url
     674             :     }
     675             : 
     676     8892472 :     if( nNamespaceToken != FastToken::DONTKNOW )
     677             :     {
     678     8874920 :         sal_Int32 nNameToken = GetToken( pName, nNameLen );
     679     8874920 :         if( nNameToken != FastToken::DONTKNOW )
     680     8846534 :             return nNamespaceToken | nNameToken;
     681             :     }
     682             : 
     683       45938 :     return FastToken::DONTKNOW;
     684             : }
     685             : 
     686     2713718 : sal_Int32 FastSaxParserImpl::GetNamespaceToken( const OUString& rNamespaceURL )
     687             : {
     688     2713718 :     NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
     689     2713718 :     if( aIter != maNamespaceMap.end() )
     690      172826 :         return (*aIter).second;
     691             :     else
     692     2540892 :         return FastToken::DONTKNOW;
     693             : }
     694             : 
     695           0 : OUString FastSaxParserImpl::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
     696             : {
     697           0 :     Entity& rEntity = getEntity();
     698           0 :     if( !rEntity.maNamespaceCount.empty() )
     699             :     {
     700           0 :         sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
     701           0 :         while( nNamespace-- )
     702           0 :             if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
     703           0 :                 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
     704             :     }
     705             : 
     706           0 :     throw SAXException(); // prefix that has no defined namespace url
     707             : }
     708             : 
     709       45938 : OUString FastSaxParserImpl::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
     710             : {
     711       45938 :     Entity& rEntity = getEntity();
     712       45938 :     if( pPrefix && !rEntity.maNamespaceCount.empty() )
     713             :     {
     714       45938 :         sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
     715      217464 :         while( nNamespace-- )
     716             :         {
     717      171526 :             const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
     718      322058 :             if( (rPrefix.getLength() == nPrefixLen) &&
     719      150532 :                 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
     720             :             {
     721       91876 :                 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
     722             :             }
     723             :         }
     724             :     }
     725             : 
     726           0 :     throw SAXException(); // prefix that has no defined namespace url
     727             : }
     728             : 
     729      184446 : sal_Int32 FastSaxParserImpl::GetTokenWithContextNamespace( sal_Int32 nNamespaceToken, const sal_Char* pName, int nNameLen )
     730             : {
     731      184446 :     if( nNamespaceToken != FastToken::DONTKNOW )
     732             :     {
     733      180834 :         sal_Int32 nNameToken = GetToken( pName, nNameLen );
     734      180833 :         if( nNameToken != FastToken::DONTKNOW )
     735      180831 :             return nNamespaceToken | nNameToken;
     736             :     }
     737             : 
     738        3614 :     return FastToken::DONTKNOW;
     739             : }
     740             : 
     741    10808253 : void FastSaxParserImpl::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
     742             : {
     743             :     XML_Char *p;
     744    92306492 :     for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
     745             :     {
     746    81498239 :         if( *p == ':' )
     747             :         {
     748     9199060 :             rPrefixLen = p - pwName;
     749     9199060 :             rNameLen = 0;
     750             :         }
     751             :         else
     752             :         {
     753    72299179 :             rNameLen++;
     754             :         }
     755             :     }
     756    10808253 :     if( rPrefixLen )
     757             :     {
     758     9199060 :         rpPrefix = pwName;
     759     9199060 :         rpName = &pwName[ rPrefixLen + 1 ];
     760             :     }
     761             :     else
     762             :     {
     763     1609193 :         rpPrefix = 0;
     764     1609193 :         rpName = pwName;
     765             :     }
     766    10808253 : }
     767             : 
     768             : /***************
     769             : *
     770             : * parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
     771             : * the file-specific initialization work. (During a parser run, external files may be opened)
     772             : *
     773             : ****************/
     774       39050 : void FastSaxParserImpl::parseStream(const InputSource& maStructSource)
     775             :     throw (SAXException, IOException, RuntimeException, std::exception)
     776             : {
     777             :     // Only one text at one time
     778       39050 :     MutexGuard guard( maMutex );
     779             : 
     780       78100 :     Entity entity( maData );
     781       39050 :     entity.maStructSource = maStructSource;
     782             : 
     783       39050 :     if( !entity.mxTokenHandler.is() )
     784           0 :         throw SAXException("No token handler, use setTokenHandler()", Reference< XInterface >(), Any() );
     785             : 
     786       39050 :     if( !entity.maStructSource.aInputStream.is() )
     787         360 :         throw SAXException("No input source", Reference< XInterface >(), Any() );
     788             : 
     789       38690 :     entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
     790       38690 :     if( !entity.maStructSource.sEncoding.isEmpty() )
     791           0 :         entity.maConverter.setEncoding( OUStringToOString( entity.maStructSource.sEncoding, RTL_TEXTENCODING_ASCII_US ) );
     792             : 
     793             :     // create parser with proper encoding
     794       38690 :     entity.mpParser = XML_ParserCreate( 0 );
     795       38690 :     if( !entity.mpParser )
     796           0 :         throw SAXException("Couldn't create parser", Reference< XInterface >(), Any() );
     797             : 
     798             :     // set all necessary C-Callbacks
     799       38690 :     XML_SetUserData( entity.mpParser, this );
     800       38690 :     XML_SetElementHandler( entity.mpParser, call_callbackStartElement, call_callbackEndElement );
     801       38690 :     XML_SetCharacterDataHandler( entity.mpParser, call_callbackCharacters );
     802       38690 :     XML_SetEntityDeclHandler(entity.mpParser, call_callbackEntityDecl);
     803       38690 :     XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef );
     804             : 
     805       38690 :     pushEntity( entity );
     806       38690 :     Entity& rEntity = getEntity();
     807             :     try
     808             :     {
     809             :         // start the document
     810       38690 :         if( entity.mxDocumentHandler.is() )
     811             :         {
     812       38686 :             Reference< XLocator > xLoc( mxDocumentLocator.get() );
     813       38686 :             entity.mxDocumentHandler->setDocumentLocator( xLoc );
     814       38686 :             entity.mxDocumentHandler->startDocument();
     815             :         }
     816             : 
     817       38690 :         rEntity.mbEnableThreads = (rEntity.maStructSource.aInputStream->available() > 10000);
     818             : 
     819       38690 :         if (rEntity.mbEnableThreads)
     820             :         {
     821        2858 :             rtl::Reference<ParserThread> xParser;
     822        2858 :             xParser = new ParserThread(this);
     823        2858 :             xParser->launch();
     824        2858 :             bool done = false;
     825        3223 :             do {
     826        3223 :                 rEntity.maConsumeResume.wait();
     827        3223 :                 rEntity.maConsumeResume.reset();
     828             : 
     829        3223 :                 osl::ResettableMutexGuard aGuard(rEntity.maEventProtector);
     830        9946 :                 while (!rEntity.maPendingEvents.empty())
     831             :                 {
     832        3500 :                     if (rEntity.maPendingEvents.size() <= rEntity.mnEventLowWater)
     833        3461 :                         rEntity.maProduceResume.set(); // start producer again
     834             : 
     835        3500 :                     EventList *pEventList = rEntity.maPendingEvents.front();
     836        3500 :                     rEntity.maPendingEvents.pop();
     837        3500 :                     aGuard.clear(); // unlock
     838             : 
     839        3500 :                     if (!consume(pEventList))
     840        2858 :                         done = true;
     841             : 
     842        3500 :                     aGuard.reset(); // lock
     843        3500 :                     rEntity.maUsedEvents.push(pEventList);
     844        3223 :                 }
     845        3223 :             } while (!done);
     846        2858 :             xParser->join();
     847        2858 :             deleteUsedEvents();
     848             :         }
     849             :         else
     850             :         {
     851       35832 :             parse();
     852             :         }
     853             : 
     854             :         // finish document
     855       38678 :         if( entity.mxDocumentHandler.is() )
     856             :         {
     857       38676 :             entity.mxDocumentHandler->endDocument();
     858             :         }
     859             :     }
     860          24 :     catch (const SAXException&)
     861             :     {
     862          12 :         popEntity();
     863          12 :         XML_ParserFree( entity.mpParser );
     864          12 :         throw;
     865             :     }
     866           0 :     catch (const IOException&)
     867             :     {
     868           0 :         popEntity();
     869           0 :         XML_ParserFree( entity.mpParser );
     870           0 :         throw;
     871             :     }
     872           0 :     catch (const RuntimeException&)
     873             :     {
     874           0 :         popEntity();
     875           0 :         XML_ParserFree( entity.mpParser );
     876           0 :         throw;
     877             :     }
     878             : 
     879       38678 :     popEntity();
     880       77728 :     XML_ParserFree( entity.mpParser );
     881       38678 : }
     882             : 
     883       50884 : void FastSaxParserImpl::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
     884             : {
     885       50884 :     maData.mxDocumentHandler = Handler;
     886       50884 : }
     887             : 
     888       52970 : void FastSaxParserImpl::setTokenHandler( const Reference< XFastTokenHandler >& xHandler ) throw (RuntimeException)
     889             : {
     890       52970 :     maData.mxTokenHandler = xHandler;
     891       52970 :     maData.mpTokenHandler = dynamic_cast< FastTokenHandlerBase *>( xHandler.get() );
     892       52970 : }
     893             : 
     894     2495992 : void FastSaxParserImpl::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
     895             : {
     896     2495992 :     if( NamespaceToken >= FastToken::NAMESPACE )
     897             :     {
     898     2495992 :         if( GetNamespaceToken( NamespaceURL ) == FastToken::DONTKNOW )
     899             :         {
     900     2495992 :             maNamespaceMap[ NamespaceURL ] = NamespaceToken;
     901     4991984 :             return;
     902             :         }
     903             :     }
     904           0 :     throw IllegalArgumentException();
     905             : }
     906             : 
     907           0 : OUString FastSaxParserImpl::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
     908             : {
     909             :     try
     910             :     {
     911           0 :         return GetNamespaceURL( OUStringToOString( rPrefix, RTL_TEXTENCODING_UTF8 ) );
     912             :     }
     913           0 :     catch (const Exception&)
     914             :     {
     915             :     }
     916           0 :     throw IllegalArgumentException();
     917             : }
     918             : 
     919           0 : void FastSaxParserImpl::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
     920             : {
     921           0 :     maData.mxErrorHandler = Handler;
     922           0 : }
     923             : 
     924           0 : void FastSaxParserImpl::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
     925             : {
     926           0 :     maData.mxEntityResolver = Resolver;
     927           0 : }
     928             : 
     929           0 : void FastSaxParserImpl::setLocale( const Locale & Locale ) throw (RuntimeException)
     930             : {
     931           0 :     maData.maLocale = Locale;
     932           0 : }
     933             : 
     934        2858 : void FastSaxParserImpl::deleteUsedEvents()
     935             : {
     936        2858 :     Entity& rEntity = getEntity();
     937        2858 :     osl::ResettableMutexGuard aGuard(rEntity.maEventProtector);
     938             : 
     939        8799 :     while (!rEntity.maUsedEvents.empty())
     940             :     {
     941        3083 :         EventList *pEventList = rEntity.maUsedEvents.front();
     942        3083 :         rEntity.maUsedEvents.pop();
     943             : 
     944        3083 :         aGuard.clear(); // unlock
     945             : 
     946        3083 :         delete pEventList;
     947             : 
     948        3083 :         aGuard.reset(); // lock
     949        2858 :     }
     950        2858 : }
     951             : 
     952     2125336 : void FastSaxParserImpl::produce( bool bForceFlush )
     953             : {
     954     2125336 :     Entity& rEntity = getEntity();
     955     4247814 :     if (bForceFlush ||
     956     2122478 :         rEntity.mnProducedEventsSize == rEntity.mnEventListSize)
     957             :     {
     958        3500 :         osl::ResettableMutexGuard aGuard(rEntity.maEventProtector);
     959             : 
     960        7008 :         while (rEntity.maPendingEvents.size() >= rEntity.mnEventHighWater)
     961             :         { // pause parsing for a bit
     962           8 :             aGuard.clear(); // unlock
     963           8 :             rEntity.maProduceResume.wait();
     964           8 :             rEntity.maProduceResume.reset();
     965           8 :             aGuard.reset(); // lock
     966             :         }
     967             : 
     968        3500 :         rEntity.maPendingEvents.push(rEntity.mpProducedEvents);
     969        3500 :         rEntity.mpProducedEvents = 0;
     970             : 
     971        3500 :         aGuard.clear(); // unlock
     972             : 
     973        3500 :         rEntity.maConsumeResume.set();
     974             :     }
     975     2125336 : }
     976             : 
     977         138 : bool FastSaxParserImpl::hasNamespaceURL( const OUString& rPrefix ) const
     978             : {
     979         138 :     if (maEntities.empty())
     980         138 :         return false;
     981             : 
     982           0 :     const Entity& rEntity = getEntity();
     983             : 
     984           0 :     if (rEntity.maNamespaceCount.empty())
     985           0 :         return false;
     986             : 
     987           0 :     OString aPrefix = OUStringToOString(rPrefix, RTL_TEXTENCODING_UTF8);
     988           0 :     sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
     989           0 :     while (nNamespace--)
     990             :     {
     991           0 :         if (rEntity.maNamespaceDefines[nNamespace]->maPrefix == aPrefix)
     992           0 :             return true;
     993             :     }
     994             : 
     995           0 :     return false;
     996             : }
     997             : 
     998        3500 : bool FastSaxParserImpl::consume(EventList *pEventList)
     999             : {
    1000        3500 :     Entity& rEntity = getEntity();
    1001     6377934 :     for (EventList::iterator aEventIt = pEventList->begin();
    1002     4251956 :          aEventIt != pEventList->end(); ++aEventIt)
    1003             :     {
    1004     2125336 :         switch ((*aEventIt).maType)
    1005             :         {
    1006             :             case START_ELEMENT:
    1007     1012250 :                 rEntity.startElement( &(*aEventIt) );
    1008     1012250 :                 break;
    1009             :             case END_ELEMENT:
    1010     1012250 :                 rEntity.endElement();
    1011     1012250 :                 break;
    1012             :             case CHARACTERS:
    1013       97978 :                 rEntity.characters( (*aEventIt).msChars );
    1014       97978 :                 break;
    1015             :             case DONE:
    1016        5716 :                 return false;
    1017             :             case EXCEPTION:
    1018           0 :                 rEntity.throwException( mxDocumentLocator, false );
    1019           0 :                 return false;
    1020             :             default:
    1021             :                 assert(false);
    1022           0 :                 return false;
    1023             :         }
    1024             :     }
    1025         642 :     return true;
    1026             : }
    1027             : 
    1028       38690 : void FastSaxParserImpl::pushEntity( const Entity& rEntity )
    1029             : {
    1030       38690 :     maEntities.push( rEntity );
    1031       38690 :     mpTop = &maEntities.top();
    1032       38690 : }
    1033             : 
    1034       38690 : void FastSaxParserImpl::popEntity()
    1035             : {
    1036       38690 :     maEntities.pop();
    1037       38690 :     mpTop = !maEntities.empty() ? &maEntities.top() : NULL;
    1038       38690 : }
    1039             : 
    1040             : // starts parsing with actual parser !
    1041       38690 : void FastSaxParserImpl::parse()
    1042             : {
    1043       38690 :     const int BUFFER_SIZE = 16 * 1024;
    1044       38690 :     Sequence< sal_Int8 > seqOut( BUFFER_SIZE );
    1045             : 
    1046       38690 :     Entity& rEntity = getEntity();
    1047       38690 :     int nRead = 0;
    1048       44692 :     do
    1049             :     {
    1050       83382 :         nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE );
    1051       83382 :         if( nRead <= 0 )
    1052             :         {
    1053       38678 :             XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), 0, 1 );
    1054       38678 :             break;
    1055             :         }
    1056             : 
    1057             :         bool const bContinue = XML_STATUS_ERROR != XML_Parse(rEntity.mpParser,
    1058       44704 :             reinterpret_cast<const char*>(seqOut.getConstArray()), nRead, 0);
    1059             : 
    1060             :         // callbacks used inside XML_Parse may have caught an exception
    1061       44704 :         if( !bContinue || rEntity.maSavedException.hasValue() )
    1062          12 :             rEntity.throwException( mxDocumentLocator, true );
    1063             :     }
    1064             :     while( nRead > 0 );
    1065       38678 :     rEntity.getEvent( DONE );
    1066       38678 :     if( rEntity.mbEnableThreads )
    1067        2870 :         produce( true );
    1068       38678 : }
    1069             : 
    1070             : // The C-Callbacks
    1071     4449100 : void FastSaxParserImpl::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
    1072             : {
    1073     4449100 :     Entity& rEntity = getEntity();
    1074     4449100 :     if( rEntity.maNamespaceCount.empty() )
    1075             :     {
    1076       38690 :         rEntity.maNamespaceCount.push(0);
    1077       38690 :         DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
    1078             :     }
    1079             :     else
    1080             :     {
    1081     4410410 :         rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
    1082             :     }
    1083             : 
    1084             :     // create attribute map and process namespace instructions
    1085     4449100 :     Event& rEvent = getEntity().getEvent( START_ELEMENT );
    1086     4449100 :     if (rEvent.mxAttributes.is())
    1087     3470717 :         rEvent.mxAttributes->clear();
    1088             :     else
    1089             :         rEvent.mxAttributes.set(
    1090             :                 new FastAttributeList( rEntity.mxTokenHandler,
    1091      978383 :                                        rEntity.mpTokenHandler ) );
    1092             : 
    1093             :     sal_Int32 nNameLen, nPrefixLen;
    1094             :     const XML_Char *pName;
    1095             :     const XML_Char *pPrefix;
    1096             : 
    1097     4449100 :     sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
    1098     4449100 :     if (!rEntity.maNamespaceStack.empty())
    1099             :     {
    1100     4410410 :         rEvent.msNamespace = rEntity.maNamespaceStack.top().msName;
    1101     4410410 :         nNamespaceToken = rEntity.maNamespaceStack.top().mnToken;
    1102             :     }
    1103             : 
    1104             :     try
    1105             :     {
    1106             :         /*  #158414# Each element may define new namespaces, also for attribues.
    1107             :             First, process all namespace attributes and cache other attributes in a
    1108             :             vector. Second, process the attributes after namespaces have been
    1109             :             initialized. */
    1110             : 
    1111             :         // #158414# first: get namespaces
    1112    10639667 :         for (int i = 0; awAttributes[i]; i += 2)
    1113             :         {
    1114             :             assert(awAttributes[i+1]);
    1115             : 
    1116     6427780 :             if( awAttributes[i][0] != 'x' ||
    1117      237212 :                 strncmp( awAttributes[i], "xmlns", 5) != 0 )
    1118     6021982 :                 continue;
    1119             : 
    1120      168586 :             splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
    1121      168586 :             if( nPrefixLen )
    1122             :             {
    1123      153294 :                 if( (nPrefixLen == 5) && (strncmp( pPrefix, "xmlns", 5 ) == 0) )
    1124             :                 {
    1125      153294 :                     DefineNamespace( OString( pName, nNameLen ), awAttributes[i+1] );
    1126             :                 }
    1127             :             }
    1128             :             else
    1129             :             {
    1130       15292 :                 if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
    1131             :                 {
    1132             :                     // default namespace is the attribute value
    1133       15292 :                     rEvent.msNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
    1134       15292 :                     nNamespaceToken = GetNamespaceToken( rEvent.msNamespace );
    1135             :                 }
    1136             :             }
    1137             :         }
    1138             : 
    1139             :         // #158414# second: fill attribute list with other attributes
    1140    10639667 :         for (int i = 0; awAttributes[i]; i += 2)
    1141             :         {
    1142     6190567 :             splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
    1143     6190567 :             if( nPrefixLen )
    1144             :             {
    1145     4781130 :                 if( (nPrefixLen != 5) || (strncmp( pPrefix, "xmlns", 5 ) != 0) )
    1146             :                 {
    1147     4627836 :                     sal_Int32 nAttributeToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
    1148     4627836 :                     if( nAttributeToken != FastToken::DONTKNOW )
    1149     4592348 :                         rEvent.mxAttributes->add( nAttributeToken, awAttributes[i+1] );
    1150             :                     else
    1151             :                         rEvent.mxAttributes->addUnknown( GetNamespaceURL( pPrefix, nPrefixLen ),
    1152       35488 :                                 OString(pName, nNameLen), awAttributes[i+1] );
    1153             :                 }
    1154             :             }
    1155             :             else
    1156             :             {
    1157     1409437 :                 if( (nNameLen != 5) || (strcmp( pName, "xmlns" ) != 0) )
    1158             :                 {
    1159     1394145 :                     sal_Int32 nAttributeToken = GetToken( pName, nNameLen );
    1160     1394146 :                     if( nAttributeToken != FastToken::DONTKNOW )
    1161     1390732 :                         rEvent.mxAttributes->add( nAttributeToken, awAttributes[i+1] );
    1162             :                     else
    1163        3414 :                         rEvent.mxAttributes->addUnknown( OString(pName, nNameLen), awAttributes[i+1] );
    1164             :                 }
    1165             :             }
    1166             :         }
    1167             : 
    1168     4449100 :         splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
    1169     4449100 :         if( nPrefixLen > 0 )
    1170     4264636 :             rEvent.mnElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
    1171      184464 :         else if( !rEvent.msNamespace.isEmpty() )
    1172      184446 :             rEvent.mnElementToken = GetTokenWithContextNamespace( nNamespaceToken, pName, nNameLen );
    1173             :         else
    1174          18 :             rEvent.mnElementToken = GetToken( pName );
    1175             : 
    1176     4449099 :         if( rEvent.mnElementToken == FastToken::DONTKNOW )
    1177             :         {
    1178       14070 :             if( nPrefixLen > 0 )
    1179             :             {
    1180       10450 :                 rEvent.msNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
    1181       10450 :                 nNamespaceToken = GetNamespaceToken( rEvent.msNamespace );
    1182             :             }
    1183       14070 :             rEvent.msElementName = OUString( pName, nNameLen, RTL_TEXTENCODING_UTF8 );
    1184             :         }
    1185             :         else // token is always preferred.
    1186     4435029 :             rEvent.msElementName = OUString( "" );
    1187             : 
    1188     4449099 :         rEntity.maNamespaceStack.push( NameWithToken(rEvent.msNamespace, nNamespaceToken) );
    1189     4449100 :         if (rEntity.mbEnableThreads)
    1190     1012250 :             produce();
    1191             :         else
    1192     3436850 :             rEntity.startElement( &rEvent );
    1193             :     }
    1194           0 :     catch (const Exception& e)
    1195             :     {
    1196           0 :         rEntity.saveException( e );
    1197             :     }
    1198     4449100 : }
    1199             : 
    1200     4449074 : void FastSaxParserImpl::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
    1201             : {
    1202     4449074 :     Entity& rEntity = getEntity();
    1203             :     assert( !rEntity.maNamespaceCount.empty() );
    1204     4449074 :     if( !rEntity.maNamespaceCount.empty() )
    1205     4449074 :         rEntity.maNamespaceCount.pop();
    1206             : 
    1207             :     assert( !rEntity.maNamespaceStack.empty() );
    1208     4449074 :     if( !rEntity.maNamespaceStack.empty() )
    1209     4449074 :         rEntity.maNamespaceStack.pop();
    1210             : 
    1211     4449074 :     rEntity.getEvent( END_ELEMENT );
    1212     4449074 :     if (rEntity.mbEnableThreads)
    1213     1012250 :         produce();
    1214             :     else
    1215     3436824 :         rEntity.endElement();
    1216     4449074 : }
    1217             : 
    1218      432284 : void FastSaxParserImpl::callbackCharacters( const XML_Char* s, int nLen )
    1219             : {
    1220      432284 :     Entity& rEntity = getEntity();
    1221      432284 :     Event& rEvent = rEntity.getEvent( CHARACTERS );
    1222      432284 :     rEvent.msChars = OUString(s, nLen, RTL_TEXTENCODING_UTF8);
    1223      432284 :     if (rEntity.mbEnableThreads)
    1224       97978 :         produce();
    1225             :     else
    1226      334306 :         rEntity.characters( rEvent.msChars );
    1227      432284 : }
    1228             : 
    1229           0 : void FastSaxParserImpl::callbackEntityDecl(
    1230             :     SAL_UNUSED_PARAMETER const XML_Char * /*entityName*/,
    1231             :     SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
    1232             :     const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
    1233             :     SAL_UNUSED_PARAMETER const XML_Char * /*base*/,
    1234             :     SAL_UNUSED_PARAMETER const XML_Char * /*systemId*/,
    1235             :     SAL_UNUSED_PARAMETER const XML_Char * /*publicId*/,
    1236             :     SAL_UNUSED_PARAMETER const XML_Char * /*notationName*/)
    1237             : {
    1238           0 :     if (value) { // value != 0 means internal entity
    1239             :         SAL_INFO("sax", "FastSaxParser: internal entity declaration, stopping");
    1240           0 :         XML_StopParser(getEntity().mpParser, XML_FALSE);
    1241           0 :         getEntity().saveException( SAXParseException(
    1242             :             "FastSaxParser: internal entity declaration, stopping",
    1243             :             static_cast<OWeakObject*>(mpFront), Any(),
    1244           0 :             mxDocumentLocator->getPublicId(),
    1245           0 :             mxDocumentLocator->getSystemId(),
    1246           0 :             mxDocumentLocator->getLineNumber(),
    1247           0 :             mxDocumentLocator->getColumnNumber() ) );
    1248             :     } else {
    1249             :         SAL_INFO("sax", "FastSaxParser: ignoring external entity declaration");
    1250             :     }
    1251           0 : }
    1252             : 
    1253           0 : bool FastSaxParserImpl::callbackExternalEntityRef(
    1254             :     XML_Parser parser, const XML_Char *context,
    1255             :     SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
    1256             :     const XML_Char *publicId )
    1257             : {
    1258           0 :     bool bOK = true;
    1259           0 :     InputSource source;
    1260             : 
    1261           0 :     Entity& rCurrEntity = getEntity();
    1262           0 :     Entity aNewEntity( rCurrEntity );
    1263             : 
    1264           0 :     if( rCurrEntity.mxEntityResolver.is() ) try
    1265             :     {
    1266           0 :         aNewEntity.maStructSource = rCurrEntity.mxEntityResolver->resolveEntity(
    1267           0 :             OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) ,
    1268           0 :             OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) );
    1269             :     }
    1270           0 :     catch (const SAXParseException & e)
    1271             :     {
    1272           0 :         rCurrEntity.saveException( e );
    1273           0 :         bOK = false;
    1274             :     }
    1275           0 :     catch (const SAXException& e)
    1276             :     {
    1277             :         rCurrEntity.saveException( SAXParseException(
    1278             :             e.Message, e.Context, e.WrappedException,
    1279           0 :             mxDocumentLocator->getPublicId(),
    1280           0 :             mxDocumentLocator->getSystemId(),
    1281           0 :             mxDocumentLocator->getLineNumber(),
    1282           0 :             mxDocumentLocator->getColumnNumber() ) );
    1283           0 :         bOK = false;
    1284             :     }
    1285             : 
    1286           0 :     if( aNewEntity.maStructSource.aInputStream.is() )
    1287             :     {
    1288           0 :         aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 );
    1289           0 :         if( !aNewEntity.mpParser )
    1290             :         {
    1291           0 :             return false;
    1292             :         }
    1293             : 
    1294           0 :         aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream );
    1295           0 :         pushEntity( aNewEntity );
    1296             :         try
    1297             :         {
    1298           0 :             parse();
    1299             :         }
    1300           0 :         catch (const SAXParseException& e)
    1301             :         {
    1302           0 :             rCurrEntity.saveException( e );
    1303           0 :             bOK = false;
    1304             :         }
    1305           0 :         catch (const IOException& e)
    1306             :         {
    1307           0 :             SAXException aEx;
    1308           0 :             aEx.WrappedException <<= e;
    1309           0 :             rCurrEntity.saveException( aEx );
    1310           0 :             bOK = false;
    1311             :         }
    1312           0 :         catch (const RuntimeException& e)
    1313             :         {
    1314           0 :             SAXException aEx;
    1315           0 :             aEx.WrappedException <<= e;
    1316           0 :             rCurrEntity.saveException( aEx );
    1317           0 :             bOK = false;
    1318             :         }
    1319             : 
    1320           0 :         popEntity();
    1321           0 :         XML_ParserFree( aNewEntity.mpParser );
    1322             :     }
    1323             : 
    1324           0 :     return bOK;
    1325             : }
    1326             : 
    1327       52972 : FastSaxParser::FastSaxParser() : mpImpl(new FastSaxParserImpl(this)) {}
    1328             : 
    1329      158914 : FastSaxParser::~FastSaxParser()
    1330             : {
    1331       52972 :     delete mpImpl;
    1332      105942 : }
    1333             : 
    1334       39050 : void FastSaxParser::parseStream( const xml::sax::InputSource& aInputSource )
    1335             :     throw (xml::sax::SAXException, io::IOException,
    1336             :            uno::RuntimeException, std::exception)
    1337             : {
    1338       39050 :     mpImpl->parseStream(aInputSource);
    1339       38678 : }
    1340             : 
    1341       50884 : void FastSaxParser::setFastDocumentHandler( const uno::Reference<xml::sax::XFastDocumentHandler>& Handler )
    1342             :     throw (uno::RuntimeException, std::exception)
    1343             : {
    1344       50884 :     mpImpl->setFastDocumentHandler(Handler);
    1345       50884 : }
    1346             : 
    1347       52970 : void FastSaxParser::setTokenHandler( const uno::Reference<xml::sax::XFastTokenHandler>& Handler )
    1348             :     throw (uno::RuntimeException, std::exception)
    1349             : {
    1350       52970 :     mpImpl->setTokenHandler(Handler);
    1351       52970 : }
    1352             : 
    1353     2495992 : void FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken )
    1354             :     throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1355             : {
    1356     2495992 :     mpImpl->registerNamespace(NamespaceURL, NamespaceToken);
    1357     2495992 : }
    1358             : 
    1359           0 : OUString FastSaxParser::getNamespaceURL( const OUString& rPrefix )
    1360             :     throw(lang::IllegalArgumentException, uno::RuntimeException, std::exception)
    1361             : {
    1362           0 :     return mpImpl->getNamespaceURL(rPrefix);
    1363             : }
    1364             : 
    1365           0 : void FastSaxParser::setErrorHandler( const uno::Reference< xml::sax::XErrorHandler >& Handler )
    1366             :     throw (uno::RuntimeException, std::exception)
    1367             : {
    1368           0 :     mpImpl->setErrorHandler(Handler);
    1369           0 : }
    1370             : 
    1371           0 : void FastSaxParser::setEntityResolver( const uno::Reference< xml::sax::XEntityResolver >& Resolver )
    1372             :     throw (uno::RuntimeException, std::exception)
    1373             : {
    1374           0 :     mpImpl->setEntityResolver(Resolver);
    1375           0 : }
    1376             : 
    1377           0 : void FastSaxParser::setLocale( const lang::Locale& rLocale )
    1378             :     throw (uno::RuntimeException, std::exception)
    1379             : {
    1380           0 :     mpImpl->setLocale(rLocale);
    1381           0 : }
    1382             : 
    1383           0 : OUString FastSaxParser::getImplementationName()
    1384             :     throw (uno::RuntimeException, std::exception)
    1385             : {
    1386           0 :     return OUString("com.sun.star.comp.extensions.xml.sax.FastParser");
    1387             : }
    1388             : 
    1389           0 : sal_Bool FastSaxParser::supportsService( const OUString& ServiceName )
    1390             :     throw (uno::RuntimeException, std::exception)
    1391             : {
    1392           0 :     return cppu::supportsService(this, ServiceName);
    1393             : }
    1394             : 
    1395           0 : uno::Sequence<OUString> FastSaxParser::getSupportedServiceNames()
    1396             :     throw (uno::RuntimeException, std::exception)
    1397             : {
    1398           0 :     Sequence<OUString> seq(1);
    1399           0 :     seq[0] = OUString("com.sun.star.xml.sax.FastParser");
    1400           0 :     return seq;
    1401             : }
    1402             : 
    1403         138 : bool FastSaxParser::hasNamespaceURL( const OUString& rPrefix ) const
    1404             : {
    1405         138 :     return mpImpl->hasNamespaceURL(rPrefix);
    1406             : }
    1407             : 
    1408             : } // namespace sax_fastparser
    1409             : 
    1410             : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
    1411       52970 : com_sun_star_comp_extensions_xml_sax_FastParser_get_implementation(
    1412             :     css::uno::XComponentContext *,
    1413             :     css::uno::Sequence<css::uno::Any> const &)
    1414             : {
    1415       52970 :     return cppu::acquire(new FastSaxParser);
    1416             : }
    1417             : 
    1418             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10