summaryrefslogtreecommitdiff
path: root/sax
diff options
context:
space:
mode:
authorMatúš Kukan <matus.kukan@gmail.com>2013-10-08 15:17:01 +0200
committerMatúš Kukan <matus.kukan@gmail.com>2013-10-17 21:38:35 +0200
commit03d76d034e5e5e30cc8de98e103c5a6e881ec06b (patch)
treedebabb8c482eb2da1690f480b11fdf0660e68150 /sax
parentbd4c869bbb66839506a45b71ab64792289ac7256 (diff)
fastparser: isolate calls to XFastContextHandler in Entity's methods
Unfortunately, we have to store maNamespace in two stacks. One for future parser thread to compute tokens and one for main thread calling XFastContextHandler. Now we are prepared to implement multithreading. Change-Id: I421b55afa2e9ea80142e6068c7a515d31913ba69
Diffstat (limited to 'sax')
-rw-r--r--sax/source/fastparser/fastparser.cxx236
-rw-r--r--sax/source/fastparser/fastparser.hxx29
2 files changed, 141 insertions, 124 deletions
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 623638a1a9dd..c67658adda93 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -23,7 +23,6 @@
#include <rtl/ustrbuf.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>
@@ -41,18 +40,15 @@ using namespace ::com::sun::star::io;
namespace sax_fastparser {
-// --------------------------------------------------------------------
-
-struct SaxContextImpl
+SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
+ mnElementToken(nElementToken)
{
- Reference< XFastContextHandler > mxContext;
- sal_Int32 mnElementToken;
- OUString maNamespace;
- OUString maElementName;
-
- SaxContextImpl() { mnElementToken = 0; }
- SaxContextImpl( const SaxContextImplPtr& p ) { mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
-};
+ if (nElementToken == FastToken::DONTKNOW)
+ {
+ maNamespace = aNamespace;
+ maElementName = aElementName;
+ }
+}
// --------------------------------------------------------------------
@@ -193,52 +189,105 @@ Entity::~Entity()
{
}
-// --------------------------------------------------------------------
-// FastSaxParser implementation
-// --------------------------------------------------------------------
-
-FastSaxParser::FastSaxParser()
+void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace,
+ const OUString& aElementName, FastAttributeList *pAttributes )
{
- mxDocumentLocator.set( new FastLocatorImpl( this ) );
- maUtf8Buffer.realloc( mnUtf8BufferSize );
-}
+ Reference< XFastContextHandler > xParentContext;
+ if( !maContextStack.empty() )
+ {
+ xParentContext = maContextStack.top().mxContext;
+ if (!xParentContext.is())
+ {
+ maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
+ return;
+ }
+ }
-// --------------------------------------------------------------------
+ maContextStack.push( SaxContext(nElementToken, aNamespace, aElementName) );
-FastSaxParser::~FastSaxParser()
-{
- if( mxDocumentLocator.is() )
- mxDocumentLocator->dispose();
+ try
+ {
+ Reference< XFastAttributeList > xAttr( pAttributes );
+ Reference< XFastContextHandler > xContext;
+ if( nElementToken == FastToken::DONTKNOW )
+ {
+ if( xParentContext.is() )
+ xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
+ else if( mxDocumentHandler.is() )
+ xContext = mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
+
+ if( xContext.is() )
+ {
+ xContext->startUnknownElement( aNamespace, aElementName, xAttr );
+ }
+ }
+ else
+ {
+ if( xParentContext.is() )
+ xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
+ else if( mxDocumentHandler.is() )
+ xContext = mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
+
+ if( xContext.is() )
+ {
+ xContext->startFastElement( nElementToken, xAttr );
+ }
+ }
+ maContextStack.top().mxContext = xContext;
+ }
+ catch (const Exception& e)
+ {
+ maSavedException <<= e;
+ }
}
-// --------------------------------------------------------------------
+void Entity::characters( const OUString& sChars )
+{
+ const Reference< XFastContextHandler >& xContext( maContextStack.top().mxContext );
+ if( xContext.is() ) try
+ {
+ xContext->characters( sChars );
+ }
+ catch (const Exception& e)
+ {
+ maSavedException <<= e;
+ }
+}
-void FastSaxParser::pushContext()
+void Entity::endElement()
{
- Entity& rEntity = getEntity();
- if( rEntity.maContextStack.empty() )
+ const SaxContext& aContext = maContextStack.top();
+ const Reference< XFastContextHandler >& xContext( aContext.mxContext );
+ if( xContext.is() ) try
{
- rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) );
- rEntity.maNamespaceCount.push(0);
- DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
+ sal_Int32 nElementToken = aContext.mnElementToken;
+ if( nElementToken != FastToken::DONTKNOW )
+ xContext->endFastElement( nElementToken );
+ else
+ xContext->endUnknownElement( aContext.maNamespace.get(), aContext.maElementName.get() );
}
- else
+ catch (const Exception& e)
{
- rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) );
- rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
+ maSavedException <<= e;
}
+ maContextStack.pop();
+}
+// --------------------------------------------------------------------
+// FastSaxParser implementation
+// --------------------------------------------------------------------
+
+FastSaxParser::FastSaxParser()
+{
+ mxDocumentLocator.set( new FastLocatorImpl( this ) );
+ maUtf8Buffer.realloc( mnUtf8BufferSize );
}
// --------------------------------------------------------------------
-void FastSaxParser::popContext()
+FastSaxParser::~FastSaxParser()
{
- Entity& rEntity = getEntity();
- assert(!rEntity.maContextStack.empty()); // pop without push?
- if( !rEntity.maContextStack.empty() )
- rEntity.maContextStack.pop();
- if( !rEntity.maNamespaceCount.empty() )
- rEntity.maNamespaceCount.pop();
+ if( mxDocumentLocator.is() )
+ mxDocumentLocator->dispose();
}
// --------------------------------------------------------------------
@@ -727,20 +776,16 @@ struct AttributeData
void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
{
- Reference< XFastContextHandler > xParentContext;
Entity& rEntity = getEntity();
- if( !rEntity.maContextStack.empty() )
+ if( rEntity.maNamespaceCount.empty() )
{
- xParentContext = rEntity.maContextStack.top()->mxContext;
- if( !xParentContext.is() )
- {
- // we ignore current elements, so no processing needed
- pushContext();
- return;
- }
+ rEntity.maNamespaceCount.push(0);
+ DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
+ }
+ else
+ {
+ rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
}
-
- pushContext();
rEntity.mxAttributes->clear();
@@ -749,6 +794,9 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
sal_Int32 nNameLen, nPrefixLen;
const XML_Char *pName;
const XML_Char *pPrefix;
+ OUString aNamespace;
+ if (!rEntity.maNamespaceStack.empty())
+ aNamespace = rEntity.maNamespaceStack.top();
try
{
@@ -783,7 +831,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
{
// namespace of the element found
- rEntity.maContextStack.top()->maNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
+ aNamespace = OUString( awAttributes[i+1], strlen( awAttributes[i+1] ), RTL_TEXTENCODING_UTF8 );
}
else
{
@@ -819,48 +867,18 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
if( nPrefixLen > 0 )
nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
- else if( !rEntity.maContextStack.top()->maNamespace.isEmpty() )
- nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen );
+ else if( !aNamespace.isEmpty() )
+ nElementToken = GetTokenWithNamespaceURL( aNamespace, pName, nNameLen );
else
nElementToken = GetToken( pName );
- rEntity.maContextStack.top()->mnElementToken = nElementToken;
- Reference< XFastAttributeList > xAttr( rEntity.mxAttributes.get() );
- Reference< XFastContextHandler > xContext;
if( nElementToken == FastToken::DONTKNOW )
- {
if( nPrefixLen > 0 )
- rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
-
- const OUString aNamespace( rEntity.maContextStack.top()->maNamespace );
- const OUString aElementName( pName, nNameLen, RTL_TEXTENCODING_UTF8 );
- rEntity.maContextStack.top()->maElementName = aElementName;
-
- if( xParentContext.is() )
- xContext = xParentContext->createUnknownChildContext( aNamespace, aElementName, xAttr );
- else if( rEntity.mxDocumentHandler.is() )
- xContext = rEntity.mxDocumentHandler->createUnknownChildContext( aNamespace, aElementName, xAttr );
+ aNamespace = GetNamespaceURL( pPrefix, nPrefixLen );
- if( xContext.is() )
- {
- rEntity.maContextStack.top()->mxContext = xContext;
- xContext->startUnknownElement( aNamespace, aElementName, xAttr );
- }
- }
- else
- {
- if( xParentContext.is() )
- xContext = xParentContext->createFastChildContext( nElementToken, xAttr );
- else if( rEntity.mxDocumentHandler.is() )
- xContext = rEntity.mxDocumentHandler->createFastChildContext( nElementToken, xAttr );
-
-
- if( xContext.is() )
- {
- rEntity.maContextStack.top()->mxContext = xContext;
- xContext->startFastElement( nElementToken, xAttr );
- }
- }
+ rEntity.maNamespaceStack.push(aNamespace);
+ rEntity.startElement( nElementToken, aNamespace,
+ OUString(pName, nNameLen, RTL_TEXTENCODING_UTF8), rEntity.mxAttributes.get() );
}
catch (const Exception& e)
{
@@ -871,41 +889,21 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
{
Entity& rEntity = getEntity();
- assert(!rEntity.maContextStack.empty()); // no context?
- if( !rEntity.maContextStack.empty() )
- {
- SaxContextImplPtr pContext = rEntity.maContextStack.top();
- const Reference< XFastContextHandler >& xContext( pContext->mxContext );
- if( xContext.is() ) try
- {
- sal_Int32 nElementToken = pContext->mnElementToken;
- if( nElementToken != FastToken::DONTKNOW )
- xContext->endFastElement( nElementToken );
- else
- xContext->endUnknownElement( pContext->maNamespace, pContext->maElementName );
- }
- catch (const Exception& e)
- {
- rEntity.maSavedException <<= e;
- }
+ assert( !rEntity.maNamespaceCount.empty() );
+ if( !rEntity.maNamespaceCount.empty() )
+ rEntity.maNamespaceCount.pop();
- popContext();
- }
+ assert( !rEntity.maNamespaceStack.empty() );
+ if( !rEntity.maNamespaceStack.empty() )
+ rEntity.maNamespaceStack.pop();
+
+ rEntity.endElement();
}
void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
{
- Entity& rEntity = getEntity();
- const Reference< XFastContextHandler >& xContext( rEntity.maContextStack.top()->mxContext );
- if( xContext.is() ) try
- {
- xContext->characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
- }
- catch (const Exception& e)
- {
- rEntity.maSavedException <<= e;
- }
+ getEntity().characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
}
void FastSaxParser::callbackEntityDecl(
diff --git a/sax/source/fastparser/fastparser.hxx b/sax/source/fastparser/fastparser.hxx
index aa71fb0ad4d9..51086965a8b4 100644
--- a/sax/source/fastparser/fastparser.hxx
+++ b/sax/source/fastparser/fastparser.hxx
@@ -22,12 +22,14 @@
#include <vector>
#include <stack>
-#include <boost/unordered_map.hpp>
+#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/unordered_map.hpp>
#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>
@@ -43,9 +45,7 @@ namespace sax_fastparser {
class FastLocatorImpl;
struct NamespaceDefine;
-struct SaxContextImpl;
-typedef ::boost::shared_ptr< SaxContextImpl > SaxContextImplPtr;
typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
typedef ::boost::unordered_map< OUString, sal_Int32,
@@ -53,6 +53,17 @@ typedef ::boost::unordered_map< OUString, sal_Int32,
// --------------------------------------------------------------------
+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;
@@ -79,13 +90,21 @@ struct Entity : public ParserData
// therefore the exception must be saved somewhere.
::com::sun::star::uno::Any maSavedException;
- ::std::stack< SaxContextImplPtr > maContextStack;
+ ::std::stack< OUString > maNamespaceStack;
+ /* 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;
explicit Entity( const ParserData& rData );
~Entity();
+ void startElement( sal_Int32 nElementToken, const OUString& aNamespace,
+ const OUString& aElementName, FastAttributeList *pAttributes );
+ void characters( const OUString& sChars );
+ void endElement();
};
// --------------------------------------------------------------------