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

Generated by: LCOV version 1.10