Bump version to 5.0-14
[LibreOffice.git] / sax / source / fastparser / fastparser.cxx
blobf118a5d13e9bb412ccbf4c4a5bf8a22e265ce28b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
43 #include <stack>
44 #include <unordered_map>
45 #include <vector>
46 #include <queue>
47 #include <cassert>
48 #include <cstring>
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;
64 namespace {
66 struct Event;
67 class FastLocatorImpl;
68 struct NamespaceDefine;
69 struct Entity;
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 };
80 struct Event
82 CallbackType maType;
83 sal_Int32 mnElementToken;
84 OUString msNamespace;
85 OUString msElementName;
86 rtl::Reference< FastAttributeList > mxAttributes;
87 OUString msChars;
90 struct NameWithToken
92 OUString msName;
93 sal_Int32 mnToken;
95 NameWithToken(const OUString& sName, const sal_Int32& nToken) :
96 msName(sName), mnToken(nToken) {}
99 struct SaxContext
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;
118 struct ParserData
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;
127 ParserData();
128 ~ParserData();
131 struct NamespaceDefine
133 OString maPrefix;
134 sal_Int32 mnToken;
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:
160 Event maSharedEvent;
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 );
189 ~Entity();
190 void startElement( Event *pEvent );
191 void characters( const OUString& sChars );
192 void endElement();
193 EventList* getEventList();
194 Event& getEvent( CallbackType aType );
197 } // namespace
199 namespace sax_fastparser {
201 class FastSaxParserImpl
203 public:
204 FastSaxParserImpl( FastSaxParser* pFront );
205 ~FastSaxParserImpl();
207 // XFastParser
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 );
222 #if 0
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);
228 #endif
230 void pushEntity( const Entity& rEntity );
231 void popEntity();
232 Entity& getEntity() { return *mpTop; }
233 const Entity& getEntity() const { return *mpTop; }
234 void parse();
235 void produce( bool bForceFlush = false );
237 bool hasNamespaceURL( const OUString& rPrefix ) const;
239 private:
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 );
251 private:
252 #if 0
253 FastSaxParser* mpFront;
254 #endif
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
268 namespace {
270 class ParserThread: public salhelper::Thread
272 FastSaxParserImpl *mpParser;
273 public:
274 ParserThread(FastSaxParserImpl *pParser): Thread("Parser"), mpParser(pParser) {}
275 private:
276 virtual void execute() SAL_OVERRIDE
280 mpParser->parse();
282 catch (const Exception &)
284 Entity &rEntity = mpParser->getEntity();
285 rEntity.getEvent( EXCEPTION );
286 mpParser->produce( true );
291 extern "C" {
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 );
312 #if 0
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 );
329 #endif
332 class FastLocatorImpl : public WeakImplHelper1< XLocator >
334 public:
335 FastLocatorImpl( FastSaxParserImpl *p ) : mpParser(p) {}
337 void dispose() { mpParser = 0; }
338 void checkDispose() throw (RuntimeException) { if( !mpParser ) throw DisposedException(); }
340 //XLocator
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;
346 private:
347 FastSaxParserImpl *mpParser;
350 sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber() throw (RuntimeException, std::exception)
352 checkDispose();
353 return xmlSAX2GetColumnNumber( mpParser->getEntity().mpParser );
356 sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber() throw (RuntimeException, std::exception)
358 checkDispose();
359 return xmlSAX2GetLineNumber( mpParser->getEntity().mpParser );
362 OUString SAL_CALL FastLocatorImpl::getPublicId() throw (RuntimeException, std::exception)
364 checkDispose();
365 return mpParser->getEntity().maStructSource.sPublicId;
368 OUString SAL_CALL FastLocatorImpl::getSystemId() throw (RuntimeException, std::exception)
370 checkDispose();
371 return mpParser->getEntity().maStructSource.sSystemId;
374 ParserData::ParserData()
375 : mpTokenHandler( NULL )
378 ParserData::~ParserData()
381 Entity::Entity(const ParserData& rData)
382 : ParserData(rData)
383 , mnProducedEventsSize(0)
384 , mpProducedEvents(NULL)
385 , mbEnableThreads(false)
386 , mpParser(NULL)
390 Entity::Entity(const Entity& e)
391 : ParserData(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)
406 Entity::~Entity()
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) );
424 return;
428 maContextStack.push( SaxContext( nElementToken, aNamespace, aElementName ) );
432 Reference< XFastAttributeList > xAttr( pEvent->mxAttributes.get() );
433 Reference< XFastContextHandler > xContext;
434 if( nElementToken == FastToken::DONTKNOW )
436 if( pParentContext )
437 xContext = pParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
438 else if( mxDocumentHandler.is() )
439 xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
441 if( xContext.is() )
443 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
446 else
448 if( pParentContext )
449 xContext = pParentContext->createFastChildContext( nElementToken, xAttr );
450 else if( mxDocumentHandler.is() )
451 xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
453 if( xContext.is() )
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 !?
471 return;
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 !?
490 return;
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 );
500 else
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();
518 maUsedEvents.pop();
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;
540 return rEvent;
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;
549 else
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,
563 bool mbDuringParse )
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
586 throw aExcept;
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;
606 } // namespace
608 namespace sax_fastparser {
610 FastSaxParserImpl::FastSaxParserImpl( FastSaxParser* ) :
611 #if 0
612 mpFront(pFront),
613 #endif
614 mpTop(NULL)
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;
660 break;
663 if( !nNamespace )
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;
683 else
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;
714 /***************
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)
719 ****************/
720 void FastSaxParserImpl::parseStream(const InputSource& maStructSource)
721 throw (SAXException, IOException, RuntimeException, std::exception)
723 xmlInitParser();
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);
759 xParser->launch();
760 bool done = false;
761 do {
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))
776 done = true;
778 aGuard.reset(); // lock
779 rEntity.maUsedEvents.push(pEventList);
781 } while (!done);
782 xParser->join();
783 deleteUsedEvents();
785 else
787 parse();
790 // finish document
791 if( rEntity.mxDocumentHandler.is() )
793 rEntity.mxDocumentHandler->endDocument();
796 catch (const SAXException&)
798 // TODO free mpParser.myDoc ?
799 xmlFreeParserCtxt( rEntity.mpParser );
800 popEntity();
801 throw;
803 catch (const IOException&)
805 xmlFreeParserCtxt( rEntity.mpParser );
806 popEntity();
807 throw;
809 catch (const RuntimeException&)
811 xmlFreeParserCtxt( rEntity.mpParser );
812 popEntity();
813 throw;
816 xmlFreeParserCtxt( rEntity.mpParser );
817 popEntity();
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;
838 return;
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
883 delete pEventList;
885 aGuard.reset(); // lock
889 void FastSaxParserImpl::produce( bool bForceFlush )
891 Entity& rEntity = getEntity();
892 if (bForceFlush ||
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())
917 return false;
919 const Entity& rEntity = getEntity();
921 if (rEntity.maNamespaceCount.empty())
922 return false;
924 OString aPrefix = OUStringToOString(rPrefix, RTL_TEXTENCODING_UTF8);
925 sal_uInt32 nNamespace = rEntity.maNamespaceCount.top();
926 while (nNamespace--)
928 if (rEntity.maNamespaceDefines[nNamespace]->maPrefix == aPrefix)
929 return true;
932 return false;
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)
943 case START_ELEMENT:
944 rEntity.startElement( &(*aEventIt) );
945 break;
946 case END_ELEMENT:
947 rEntity.endElement();
948 break;
949 case CHARACTERS:
950 rEntity.characters( (*aEventIt).msChars );
951 break;
952 case DONE:
953 return false;
954 case EXCEPTION:
955 rEntity.throwException( mxDocumentLocator, false );
956 return false;
957 default:
958 assert(false);
959 return false;
962 return true;
965 void FastSaxParserImpl::pushEntity( const Entity& rEntity )
967 maEntities.push( rEntity );
968 mpTop = &maEntities.top();
971 void FastSaxParserImpl::popEntity()
973 maEntities.pop();
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;
991 #if 0
992 XML_SetEntityDeclHandler(entity.mpParser, call_callbackEntityDecl);
993 XML_SetExternalEntityRefHandler( entity.mpParser, call_callbackExternalEntityRef );
994 #endif
995 int nRead = 0;
998 nRead = rEntity.maConverter.readAndConvert( seqOut, BUFFER_SIZE );
999 if( nRead <= 0 )
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 );
1006 break;
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);
1021 else
1023 bContinue = xmlParseChunk( rEntity.mpParser, reinterpret_cast<const char*>(seqOut.getConstArray()), nRead, 0 )
1024 == XML_ERR_OK;
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 )
1033 produce( true );
1036 // The C-Callbacks
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" ));
1048 else
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();
1057 else
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 ));
1084 else
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 ] );
1100 else
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 ] ));
1104 else
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 ] );
1109 else
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 )));
1119 else
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)
1136 produce();
1137 else
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)
1161 produce();
1162 else
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)
1183 produce();
1184 else
1185 rEntity.characters( rEvent.msChars );
1188 #if 0
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() ) );
1208 } else {
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 )
1218 bool bOK = true;
1219 InputSource source;
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 );
1233 bOK = false;
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() ) );
1243 bOK = false;
1246 if( aNewEntity.maStructSource.aInputStream.is() )
1248 aNewEntity.mpParser = XML_ExternalEntityParserCreate( parser, context, 0 );
1249 if( !aNewEntity.mpParser )
1251 return false;
1254 aNewEntity.maConverter.setInputStream( aNewEntity.maStructSource.aInputStream );
1255 pushEntity( aNewEntity );
1258 parse();
1260 catch (const SAXParseException& e)
1262 rCurrEntity.saveException( e );
1263 bOK = false;
1265 catch (const IOException& e)
1267 SAXException aEx;
1268 aEx.WrappedException <<= e;
1269 rCurrEntity.saveException( aEx );
1270 bOK = false;
1272 catch (const RuntimeException& e)
1274 SAXException aEx;
1275 aEx.WrappedException <<= e;
1276 rCurrEntity.saveException( aEx );
1277 bOK = false;
1280 popEntity();
1281 XML_ParserFree( aNewEntity.mpParser );
1284 return bOK;
1286 #endif
1288 FastSaxParser::FastSaxParser() : mpImpl(new FastSaxParserImpl(this)) {}
1290 FastSaxParser::~FastSaxParser()
1292 delete mpImpl;
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";
1361 return seq;
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: */