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