Make QDom/QXmlSimpleReader reentrant.
I moved the evil static bool to QXmlSimpleReaderPrivate, and used it from QDom, when the reader instance is a QXmlSimpleReader (if it's not, nothing happens, like before). Task-number: QTBUG-40015 Change-Id: I54ba89db334d7b086379c4a6840cf0de23f77027 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
e26fa6d206
commit
aabe80ae28
|
|
@ -54,6 +54,7 @@
|
|||
#include <qtextcodec.h>
|
||||
#include <qtextstream.h>
|
||||
#include <qxml.h>
|
||||
#include "private/qxml_p.h"
|
||||
#include <qvariant.h>
|
||||
#include <qmap.h>
|
||||
#include <qshareddata.h>
|
||||
|
|
@ -502,7 +503,7 @@ public:
|
|||
~QDomDocumentPrivate();
|
||||
|
||||
bool setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
bool setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
bool setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader, QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
|
||||
// Attributes
|
||||
QDomDocumentTypePrivate* doctype() { return type.data(); }
|
||||
|
|
@ -573,7 +574,7 @@ public:
|
|||
class QDomHandler : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
QDomHandler(QDomDocumentPrivate* d, bool namespaceProcessing);
|
||||
QDomHandler(QDomDocumentPrivate* d, QXmlSimpleReader *reader, bool namespaceProcessing);
|
||||
~QDomHandler();
|
||||
|
||||
// content handler
|
||||
|
|
@ -615,6 +616,7 @@ private:
|
|||
bool cdata;
|
||||
bool nsProcessing;
|
||||
QXmlLocator *locator;
|
||||
QXmlSimpleReader *reader;
|
||||
};
|
||||
|
||||
/**************************************************************
|
||||
|
|
@ -6208,10 +6210,10 @@ bool QDomDocumentPrivate::setContent(QXmlInputSource *source, bool namespaceProc
|
|||
{
|
||||
QXmlSimpleReader reader;
|
||||
initializeReader(reader, namespaceProcessing);
|
||||
return setContent(source, &reader, errorMsg, errorLine, errorColumn);
|
||||
return setContent(source, &reader, &reader, errorMsg, errorLine, errorColumn);
|
||||
}
|
||||
|
||||
bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn)
|
||||
bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader, QString *errorMsg, int *errorLine, int *errorColumn)
|
||||
{
|
||||
clear();
|
||||
impl = new QDomImplementationPrivate;
|
||||
|
|
@ -6221,7 +6223,7 @@ bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader
|
|||
bool namespaceProcessing = reader->feature(QLatin1String("http://xml.org/sax/features/namespaces"))
|
||||
&& !reader->feature(QLatin1String("http://xml.org/sax/features/namespace-prefixes"));
|
||||
|
||||
QDomHandler hnd(this, namespaceProcessing);
|
||||
QDomHandler hnd(this, simpleReader, namespaceProcessing);
|
||||
reader->setContentHandler(&hnd);
|
||||
reader->setErrorHandler(&hnd);
|
||||
reader->setLexicalHandler(&hnd);
|
||||
|
|
@ -6758,7 +6760,7 @@ bool QDomDocument::setContent(QXmlInputSource *source, bool namespaceProcessing,
|
|||
impl = new QDomDocumentPrivate();
|
||||
QXmlSimpleReader reader;
|
||||
initializeReader(reader, namespaceProcessing);
|
||||
return IMPL->setContent(source, &reader, errorMsg, errorLine, errorColumn);
|
||||
return IMPL->setContent(source, &reader, &reader, errorMsg, errorLine, errorColumn);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -6820,7 +6822,7 @@ bool QDomDocument::setContent(QXmlInputSource *source, QXmlReader *reader, QStri
|
|||
{
|
||||
if (!impl)
|
||||
impl = new QDomDocumentPrivate();
|
||||
return IMPL->setContent(source, reader, errorMsg, errorLine, errorColumn);
|
||||
return IMPL->setContent(source, reader, 0, errorMsg, errorLine, errorColumn);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -7360,9 +7362,9 @@ QDomComment QDomNode::toComment() const
|
|||
*
|
||||
**************************************************************/
|
||||
|
||||
QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, bool namespaceProcessing)
|
||||
QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, QXmlSimpleReader* areader, bool namespaceProcessing)
|
||||
: errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false),
|
||||
nsProcessing(namespaceProcessing), locator(0)
|
||||
nsProcessing(namespaceProcessing), locator(0), reader(areader)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -7466,11 +7468,10 @@ bool QDomHandler::processingInstruction(const QString& target, const QString& da
|
|||
return false;
|
||||
}
|
||||
|
||||
extern bool qt_xml_skipped_entity_in_content;
|
||||
bool QDomHandler::skippedEntity(const QString& name)
|
||||
{
|
||||
// we can only handle inserting entity references into content
|
||||
if (!qt_xml_skipped_entity_in_content)
|
||||
if (reader && !reader->d_ptr->skipped_entity_in_content)
|
||||
return true;
|
||||
|
||||
QDomNodePrivate *n = doc->createEntityReference(name);
|
||||
|
|
|
|||
|
|
@ -100,10 +100,6 @@ static const signed char cltDq = 12; // "
|
|||
static const signed char cltSq = 13; // '
|
||||
static const signed char cltUnknown = 14;
|
||||
|
||||
// Hack for letting QDom know where the skipped entity occurred
|
||||
// ### the use of this variable means the code isn't reentrant.
|
||||
bool qt_xml_skipped_entity_in_content;
|
||||
|
||||
// character lookup table
|
||||
static const signed char charLookupTable[256]={
|
||||
cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
|
||||
|
|
@ -3230,7 +3226,7 @@ bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
qt_xml_skipped_entity_in_content = false;
|
||||
d->skipped_entity_in_content = false;
|
||||
return d->parseBeginOrContinue(0, incremental);
|
||||
}
|
||||
|
||||
|
|
@ -7594,13 +7590,13 @@ bool QXmlSimpleReaderPrivate::processReference()
|
|||
}
|
||||
|
||||
if (contentHnd) {
|
||||
qt_xml_skipped_entity_in_content = parseReference_context == InContent;
|
||||
skipped_entity_in_content = parseReference_context == InContent;
|
||||
if (!contentHnd->skippedEntity(reference)) {
|
||||
qt_xml_skipped_entity_in_content = false;
|
||||
skipped_entity_in_content = false;
|
||||
reportParseError(contentHnd->errorString());
|
||||
return false; // error
|
||||
}
|
||||
qt_xml_skipped_entity_in_content = false;
|
||||
skipped_entity_in_content = false;
|
||||
}
|
||||
}
|
||||
} else if ((*itExtern).notation.isNull()) {
|
||||
|
|
@ -7630,13 +7626,13 @@ bool QXmlSimpleReaderPrivate::processReference()
|
|||
}
|
||||
}
|
||||
if (skipIt && contentHnd) {
|
||||
qt_xml_skipped_entity_in_content = true;
|
||||
skipped_entity_in_content = true;
|
||||
if (!contentHnd->skippedEntity(reference)) {
|
||||
qt_xml_skipped_entity_in_content = false;
|
||||
skipped_entity_in_content = false;
|
||||
reportParseError(contentHnd->errorString());
|
||||
return false; // error
|
||||
}
|
||||
qt_xml_skipped_entity_in_content = false;
|
||||
skipped_entity_in_content = false;
|
||||
}
|
||||
parseReference_charDataRead = false;
|
||||
} break;
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ private:
|
|||
QScopedPointer<QXmlSimpleReaderPrivate> d_ptr;
|
||||
|
||||
friend class QXmlSimpleReaderLocator;
|
||||
friend class QDomHandler;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ private:
|
|||
// used in QXmlSimpleReader::parseContent() to decide whether character
|
||||
// data was read
|
||||
bool contentCharDataRead;
|
||||
// Hack for letting QDom know where the skipped entity occurred
|
||||
bool skipped_entity_in_content;
|
||||
|
||||
// helper classes
|
||||
QScopedPointer<QXmlLocator> locator;
|
||||
|
|
|
|||
Loading…
Reference in New Issue