Port QXmlStremReader to QAnyStringView
Port the constructor and addData() method to QAnyStringView, but keep the overloads taking a QByteArray to avoid extra copies when actual QByteArray is passed. These overlaods need to be Q_WEAK_OVERLOADs, to avoid ambiguities (e.g. for const char * arguments). Additionally, add a test to make sure the patch doesn't break parsing from a QLatin1StringView input. [ChangeLog][QtCore][QXmlStremReader] Added constructor and addData() overloads taking QAnyStringView. Change-Id: I0efaab82a2123271c88407e380f3c67d1099a4a6 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
c78ec50529
commit
6bc227a06a
@ -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)
|
||||
|
@ -360,43 +360,57 @@ QXmlStreamReader::QXmlStreamReader(QIODevice *device)
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new stream reader that reads from \a data.
|
||||
\overload
|
||||
|
||||
\sa addData(), clear(), setDevice()
|
||||
*/
|
||||
QXmlStreamReader::QXmlStreamReader(const QByteArray &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.
|
||||
|
||||
\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);
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
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 = data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new stream reader that reads from \a data.
|
||||
|
||||
\sa addData(), clear(), setDevice()
|
||||
*/
|
||||
QXmlStreamReader::QXmlStreamReader(const QString &data)
|
||||
: d_ptr(new QXmlStreamReaderPrivate(this))
|
||||
{
|
||||
Q_D(QXmlStreamReader);
|
||||
d->dataBuffer = data.toUtf8();
|
||||
d->decoder = QStringDecoder(QStringDecoder::Utf8);
|
||||
d->lockEncoding = true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new stream reader that reads from \a data.
|
||||
|
||||
\sa addData(), clear(), setDevice()
|
||||
*/
|
||||
QXmlStreamReader::QXmlStreamReader(const char *data)
|
||||
: d_ptr(new QXmlStreamReaderPrivate(this))
|
||||
{
|
||||
Q_D(QXmlStreamReader);
|
||||
d->dataBuffer = QByteArray(data);
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs the reader.
|
||||
*/
|
||||
@ -443,14 +457,54 @@ QIODevice *QXmlStreamReader::device() const
|
||||
return d->device;
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
|
||||
\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 QByteArray &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);
|
||||
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()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
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)
|
||||
{
|
||||
Q_D(QXmlStreamReader);
|
||||
if (d->device) {
|
||||
@ -460,32 +514,6 @@ void QXmlStreamReader::addData(const QByteArray &data)
|
||||
d->dataBuffer += data;
|
||||
}
|
||||
|
||||
/*!
|
||||
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)
|
||||
{
|
||||
Q_D(QXmlStreamReader);
|
||||
d->lockEncoding = true;
|
||||
if (!d->decoder.isValid())
|
||||
d->decoder = QStringDecoder(QStringDecoder::Utf8);
|
||||
addData(data.toUtf8());
|
||||
}
|
||||
|
||||
/*!
|
||||
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 char *data)
|
||||
{
|
||||
addData(QByteArray(data));
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes any device() or data from the reader and resets its
|
||||
internal state to the initial state.
|
||||
|
@ -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;
|
||||
|
@ -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>");
|
||||
|
Loading…
Reference in New Issue
Block a user