include/sax/fastattribs.hxx | 5 sax/CppunitTest_sax_parser.mk | 43 +++++++ sax/Module_sax.mk | 9 - sax/qa/cppunit/parser.cxx | 108 +++++++++++++++++++ sax/source/fastparser/fastparser.cxx | 198 ++++++++++++++++++----------------- sax/source/fastparser/fastparser.hxx | 44 ++++--- sax/source/tools/fastattribs.cxx | 73 ++++++------ 7 files changed, 324 insertions(+), 156 deletions(-)
New commits: commit d574f3781717add908985d74d2f568effaea2d5a Author: Matúš Kukan <matus.ku...@gmail.com> Date: Tue Oct 15 17:28:35 2013 +0200 sax: add unittest for fastparser Adapt FastSaxParser so that it does not require XFastDocumentHandler. Change-Id: I7af49752dfbb4b55b8dde094fe6b762bd179be78 diff --git a/sax/CppunitTest_sax_parser.mk b/sax/CppunitTest_sax_parser.mk new file mode 100644 index 0000000..ed2176d --- /dev/null +++ b/sax/CppunitTest_sax_parser.mk @@ -0,0 +1,43 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,sax_parser)) + +$(eval $(call gb_CppunitTest_add_exception_objects,sax_parser, \ + sax/qa/cppunit/parser \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,sax_parser, \ + comphelper \ + cppu \ + sal \ + test \ +)) + +$(eval $(call gb_CppunitTest_use_api,sax_parser,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_CppunitTest_use_ure,sax_parser)) + +$(eval $(call gb_CppunitTest_use_components,sax_parser,\ + configmgr/source/configmgr \ + framework/util/fwk \ + i18npool/util/i18npool \ + oox/util/oox \ + sax/source/fastparser/fastsax \ + sfx2/util/sfx \ + ucb/source/core/ucb1 \ + ucb/source/ucp/file/ucpfile1 \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,sax_parser)) + +# vim: set noet sw=4 ts=4: diff --git a/sax/Module_sax.mk b/sax/Module_sax.mk index 17c98c0..4352282 100644 --- a/sax/Module_sax.mk +++ b/sax/Module_sax.mk @@ -10,14 +10,15 @@ $(eval $(call gb_Module_Module,sax)) $(eval $(call gb_Module_add_targets,sax,\ - Library_expwrap \ - Library_fastsax \ - Library_sax \ + Library_expwrap \ + Library_fastsax \ + Library_sax \ StaticLibrary_sax_shared \ )) $(eval $(call gb_Module_add_check_targets,sax,\ - CppunitTest_sax \ + CppunitTest_sax \ + CppunitTest_sax_parser \ )) # vim: set noet sw=4 ts=4: diff --git a/sax/qa/cppunit/parser.cxx b/sax/qa/cppunit/parser.cxx new file mode 100644 index 0000000..861c53f --- /dev/null +++ b/sax/qa/cppunit/parser.cxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/io/Pipe.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/xml/sax/XFastParser.hpp> +#include <com/sun/star/xml/sax/XFastTokenHandler.hpp> + +#include <test/bootstrapfixture.hxx> +#include <comphelper/componentcontext.hxx> + +using namespace css; +using namespace css::xml::sax; + +namespace { + +class ParserTest: public test::BootstrapFixture +{ + InputSource maInput; + uno::Reference< XFastParser > mxParser; + uno::Reference< XFastTokenHandler > mxTokenHandler; + uno::Reference< XFastDocumentHandler > mxDocumentHandler; + +public: + virtual void setUp(); + virtual void tearDown(); + + void parse(); + + CPPUNIT_TEST_SUITE(ParserTest); + CPPUNIT_TEST(parse); + CPPUNIT_TEST_SUITE_END(); + +private: + uno::Reference< io::XInputStream > createStream(OString sInput); +}; + +void ParserTest::setUp() +{ + test::BootstrapFixture::setUp(); + mxParser.set( comphelper::ComponentContext(m_xContext).createComponent( + "com.sun.star.xml.sax.FastParser"), uno::UNO_QUERY ); + CPPUNIT_ASSERT_MESSAGE("No FastParser!", mxParser.is()); + mxTokenHandler.set( comphelper::ComponentContext(m_xContext).createComponent( + "com.sun.star.xml.sax.FastTokenHandler"), uno::UNO_QUERY ); + CPPUNIT_ASSERT_MESSAGE("No TokenHandler!", mxTokenHandler.is()); + mxParser->setTokenHandler( mxTokenHandler ); +} + +void ParserTest::tearDown() +{ + test::BootstrapFixture::tearDown(); +} + +uno::Reference< io::XInputStream > ParserTest::createStream(OString sInput) +{ + uno::Reference< io::XOutputStream > xPipe( io::Pipe::create(m_xContext) ); + uno::Reference< io::XInputStream > xInStream( xPipe, uno::UNO_QUERY ); + uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)sInput.getStr(), sInput.getLength() ); + xPipe->writeBytes( aSeq ); + xPipe->flush(); + xPipe->closeOutput(); + return xInStream; +} + +void ParserTest::parse() +{ + maInput.aInputStream = createStream("<a>...<b />..</a>"); + mxParser->parseStream( maInput ); + + maInput.aInputStream = createStream("<b></a>"); + bool bException = false; + try + { + mxParser->parseStream( maInput ); + } + catch (const SAXParseException &) + { + bException = true; + } + CPPUNIT_ASSERT_MESSAGE("No Exception!", bException); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(ParserTest); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index a271c28..664b28b 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -246,7 +246,7 @@ void Entity::startElement( Event *pEvent ) { if( xParentContext.is() ) xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr ); - else + else if( mxDocumentHandler.is() ) xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr ); if( xContext.is() ) @@ -258,7 +258,7 @@ void Entity::startElement( Event *pEvent ) { if( xParentContext.is() ) xContext = xParentContext->createFastChildContext( nElementToken, xAttr ); - else + else if( mxDocumentHandler.is() ) xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr ); if( xContext.is() ) commit 7036afe099a387ebcce686378140e68447657dec Author: Matúš Kukan <matus.ku...@gmail.com> Date: Tue Oct 15 14:43:24 2013 +0200 fastparser: don't create temporary Events; use references to event list Change-Id: I1e12fbeeb90d6020d0566d05fc0318082e1da5fc diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 0e90dcb..a271c28 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -76,7 +76,8 @@ private: } catch (const SAXParseException& e) { - mpParser->produce(Event( CallbackType::EXCEPTION )); + mpParser->getEntity().getEvent( CallbackType::EXCEPTION ); + mpParser->produce( CallbackType::EXCEPTION ); } } }; @@ -187,28 +188,6 @@ OUString SAL_CALL FastLocatorImpl::getSystemId(void) throw (RuntimeException) // -------------------------------------------------------------------- -Event::Event(const CallbackType& t): maType(t) -{} - -Event::Event(const CallbackType& t, const OUString& sChars): Event(t) -{ - msChars = sChars; -} - -Event::Event(const CallbackType& t, sal_Int32 nElementToken, const OUString& aNamespace, - const OUString& aElementName, FastAttributeList *pAttributes): Event(t) -{ - mnElementToken = nElementToken; - maNamespace = aNamespace; - maElementName = aElementName; - mpAttributes = rtl::Reference< FastAttributeList >(pAttributes); -} - -Event::~Event() -{} - -// -------------------------------------------------------------------- - ParserData::ParserData() {} @@ -243,9 +222,9 @@ Entity::~Entity() void Entity::startElement( Event *pEvent ) { - const sal_Int32& nElementToken = pEvent->mnElementToken.get(); - const OUString& aNamespace = pEvent->maNamespace.get(); - const OUString& aElementName = pEvent->maElementName.get(); + const sal_Int32& nElementToken = pEvent->mnElementToken; + const OUString& aNamespace = pEvent->msNamespace; + const OUString& aElementName = pEvent->msElementName; Reference< XFastContextHandler > xParentContext; if( !maContextStack.empty() ) { @@ -261,7 +240,7 @@ void Entity::startElement( Event *pEvent ) try { - Reference< XFastAttributeList > xAttr( pEvent->mpAttributes.get().get() ); + Reference< XFastAttributeList > xAttr( pEvent->mxAttributes.get() ); Reference< XFastContextHandler > xContext; if( nElementToken == FastToken::DONTKNOW ) { @@ -337,17 +316,26 @@ EventList* Entity::getEventList() mpProducedEvents = maUsedEvents.front(); maUsedEvents.pop(); aGuard.clear(); // unlock - mpProducedEvents->clear(); + mnProducedEventsSize = 0; } if (!mpProducedEvents) { mpProducedEvents = new EventList(); - mpProducedEvents->reserve(mnEventListSize); + mpProducedEvents->resize(mnEventListSize); + mnProducedEventsSize = 0; } } return mpProducedEvents; } +Event& Entity::getEvent( CallbackType aType ) +{ + EventList* pEventList = getEventList(); + Event& rEvent = (*pEventList)[mnProducedEventsSize++]; + rEvent.maType = aType; + return rEvent; +} + // -------------------------------------------------------------------- // FastSaxParser implementation // -------------------------------------------------------------------- @@ -604,6 +592,7 @@ void FastSaxParser::parseStream( const InputSource& maStructSource) throw (SAXEx done = true; aGuard.reset(); // lock + rEntity.maUsedEvents.push(pEventList); } } while (!done); xParser->join(); @@ -792,14 +781,12 @@ void FastSaxParser::deleteUsedEvents() } } -void FastSaxParser::produce(const Event& aEvent) +void FastSaxParser::produce( CallbackType aType ) { Entity& rEntity = getEntity(); - EventList* pEventList = rEntity.getEventList(); - pEventList->push_back( aEvent ); - if (aEvent.maType == CallbackType::DONE || - aEvent.maType == CallbackType::EXCEPTION || - pEventList->size() == rEntity.mnEventListSize) + if (aType == CallbackType::DONE || + aType == CallbackType::EXCEPTION || + rEntity.mnProducedEventsSize == rEntity.mnEventListSize) { osl::ResettableMutexGuard aGuard(rEntity.maEventProtector); @@ -811,7 +798,7 @@ void FastSaxParser::produce(const Event& aEvent) aGuard.reset(); // lock } - rEntity.maPendingEvents.push(pEventList); + rEntity.maPendingEvents.push(rEntity.mpProducedEvents); rEntity.mpProducedEvents = 0; aGuard.clear(); // unlock @@ -823,7 +810,6 @@ void FastSaxParser::produce(const Event& aEvent) bool FastSaxParser::consume(EventList *pEventList) { Entity& rEntity = getEntity(); - bool bIsParserFinished = false; for (EventList::iterator aEventIt = pEventList->begin(); aEventIt != pEventList->end(); ++aEventIt) { @@ -836,13 +822,12 @@ bool FastSaxParser::consume(EventList *pEventList) rEntity.endElement(); break; case CallbackType::CHARACTERS: - rEntity.characters( (*aEventIt).msChars.get() ); + rEntity.characters( (*aEventIt).msChars ); break; case CallbackType::DONE: - bIsParserFinished = true; - assert(aEventIt+1 == pEventList->end()); - break; + return false; case CallbackType::EXCEPTION: + { assert( rEntity.maSavedException.hasValue() ); // Error during parsing ! XML_Error xmlE = XML_GetErrorCode( rEntity.mpParser ); @@ -863,10 +848,13 @@ bool FastSaxParser::consume(EventList *pEventList) rEntity.mxErrorHandler->fatalError( Any( aExcept ) ); throw aExcept; + } + default: + assert(false); + return false; } } - rEntity.maUsedEvents.push(pEventList); - return !bIsParserFinished; + return true; } // starts parsing with actual parser ! @@ -916,7 +904,8 @@ void FastSaxParser::parse() } } while( nRead > 0 ); - produce(Event( CallbackType::DONE )); + rEntity.getEvent( CallbackType::DONE ); + produce( CallbackType::DONE ); } //------------------------------------------ @@ -939,15 +928,20 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char } // create attribute map and process namespace instructions + Event& rEvent = getEntity().getEvent( CallbackType::START_ELEMENT ); + if (rEvent.mxAttributes.is()) + rEvent.mxAttributes->clear(); + else + rEvent.mxAttributes.set( new FastAttributeList( rEntity.mxTokenHandler ) ); + sal_Int32 nNameLen, nPrefixLen; const XML_Char *pName; const XML_Char *pPrefix; - OUString sNamespace; + sal_Int32 nNamespaceToken = FastToken::DONTKNOW; - FastAttributeList *pAttributes = new FastAttributeList( rEntity.mxTokenHandler ); if (!rEntity.maNamespaceStack.empty()) { - sNamespace = rEntity.maNamespaceStack.top().msName; + rEvent.msNamespace = rEntity.maNamespaceStack.top().msName; nNamespaceToken = rEntity.maNamespaceStack.top().mnToken; } @@ -976,8 +970,8 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) ) { // default namespace is the attribute value - sNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 ); - nNamespaceToken = GetNamespaceToken( sNamespace ); + rEvent.msNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 ); + nNamespaceToken = GetNamespaceToken( rEvent.msNamespace ); } } } @@ -992,9 +986,9 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char { sal_Int32 nAttributeToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen ); if( nAttributeToken != FastToken::DONTKNOW ) - pAttributes->add( nAttributeToken, OString(awAttributes[i+1]) ); + rEvent.mxAttributes->add( nAttributeToken, OString(awAttributes[i+1]) ); else - pAttributes->addUnknown( GetNamespaceURL( pPrefix, nPrefixLen ), + rEvent.mxAttributes->addUnknown( GetNamespaceURL( pPrefix, nPrefixLen ), OString(pName, nNameLen), OString(awAttributes[i+1]) ); } } @@ -1004,32 +998,31 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char { sal_Int32 nAttributeToken = GetToken( pName, nNameLen ); if( nAttributeToken != FastToken::DONTKNOW ) - pAttributes->add( nAttributeToken, OString(awAttributes[i+1]) ); + rEvent.mxAttributes->add( nAttributeToken, OString(awAttributes[i+1]) ); else - pAttributes->addUnknown( OString(pName, nNameLen), OString(awAttributes[i+1]) ); + rEvent.mxAttributes->addUnknown( OString(pName, nNameLen), OString(awAttributes[i+1]) ); } } } - sal_Int32 nElementToken; splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen ); if( nPrefixLen > 0 ) - nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen ); - else if( !sNamespace.isEmpty() ) - nElementToken = GetTokenWithContextNamespace( nNamespaceToken, pName, nNameLen ); + rEvent.mnElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen ); + else if( !rEvent.msNamespace.isEmpty() ) + rEvent.mnElementToken = GetTokenWithContextNamespace( nNamespaceToken, pName, nNameLen ); else - nElementToken = GetToken( pName ); + rEvent.mnElementToken = GetToken( pName ); - if( nElementToken == FastToken::DONTKNOW ) + if( rEvent.mnElementToken == FastToken::DONTKNOW ) if( nPrefixLen > 0 ) { - sNamespace = GetNamespaceURL( pPrefix, nPrefixLen ); - nNamespaceToken = GetNamespaceToken( sNamespace ); + rEvent.msNamespace = GetNamespaceURL( pPrefix, nPrefixLen ); + nNamespaceToken = GetNamespaceToken( rEvent.msNamespace ); } - rEntity.maNamespaceStack.push( NameWithToken(sNamespace, nNamespaceToken) ); - produce(Event( CallbackType::START_ELEMENT, nElementToken, sNamespace, - OUString(pName, nNameLen, RTL_TEXTENCODING_UTF8), pAttributes )); + rEntity.maNamespaceStack.push( NameWithToken(rEvent.msNamespace, nNamespaceToken) ); + rEvent.msElementName = OUString(pName, nNameLen, RTL_TEXTENCODING_UTF8); + produce( CallbackType::START_ELEMENT ); } catch (const Exception& e) { @@ -1048,13 +1041,16 @@ void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* ) if( !rEntity.maNamespaceStack.empty() ) rEntity.maNamespaceStack.pop(); - produce(Event( CallbackType::END_ELEMENT )); + rEntity.getEvent( CallbackType::END_ELEMENT ); + produce( CallbackType::END_ELEMENT ); } void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen ) { - produce(Event( CallbackType::CHARACTERS, OUString(s, nLen, RTL_TEXTENCODING_UTF8) )); + Event& rEvent = getEntity().getEvent( CallbackType::CHARACTERS ); + rEvent.msChars = OUString(s, nLen, RTL_TEXTENCODING_UTF8); + produce( CallbackType::CHARACTERS ); } void FastSaxParser::callbackEntityDecl( diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx index 135cf6c..28ce7e2 100644 --- a/sax/source/fastparser/fastparser.hxx +++ b/sax/source/fastparser/fastparser.hxx @@ -56,7 +56,7 @@ typedef ::boost::unordered_map< OUString, sal_Int32, typedef std::vector<Event> EventList; -enum CallbackType { START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION }; +enum CallbackType { INVALID, START_ELEMENT, END_ELEMENT, CHARACTERS, DONE, EXCEPTION }; struct NameWithToken { @@ -67,17 +67,12 @@ struct NameWithToken }; struct Event { - boost::optional< OUString > msChars; - boost::optional< sal_Int32 > mnElementToken; - boost::optional< OUString > maNamespace; - boost::optional< OUString > maElementName; - boost::optional< rtl::Reference< FastAttributeList > > mpAttributes; + OUString msChars; + sal_Int32 mnElementToken; + OUString msNamespace; + OUString msElementName; + rtl::Reference< FastAttributeList > mxAttributes; CallbackType maType; - Event(const CallbackType& t); - Event(const CallbackType& t, const OUString& sChars); - Event(const CallbackType& t, sal_Int32 nElementToken, const OUString& aNamespace, - const OUString& aElementName, FastAttributeList *pAttributes); - ~Event(); }; // -------------------------------------------------------------------- @@ -112,6 +107,8 @@ struct Entity : public ParserData { // unique for each Entity instance: + // Number of valid events in mpProducedEvents: + size_t mnProducedEventsSize; EventList *mpProducedEvents; std::queue< EventList * > maPendingEvents; std::queue< EventList * > maUsedEvents; @@ -150,6 +147,7 @@ struct Entity : public ParserData void characters( const OUString& sChars ); void endElement(); EventList* getEventList(); + Event& getEvent( CallbackType aType ); }; // -------------------------------------------------------------------- @@ -193,7 +191,7 @@ public: inline void popEntity() { maEntities.pop(); } Entity& getEntity() { return maEntities.top(); } void parse(); - void produce( const Event& ); + void produce( CallbackType aType ); private: bool consume(EventList *); commit d94c70368db5d5dfa9ecce58ebf55f4fbc7ee237 Author: Matúš Kukan <matus.ku...@gmail.com> Date: Tue Oct 15 11:39:04 2013 +0200 fastparser: fix leak by storing rtl::Reference instead of pointer Change-Id: I003dc48fed9029c9af430d4d2d361425d351ff54 diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 2484d22..0e90dcb 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -201,7 +201,7 @@ Event::Event(const CallbackType& t, sal_Int32 nElementToken, const OUString& aNa mnElementToken = nElementToken; maNamespace = aNamespace; maElementName = aElementName; - mpAttributes = pAttributes; + mpAttributes = rtl::Reference< FastAttributeList >(pAttributes); } Event::~Event() @@ -241,9 +241,11 @@ Entity::~Entity() { } -void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace, - const OUString& aElementName, FastAttributeList *pAttributes ) +void Entity::startElement( Event *pEvent ) { + const sal_Int32& nElementToken = pEvent->mnElementToken.get(); + const OUString& aNamespace = pEvent->maNamespace.get(); + const OUString& aElementName = pEvent->maElementName.get(); Reference< XFastContextHandler > xParentContext; if( !maContextStack.empty() ) { @@ -259,7 +261,7 @@ void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace, try { - Reference< XFastAttributeList > xAttr( pAttributes ); + Reference< XFastAttributeList > xAttr( pEvent->mpAttributes.get().get() ); Reference< XFastContextHandler > xContext; if( nElementToken == FastToken::DONTKNOW ) { @@ -822,14 +824,13 @@ bool FastSaxParser::consume(EventList *pEventList) { Entity& rEntity = getEntity(); bool bIsParserFinished = false; - for (EventList::const_iterator aEventIt = pEventList->begin(); + for (EventList::iterator aEventIt = pEventList->begin(); aEventIt != pEventList->end(); ++aEventIt) { switch ((*aEventIt).maType) { case CallbackType::START_ELEMENT: - rEntity.startElement( (*aEventIt).mnElementToken.get(), (*aEventIt).maNamespace.get(), - (*aEventIt).maElementName.get(), (*aEventIt).mpAttributes.get() ); + rEntity.startElement( &(*aEventIt) ); break; case CallbackType::END_ELEMENT: rEntity.endElement(); diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx index 1e154b8..135cf6c 100644 --- a/sax/source/fastparser/fastparser.hxx +++ b/sax/source/fastparser/fastparser.hxx @@ -71,7 +71,7 @@ struct Event { boost::optional< sal_Int32 > mnElementToken; boost::optional< OUString > maNamespace; boost::optional< OUString > maElementName; - boost::optional< FastAttributeList * > mpAttributes; + boost::optional< rtl::Reference< FastAttributeList > > mpAttributes; CallbackType maType; Event(const CallbackType& t); Event(const CallbackType& t, const OUString& sChars); @@ -146,8 +146,7 @@ struct Entity : public ParserData explicit Entity( const ParserData& rData ); Entity( const Entity& rEntity ); ~Entity(); - void startElement( sal_Int32 nElementToken, const OUString& aNamespace, - const OUString& aElementName, FastAttributeList *pAttributes ); + void startElement( Event *pEvent ); void characters( const OUString& sChars ); void endElement(); EventList* getEventList(); commit 14b69701f0da5a6133a7e174c6328416512341a3 Author: Matúš Kukan <matus.ku...@gmail.com> Date: Tue Oct 15 10:32:55 2013 +0200 fastparser: re-use event lists if possible Change-Id: I53800abaca51d42d7d44a98fb271de7df7f90f58 diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index deee49e..2484d22 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -324,6 +324,28 @@ void Entity::endElement() } maContextStack.pop(); } + +EventList* Entity::getEventList() +{ + if (!mpProducedEvents) + { + osl::ResettableMutexGuard aGuard(maEventProtector); + if (!maUsedEvents.empty()) + { + mpProducedEvents = maUsedEvents.front(); + maUsedEvents.pop(); + aGuard.clear(); // unlock + mpProducedEvents->clear(); + } + if (!mpProducedEvents) + { + mpProducedEvents = new EventList(); + mpProducedEvents->reserve(mnEventListSize); + } + } + return mpProducedEvents; +} + // -------------------------------------------------------------------- // FastSaxParser implementation // -------------------------------------------------------------------- @@ -771,15 +793,11 @@ void FastSaxParser::deleteUsedEvents() void FastSaxParser::produce(const Event& aEvent) { Entity& rEntity = getEntity(); - if (!rEntity.mpProducedEvents) - { - rEntity.mpProducedEvents = new EventList(); - rEntity.mpProducedEvents->reserve(rEntity.mnEventListSize); - } - rEntity.mpProducedEvents->push_back( aEvent ); + EventList* pEventList = rEntity.getEventList(); + pEventList->push_back( aEvent ); if (aEvent.maType == CallbackType::DONE || aEvent.maType == CallbackType::EXCEPTION || - rEntity.mpProducedEvents->size() == rEntity.mnEventListSize) + pEventList->size() == rEntity.mnEventListSize) { osl::ResettableMutexGuard aGuard(rEntity.maEventProtector); @@ -791,14 +809,12 @@ void FastSaxParser::produce(const Event& aEvent) aGuard.reset(); // lock } - rEntity.maPendingEvents.push(rEntity.mpProducedEvents); + rEntity.maPendingEvents.push(pEventList); rEntity.mpProducedEvents = 0; aGuard.clear(); // unlock rEntity.maConsumeResume.set(); - - deleteUsedEvents(); } } diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx index 8859c46..1e154b8 100644 --- a/sax/source/fastparser/fastparser.hxx +++ b/sax/source/fastparser/fastparser.hxx @@ -150,6 +150,7 @@ struct Entity : public ParserData const OUString& aElementName, FastAttributeList *pAttributes ); void characters( const OUString& sChars ); void endElement(); + EventList* getEventList(); }; // -------------------------------------------------------------------- commit 51137d7e4a63dc4be1e1f01873d74f7e541b4251 Author: Matúš Kukan <matus.ku...@gmail.com> Date: Tue Oct 15 09:29:27 2013 +0200 FastAttributeList: use vectors instead of map; the size is small Change-Id: If0ea36155d8ab3f5c91c2aafd6932fabeadadd41 diff --git a/include/sax/fastattribs.hxx b/include/sax/fastattribs.hxx index f31be4b..88e9d61 100644 --- a/include/sax/fastattribs.hxx +++ b/include/sax/fastattribs.hxx @@ -47,7 +47,6 @@ struct UnknownAttribute void FillAttribute( ::com::sun::star::xml::Attribute* pAttrib ) const; }; -typedef std::map< sal_Int32, OString > FastAttributeMap; typedef std::vector< UnknownAttribute > UnknownAttributeList; class SAX_DLLPUBLIC FastAttributeList : public ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastAttributeList > @@ -71,9 +70,9 @@ public: virtual ::com::sun::star::uno::Sequence< ::com::sun::star::xml::FastAttribute > SAL_CALL getFastAttributes() throw (::com::sun::star::uno::RuntimeException); private: - FastAttributeMap maAttributes; + std::vector< sal_Int32 > maAttributeTokens; + std::vector< OString > maAttributeValues; UnknownAttributeList maUnknownAttributes; - FastAttributeMap::iterator maLastIter; ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler > mxTokenHandler; }; diff --git a/sax/source/tools/fastattribs.cxx b/sax/source/tools/fastattribs.cxx index bb348a4..b25ff08 100644 --- a/sax/source/tools/fastattribs.cxx +++ b/sax/source/tools/fastattribs.cxx @@ -50,7 +50,6 @@ void UnknownAttribute::FillAttribute( Attribute* pAttrib ) const FastAttributeList::FastAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastTokenHandler >& xTokenHandler ) : mxTokenHandler( xTokenHandler ) { - maLastIter = maAttributes.end(); } FastAttributeList::~FastAttributeList() @@ -59,14 +58,15 @@ FastAttributeList::~FastAttributeList() void FastAttributeList::clear() { - maAttributes.clear(); + maAttributeTokens.clear(); + maAttributeValues.clear(); maUnknownAttributes.clear(); - maLastIter = maAttributes.end(); } void FastAttributeList::add( sal_Int32 nToken, const OString& rValue ) { - maAttributes[nToken] = rValue; + maAttributeTokens.push_back( nToken ); + maAttributeValues.push_back( rValue ); } void FastAttributeList::addUnknown( const OUString& rNamespaceURL, const OString& rName, const OString& rValue ) @@ -82,55 +82,53 @@ void FastAttributeList::addUnknown( const OString& rName, const OString& rValue // XFastAttributeList sal_Bool FastAttributeList::hasAttribute( ::sal_Int32 Token ) throw (RuntimeException) { - maLastIter = maAttributes.find( Token ); - return ( maLastIter != maAttributes.end() ) ? sal_True : sal_False; + for (size_t i = 0; i < maAttributeTokens.size(); ++i) + if (maAttributeTokens[i] == Token) + return sal_True; + + return sal_False; } sal_Int32 FastAttributeList::getValueToken( ::sal_Int32 Token ) throw (SAXException, RuntimeException) { - if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) ) - maLastIter = maAttributes.find( Token ); - - if( maLastIter == maAttributes.end() ) - throw SAXException(); + for (size_t i = 0; i < maAttributeTokens.size(); ++i) + if (maAttributeTokens[i] == Token) + { + Sequence< sal_Int8 > aSeq( (sal_Int8*) maAttributeValues[i].getStr(), maAttributeValues[i].getLength() ); + return mxTokenHandler->getTokenFromUTF8( aSeq ); + } - Sequence< sal_Int8 > aSeq( (sal_Int8*)(*maLastIter).second.getStr(), (*maLastIter).second.getLength() ) ; - return mxTokenHandler->getTokenFromUTF8( aSeq ); + throw SAXException(); } sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int32 Default ) throw (RuntimeException) { - if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) ) - maLastIter = maAttributes.find( Token ); - - if( maLastIter == maAttributes.end() ) - return Default; + for (size_t i = 0; i < maAttributeTokens.size(); ++i) + if (maAttributeTokens[i] == Token) + { + Sequence< sal_Int8 > aSeq( (sal_Int8*) maAttributeValues[i].getStr(), maAttributeValues[i].getLength() ); + return mxTokenHandler->getTokenFromUTF8( aSeq ); + } - Sequence< sal_Int8 > aSeq( (sal_Int8*)(*maLastIter).second.getStr(), (*maLastIter).second.getLength() ) ; - return mxTokenHandler->getTokenFromUTF8( aSeq ); + return Default; } OUString FastAttributeList::getValue( ::sal_Int32 Token ) throw (SAXException, RuntimeException) { - if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) ) - maLastIter = maAttributes.find( Token ); + for (size_t i = 0; i < maAttributeTokens.size(); ++i) + if (maAttributeTokens[i] == Token) + return OStringToOUString( maAttributeValues[i], RTL_TEXTENCODING_UTF8 ); - if( maLastIter == maAttributes.end() ) - throw SAXException(); - - return OStringToOUString( (*maLastIter).second, RTL_TEXTENCODING_UTF8 ); + throw SAXException(); } OUString FastAttributeList::getOptionalValue( ::sal_Int32 Token ) throw (RuntimeException) { - if( ( maLastIter == maAttributes.end() ) || ( ( *maLastIter ).first != Token ) ) - maLastIter = maAttributes.find( Token ); - - OUString aRet; - if( maLastIter != maAttributes.end() ) - aRet = OStringToOUString( (*maLastIter).second, RTL_TEXTENCODING_UTF8 ); + for (size_t i = 0; i < maAttributeTokens.size(); ++i) + if (maAttributeTokens[i] == Token) + return OStringToOUString( maAttributeValues[i], RTL_TEXTENCODING_UTF8 ); - return aRet; + return OUString(); } Sequence< Attribute > FastAttributeList::getUnknownAttributes( ) throw (RuntimeException) { @@ -142,13 +140,12 @@ Sequence< Attribute > FastAttributeList::getUnknownAttributes( ) throw (Runtime } Sequence< FastAttribute > FastAttributeList::getFastAttributes( ) throw (RuntimeException) { - Sequence< FastAttribute > aSeq( maAttributes.size() ); + Sequence< FastAttribute > aSeq( maAttributeTokens.size() ); FastAttribute* pAttr = aSeq.getArray(); - FastAttributeMap::iterator fastAttrIter = maAttributes.begin(); - for(; fastAttrIter != maAttributes.end(); ++fastAttrIter ) + for (size_t i = 0; i < maAttributeTokens.size(); ++i) { - pAttr->Token = fastAttrIter->first; - pAttr->Value = OStringToOUString( fastAttrIter->second, RTL_TEXTENCODING_UTF8 ); + pAttr->Token = maAttributeTokens[i]; + pAttr->Value = OStringToOUString( maAttributeValues[i], RTL_TEXTENCODING_UTF8 ); pAttr++; } return aSeq; commit a606a6b91955f5da17c0e6c88365e484f2e2b0cf Author: Matúš Kukan <matus.ku...@gmail.com> Date: Mon Oct 14 21:47:54 2013 +0200 fastparser: don't use pointers in context stack Change-Id: Id45fd2edd6186b58062bb77e894b7d8618b723e8 diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 9c0b176..deee49e 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -24,7 +24,6 @@ #include <salhelper/thread.hxx> #include <com/sun/star/lang/DisposedException.hpp> -#include <com/sun/star/xml/sax/XFastContextHandler.hpp> #include <com/sun/star/xml/sax/SAXParseException.hpp> #include <com/sun/star/xml/sax/FastToken.hpp> @@ -42,25 +41,15 @@ using namespace ::com::sun::star::io; namespace sax_fastparser { -// -------------------------------------------------------------------- - -struct SaxContextImpl -{ - Reference< XFastContextHandler > mxContext; - sal_Int32 mnElementToken; - boost::optional< OUString > maNamespace; - boost::optional< OUString > maElementName; - - SaxContextImpl( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ): +SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ): mnElementToken(nElementToken) +{ + if (nElementToken == FastToken::DONTKNOW) { - if (nElementToken == FastToken::DONTKNOW) - { - maNamespace = aNamespace; - maElementName = aElementName; - } + maNamespace = aNamespace; + maElementName = aElementName; } -}; +} // -------------------------------------------------------------------- @@ -258,15 +247,15 @@ void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace, Reference< XFastContextHandler > xParentContext; if( !maContextStack.empty() ) { - xParentContext = maContextStack.top()->mxContext; + xParentContext = maContextStack.top().mxContext; if (!xParentContext.is()) { - maContextStack.push( new SaxContextImpl(nElementToken, aNamespace, aElementName) ); + maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) ); return; } } - maContextStack.push( new SaxContextImpl(nElementToken, aNamespace, aElementName) ); + maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) ); try { @@ -296,7 +285,7 @@ void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace, xContext->startFastElement( nElementToken, xAttr ); } } - maContextStack.top()->mxContext = xContext; + maContextStack.top().mxContext = xContext; } catch (const Exception& e) { @@ -306,7 +295,7 @@ void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace, void Entity::characters( const OUString& sChars ) { - const Reference< XFastContextHandler >& xContext( maContextStack.top()->mxContext ); + const Reference< XFastContextHandler >& xContext( maContextStack.top().mxContext ); if( xContext.is() ) try { xContext->characters( sChars ); @@ -319,21 +308,20 @@ void Entity::characters( const OUString& sChars ) void Entity::endElement() { - SaxContextImpl* pContext = maContextStack.top(); - const Reference< XFastContextHandler >& xContext( pContext->mxContext ); + const SaxContext& aContext = maContextStack.top(); + const Reference< XFastContextHandler >& xContext( aContext.mxContext ); if( xContext.is() ) try { - sal_Int32 nElementToken = pContext->mnElementToken; + sal_Int32 nElementToken = aContext.mnElementToken; if( nElementToken != FastToken::DONTKNOW ) xContext->endFastElement( nElementToken ); else - xContext->endUnknownElement( pContext->maNamespace.get(), pContext->maElementName.get() ); + xContext->endUnknownElement( aContext.maNamespace.get(), aContext.maElementName.get() ); } catch (const Exception& e) { maSavedException <<= e; } - delete pContext; maContextStack.pop(); } // -------------------------------------------------------------------- diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx index 184f4ef..8859c46 100644 --- a/sax/source/fastparser/fastparser.hxx +++ b/sax/source/fastparser/fastparser.hxx @@ -28,9 +28,10 @@ #include <boost/unordered_map.hpp> #include <osl/conditn.hxx> #include <rtl/ref.hxx> +#include <com/sun/star/xml/sax/XFastContextHandler.hpp> +#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> #include <com/sun/star/xml/sax/XFastParser.hpp> #include <com/sun/star/xml/sax/XFastTokenHandler.hpp> -#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <cppuhelper/implbase2.hxx> @@ -47,7 +48,6 @@ namespace sax_fastparser { struct Event; class FastLocatorImpl; struct NamespaceDefine; -struct SaxContextImpl; typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef; @@ -82,6 +82,17 @@ struct Event { // -------------------------------------------------------------------- +struct SaxContext +{ + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > mxContext; + sal_Int32 mnElementToken; + boost::optional< OUString > maNamespace; + boost::optional< OUString > maElementName; + SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ); +}; + +// -------------------------------------------------------------------- + struct ParserData { ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler; @@ -124,7 +135,10 @@ struct Entity : public ParserData ::com::sun::star::uno::Any maSavedException; ::std::stack< NameWithToken > maNamespaceStack; - ::std::stack< SaxContextImpl* > maContextStack; + /* Context for main thread consuming events. + * startElement() stores the data, which characters() and endElement() uses + */ + ::std::stack< SaxContext> maContextStack; // Determines which elements of maNamespaceDefines are valid in current context ::std::stack< sal_uInt32 > maNamespaceCount; ::std::vector< NamespaceDefineRef > maNamespaceDefines; commit e1571394d6dfd28b27c3a00f48dcb1d8f20496b9 Author: Matúš Kukan <matus.ku...@gmail.com> Date: Mon Oct 14 18:23:36 2013 +0200 fastparser: use boost::optional in SaxContextImpl Change-Id: Ia6c797b105348afcc0c426ba2abe3fa0a3c452fe diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx index 8941b0e..9c0b176 100644 --- a/sax/source/fastparser/fastparser.cxx +++ b/sax/source/fastparser/fastparser.cxx @@ -47,12 +47,19 @@ namespace sax_fastparser { struct SaxContextImpl { Reference< XFastContextHandler > mxContext; - sal_Int32 mnElementToken; - OUString maNamespace; - OUString maElementName; + sal_Int32 mnElementToken; + boost::optional< OUString > maNamespace; + boost::optional< OUString > maElementName; SaxContextImpl( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ): - mnElementToken(nElementToken), maNamespace(aNamespace), maElementName(aElementName) {} + mnElementToken(nElementToken) + { + if (nElementToken == FastToken::DONTKNOW) + { + maNamespace = aNamespace; + maElementName = aElementName; + } + } }; // -------------------------------------------------------------------- @@ -320,7 +327,7 @@ void Entity::endElement() if( nElementToken != FastToken::DONTKNOW ) xContext->endFastElement( nElementToken ); else - xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName ); + xContext->endUnknownElement( pContext->maNamespace.get(), pContext->maElementName.get() ); } catch (const Exception& e) {
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits