LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sax/source/fastparser - fastparser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 315 444 70.9 %
Date: 2013-07-09 Functions: 50 60 83.3 %
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 <boost/scoped_ptr.hpp>
      21             : 
      22             : #include <osl/diagnose.h>
      23             : #include <rtl/ustrbuf.hxx>
      24             : 
      25             : #include <com/sun/star/lang/DisposedException.hpp>
      26             : #include <com/sun/star/xml/sax/XFastContextHandler.hpp>
      27             : #include <com/sun/star/xml/sax/SAXParseException.hpp>
      28             : #include <com/sun/star/xml/sax/FastToken.hpp>
      29             : 
      30             : #include "fastparser.hxx"
      31             : 
      32             : #include <string.h>
      33             : 
      34             : using namespace ::std;
      35             : using namespace ::osl;
      36             : using namespace ::cppu;
      37             : using namespace ::com::sun::star::uno;
      38             : using namespace ::com::sun::star::lang;
      39             : using namespace ::com::sun::star::xml::sax;
      40             : using namespace ::com::sun::star::io;
      41             : 
      42             : namespace sax_fastparser {
      43             : 
      44             : // --------------------------------------------------------------------
      45             : 
      46      112475 : struct SaxContextImpl
      47             : {
      48             :     Reference< XFastContextHandler >    mxContext;
      49             :     sal_uInt32      mnNamespaceCount;
      50             :     sal_Int32       mnElementToken;
      51             :     OUString        maNamespace;
      52             :     OUString        maElementName;
      53             : 
      54        1811 :     SaxContextImpl() { mnNamespaceCount = 0; mnElementToken = 0; }
      55      110664 :     SaxContextImpl( const SaxContextImplPtr& p ) { mnNamespaceCount = p->mnNamespaceCount; mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
      56             : };
      57             : 
      58             : // --------------------------------------------------------------------
      59             : 
      60        7685 : struct NamespaceDefine
      61             : {
      62             :     OString     maPrefix;
      63             :     sal_Int32   mnToken;
      64             :     OUString    maNamespaceURL;
      65             : 
      66        7685 :     NamespaceDefine( const OString& rPrefix, sal_Int32 nToken, const OUString& rNamespaceURL ) : maPrefix( rPrefix ), mnToken( nToken ), maNamespaceURL( rNamespaceURL ) {}
      67             : };
      68             : 
      69             : // --------------------------------------------------------------------
      70             : // FastLocatorImpl
      71             : // --------------------------------------------------------------------
      72             : 
      73             : class FastSaxParser;
      74             : 
      75        4034 : class FastLocatorImpl : public WeakImplHelper1< XLocator >
      76             : {
      77             : public:
      78        2017 :     FastLocatorImpl( FastSaxParser *p ) : mpParser(p) {}
      79             : 
      80        2017 :     void dispose() { mpParser = 0; }
      81           6 :     void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
      82             : 
      83             :     //XLocator
      84             :     virtual sal_Int32 SAL_CALL getColumnNumber(void) throw (RuntimeException);
      85             :     virtual sal_Int32 SAL_CALL getLineNumber(void) throw (RuntimeException);
      86             :     virtual OUString SAL_CALL getPublicId(void) throw (RuntimeException);
      87             :     virtual OUString SAL_CALL getSystemId(void) throw (RuntimeException);
      88             : 
      89             : private:
      90             :     FastSaxParser *mpParser;
      91             : };
      92             : 
      93             : // --------------------------------------------------------------------
      94             : // FastSaxParser
      95             : // --------------------------------------------------------------------
      96             : 
      97             : //---------------------------------------------
      98             : // the implementation part
      99             : //---------------------------------------------
     100             : 
     101             : extern "C" {
     102             : 
     103      112475 : static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
     104             : {
     105      112475 :     FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
     106      112475 :     pFastParser->callbackStartElement( name, atts );
     107      112475 : }
     108             : 
     109      112469 : static void call_callbackEndElement(void *userData, const XML_Char *name)
     110             : {
     111      112469 :     FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
     112      112469 :     pFastParser->callbackEndElement( name );
     113      112469 : }
     114             : 
     115       21067 : static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
     116             : {
     117       21067 :     FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( userData );
     118       21067 :     pFastParser->callbackCharacters( s, nLen );
     119       21067 : }
     120             : 
     121           0 : static void call_callbackEntityDecl(void *userData, const XML_Char *entityName,
     122             :         int is_parameter_entity, const XML_Char *value, int value_length,
     123             :         const XML_Char *base, const XML_Char *systemId,
     124             :         const XML_Char *publicId, const XML_Char *notationName)
     125             : {
     126           0 :     FastSaxParser* pFastParser = reinterpret_cast<FastSaxParser*>(userData);
     127             :     pFastParser->callbackEntityDecl(entityName, is_parameter_entity, value,
     128           0 :             value_length, base, systemId, publicId, notationName);
     129           0 : }
     130             : 
     131           0 : static int call_callbackExternalEntityRef( XML_Parser parser,
     132             :         const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId )
     133             : {
     134           0 :     FastSaxParser* pFastParser = reinterpret_cast< FastSaxParser* >( XML_GetUserData( parser ) );
     135           0 :     return pFastParser->callbackExternalEntityRef( parser, openEntityNames, base, systemId, publicId );
     136             : }
     137             : 
     138             : } // extern "C"
     139             : 
     140             : // --------------------------------------------------------------------
     141             : // FastLocatorImpl implementation
     142             : // --------------------------------------------------------------------
     143             : 
     144           1 : sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber(void) throw (RuntimeException)
     145             : {
     146           1 :     checkDispose();
     147           1 :     return XML_GetCurrentColumnNumber( mpParser->getEntity().mpParser );
     148             : }
     149             : 
     150             : // --------------------------------------------------------------------
     151             : 
     152           2 : sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber(void) throw (RuntimeException)
     153             : {
     154           2 :     checkDispose();
     155           2 :     return XML_GetCurrentLineNumber( mpParser->getEntity().mpParser );
     156             : }
     157             : 
     158             : // --------------------------------------------------------------------
     159             : 
     160           1 : OUString SAL_CALL FastLocatorImpl::getPublicId(void) throw (RuntimeException)
     161             : {
     162           1 :     checkDispose();
     163           1 :     return mpParser->getEntity().maStructSource.sPublicId;
     164             : }
     165             : // --------------------------------------------------------------------
     166             : 
     167           2 : OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException)
     168             : {
     169           2 :     checkDispose();
     170           2 :     return mpParser->getEntity().maStructSource.sSystemId;
     171             : }
     172             : 
     173             : // --------------------------------------------------------------------
     174             : 
     175        2017 : ParserData::ParserData()
     176             : {
     177        2017 : }
     178             : 
     179        5711 : ParserData::~ParserData()
     180             : {
     181        5711 : }
     182             : 
     183             : // --------------------------------------------------------------------
     184             : 
     185        1883 : Entity::Entity( const ParserData& rData ) :
     186        1883 :     ParserData( rData )
     187             : {
     188             :     // performance-improvement. Reference is needed when calling the startTag callback.
     189             :     // Handing out the same object with every call is allowed (see sax-specification)
     190        1883 :     mxAttributes.set( new FastAttributeList( mxTokenHandler ) );
     191        1883 : }
     192             : 
     193        3694 : Entity::~Entity()
     194             : {
     195        3694 : }
     196             : 
     197             : // --------------------------------------------------------------------
     198             : // FastSaxParser implementation
     199             : // --------------------------------------------------------------------
     200             : 
     201        2017 : FastSaxParser::FastSaxParser()
     202             : {
     203        2017 :     mxDocumentLocator.set( new FastLocatorImpl( this ) );
     204        2017 : }
     205             : 
     206             : // --------------------------------------------------------------------
     207             : 
     208        6051 : FastSaxParser::~FastSaxParser()
     209             : {
     210        2017 :     if( mxDocumentLocator.is() )
     211        2017 :         mxDocumentLocator->dispose();
     212        4034 : }
     213             : 
     214             : // --------------------------------------------------------------------
     215             : 
     216      112475 : void FastSaxParser::pushContext()
     217             : {
     218      112475 :     Entity& rEntity = getEntity();
     219      112475 :     if( rEntity.maContextStack.empty() )
     220             :     {
     221        1811 :         rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) );
     222        1811 :         DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
     223             :     }
     224             :     else
     225             :     {
     226      110664 :         rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) );
     227             :     }
     228      112475 : }
     229             : 
     230             : // --------------------------------------------------------------------
     231             : 
     232      112469 : void FastSaxParser::popContext()
     233             : {
     234      112469 :     Entity& rEntity = getEntity();
     235             :     assert(!rEntity.maContextStack.empty()); // pop without push?
     236      112469 :     if( !rEntity.maContextStack.empty() )
     237      112469 :         rEntity.maContextStack.pop();
     238      112469 : }
     239             : 
     240             : // --------------------------------------------------------------------
     241             : 
     242        7685 : void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
     243             : {
     244        7685 :     Entity& rEntity = getEntity();
     245             :     assert(!rEntity.maContextStack.empty()); // need a context!
     246        7685 :     if( !rEntity.maContextStack.empty() )
     247             :     {
     248        7685 :         sal_uInt32 nOffset = rEntity.maContextStack.top()->mnNamespaceCount++;
     249             : 
     250        7685 :         if( rEntity.maNamespaceDefines.size() <= nOffset )
     251        1811 :             rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 );
     252             : 
     253        7685 :         const OUString aNamespaceURL( pNamespaceURL, strlen( pNamespaceURL ), RTL_TEXTENCODING_UTF8 );
     254        7685 :         rEntity.maNamespaceDefines[nOffset].reset( new NamespaceDefine( rPrefix, GetNamespaceToken( aNamespaceURL ), aNamespaceURL ) );
     255             :     }
     256        7685 : }
     257             : 
     258             : // --------------------------------------------------------------------
     259             : 
     260       44715 : sal_Int32 FastSaxParser::GetToken( const OString& rToken )
     261             : {
     262       44715 :     Sequence< sal_Int8 > aSeq( (sal_Int8*)rToken.getStr(), rToken.getLength() );
     263             : 
     264       44715 :     return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
     265             : }
     266             : 
     267      152101 : sal_Int32 FastSaxParser::GetToken( const sal_Char* pToken, sal_Int32 nLen /* = 0 */ )
     268             : {
     269      152101 :     if( !nLen )
     270           4 :         nLen = strlen( pToken );
     271             : 
     272      152101 :     Sequence< sal_Int8 > aSeq( (sal_Int8*)pToken, nLen );
     273             : 
     274      152101 :     return getEntity().mxTokenHandler->getTokenFromUTF8( aSeq );
     275             : }
     276             : 
     277             : // --------------------------------------------------------------------
     278             : 
     279       62452 : sal_Int32 FastSaxParser::GetTokenWithPrefix( const OString& rPrefix, const OString& rName ) throw (SAXException)
     280             : {
     281       62452 :     sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
     282             : 
     283       62452 :     Entity& rEntity = getEntity();
     284       62452 :     sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
     285      209858 :     while( nNamespace-- )
     286             :     {
     287      147406 :         if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
     288             :         {
     289       62452 :             nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
     290       62452 :             break;
     291             :         }
     292             : 
     293       84954 :         if( !nNamespace )
     294           0 :             throw SAXException(); // prefix that has no defined namespace url
     295             :     }
     296             : 
     297       62452 :     if( nNamespaceToken != FastToken::DONTKNOW )
     298             :     {
     299       61949 :         sal_Int32 nNameToken = GetToken( rName.getStr(), rName.getLength() );
     300       61949 :         if( nNameToken != FastToken::DONTKNOW )
     301       61949 :             return nNamespaceToken | nNameToken;
     302             :     }
     303             : 
     304         503 :     return FastToken::DONTKNOW;
     305             : }
     306             : 
     307       80300 : sal_Int32 FastSaxParser::GetTokenWithPrefix( const sal_Char*pPrefix, int nPrefixLen, const sal_Char* pName, int nNameLen ) throw (SAXException)
     308             : {
     309       80300 :     sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
     310             : 
     311       80300 :     Entity& rEntity = getEntity();
     312       80300 :     sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
     313      256118 :     while( nNamespace-- )
     314             :     {
     315      175818 :         const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
     316      277433 :         if( (rPrefix.getLength() == nPrefixLen) &&
     317      101615 :             (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
     318             :         {
     319       80300 :             nNamespaceToken = rEntity.maNamespaceDefines[nNamespace]->mnToken;
     320       80300 :             break;
     321             :         }
     322             : 
     323       95518 :         if( !nNamespace )
     324           0 :             throw SAXException(); // prefix that has no defined namespace url
     325             :     }
     326             : 
     327       80300 :     if( nNamespaceToken != FastToken::DONTKNOW )
     328             :     {
     329       80266 :         sal_Int32 nNameToken = GetToken( pName, nNameLen );
     330       80266 :         if( nNameToken != FastToken::DONTKNOW )
     331       80266 :             return nNamespaceToken | nNameToken;
     332             :     }
     333             : 
     334          34 :     return FastToken::DONTKNOW;
     335             : }
     336             : 
     337             : // --------------------------------------------------------------------
     338             : 
     339       45596 : sal_Int32 FastSaxParser::GetNamespaceToken( const OUString& rNamespaceURL )
     340             : {
     341       45596 :     NamespaceMap::iterator aIter( maNamespaceMap.find( rNamespaceURL ) );
     342       45596 :     if( aIter != maNamespaceMap.end() )
     343       15528 :         return (*aIter).second;
     344             :     else
     345       30068 :         return FastToken::DONTKNOW;
     346             : }
     347             : 
     348             : // --------------------------------------------------------------------
     349             : 
     350         509 : OUString FastSaxParser::GetNamespaceURL( const OString& rPrefix ) throw (SAXException)
     351             : {
     352         509 :     Entity& rEntity = getEntity();
     353         509 :     if( !rEntity.maContextStack.empty() )
     354             :     {
     355         509 :         sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
     356        1305 :         while( nNamespace-- )
     357         796 :             if( rEntity.maNamespaceDefines[nNamespace]->maPrefix == rPrefix )
     358        1018 :                 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
     359             :     }
     360             : 
     361           0 :     throw SAXException(); // prefix that has no defined namespace url
     362             : }
     363             : 
     364          34 : OUString FastSaxParser::GetNamespaceURL( const sal_Char*pPrefix, int nPrefixLen ) throw(SAXException)
     365             : {
     366          34 :     Entity& rEntity = getEntity();
     367          34 :     if( pPrefix && !rEntity.maContextStack.empty() )
     368             :     {
     369          34 :         sal_uInt32 nNamespace = rEntity.maContextStack.top()->mnNamespaceCount;
     370          86 :         while( nNamespace-- )
     371             :         {
     372          52 :             const OString& rPrefix( rEntity.maNamespaceDefines[nNamespace]->maPrefix );
     373          87 :             if( (rPrefix.getLength() == nPrefixLen) &&
     374          35 :                 (strncmp( rPrefix.getStr(), pPrefix, nPrefixLen ) == 0 ) )
     375             :             {
     376          68 :                 return rEntity.maNamespaceDefines[nNamespace]->maNamespaceURL;
     377             :             }
     378             :         }
     379             :     }
     380             : 
     381           0 :     throw SAXException(); // prefix that has no defined namespace url
     382             : }
     383             : 
     384             : // --------------------------------------------------------------------
     385             : 
     386        9882 : sal_Int32 FastSaxParser::GetTokenWithNamespaceURL( const OUString& rNamespaceURL, const sal_Char* pName, int nNameLen )
     387             : {
     388        9882 :     sal_Int32 nNamespaceToken = GetNamespaceToken( rNamespaceURL );
     389             : 
     390        9882 :     if( nNamespaceToken != FastToken::DONTKNOW )
     391             :     {
     392        9882 :         sal_Int32 nNameToken = GetToken( pName, nNameLen );
     393        9882 :         if( nNameToken != FastToken::DONTKNOW )
     394        9882 :             return nNamespaceToken | nNameToken;
     395             :     }
     396             : 
     397           0 :     return FastToken::DONTKNOW;
     398             : }
     399             : 
     400             : // --------------------------------------------------------------------
     401             : 
     402      203972 : void FastSaxParser::splitName( const XML_Char *pwName, const XML_Char *&rpPrefix, sal_Int32 &rPrefixLen, const XML_Char *&rpName, sal_Int32 &rNameLen )
     403             : {
     404             :     XML_Char *p;
     405     1603562 :     for( p = const_cast< XML_Char* >( pwName ), rNameLen = 0, rPrefixLen = 0; *p; p++ )
     406             :     {
     407     1399590 :         if( *p == ':' )
     408             :         {
     409      148626 :             rPrefixLen = p - pwName;
     410      148626 :             rNameLen = 0;
     411             :         }
     412             :         else
     413             :         {
     414     1250964 :             rNameLen++;
     415             :         }
     416             :     }
     417      203972 :     if( rPrefixLen )
     418             :     {
     419      148626 :         rpPrefix = pwName;
     420      148626 :         rpName = &pwName[ rPrefixLen + 1 ];
     421             :     }
     422             :     else
     423             :     {
     424       55346 :         rpPrefix = 0;
     425       55346 :         rpName = pwName;
     426             :     }
     427      203972 : }
     428             : 
     429             : /***************
     430             : *
     431             : * parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
     432             : * the file-specific initialization work. (During a parser run, external files may be opened)
     433             : *
     434             : ****************/
     435        1883 : void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXException, IOException, RuntimeException)
     436             : {
     437             :     // Only one text at one time
     438        1883 :     MutexGuard guard( maMutex );
     439             : 
     440        3766 :     Entity entity( maData );
     441        1883 :     entity.maStructSource = maStructSource;
     442             : 
     443        1883 :     if( !entity.maStructSource.aInputStream.is() )
     444          72 :         throw SAXException("No input source", Reference< XInterface >(), Any() );
     445             : 
     446        1811 :     entity.maConverter.setInputStream( entity.maStructSource.aInputStream );
     447        1811 :     if( !entity.maStructSource.sEncoding.isEmpty() )
     448           0 :         entity.maConverter.setEncoding( OUStringToOString( entity.maStructSource.sEncoding, RTL_TEXTENCODING_ASCII_US ) );
     449             : 
     450             :     // create parser with proper encoding
     451        1811 :     entity.mpParser = XML_ParserCreate( 0 );
     452        1811 :     if( !entity.mpParser )
     453           0 :         throw SAXException("Couldn't create parser", Reference< XInterface >(), Any() );
     454             : 
     455             :     // set all necessary C-Callbacks
     456        1811 :     XML_SetUserData( entity.mpParser, this );
     457        1811 :     XML_SetElementHandler( entity.mpParser, call_callbackStartElement, call_callbackEndElement );
     458        1811 :     XML_SetCharacterDataHandler( entity.mpParser, call_callbackCharacters );
     459        1811 :     XML_SetEntityDeclHandler(entity.mpParser, call_callbackEntityDecl);
     460        1811 :     XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef );
     461             : 
     462        1811 :     pushEntity( entity );
     463             :     try
     464             :     {
     465             :         // start the document
     466        1811 :         if( entity.mxDocumentHandler.is() )
     467             :         {
     468        1811 :             Reference< XLocator > xLoc( mxDocumentLocator.get() );
     469        1811 :             entity.mxDocumentHandler->setDocumentLocator( xLoc );
     470        1811 :             entity.mxDocumentHandler->startDocument();
     471             :         }
     472             : 
     473        1811 :         parse();
     474             : 
     475             :         // finish document
     476        1810 :         if( entity.mxDocumentHandler.is() )
     477             :         {
     478        1810 :             entity.mxDocumentHandler->endDocument();
     479             :         }
     480             :     }
     481           2 :     catch (const SAXException&)
     482             :     {
     483           1 :         popEntity();
     484           1 :         XML_ParserFree( entity.mpParser );
     485           1 :           throw;
     486             :     }
     487           0 :     catch (const IOException&)
     488             :     {
     489           0 :         popEntity();
     490           0 :         XML_ParserFree( entity.mpParser );
     491           0 :         throw;
     492             :     }
     493           0 :     catch (const RuntimeException&)
     494             :     {
     495           0 :         popEntity();
     496           0 :         XML_ParserFree( entity.mpParser );
     497           0 :         throw;
     498             :     }
     499             : 
     500        1810 :     popEntity();
     501        3693 :     XML_ParserFree( entity.mpParser );
     502        1810 : }
     503             : 
     504        2168 : void FastSaxParser::setFastDocumentHandler( const Reference< XFastDocumentHandler >& Handler ) throw (RuntimeException)
     505             : {
     506        2168 :     maData.mxDocumentHandler = Handler;
     507        2168 : }
     508             : 
     509        2017 : void SAL_CALL FastSaxParser::setTokenHandler( const Reference< XFastTokenHandler >& Handler ) throw (RuntimeException)
     510             : {
     511        2017 :     maData.mxTokenHandler = Handler;
     512        2017 : }
     513             : 
     514       28029 : void SAL_CALL FastSaxParser::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) throw (IllegalArgumentException, RuntimeException)
     515             : {
     516       28029 :     if( NamespaceToken >= FastToken::NAMESPACE )
     517             :     {
     518       28029 :         if( GetNamespaceToken( NamespaceURL ) == FastToken::DONTKNOW )
     519             :         {
     520       28029 :             maNamespaceMap[ NamespaceURL ] = NamespaceToken;
     521       56058 :             return;
     522             :         }
     523             :     }
     524           0 :     throw IllegalArgumentException();
     525             : }
     526             : 
     527           6 : OUString SAL_CALL FastSaxParser::getNamespaceURL( const OUString& rPrefix ) throw(IllegalArgumentException, RuntimeException)
     528             : {
     529             :     try
     530             :     {
     531          12 :         return GetNamespaceURL( OUStringToOString( rPrefix, RTL_TEXTENCODING_UTF8 ) );
     532             :     }
     533           0 :     catch (const Exception&)
     534             :     {
     535             :     }
     536           0 :     throw IllegalArgumentException();
     537             : }
     538             : 
     539           0 : void FastSaxParser::setErrorHandler(const Reference< XErrorHandler > & Handler) throw (RuntimeException)
     540             : {
     541           0 :     maData.mxErrorHandler = Handler;
     542           0 : }
     543             : 
     544           0 : void FastSaxParser::setEntityResolver(const Reference < XEntityResolver > & Resolver) throw (RuntimeException)
     545             : {
     546           0 :     maData.mxEntityResolver = Resolver;
     547           0 : }
     548             : 
     549           0 : void FastSaxParser::setLocale( const Locale & Locale ) throw (RuntimeException)
     550             : {
     551           0 :     maData.maLocale = Locale;
     552           0 : }
     553             : 
     554          13 : Sequence< OUString > FastSaxParser::getSupportedServiceNames_Static(void)
     555             : {
     556          13 :     Sequence<OUString> aRet(1);
     557          13 :     aRet.getArray()[0] = OUString( PARSER_SERVICE_NAME );
     558          13 :     return aRet;
     559             : }
     560             : 
     561             : // XServiceInfo
     562           0 : OUString FastSaxParser::getImplementationName() throw (RuntimeException)
     563             : {
     564           0 :     return OUString( PARSER_IMPLEMENTATION_NAME );
     565             : }
     566             : 
     567             : // XServiceInfo
     568           0 : sal_Bool FastSaxParser::supportsService(const OUString& ServiceName) throw (RuntimeException)
     569             : {
     570           0 :     Sequence< OUString > aSNL = getSupportedServiceNames();
     571           0 :     const OUString * pArray = aSNL.getConstArray();
     572             : 
     573           0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
     574           0 :         if( pArray[i] == ServiceName )
     575           0 :             return sal_True;
     576             : 
     577           0 :     return sal_False;
     578             : }
     579             : 
     580             : // XServiceInfo
     581           0 : Sequence< OUString > FastSaxParser::getSupportedServiceNames(void) throw (RuntimeException)
     582             : {
     583             : 
     584           0 :     Sequence<OUString> seq(1);
     585           0 :     seq.getArray()[0] = OUString( PARSER_SERVICE_NAME );
     586           0 :     return seq;
     587             : }
     588             : 
     589             : 
     590             : /*---------------------------------------
     591             : *
     592             : * Helper functions and classes
     593             : *
     594             : *-------------------------------------------*/
     595             : 
     596             : namespace {
     597             : 
     598           1 : OUString lclGetErrorMessage( XML_Error xmlE, const OUString& sSystemId, sal_Int32 nLine )
     599             : {
     600           1 :     const sal_Char* pMessage = "";
     601           1 :     switch( xmlE )
     602             :     {
     603           0 :         case XML_ERROR_NONE:                            pMessage = "No";                                    break;
     604           0 :         case XML_ERROR_NO_MEMORY:                       pMessage = "no memory";                             break;
     605           0 :         case XML_ERROR_SYNTAX:                          pMessage = "syntax";                                break;
     606           0 :         case XML_ERROR_NO_ELEMENTS:                     pMessage = "no elements";                           break;
     607           0 :         case XML_ERROR_INVALID_TOKEN:                   pMessage = "invalid token";                         break;
     608           0 :         case XML_ERROR_UNCLOSED_TOKEN:                  pMessage = "unclosed token";                        break;
     609           0 :         case XML_ERROR_PARTIAL_CHAR:                    pMessage = "partial char";                          break;
     610           1 :         case XML_ERROR_TAG_MISMATCH:                    pMessage = "tag mismatch";                          break;
     611           0 :         case XML_ERROR_DUPLICATE_ATTRIBUTE:             pMessage = "duplicate attribute";                   break;
     612           0 :         case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:          pMessage = "junk after doc element";                break;
     613           0 :         case XML_ERROR_PARAM_ENTITY_REF:                pMessage = "parameter entity reference";            break;
     614           0 :         case XML_ERROR_UNDEFINED_ENTITY:                pMessage = "undefined entity";                      break;
     615           0 :         case XML_ERROR_RECURSIVE_ENTITY_REF:            pMessage = "recursive entity reference";            break;
     616           0 :         case XML_ERROR_ASYNC_ENTITY:                    pMessage = "async entity";                          break;
     617           0 :         case XML_ERROR_BAD_CHAR_REF:                    pMessage = "bad char reference";                    break;
     618           0 :         case XML_ERROR_BINARY_ENTITY_REF:               pMessage = "binary entity reference";               break;
     619           0 :         case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:   pMessage = "attribute external entity reference";   break;
     620           0 :         case XML_ERROR_MISPLACED_XML_PI:                pMessage = "misplaced xml processing instruction";  break;
     621           0 :         case XML_ERROR_UNKNOWN_ENCODING:                pMessage = "unknown encoding";                      break;
     622           0 :         case XML_ERROR_INCORRECT_ENCODING:              pMessage = "incorrect encoding";                    break;
     623           0 :         case XML_ERROR_UNCLOSED_CDATA_SECTION:          pMessage = "unclosed cdata section";                break;
     624           0 :         case XML_ERROR_EXTERNAL_ENTITY_HANDLING:        pMessage = "external entity reference";             break;
     625           0 :         case XML_ERROR_NOT_STANDALONE:                  pMessage = "not standalone";                        break;
     626             :         default:;
     627             :     }
     628             : 
     629           1 :     OUStringBuffer aBuffer( sal_Unicode( '[' ) );
     630           1 :     aBuffer.append( sSystemId );
     631           1 :     aBuffer.append( " line " );
     632           1 :     aBuffer.append( nLine );
     633           1 :     aBuffer.append( "]: " );
     634           1 :     aBuffer.append( pMessage );
     635           1 :     aBuffer.append( " error" );
     636           1 :     return aBuffer.makeStringAndClear();
     637             : }
     638             : 
     639             : } // namespace
     640             : 
     641             : // starts parsing with actual parser !
     642        1811 : void FastSaxParser::parse()
     643             : {
     644        1811 :     const int BUFFER_SIZE = 16 * 1024;
     645        1811 :     Sequence< sal_Int8 > seqOut( BUFFER_SIZE );
     646             : 
     647        1811 :     Entity& rEntity = getEntity();
     648        1811 :     int nRead = 0;
     649        1884 :     do
     650             :     {
     651        3695 :         nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE );
     652        3695 :         if( nRead <= 0 )
     653             :         {
     654        1810 :             XML_Parse( rEntity.mpParser, (const char*) seqOut.getConstArray(), 0, 1 );
     655        1810 :             break;
     656             :         }
     657             : 
     658             :         bool const bContinue = XML_STATUS_ERROR != XML_Parse(rEntity.mpParser,
     659        1885 :             reinterpret_cast<const char*>(seqOut.getConstArray()), nRead, 0);
     660             :         // callbacks used inside XML_Parse may have caught an exception
     661        1885 :         if( !bContinue || rEntity.maSavedException.hasValue() )
     662             :         {
     663             :             // Error during parsing !
     664           1 :             XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser );
     665           1 :             OUString sSystemId = mxDocumentLocator->getSystemId();
     666           1 :             sal_Int32 nLine = mxDocumentLocator->getLineNumber();
     667             : 
     668             :             SAXParseException aExcept(
     669             :                 lclGetErrorMessage( xmlE, sSystemId, nLine ),
     670             :                 Reference< XInterface >(),
     671           1 :                 Any( &rEntity.maSavedException, getCppuType( &rEntity.maSavedException ) ),
     672           1 :                 mxDocumentLocator->getPublicId(),
     673           1 :                 mxDocumentLocator->getSystemId(),
     674           1 :                 mxDocumentLocator->getLineNumber(),
     675           1 :                 mxDocumentLocator->getColumnNumber()
     676           6 :             );
     677             : 
     678             :             // error handler is set, it may throw the exception
     679           1 :             if( rEntity.mxErrorHandler.is() )
     680           0 :                 rEntity.mxErrorHandler->fatalError( Any( aExcept ) );
     681             : 
     682             :             // error handler has not thrown, but parsing cannot go on, the
     683             :             // exception MUST be thrown
     684           2 :             throw aExcept;
     685             :         }
     686             :     }
     687        1811 :     while( nRead > 0 );
     688        1810 : }
     689             : 
     690             : //------------------------------------------
     691             : //
     692             : // The C-Callbacks
     693             : //
     694             : //-----------------------------------------
     695             : 
     696             : namespace {
     697             : 
     698      327778 : struct AttributeData
     699             : {
     700             :     OString             maPrefix;
     701             :     OString             maName;
     702             :     OString             maValue;
     703             : };
     704             : 
     705             : } // namespace
     706             : 
     707      112475 : void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
     708             : {
     709      112475 :     Reference< XFastContextHandler > xParentContext;
     710      112475 :     Entity& rEntity = getEntity();
     711      112475 :     if( !rEntity.maContextStack.empty() )
     712             :     {
     713      110664 :         xParentContext = rEntity.maContextStack.top()->mxContext;
     714      110664 :         if( !xParentContext.is() )
     715             :         {
     716             :             // we ignore current elements, so no processing needed
     717       22289 :             pushContext();
     718      134764 :             return;
     719             :         }
     720             :     }
     721             : 
     722       90186 :     pushContext();
     723             : 
     724       90186 :     rEntity.mxAttributes->clear();
     725             : 
     726             :     // create attribute map and process namespace instructions
     727       90186 :     int i = 0;
     728             :     sal_Int32 nNameLen, nPrefixLen;
     729             :     const XML_Char *pName;
     730             :     const XML_Char *pPrefix;
     731             : 
     732             :     try
     733             :     {
     734             :         /*  #158414# Each element may define new namespaces, also for attribues.
     735             :             First, process all namespace attributes and cache other attributes in a
     736             :             vector. Second, process the attributes after namespaces have been
     737             :             initialized. */
     738       90186 :         ::std::vector< AttributeData > aAttribs;
     739             : 
     740             :         // #158414# first: get namespaces
     741      203972 :         for( ; awAttributes[i]; i += 2 )
     742             :         {
     743             :             assert(awAttributes[i+1]);
     744             : 
     745      113786 :             splitName( awAttributes[i], pPrefix, nPrefixLen, pName, nNameLen );
     746      113786 :             if( nPrefixLen )
     747             :             {
     748       68326 :                 if( (nPrefixLen == 5) && (strncmp( pPrefix, "xmlns", 5 ) == 0) )
     749             :                 {
     750        5874 :                     DefineNamespace( OString( pName, nNameLen ), awAttributes[i+1] );
     751             :                 }
     752             :                 else
     753             :                 {
     754       62452 :                     aAttribs.resize( aAttribs.size() + 1 );
     755       62452 :                     aAttribs.back().maPrefix = OString( pPrefix, nPrefixLen );
     756       62452 :                     aAttribs.back().maName = OString( pName, nNameLen );
     757       62452 :                     aAttribs.back().maValue = OString( awAttributes[i+1] );
     758             :                 }
     759             :             }
     760             :             else
     761             :             {
     762       45460 :                 if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
     763             :                 {
     764             :                     // namespace of the element found
     765         745 :                     rEntity.maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
     766             :                 }
     767             :                 else
     768             :                 {
     769       44715 :                     aAttribs.resize( aAttribs.size() + 1 );
     770       44715 :                     aAttribs.back().maName = OString( pName, nNameLen );
     771       44715 :                     aAttribs.back().maValue = OString( awAttributes[i+1] );
     772             :                 }
     773             :             }
     774             :         }
     775             : 
     776             :         // #158414# second: fill attribute list with other attributes
     777      197353 :         for( ::std::vector< AttributeData >::const_iterator aIt = aAttribs.begin(), aEnd = aAttribs.end(); aIt != aEnd; ++aIt )
     778             :         {
     779      107167 :             if( !aIt->maPrefix.isEmpty() )
     780             :             {
     781       62452 :                 sal_Int32 nAttributeToken = GetTokenWithPrefix( aIt->maPrefix, aIt->maName );
     782       62452 :                 if( nAttributeToken != FastToken::DONTKNOW )
     783       61949 :                     rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
     784             :                 else
     785         503 :                     rEntity.mxAttributes->addUnknown( GetNamespaceURL( aIt->maPrefix ), aIt->maName, aIt->maValue );
     786             :             }
     787             :             else
     788             :             {
     789       44715 :                 sal_Int32 nAttributeToken = GetToken( aIt->maName );
     790       44715 :                 if( nAttributeToken != FastToken::DONTKNOW )
     791       44715 :                     rEntity.mxAttributes->add( nAttributeToken, aIt->maValue );
     792             :                 else
     793           0 :                     rEntity.mxAttributes->addUnknown( aIt->maName, aIt->maValue );
     794             :             }
     795             :         }
     796             : 
     797             :         sal_Int32 nElementToken;
     798       90186 :         splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
     799       90186 :         if( nPrefixLen > 0 )
     800       80300 :             nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
     801        9886 :         else if( !rEntity.maContextStack.top()->maNamespace.isEmpty() )
     802        9882 :             nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen );
     803             :         else
     804           4 :             nElementToken = GetToken( pName );
     805       90186 :         rEntity.maContextStack.top()->mnElementToken = nElementToken;
     806             : 
     807      180372 :         Reference< XFastAttributeList > xAttr( rEntity.mxAttributes.get() );
     808      180372 :         Reference< XFastContextHandler > xContext;
     809       90186 :         if( nElementToken == FastToken::DONTKNOW )
     810             :         {
     811          34 :             if( nPrefixLen > 0 )
     812          34 :                 rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
     813             : 
     814          34 :             const OUString aNamespace( rEntity.maContextStack.top()->maNamespace );
     815          68 :             const OUString aElementName( pName, nNameLen, RTL_TEXTENCODING_UTF8 );
     816          34 :             rEntity.maContextStack.top()->maElementName = aElementName;
     817             : 
     818          34 :             if( xParentContext.is() )
     819          34 :                 xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
     820             :             else
     821           0 :                 xContext = rEntity.mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
     822             : 
     823          34 :             if( xContext.is() )
     824             :             {
     825          19 :                 rEntity.maContextStack.top()->mxContext = xContext;
     826          19 :                 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
     827          34 :             }
     828             :         }
     829             :         else
     830             :         {
     831       90152 :             if( xParentContext.is() )
     832       88341 :                 xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
     833             :             else
     834        1811 :                 xContext = rEntity.mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
     835             : 
     836             : 
     837       90152 :             if( xContext.is() )
     838             :             {
     839       85284 :                 rEntity.maContextStack.top()->mxContext = xContext;
     840       85284 :                 xContext->startFastElement( nElementToken, xAttr );
     841             :             }
     842       90186 :         }
     843             :     }
     844           0 :     catch (const Exception& e)
     845             :     {
     846           0 :         rEntity.maSavedException <<= e;
     847       90186 :     }
     848             : }
     849             : 
     850      112469 : void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
     851             : {
     852      112469 :     Entity& rEntity = getEntity();
     853             :     assert(!rEntity.maContextStack.empty()); // no context?
     854      112469 :     if( !rEntity.maContextStack.empty() )
     855             :     {
     856      112469 :         SaxContextImplPtr pContext = rEntity.maContextStack.top();
     857      112469 :         const Reference< XFastContextHandler >& xContext( pContext->mxContext );
     858      112469 :         if( xContext.is() ) try
     859             :         {
     860       85297 :             sal_Int32 nElementToken = pContext->mnElementToken;
     861       85297 :             if( nElementToken != FastToken::DONTKNOW )
     862       85278 :                 xContext->endFastElement( nElementToken );
     863             :             else
     864          19 :                 xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName );
     865             :         }
     866           0 :         catch (const Exception& e)
     867             :         {
     868           0 :             rEntity.maSavedException <<= e;
     869             :         }
     870             : 
     871      112469 :         popContext();
     872             :     }
     873      112469 : }
     874             : 
     875             : 
     876       21067 : void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
     877             : {
     878       21067 :     Entity& rEntity = getEntity();
     879       21067 :     const Reference< XFastContextHandler >& xContext( rEntity.maContextStack.top()->mxContext );
     880       21067 :     if( xContext.is() ) try
     881             :     {
     882       20648 :         xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
     883             :     }
     884           0 :     catch (const Exception& e)
     885             :     {
     886           0 :         rEntity.maSavedException <<= e;
     887             :     }
     888       21067 : }
     889             : 
     890           0 : void FastSaxParser::callbackEntityDecl(
     891             :     SAL_UNUSED_PARAMETER const XML_Char * /*entityName*/,
     892             :     SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
     893             :     const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
     894             :     SAL_UNUSED_PARAMETER const XML_Char * /*base*/,
     895             :     SAL_UNUSED_PARAMETER const XML_Char * /*systemId*/,
     896             :     SAL_UNUSED_PARAMETER const XML_Char * /*publicId*/,
     897             :     SAL_UNUSED_PARAMETER const XML_Char * /*notationName*/)
     898             : {
     899           0 :     if (value) { // value != 0 means internal entity
     900             :         SAL_INFO("sax", "FastSaxParser: internal entity declaration, stopping");
     901           0 :         XML_StopParser(getEntity().mpParser, XML_FALSE);
     902           0 :         getEntity().maSavedException <<= SAXParseException(
     903             :             "FastSaxParser: internal entity declaration, stopping",
     904             :             static_cast<OWeakObject*>(this), Any(),
     905           0 :             mxDocumentLocator->getPublicId(),
     906           0 :             mxDocumentLocator->getSystemId(),
     907           0 :             mxDocumentLocator->getLineNumber(),
     908           0 :             mxDocumentLocator->getColumnNumber() );
     909             :     } else {
     910             :         SAL_INFO("sax", "FastSaxParser: ignoring external entity declaration");
     911             :     }
     912           0 : }
     913             : 
     914           0 : int FastSaxParser::callbackExternalEntityRef(
     915             :     XML_Parser parser, const XML_Char *context,
     916             :     SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
     917             :     const XML_Char *publicId )
     918             : {
     919           0 :     bool bOK = true;
     920           0 :     InputSource source;
     921             : 
     922           0 :     Entity& rCurrEntity = getEntity();
     923           0 :     Entity aNewEntity( rCurrEntity );
     924             : 
     925           0 :     if( rCurrEntity.mxEntityResolver.is() ) try
     926             :     {
     927           0 :         aNewEntity.maStructSource = rCurrEntity.mxEntityResolver->resolveEntity(
     928           0 :             OUString( publicId, strlen( publicId ), RTL_TEXTENCODING_UTF8 ) ,
     929           0 :             OUString( systemId, strlen( systemId ), RTL_TEXTENCODING_UTF8 ) );
     930             :     }
     931           0 :     catch (const SAXParseException & e)
     932             :     {
     933           0 :         rCurrEntity.maSavedException <<= e;
     934           0 :         bOK = false;
     935             :     }
     936           0 :     catch (const SAXException& e)
     937             :     {
     938           0 :         rCurrEntity.maSavedException <<= SAXParseException(
     939             :             e.Message, e.Context, e.WrappedException,
     940           0 :             mxDocumentLocator->getPublicId(),
     941           0 :             mxDocumentLocator->getSystemId(),
     942           0 :             mxDocumentLocator->getLineNumber(),
     943           0 :             mxDocumentLocator->getColumnNumber() );
     944           0 :         bOK = false;
     945             :     }
     946             : 
     947           0 :     if( aNewEntity.maStructSource.aInputStream.is() )
     948             :     {
     949           0 :         aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 );
     950           0 :         if( !aNewEntity.mpParser )
     951             :         {
     952           0 :             return false;
     953             :         }
     954             : 
     955           0 :         aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream );
     956           0 :         pushEntity( aNewEntity );
     957             :         try
     958             :         {
     959           0 :             parse();
     960             :         }
     961           0 :         catch (const SAXParseException& e)
     962             :         {
     963           0 :             rCurrEntity.maSavedException <<= e;
     964           0 :             bOK = false;
     965             :         }
     966           0 :         catch (const IOException& e)
     967             :         {
     968           0 :             SAXException aEx;
     969           0 :             aEx.WrappedException <<= e;
     970           0 :             rCurrEntity.maSavedException <<= aEx;
     971           0 :             bOK = false;
     972             :         }
     973           0 :         catch (const RuntimeException& e)
     974             :         {
     975           0 :             SAXException aEx;
     976           0 :             aEx.WrappedException <<= e;
     977           0 :             rCurrEntity.maSavedException <<= aEx;
     978           0 :             bOK = false;
     979             :         }
     980             : 
     981           0 :         popEntity();
     982           0 :         XML_ParserFree( aNewEntity.mpParser );
     983             :     }
     984             : 
     985           0 :     return bOK;
     986             : }
     987             : 
     988             : } // namespace sax_fastparser
     989             : 
     990             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10