Kaydet (Commit) 03d76d03 authored tarafından Matúš Kukan's avatar Matúš Kukan

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
üst bd4c869b
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <rtl/ustrbuf.hxx> #include <rtl/ustrbuf.hxx>
#include <com/sun/star/lang/DisposedException.hpp> #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/SAXParseException.hpp>
#include <com/sun/star/xml/sax/FastToken.hpp> #include <com/sun/star/xml/sax/FastToken.hpp>
...@@ -41,18 +40,15 @@ using namespace ::com::sun::star::io; ...@@ -41,18 +40,15 @@ using namespace ::com::sun::star::io;
namespace sax_fastparser { namespace sax_fastparser {
// -------------------------------------------------------------------- SaxContext::SaxContext( sal_Int32 nElementToken, const OUString& aNamespace, const OUString& aElementName ):
mnElementToken(nElementToken)
struct SaxContextImpl
{ {
Reference< XFastContextHandler > mxContext; if (nElementToken == FastToken::DONTKNOW)
sal_Int32 mnElementToken; {
OUString maNamespace; maNamespace = aNamespace;
OUString maElementName; maElementName = aElementName;
}
SaxContextImpl() { mnElementToken = 0; } }
SaxContextImpl( const SaxContextImplPtr& p ) { mnElementToken = p->mnElementToken; maNamespace = p->maNamespace; }
};
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -193,52 +189,105 @@ Entity::~Entity() ...@@ -193,52 +189,105 @@ Entity::~Entity()
{ {
} }
// -------------------------------------------------------------------- void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace,
// FastSaxParser implementation const OUString& aElementName, FastAttributeList *pAttributes )
// --------------------------------------------------------------------
FastSaxParser::FastSaxParser()
{ {
mxDocumentLocator.set( new FastLocatorImpl( this ) ); Reference< XFastContextHandler > xParentContext;
maUtf8Buffer.realloc( mnUtf8BufferSize ); 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() try
{ {
if( mxDocumentLocator.is() ) Reference< XFastAttributeList > xAttr( pAttributes );
mxDocumentLocator->dispose(); 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(); const SaxContext& aContext = maContextStack.top();
if( rEntity.maContextStack.empty() ) const Reference< XFastContextHandler >& xContext( aContext.mxContext );
if( xContext.is() ) try
{ {
rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) ); sal_Int32 nElementToken = aContext.mnElementToken;
rEntity.maNamespaceCount.push(0); if( nElementToken != FastToken::DONTKNOW )
DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace"); 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() ) ) ); maSavedException <<= e;
rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
} }
maContextStack.pop();
}
// --------------------------------------------------------------------
// FastSaxParser implementation
// --------------------------------------------------------------------
FastSaxParser::FastSaxParser()
{
mxDocumentLocator.set( new FastLocatorImpl( this ) );
maUtf8Buffer.realloc( mnUtf8BufferSize );
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void FastSaxParser::popContext() FastSaxParser::~FastSaxParser()
{ {
Entity& rEntity = getEntity(); if( mxDocumentLocator.is() )
assert(!rEntity.maContextStack.empty()); // pop without push? mxDocumentLocator->dispose();
if( !rEntity.maContextStack.empty() )
rEntity.maContextStack.pop();
if( !rEntity.maNamespaceCount.empty() )
rEntity.maNamespaceCount.pop();
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
...@@ -727,20 +776,16 @@ struct AttributeData ...@@ -727,20 +776,16 @@ struct AttributeData
void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes ) void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char** awAttributes )
{ {
Reference< XFastContextHandler > xParentContext;
Entity& rEntity = getEntity(); Entity& rEntity = getEntity();
if( !rEntity.maContextStack.empty() ) if( rEntity.maNamespaceCount.empty() )
{ {
xParentContext = rEntity.maContextStack.top()->mxContext; rEntity.maNamespaceCount.push(0);
if( !xParentContext.is() ) DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
{ }
// we ignore current elements, so no processing needed else
pushContext(); {
return; rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
}
} }
pushContext();
rEntity.mxAttributes->clear(); rEntity.mxAttributes->clear();
...@@ -749,6 +794,9 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char ...@@ -749,6 +794,9 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
sal_Int32 nNameLen, nPrefixLen; sal_Int32 nNameLen, nPrefixLen;
const XML_Char *pName; const XML_Char *pName;
const XML_Char *pPrefix; const XML_Char *pPrefix;
OUString aNamespace;
if (!rEntity.maNamespaceStack.empty())
aNamespace = rEntity.maNamespaceStack.top();
try try
{ {
...@@ -783,7 +831,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char ...@@ -783,7 +831,7 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) ) if( (nNameLen == 5) && (strcmp( pName, "xmlns" ) == 0) )
{ {
// namespace of the element found // 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 else
{ {
...@@ -819,48 +867,18 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char ...@@ -819,48 +867,18 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen ); splitName( pwName, pPrefix, nPrefixLen, pName, nNameLen );
if( nPrefixLen > 0 ) if( nPrefixLen > 0 )
nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen ); nElementToken = GetTokenWithPrefix( pPrefix, nPrefixLen, pName, nNameLen );
else if( !rEntity.maContextStack.top()->maNamespace.isEmpty() ) else if( !aNamespace.isEmpty() )
nElementToken = GetTokenWithNamespaceURL( rEntity.maContextStack.top()->maNamespace, pName, nNameLen ); nElementToken = GetTokenWithNamespaceURL( aNamespace, pName, nNameLen );
else else
nElementToken = GetToken( pName ); nElementToken = GetToken( pName );
rEntity.maContextStack.top()->mnElementToken = nElementToken;
Reference< XFastAttributeList > xAttr( rEntity.mxAttributes.get() );
Reference< XFastContextHandler > xContext;
if( nElementToken == FastToken::DONTKNOW ) if( nElementToken == FastToken::DONTKNOW )
{
if( nPrefixLen > 0 ) if( nPrefixLen > 0 )
rEntity.maContextStack.top()->maNamespace = GetNamespaceURL( pPrefix, nPrefixLen ); aNamespace = 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 );
if( xContext.is() ) rEntity.maNamespaceStack.push(aNamespace);
{ rEntity.startElement( nElementToken, aNamespace,
rEntity.maContextStack.top()->mxContext = xContext; OUString(pName, nNameLen, RTL_TEXTENCODING_UTF8), rEntity.mxAttributes.get() );
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 );
}
}
} }
catch (const Exception& e) catch (const Exception& e)
{ {
...@@ -871,41 +889,21 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char ...@@ -871,41 +889,21 @@ void FastSaxParser::callbackStartElement( const XML_Char* pwName, const XML_Char
void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* ) void FastSaxParser::callbackEndElement( SAL_UNUSED_PARAMETER const XML_Char* )
{ {
Entity& rEntity = getEntity(); Entity& rEntity = getEntity();
assert(!rEntity.maContextStack.empty()); // no context? assert( !rEntity.maNamespaceCount.empty() );
if( !rEntity.maContextStack.empty() ) if( !rEntity.maNamespaceCount.empty() )
{ rEntity.maNamespaceCount.pop();
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;
}
popContext(); assert( !rEntity.maNamespaceStack.empty() );
} if( !rEntity.maNamespaceStack.empty() )
rEntity.maNamespaceStack.pop();
rEntity.endElement();
} }
void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen ) void FastSaxParser::callbackCharacters( const XML_Char* s, int nLen )
{ {
Entity& rEntity = getEntity(); getEntity().characters( OUString( s, nLen, RTL_TEXTENCODING_UTF8 ) );
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;
}
} }
void FastSaxParser::callbackEntityDecl( void FastSaxParser::callbackEntityDecl(
......
...@@ -22,12 +22,14 @@ ...@@ -22,12 +22,14 @@
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <boost/unordered_map.hpp> #include <boost/optional.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <rtl/ref.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/XFastParser.hpp>
#include <com/sun/star/xml/sax/XFastTokenHandler.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 <com/sun/star/lang/XServiceInfo.hpp>
#include <cppuhelper/implbase2.hxx> #include <cppuhelper/implbase2.hxx>
...@@ -43,9 +45,7 @@ namespace sax_fastparser { ...@@ -43,9 +45,7 @@ namespace sax_fastparser {
class FastLocatorImpl; class FastLocatorImpl;
struct NamespaceDefine; struct NamespaceDefine;
struct SaxContextImpl;
typedef ::boost::shared_ptr< SaxContextImpl > SaxContextImplPtr;
typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef; typedef ::boost::shared_ptr< NamespaceDefine > NamespaceDefineRef;
typedef ::boost::unordered_map< OUString, sal_Int32, typedef ::boost::unordered_map< OUString, sal_Int32,
...@@ -53,6 +53,17 @@ 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 struct ParserData
{ {
::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler; ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastDocumentHandler > mxDocumentHandler;
...@@ -79,13 +90,21 @@ struct Entity : public ParserData ...@@ -79,13 +90,21 @@ struct Entity : public ParserData
// therefore the exception must be saved somewhere. // therefore the exception must be saved somewhere.
::com::sun::star::uno::Any maSavedException; ::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 // Determines which elements of maNamespaceDefines are valid in current context
::std::stack< sal_uInt32 > maNamespaceCount; ::std::stack< sal_uInt32 > maNamespaceCount;
::std::vector< NamespaceDefineRef > maNamespaceDefines; ::std::vector< NamespaceDefineRef > maNamespaceDefines;
explicit Entity( const ParserData& rData ); explicit Entity( const ParserData& rData );
~Entity(); ~Entity();
void startElement( sal_Int32 nElementToken, const OUString& aNamespace,
const OUString& aElementName, FastAttributeList *pAttributes );
void characters( const OUString& sChars );
void endElement();
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment