diff options
-rw-r--r-- | src/corelib/compat/removed_api.cpp | 35 | ||||
-rw-r--r-- | src/corelib/serialization/qxmlstream.cpp | 128 | ||||
-rw-r--r-- | src/corelib/serialization/qxmlstream.h | 15 | ||||
-rw-r--r-- | tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp | 22 |
4 files changed, 150 insertions, 50 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index d56ea9f43a..ba844715d8 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -278,3 +278,38 @@ QT_WARNING_POP // order sections alphabetically to reduce chances of merge conflicts #endif // QT_CORE_REMOVED_SINCE(6, 4) + +#if QT_CORE_REMOVED_SINCE(6, 5) + +#include "qxmlstream.h" + +QXmlStreamReader::QXmlStreamReader(const QByteArray &data) + : QXmlStreamReader(data, PrivateConsructorTag{}) +{ +} + +QXmlStreamReader::QXmlStreamReader(const QString &data) + : QXmlStreamReader(qToAnyStringViewIgnoringNull(data)) +{ +} + +QXmlStreamReader::QXmlStreamReader(const char *data) + : QXmlStreamReader(QAnyStringView(data)) +{ +} + +void QXmlStreamReader::addData(const QByteArray &data) +{ + addData<>(data); +} +void QXmlStreamReader::addData(const QString &data) +{ + addData(qToAnyStringViewIgnoringNull(data)); +} + +void QXmlStreamReader::addData(const char *data) +{ + addData(QAnyStringView(data)); +} + +#endif // QT_CORE_REMOVED_SINCE(6, 5) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index a6a2bc41af..28e927d7da 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -360,41 +360,55 @@ QXmlStreamReader::QXmlStreamReader(QIODevice *device) } /*! - Creates a new stream reader that reads from \a data. + \overload - \sa addData(), clear(), setDevice() - */ -QXmlStreamReader::QXmlStreamReader(const QByteArray &data) - : d_ptr(new QXmlStreamReaderPrivate(this)) -{ - Q_D(QXmlStreamReader); - d->dataBuffer = data; -} + \fn QXmlStreamReader::QXmlStreamReader(const QByteArray &data) + + Creates a new stream reader that reads from \a data. + + \sa addData(), clear(), setDevice() +*/ /*! - Creates a new stream reader that reads from \a data. + Creates a new stream reader that reads from \a data. - \sa addData(), clear(), setDevice() - */ -QXmlStreamReader::QXmlStreamReader(const QString &data) + \note In Qt versions prior to 6.5, this constructor was overloaded + for QString and \c {const char*}. + + \sa addData(), clear(), setDevice() +*/ +QXmlStreamReader::QXmlStreamReader(QAnyStringView data) : d_ptr(new QXmlStreamReaderPrivate(this)) { Q_D(QXmlStreamReader); - d->dataBuffer = data.toUtf8(); - d->decoder = QStringDecoder(QStringDecoder::Utf8); - d->lockEncoding = true; + data.visit([d](auto data) { + if constexpr (std::is_same_v<decltype(data), QStringView>) { + d->dataBuffer = data.toUtf8(); + d->decoder = QStringDecoder(QStringDecoder::Utf8); + d->lockEncoding = true; + } else if constexpr (std::is_same_v<decltype(data), QLatin1StringView>) { + // Conversion to a QString is required, to avoid breaking + // pre-existing (before porting to QAnyStringView) behavior. + d->dataBuffer = QString::fromLatin1(data).toUtf8(); + d->decoder = QStringDecoder(QStringDecoder::Utf8); + d->lockEncoding = true; + } else { + d->dataBuffer = QByteArray(data.data(), data.size()); + } + }); } /*! - Creates a new stream reader that reads from \a data. + \internal - \sa addData(), clear(), setDevice() - */ -QXmlStreamReader::QXmlStreamReader(const char *data) + Creates a new stream reader that reads from \a data. + Used by the weak constructor taking a QByteArray. +*/ +QXmlStreamReader::QXmlStreamReader(const QByteArray &data, PrivateConsructorTag) : d_ptr(new QXmlStreamReaderPrivate(this)) { Q_D(QXmlStreamReader); - d->dataBuffer = QByteArray(data); + d->dataBuffer = data; } /*! @@ -443,47 +457,61 @@ QIODevice *QXmlStreamReader::device() const return d->device; } - /*! - Adds more \a data for the reader to read. This function does - nothing if the reader has a device(). + \overload - \sa readNext(), clear() - */ -void QXmlStreamReader::addData(const QByteArray &data) -{ - Q_D(QXmlStreamReader); - if (d->device) { - qWarning("QXmlStreamReader: addData() with device()"); - return; - } - d->dataBuffer += data; -} + \fn void QXmlStreamReader::addData(const QByteArray &data) + + Adds more \a data for the reader to read. This function does + nothing if the reader has a device(). + + \sa readNext(), clear() +*/ /*! - Adds more \a data for the reader to read. This function does - nothing if the reader has a device(). + Adds more \a data for the reader to read. This function does + nothing if the reader has a device(). - \sa readNext(), clear() - */ -void QXmlStreamReader::addData(const QString &data) + \note In Qt versions prior to 6.5, this function was overloaded + for QString and \c {const char*}. + + \sa readNext(), clear() +*/ +void QXmlStreamReader::addData(QAnyStringView data) { Q_D(QXmlStreamReader); - d->lockEncoding = true; - if (!d->decoder.isValid()) - d->decoder = QStringDecoder(QStringDecoder::Utf8); - addData(data.toUtf8()); + data.visit([=](auto data) { + if constexpr (std::is_same_v<decltype(data), QStringView>) { + d->lockEncoding = true; + if (!d->decoder.isValid()) + d->decoder = QStringDecoder(QStringDecoder::Utf8); + addDataImpl(data.toUtf8()); + } else if constexpr (std::is_same_v<decltype(data), QLatin1StringView>) { + // Conversion to a QString is required, to avoid breaking + // pre-existing (before porting to QAnyStringView) behavior. + if (!d->decoder.isValid()) + d->decoder = QStringDecoder(QStringDecoder::Utf8); + addDataImpl(QString::fromLatin1(data).toUtf8()); + } else { + addDataImpl(QByteArray(data.data(), data.size())); + } + }); } /*! - Adds more \a data for the reader to read. This function does - nothing if the reader has a device(). + \internal - \sa readNext(), clear() - */ -void QXmlStreamReader::addData(const char *data) + Adds more \a data for the reader to read. This function does + nothing if the reader has a device(). +*/ +void QXmlStreamReader::addDataImpl(const QByteArray &data) { - addData(QByteArray(data)); + Q_D(QXmlStreamReader); + if (d->device) { + qWarning("QXmlStreamReader: addData() with device()"); + return; + } + d->dataBuffer += data; } /*! diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h index 366d357b37..8ba24f430e 100644 --- a/src/corelib/serialization/qxmlstream.h +++ b/src/corelib/serialization/qxmlstream.h @@ -197,16 +197,27 @@ public: QXmlStreamReader(); explicit QXmlStreamReader(QIODevice *device); +#if QT_CORE_REMOVED_SINCE(6, 5) explicit QXmlStreamReader(const QByteArray &data); explicit QXmlStreamReader(const QString &data); explicit QXmlStreamReader(const char * data); +#endif // QT_CORE_REMOVED_SINCE(6, 5) + Q_WEAK_OVERLOAD + explicit QXmlStreamReader(const QByteArray &data) + : QXmlStreamReader(data, PrivateConsructorTag{}) { } + explicit QXmlStreamReader(QAnyStringView data); ~QXmlStreamReader(); void setDevice(QIODevice *device); QIODevice *device() const; +#if QT_CORE_REMOVED_SINCE(6, 5) void addData(const QByteArray &data); void addData(const QString &data); void addData(const char *data); +#endif // QT_CORE_REMOVED_SINCE(6, 5) + Q_WEAK_OVERLOAD + void addData(const QByteArray &data) { addDataImpl(data); } + void addData(QAnyStringView data); void clear(); @@ -293,6 +304,10 @@ public: QXmlStreamEntityResolver *entityResolver() const; private: + struct PrivateConsructorTag { }; + QXmlStreamReader(const QByteArray &data, PrivateConsructorTag); + void addDataImpl(const QByteArray &data); + Q_DISABLE_COPY(QXmlStreamReader) Q_DECLARE_PRIVATE(QXmlStreamReader) QScopedPointer<QXmlStreamReaderPrivate> d_ptr; diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index 2799e7a999..3cad03641b 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -16,6 +16,8 @@ #include "qc14n.h" +using namespace Qt::StringLiterals; + Q_DECLARE_METATYPE(QXmlStreamReader::ReadElementTextBehaviour) static const char *const catalogFile = "XML-Test-Suite/xmlconf/finalCatalog.xml"; @@ -558,6 +560,7 @@ private slots: void setEntityResolver(); void readFromQBuffer() const; void readFromQBufferInvalid() const; + void readFromLatin1String() const; void readNextStartElement() const; void readElementText() const; void readElementText_data() const; @@ -1099,6 +1102,25 @@ void tst_QXmlStream::readFromQBufferInvalid() const QVERIFY(reader.hasError()); } +void tst_QXmlStream::readFromLatin1String() const +{ + const auto in = "<a>M\xE5rten</a>"_L1; + { + QXmlStreamReader reader(in); + QVERIFY(reader.readNextStartElement()); + QString text = reader.readElementText(); + QCOMPARE(text, "M\xE5rten"_L1); + } + // Same as above, but with addData() + { + QXmlStreamReader reader; + reader.addData(in); + QVERIFY(reader.readNextStartElement()); + QString text = reader.readElementText(); + QCOMPARE(text, "M\xE5rten"_L1); + } +} + void tst_QXmlStream::readNextStartElement() const { QLatin1String in("<?xml version=\"1.0\"?><A><!-- blah --><B><C/></B><B attr=\"value\"/>text</A>"); |