summaryrefslogtreecommitdiff
path: root/sax
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2014-11-20 13:42:16 +0100
committerLuboš Luňák <l.lunak@collabora.com>2014-11-20 18:43:44 +0100
commit0df9ac47dfa287249e77bb8f6a5555324a94a48d (patch)
tree5b1a2eded3f710821fcb9f2ef5c3c5a9e6e0b141 /sax
parent06d90253c2890d437063aae263a1f9a5f9280ad8 (diff)
make FastSaxParser provide the whole content in one characters() call
SAX interface is not required to provide the whole node content in one characters() call (e.g. if there's an entity that needs decoding). However it's easier to consumers to assume this (e.g. writerfilter's DomainMapper::lcl_utext() handles datecontrol that way), and expat apparently never used this. However this can happen with libxml2, so ensure such consumers still work. Change-Id: Ib564f372fbea8451f84553a6d49a07d091a950e9
Diffstat (limited to 'sax')
-rw-r--r--sax/source/fastparser/fastparser.cxx19
1 files changed, 18 insertions, 1 deletions
diff --git a/sax/source/fastparser/fastparser.cxx b/sax/source/fastparser/fastparser.cxx
index 38a4bbb750b4..e1d22d215f78 100644
--- a/sax/source/fastparser/fastparser.cxx
+++ b/sax/source/fastparser/fastparser.cxx
@@ -237,6 +237,7 @@ public:
private:
bool consume(EventList *);
void deleteUsedEvents();
+ void sendPendingCharacters();
sal_Int32 GetToken( const xmlChar* pName, sal_Int32 nameLen );
sal_Int32 GetTokenWithPrefix( const xmlChar* pPrefix, int prefixLen, const xmlChar* pName, int nameLen ) throw (::com::sun::star::xml::sax::SAXException);
@@ -257,6 +258,7 @@ private:
Entity *mpTop; /// std::stack::top() is amazingly slow => cache this.
::std::stack< Entity > maEntities; /// Entity stack for each call of parseStream().
+ OUString pendingCharacters; /// Data from characters() callback that needs to be sent.
};
} // namespace sax_fastparser
@@ -1048,6 +1050,8 @@ void FastSaxParserImpl::parse()
void FastSaxParserImpl::callbackStartElement(const xmlChar *localName , const xmlChar* prefix, const xmlChar* URI,
int numNamespaces, const xmlChar** namespaces, int numAttributes, int /*defaultedAttributes*/, const xmlChar **attributes)
{
+ if( !pendingCharacters.isEmpty())
+ sendPendingCharacters();
Entity& rEntity = getEntity();
if( rEntity.maNamespaceCount.empty() )
{
@@ -1154,6 +1158,8 @@ void FastSaxParserImpl::callbackStartElement(const xmlChar *localName , const xm
void FastSaxParserImpl::callbackEndElement( const xmlChar*, const xmlChar*, const xmlChar* )
{
+ if( !pendingCharacters.isEmpty())
+ sendPendingCharacters();
Entity& rEntity = getEntity();
assert( !rEntity.maNamespaceCount.empty() );
if( !rEntity.maNamespaceCount.empty() )
@@ -1172,9 +1178,20 @@ void FastSaxParserImpl::callbackEndElement( const xmlChar*, const xmlChar*, cons
void FastSaxParserImpl::callbackCharacters( const xmlChar* s, int nLen )
{
+ // SAX interface allows that the characters callback splits content of one XML node
+ // (e.g. because there's an entity that needs decoding), however for consumers it's
+ // simpler FastSaxParser's character callback provides the whole string at once,
+ // so merge data from possible multiple calls and send them at once (before the element
+ // ends or another one starts).
+ pendingCharacters += OUString( XML_CAST( s ), nLen, RTL_TEXTENCODING_UTF8 );
+}
+
+void FastSaxParserImpl::sendPendingCharacters()
+{
Entity& rEntity = getEntity();
Event& rEvent = rEntity.getEvent( CHARACTERS );
- rEvent.msChars = OUString( XML_CAST( s ), nLen, RTL_TEXTENCODING_UTF8);
+ rEvent.msChars = pendingCharacters;
+ pendingCharacters.clear();
if (rEntity.mbEnableThreads)
produce();
else