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
This commit is contained in:
@@ -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,6 +189,89 @@ Entity::~Entity()
|
||||
{
|
||||
}
|
||||
|
||||
void Entity::startElement( sal_Int32 nElementToken, const OUString& aNamespace,
|
||||
const OUString& aElementName, FastAttributeList *pAttributes )
|
||||
{
|
||||
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) );
|
||||
|
||||
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 Entity::endElement()
|
||||
{
|
||||
const SaxContext& aContext = maContextStack.top();
|
||||
const Reference< XFastContextHandler >& xContext( aContext.mxContext );
|
||||
if( xContext.is() ) try
|
||||
{
|
||||
sal_Int32 nElementToken = aContext.mnElementToken;
|
||||
if( nElementToken != FastToken::DONTKNOW )
|
||||
xContext->endFastElement( nElementToken );
|
||||
else
|
||||
xContext->endUnknownElement( aContext.maNamespace.get(), aContext.maElementName.get() );
|
||||
}
|
||||
catch (const Exception& e)
|
||||
{
|
||||
maSavedException <<= e;
|
||||
}
|
||||
maContextStack.pop();
|
||||
}
|
||||
// --------------------------------------------------------------------
|
||||
// FastSaxParser implementation
|
||||
// --------------------------------------------------------------------
|
||||
@@ -213,36 +292,6 @@ FastSaxParser::~FastSaxParser()
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void FastSaxParser::pushContext()
|
||||
{
|
||||
Entity& rEntity = getEntity();
|
||||
if( rEntity.maContextStack.empty() )
|
||||
{
|
||||
rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl ) );
|
||||
rEntity.maNamespaceCount.push(0);
|
||||
DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
|
||||
}
|
||||
else
|
||||
{
|
||||
rEntity.maContextStack.push( SaxContextImplPtr( new SaxContextImpl( rEntity.maContextStack.top() ) ) );
|
||||
rEntity.maNamespaceCount.push( rEntity.maNamespaceCount.top() );
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void FastSaxParser::popContext()
|
||||
{
|
||||
Entity& rEntity = getEntity();
|
||||
assert(!rEntity.maContextStack.empty()); // pop without push?
|
||||
if( !rEntity.maContextStack.empty() )
|
||||
rEntity.maContextStack.pop();
|
||||
if( !rEntity.maNamespaceCount.empty() )
|
||||
rEntity.maNamespaceCount.pop();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void FastSaxParser::DefineNamespace( const OString& rPrefix, const sal_Char* pNamespaceURL )
|
||||
{
|
||||
Entity& rEntity = getEntity();
|
||||
@@ -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() )
|
||||
rEntity.maNamespaceCount.push(0);
|
||||
DefineNamespace( OString("xml"), "http://www.w3.org/XML/1998/namespace");
|
||||
}
|
||||
else
|
||||
{
|
||||
// we ignore current elements, so no processing needed
|
||||
pushContext();
|
||||
return;
|
||||
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 );
|
||||
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.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(
|
||||
|
@@ -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();
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user