summaryrefslogtreecommitdiffstats
path: root/src/xmlpatterns/acceltree
diff options
context:
space:
mode:
authorTobias Koenig <tokoe@kde.org>2009-05-16 10:19:10 (GMT)
committerTobias Koenig <tokoe@kde.org>2009-05-16 10:19:10 (GMT)
commit135a028d9dc9a28a0a072665a7dc43b7e9e187be (patch)
treed259e1d265589d10a541899d4982ab4e656900eb /src/xmlpatterns/acceltree
parent210bd7b6033e41aad61fe131002dc5e496d7427a (diff)
downloadQt-135a028d9dc9a28a0a072665a7dc43b7e9e187be.zip
Qt-135a028d9dc9a28a0a072665a7dc43b7e9e187be.tar.gz
Qt-135a028d9dc9a28a0a072665a7dc43b7e9e187be.tar.bz2
Add W3C XML Schema validation support
This was done by Tobias Koenig, as part of an internship at Trolltech/Qt Software, started at Wed Oct 1 18:32:43 2008 +0200, and the last commit being part of this commit dating Tue Feb 24 11:03:36 2009 +0100. This is work consisting of about 650 commits squashed into one, where the first commit was 61b280386c1905a15690fdd917dcbc8eb09b6283, in the repository before Qt's history cut.
Diffstat (limited to 'src/xmlpatterns/acceltree')
-rw-r--r--src/xmlpatterns/acceltree/qacceltree.cpp43
-rw-r--r--src/xmlpatterns/acceltree/qacceltree_p.h17
-rw-r--r--src/xmlpatterns/acceltree/qacceltreebuilder.cpp31
-rw-r--r--src/xmlpatterns/acceltree/qacceltreebuilder_p.h19
-rw-r--r--src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp60
-rw-r--r--src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h27
6 files changed, 156 insertions, 41 deletions
diff --git a/src/xmlpatterns/acceltree/qacceltree.cpp b/src/xmlpatterns/acceltree/qacceltree.cpp
index 60e6e27..061021a 100644
--- a/src/xmlpatterns/acceltree/qacceltree.cpp
+++ b/src/xmlpatterns/acceltree/qacceltree.cpp
@@ -42,6 +42,7 @@
#include <QStack>
#include "qabstractxmlreceiver.h"
+#include "qabstractxmlnodemodel_p.h"
#include "qacceliterators_p.h"
#include "qacceltree_p.h"
#include "qatomicstring_p.h"
@@ -55,6 +56,37 @@ QT_BEGIN_NAMESPACE
using namespace QPatternist;
+namespace QPatternist {
+
+ class AccelTreePrivate : public QAbstractXmlNodeModelPrivate
+ {
+ public:
+ AccelTreePrivate(AccelTree *accelTree)
+ : m_accelTree(accelTree)
+ {
+ }
+
+ virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const
+ {
+ return m_accelTree->sourceLocation(index);
+ }
+
+ private:
+ AccelTree *m_accelTree;
+ };
+}
+
+AccelTree::AccelTree(const QUrl &docURI, const QUrl &bURI)
+ : QAbstractXmlNodeModel(new AccelTreePrivate(this))
+ , m_documentURI(docURI)
+ , m_baseURI(bURI)
+{
+ /* Pre-allocate at least a little bit. */
+ // TODO. Do it according to what an average 4 KB doc contains.
+ basicData.reserve(100);
+ data.reserve(30);
+}
+
void AccelTree::printStats(const NamePool::Ptr &np) const
{
Q_ASSERT(np);
@@ -674,6 +706,17 @@ void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node,
}
+QSourceLocation AccelTree::sourceLocation(const QXmlNodeModelIndex &index) const
+{
+ const PreNumber key = toPreNumber(index);
+ if (sourcePositions.contains(key)) {
+ const QPair<qint64, qint64> position = sourcePositions.value(key);
+ return QSourceLocation(m_documentURI, position.first, position.second);
+ } else {
+ return QSourceLocation();
+ }
+}
+
void AccelTree::copyChildren(const QXmlNodeModelIndex &node,
QAbstractXmlReceiver *const receiver,
const NodeCopySettings &settings) const
diff --git a/src/xmlpatterns/acceltree/qacceltree_p.h b/src/xmlpatterns/acceltree/qacceltree_p.h
index 10320ba..4c0d844 100644
--- a/src/xmlpatterns/acceltree/qacceltree_p.h
+++ b/src/xmlpatterns/acceltree/qacceltree_p.h
@@ -91,6 +91,7 @@ namespace QPatternist
*/
class AccelTree : public QAbstractXmlNodeModel
{
+ friend class AccelTreePrivate;
public:
using QAbstractXmlNodeModel::createIndex;
@@ -99,15 +100,7 @@ namespace QPatternist
typedef PreNumber PostNumber;
typedef qint8 Depth;
- inline AccelTree(const QUrl &docURI,
- const QUrl &bURI) : m_documentURI(docURI),
- m_baseURI(bURI)
- {
- /* Pre-allocate at least a little bit. */
- // TODO. Do it according to what an average 4 KB doc contains.
- basicData.reserve(100);
- data.reserve(30);
- }
+ AccelTree(const QUrl &docURI, const QUrl &bURI);
/**
* @short Houses data for a node, and that all node kinds have.
@@ -280,6 +273,7 @@ namespace QPatternist
QHash<PreNumber, QString> data;
QVector<BasicNodeData> basicData;
+ QHash<PreNumber, QPair<qint64, qint64> > sourcePositions;
inline QUrl documentUri() const
{
@@ -381,6 +375,11 @@ namespace QPatternist
private:
/**
+ * Returns the source location for the object with the given @p index.
+ */
+ QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const;
+
+ /**
* Copies the children of @p node to @p receiver.
*/
inline void copyChildren(const QXmlNodeModelIndex &node,
diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp
index 5b16cc3..ddc118c 100644
--- a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp
+++ b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp
@@ -49,15 +49,17 @@ template <bool FromDocument>
AccelTreeBuilder<FromDocument>::AccelTreeBuilder(const QUrl &docURI,
const QUrl &baseURI,
const NamePool::Ptr &np,
- ReportContext *const context) : m_preNumber(-1)
- , m_isPreviousAtomic(false)
- , m_hasCharacters(false)
- , m_isCharactersCompressed(false)
- , m_namePool(np)
- , m_document(new AccelTree(docURI, baseURI))
- , m_skippedDocumentNodes(0)
- , m_documentURI(docURI)
- , m_context(context)
+ ReportContext *const context,
+ Features features) : m_preNumber(-1)
+ , m_isPreviousAtomic(false)
+ , m_hasCharacters(false)
+ , m_isCharactersCompressed(false)
+ , m_namePool(np)
+ , m_document(new AccelTree(docURI, baseURI))
+ , m_skippedDocumentNodes(0)
+ , m_documentURI(docURI)
+ , m_context(context)
+ , m_features(features)
{
Q_ASSERT(m_namePool);
@@ -126,9 +128,18 @@ void AccelTreeBuilder<FromDocument>::item(const Item &it)
template <bool FromDocument>
void AccelTreeBuilder<FromDocument>::startElement(const QXmlName &name)
{
+ startElement(name, 1, 1);
+}
+
+template <bool FromDocument>
+void AccelTreeBuilder<FromDocument>::startElement(const QXmlName &name, qint64 line, qint64 column)
+{
startStructure();
- m_document->basicData.append(AccelTree::BasicNodeData(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name));
+ AccelTree::BasicNodeData data(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name);
+ m_document->basicData.append(data);
+ if (m_features & SourceLocationsFeature)
+ m_document->sourcePositions.insert(m_document->maximumPreNumber(), qMakePair(line, column));
++m_preNumber;
m_ancestors.push(m_preNumber);
diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h
index 653eb85..91e8d68 100644
--- a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h
+++ b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h
@@ -90,15 +90,27 @@ namespace QPatternist
typedef QExplicitlySharedDataPointer<AccelTreeBuilder> Ptr;
/**
+ * Describes the memory relevant features the builder shall support.
+ */
+ enum Feature
+ {
+ NoneFeature, ///< No special features are enabled.
+ SourceLocationsFeature = 1 ///< The accel tree builder will store source locations for each start element.
+ };
+ Q_DECLARE_FLAGS(Features, Feature)
+
+ /**
* @param context may be @c null.
*/
AccelTreeBuilder(const QUrl &docURI,
const QUrl &baseURI,
const NamePool::Ptr &np,
- ReportContext *const context);
+ ReportContext *const context,
+ Features features = NoneFeature);
virtual void startDocument();
virtual void endDocument();
virtual void startElement(const QXmlName &name);
+ void startElement(const QXmlName &name, qint64 line, qint64 column);
virtual void endElement();
virtual void attribute(const QXmlName &name, const QStringRef &value);
virtual void characters(const QStringRef &ch);
@@ -175,8 +187,13 @@ namespace QPatternist
* a member.
*/
ReportContext *const m_context;
+
+ Features m_features;
};
+ Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder<true>::Features)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder<false>::Features)
+
#include "qacceltreebuilder.cpp"
}
diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
index 4a5c219..7c3d2c0 100644
--- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
+++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp
@@ -46,7 +46,6 @@
#include <QtNetwork/QNetworkRequest>
-#include "qacceltreebuilder_p.h"
#include "qatomicstring_p.h"
#include "qautoptr_p.h"
#include "qcommonsequencetypes_p.h"
@@ -57,14 +56,12 @@ QT_BEGIN_NAMESPACE
using namespace QPatternist;
-static inline uint qHash(const QUrl &uri)
-{
- return qHash(uri.toString());
-}
-
AccelTreeResourceLoader::AccelTreeResourceLoader(const NamePool::Ptr &np,
- const NetworkAccessDelegator::Ptr &manager) : m_namePool(np)
- , m_networkAccessDelegator(manager)
+ const NetworkAccessDelegator::Ptr &manager,
+ AccelTreeBuilder<true>::Features features)
+ : m_namePool(np)
+ , m_networkAccessDelegator(manager)
+ , m_features(features)
{
Q_ASSERT(m_namePool);
Q_ASSERT(m_networkAccessDelegator);
@@ -74,7 +71,7 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri,
const ReportContext::Ptr &context)
{
Q_ASSERT(uri.isValid());
- AccelTreeBuilder<true> builder(uri, uri, m_namePool, context.data());
+ AccelTreeBuilder<true> builder(uri, uri, m_namePool, context.data(), m_features);
const AutoPtr<QNetworkReply> reply(load(uri, m_networkAccessDelegator, context));
@@ -88,18 +85,35 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri,
return success;
}
+bool AccelTreeResourceLoader::retrieveDocument(QIODevice *source, const QUrl &documentUri, const ReportContext::Ptr &context)
+{
+ Q_ASSERT(source);
+ Q_ASSERT(source->isReadable());
+ Q_ASSERT(documentUri.isValid());
+
+ AccelTreeBuilder<true> builder(documentUri, documentUri, m_namePool, context.data(), m_features);
+
+ bool success = false;
+ success = streamToReceiver(source, &builder, m_namePool, context, documentUri);
+
+ m_loadedDocuments.insert(documentUri, builder.builtDocument());
+
+ return success;
+}
+
QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
const NetworkAccessDelegator::Ptr &networkDelegator,
- const ReportContext::Ptr &context)
+ const ReportContext::Ptr &context, ErrorHandling errorHandling)
{
return load(uri,
networkDelegator->managerFor(uri),
- context);
+ context, errorHandling);
}
QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
QNetworkAccessManager *const networkManager,
- const ReportContext::Ptr &context)
+ const ReportContext::Ptr &context, ErrorHandling errorHandling)
+
{
Q_ASSERT(networkManager);
Q_ASSERT(uri.isValid());
@@ -120,7 +134,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
const QSourceLocation location(uri);
- if(context)
+ if(context && (errorHandling == FailOnError))
context->error(errorMessage, ReportContext::FODC0002, location);
return 0;
@@ -130,7 +144,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri,
}
bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev,
- QAbstractXmlReceiver *const receiver,
+ AccelTreeBuilder<true> *const receiver,
const NamePool::Ptr &np,
const ReportContext::Ptr &context,
const QUrl &uri)
@@ -154,7 +168,7 @@ bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev,
{
/* Send the name. */
receiver->startElement(np->allocateQName(reader.namespaceUri().toString(), reader.name().toString(),
- reader.prefix().toString()));
+ reader.prefix().toString()), reader.lineNumber(), reader.columnNumber());
/* Send namespace declarations. */
const QXmlStreamNamespaceDeclarations &nss = reader.namespaceDeclarations();
@@ -263,6 +277,22 @@ Item AccelTreeResourceLoader::openDocument(const QUrl &uri,
}
}
+Item AccelTreeResourceLoader::openDocument(QIODevice *source, const QUrl &documentUri,
+ const ReportContext::Ptr &context)
+{
+ const AccelTree::Ptr doc(m_loadedDocuments.value(documentUri));
+
+ if(doc)
+ return doc->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */
+ else
+ {
+ if(retrieveDocument(source, documentUri, context))
+ return m_loadedDocuments.value(documentUri)->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */
+ else
+ return Item();
+ }
+}
+
SequenceType::Ptr AccelTreeResourceLoader::announceDocument(const QUrl &uri, const Usage)
{
// TODO deal with the usage thingy
diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h
index 863fd65..56f547a 100644
--- a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h
+++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h
@@ -52,12 +52,12 @@
#ifndef Patternist_AccelTreeResourceLoader_H
#define Patternist_AccelTreeResourceLoader_H
-#include <QtCore/QHash>
#include <QtCore/QEventLoop>
#include <QtNetwork/QNetworkReply>
#include "qabstractxmlreceiver.h"
#include "qacceltree_p.h"
+#include "qacceltreebuilder_p.h"
#include "qdeviceresourceloader_p.h"
#include "qnamepool_p.h"
#include "qnetworkaccessdelegator_p.h"
@@ -115,13 +115,25 @@ namespace QPatternist
{
public:
/**
+ * Describes the behaviour of the resource loader in case of an
+ * error.
+ */
+ enum ErrorHandling
+ {
+ FailOnError, ///< The resource loader will report the error via the report context.
+ ContinueOnError ///< The resource loader will report no error and return an empty QNetworkReply.
+ };
+
+ /**
* AccelTreeResourceLoader does not own @p context.
*/
AccelTreeResourceLoader(const NamePool::Ptr &np,
- const NetworkAccessDelegator::Ptr &networkDelegator);
+ const NetworkAccessDelegator::Ptr &networkDelegator, AccelTreeBuilder<true>::Features = AccelTreeBuilder<true>::NoneFeature);
virtual Item openDocument(const QUrl &uri,
const ReportContext::Ptr &context);
+ virtual Item openDocument(QIODevice *source, const QUrl &documentUri,
+ const ReportContext::Ptr &context);
virtual SequenceType::Ptr announceDocument(const QUrl &uri, const Usage usageHint);
virtual bool isDocumentAvailable(const QUrl &uri);
@@ -133,7 +145,6 @@ namespace QPatternist
const ReportContext::Ptr &context,
const SourceLocationReflection *const where);
-
/**
* @short Helper function that do NetworkAccessDelegator::get(), but
* does it blocked.
@@ -149,14 +160,14 @@ namespace QPatternist
*/
static QNetworkReply *load(const QUrl &uri,
QNetworkAccessManager *const networkManager,
- const ReportContext::Ptr &context);
+ const ReportContext::Ptr &context, ErrorHandling handling = FailOnError);
/**
* @overload
*/
static QNetworkReply *load(const QUrl &uri,
const NetworkAccessDelegator::Ptr &networkDelegator,
- const ReportContext::Ptr &context);
+ const ReportContext::Ptr &context, ErrorHandling handling = FailOnError);
/**
* @short Returns the URIs this AccelTreeResourceLoader has loaded
@@ -165,14 +176,17 @@ namespace QPatternist
virtual QSet<QUrl> deviceURIs() const;
virtual void clear(const QUrl &uri);
+
private:
static bool streamToReceiver(QIODevice *const dev,
- QAbstractXmlReceiver *const receiver,
+ AccelTreeBuilder<true> *const receiver,
const NamePool::Ptr &np,
const ReportContext::Ptr &context,
const QUrl &uri);
bool retrieveDocument(const QUrl &uri,
const ReportContext::Ptr &context);
+ bool retrieveDocument(QIODevice *source, const QUrl &documentUri,
+ const ReportContext::Ptr &context);
/**
* If @p context is @c null, no error reporting should be done.
*/
@@ -185,6 +199,7 @@ namespace QPatternist
const NamePool::Ptr m_namePool;
const NetworkAccessDelegator::Ptr m_networkAccessDelegator;
QHash<QPair<QUrl, QString>, QString> m_unparsedTexts;
+ AccelTreeBuilder<true>::Features m_features;
};
}