[Libreoffice-commits] core.git: Branch 'feature/saxparser' - 7 commits - include/sax sax/CppunitTest_sax_parser.mk sax/Module_sax.mk sax/qa sax/source
Matúš Kukan
matus.kukan at gmail.com
Tue Oct 15 13:16:27 PDT 2013
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.kukan at 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.kukan at 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.kukan at 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.kukan at 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.kukan at 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.kukan at 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.kukan at 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)
{
More information about the Libreoffice-commits
mailing list