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

Generated by: LCOV version 1.10