25#include <com/sun/star/io/XSeekable.hpp>
26#include <com/sun/star/lang/DisposedException.hpp>
27#include <com/sun/star/lang/IllegalArgumentException.hpp>
28#include <com/sun/star/uno/XComponentContext.hpp>
29#include <com/sun/star/xml/sax/FastToken.hpp>
30#include <com/sun/star/xml/sax/SAXParseException.hpp>
31#include <com/sun/star/xml/sax/XFastContextHandler.hpp>
35#include <osl/conditn.hxx>
37#include <rtl/ustrbuf.hxx>
49#include <unordered_map>
53#include <libxml/parser.h>
56#define XML_CAST( str ) reinterpret_cast< const char* >( str )
59using namespace ::
cppu;
73struct NamespaceDefine;
76typedef std::unordered_map< OUString, sal_Int32 > NamespaceMap;
81 bool mbIsAttributesEmpty;
84enum class CallbackType { START_ELEMENT, END_ELEMENT, CHARACTERS, PROCESSING_INSTRUCTION,
DONE, EXCEPTION };
89 sal_Int32 mnElementToken;
91 OUString msElementName;
102 NameWithToken(OUString sName, sal_Int32 nToken) :
108 Reference< XFastContextHandler >
mxContext;
109 sal_Int32 mnElementToken;
110 std::optional<OUString> moNamespace;
111 std::optional<OUString> moElementName;
113 SaxContext( sal_Int32 nElementToken,
const OUString& aNamespace,
const OUString& aElementName ):
114 mnElementToken(nElementToken)
116 if (nElementToken == FastToken::DONTKNOW)
118 moNamespace = aNamespace;
119 moElementName = aElementName;
126 css::uno::Reference< css::xml::sax::XFastDocumentHandler > mxDocumentHandler;
128 css::uno::Reference< css::xml::sax::XErrorHandler > mxErrorHandler;
129 css::uno::Reference< css::xml::sax::XFastNamespaceHandler >mxNamespaceHandler;
134struct NamespaceDefine
138 OUString maNamespaceURL;
140 NamespaceDefine( OString aPrefix, sal_Int32 nToken, OUString aNamespaceURL )
141 :
maPrefix(
std::move( aPrefix )), mnToken(
nToken ), maNamespaceURL(
std::move( aNamespaceURL )) {}
142 NamespaceDefine() : mnToken(-1) {}
146struct Entity :
public ParserData
149 static const size_t mnEventListSize = 1000;
154 size_t mnProducedEventsSize;
155 std::optional<EventList> mxProducedEvents;
156 std::queue<EventList> maPendingEvents;
157 std::queue<EventList> maUsedEvents;
158 std::mutex maEventProtector;
160 static const size_t mnEventLowWater = 4;
161 static const size_t mnEventHighWater = 8;
162 osl::Condition maConsumeResume;
163 osl::Condition maProduceResume;
170 bool mbEnableThreads;
171 css::xml::sax::InputSource maStructSource;
172 xmlParserCtxtPtr mpParser;
178 css::uno::Any maSavedException;
179 std::mutex maSavedExceptionMutex;
180 void saveException(
const Any & e );
183 void throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
184 bool mbDuringParse );
186 std::stack< NameWithToken, std::vector<NameWithToken> > maNamespaceStack;
190 std::stack< SaxContext, std::vector<SaxContext> > maContextStack;
192 std::stack< sal_uInt32, std::vector<sal_uInt32> > maNamespaceCount;
193 std::vector< NamespaceDefine > maNamespaceDefines;
195 explicit Entity(
const ParserData& rData );
196 Entity(
const Entity& rEntity ) =
delete;
197 Entity& operator=(
const Entity& rEntity ) =
delete;
198 void startElement( Event
const *pEvent );
199 void characters(
const OUString& sChars );
201 void processingInstruction(
const OUString& rTarget,
const OUString& rData );
202 EventList& getEventList();
203 Event& getEvent( CallbackType aType );
207struct ReplacementPair
210 OUString replacement;
212inline bool operator<(
const ReplacementPair& lhs,
const ReplacementPair& rhs)
214 return lhs.name < rhs.name;
216inline bool operator<(
const ReplacementPair& lhs,
const char* rhs)
218 return lhs.name.compareToAscii(rhs) < 0;
240 void parseStream(
const css::xml::sax::InputSource& aInputSource );
244 void setTokenHandler(
const css::uno::Reference< css::xml::sax::XFastTokenHandler >& Handler );
247 void registerNamespace(
const OUString& NamespaceURL, sal_Int32 NamespaceToken );
252 void setErrorHandler(
const css::uno::Reference< css::xml::sax::XErrorHandler >& Handler );
254 void setNamespaceHandler(
const css::uno::Reference< css::xml::sax::XFastNamespaceHandler >& Handler);
257 const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString>>& replacements);
260 void callbackStartElement(
const xmlChar *localName ,
const xmlChar* prefix,
const xmlChar* URI,
261 int numNamespaces,
const xmlChar**
namespaces,
int numAttributes,
const xmlChar **attributes );
267 void pushEntity(
const ParserData&, xml::sax::InputSource
const&);
271 void produce(
bool bForceFlush =
false );
281 sal_Int32
GetToken(
const xmlChar* pName );
288 void DefineNamespace(
const OString& rPrefix,
const OUString& namespaceURL );
312 virtual void execute()
override
321 rEntity.getEvent( CallbackType::EXCEPTION );
329static void call_callbackStartElement(
void *userData,
const xmlChar *localName ,
const xmlChar* prefix,
const xmlChar* URI,
330 int numNamespaces,
const xmlChar**
namespaces,
int numAttributes,
int ,
const xmlChar **attributes)
336static void call_callbackEndElement(
void *userData,
const xmlChar* ,
const xmlChar* ,
const xmlChar* )
342static void call_callbackCharacters(
void *userData ,
const xmlChar *s ,
int nLen )
348static void call_callbackProcessingInstruction(
void *userData,
const xmlChar *target,
const xmlChar *data )
354static xmlEntityPtr call_callbackGetEntity(
void *userData,
const xmlChar *name)
362class FastLocatorImpl :
public WeakImplHelper< XLocator >
367 void dispose() { mpParser =
nullptr; }
369 void checkDispose()
const {
if( !mpParser )
throw DisposedException(); }
372 virtual sal_Int32 SAL_CALL getColumnNumber()
override;
373 virtual sal_Int32 SAL_CALL getLineNumber()
override;
374 virtual OUString SAL_CALL getPublicId()
override;
375 virtual OUString SAL_CALL getSystemId()
override;
381sal_Int32 SAL_CALL FastLocatorImpl::getColumnNumber()
384 return xmlSAX2GetColumnNumber( mpParser->
getEntity().mpParser );
387sal_Int32 SAL_CALL FastLocatorImpl::getLineNumber()
390 return xmlSAX2GetLineNumber( mpParser->
getEntity().mpParser );
393OUString SAL_CALL FastLocatorImpl::getPublicId()
396 return mpParser->
getEntity().maStructSource.sPublicId;
399OUString SAL_CALL FastLocatorImpl::getSystemId()
402 return mpParser->
getEntity().maStructSource.sSystemId;
405ParserData::ParserData()
408Entity::Entity(
const ParserData& rData)
410 , mnProducedEventsSize(0)
411 , mbEnableThreads(false)
416void Entity::startElement( Event
const *pEvent )
418 const sal_Int32& nElementToken = pEvent->mnElementToken;
419 const OUString& aNamespace = pEvent->msNamespace;
420 const OUString& aElementName = pEvent->msElementName;
423 XFastContextHandler *pParentContext =
nullptr;
424 if( !maContextStack.empty() )
426 pParentContext = maContextStack.top().mxContext.get();
427 if( !pParentContext )
429 maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
434 maContextStack.push( SaxContext( nElementToken, aNamespace, aElementName ) );
438 const Reference< XFastAttributeList > & xAttr( pEvent->mxAttributes );
439 Reference< XFastContextHandler > xContext;
441 if ( mxNamespaceHandler.is() )
443 const Sequence< xml::Attribute > NSDeclAttribs = pEvent->mxDeclAttributes->getUnknownAttributes();
444 for (
const auto& rNSDeclAttrib : NSDeclAttribs)
446 mxNamespaceHandler->registerNamespace( rNSDeclAttrib.Name, rNSDeclAttrib.Value );
450 if( nElementToken == FastToken::DONTKNOW )
453 xContext = pParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
454 else if( mxDocumentHandler.is() )
455 xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
459 xContext->startUnknownElement( aNamespace, aElementName, xAttr );
465 xContext = pParentContext->createFastChildContext( nElementToken, xAttr );
466 else if( mxDocumentHandler.is() )
467 xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
470 xContext->startFastElement( nElementToken, xAttr );
473 maContextStack.top().mxContext = std::move( xContext );
477 saveException( ::cppu::getCaughtException() );
481void Entity::characters(
const OUString& sChars )
483 if (maContextStack.empty())
489 XFastContextHandler * pContext( maContextStack.top().mxContext.get() );
492 pContext->characters( sChars );
496 saveException( ::cppu::getCaughtException() );
500void Entity::endElement()
502 if (maContextStack.empty())
508 const SaxContext& aContext = maContextStack.top();
509 XFastContextHandler* pContext( aContext.mxContext.get() );
513 sal_Int32 nElementToken = aContext.mnElementToken;
514 if( nElementToken != FastToken::DONTKNOW )
515 pContext->endFastElement( nElementToken );
517 pContext->endUnknownElement( *aContext.moNamespace, *aContext.moElementName );
521 saveException( ::cppu::getCaughtException() );
523 maContextStack.pop();
526void Entity::processingInstruction(
const OUString& rTarget,
const OUString& rData )
528 if( mxDocumentHandler.is() )
try
530 mxDocumentHandler->processingInstruction( rTarget, rData );
534 saveException( ::cppu::getCaughtException() );
538EventList& Entity::getEventList()
540 if (!mxProducedEvents)
542 std::unique_lock aGuard(maEventProtector);
543 if (!maUsedEvents.empty())
545 mxProducedEvents = std::move(maUsedEvents.front());
548 mnProducedEventsSize = 0;
550 if (!mxProducedEvents)
552 mxProducedEvents.emplace();
553 mxProducedEvents->maEvents.resize(mnEventListSize);
554 mxProducedEvents->mbIsAttributesEmpty =
false;
555 mnProducedEventsSize = 0;
558 return *mxProducedEvents;
561Event& Entity::getEvent( CallbackType aType )
563 if (!mbEnableThreads)
564 return maSharedEvent;
566 EventList& rEventList = getEventList();
567 if (mnProducedEventsSize == rEventList.maEvents.size())
570 "Event vector should only exceed " << mnEventListSize <<
571 " temporarily while an exception is pending");
572 rEventList.maEvents.resize(mnProducedEventsSize + 1);
574 Event& rEvent = rEventList.maEvents[mnProducedEventsSize++];
575 rEvent.maType = aType;
579OUString lclGetErrorMessage( xmlParserCtxtPtr ctxt, std::u16string_view sSystemId, sal_Int32 nLine )
581 const char* pMessage;
582 xmlErrorPtr error = xmlCtxtGetLastError( ctxt );
583 if( error && error->message )
584 pMessage = error->message;
586 pMessage =
"unknown error";
587 return OUString::Concat(
"[") + sSystemId +
" line " + OUString::number(nLine) +
"]: " +
588 OUString(pMessage, strlen(pMessage), RTL_TEXTENCODING_ASCII_US);
593void Entity::throwException( const ::rtl::Reference< FastLocatorImpl > &xDocumentLocator,
599 std::scoped_lock g(maSavedExceptionMutex);
600 if (maSavedException.hasValue())
602 savedException.setValue(&maSavedException,
cppu::UnoType<
decltype(maSavedException)>::get());
605 SAXParseException aExcept(
606 lclGetErrorMessage( mpParser,
607 xDocumentLocator->getSystemId(),
608 xDocumentLocator->getLineNumber() ),
609 Reference< XInterface >(),
611 xDocumentLocator->getPublicId(),
612 xDocumentLocator->getSystemId(),
613 xDocumentLocator->getLineNumber(),
614 xDocumentLocator->getColumnNumber()
618 if( !mbDuringParse || !mbEnableThreads )
620 if (mxErrorHandler.is() )
621 mxErrorHandler->fatalError(
Any( aExcept ) );
635void Entity::saveException(
const Any & e )
641 std::scoped_lock g(maSavedExceptionMutex);
642 if (maSavedException.hasValue())
644 SAL_INFO(
"sax.fastparser",
"discarding exception, already have one");
648 maSavedException = e;
652bool Entity::hasException()
654 std::scoped_lock g(maSavedExceptionMutex);
655 return maSavedException.hasValue();
663 m_bIgnoreMissingNSDecl(false),
664 m_bDisableThreadedParser(false),
678 xmlNodePtr pPtr =
reinterpret_cast<xmlNodePtr
>(entity);
687 assert(!rEntity.maNamespaceCount.empty());
689 sal_uInt32 nOffset = rEntity.maNamespaceCount.top()++;
690 if( rEntity.maNamespaceDefines.size() <= nOffset )
691 rEntity.maNamespaceDefines.resize( rEntity.maNamespaceDefines.size() + 64 );
693 rEntity.maNamespaceDefines[nOffset] = NamespaceDefine( rPrefix,
GetNamespaceToken( namespaceURL ), namespaceURL );
705 if (rEntity.maNamespaceCount.empty())
706 return FastToken::DONTKNOW;
709 sal_uInt32
nNamespace = rEntity.maNamespaceCount.top();
712 const auto & rNamespaceDefine = rEntity.maNamespaceDefines[
nNamespace];
713 if( rNamespaceDefine.maPrefix ==
sPrefix )
718 throw SAXException(
"No namespace defined for " + OStringToOUString(
sPrefix,
719 RTL_TEXTENCODING_UTF8), {}, {});
721 return FastToken::DONTKNOW;
726 NamespaceMap::iterator aIter(
maNamespaceMap.find( rNamespaceURL ) );
728 return (*aIter).second;
730 return FastToken::DONTKNOW;
736 if( !rEntity.maNamespaceCount.empty() )
738 sal_uInt32
nNamespace = rEntity.maNamespaceCount.top();
740 if( rEntity.maNamespaceDefines[
nNamespace].maPrefix == rPrefix )
741 return rEntity.maNamespaceDefines[
nNamespace].maNamespaceURL;
744 throw SAXException(
"No namespace defined for " + OUString::fromUtf8(rPrefix),
745 Reference< XInterface >(),
Any());
750 if( nNamespaceToken != FastToken::DONTKNOW )
753 if( nNameToken != FastToken::DONTKNOW )
754 return nNamespaceToken | nNameToken;
757 return FastToken::DONTKNOW;
811 std::unique_lock guard(
maMutex );
815 ParserCleanup aEnsureFree(*
this, rEntity);
818 if( rEntity.mxDocumentHandler.is() )
821 rEntity.mxDocumentHandler->startDocument();
825 rEntity.mbEnableThreads =
false;
829 Reference<css::io::XSeekable> xSeekable(rEntity.maStructSource.aInputStream, UNO_QUERY);
831 rEntity.mbEnableThreads = (xSeekable.is() && xSeekable->getLength() > 10000)
832 || (rEntity.maStructSource.aInputStream->available() > 10000);
836 if (rEntity.mbEnableThreads)
840 aEnsureFree.setThread(xParser);
843 rEntity.maConsumeResume.wait();
844 rEntity.maConsumeResume.reset();
846 std::unique_lock aGuard(rEntity.maEventProtector);
847 while (!rEntity.maPendingEvents.empty())
849 if (rEntity.maPendingEvents.size() <= Entity::mnEventLowWater)
850 rEntity.maProduceResume.set();
852 EventList
aEventList = std::move(rEntity.maPendingEvents.front());
853 rEntity.maPendingEvents.pop();
861 if ( rEntity.maPendingEvents.size() <= Entity::mnEventLowWater )
866 if (rEvent.mxAttributes.is())
868 rEvent.mxAttributes->clear();
869 if( rEntity.mxNamespaceHandler.is() )
870 rEvent.mxDeclAttributes->clear();
877 rEntity.maUsedEvents.push(std::move(
aEventList));
880 aEnsureFree.joinThread();
886 if( rEntity.maSavedException.hasValue() )
895 if( rEntity.mxDocumentHandler.is() )
897 rEntity.mxDocumentHandler->endDocument();
903 maData.mxDocumentHandler = Handler;
908 assert(
dynamic_cast< FastTokenHandlerBase *
>( xHandler.get() ) &&
"we expect this handler to be a subclass of FastTokenHandlerBase" );
914 if( NamespaceToken < FastToken::NAMESPACE )
915 throw IllegalArgumentException(
"Invalid namespace token " + OUString::number(NamespaceToken), css::uno::Reference<css::uno::XInterface >(), 0);
922 throw IllegalArgumentException(
"namespace URL is already registered: " + NamespaceURL, css::uno::Reference<css::uno::XInterface >(), 0);
934 throw IllegalArgumentException();
939 maData.mxErrorHandler = Handler;
944 maData.mxNamespaceHandler = Handler;
948 const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString>>& replacements)
951 for (
size_t i = 0;
i < replacements.size(); ++
i)
963 std::unique_lock aGuard(rEntity.maEventProtector);
965 while (!rEntity.maUsedEvents.empty())
968 EventList
aEventList = std::move(rEntity.maUsedEvents.front());
969 rEntity.maUsedEvents.pop();
982 rEntity.mnProducedEventsSize >= Entity::mnEventListSize))
985 std::unique_lock aGuard(rEntity.maEventProtector);
987 while (rEntity.maPendingEvents.size() >= Entity::mnEventHighWater)
990 rEntity.maProduceResume.wait();
991 rEntity.maProduceResume.reset();
995 rEntity.maPendingEvents.push(std::move(*rEntity.mxProducedEvents));
996 rEntity.mxProducedEvents.reset();
997 assert(!rEntity.mxProducedEvents);
1001 rEntity.maConsumeResume.set();
1007 rEventList.mbIsAttributesEmpty =
false;
1008 for (
auto& rEvent : rEventList.maEvents)
1010 switch (rEvent.maType)
1012 case CallbackType::START_ELEMENT:
1013 rEntity.startElement( &rEvent );
1015 case CallbackType::END_ELEMENT:
1016 rEntity.endElement();
1018 case CallbackType::CHARACTERS:
1019 rEntity.characters( rEvent.msChars );
1021 case CallbackType::PROCESSING_INSTRUCTION:
1022 rEntity.processingInstruction(
1023 rEvent.msNamespace, rEvent.msElementName );
1025 case CallbackType::DONE:
1027 case CallbackType::EXCEPTION:
1039 xml::sax::InputSource
const& rSource)
1041 if (!rSource.aInputStream.is())
1042 throw SAXException(
"No input source", Reference<XInterface>(),
Any());
1047 mpTop->maStructSource = rSource;
1049 mpTop->maConverter.setInputStream(
mpTop->maStructSource.aInputStream);
1050 if (!
mpTop->maStructSource.sEncoding.isEmpty())
1071 static xmlSAXHandler callbacks;
1072 callbacks.startElementNs = call_callbackStartElement;
1073 callbacks.endElementNs = call_callbackEndElement;
1074 callbacks.characters = call_callbackCharacters;
1075 callbacks.processingInstruction = call_callbackProcessingInstruction;
1076 callbacks.getEntity = call_callbackGetEntity;
1077 callbacks.initialized = XML_SAX2_MAGIC;
1081 nRead = rEntity.maConverter.readAndConvert( seqOut,
BUFFER_SIZE );
1084 if( rEntity.mpParser !=
nullptr )
1086 if( xmlParseChunk( rEntity.mpParser,
reinterpret_cast<const char*
>(seqOut.getConstArray()), 0, 1 ) != XML_ERR_OK )
1088 if (rEntity.hasException())
1094 bool bContinue =
true;
1095 if( rEntity.mpParser ==
nullptr )
1098 rEntity.mpParser = xmlCreatePushParserCtxt( &callbacks,
this,
1099 reinterpret_cast<const char*
>(seqOut.getConstArray()), nRead,
nullptr );
1100 if( !rEntity.mpParser )
1101 throw SAXException(
"Couldn't create parser", Reference< XInterface >(),
Any() );
1107 xmlCtxtUseOptions(rEntity.mpParser, XML_PARSE_NOENT | XML_PARSE_HUGE);
1111 bContinue = xmlParseChunk( rEntity.mpParser,
reinterpret_cast<const char*
>(seqOut.getConstArray()), nRead, 0 )
1120 if (rEntity.hasException())
1124 }
while( nRead > 0 );
1125 rEntity.getEvent( CallbackType::DONE );
1126 if( rEntity.mbEnableThreads )
1132 int numNamespaces,
const xmlChar**
namespaces,
int numAttributes,
const xmlChar **attributes)
1137 if( rEntity.maNamespaceCount.empty() )
1139 rEntity.maNamespaceCount.push(0);
1144 rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
1148 Event& rEvent = rEntity.getEvent( CallbackType::START_ELEMENT );
1149 bool bIsAttributesEmpty =
false;
1150 if ( rEntity.mbEnableThreads )
1151 bIsAttributesEmpty = rEntity.getEventList().mbIsAttributesEmpty;
1153 if (rEvent.mxAttributes.is())
1155 if( !bIsAttributesEmpty )
1156 rEvent.mxAttributes->clear();
1159 rEvent.mxAttributes.set(
1162 if( rEntity.mxNamespaceHandler.is() )
1164 if (rEvent.mxDeclAttributes.is())
1166 if( !bIsAttributesEmpty )
1167 rEvent.mxDeclAttributes->clear();
1170 rEvent.mxDeclAttributes.set(
1174 OUString sNamespace;
1175 sal_Int32 nNamespaceToken = FastToken::DONTKNOW;
1176 if (!rEntity.maNamespaceStack.empty())
1178 sNamespace = rEntity.maNamespaceStack.top().msName;
1179 nNamespaceToken = rEntity.maNamespaceStack.top().mnToken;
1189 for (
int i = 0;
i < numNamespaces * 2;
i += 2)
1198 if( rEntity.mxNamespaceHandler.is() )
1207 if( rEntity.mxNamespaceHandler.is() )
1212 if ( rEntity.mxTokenHandler.is() )
1215 rEvent.mxAttributes->reserve( numAttributes );
1216 for (
int i = 0;
i < numAttributes * 5;
i += 5)
1219 if( attributes[
i + 1 ] !=
nullptr )
1222 if( nAttributeToken != FastToken::DONTKNOW )
1223 rEvent.mxAttributes->add( nAttributeToken, std::string_view(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ]) );
1229 sal_Int32 nAttributeToken =
GetToken(attributes[
i ]);
1230 if( nAttributeToken != FastToken::DONTKNOW )
1231 rEvent.mxAttributes->add( nAttributeToken, std::string_view(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ]) );
1234 SAL_WARN(
"xmloff",
"unknown attribute " <<
XML_CAST( attributes[
i ] ) <<
"=" <<
1235 OString(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ] ));
1236 rEvent.mxAttributes->addUnknown(
XML_CAST( attributes[
i ] ),
1237 OString(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ] ));
1244 else if( !sNamespace.isEmpty() )
1247 rEvent.mnElementToken =
GetToken(localName);
1251 for (
int i = 0;
i < numAttributes * 5;
i += 5)
1253 if( attributes[
i + 1 ] !=
nullptr )
1256 rEvent.mxAttributes->addUnknown(
XML_CAST( attributes[
i ] ),
1257 OString(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ] ));
1260 rEvent.mnElementToken = FastToken::DONTKNOW;
1263 if( rEvent.mnElementToken == FastToken::DONTKNOW )
1265 OUString aElementPrefix;
1269 sNamespace = OUString(
XML_CAST( URI ), strlen(
XML_CAST( URI )), RTL_TEXTENCODING_UTF8 );
1275 OUString aElementLocalName(
XML_CAST( localName ), strlen(
XML_CAST( localName )), RTL_TEXTENCODING_UTF8 );
1276 rEvent.msNamespace = sNamespace;
1277 if( aElementPrefix.isEmpty() )
1278 rEvent.msElementName = std::move(aElementLocalName);
1280 rEvent.msElementName = aElementPrefix +
":" + aElementLocalName;
1283 rEvent.msElementName.clear();
1285 rEntity.maNamespaceStack.push( NameWithToken(sNamespace, nNamespaceToken) );
1286 if (rEntity.mbEnableThreads)
1291 rEntity.startElement( &rEvent );
1296 rEntity.saveException( ::cppu::getCaughtException() );
1302 OUString aNamespaceURI;
1304 aNamespaceURI = OUString(
XML_CAST( attributes[
i + 2 ] ), strlen(
XML_CAST( attributes[
i + 2 ] )), RTL_TEXTENCODING_UTF8 );
1305 const OString& rPrefix = OString(
XML_CAST( attributes[
i + 1 ] ));
1306 const OString& rLocalName = OString(
XML_CAST( attributes[
i ] ));
1307 OString aQualifiedName = (rPrefix.isEmpty())? rLocalName : rPrefix +
":" + rLocalName;
1308 xAttributes->addUnknown( aNamespaceURI, aQualifiedName,
1309 OString(
XML_CAST( attributes[
i + 3 ] ), attributes[
i + 4 ] - attributes[
i + 3 ] ));
1310 SAL_INFO(
"xmloff",
"unknown element " << aQualifiedName <<
" " << aNamespaceURI);
1318 SAL_WARN_IF(rEntity.maNamespaceCount.empty(),
"sax",
"Empty NamespaceCount");
1319 if( !rEntity.maNamespaceCount.empty() )
1320 rEntity.maNamespaceCount.pop();
1322 SAL_WARN_IF(rEntity.maNamespaceStack.empty(),
"sax",
"Empty NamespaceStack");
1323 if( !rEntity.maNamespaceStack.empty() )
1324 rEntity.maNamespaceStack.pop();
1326 rEntity.getEvent( CallbackType::END_ELEMENT );
1327 if (rEntity.mbEnableThreads)
1330 rEntity.endElement();
1353 if (rEntity.mbEnableThreads)
1355 Event& rEvent = rEntity.getEvent( CallbackType::CHARACTERS );
1356 rEvent.msChars = std::move(sChars);
1360 rEntity.characters( sChars );
1369 Event& rEvent = rEntity.getEvent( CallbackType::PROCESSING_INSTRUCTION );
1373 rEvent.msNamespace = OUString(
XML_CAST( target ), strlen(
XML_CAST( target ) ), RTL_TEXTENCODING_UTF8 );
1374 if ( data !=
nullptr )
1375 rEvent.msElementName = OUString(
XML_CAST( data ), strlen(
XML_CAST( data ) ), RTL_TEXTENCODING_UTF8 );
1377 rEvent.msElementName.clear();
1379 if (rEntity.mbEnableThreads)
1382 rEntity.processingInstruction( rEvent.msNamespace, rEvent.msElementName );
1388 return xmlGetPredefinedEntity(
name);
1390 int lname = strlen(dname);
1392 return xmlGetPredefinedEntity(
name);
1396 if (it !=
m_Replacements.end() && it->name.compareToAscii(dname) == 0)
1398 xmlEntityPtr entpt = xmlNewEntity(
1399 nullptr,
name, XML_INTERNAL_GENERAL_ENTITY,
nullptr,
nullptr,
1406 return xmlGetPredefinedEntity(
name);
1407 if ( dname[0] ==
'#' )
1409 sal_uInt32 cval = 0;
1410 if( dname[1] ==
'x' || dname[1] ==
'X' )
1413 return xmlGetPredefinedEntity(
name);
1414 cval =
static_cast<sal_uInt32
>( strtoul( dname + 2,
nullptr, 16 ) );
1416 return xmlGetPredefinedEntity(
name);
1417 OUString vname( &cval, 1 );
1419 = xmlNewEntity(
nullptr,
name, XML_INTERNAL_GENERAL_ENTITY,
nullptr,
nullptr,
1426 cval =
static_cast<sal_uInt32
>( strtoul( dname + 2,
nullptr, 10 ) );
1428 return xmlGetPredefinedEntity(
name);
1429 OUString vname(&cval, 1);
1431 = xmlNewEntity(
nullptr,
name, XML_INTERNAL_GENERAL_ENTITY,
nullptr,
nullptr,
1437 return xmlGetPredefinedEntity(
name);
1449 if (!rArguments.hasElements())
1453 if ( !(rArguments[0] >>= str) )
1454 throw IllegalArgumentException();
1456 if ( str ==
"IgnoreMissingNSDecl" )
1457 mpImpl->m_bIgnoreMissingNSDecl =
true;
1458 else if ( str ==
"DoSmeplease" )
1460 else if ( str ==
"DisableThreadedParser" )
1461 mpImpl->m_bDisableThreadedParser =
true;
1463 throw IllegalArgumentException();
1469 mpImpl->parseStream(aInputSource);
1474 mpImpl->setFastDocumentHandler(Handler);
1479 mpImpl->setTokenHandler(Handler);
1484 mpImpl->registerNamespace(NamespaceURL, NamespaceToken);
1489 return mpImpl->getNamespaceURL(rPrefix);
1494 mpImpl->setErrorHandler(Handler);
1509 mpImpl->setNamespaceHandler(Handler);
1514 return "com.sun.star.comp.extensions.xml.sax.FastParser";
1518 const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString>>& replacements)
1520 mpImpl->setCustomEntityNames(replacements);
1530 return {
"com.sun.star.xml.sax.FastParser" };
1535extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1537 css::uno::XComponentContext *,
1538 css::uno::Sequence<css::uno::Any>
const &)
1561constexpr OUStringLiteral
XML_N_SVG(u
"http://www.w3.org/2000/svg");
1562constexpr OUStringLiteral
XML_N_SVG_COMPAT(u
"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
1563constexpr OUStringLiteral
XML_N_FO(u
"http://www.w3.org/1999/XSL/Format");
1564constexpr OUStringLiteral
XML_N_FO_COMPAT(u
"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
1565constexpr OUStringLiteral
XML_N_SMIL(u
"http://www.w3.org/2001/SMIL20/");
1567constexpr OUStringLiteral
XML_N_SMIL_COMPAT(u
"urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0");
1581 bool bSuccess =
false;
1583 if( rName.startsWith( sURIPrefix ) )
1586 sal_Int32 nCompareFrom = rName.getLength() - sURISuffix.getLength();
1587 if( rName.subView( nCompareFrom ) == sURISuffix )
1624 sal_Int32 nNameLen = rName.getLength();
1627 if( !rName.startsWith( rOasisURN ) )
1631 sal_Int32
nPos = rOasisURN.getLength();
1632 if(
nPos >= nNameLen || rName[
nPos] !=
':' )
1636 sal_Int32 nTCIdStart =
nPos+1;
1637 sal_Int32 nTCIdEnd = rName.indexOf(
':', nTCIdStart );
1638 if( -1 == nTCIdEnd )
1642 nPos = nTCIdEnd + 1;
1643 std::u16string_view sTmp( rName.subView(
nPos ) );
1649 nPos += rXMLNS.getLength();
1650 if(
nPos >= nNameLen || rName[
nPos] !=
':' )
1654 nPos = rName.indexOf(
':',
nPos+1 );
1659 sal_Int32 nVersionStart =
nPos+1;
1660 if( nVersionStart+2 >= nNameLen ||
1661 -1 != rName.indexOf(
':', nVersionStart ) )
1665 if( rName[nVersionStart] !=
'1' || rName[nVersionStart+1] !=
'.' )
1670 rName = rName.subView( 0, nTCIdStart ) +
1672 rName.subView( nTCIdEnd, nVersionStart-nTCIdEnd ) +
SharedBitmapDescriptor mpTop
sal_Int32 GetNamespaceToken(const OUString &rNamespaceURL)
xmlEntityPtr callbackGetEntity(const xmlChar *name)
NamespaceMap maNamespaceMap
void setCustomEntityNames(const ::css::uno::Sequence<::css::beans::Pair<::rtl::OUString, ::rtl::OUString > > &replacements)
void addUnknownElementWithPrefix(const xmlChar **attributes, int i, rtl::Reference< FastAttributeList > const &xAttributes)
void callbackEndElement()
void setFastDocumentHandler(const css::uno::Reference< css::xml::sax::XFastDocumentHandler > &Handler)
bool m_bDisableThreadedParser
std::vector< ReplacementPair > m_Replacements
void callbackProcessingInstruction(const xmlChar *target, const xmlChar *data)
std::vector< char > pendingCharacters
Entity stack for each call of parseStream().
void pushEntity(const ParserData &, xml::sax::InputSource const &)
void callbackCharacters(const xmlChar *s, int nLen)
std::stack< Entity > maEntities
std::stack::top() is amazingly slow => cache this.
void setNamespaceHandler(const css::uno::Reference< css::xml::sax::XFastNamespaceHandler > &Handler)
Entity * mpTop
Cached parser configuration for next call of parseStream().
sal_Int32 GetToken(const xmlChar *pName)
void sendPendingCharacters()
OUString const & GetNamespaceURL(std::string_view rPrefix)
void DefineNamespace(const OString &rPrefix, const OUString &namespaceURL)
void setErrorHandler(const css::uno::Reference< css::xml::sax::XErrorHandler > &Handler)
std::vector< xmlEntityPtr > m_TemporalEntities
::rtl::Reference< FastLocatorImpl > mxDocumentLocator
OUString const & getNamespaceURL(std::u16string_view rPrefix)
sal_Int32 GetTokenWithPrefix(const xmlChar *pPrefix, const xmlChar *pName)
void setTokenHandler(const css::uno::Reference< css::xml::sax::XFastTokenHandler > &Handler)
void registerNamespace(const OUString &NamespaceURL, sal_Int32 NamespaceToken)
void parseStream(const css::xml::sax::InputSource &aInputSource)
bool consume(EventList &)
sal_Int32 GetTokenWithContextNamespace(sal_Int32 nNamespaceToken, const xmlChar *pName)
void produce(bool bForceFlush=false)
bool m_bIgnoreMissingNSDecl
void callbackStartElement(const xmlChar *localName, const xmlChar *prefix, const xmlChar *URI, int numNamespaces, const xmlChar **namespaces, int numAttributes, const xmlChar **attributes)
std::mutex maMutex
Protecting whole parseStream() execution.
virtual void SAL_CALL setErrorHandler(const css::uno::Reference< css::xml::sax::XErrorHandler > &Handler) override
virtual void SAL_CALL setLocale(const css::lang::Locale &rLocale) override
virtual ~FastSaxParser() override
virtual void SAL_CALL setCustomEntityNames(const ::css::uno::Sequence< ::css::beans::Pair<::rtl::OUString, ::rtl::OUString > > &replacements) override
std::unique_ptr< FastSaxParserImpl > mpImpl
virtual void SAL_CALL parseStream(const css::xml::sax::InputSource &aInputSource) override
virtual void SAL_CALL initialize(css::uno::Sequence< css::uno::Any > const &rArguments) override
virtual void SAL_CALL setNamespaceHandler(const css::uno::Reference< css::xml::sax::XFastNamespaceHandler > &Handler) override
virtual OUString SAL_CALL getNamespaceURL(const OUString &rPrefix) override
virtual void SAL_CALL setFastDocumentHandler(const css::uno::Reference< css::xml::sax::XFastDocumentHandler > &Handler) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL setEntityResolver(const css::uno::Reference< css::xml::sax::XEntityResolver > &Resolver) override
virtual void SAL_CALL setTokenHandler(const css::uno::Reference< css::xml::sax::XFastTokenHandler > &Handler) override
virtual void SAL_CALL registerNamespace(const OUString &NamespaceURL, sal_Int32 NamespaceToken) override
A native C++ interface to tokenisation.
static sal_Int32 getTokenFromChars(const FastTokenHandlerBase *pTokenHandler, std::string_view str)
Client method to attempt the use of this interface if possible.
OString exceptionToString(const css::uno::Any &caught)
std::deque< ScriptEventDescriptor > aEventList
constexpr OUStringLiteral XML_N_SMIL_COMPAT(u"urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0")
constexpr OUStringLiteral XML_N_XFORMS_1_0(u"http://www.w3.org/2002/xforms")
static void NormalizeURI(OUString &rName)
constexpr OUStringLiteral XML_URN_OASIS_NAMES_TC(u"urn:oasis:names:tc")
constexpr OUStringLiteral XML_URI_W3_PREFIX(u"http://www.w3.org/")
FastSaxParserImpl & m_rParser
static bool NormalizeOasisURN(OUString &rName)
static bool NormalizeW3URI(OUString &rName)
constexpr OUStringLiteral XML_XMLNS(u"xmlns")
constexpr OUStringLiteral XML_N_SMIL_OLD(u"http://www.w3.org/2001/SMIL20")
constexpr OUStringLiteral XML_N_SVG(u"http://www.w3.org/2000/svg")
constexpr OUStringLiteral XML_URI_XFORMS_SUFFIX(u"/xforms")
constexpr OUStringLiteral XML_N_SVG_COMPAT(u"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0")
constexpr OUStringLiteral XML_N_FO_COMPAT(u"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0")
constexpr OUStringLiteral XML_OPENDOCUMENT(u"opendocument")
constexpr OUStringLiteral XML_N_FO(u"http://www.w3.org/1999/XSL/Format")
constexpr OUStringLiteral XML_1_0(u"1.0")
constexpr OUStringLiteral XML_N_SMIL(u"http://www.w3.org/2001/SMIL20/")
rtl::Reference< ParserThread > m_xParser
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_extensions_xml_sax_FastParser_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void SAL_CALL throwException(Any const &exc)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OReadStatusBarDocumentHandler::StatusBar_XML_Namespace nNamespace
bool operator<(const wwFont &r1, const wwFont &r2)