1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sax/fastparser.hxx"
21 #include "sax/fastattribs.hxx"
22 #include "xml2utf.hxx"
24 #include <com/sun/star/lang/DisposedException.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <com/sun/star/xml/sax/FastToken.hpp>
27 #include <com/sun/star/xml/sax/SAXParseException.hpp>
28 #include <com/sun/star/xml/sax/XFastContextHandler.hpp>
29 #include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
30 #include <com/sun/star/xml/sax/XFastTokenHandler.hpp>
31 #include <cppuhelper/supportsservice.hxx>
32 #include <cppuhelper/exc_hlp.hxx>
33 #include <osl/conditn.hxx>
34 #include <osl/diagnose.h>
35 #include <rtl/ref.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <sal/log.hxx>
38 #include <salhelper/thread.hxx>
40 #include <boost/optional.hpp>
41 #include <boost/scoped_ptr.hpp>
42 #include <boost/shared_ptr.hpp>
44 #include <unordered_map>
49 #include <libxml/parser.h>
51 // Inverse of libxml's BAD_CAST.
52 #define XML_CAST( str ) reinterpret_cast< const sal_Char* >( str )
54 using namespace ::std
;
55 using namespace ::osl
;
56 using namespace ::cppu
;
57 using namespace ::com::sun::star::uno
;
58 using namespace ::com::sun::star::lang
;
59 using namespace ::com::sun::star::xml::sax
;
60 using namespace ::com::sun::star::io
;
61 using namespace com::sun::star
;
62 using namespace sax_fastparser
;
67 class FastLocatorImpl
;
68 struct NamespaceDefine
;
71 typedef ::boost::shared_ptr
< NamespaceDefine
> NamespaceDefineRef
;
73 typedef std::unordered_map
< OUString
, sal_Int32
,
74 OUStringHash
, ::std::equal_to
< OUString
> > NamespaceMap
;
76 typedef std::vector
<Event
> EventList
;
78 enum CallbackType
{ INVALID
, START_ELEMENT
, END_ELEMENT
, CHARACTERS
, DONE
, EXCEPTION
};
83 sal_Int32 mnElementToken
;
85 OUString msElementName
;
86 rtl::Reference
< FastAttributeList
> mxAttributes
;
95 NameWithToken(const OUString
& sName
, const sal_Int32
& nToken
) :
96 msName(sName
), mnToken(nToken
) {}
101 Reference
< XFastContextHandler
> mxContext
;
102 sal_Int32 mnElementToken
;
103 OUString maNamespace
;
104 OUString maElementName
;
106 SaxContext( sal_Int32 nElementToken
, const OUString
& aNamespace
, const OUString
& aElementName
):
107 mnElementToken(nElementToken
)
109 if (nElementToken
== FastToken::DONTKNOW
)
111 maNamespace
= aNamespace
;
112 maElementName
= aElementName
;
120 ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XFastDocumentHandler
> mxDocumentHandler
;
121 ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XFastTokenHandler
> mxTokenHandler
;
122 FastTokenHandlerBase
*mpTokenHandler
;
123 ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XErrorHandler
> mxErrorHandler
;
124 ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XEntityResolver
> mxEntityResolver
;
125 ::com::sun::star::lang::Locale maLocale
;
131 struct NamespaceDefine
135 OUString maNamespaceURL
;
137 NamespaceDefine( const OString
& rPrefix
, sal_Int32 nToken
, const OUString
& rNamespaceURL
) : maPrefix( rPrefix
), mnToken( nToken
), maNamespaceURL( rNamespaceURL
) {}
140 // Entity binds all information needed for a single file | single call of parseStream
141 struct Entity
: public ParserData
143 // Amount of work producer sends to consumer in one iteration:
144 static const size_t mnEventListSize
= 1000;
146 // unique for each Entity instance:
148 // Number of valid events in mpProducedEvents:
149 size_t mnProducedEventsSize
;
150 EventList
*mpProducedEvents
;
151 std::queue
< EventList
* > maPendingEvents
;
152 std::queue
< EventList
* > maUsedEvents
;
153 osl::Mutex maEventProtector
;
155 static const size_t mnEventLowWater
= 4;
156 static const size_t mnEventHighWater
= 8;
157 osl::Condition maConsumeResume
;
158 osl::Condition maProduceResume
;
159 // Event we use to store data if threading is disabled:
162 // copied in copy constructor:
164 // Allow to disable threading for small documents:
165 bool mbEnableThreads
;
166 ::com::sun::star::xml::sax::InputSource maStructSource
;
167 xmlParserCtxtPtr mpParser
;
168 ::sax_expatwrap::XMLFile2UTFConverter maConverter
;
170 // Exceptions cannot be thrown through the C-XmlParser (possible
171 // resource leaks), therefore any exception thrown by a UNO callback
172 // must be saved somewhere until the C-XmlParser is stopped.
173 ::com::sun::star::uno::Any maSavedException
;
174 void saveException( const Any
& e
);
175 void throwException( const ::rtl::Reference
< FastLocatorImpl
> &xDocumentLocator
,
176 bool mbDuringParse
);
178 ::std::stack
< NameWithToken
> maNamespaceStack
;
179 /* Context for main thread consuming events.
180 * startElement() stores the data, which characters() and endElement() uses
182 ::std::stack
< SaxContext
> maContextStack
;
183 // Determines which elements of maNamespaceDefines are valid in current context
184 ::std::stack
< sal_uInt32
> maNamespaceCount
;
185 ::std::vector
< NamespaceDefineRef
> maNamespaceDefines
;
187 explicit Entity( const ParserData
& rData
);
188 Entity( const Entity
& rEntity
);
190 void startElement( Event
*pEvent
);
191 void characters( const OUString
& sChars
);
193 EventList
* getEventList();
194 Event
& getEvent( CallbackType aType
);
199 namespace sax_fastparser
{
201 class FastSaxParserImpl
204 FastSaxParserImpl( FastSaxParser
* pFront
);
205 ~FastSaxParserImpl();
208 void parseStream( const ::com::sun::star::xml::sax::InputSource
& aInputSource
) throw (::com::sun::star::xml::sax::SAXException
, ::com::sun::star::io::IOException
, ::com::sun::star::uno::RuntimeException
, std::exception
);
209 void setFastDocumentHandler( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XFastDocumentHandler
>& Handler
) throw (::com::sun::star::uno::RuntimeException
);
210 void setTokenHandler( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XFastTokenHandler
>& Handler
) throw (::com::sun::star::uno::RuntimeException
);
211 void registerNamespace( const OUString
& NamespaceURL
, sal_Int32 NamespaceToken
) throw (::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
);
212 OUString
getNamespaceURL( const OUString
& rPrefix
) throw(::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
);
213 void setErrorHandler( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XErrorHandler
>& Handler
) throw (::com::sun::star::uno::RuntimeException
);
214 void setEntityResolver( const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XEntityResolver
>& Resolver
) throw (::com::sun::star::uno::RuntimeException
);
215 void setLocale( const ::com::sun::star::lang::Locale
& rLocale
) throw (::com::sun::star::uno::RuntimeException
);
217 // called by the C callbacks of the expat parser
218 void callbackStartElement( const xmlChar
*localName
, const xmlChar
* prefix
, const xmlChar
* URI
,
219 int numNamespaces
, const xmlChar
** namespaces
, int numAttributes
, int defaultedAttributes
, const xmlChar
**attributes
);
220 void callbackEndElement( const xmlChar
* localName
, const xmlChar
* prefix
, const xmlChar
* URI
);
221 void callbackCharacters( const xmlChar
* s
, int nLen
);
223 bool callbackExternalEntityRef( XML_Parser parser
, const xmlChar
*openEntityNames
, const xmlChar
*base
, const xmlChar
*systemId
, const xmlChar
*publicId
);
224 void callbackEntityDecl(const xmlChar
*entityName
, int is_parameter_entity
,
225 const xmlChar
*value
, int value_length
, const xmlChar
*base
,
226 const xmlChar
*systemId
, const xmlChar
*publicId
,
227 const xmlChar
*notationName
);
230 void pushEntity( const Entity
& rEntity
);
232 Entity
& getEntity() { return *mpTop
; }
233 const Entity
& getEntity() const { return *mpTop
; }
235 void produce( bool bForceFlush
= false );
237 bool hasNamespaceURL( const OUString
& rPrefix
) const;
240 bool consume(EventList
*);
241 void deleteUsedEvents();
242 void sendPendingCharacters();
244 sal_Int32
GetToken( const xmlChar
* pName
, sal_Int32 nameLen
);
245 sal_Int32
GetTokenWithPrefix( const xmlChar
* pPrefix
, int prefixLen
, const xmlChar
* pName
, int nameLen
) throw (::com::sun::star::xml::sax::SAXException
);
246 OUString
GetNamespaceURL( const OString
& rPrefix
) throw (::com::sun::star::xml::sax::SAXException
);
247 sal_Int32
GetNamespaceToken( const OUString
& rNamespaceURL
);
248 sal_Int32
GetTokenWithContextNamespace( sal_Int32 nNamespaceToken
, const xmlChar
* pName
, int nNameLen
);
249 void DefineNamespace( const OString
& rPrefix
, const OUString
& namespaceURL
);
253 FastSaxParser
* mpFront
;
255 osl::Mutex maMutex
; ///< Protecting whole parseStream() execution
256 ::rtl::Reference
< FastLocatorImpl
> mxDocumentLocator
;
257 NamespaceMap maNamespaceMap
;
259 ParserData maData
; /// Cached parser configuration for next call of parseStream().
261 Entity
*mpTop
; /// std::stack::top() is amazingly slow => cache this.
262 ::std::stack
< Entity
> maEntities
; /// Entity stack for each call of parseStream().
263 OUString pendingCharacters
; /// Data from characters() callback that needs to be sent.
266 } // namespace sax_fastparser
270 class ParserThread
: public salhelper::Thread
272 FastSaxParserImpl
*mpParser
;
274 ParserThread(FastSaxParserImpl
*pParser
): Thread("Parser"), mpParser(pParser
) {}
276 virtual void execute() SAL_OVERRIDE
282 catch (const Exception
&)
284 Entity
&rEntity
= mpParser
->getEntity();
285 rEntity
.getEvent( EXCEPTION
);
286 mpParser
->produce( true );
293 static void call_callbackStartElement(void *userData
, const xmlChar
*localName
, const xmlChar
* prefix
, const xmlChar
* URI
,
294 int numNamespaces
, const xmlChar
** namespaces
, int numAttributes
, int defaultedAttributes
, const xmlChar
**attributes
)
296 FastSaxParserImpl
* pFastParser
= static_cast<FastSaxParserImpl
*>( userData
);
297 pFastParser
->callbackStartElement( localName
, prefix
, URI
, numNamespaces
, namespaces
, numAttributes
, defaultedAttributes
, attributes
);
300 static void call_callbackEndElement(void *userData
, const xmlChar
* localName
, const xmlChar
* prefix
, const xmlChar
* URI
)
302 FastSaxParserImpl
* pFastParser
= static_cast<FastSaxParserImpl
*>( userData
);
303 pFastParser
->callbackEndElement( localName
, prefix
, URI
);
306 static void call_callbackCharacters( void *userData
, const xmlChar
*s
, int nLen
)
308 FastSaxParserImpl
* pFastParser
= static_cast<FastSaxParserImpl
*>( userData
);
309 pFastParser
->callbackCharacters( s
, nLen
);
313 static void call_callbackEntityDecl(void *userData
, const xmlChar
*entityName
,
314 int is_parameter_entity
, const xmlChar
*value
, int value_length
,
315 const xmlChar
*base
, const xmlChar
*systemId
,
316 const xmlChar
*publicId
, const xmlChar
*notationName
)
318 FastSaxParserImpl
* pFastParser
= reinterpret_cast<FastSaxParserImpl
*>(userData
);
319 pFastParser
->callbackEntityDecl(entityName
, is_parameter_entity
, value
,
320 value_length
, base
, systemId
, publicId
, notationName
);
323 static int call_callbackExternalEntityRef( XML_Parser parser
,
324 const xmlChar
*openEntityNames
, const xmlChar
*base
, const xmlChar
*systemId
, const xmlChar
*publicId
)
326 FastSaxParserImpl
* pFastParser
= reinterpret_cast<FastSaxParserImpl
*>( XML_GetUserData( parser
) );
327 return pFastParser
->callbackExternalEntityRef( parser
, openEntityNames
, base
, systemId
, publicId
);
332 class FastLocatorImpl
: public WeakImplHelper1
< XLocator
>
335 FastLocatorImpl( FastSaxParserImpl
*p
) : mpParser(p
) {}
337 void dispose() { mpParser
= 0; }
338 void checkDispose() throw (RuntimeException
) { if( !mpParser
) throw DisposedException(); }
341 virtual sal_Int32 SAL_CALL
getColumnNumber() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
342 virtual sal_Int32 SAL_CALL
getLineNumber() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
343 virtual OUString SAL_CALL
getPublicId() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
344 virtual OUString SAL_CALL
getSystemId() throw (RuntimeException
, std::exception
) SAL_OVERRIDE
;
347 FastSaxParserImpl
*mpParser
;
350 sal_Int32 SAL_CALL
FastLocatorImpl::getColumnNumber() throw (RuntimeException
, std::exception
)
353 return xmlSAX2GetColumnNumber( mpParser
->getEntity().mpParser
);
356 sal_Int32 SAL_CALL
FastLocatorImpl::getLineNumber() throw (RuntimeException
, std::exception
)
359 return xmlSAX2GetLineNumber( mpParser
->getEntity().mpParser
);
362 OUString SAL_CALL
FastLocatorImpl::getPublicId() throw (RuntimeException
, std::exception
)
365 return mpParser
->getEntity().maStructSource
.sPublicId
;
368 OUString SAL_CALL
FastLocatorImpl::getSystemId() throw (RuntimeException
, std::exception
)
371 return mpParser
->getEntity().maStructSource
.sSystemId
;
374 ParserData::ParserData()
375 : mpTokenHandler( NULL
)
378 ParserData::~ParserData()
381 Entity::Entity(const ParserData
& rData
)
383 , mnProducedEventsSize(0)
384 , mpProducedEvents(NULL
)
385 , mbEnableThreads(false)
390 Entity::Entity(const Entity
& e
)
392 , mnProducedEventsSize(0)
393 , mpProducedEvents(NULL
)
394 , mbEnableThreads(e
.mbEnableThreads
)
395 , maStructSource(e
.maStructSource
)
396 , mpParser(e
.mpParser
)
397 , maConverter(e
.maConverter
)
398 , maSavedException(e
.maSavedException
)
399 , maNamespaceStack(e
.maNamespaceStack
)
400 , maContextStack(e
.maContextStack
)
401 , maNamespaceCount(e
.maNamespaceCount
)
402 , maNamespaceDefines(e
.maNamespaceDefines
)
410 void Entity::startElement( Event
*pEvent
)
412 const sal_Int32
& nElementToken
= pEvent
->mnElementToken
;
413 const OUString
& aNamespace
= pEvent
->msNamespace
;
414 const OUString
& aElementName
= pEvent
->msElementName
;
416 // Use un-wrapped pointers to avoid significant acquire/release overhead
417 XFastContextHandler
*pParentContext
= NULL
;
418 if( !maContextStack
.empty() )
420 pParentContext
= maContextStack
.top().mxContext
.get();
421 if( !pParentContext
)
423 maContextStack
.push( SaxContext(nElementToken
, aNamespace
, aElementName
) );
428 maContextStack
.push( SaxContext( nElementToken
, aNamespace
, aElementName
) );
432 Reference
< XFastAttributeList
> xAttr( pEvent
->mxAttributes
.get() );
433 Reference
< XFastContextHandler
> xContext
;
434 if( nElementToken
== FastToken::DONTKNOW
)
437 xContext
= pParentContext
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
438 else if( mxDocumentHandler
.is() )
439 xContext
= mxDocumentHandler
->createUnknownChildContext( aNamespace
, aElementName
, xAttr
);
443 xContext
->startUnknownElement( aNamespace
, aElementName
, xAttr
);
449 xContext
= pParentContext
->createFastChildContext( nElementToken
, xAttr
);
450 else if( mxDocumentHandler
.is() )
451 xContext
= mxDocumentHandler
->createFastChildContext( nElementToken
, xAttr
);
454 xContext
->startFastElement( nElementToken
, xAttr
);
456 // swap the reference we own in to avoid referencing thrash.
457 maContextStack
.top().mxContext
.set( static_cast<XFastContextHandler
*>( xContext
.get() ) );
458 xContext
.set( NULL
, UNO_REF_NO_ACQUIRE
);
460 catch (const Exception
&)
462 saveException( ::cppu::getCaughtException() );
466 void Entity::characters( const OUString
& sChars
)
468 if (maContextStack
.empty())
470 // Malformed XML stream !?
474 const Reference
< XFastContextHandler
>& xContext( maContextStack
.top().mxContext
);
475 if( xContext
.is() ) try
477 xContext
->characters( sChars
);
479 catch (const Exception
&)
481 saveException( ::cppu::getCaughtException() );
485 void Entity::endElement()
487 if (maContextStack
.empty())
489 // Malformed XML stream !?
493 const SaxContext
& aContext
= maContextStack
.top();
494 const Reference
< XFastContextHandler
>& xContext( aContext
.mxContext
);
495 if( xContext
.is() ) try
497 sal_Int32 nElementToken
= aContext
.mnElementToken
;
498 if( nElementToken
!= FastToken::DONTKNOW
)
499 xContext
->endFastElement( nElementToken
);
501 xContext
->endUnknownElement( aContext
.maNamespace
, aContext
.maElementName
);
503 catch (const Exception
&)
505 saveException( ::cppu::getCaughtException() );
507 maContextStack
.pop();
510 EventList
* Entity::getEventList()
512 if (!mpProducedEvents
)
514 osl::ResettableMutexGuard
aGuard(maEventProtector
);
515 if (!maUsedEvents
.empty())
517 mpProducedEvents
= maUsedEvents
.front();
519 aGuard
.clear(); // unlock
520 mnProducedEventsSize
= 0;
522 if (!mpProducedEvents
)
524 mpProducedEvents
= new EventList();
525 mpProducedEvents
->resize(mnEventListSize
);
526 mnProducedEventsSize
= 0;
529 return mpProducedEvents
;
532 Event
& Entity::getEvent( CallbackType aType
)
534 if (!mbEnableThreads
)
535 return maSharedEvent
;
537 EventList
* pEventList
= getEventList();
538 Event
& rEvent
= (*pEventList
)[mnProducedEventsSize
++];
539 rEvent
.maType
= aType
;
543 OUString
lclGetErrorMessage( xmlParserCtxtPtr ctxt
, const OUString
& sSystemId
, sal_Int32 nLine
)
545 const sal_Char
* pMessage
;
546 xmlErrorPtr error
= xmlCtxtGetLastError( ctxt
);
547 if( error
&& error
->message
)
548 pMessage
= error
->message
;
550 pMessage
= "unknown error";
551 OUStringBuffer
aBuffer( "[" );
552 aBuffer
.append( sSystemId
);
553 aBuffer
.append( " line " );
554 aBuffer
.append( nLine
);
555 aBuffer
.append( "]: " );
556 aBuffer
.appendAscii( pMessage
);
557 return aBuffer
.makeStringAndClear();
560 // throw an exception, but avoid callback if
561 // during a threaded produce
562 void Entity::throwException( const ::rtl::Reference
< FastLocatorImpl
> &xDocumentLocator
,
565 // Error during parsing !
566 SAXParseException
aExcept(
567 lclGetErrorMessage( mpParser
,
568 xDocumentLocator
->getSystemId(),
569 xDocumentLocator
->getLineNumber() ),
570 Reference
< XInterface
>(),
571 Any( &maSavedException
, cppu::UnoType
<decltype(maSavedException
)>::get() ),
572 xDocumentLocator
->getPublicId(),
573 xDocumentLocator
->getSystemId(),
574 xDocumentLocator
->getLineNumber(),
575 xDocumentLocator
->getColumnNumber()
578 // error handler is set, it may throw the exception
579 if( !mbDuringParse
|| !mbEnableThreads
)
581 if (mxErrorHandler
.is() )
582 mxErrorHandler
->fatalError( Any( aExcept
) );
585 // error handler has not thrown, but parsing must stop => throw ourselves
589 // In the single threaded case we emit events via our C
590 // callbacks, so any exception caught must be queued up until
591 // we can safely re-throw it from our C++ parent of parse()
593 // If multi-threaded, we need to push an EXCEPTION event, at
594 // which point we transfer ownership of maSavedException to
595 // the consuming thread.
596 void Entity::saveException( const Any
& e
)
598 // fdo#81214 - allow the parser to run on after an exception,
599 // unexpectedly some 'startElements' produce an UNO_QUERY_THROW
600 // for XComponent; and yet expect to continue parsing.
601 SAL_WARN("sax", "Unexpected exception from XML parser "
602 << e
.get
<Exception
>().Message
);
603 maSavedException
= e
;
608 namespace sax_fastparser
{
610 FastSaxParserImpl::FastSaxParserImpl( FastSaxParser
* ) :
616 mxDocumentLocator
.set( new FastLocatorImpl( this ) );
619 FastSaxParserImpl::~FastSaxParserImpl()
621 if( mxDocumentLocator
.is() )
622 mxDocumentLocator
->dispose();
625 void FastSaxParserImpl::DefineNamespace( const OString
& rPrefix
, const OUString
& namespaceURL
)
627 Entity
& rEntity
= getEntity();
628 assert(!rEntity
.maNamespaceCount
.empty()); // need a context!
630 sal_uInt32 nOffset
= rEntity
.maNamespaceCount
.top()++;
631 if( rEntity
.maNamespaceDefines
.size() <= nOffset
)
632 rEntity
.maNamespaceDefines
.resize( rEntity
.maNamespaceDefines
.size() + 64 );
634 rEntity
.maNamespaceDefines
[nOffset
].reset( new NamespaceDefine( rPrefix
, GetNamespaceToken( namespaceURL
), namespaceURL
) );
637 sal_Int32
FastSaxParserImpl::GetToken( const xmlChar
* pName
, sal_Int32 nameLen
/* = 0 */ )
639 return FastTokenHandlerBase::getTokenFromChars( getEntity().mxTokenHandler
,
640 getEntity().mpTokenHandler
,
641 XML_CAST( pName
), nameLen
); // uses utf-8
644 sal_Int32
FastSaxParserImpl::GetTokenWithPrefix( const xmlChar
* pPrefix
, int nPrefixLen
, const xmlChar
* pName
, int nNameLen
) throw (SAXException
)
646 sal_Int32 nNamespaceToken
= FastToken::DONTKNOW
;
648 Entity
& rEntity
= getEntity();
649 if (rEntity
.maNamespaceCount
.empty())
650 return nNamespaceToken
;
652 sal_uInt32 nNamespace
= rEntity
.maNamespaceCount
.top();
653 while( nNamespace
-- )
655 const OString
& rPrefix( rEntity
.maNamespaceDefines
[nNamespace
]->maPrefix
);
656 if( (rPrefix
.getLength() == nPrefixLen
) &&
657 (strncmp( rPrefix
.getStr(), XML_CAST( pPrefix
), nPrefixLen
) == 0 ) )
659 nNamespaceToken
= rEntity
.maNamespaceDefines
[nNamespace
]->mnToken
;
664 throw SAXException("No namespace defined for " + OUString(XML_CAST(pPrefix
),
665 nPrefixLen
, RTL_TEXTENCODING_UTF8
), Reference
< XInterface
>(), Any());
668 if( nNamespaceToken
!= FastToken::DONTKNOW
)
670 sal_Int32 nNameToken
= GetToken( pName
, nNameLen
);
671 if( nNameToken
!= FastToken::DONTKNOW
)
672 return nNamespaceToken
| nNameToken
;
675 return FastToken::DONTKNOW
;
678 sal_Int32
FastSaxParserImpl::GetNamespaceToken( const OUString
& rNamespaceURL
)
680 NamespaceMap::iterator
aIter( maNamespaceMap
.find( rNamespaceURL
) );
681 if( aIter
!= maNamespaceMap
.end() )
682 return (*aIter
).second
;
684 return FastToken::DONTKNOW
;
687 OUString
FastSaxParserImpl::GetNamespaceURL( const OString
& rPrefix
) throw (SAXException
)
689 Entity
& rEntity
= getEntity();
690 if( !rEntity
.maNamespaceCount
.empty() )
692 sal_uInt32 nNamespace
= rEntity
.maNamespaceCount
.top();
693 while( nNamespace
-- )
694 if( rEntity
.maNamespaceDefines
[nNamespace
]->maPrefix
== rPrefix
)
695 return rEntity
.maNamespaceDefines
[nNamespace
]->maNamespaceURL
;
698 throw SAXException("No namespace defined for " + OUString::fromUtf8(rPrefix
),
699 Reference
< XInterface
>(), Any());
702 sal_Int32
FastSaxParserImpl::GetTokenWithContextNamespace( sal_Int32 nNamespaceToken
, const xmlChar
* pName
, int nNameLen
)
704 if( nNamespaceToken
!= FastToken::DONTKNOW
)
706 sal_Int32 nNameToken
= GetToken( pName
, nNameLen
);
707 if( nNameToken
!= FastToken::DONTKNOW
)
708 return nNamespaceToken
| nNameToken
;
711 return FastToken::DONTKNOW
;
716 * parseStream does Parser-startup initializations. The FastSaxParser::parse() method does
717 * the file-specific initialization work. (During a parser run, external files may be opened)
720 void FastSaxParserImpl::parseStream(const InputSource
& maStructSource
)
721 throw (SAXException
, IOException
, RuntimeException
, std::exception
)
725 // Only one text at one time
726 MutexGuard
guard( maMutex
);
728 Entity
entity( maData
);
729 entity
.maStructSource
= maStructSource
;
731 if( !entity
.mxTokenHandler
.is() )
732 throw SAXException("No token handler, use setTokenHandler()", Reference
< XInterface
>(), Any() );
734 if( !entity
.maStructSource
.aInputStream
.is() )
735 throw SAXException("No input source", Reference
< XInterface
>(), Any() );
737 entity
.maConverter
.setInputStream( entity
.maStructSource
.aInputStream
);
738 if( !entity
.maStructSource
.sEncoding
.isEmpty() )
739 entity
.maConverter
.setEncoding( OUStringToOString( entity
.maStructSource
.sEncoding
, RTL_TEXTENCODING_ASCII_US
) );
741 pushEntity( entity
);
742 Entity
& rEntity
= getEntity();
745 // start the document
746 if( rEntity
.mxDocumentHandler
.is() )
748 Reference
< XLocator
> xLoc( mxDocumentLocator
.get() );
749 rEntity
.mxDocumentHandler
->setDocumentLocator( xLoc
);
750 rEntity
.mxDocumentHandler
->startDocument();
753 rEntity
.mbEnableThreads
= (rEntity
.maStructSource
.aInputStream
->available() > 10000);
755 if (rEntity
.mbEnableThreads
)
757 rtl::Reference
<ParserThread
> xParser
;
758 xParser
= new ParserThread(this);
762 rEntity
.maConsumeResume
.wait();
763 rEntity
.maConsumeResume
.reset();
765 osl::ResettableMutexGuard
aGuard(rEntity
.maEventProtector
);
766 while (!rEntity
.maPendingEvents
.empty())
768 if (rEntity
.maPendingEvents
.size() <= rEntity
.mnEventLowWater
)
769 rEntity
.maProduceResume
.set(); // start producer again
771 EventList
*pEventList
= rEntity
.maPendingEvents
.front();
772 rEntity
.maPendingEvents
.pop();
773 aGuard
.clear(); // unlock
775 if (!consume(pEventList
))
778 aGuard
.reset(); // lock
779 rEntity
.maUsedEvents
.push(pEventList
);
791 if( rEntity
.mxDocumentHandler
.is() )
793 rEntity
.mxDocumentHandler
->endDocument();
796 catch (const SAXException
&)
798 // TODO free mpParser.myDoc ?
799 xmlFreeParserCtxt( rEntity
.mpParser
);
803 catch (const IOException
&)
805 xmlFreeParserCtxt( rEntity
.mpParser
);
809 catch (const RuntimeException
&)
811 xmlFreeParserCtxt( rEntity
.mpParser
);
816 xmlFreeParserCtxt( rEntity
.mpParser
);
820 void FastSaxParserImpl::setFastDocumentHandler( const Reference
< XFastDocumentHandler
>& Handler
) throw (RuntimeException
)
822 maData
.mxDocumentHandler
= Handler
;
825 void FastSaxParserImpl::setTokenHandler( const Reference
< XFastTokenHandler
>& xHandler
) throw (RuntimeException
)
827 maData
.mxTokenHandler
= xHandler
;
828 maData
.mpTokenHandler
= dynamic_cast< FastTokenHandlerBase
*>( xHandler
.get() );
831 void FastSaxParserImpl::registerNamespace( const OUString
& NamespaceURL
, sal_Int32 NamespaceToken
) throw (IllegalArgumentException
, RuntimeException
)
833 if( NamespaceToken
>= FastToken::NAMESPACE
)
835 if( GetNamespaceToken( NamespaceURL
) == FastToken::DONTKNOW
)
837 maNamespaceMap
[ NamespaceURL
] = NamespaceToken
;
841 throw IllegalArgumentException();
844 OUString
FastSaxParserImpl::getNamespaceURL( const OUString
& rPrefix
) throw(IllegalArgumentException
, RuntimeException
)
848 return GetNamespaceURL( OUStringToOString( rPrefix
, RTL_TEXTENCODING_UTF8
) );
850 catch (const Exception
&)
853 throw IllegalArgumentException();
856 void FastSaxParserImpl::setErrorHandler(const Reference
< XErrorHandler
> & Handler
) throw (RuntimeException
)
858 maData
.mxErrorHandler
= Handler
;
861 void FastSaxParserImpl::setEntityResolver(const Reference
< XEntityResolver
> & Resolver
) throw (RuntimeException
)
863 maData
.mxEntityResolver
= Resolver
;
866 void FastSaxParserImpl::setLocale( const lang::Locale
& Locale
) throw (RuntimeException
)
868 maData
.maLocale
= Locale
;
871 void FastSaxParserImpl::deleteUsedEvents()
873 Entity
& rEntity
= getEntity();
874 osl::ResettableMutexGuard
aGuard(rEntity
.maEventProtector
);
876 while (!rEntity
.maUsedEvents
.empty())
878 EventList
*pEventList
= rEntity
.maUsedEvents
.front();
879 rEntity
.maUsedEvents
.pop();
881 aGuard
.clear(); // unlock
885 aGuard
.reset(); // lock
889 void FastSaxParserImpl::produce( bool bForceFlush
)
891 Entity
& rEntity
= getEntity();
893 rEntity
.mnProducedEventsSize
== rEntity
.mnEventListSize
)
895 osl::ResettableMutexGuard
aGuard(rEntity
.maEventProtector
);
897 while (rEntity
.maPendingEvents
.size() >= rEntity
.mnEventHighWater
)
898 { // pause parsing for a bit
899 aGuard
.clear(); // unlock
900 rEntity
.maProduceResume
.wait();
901 rEntity
.maProduceResume
.reset();
902 aGuard
.reset(); // lock
905 rEntity
.maPendingEvents
.push(rEntity
.mpProducedEvents
);
906 rEntity
.mpProducedEvents
= 0;
908 aGuard
.clear(); // unlock
910 rEntity
.maConsumeResume
.set();
914 bool FastSaxParserImpl::hasNamespaceURL( const OUString
& rPrefix
) const
916 if (maEntities
.empty())
919 const Entity
& rEntity
= getEntity();
921 if (rEntity
.maNamespaceCount
.empty())
924 OString aPrefix
= OUStringToOString(rPrefix
, RTL_TEXTENCODING_UTF8
);
925 sal_uInt32 nNamespace
= rEntity
.maNamespaceCount
.top();
928 if (rEntity
.maNamespaceDefines
[nNamespace
]->maPrefix
== aPrefix
)
935 bool FastSaxParserImpl::consume(EventList
*pEventList
)
937 Entity
& rEntity
= getEntity();
938 for (EventList::iterator aEventIt
= pEventList
->begin();
939 aEventIt
!= pEventList
->end(); ++aEventIt
)
941 switch ((*aEventIt
).maType
)
944 rEntity
.startElement( &(*aEventIt
) );
947 rEntity
.endElement();
950 rEntity
.characters( (*aEventIt
).msChars
);
955 rEntity
.throwException( mxDocumentLocator
, false );
965 void FastSaxParserImpl::pushEntity( const Entity
& rEntity
)
967 maEntities
.push( rEntity
);
968 mpTop
= &maEntities
.top();
971 void FastSaxParserImpl::popEntity()
974 mpTop
= !maEntities
.empty() ? &maEntities
.top() : NULL
;
977 // starts parsing with actual parser !
978 void FastSaxParserImpl::parse()
980 const int BUFFER_SIZE
= 16 * 1024;
981 Sequence
< sal_Int8
> seqOut( BUFFER_SIZE
);
983 Entity
& rEntity
= getEntity();
985 // set all necessary C-Callbacks
986 static xmlSAXHandler callbacks
;
987 callbacks
.startElementNs
= call_callbackStartElement
;
988 callbacks
.endElementNs
= call_callbackEndElement
;
989 callbacks
.characters
= call_callbackCharacters
;
990 callbacks
.initialized
= XML_SAX2_MAGIC
;
992 XML_SetEntityDeclHandler(entity
.mpParser
, call_callbackEntityDecl
);
993 XML_SetExternalEntityRefHandler( entity
.mpParser
, call_callbackExternalEntityRef
);
998 nRead
= rEntity
.maConverter
.readAndConvert( seqOut
, BUFFER_SIZE
);
1001 if( rEntity
.mpParser
!= NULL
)
1003 if( xmlParseChunk( rEntity
.mpParser
, reinterpret_cast<const char*>(seqOut
.getConstArray()), 0, 1 ) != XML_ERR_OK
)
1004 rEntity
.throwException( mxDocumentLocator
, true );
1009 bool bContinue
= true;
1010 if( rEntity
.mpParser
== NULL
)
1012 // create parser with proper encoding (needs the first chunk of data)
1013 rEntity
.mpParser
= xmlCreatePushParserCtxt( &callbacks
, this,
1014 reinterpret_cast<const char*>(seqOut
.getConstArray()), nRead
, NULL
);
1015 if( !rEntity
.mpParser
)
1016 throw SAXException("Couldn't create parser", Reference
< XInterface
>(), Any() );
1018 // Tell libxml2 parser to decode entities in attribute values.
1019 xmlCtxtUseOptions(rEntity
.mpParser
, XML_PARSE_NOENT
);
1023 bContinue
= xmlParseChunk( rEntity
.mpParser
, reinterpret_cast<const char*>(seqOut
.getConstArray()), nRead
, 0 )
1027 // callbacks used inside XML_Parse may have caught an exception
1028 if( !bContinue
|| rEntity
.maSavedException
.hasValue() )
1029 rEntity
.throwException( mxDocumentLocator
, true );
1030 } while( nRead
> 0 );
1031 rEntity
.getEvent( DONE
);
1032 if( rEntity
.mbEnableThreads
)
1037 void FastSaxParserImpl::callbackStartElement(const xmlChar
*localName
, const xmlChar
* prefix
, const xmlChar
* URI
,
1038 int numNamespaces
, const xmlChar
** namespaces
, int numAttributes
, int /*defaultedAttributes*/, const xmlChar
**attributes
)
1040 if( !pendingCharacters
.isEmpty())
1041 sendPendingCharacters();
1042 Entity
& rEntity
= getEntity();
1043 if( rEntity
.maNamespaceCount
.empty() )
1045 rEntity
.maNamespaceCount
.push(0);
1046 DefineNamespace( OString("xml"), OUString( "http://www.w3.org/XML/1998/namespace" ));
1050 rEntity
.maNamespaceCount
.push( rEntity
.maNamespaceCount
.top() );
1053 // create attribute map and process namespace instructions
1054 Event
& rEvent
= getEntity().getEvent( START_ELEMENT
);
1055 if (rEvent
.mxAttributes
.is())
1056 rEvent
.mxAttributes
->clear();
1058 rEvent
.mxAttributes
.set(
1059 new FastAttributeList( rEntity
.mxTokenHandler
,
1060 rEntity
.mpTokenHandler
) );
1062 sal_Int32 nNamespaceToken
= FastToken::DONTKNOW
;
1063 if (!rEntity
.maNamespaceStack
.empty())
1065 rEvent
.msNamespace
= rEntity
.maNamespaceStack
.top().msName
;
1066 nNamespaceToken
= rEntity
.maNamespaceStack
.top().mnToken
;
1071 /* #158414# Each element may define new namespaces, also for attribues.
1072 First, process all namespaces, second, process the attributes after namespaces
1073 have been initialized. */
1075 // #158414# first: get namespaces
1076 for (int i
= 0; i
< numNamespaces
* 2; i
+= 2)
1078 // namespaces[] is (prefix/URI)
1079 if( namespaces
[ i
] != NULL
)
1081 DefineNamespace( OString( XML_CAST( namespaces
[ i
] )),
1082 OUString( XML_CAST( namespaces
[ i
+ 1 ] ), strlen( XML_CAST( namespaces
[ i
+ 1 ] )), RTL_TEXTENCODING_UTF8
));
1086 // default namespace
1087 rEvent
.msNamespace
= OUString( XML_CAST( namespaces
[ i
+ 1 ] ), strlen( XML_CAST( namespaces
[ i
+ 1 ] )), RTL_TEXTENCODING_UTF8
);
1088 nNamespaceToken
= GetNamespaceToken( rEvent
.msNamespace
);
1092 // #158414# second: fill attribute list with other attributes
1093 for (int i
= 0; i
< numAttributes
* 5; i
+= 5)
1095 if( attributes
[ i
+ 1 ] != NULL
)
1097 sal_Int32 nAttributeToken
= GetTokenWithPrefix( attributes
[ i
+ 1 ], strlen( XML_CAST( attributes
[ i
+ 1 ] )), attributes
[ i
], strlen( XML_CAST( attributes
[ i
] )));
1098 if( nAttributeToken
!= FastToken::DONTKNOW
)
1099 rEvent
.mxAttributes
->add( nAttributeToken
, XML_CAST( attributes
[ i
+ 3 ] ), attributes
[ i
+ 4 ] - attributes
[ i
+ 3 ] );
1101 rEvent
.mxAttributes
->addUnknown( OUString( XML_CAST( attributes
[ i
+ 2 ] ), strlen( XML_CAST( attributes
[ i
+ 2 ] )), RTL_TEXTENCODING_UTF8
),
1102 OString( XML_CAST( attributes
[ i
] )), OString( XML_CAST( attributes
[ i
+ 3 ] ), attributes
[ i
+ 4 ] - attributes
[ i
+ 3 ] ));
1106 sal_Int32 nAttributeToken
= GetToken( attributes
[ i
], strlen( XML_CAST( attributes
[ i
] )));
1107 if( nAttributeToken
!= FastToken::DONTKNOW
)
1108 rEvent
.mxAttributes
->add( nAttributeToken
, XML_CAST( attributes
[ i
+ 3 ] ), attributes
[ i
+ 4 ] - attributes
[ i
+ 3 ] );
1110 rEvent
.mxAttributes
->addUnknown( XML_CAST( attributes
[ i
] ),
1111 OString( XML_CAST( attributes
[ i
+ 3 ] ), attributes
[ i
+ 4 ] - attributes
[ i
+ 3 ] ));
1115 if( prefix
!= NULL
)
1116 rEvent
.mnElementToken
= GetTokenWithPrefix( prefix
, strlen( XML_CAST( prefix
)), localName
, strlen( XML_CAST( localName
)));
1117 else if( !rEvent
.msNamespace
.isEmpty() )
1118 rEvent
.mnElementToken
= GetTokenWithContextNamespace( nNamespaceToken
, localName
, strlen( XML_CAST( localName
)));
1120 rEvent
.mnElementToken
= GetToken( localName
, strlen( XML_CAST( localName
)));
1122 if( rEvent
.mnElementToken
== FastToken::DONTKNOW
)
1124 if( prefix
!= NULL
)
1126 rEvent
.msNamespace
= OUString( XML_CAST( URI
), strlen( XML_CAST( URI
)), RTL_TEXTENCODING_UTF8
);
1127 nNamespaceToken
= GetNamespaceToken( rEvent
.msNamespace
);
1129 rEvent
.msElementName
= OUString( XML_CAST( localName
), strlen( XML_CAST( localName
)), RTL_TEXTENCODING_UTF8
);
1131 else // token is always preferred.
1132 rEvent
.msElementName
.clear();
1134 rEntity
.maNamespaceStack
.push( NameWithToken(rEvent
.msNamespace
, nNamespaceToken
) );
1135 if (rEntity
.mbEnableThreads
)
1138 rEntity
.startElement( &rEvent
);
1140 catch (const Exception
&)
1142 rEntity
.saveException( ::cppu::getCaughtException() );
1146 void FastSaxParserImpl::callbackEndElement( const xmlChar
*, const xmlChar
*, const xmlChar
* )
1148 if( !pendingCharacters
.isEmpty())
1149 sendPendingCharacters();
1150 Entity
& rEntity
= getEntity();
1151 SAL_WARN_IF(rEntity
.maNamespaceCount
.empty(), "sax", "Empty NamespaceCount");
1152 if( !rEntity
.maNamespaceCount
.empty() )
1153 rEntity
.maNamespaceCount
.pop();
1155 SAL_WARN_IF(rEntity
.maNamespaceStack
.empty(), "sax", "Empty NamespaceStack");
1156 if( !rEntity
.maNamespaceStack
.empty() )
1157 rEntity
.maNamespaceStack
.pop();
1159 rEntity
.getEvent( END_ELEMENT
);
1160 if (rEntity
.mbEnableThreads
)
1163 rEntity
.endElement();
1166 void FastSaxParserImpl::callbackCharacters( const xmlChar
* s
, int nLen
)
1168 // SAX interface allows that the characters callback splits content of one XML node
1169 // (e.g. because there's an entity that needs decoding), however for consumers it's
1170 // simpler FastSaxParser's character callback provides the whole string at once,
1171 // so merge data from possible multiple calls and send them at once (before the element
1172 // ends or another one starts).
1173 pendingCharacters
+= OUString( XML_CAST( s
), nLen
, RTL_TEXTENCODING_UTF8
);
1176 void FastSaxParserImpl::sendPendingCharacters()
1178 Entity
& rEntity
= getEntity();
1179 Event
& rEvent
= rEntity
.getEvent( CHARACTERS
);
1180 rEvent
.msChars
= pendingCharacters
;
1181 pendingCharacters
.clear();
1182 if (rEntity
.mbEnableThreads
)
1185 rEntity
.characters( rEvent
.msChars
);
1189 void FastSaxParserImpl::callbackEntityDecl(
1190 SAL_UNUSED_PARAMETER
const xmlChar
* /*entityName*/,
1191 SAL_UNUSED_PARAMETER
int /*is_parameter_entity*/,
1192 const xmlChar
*value
, SAL_UNUSED_PARAMETER
int /*value_length*/,
1193 SAL_UNUSED_PARAMETER
const xmlChar
* /*base*/,
1194 SAL_UNUSED_PARAMETER
const xmlChar
* /*systemId*/,
1195 SAL_UNUSED_PARAMETER
const xmlChar
* /*publicId*/,
1196 SAL_UNUSED_PARAMETER
const xmlChar
* /*notationName*/)
1198 if (value
) { // value != 0 means internal entity
1199 SAL_INFO("sax", "FastSaxParser: internal entity declaration, stopping");
1200 XML_StopParser(getEntity().mpParser
, XML_FALSE
);
1201 getEntity().saveException( SAXParseException(
1202 "FastSaxParser: internal entity declaration, stopping",
1203 static_cast<OWeakObject
*>(mpFront
), Any(),
1204 mxDocumentLocator
->getPublicId(),
1205 mxDocumentLocator
->getSystemId(),
1206 mxDocumentLocator
->getLineNumber(),
1207 mxDocumentLocator
->getColumnNumber() ) );
1209 SAL_INFO("sax", "FastSaxParser: ignoring external entity declaration");
1213 bool FastSaxParserImpl::callbackExternalEntityRef(
1214 XML_Parser parser
, const xmlChar
*context
,
1215 SAL_UNUSED_PARAMETER
const xmlChar
* /*base*/, const xmlChar
*systemId
,
1216 const xmlChar
*publicId
)
1221 Entity
& rCurrEntity
= getEntity();
1222 Entity
aNewEntity( rCurrEntity
);
1224 if( rCurrEntity
.mxEntityResolver
.is() ) try
1226 aNewEntity
.maStructSource
= rCurrEntity
.mxEntityResolver
->resolveEntity(
1227 OUString( publicId
, strlen( publicId
), RTL_TEXTENCODING_UTF8
) ,
1228 OUString( systemId
, strlen( systemId
), RTL_TEXTENCODING_UTF8
) );
1230 catch (const SAXParseException
& e
)
1232 rCurrEntity
.saveException( e
);
1235 catch (const SAXException
& e
)
1237 rCurrEntity
.saveException( SAXParseException(
1238 e
.Message
, e
.Context
, e
.WrappedException
,
1239 mxDocumentLocator
->getPublicId(),
1240 mxDocumentLocator
->getSystemId(),
1241 mxDocumentLocator
->getLineNumber(),
1242 mxDocumentLocator
->getColumnNumber() ) );
1246 if( aNewEntity
.maStructSource
.aInputStream
.is() )
1248 aNewEntity
.mpParser
= XML_ExternalEntityParserCreate( parser
, context
, 0 );
1249 if( !aNewEntity
.mpParser
)
1254 aNewEntity
.maConverter
.setInputStream( aNewEntity
.maStructSource
.aInputStream
);
1255 pushEntity( aNewEntity
);
1260 catch (const SAXParseException
& e
)
1262 rCurrEntity
.saveException( e
);
1265 catch (const IOException
& e
)
1268 aEx
.WrappedException
<<= e
;
1269 rCurrEntity
.saveException( aEx
);
1272 catch (const RuntimeException
& e
)
1275 aEx
.WrappedException
<<= e
;
1276 rCurrEntity
.saveException( aEx
);
1281 XML_ParserFree( aNewEntity
.mpParser
);
1288 FastSaxParser::FastSaxParser() : mpImpl(new FastSaxParserImpl(this)) {}
1290 FastSaxParser::~FastSaxParser()
1295 void FastSaxParser::parseStream( const xml::sax::InputSource
& aInputSource
)
1296 throw (xml::sax::SAXException
, io::IOException
,
1297 uno::RuntimeException
, std::exception
)
1299 mpImpl
->parseStream(aInputSource
);
1302 void FastSaxParser::setFastDocumentHandler( const uno::Reference
<xml::sax::XFastDocumentHandler
>& Handler
)
1303 throw (uno::RuntimeException
, std::exception
)
1305 mpImpl
->setFastDocumentHandler(Handler
);
1308 void FastSaxParser::setTokenHandler( const uno::Reference
<xml::sax::XFastTokenHandler
>& Handler
)
1309 throw (uno::RuntimeException
, std::exception
)
1311 mpImpl
->setTokenHandler(Handler
);
1314 void FastSaxParser::registerNamespace( const OUString
& NamespaceURL
, sal_Int32 NamespaceToken
)
1315 throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
)
1317 mpImpl
->registerNamespace(NamespaceURL
, NamespaceToken
);
1320 OUString
FastSaxParser::getNamespaceURL( const OUString
& rPrefix
)
1321 throw(lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
)
1323 return mpImpl
->getNamespaceURL(rPrefix
);
1326 void FastSaxParser::setErrorHandler( const uno::Reference
< xml::sax::XErrorHandler
>& Handler
)
1327 throw (uno::RuntimeException
, std::exception
)
1329 mpImpl
->setErrorHandler(Handler
);
1332 void FastSaxParser::setEntityResolver( const uno::Reference
< xml::sax::XEntityResolver
>& Resolver
)
1333 throw (uno::RuntimeException
, std::exception
)
1335 mpImpl
->setEntityResolver(Resolver
);
1338 void FastSaxParser::setLocale( const lang::Locale
& rLocale
)
1339 throw (uno::RuntimeException
, std::exception
)
1341 mpImpl
->setLocale(rLocale
);
1344 OUString
FastSaxParser::getImplementationName()
1345 throw (uno::RuntimeException
, std::exception
)
1347 return OUString("com.sun.star.comp.extensions.xml.sax.FastParser");
1350 sal_Bool
FastSaxParser::supportsService( const OUString
& ServiceName
)
1351 throw (uno::RuntimeException
, std::exception
)
1353 return cppu::supportsService(this, ServiceName
);
1356 uno::Sequence
<OUString
> FastSaxParser::getSupportedServiceNames()
1357 throw (uno::RuntimeException
, std::exception
)
1359 Sequence
<OUString
> seq(1);
1360 seq
[0] = "com.sun.star.xml.sax.FastParser";
1364 bool FastSaxParser::hasNamespaceURL( const OUString
& rPrefix
) const
1366 return mpImpl
->hasNamespaceURL(rPrefix
);
1369 } // namespace sax_fastparser
1371 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
1372 com_sun_star_comp_extensions_xml_sax_FastParser_get_implementation(
1373 css::uno::XComponentContext
*,
1374 css::uno::Sequence
<css::uno::Any
> const &)
1376 return cppu::acquire(new FastSaxParser
);
1379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */