/**************************************************************************** ** ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef CONDITIONALSTREAMREADER_H #define CONDITIONALSTREAMREADER_H #include #include QT_FORWARD_DECLARE_CLASS(QDebug) class ProxyEntityResolver; /// ConditionalStreamReader encapsulates QXmlStreamReader, offering the same /// API (except readNextStartElement() and similar conveniences) and internally /// uses Processing Instructions like: /// ... /// to exclude/include sections depending on a list of condition keywords, /// containing for example the OS. /// It should be possible to use it as a drop-in replacement for /// QXmlStreamReader for any parsing code based on readNext(). /// It also allows for specifying entities using a Processing Instruction: /// /// which can be used in conjunction with conditional processing. class ConditionalStreamReader { public: using TokenType = QXmlStreamReader::TokenType; explicit ConditionalStreamReader(QIODevice *iod); explicit ConditionalStreamReader(const QString &s); ~ConditionalStreamReader(); QIODevice *device() const { return m_reader.device(); } // Note: Caching of entity values is done internally by // ConditionalStreamReader. void setEntityResolver(QXmlStreamEntityResolver *resolver); QXmlStreamEntityResolver *entityResolver() const; bool atEnd() const { return m_reader.atEnd(); } TokenType readNext(); TokenType tokenType() const { return m_reader.tokenType(); } qint64 lineNumber() const { return m_reader.lineNumber(); } qint64 columnNumber() const { return m_reader.columnNumber(); } QXmlStreamAttributes attributes() const { return m_reader.attributes(); } QString readElementText(QXmlStreamReader::ReadElementTextBehaviour behaviour = QXmlStreamReader::ErrorOnUnexpectedElement) { return m_reader.readElementText(behaviour); } QStringView name() const { return m_reader.name(); } QStringView qualifiedName() const { return m_reader.qualifiedName(); } QStringView text() const { return m_reader.text(); } QString errorString() const { return m_reader.errorString(); } QXmlStreamReader::Error error() const { return m_reader.error(); } bool hasError() const { return m_reader.hasError(); } // Additional functions (not delegating to QXmlStreamReader) void defineEntity(const QString &name, const QString &value); const QStringList &conditions() const { return m_conditions; } void setConditions(const QStringList &newConditions); static QStringList platformConditions(); private: enum class PiTokens { None, If, Endif, EntityDefinition }; using ExtendedToken = std::pair; ExtendedToken readNextInternal(); void init(); bool conditionMatches() const; bool readEntityDefinitonPi(); QXmlStreamReader m_reader; ProxyEntityResolver *m_proxyEntityResolver = nullptr; QStringList m_conditions = ConditionalStreamReader::platformConditions(); }; QDebug operator<<(QDebug dbg, const QXmlStreamAttributes &a); #endif // CONDITIONALSTREAMREADER_H