summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/serialization')
-rwxr-xr-xsrc/corelib/serialization/make-xml-parser.sh40
-rw-r--r--src/corelib/serialization/qbinaryjson.cpp415
-rw-r--r--src/corelib/serialization/qbinaryjson_p.h615
-rw-r--r--src/corelib/serialization/qbinaryjsonarray.cpp137
-rw-r--r--src/corelib/serialization/qbinaryjsonarray_p.h98
-rw-r--r--src/corelib/serialization/qbinaryjsonobject.cpp149
-rw-r--r--src/corelib/serialization/qbinaryjsonobject_p.h97
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue.cpp147
-rw-r--r--src/corelib/serialization/qbinaryjsonvalue_p.h136
-rw-r--r--src/corelib/serialization/qcborarray.cpp221
-rw-r--r--src/corelib/serialization/qcborarray.h221
-rw-r--r--src/corelib/serialization/qcborcommon.cpp73
-rw-r--r--src/corelib/serialization/qcborcommon.h49
-rw-r--r--src/corelib/serialization/qcborcommon_p.h43
-rw-r--r--src/corelib/serialization/qcbordiagnostic.cpp88
-rw-r--r--src/corelib/serialization/qcbormap.cpp445
-rw-r--r--src/corelib/serialization/qcbormap.h322
-rw-r--r--src/corelib/serialization/qcborstream.h42
-rw-r--r--src/corelib/serialization/qcborstreamreader.cpp617
-rw-r--r--src/corelib/serialization/qcborstreamreader.h79
-rw-r--r--src/corelib/serialization/qcborstreamwriter.cpp100
-rw-r--r--src/corelib/serialization/qcborstreamwriter.h46
-rw-r--r--src/corelib/serialization/qcborvalue.cpp1315
-rw-r--r--src/corelib/serialization/qcborvalue.h358
-rw-r--r--src/corelib/serialization/qcborvalue_p.h164
-rw-r--r--src/corelib/serialization/qdatastream.cpp347
-rw-r--r--src/corelib/serialization/qdatastream.h387
-rw-r--r--src/corelib/serialization/qdatastream_p.h45
-rw-r--r--src/corelib/serialization/qjson_p.h89
-rw-r--r--src/corelib/serialization/qjsonarray.cpp334
-rw-r--r--src/corelib/serialization/qjsonarray.h341
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp166
-rw-r--r--src/corelib/serialization/qjsondocument.cpp296
-rw-r--r--src/corelib/serialization/qjsondocument.h80
-rw-r--r--src/corelib/serialization/qjsonobject.cpp436
-rw-r--r--src/corelib/serialization/qjsonobject.h392
-rw-r--r--src/corelib/serialization/qjsonparser.cpp275
-rw-r--r--src/corelib/serialization/qjsonparser_p.h40
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp516
-rw-r--r--src/corelib/serialization/qjsonvalue.h294
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp65
-rw-r--r--src/corelib/serialization/qjsonwriter_p.h40
-rw-r--r--src/corelib/serialization/qtextstream.cpp478
-rw-r--r--src/corelib/serialization/qtextstream.h126
-rw-r--r--src/corelib/serialization/qtextstream_p.h74
-rw-r--r--src/corelib/serialization/qxmlstream.cpp1546
-rw-r--r--src/corelib/serialization/qxmlstream.g589
-rw-r--r--src/corelib/serialization/qxmlstream.h344
-rw-r--r--src/corelib/serialization/qxmlstream_p.h1846
-rw-r--r--src/corelib/serialization/qxmlstreamgrammar.cpp496
-rw-r--r--src/corelib/serialization/qxmlstreamgrammar_p.h128
-rw-r--r--src/corelib/serialization/qxmlstreamparser_p.h1006
-rw-r--r--src/corelib/serialization/qxmlutils.cpp81
-rw-r--r--src/corelib/serialization/qxmlutils_p.h42
-rw-r--r--src/corelib/serialization/serialization.pri76
55 files changed, 7627 insertions, 9365 deletions
diff --git a/src/corelib/serialization/make-xml-parser.sh b/src/corelib/serialization/make-xml-parser.sh
index 0296e4c22b..1889833700 100755
--- a/src/corelib/serialization/make-xml-parser.sh
+++ b/src/corelib/serialization/make-xml-parser.sh
@@ -1,42 +1,6 @@
#!/bin/sh
-#############################################################################
-##
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## 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 Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## 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-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2016 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
me=$(dirname $0)
mkdir -p $me/out
diff --git a/src/corelib/serialization/qbinaryjson.cpp b/src/corelib/serialization/qbinaryjson.cpp
deleted file mode 100644
index 4149705df5..0000000000
--- a/src/corelib/serialization/qbinaryjson.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjson_p.h"
-
-#include <qjsonobject.h>
-#include <qjsonarray.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QBinaryJsonPrivate {
-
-static Q_CONSTEXPR Base emptyArray = {
- { qle_uint(sizeof(Base)) },
- { 0 },
- { qle_uint(0) }
-};
-
-static Q_CONSTEXPR Base emptyObject = {
- { qle_uint(sizeof(Base)) },
- { qToLittleEndian(1U) },
- { qle_uint(0) }
-};
-
-void MutableData::compact()
-{
- static_assert(sizeof(Value) == sizeof(offset));
-
- Base *base = header->root();
- int reserve = 0;
- if (base->is_object) {
- auto *o = static_cast<Object *>(base);
- for (uint i = 0; i < o->length; ++i)
- reserve += o->entryAt(i)->usedStorage(o);
- } else {
- auto *a = static_cast<Array *>(base);
- for (uint i = 0; i < a->length; ++i)
- reserve += a->at(i)->usedStorage(a);
- }
-
- uint size = sizeof(Base) + reserve + base->length * sizeof(offset);
- uint alloc = sizeof(Header) + size;
- auto *h = reinterpret_cast<Header *>(malloc(alloc));
- Q_CHECK_PTR(h);
- h->tag = QJsonDocument::BinaryFormatTag;
- h->version = 1;
- Base *b = h->root();
- b->size = size;
- b->is_object = header->root()->is_object;
- b->length = base->length;
- b->tableOffset = reserve + sizeof(Array);
-
- uint offset = sizeof(Base);
- if (b->is_object) {
- const auto *o = static_cast<const Object *>(base);
- auto *no = static_cast<Object *>(b);
-
- for (uint i = 0; i < o->length; ++i) {
- no->table()[i] = offset;
-
- const Entry *e = o->entryAt(i);
- Entry *ne = no->entryAt(i);
- uint s = e->size();
- memcpy(ne, e, s);
- offset += s;
- uint dataSize = e->value.usedStorage(o);
- if (dataSize) {
- memcpy(reinterpret_cast<char *>(no) + offset, e->value.data(o), dataSize);
- ne->value.value = offset;
- offset += dataSize;
- }
- }
- } else {
- const auto *a = static_cast<const Array *>(base);
- auto *na = static_cast<Array *>(b);
-
- for (uint i = 0; i < a->length; ++i) {
- const Value *v = a->at(i);
- Value *nv = na->at(i);
- *nv = *v;
- uint dataSize = v->usedStorage(a);
- if (dataSize) {
- memcpy(reinterpret_cast<char *>(na) + offset, v->data(a), dataSize);
- nv->value = offset;
- offset += dataSize;
- }
- }
- }
- Q_ASSERT(offset == uint(b->tableOffset));
-
- free(header);
- header = h;
- this->alloc = alloc;
- compactionCounter = 0;
-}
-
-bool ConstData::isValid() const
-{
- if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1U)
- return false;
-
- const Base *root = header->root();
- const uint maxSize = alloc - sizeof(Header);
- return root->is_object
- ? static_cast<const Object *>(root)->isValid(maxSize)
- : static_cast<const Array *>(root)->isValid(maxSize);
-}
-
-QJsonDocument ConstData::toJsonDocument() const
-{
- const Base *root = header->root();
- return root->is_object
- ? QJsonDocument(static_cast<const Object *>(root)->toJsonObject())
- : QJsonDocument(static_cast<const Array *>(root)->toJsonArray());
-}
-
-uint Base::reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace)
-{
- Q_ASSERT(posInTable <= length);
- if (size + dataSize >= Value::MaxSize) {
- qWarning("QJson: Document too large to store in data structure %d %d %d",
- uint(size), dataSize, Value::MaxSize);
- return 0;
- }
-
- offset off = tableOffset;
- // move table to new position
- if (replace) {
- memmove(reinterpret_cast<char *>(table()) + dataSize, table(), length * sizeof(offset));
- } else {
- memmove(reinterpret_cast<char *>(table() + posInTable + numItems) + dataSize,
- table() + posInTable, (length - posInTable) * sizeof(offset));
- memmove(reinterpret_cast<char *>(table()) + dataSize, table(), posInTable * sizeof(offset));
- }
- tableOffset += dataSize;
- for (uint i = 0; i < numItems; ++i)
- table()[posInTable + i] = off;
- size += dataSize;
- if (!replace) {
- length += numItems;
- size += numItems * sizeof(offset);
- }
- return off;
-}
-
-uint Object::indexOf(QStringView key, bool *exists) const
-{
- uint min = 0;
- uint n = length;
- while (n > 0) {
- uint half = n >> 1;
- uint middle = min + half;
- if (*entryAt(middle) >= key) {
- n = half;
- } else {
- min = middle + 1;
- n -= half + 1;
- }
- }
- if (min < length && *entryAt(min) == key) {
- *exists = true;
- return min;
- }
- *exists = false;
- return min;
-}
-
-QJsonObject Object::toJsonObject() const
-{
- QJsonObject object;
- for (uint i = 0; i < length; ++i) {
- const Entry *e = entryAt(i);
- object.insert(e->key(), e->value.toJsonValue(this));
- }
- return object;
-}
-
-bool Object::isValid(uint maxSize) const
-{
- if (size > maxSize || tableOffset + length * sizeof(offset) > size)
- return false;
-
- QString lastKey;
- for (uint i = 0; i < length; ++i) {
- if (table()[i] + sizeof(Entry) >= tableOffset)
- return false;
- const Entry *e = entryAt(i);
- if (!e->isValid(tableOffset - table()[i]))
- return false;
- const QString key = e->key();
- if (key < lastKey)
- return false;
- if (!e->value.isValid(this))
- return false;
- lastKey = key;
- }
- return true;
-}
-
-QJsonArray Array::toJsonArray() const
-{
- QJsonArray array;
- const offset *values = table();
- for (uint i = 0; i < length; ++i)
- array.append(reinterpret_cast<const Value *>(values + i)->toJsonValue(this));
- return array;
-}
-
-bool Array::isValid(uint maxSize) const
-{
- if (size > maxSize || tableOffset + length * sizeof(offset) > size)
- return false;
-
- const offset *values = table();
- for (uint i = 0; i < length; ++i) {
- if (!reinterpret_cast<const Value *>(values + i)->isValid(this))
- return false;
- }
- return true;
-}
-
-uint Value::usedStorage(const Base *b) const
-{
- uint s = 0;
- switch (type) {
- case QJsonValue::Double:
- if (!latinOrIntValue)
- s = sizeof(double);
- break;
- case QJsonValue::String: {
- const char *d = data(b);
- s = latinOrIntValue
- ? (sizeof(ushort)
- + qFromLittleEndian(*reinterpret_cast<const ushort *>(d)))
- : (sizeof(int)
- + sizeof(ushort) * qFromLittleEndian(*reinterpret_cast<const int *>(d)));
- break;
- }
- case QJsonValue::Array:
- case QJsonValue::Object:
- s = base(b)->size;
- break;
- case QJsonValue::Null:
- case QJsonValue::Bool:
- default:
- break;
- }
- return alignedSize(s);
-}
-
-QJsonValue Value::toJsonValue(const Base *b) const
-{
- switch (type) {
- case QJsonValue::Null:
- return QJsonValue(QJsonValue::Null);
- case QJsonValue::Bool:
- return QJsonValue(toBoolean());
- case QJsonValue::Double:
- return QJsonValue(toDouble(b));
- case QJsonValue::String:
- return QJsonValue(toString(b));
- case QJsonValue::Array:
- return static_cast<const Array *>(base(b))->toJsonArray();
- case QJsonValue::Object:
- return static_cast<const Object *>(base(b))->toJsonObject();
- case QJsonValue::Undefined:
- return QJsonValue(QJsonValue::Undefined);
- }
- Q_UNREACHABLE();
- return QJsonValue(QJsonValue::Undefined);
-}
-
-inline bool isValidValueOffset(uint offset, uint tableOffset)
-{
- return offset >= sizeof(Base)
- && offset + sizeof(uint) <= tableOffset;
-}
-
-bool Value::isValid(const Base *b) const
-{
- switch (type) {
- case QJsonValue::Null:
- case QJsonValue::Bool:
- return true;
- case QJsonValue::Double:
- return latinOrIntValue || isValidValueOffset(value, b->tableOffset);
- case QJsonValue::String:
- if (!isValidValueOffset(value, b->tableOffset))
- return false;
- if (latinOrIntValue)
- return asLatin1String(b).isValid(b->tableOffset - value);
- return asString(b).isValid(b->tableOffset - value);
- case QJsonValue::Array:
- return isValidValueOffset(value, b->tableOffset)
- && static_cast<const Array *>(base(b))->isValid(b->tableOffset - value);
- case QJsonValue::Object:
- return isValidValueOffset(value, b->tableOffset)
- && static_cast<const Object *>(base(b))->isValid(b->tableOffset - value);
- default:
- return false;
- }
-}
-
-uint Value::requiredStorage(const QBinaryJsonValue &v, bool *compressed)
-{
- *compressed = false;
- switch (v.type()) {
- case QJsonValue::Double:
- if (QBinaryJsonPrivate::compressedNumber(v.toDouble()) != INT_MAX) {
- *compressed = true;
- return 0;
- }
- return sizeof(double);
- case QJsonValue::String: {
- QString s = v.toString();
- *compressed = QBinaryJsonPrivate::useCompressed(s);
- return QBinaryJsonPrivate::qStringSize(s, *compressed);
- }
- case QJsonValue::Array:
- case QJsonValue::Object:
- return v.base ? uint(v.base->size) : sizeof(QBinaryJsonPrivate::Base);
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- case QJsonValue::Bool:
- break;
- }
- return 0;
-}
-
-uint Value::valueToStore(const QBinaryJsonValue &v, uint offset)
-{
- switch (v.type()) {
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- break;
- case QJsonValue::Bool:
- return v.toBool();
- case QJsonValue::Double: {
- int c = QBinaryJsonPrivate::compressedNumber(v.toDouble());
- if (c != INT_MAX)
- return c;
- }
- Q_FALLTHROUGH();
- case QJsonValue::String:
- case QJsonValue::Array:
- case QJsonValue::Object:
- return offset;
- }
- return 0;
-}
-
-void Value::copyData(const QBinaryJsonValue &v, char *dest, bool compressed)
-{
- switch (v.type()) {
- case QJsonValue::Double:
- if (!compressed)
- qToLittleEndian(v.toDouble(), dest);
- break;
- case QJsonValue::String: {
- const QString str = v.toString();
- QBinaryJsonPrivate::copyString(dest, str, compressed);
- break;
- }
- case QJsonValue::Array:
- case QJsonValue::Object: {
- const QBinaryJsonPrivate::Base *b = v.base;
- if (!b)
- b = (v.type() == QJsonValue::Array ? &emptyArray : &emptyObject);
- memcpy(dest, b, b->size);
- break;
- }
- default:
- break;
- }
-}
-
-} // namespace QBinaryJsonPrivate
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjson_p.h b/src/corelib/serialization/qbinaryjson_p.h
deleted file mode 100644
index 3eca794a58..0000000000
--- a/src/corelib/serialization/qbinaryjson_p.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSON_P_H
-#define QBINARYJSON_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qbinaryjsonvalue_p.h>
-#include <private/qendian_p.h>
-
-#include <qjsondocument.h>
-
-#include <limits>
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-// in qstring.cpp
-void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len);
-
-/*
- This defines a binary data structure for Json data. The data structure is optimised for fast reading
- and minimum allocations. The whole data structure can be mmap'ed and used directly.
-
- In most cases the binary structure is not as space efficient as a utf8 encoded text representation, but
- much faster to access.
-
- The size requirements are:
-
- String:
- Latin1 data: 2 bytes header + string.length()
- Full Unicode: 4 bytes header + 2*(string.length())
-
- Values: 4 bytes + size of data (size can be 0 for some data)
- bool: 0 bytes
- double: 8 bytes (0 if integer with less than 27bits)
- string: see above
- array: size of array
- object: size of object
- Array: 12 bytes + 4*length + size of Value data
- Object: 12 bytes + 8*length + size of Key Strings + size of Value data
-
- For an example such as
-
- { // object: 12 + 5*8 = 52
- "firstName": "John", // key 12, value 8 = 20
- "lastName" : "Smith", // key 12, value 8 = 20
- "age" : 25, // key 8, value 0 = 8
- "address" : // key 12, object below = 140
- { // object: 12 + 4*8
- "streetAddress": "21 2nd Street", // key 16, value 16
- "city" : "New York", // key 8, value 12
- "state" : "NY", // key 8, value 4
- "postalCode" : "10021" // key 12, value 8
- }, // object total: 128
- "phoneNumber": // key: 16, value array below = 172
- [ // array: 12 + 2*4 + values below: 156
- { // object 12 + 2*8
- "type" : "home", // key 8, value 8
- "number": "212 555-1234" // key 8, value 16
- }, // object total: 68
- { // object 12 + 2*8
- "type" : "fax", // key 8, value 8
- "number": "646 555-4567" // key 8, value 16
- } // object total: 68
- ] // array total: 156
- } // great total: 412 bytes
-
- The uncompressed text file used roughly 500 bytes, so in this case we end up using about
- the same space as the text representation.
-
- Other measurements have shown a slightly bigger binary size than a compact text
- representation where all possible whitespace was stripped out.
-*/
-namespace QBinaryJsonPrivate {
-
-class Array;
-class Object;
-class Value;
-class Entry;
-
-template<typename T>
-using q_littleendian = QLEInteger<T>;
-
-using qle_short = q_littleendian<short>;
-using qle_ushort = q_littleendian<unsigned short>;
-using qle_int = q_littleendian<int>;
-using qle_uint = q_littleendian<unsigned int>;
-
-template<int pos, int width>
-using qle_bitfield = QLEIntegerBitfield<uint, pos, width>;
-
-template<int pos, int width>
-using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>;
-
-using offset = qle_uint;
-
-// round the size up to the next 4 byte boundary
-inline uint alignedSize(uint size) { return (size + 3) & ~3; }
-
-const int MaxLatin1Length = 0x7fff;
-
-static inline bool useCompressed(QStringView s)
-{
- if (s.length() > MaxLatin1Length)
- return false;
- return QtPrivate::isLatin1(s);
-}
-
-static inline bool useCompressed(QLatin1String s)
-{
- return s.size() <= MaxLatin1Length;
-}
-
-static inline uint qStringSize(const QString &string, bool compress)
-{
- uint l = 2 + string.size();
- if (!compress)
- l *= 2;
- return alignedSize(l);
-}
-
-// returns INT_MAX if it can't compress it into 28 bits
-static inline int compressedNumber(double d)
-{
- // this relies on details of how ieee floats are represented
- const int exponent_off = 52;
- const quint64 fraction_mask = 0x000fffffffffffffULL;
- const quint64 exponent_mask = 0x7ff0000000000000ULL;
-
- quint64 val;
- memcpy (&val, &d, sizeof(double));
- int exp = (int)((val & exponent_mask) >> exponent_off) - 1023;
- if (exp < 0 || exp > 25)
- return std::numeric_limits<int>::max();
-
- quint64 non_int = val & (fraction_mask >> exp);
- if (non_int)
- return std::numeric_limits<int>::max();
-
- bool neg = (val >> 63) != 0;
- val &= fraction_mask;
- val |= ((quint64)1 << 52);
- int res = (int)(val >> (52 - exp));
- return neg ? -res : res;
-}
-
-class Latin1String;
-
-class String
-{
-public:
- explicit String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
-
- struct Data {
- qle_uint length;
- qle_ushort utf16[1];
- };
- const Data *d;
-
- uint byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; }
- bool isValid(uint maxSize) const
- {
- // Check byteSize() <= maxSize, avoiding integer overflow
- return maxSize >= sizeof(uint)
- && uint(d->length) <= (maxSize - sizeof(uint)) / sizeof(ushort);
- }
-
- static void copy(char *dest, QStringView str)
- {
- Data *data = reinterpret_cast<Data *>(dest);
- data->length = str.length();
- qToLittleEndian<quint16>(str.utf16(), str.length(), data->utf16);
- fillTrailingZeros(data);
- }
-
- static void fillTrailingZeros(Data *data)
- {
- if (data->length & 1)
- data->utf16[data->length] = 0;
- }
-
- bool operator ==(QStringView str) const
- {
- int slen = str.length();
- int l = d->length;
- if (slen != l)
- return false;
- const auto *s = reinterpret_cast<const ushort *>(str.utf16());
- const qle_ushort *a = d->utf16;
- const ushort *b = s;
- while (l-- && *a == *b)
- a++,b++;
- return (l == -1);
- }
-
- bool operator ==(const String &str) const
- {
- if (d->length != str.d->length)
- return false;
- return !memcmp(d->utf16, str.d->utf16, d->length * sizeof(ushort));
- }
-
- QString toString() const
- {
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- return QString(reinterpret_cast<const QChar *>(d->utf16), d->length);
-#else
- const uint l = d->length;
- QString str(l, Qt::Uninitialized);
- QChar *ch = str.data();
- for (uint i = 0; i < l; ++i)
- ch[i] = QChar(d->utf16[i]);
- return str;
-#endif
- }
-};
-
-class Latin1String
-{
-public:
- explicit Latin1String(const char *data) : d(reinterpret_cast<const Data *>(data)) {}
-
- struct Data {
- qle_ushort length;
- char latin1[1];
- };
- const Data *d;
-
- uint byteSize() const { return sizeof(ushort) + sizeof(char) * (d->length); }
- bool isValid(uint maxSize) const { return byteSize() <= maxSize; }
-
- static void copy(char *dest, QStringView src)
- {
- Data *data = reinterpret_cast<Data *>(dest);
- data->length = src.length(); // ### narrows from int to ushort
- auto *l = reinterpret_cast<uchar *>(data->latin1);
- qt_to_latin1_unchecked(l, src.utf16(), data->length);
-
- for (uint len = data->length; quintptr(l + len) & 0x3; ++len)
- l[len] = 0;
- }
-
- QLatin1String toQLatin1String() const noexcept { return QLatin1String(d->latin1, d->length); }
- QString toString() const { return QString::fromLatin1(d->latin1, d->length); }
-};
-
-static inline void copyString(char *dest, QStringView str, bool compress)
-{
- if (compress)
- Latin1String::copy(dest, str);
- else
- String::copy(dest, str);
-}
-
-/*
- Base is the base class for both Object and Array. Both classes work more or less the same way.
- The class starts with a header (defined by the struct below), then followed by data (the data for
- values in the Array case and Entry's (see below) for objects.
-
- After the data a table follows (tableOffset points to it) containing Value objects for Arrays, and
- offsets from the beginning of the object to Entry's in the case of Object.
-
- Entry's in the Object's table are lexicographically sorted by key in the table(). This allows the usage
- of a binary search over the keys in an Object.
- */
-class Base
-{
-public:
- qle_uint size;
- union {
- uint _dummy;
- qle_bitfield<0, 1> is_object;
- qle_bitfield<1, 31> length;
- };
- offset tableOffset;
- // content follows here
-
- bool isObject() const { return !!is_object; }
- bool isArray() const { return !isObject(); }
-
- offset *table()
- {
- return reinterpret_cast<offset *>(reinterpret_cast<char *>(this) + tableOffset);
- }
-
- const offset *table() const
- {
- return reinterpret_cast<const offset *>(reinterpret_cast<const char *>(this) + tableOffset);
- }
-
- uint reserveSpace(uint dataSize, uint posInTable, uint numItems, bool replace);
-};
-
-class Object : public Base
-{
-public:
- const Entry *entryAt(uint i) const
- {
- return reinterpret_cast<const Entry *>(reinterpret_cast<const char *>(this) + table()[i]);
- }
-
- Entry *entryAt(uint i)
- {
- return reinterpret_cast<Entry *>(reinterpret_cast<char *>(this) + table()[i]);
- }
-
- uint indexOf(QStringView key, bool *exists) const;
- QJsonObject toJsonObject() const;
- bool isValid(uint maxSize) const;
-};
-
-class Array : public Base
-{
-public:
- const Value *at(uint i) const { return reinterpret_cast<const Value *>(table() + i); }
- Value *at(uint i) { return reinterpret_cast<Value *>(table() + i); }
-
- QJsonArray toJsonArray() const;
- bool isValid(uint maxSize) const;
-};
-
-class Value
-{
-public:
- enum {
- MaxSize = (1 << 27) - 1
- };
- union {
- uint _dummy;
- qle_bitfield<0, 3> type;
- qle_bitfield<3, 1> latinOrIntValue;
- qle_bitfield<4, 1> latinKey;
- qle_bitfield<5, 27> value;
- qle_signedbitfield<5, 27> int_value;
- };
-
- inline const char *data(const Base *b) const
- {
- return reinterpret_cast<const char *>(b) + value;
- }
-
- uint usedStorage(const Base *b) const;
-
- bool toBoolean() const
- {
- Q_ASSERT(type == QJsonValue::Bool);
- return value != 0;
- }
-
- double toDouble(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::Double);
- if (latinOrIntValue)
- return int_value;
-
- auto i = qFromLittleEndian<quint64>(reinterpret_cast<const uchar *>(b) + value);
- double d;
- memcpy(&d, &i, sizeof(double));
- return d;
- }
-
- QString toString(const Base *b) const
- {
- return latinOrIntValue
- ? asLatin1String(b).toString()
- : asString(b).toString();
- }
-
- String asString(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::String && !latinOrIntValue);
- return String(data(b));
- }
-
- Latin1String asLatin1String(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::String && latinOrIntValue);
- return Latin1String(data(b));
- }
-
- const Base *base(const Base *b) const
- {
- Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object);
- return reinterpret_cast<const Base *>(data(b));
- }
-
- QJsonValue toJsonValue(const Base *b) const;
- bool isValid(const Base *b) const;
-
- static uint requiredStorage(const QBinaryJsonValue &v, bool *compressed);
- static uint valueToStore(const QBinaryJsonValue &v, uint offset);
- static void copyData(const QBinaryJsonValue &v, char *dest, bool compressed);
-};
-
-class Entry {
-public:
- Value value;
- // key
- // value data follows key
-
- uint size() const
- {
- uint s = sizeof(Entry);
- if (value.latinKey)
- s += shallowLatin1Key().byteSize();
- else
- s += shallowKey().byteSize();
- return alignedSize(s);
- }
-
- uint usedStorage(Base *b) const
- {
- return size() + value.usedStorage(b);
- }
-
- String shallowKey() const
- {
- Q_ASSERT(!value.latinKey);
- return String(reinterpret_cast<const char *>(this) + sizeof(Entry));
- }
-
- Latin1String shallowLatin1Key() const
- {
- Q_ASSERT(value.latinKey);
- return Latin1String(reinterpret_cast<const char *>(this) + sizeof(Entry));
- }
-
- QString key() const
- {
- return value.latinKey
- ? shallowLatin1Key().toString()
- : shallowKey().toString();
- }
-
- bool isValid(uint maxSize) const
- {
- if (maxSize < sizeof(Entry))
- return false;
- maxSize -= sizeof(Entry);
- return value.latinKey
- ? shallowLatin1Key().isValid(maxSize)
- : shallowKey().isValid(maxSize);
- }
-
- bool operator ==(QStringView key) const
- {
- return value.latinKey
- ? (shallowLatin1Key().toQLatin1String() == key)
- : (shallowKey() == key);
- }
-
- bool operator >=(QStringView key) const
- {
- return value.latinKey
- ? (shallowLatin1Key().toQLatin1String() >= key)
- : (shallowKey().toString() >= key);
- }
-};
-
-class Header {
-public:
- qle_uint tag; // 'qbjs'
- qle_uint version; // 1
- Base *root() { return reinterpret_cast<Base *>(this + 1); }
- const Base *root() const { return reinterpret_cast<const Base *>(this + 1); }
-};
-
-class ConstData
-{
- Q_DISABLE_COPY_MOVE(ConstData)
-public:
- const uint alloc;
- union {
- const char *rawData;
- const Header *header;
- };
-
- ConstData(const char *raw, uint a) : alloc(a), rawData(raw) {}
- bool isValid() const;
- QJsonDocument toJsonDocument() const;
-};
-
-class MutableData
-{
- Q_DISABLE_COPY_MOVE(MutableData)
-public:
- QAtomicInt ref;
- uint alloc;
- union {
- char *rawData;
- Header *header;
- };
- uint compactionCounter : 31;
-
- MutableData(char *raw, uint a)
- : alloc(a), rawData(raw), compactionCounter(0)
- {
- }
-
- MutableData(uint reserved, QJsonValue::Type valueType)
- : rawData(nullptr), compactionCounter(0)
- {
- Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object);
-
- alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset);
- header = reinterpret_cast<Header *>(malloc(alloc));
- Q_CHECK_PTR(header);
- header->tag = QJsonDocument::BinaryFormatTag;
- header->version = 1;
- Base *b = header->root();
- b->size = sizeof(Base);
- b->is_object = (valueType == QJsonValue::Object);
- b->tableOffset = sizeof(Base);
- b->length = 0;
- }
-
- ~MutableData()
- {
- free(rawData);
- }
-
- MutableData *clone(const Base *b, uint reserve = 0)
- {
- uint size = sizeof(Header) + b->size;
- if (b == header->root() && ref.loadRelaxed() == 1 && alloc >= size + reserve)
- return this;
-
- if (reserve) {
- if (reserve < 128)
- reserve = 128;
- size = qMax(size + reserve, qMin(size *2, uint(Value::MaxSize)));
- if (size > Value::MaxSize) {
- qWarning("QJson: Document too large to store in data structure");
- return nullptr;
- }
- }
- char *raw = reinterpret_cast<char *>(malloc(size));
- Q_CHECK_PTR(raw);
- memcpy(raw + sizeof(Header), b, b->size);
- auto *h = reinterpret_cast<Header *>(raw);
- h->tag = QJsonDocument::BinaryFormatTag;
- h->version = 1;
- auto *d = new MutableData(raw, size);
- d->compactionCounter = (b == header->root()) ? compactionCounter : 0;
- return d;
- }
-
- char *takeRawData(uint *size)
- {
- *size = alloc;
- char *result = rawData;
- rawData = nullptr;
- alloc = 0;
- return result;
- }
-
- void compact();
-};
-
-} // namespace QBinaryJsonPrivate
-
-Q_DECLARE_TYPEINFO(QBinaryJsonPrivate::Value, Q_PRIMITIVE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSON_P_H
diff --git a/src/corelib/serialization/qbinaryjsonarray.cpp b/src/corelib/serialization/qbinaryjsonarray.cpp
deleted file mode 100644
index 68937fe17d..0000000000
--- a/src/corelib/serialization/qbinaryjsonarray.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonarray_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonarray.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonArray::~QBinaryJsonArray()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonArray QBinaryJsonArray::fromJsonArray(const QJsonArray &array)
-{
- QBinaryJsonArray binary;
- for (const QJsonValue &value : array)
- binary.append(QBinaryJsonValue::fromJsonValue(value));
- if (binary.d) // We want to compact it as it is a root item now
- binary.d->compactionCounter++;
- binary.compact();
- return binary;
-}
-
-void QBinaryJsonArray::append(const QBinaryJsonValue &value)
-{
- const uint i = a ? a->length : 0;
-
- bool compressed;
- uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &compressed);
-
- if (!detach(valueSize + sizeof(QBinaryJsonPrivate::Value)))
- return;
-
- if (!a->length)
- a->tableOffset = sizeof(QBinaryJsonPrivate::Array);
-
- uint valueOffset = a->reserveSpace(valueSize, i, 1, false);
- if (!valueOffset)
- return;
-
- QBinaryJsonPrivate::Value *v = a->at(i);
- v->type = (value.t == QJsonValue::Undefined ? QJsonValue::Null : value.t);
- v->latinOrIntValue = compressed;
- v->latinKey = false;
- v->value = QBinaryJsonPrivate::Value::valueToStore(value, valueOffset);
- if (valueSize) {
- QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(a) + valueOffset,
- compressed);
- }
-}
-
-char *QBinaryJsonArray::takeRawData(uint *size)
-{
- if (d)
- return d->takeRawData(size);
- *size = 0;
- return nullptr;
-}
-
-bool QBinaryJsonArray::detach(uint reserve)
-{
- if (!d) {
- if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
- qWarning("QBinaryJson: Document too large to store in data structure");
- return false;
- }
- d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Array);
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
- d->ref.ref();
- return true;
- }
- if (reserve == 0 && d->ref.loadRelaxed() == 1)
- return true;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(a, reserve);
- if (!x)
- return false;
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
- return true;
-}
-
-void QBinaryJsonArray::compact()
-{
- if (!d || !d->compactionCounter)
- return;
-
- detach();
- d->compact();
- a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root());
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/corelib/serialization/qbinaryjsonarray_p.h b/src/corelib/serialization/qbinaryjsonarray_p.h
deleted file mode 100644
index 2bb8fed387..0000000000
--- a/src/corelib/serialization/qbinaryjsonarray_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONARRAY_P_H
-#define QBINARYJSONARRAY_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qbinaryjsonvalue_p.h"
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonArray
-{
- Q_DISABLE_COPY(QBinaryJsonArray)
-public:
- QBinaryJsonArray() = default;
- ~QBinaryJsonArray();
-
- QBinaryJsonArray(QBinaryJsonArray &&other) noexcept
- : d(other.d),
- a(other.a)
- {
- other.d = nullptr;
- other.a = nullptr;
- }
-
- QBinaryJsonArray &operator =(QBinaryJsonArray &&other) noexcept
- {
- qSwap(d, other.d);
- qSwap(a, other.a);
- return *this;
- }
-
- static QBinaryJsonArray fromJsonArray(const QJsonArray &array);
- char *takeRawData(uint *size);
-
-private:
- friend class QBinaryJsonValue;
-
- void append(const QBinaryJsonValue &value);
- void compact();
- bool detach(uint reserve = 0);
-
- QBinaryJsonPrivate::MutableData *d = nullptr;
- QBinaryJsonPrivate::Array *a = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONARRAY_P_H
diff --git a/src/corelib/serialization/qbinaryjsonobject.cpp b/src/corelib/serialization/qbinaryjsonobject.cpp
deleted file mode 100644
index 3186ab6087..0000000000
--- a/src/corelib/serialization/qbinaryjsonobject.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonobject.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonObject::~QBinaryJsonObject()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonObject QBinaryJsonObject::fromJsonObject(const QJsonObject &object)
-{
- QBinaryJsonObject binary;
- for (auto it = object.begin(), end = object.end(); it != end; ++it)
- binary.insert(it.key(), QBinaryJsonValue::fromJsonValue(it.value()));
- if (binary.d) // We want to compact it as it is a root item now
- binary.d->compactionCounter++;
- binary.compact();
- return binary;
-}
-
-void QBinaryJsonObject::insert(const QString &key, const QBinaryJsonValue &value)
-{
- bool latinOrIntValue;
- uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(value, &latinOrIntValue);
-
- bool latinKey = QBinaryJsonPrivate::useCompressed(key);
- uint valueOffset = sizeof(QBinaryJsonPrivate::Entry)
- + QBinaryJsonPrivate::qStringSize(key, latinKey);
- uint requiredSize = valueOffset + valueSize;
-
- if (!detach(requiredSize + sizeof(QBinaryJsonPrivate::offset))) // offset for the new index entry
- return;
-
- if (!o->length)
- o->tableOffset = sizeof(QBinaryJsonPrivate::Object);
-
- bool keyExists = false;
- uint pos = o->indexOf(key, &keyExists);
- if (keyExists)
- ++d->compactionCounter;
-
- uint off = o->reserveSpace(requiredSize, pos, 1, keyExists);
- if (!off)
- return;
-
- QBinaryJsonPrivate::Entry *e = o->entryAt(pos);
- e->value.type = value.t;
- e->value.latinKey = latinKey;
- e->value.latinOrIntValue = latinOrIntValue;
- e->value.value = QBinaryJsonPrivate::Value::valueToStore(
- value, reinterpret_cast<char *>(e) - reinterpret_cast<char *>(o) + valueOffset);
- QBinaryJsonPrivate::copyString(reinterpret_cast<char *>(e + 1), key, latinKey);
- if (valueSize) {
- QBinaryJsonPrivate::Value::copyData(value, reinterpret_cast<char *>(e) + valueOffset,
- latinOrIntValue);
- }
-
- if (d->compactionCounter > 32U && d->compactionCounter >= unsigned(o->length) / 2U)
- compact();
-}
-
-char *QBinaryJsonObject::takeRawData(uint *size) const
-{
- if (d)
- return d->takeRawData(size);
- *size = 0;
- return nullptr;
-}
-
-bool QBinaryJsonObject::detach(uint reserve)
-{
- if (!d) {
- if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
- qWarning("QBinaryJson: Document too large to store in data structure");
- return false;
- }
- d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Object);
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
- d->ref.ref();
- return true;
- }
- if (reserve == 0 && d->ref.loadRelaxed() == 1)
- return true;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(o, reserve);
- if (!x)
- return false;
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
- return true;
-}
-
-void QBinaryJsonObject::compact()
-{
- if (!d || !d->compactionCounter)
- return;
-
- detach();
- d->compact();
- o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjsonobject_p.h b/src/corelib/serialization/qbinaryjsonobject_p.h
deleted file mode 100644
index c0991ac339..0000000000
--- a/src/corelib/serialization/qbinaryjsonobject_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONOBJECT_H
-#define QBINARYJSONOBJECT_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qbinaryjsonvalue_p.h"
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonObject
-{
- Q_DISABLE_COPY(QBinaryJsonObject)
-public:
- QBinaryJsonObject() = default;
- ~QBinaryJsonObject();
-
- QBinaryJsonObject(QBinaryJsonObject &&other) noexcept
- : d(other.d), o(other.o)
- {
- other.d = nullptr;
- other.o = nullptr;
- }
-
- QBinaryJsonObject &operator =(QBinaryJsonObject &&other) noexcept
- {
- qSwap(d, other.d);
- qSwap(o, other.o);
- return *this;
- }
-
- static QBinaryJsonObject fromJsonObject(const QJsonObject &object);
- char *takeRawData(uint *size) const;
-
-private:
- friend class QBinaryJsonValue;
-
- void insert(const QString &key, const QBinaryJsonValue &value);
- bool detach(uint reserve = 0);
- void compact();
-
- QBinaryJsonPrivate::MutableData *d = nullptr;
- QBinaryJsonPrivate::Object *o = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONOBJECT_P_H
diff --git a/src/corelib/serialization/qbinaryjsonvalue.cpp b/src/corelib/serialization/qbinaryjsonvalue.cpp
deleted file mode 100644
index 7d0bc3d366..0000000000
--- a/src/corelib/serialization/qbinaryjsonvalue.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjsonvalue_p.h"
-#include "qbinaryjsonarray_p.h"
-#include "qbinaryjson_p.h"
-
-#include <qjsonarray.h>
-#include <qjsonobject.h>
-
-QT_BEGIN_NAMESPACE
-
-QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data,
- QBinaryJsonPrivate::Base *parent,
- const QBinaryJsonPrivate::Value &v)
- : t(QJsonValue::Type(uint(v.type)))
-{
- switch (t) {
- case QJsonValue::Undefined:
- case QJsonValue::Null:
- dbl = 0;
- break;
- case QJsonValue::Bool:
- b = v.toBoolean();
- break;
- case QJsonValue::Double:
- dbl = v.toDouble(parent);
- break;
- case QJsonValue::String:
- stringData = v.toString(parent);
- break;
- case QJsonValue::Array:
- case QJsonValue::Object:
- d = data;
- base = v.base(parent);
- break;
- }
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::QBinaryJsonValue(QString string)
- : d(nullptr), t(QJsonValue::String)
-{
- stringData = std::move(string);
-}
-
-QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a)
- : base(a.a), d(a.d), t(QJsonValue::Array)
-{
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o)
- : base(o.o), d(o.d), t(QJsonValue::Object)
-{
- if (d)
- d->ref.ref();
-}
-
-QBinaryJsonValue::~QBinaryJsonValue()
-{
- if (d && !d->ref.deref())
- delete d;
-}
-
-QBinaryJsonValue QBinaryJsonValue::fromJsonValue(const QJsonValue &json)
-{
- switch (json.type()) {
- case QJsonValue::Bool:
- return QBinaryJsonValue(json.toBool());
- case QJsonValue::Double:
- return QBinaryJsonValue(json.toDouble());
- case QJsonValue::String:
- return QBinaryJsonValue(json.toString());
- case QJsonValue::Array:
- return QBinaryJsonArray::fromJsonArray(json.toArray());
- case QJsonValue::Object:
- return QBinaryJsonObject::fromJsonObject(json.toObject());
- case QJsonValue::Null:
- return QBinaryJsonValue(QJsonValue::Null);
- case QJsonValue::Undefined:
- return QBinaryJsonValue(QJsonValue::Undefined);
- }
- Q_UNREACHABLE();
- return QBinaryJsonValue(QJsonValue::Null);
-}
-
-QString QBinaryJsonValue::toString() const
-{
- if (t != QJsonValue::String)
- return QString();
- return stringData;
-}
-
-void QBinaryJsonValue::detach()
-{
- if (!d)
- return;
-
- QBinaryJsonPrivate::MutableData *x = d->clone(base);
- x->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = x;
- base = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
-}
-
-QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qbinaryjsonvalue_p.h b/src/corelib/serialization/qbinaryjsonvalue_p.h
deleted file mode 100644
index c3b943250c..0000000000
--- a/src/corelib/serialization/qbinaryjsonvalue_p.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QBINARYJSONVALUE_P_H
-#define QBINARYJSONVALUE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qjsonvalue.h>
-
-QT_REQUIRE_CONFIG(binaryjson);
-
-QT_BEGIN_NAMESPACE
-
-class QBinaryJsonArray;
-class QBinaryJsonObject;
-
-namespace QBinaryJsonPrivate {
-class ConstData;
-class MutableData;
-class Base;
-class Value;
-class Object;
-class Array;
-}
-
-class Q_CORE_EXPORT QBinaryJsonValue
-{
- Q_DISABLE_COPY(QBinaryJsonValue)
-public:
- explicit QBinaryJsonValue(QJsonValue::Type type) : ui(0), t(type) {}
- explicit QBinaryJsonValue(bool b) : b(b), t(QJsonValue::Bool) {}
- explicit QBinaryJsonValue(double n) : dbl(n), t(QJsonValue::Double) {}
- explicit QBinaryJsonValue(QString s);
- QBinaryJsonValue(const QBinaryJsonArray &a);
- QBinaryJsonValue(const QBinaryJsonObject &o);
-
- ~QBinaryJsonValue();
-
- QBinaryJsonValue(QBinaryJsonValue &&other) noexcept
- : ui(other.ui),
- stringData(std::move(other.stringData)),
- d(other.d),
- t(other.t)
- {
- other.ui = 0;
- other.d = nullptr;
- other.t = QJsonValue::Null;
- }
-
- QBinaryJsonValue &operator =(QBinaryJsonValue &&other) noexcept
- {
- qSwap(stringData, other.stringData);
- qSwap(ui, other.ui);
- qSwap(d, other.d);
- qSwap(t, other.t);
- return *this;
- }
-
- static QBinaryJsonValue fromJsonValue(const QJsonValue &json);
- QJsonValue::Type type() const { return t; }
- bool toBool() const { return (t == QJsonValue::Bool) && b; }
- double toDouble() const { return (t == QJsonValue::Double) ? dbl : 0; }
- QString toString() const;
-
-private:
- friend class QBinaryJsonPrivate::Value;
- friend class QBinaryJsonArray;
- friend class QBinaryJsonObject;
-
- QBinaryJsonValue(QBinaryJsonPrivate::MutableData *d, QBinaryJsonPrivate::Base *parent,
- const QBinaryJsonPrivate::Value &v);
-
- void detach();
-
- union {
- quint64 ui;
- bool b;
- double dbl;
- const QBinaryJsonPrivate::Base *base;
- };
- QString stringData;
- QBinaryJsonPrivate::MutableData *d = nullptr; // needed for Objects and Arrays
- QJsonValue::Type t = QJsonValue::Null;
-};
-
-QT_END_NAMESPACE
-
-#endif // QBINARYJSONVALUE_P_H
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index 2e0de4f4fc..626fb49a70 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborarray.h"
#include "qcborvalue_p.h"
@@ -49,24 +13,30 @@ using namespace QtCbor;
\class QCborArray
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborArray class is used to hold an array of CBOR elements.
+ \compares strong
+ \compareswith strong QCborValueConstRef
+ \endcompareswith
+
This class can be used to hold one sequential container in CBOR (an array).
CBOR is the Concise Binary Object Representation, a very compact form of
binary data encoding that is a superset of JSON. It was created by the IETF
Constrained RESTful Environments (CoRE) WG, which has used it in many new
RFCs. It is meant to be used alongside the
- \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+ \l{RFC 7252}{CoAP protocol}.
QCborArray is very similar to \l QVariantList and \l QJsonArray and its API
is almost identical to those two classes. It can also be converted to and
from those two, though there may be loss of information in some
conversions.
- \sa QCborValue, QCborMap, QJsonArray, QList
+ \sa QCborValue, QCborMap, QJsonArray, QList, {Parsing and displaying CBOR data},
+ {Serialization Converter}, {Saving and Loading a Game}
*/
/*!
@@ -454,7 +424,7 @@ void QCborArray::removeAt(qsizetype i)
bool QCborArray::contains(const QCborValue &value) const
{
for (qsizetype i = 0; i < size(); ++i) {
- int cmp = d->compareElement(i, value);
+ int cmp = d->compareElement(i, value, Comparison::ForEquality);
if (cmp == 0)
return true;
}
@@ -476,9 +446,9 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator==(const QCborArray &other) const
+ \fn bool QCborArray::operator==(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
returns true if both arrays contains the same elements, false otherwise.
For more information on CBOR equality in Qt, see, QCborValue::compare().
@@ -488,9 +458,9 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator!=(const QCborArray &other) const
+ \fn bool QCborArray::operator!=(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
returns true if the two arrays' contents are different, false otherwise.
For more information on CBOR equality in Qt, see, QCborValue::compare().
@@ -500,19 +470,58 @@ bool QCborArray::contains(const QCborValue &value) const
*/
/*!
- \fn bool QCborArray::operator<(const QCborArray &other) const
+ \fn bool QCborArray::operator<(const QCborArray &lhs, const QCborArray &rhs)
- Compares this array and \a other, comparing each element in sequence, and
- returns true if this array should be sorted before \a other, false
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted before \a rhs, false
otherwise.
For more information on CBOR sorting order, see QCborValue::compare().
\sa compare(), QCborValue::operator==(), QCborMap::operator==(),
- operator==(), operator!=()
+ operator==(), operator!=(), operator<=()
*/
/*!
+ \fn bool QCborArray::operator<=(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted before \a rhs, or if both
+ arrays contains the same elements, false otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator<()
+*/
+
+/*!
+ \fn bool QCborArray::operator>(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted after \a rhs, false
+ otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator>=()
+*/
+
+/*!
+ \fn bool QCborArray::operator>=(const QCborArray &lhs, const QCborArray &rhs)
+
+ Compares \a lhs and \a rhs arrays, comparing each element in sequence, and
+ returns true if \a lhs array should be sorted after \a rhs, or if both
+ arrays contains the same elements, false otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=(), operator>()
+*/
+
+/*!
\typedef QCborArray::iterator
A synonym to QCborArray::Iterator.
@@ -713,6 +722,10 @@ void QCborArray::detach(qsizetype reserved)
\brief The QCborArray::Iterator class provides an STL-style non-const iterator for QCborArray.
+ \compares strong
+ \compareswith strong QCborArray::ConstIterator
+ \endcompareswith
+
QCborArray::Iterator allows you to iterate over a QCborArray and to modify
the array item associated with the iterator. If you want to iterate over a
const QCborArray, use QCborArray::ConstIterator instead. It is generally a
@@ -809,7 +822,7 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn QCborValueRef QCborArray::Iterator::operator[](qsizetype j)
+ \fn QCborValueRef QCborArray::Iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at a position \a j steps forward
from the item pointed to by this iterator.
@@ -827,63 +840,63 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborArray::Iterator::operator==(const Iterator &other) const
- \fn bool QCborArray::Iterator::operator==(const ConstIterator &other) const
+ \fn bool QCborArray::Iterator::operator==(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator==(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the array as this
+ Returns \c true if \a lhs points to the same entry in the array as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborArray::Iterator::operator!=(const Iterator &other) const
- \fn bool QCborArray::Iterator::operator!=(const ConstIterator &other) const
+ \fn bool QCborArray::Iterator::operator!=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator!=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the array than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the array than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborArray::Iterator::operator<(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator<(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator<(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator<(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator<=(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator<=(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator<=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator<=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator>(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator>(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator>(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator>(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::Iterator::operator>=(const Iterator& other) const
- \fn bool QCborArray::Iterator::operator>=(const ConstIterator& other) const
+ \fn bool QCborArray::Iterator::operator>=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborArray::Iterator::operator>=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborArray::Iterator &QCborArray::Iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the next item in
the array and returns this iterator.
Calling this function on QCborArray::end() leads to undefined results.
@@ -895,14 +908,14 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::Iterator QCborArray::Iterator::operator++(int)
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the next item
in the array and returns an iterator to the previously current item.
*/
/*!
\fn QCborArray::Iterator &QCborArray::Iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--it}, makes the preceding item current and
returns this iterator.
Calling this function on QCborArray::begin() leads to undefined results.
@@ -914,7 +927,7 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::Iterator QCborArray::Iterator::operator--(int)
\overload
- The postfix -- operator, \c{it--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{it--}, makes the preceding item current and
returns an iterator to the previously current item.
*/
@@ -968,6 +981,10 @@ void QCborArray::detach(qsizetype reserved)
\brief The QCborArray::ConstIterator class provides an STL-style const iterator for QCborArray.
+ \compares strong
+ \compareswith strong QCborArray::Iterator
+ \endcompareswith
+
QCborArray::ConstIterator allows you to iterate over a QCborArray. If you
want to modify the QCborArray as you iterate over it, use
QCborArray::Iterator instead. It is generally good practice to use
@@ -1055,7 +1072,7 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn const QCborValueRef QCborArray::ConstIterator::operator[](qsizetype j)
+ \fn QCborValueRef QCborArray::ConstIterator::operator[](qsizetype j) const
Returns the item at a position \a j steps forward from the item pointed to
by this iterator.
@@ -1067,63 +1084,57 @@ void QCborArray::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborArray::ConstIterator::operator==(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the array as this
+ Returns \c true if \a lhs points to the same entry in the array as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborArray::ConstIterator::operator!=(const Iterator &o) const
- \fn bool QCborArray::ConstIterator::operator!=(const ConstIterator &o) const
+ \fn bool QCborArray::ConstIterator::operator!=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a o points to a different entry in the array than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the array than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborArray::ConstIterator::operator<(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator<=(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator>(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborArray::ConstIterator::operator>=(const Iterator &other) const
- \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the array pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the array pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the next item in
the array and returns this iterator.
Calling this function on QCborArray::end() leads to undefined results.
@@ -1135,14 +1146,14 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::ConstIterator QCborArray::ConstIterator::operator++(int)
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the next item
in the array and returns an iterator to the previously current item.
*/
/*!
\fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--it}, makes the preceding item current and
returns this iterator.
Calling this function on QCborArray::begin() leads to undefined results.
@@ -1154,7 +1165,7 @@ void QCborArray::detach(qsizetype reserved)
\fn QCborArray::ConstIterator QCborArray::ConstIterator::operator--(int)
\overload
- The postfix -- operator, \c{it--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{it--}, makes the preceding item current and
returns an iterator to the previously current item.
*/
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index 8d0aceac33..481f316f33 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORARRAY_H
#define QCBORARRAY_H
@@ -49,13 +13,15 @@ QT_BEGIN_NAMESPACE
class QJsonArray;
class QDataStream;
+namespace QJsonPrivate { class Variant; }
+
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborArray
{
public:
class ConstIterator;
class Iterator {
- mutable QCborValueRef item;
+ QCborValueRef item {};
friend class ConstIterator;
friend class QCborArray;
Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
@@ -66,8 +32,8 @@ public:
typedef QCborValueRef reference;
typedef QCborValueRef *pointer;
- Q_DECL_CONSTEXPR Iterator() = default;
- Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ constexpr Iterator() = default;
+ constexpr Iterator(const Iterator &) = default;
Iterator &operator=(const Iterator &other)
{
// rebind the reference
@@ -77,21 +43,23 @@ public:
}
QCborValueRef operator*() const { return item; }
- QCborValueRef *operator->() const { return &item; }
- QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
-
+ QCborValueRef *operator->() { return &item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+ QCborValueRef operator[](qsizetype j) const { return { item.d, item.i + j }; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
Iterator &operator++() { ++item.i; return *this; }
Iterator operator++(int) { Iterator n = *this; ++item.i; return n; }
Iterator &operator--() { item.i--; return *this; }
@@ -101,10 +69,57 @@ public:
Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + j }); }
Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - j }); }
qsizetype operator-(Iterator j) const { return item.i - j.item.i; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static bool comparesEqual_helper(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator)
+ friend bool comparesEqual(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator, ConstIterator)
};
class ConstIterator {
- QCborValueRef item;
+ QCborValueConstRef item;
friend class Iterator;
friend class QCborArray;
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
@@ -115,8 +130,8 @@ public:
typedef const QCborValueRef reference;
typedef const QCborValueRef *pointer;
- Q_DECL_CONSTEXPR ConstIterator() = default;
- Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ constexpr ConstIterator() = default;
+ constexpr ConstIterator(const ConstIterator &) = default;
ConstIterator &operator=(const ConstIterator &other)
{
// rebind the reference
@@ -125,22 +140,23 @@ public:
return *this;
}
- const QCborValueRef operator*() const { return item; }
- const QCborValueRef *operator->() const { return &item; }
- const QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
-
+ QCborValueConstRef operator*() const { return item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+ QCborValueConstRef operator[](qsizetype j) const { return QCborValueRef{ item.d, item.i + j }; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
ConstIterator &operator++() { ++item.i; return *this; }
ConstIterator operator++(int) { ConstIterator n = *this; ++item.i; return n; }
ConstIterator &operator--() { item.i--; return *this; }
@@ -150,6 +166,31 @@ public:
ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + j }); }
ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - j }); }
qsizetype operator-(ConstIterator j) const { return item.i - j.item.i; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const ConstIterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(ConstIterator)
};
typedef qsizetype size_type;
@@ -174,7 +215,7 @@ public:
void swap(QCborArray &other) noexcept
{
- qSwap(d, other.d);
+ d.swap(other.d);
}
QCborValue toCborValue() const { return *this; }
@@ -214,19 +255,11 @@ public:
bool contains(const QCborValue &value) const;
int compare(const QCborArray &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborArray &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborArray &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborArray &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborArray &other) const
{ return compare(other) < 0; }
#endif
@@ -265,14 +298,58 @@ public:
static QCborArray fromStringList(const QStringList &list);
static QCborArray fromVariantList(const QVariantList &list);
static QCborArray fromJsonArray(const QJsonArray &array);
+ static QCborArray fromJsonArray(QJsonArray &&array) noexcept;
QVariantList toVariantList() const;
QJsonArray toJsonArray() const;
private:
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual(const QCborArray &lhs, const QCborArray &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborArray &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborArray &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray, QCborValue)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborArray &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborArray &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborArray, QCborValueConstRef)
+
void detach(qsizetype reserve = 0);
friend QCborValue;
friend QCborValueRef;
+ friend class QJsonPrivate::Variant;
explicit QCborArray(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -284,6 +361,7 @@ inline QCborValue::QCborValue(QCborArray &&a)
{
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
inline QCborArray QCborValueRef::toArray() const
{
return concrete().toArray();
@@ -293,6 +371,17 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const
{
return concrete().toArray(a);
}
+#endif
+
+inline QCborArray QCborValueConstRef::toArray() const
+{
+ return concrete().toArray();
+}
+
+inline QCborArray QCborValueConstRef::toArray(const QCborArray &a) const
+{
+ return concrete().toArray(a);
+}
Q_CORE_EXPORT size_t qHash(const QCborArray &array, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborcommon.cpp b/src/corelib/serialization/qcborcommon.cpp
index b29e1f1bf6..b3d4f70aa2 100644
--- a/src/corelib/serialization/qcborcommon.cpp
+++ b/src/corelib/serialization/qcborcommon.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#define CBOR_NO_ENCODER_API
#define CBOR_NO_PARSER_API
@@ -46,11 +10,14 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QCborTag)
+
#include <cborerrorstrings.c>
/*!
\headerfile <QtCborCommon>
-
+ \inmodule QtCore
+ \ingroup qtserialization
\brief The <QtCborCommon> header contains definitions common to both the
streaming classes (QCborStreamReader and QCborStreamWriter) and to
QCborValue.
@@ -145,7 +112,7 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
\value PositiveBignum A positive number of arbitrary length, encoded as a byte array in
network byte order. For example, the number 2\sup{64} is represented by
a byte array containing the byte value 0x01 followed by 8 zero bytes.
- \value NegativeBignum A negative number of arbirary length, encoded as the absolute value
+ \value NegativeBignum A negative number of arbitrary length, encoded as the absolute value
of that number, minus one. For example, a byte array containing
byte value 0x02 followed by 8 zero bytes represents the number
-2\sup{65} - 1.
@@ -153,11 +120,11 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
is the exponent of the power of 10, the second the integral
mantissa. The value 273.15 would be encoded as array \c{[-2, 27315]}.
\value Bigfloat Similar to Decimal, but the exponent is a power of 2 instead.
- \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Mac0 A \c Mac0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Mac0 A \c Mac0 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Sign1 A \c Sign1 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Sign1 A \c Sign1 map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
\value ExpectedBase64url Indicates that the byte array should be encoded using Base64url
if the stream is converted to JSON.
@@ -172,13 +139,13 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
\value RegularExpression Indicates that the string contains a Perl-Compatible Regular
Expression pattern.
\value MimeMessage Indicates that the string contains a MIME message (according to
- \l{https://tools.ietf.org/html/rfc2045}){RFC 2045}.
+ \l{RFC 2045}).
\value Uuid Indicates that the byte array contains a UUID.
- \value COSE_Encrypt An \c Encrypt map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Encrypt An \c Encrypt map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Mac A \c Mac map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Mac A \c Mac map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
- \value COSE_Sign A \c Sign map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ \value COSE_Sign A \c Sign map as specified by \l{RFC 8152}
(CBOR Object Signing and Encryption).
\value Signature No change in interpretation; this tag can be used as the outermost
tag in a CBOR stream as the file header.
@@ -205,14 +172,16 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
/*!
\class QCborError
\inmodule QtCore
- \inheaderfile <QtCborCommon>
+ \inheaderfile QtCborCommon
\reentrant
\since 5.12
\brief The QCborError class holds the error condition found while parsing or
validating a CBOR stream.
- \sa QCborStreamReader, QCborValue, QCborParserError
+ \sa QCborStreamReader, QCborValue, QCborParserError,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -230,8 +199,8 @@ QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
element.
\value UnexpectedBreak The CBOR stream contains a Break where it is not allowed (data is
corrupt and the error is not recoverable).
- \value UnknownType The CBOR stream contains an unknown/unparseable Type (data is corrupt
- and the and the error is not recoverable).
+ \value UnknownType The CBOR stream contains an unknown/unparsable Type (data is corrupt
+ and the error is not recoverable).
\value IllegalType The CBOR stream contains a known type in a position it is not allowed
to exist (data is corrupt and the error is not recoverable).
\value IllegalNumber The CBOR stream appears to be encoding a number larger than 64-bit
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
index 1497da3d2e..bd7a93dfe7 100644
--- a/src/corelib/serialization/qcborcommon.h
+++ b/src/corelib/serialization/qcborcommon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORCOMMON_H
#define QCBORCOMMON_H
@@ -50,7 +14,6 @@
/* X11 headers use these values too, but as defines */
#if defined(False) && defined(True)
-# define QT_X11_DEFINES_FOUND 1
# undef True
# undef False
#endif
@@ -133,9 +96,9 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
#endif
-#if !defined(QT_NO_DEBUG_STREAM)
-QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
-QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
+#if !defined(QT_NO_DATASTREAM)
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, QCborSimpleType st);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st);
#endif
inline size_t qHash(QCborSimpleType tag, size_t seed = 0)
@@ -152,7 +115,7 @@ enum class QCborNegativeInteger : quint64 {};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QCborTag)
+QT_DECL_METATYPE_EXTERN(QCborTag, Q_CORE_EXPORT)
// To avoid changing namespace we need to reinstate defines, even though our .cpp
// will then have to remove them again.
diff --git a/src/corelib/serialization/qcborcommon_p.h b/src/corelib/serialization/qcborcommon_p.h
index 9b7f4b7099..69e80cb9d6 100644
--- a/src/corelib/serialization/qcborcommon_p.h
+++ b/src/corelib/serialization/qcborcommon_p.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORCOMMON_P_H
#define QCBORCOMMON_P_H
#include "qcborcommon.h"
+#include "private/qglobal_p.h"
//
// W A R N I N G
diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp
index 2e92dab0a4..e89afc4827 100644
--- a/src/corelib/serialization/qcbordiagnostic.cpp
+++ b/src/corelib/serialization/qcbordiagnostic.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -49,6 +13,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace {
class DiagnosticNotation
{
@@ -75,7 +41,7 @@ private:
++dn->nestingLevel;
static const char indent[IndentationWidth + 1] = " ";
if (dn->opts & QCborValue::LineWrapped)
- dn->separator += QLatin1String(indent, IndentationWidth);
+ dn->separator += QLatin1StringView(indent, IndentationWidth);
}
~Nest()
{
@@ -86,7 +52,7 @@ private:
};
DiagnosticNotation(QCborValue::DiagnosticNotationOptions opts_)
- : separator(QLatin1String(opts_ & QCborValue::LineWrapped ? "\n" : "")), opts(opts_)
+ : separator(opts_ & QCborValue::LineWrapped ? "\n"_L1 : ""_L1), opts(opts_)
{
byteArrayFormatStack.push(int(QCborKnownTags::ExpectedBase16));
}
@@ -109,11 +75,11 @@ static QString makeFpString(double d)
} else if (convertDoubleTo(d, &v)) {
s = QString::fromLatin1("%1.0").arg(v);
if (d < 0)
- s.prepend(QLatin1Char('-'));
+ s.prepend(u'-');
} else {
s = QString::number(d, 'g', QLocale::FloatingPointShortest);
if (!s.contains(u'.') && !s.contains(u'e'))
- s += QLatin1Char('.');
+ s += u'.';
}
return s;
}
@@ -131,7 +97,7 @@ static bool isByteArrayEncodingTag(QCborTag tag)
void DiagnosticNotation::appendString(const QString &s)
{
- result += QLatin1Char('"');
+ result += u'"';
const QChar *begin = s.begin();
const QChar *end = s.end();
@@ -161,7 +127,7 @@ void DiagnosticNotation::appendString(const QString &s)
};
int buflen = 2;
QChar buf[10];
- buf[0] = QLatin1Char('\\');
+ buf[0] = u'\\';
buf[1] = QChar::Null;
char16_t uc = ptr->unicode();
@@ -203,18 +169,18 @@ void DiagnosticNotation::appendString(const QString &s)
begin = ptr + 1;
}
- result += QLatin1Char('"');
+ result += u'"';
}
void DiagnosticNotation::appendArray(const QCborArray &a)
{
- result += QLatin1Char('[');
+ result += u'[';
// length 2 (including the space) when not line wrapping
- QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ QLatin1StringView commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
{
Nest n(this);
- QLatin1String comma;
+ QLatin1StringView comma;
for (auto v : a) {
result += comma + separator;
comma = commaValue;
@@ -222,28 +188,28 @@ void DiagnosticNotation::appendArray(const QCborArray &a)
}
}
- result += separator + QLatin1Char(']');
+ result += separator + u']';
}
void DiagnosticNotation::appendMap(const QCborMap &m)
{
- result += QLatin1Char('{');
+ result += u'{';
// length 2 (including the space) when not line wrapping
- QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ QLatin1StringView commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
{
Nest n(this);
- QLatin1String comma;
+ QLatin1StringView comma;
for (auto v : m) {
result += comma + separator;
comma = commaValue;
appendValue(v.first);
- result += QLatin1String(": ");
+ result += ": "_L1;
appendValue(v.second);
}
}
- result += separator + QLatin1Char('}');
+ result += separator + u'}';
};
void DiagnosticNotation::appendValue(const QCborValue &v)
@@ -276,16 +242,16 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
case QCborValue::Map:
return appendMap(v.toMap());
case QCborValue::False:
- result += QLatin1String("false");
+ result += "false"_L1;
return;
case QCborValue::True:
- result += QLatin1String("true");
+ result += "true"_L1;
return;
case QCborValue::Null:
- result += QLatin1String("null");
+ result += "null"_L1;
return;
case QCborValue::Undefined:
- result += QLatin1String("undefined");
+ result += "undefined"_L1;
return;
case QCborValue::Double:
result += makeFpString(v.toDouble());
@@ -305,9 +271,9 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
bool byteArrayFormat = opts & QCborValue::ExtendedFormat && isByteArrayEncodingTag(v.tag());
if (byteArrayFormat)
byteArrayFormatStack.push(int(v.tag()));
- result += QString::number(quint64(v.tag())) + QLatin1Char('(');
+ result += QString::number(quint64(v.tag())) + u'(';
appendValue(v.taggedValue());
- result += QLatin1Char(')');
+ result += u')';
if (byteArrayFormat)
byteArrayFormatStack.pop();
} else {
@@ -326,7 +292,7 @@ void DiagnosticNotation::appendValue(const QCborValue &v)
would be possible.
CBOR diagnostic notation is specified by
- \l{https://tools.ietf.org/html/rfc7049#section-6}{section 6} of RFC 7049.
+ \l{RFC 7049, section 6}{section 6} of RFC 7049.
It is a text representation of the CBOR stream and it is very similar to
JSON, but it supports the CBOR types not found in JSON. The extended format
enabled by the \l{DiagnosticNotationOption}{ExtendedFormat} flag is
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 34c8c72059..038e0d61ce 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcbormap.h"
#include "qcborvalue_p.h"
@@ -48,17 +12,22 @@ using namespace QtCbor;
\class QCborMap
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborMap class is used to hold an associative container representable in CBOR.
+ \compares strong
+ \compareswith strong QCborValue QCborValueConstRef
+ \endcompareswith
+
This class can be used to hold an associative container in CBOR, a map
between a key and a value type. CBOR is the Concise Binary Object
Representation, a very compact form of binary data encoding that is a
superset of JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ be used alongside the \l{RFC 7252}{CoAP
protocol}.
Unlike JSON and \l QVariantMap, CBOR map keys can be of any type, not just
@@ -82,7 +51,9 @@ using namespace QtCbor;
stringified using a one-way method that the conversion back to QCborMap
will not undo.
- \sa QCborArray, QCborValue, QJsonDocument, QVariantMap
+ \sa QCborArray, QCborValue, QJsonDocument, QVariantMap,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -328,7 +299,7 @@ QList<QCborValue> QCborMap::keys() const
duplicate keys is usually an indication of a problem in the sender.
\sa operator[](qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
/*!
@@ -350,7 +321,8 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
- operator[](QLatin1String), operator[](const QString &), operator[](const QCborOperator[] &)
+ operator[](QLatin1StringView), operator[](const QString &),
+ operator[](const QCborOperator[] &)
*/
/*!
@@ -366,7 +338,7 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), operator[](qint64), find(qint64), contains(qint64),
- take(QLatin1String), take(const QString &), take(const QCborValue &), insert()
+ take(QLatin1StringView), take(const QString &), take(const QCborValue &), insert()
*/
/*!
@@ -382,7 +354,7 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), operator[](qint64), find(qint64), contains(qint64)
- remove(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ remove(QLatin1StringView), remove(const QString &), remove(const QCborValue &)
*/
/*!
@@ -393,7 +365,7 @@ QList<QCborValue> QCborMap::keys() const
are simpler to encode and decode.
\sa value(qint64), operator[](qint64), find(qint64), remove(qint64),
- contains(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ contains(QLatin1StringView), remove(const QString &), remove(const QCborValue &)
*/
/*!
@@ -418,22 +390,15 @@ QList<QCborValue> QCborMap::keys() const
is usually an indication of a problem in the sender.
\sa value(qint64), find(qint64), contains(qint64), remove(qint64),
- operator[](QLatin1String), operator[](const QString &), operator[](const QCborValue &)
+ operator[](QLatin1StringView), operator[](const QString &), operator[](const QCborValue &)
*/
QCborValueRef QCborMap::operator[](qint64 key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
- \fn QCborValue QCborMap::value(QLatin1String key) const
+ \fn QCborValue QCborMap::value(QLatin1StringView key) const
\overload
Returns the QCborValue element in this map that corresponds to key \a key,
@@ -450,13 +415,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa operator[](QLatin1String), find(QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa operator[](QLatin1StringView), find(QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView)
value(qint64), value(const QString &), value(const QCborValue &)
*/
/*!
- \fn QCborValue QCborMap::operator[](QLatin1String key) const
+ \fn QCborValue QCborMap::operator[](QLatin1StringView key) const
\overload
Returns the QCborValue element in this map that corresponds to key \a key,
@@ -473,13 +438,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), find(QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), find(QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView)
operator[](qint64), operator[](const QString &), operator[](const QCborOperator[] &)
*/
/*!
- \fn QCborValue QCborMap::take(QLatin1String key)
+ \fn QCborValue QCborMap::take(QLatin1StringView key)
Removes the key \a key and the corresponding value from the map and returns
the value, if it is found. If the map contains no such key, this function does nothing.
@@ -490,12 +455,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String),
- take(qint64), take(const QString &), take(const QCborValue &), insert()
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ contains(QLatin1StringView), take(qint64), take(const QString &),
+ take(const QCborValue &), insert()
*/
/*!
- \fn void QCborMap::remove(QLatin1String key)
+ \fn void QCborMap::remove(QLatin1StringView key)
\overload
Removes the key \a key and the corresponding value from the map, if it is
@@ -507,19 +473,21 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String)
- remove(qint64), remove(const QString &), remove(const QCborValue &)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ contains(QLatin1StringView), remove(qint64), remove(const QString &),
+ remove(const QCborValue &)
*/
/*!
- \fn bool QCborMap::contains(QLatin1String key) const
+ \fn bool QCborMap::contains(QLatin1StringView key) const
\overload
Returns true if this map contains a key-value pair identified by key \a
key.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), remove(QLatin1String),
- contains(qint64), remove(const QString &), remove(const QCborValue &)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ remove(QLatin1StringView), contains(qint64), remove(const QString &),
+ remove(const QCborValue &)
*/
/*!
@@ -544,19 +512,13 @@ QCborValueRef QCborMap::operator[](qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), find(QLatin1String), contains(QLatin1String), remove(QLatin1String),
- operator[](qint64), operator[](const QString &), operator[](const QCborValue &)
+ \sa value(QLatin1StringView), find(QLatin1StringView), contains(QLatin1StringView),
+ remove(QLatin1StringView), operator[](qint64), operator[](const QString &),
+ operator[](const QCborValue &)
*/
-QCborValueRef QCborMap::operator[](QLatin1String key)
+QCborValueRef QCborMap::operator[](QLatin1StringView key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -579,7 +541,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa operator[](const QString &), find(const QString &), constFind(const QString &),
remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
/*!
@@ -602,7 +564,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), find(const QString &), constFind(const QString &),
remove(const QString &), contains(const QString &)
- operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ operator[](qint64), operator[](QLatin1StringView), operator[](const QCborOperator[] &)
*/
/*!
@@ -617,8 +579,9 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QString &), operator[](const QString &), find(const QString &), contains(const QString &),
- take(QLatin1String), take(qint64), take(const QCborValue &), insert()
+ \sa value(const QString &), operator[](const QString &), find(const QString &),
+ contains(const QString &), take(QLatin1StringView), take(qint64),
+ take(const QCborValue &), insert()
*/
/*!
@@ -636,7 +599,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), operator[](const QString &), find(const QString &),
contains(const QString &)
- remove(qint64), remove(QLatin1String), remove(const QCborValue &)
+ remove(qint64), remove(QLatin1StringView), remove(const QCborValue &)
*/
/*!
@@ -648,7 +611,7 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
\sa value(const QString &), operator[](const QString &), find(const QString &),
remove(const QString &),
- contains(qint64), remove(QLatin1String), remove(const QCborValue &)
+ contains(qint64), remove(QLatin1StringView), remove(const QCborValue &)
*/
/*!
@@ -673,19 +636,13 @@ QCborValueRef QCborMap::operator[](QLatin1String key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QString &), find(const QString &), contains(const QString &), remove(const QString &),
- operator[](qint64), operator[](QLatin1String), operator[](const QCborValue &)
+ \sa value(const QString &), find(const QString &), contains(const QString &),
+ remove(const QString &), operator[](qint64), operator[](QLatin1StringView),
+ operator[](const QCborValue &)
*/
QCborValueRef QCborMap::operator[](const QString & key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -707,7 +664,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa operator[](const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &)
- value(qint64), value(QLatin1String), value(const QString &)
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
/*!
@@ -729,7 +686,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &)
- operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ operator[](qint64), operator[](QLatin1StringView), operator[](const QCborOperator[] &)
*/
/*!
@@ -744,8 +701,9 @@ QCborValueRef QCborMap::operator[](const QString & key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &), contains(const QCborValue &),
- take(QLatin1String), take(const QString &), take(qint64), insert()
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
+ contains(const QCborValue &), take(QLatin1StringView), take(const QString &),
+ take(qint64), insert()
*/
/*!
@@ -762,7 +720,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
contains(const QCborValue &)
- remove(qint64), remove(QLatin1String), remove(const QString &)
+ remove(qint64), remove(QLatin1StringView), remove(const QString &)
*/
/*!
@@ -773,7 +731,7 @@ QCborValueRef QCborMap::operator[](const QString & key)
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
remove(const QCborValue &),
- contains(qint64), remove(QLatin1String), remove(const QString &)
+ contains(qint64), remove(QLatin1StringView), remove(const QString &)
*/
/*!
@@ -798,19 +756,21 @@ QCborValueRef QCborMap::operator[](const QString & key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(const QCborValue &), find(const QCborValue &), contains(const QCborValue &), remove(const QCborValue &),
- operator[](qint64), operator[](QLatin1String), operator[](const QString &)
+ \sa value(const QCborValue &), find(const QCborValue &), contains(const QCborValue &),
+ remove(const QCborValue &), operator[](qint64), operator[](QLatin1StringView),
+ operator[](const QString &)
*/
QCborValueRef QCborMap::operator[](const QCborValue &key)
{
- auto it = find(key);
- if (it == constEnd()) {
- // insert element
- detach(it.item.i + 2);
- d->append(key);
- d->append(Undefined{});
- }
- return { d.data(), it.item.i };
+ return QCborContainerPrivate::findOrAddMapKey<const QCborValue &>(*this, key);
+}
+
+template <typename KeyType> inline QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborMap &map, KeyType key)
+{
+ QCborValueRef result = findOrAddMapKey<KeyType>(map.d.data(), key);
+ map.d = result.d;
+ return result;
}
/*!
@@ -829,8 +789,8 @@ QCborValueRef QCborMap::operator[](const QCborValue &key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(qint64), operator[](qint64), constFind(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ \sa value(qint64), operator[](qint64), constFind(qint64), remove(qint64), contains(qint64),
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
QCborMap::iterator QCborMap::find(qint64 key)
{
@@ -840,8 +800,8 @@ QCborMap::iterator QCborMap::find(qint64 key)
}
/*!
- \fn QCborMap::iterator QCborMap::find(QLatin1String key)
- \fn QCborMap::const_iterator QCborMap::find(QLatin1String key) const
+ \fn QCborMap::iterator QCborMap::find(QLatin1StringView key)
+ \fn QCborMap::const_iterator QCborMap::find(QLatin1StringView key) const
\overload
Returns a map iterator to the key-value pair whose key is \a key, if the
@@ -853,11 +813,11 @@ QCborMap::iterator QCborMap::find(qint64 key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), constFind(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), constFind(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView),
value(qint64), value(const QString &), value(const QCborValue &)
*/
-QCborMap::iterator QCborMap::find(QLatin1String key)
+QCborMap::iterator QCborMap::find(QLatin1StringView key)
{
detach();
auto it = constFind(key);
@@ -879,8 +839,8 @@ QCborMap::iterator QCborMap::find(QLatin1String key)
is usually an indication of a problem in the sender.
\sa value(const QString &), operator[](const QString &), constFind(const QString &),
- remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ remove(const QString &), contains(const QString &),
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
QCborMap::iterator QCborMap::find(const QString & key)
{
@@ -904,8 +864,8 @@ QCborMap::iterator QCborMap::find(const QString & key)
is usually an indication of a problem in the sender.
\sa value(const QCborValue &), operator[](const QCborValue &), constFind(const QCborValue &),
- remove(const QCborValue &), contains(const QCborValue &)
- value(qint64), value(QLatin1String), value(const QString &)
+ remove(const QCborValue &), contains(const QCborValue &),
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
QCborMap::iterator QCborMap::find(const QCborValue &key)
{
@@ -927,17 +887,12 @@ QCborMap::iterator QCborMap::find(const QCborValue &key)
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(qint64), operator[](qint64), find(qint64), remove(qint64), contains(qint64)
- value(QLatin1String), value(const QString &), value(const QCborValue &)
+ \sa value(qint64), operator[](qint64), find(qint64), remove(qint64), contains(qint64),
+ value(QLatin1StringView), value(const QString &), value(const QCborValue &)
*/
QCborMap::const_iterator QCborMap::constFind(qint64 key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- const auto &e = d->elements.at(i);
- if (e.type == QCborValue::Integer && e.value == key)
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(key) : constEnd();
}
/*!
@@ -952,17 +907,13 @@ QCborMap::const_iterator QCborMap::constFind(qint64 key) const
stream with them. They are usually not permitted and having duplicate keys
is usually an indication of a problem in the sender.
- \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String),
- remove(QLatin1String), contains(QLatin1String)
+ \sa value(QLatin1StringView), operator[](QLatin1StringView), find(QLatin1StringView),
+ remove(QLatin1StringView), contains(QLatin1StringView),
value(qint64), value(const QString &), value(const QCborValue &)
*/
-QCborMap::const_iterator QCborMap::constFind(QLatin1String key) const
+QCborMap::const_iterator QCborMap::constFind(QLatin1StringView key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- if (d->stringEqualsElement(i, key))
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(key) : constEnd();
}
/*!
@@ -978,16 +929,12 @@ QCborMap::const_iterator QCborMap::constFind(QLatin1String key) const
is usually an indication of a problem in the sender.
\sa value(const QString &), operator[](const QString &), find(const QString &),
- remove(const QString &), contains(const QString &)
- value(qint64), value(QLatin1String), value(const QCborValue &)
+ remove(const QString &), contains(const QString &),
+ value(qint64), value(QLatin1StringView), value(const QCborValue &)
*/
-QCborMap::const_iterator QCborMap::constFind(const QString & key) const
+QCborMap::const_iterator QCborMap::constFind(const QString &key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- if (d->stringEqualsElement(i, key))
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey(qToStringViewIgnoringNull(key)) : constEnd();
}
/*!
@@ -1004,16 +951,11 @@ QCborMap::const_iterator QCborMap::constFind(const QString & key) const
\sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
remove(const QCborValue &), contains(const QCborValue &),
- value(qint64), value(QLatin1String), value(const QString &)
+ value(qint64), value(QLatin1StringView), value(const QString &)
*/
QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
{
- for (qsizetype i = 0; i < 2 * size(); i += 2) {
- int cmp = d->compareElement(i, key);
- if (cmp == 0)
- return { d.data(), i + 1 };
- }
- return constEnd();
+ return d ? d->findCborMapKey<const QCborValue &>(key) : constEnd();
}
/*!
@@ -1031,7 +973,7 @@ QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
*/
/*!
- \fn QCborMap::iterator QCborMap::insert(QLatin1String key, const QCborValue &value)
+ \fn QCborMap::iterator QCborMap::insert(QLatin1StringView key, const QCborValue &value)
\overload
Inserts the key \a key and value \a value into this map and returns a map
@@ -1040,8 +982,8 @@ QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
If the map already had a key equal to \a key, its value will be overwritten
by \a value.
- \sa erase(), remove(QLatin1String), value(QLatin1String), operator[](QLatin1String),
- find(QLatin1String), contains(QLatin1String), take(QLatin1String), extract()
+ \sa erase(), remove(QLatin1StringView), value(QLatin1StringView), operator[](QLatin1StringView),
+ find(QLatin1StringView), contains(QLatin1StringView), take(QLatin1StringView), extract()
*/
/*!
@@ -1167,10 +1109,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator==(const QCborMap &other) const
+ \fn bool QCborMap::operator==(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if the two maps contains the same elements in the same order,
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if the two maps contain the same elements in the same order,
false otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1186,10 +1128,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator!=(const QCborMap &other) const
+ \fn bool QCborMap::operator!=(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if the two maps contains any different elements or elements in
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if the two maps contain any different elements or elements in
different orders, false otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1205,10 +1147,10 @@ QCborValue QCborMap::extract(iterator it)
*/
/*!
- \fn bool QCborMap::operator<(const QCborMap &other) const
+ \fn bool QCborMap::operator<(const QCborMap &lhs, const QCborMap &rhs)
- Compares this map and \a other, comparing each element in sequence, and
- returns true if this map should be sorted before \a other, false
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted before \a rhs, false
otherwise.
Note that CBOR maps are unordered, which means that two maps containing the
@@ -1223,6 +1165,65 @@ QCborValue QCborMap::extract(iterator it)
operator==(), operator!=()
*/
+/*!
+ \fn bool QCborMap::operator<=(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted before \a rhs or
+ if the two maps contain the same elements in the same order, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::operator>=(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted after \a rhs or
+ if the two maps contain the same elements in the same order, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::operator>(const QCborMap &lhs, const QCborMap &rhs)
+
+ Compares \a lhs and \a rhs maps, comparing each element in sequence, and
+ returns true if \a lhs map should be sorted after \a rhs, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
void QCborMap::detach(qsizetype reserved)
{
d = QCborContainerPrivate::detach(d.data(), reserved ? reserved : size() * 2);
@@ -1237,6 +1238,10 @@ void QCborMap::detach(qsizetype reserved)
\brief The QCborMap::Iterator class provides an STL-style non-const iterator for QCborMap.
+ \compares strong
+ \compareswith strong ConstIterator
+ \endcompareswith
+
QCborMap::Iterator allows you to iterate over a QCborMap and to modify the
value (but not the key) stored under a particular key. If you want to
iterate over a const QCborMap, you should use QCborMap::ConstIterator. It
@@ -1358,63 +1363,63 @@ void QCborMap::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborMap::Iterator::operator==(const Iterator &other) const
- \fn bool QCborMap::Iterator::operator==(const ConstIterator &other) const
+ \fn bool QCborMap::Iterator::operator==(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator==(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the map as this
+ Returns \c true if \a lhs points to the same entry in the map as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborMap::Iterator::operator!=(const Iterator &other) const
- \fn bool QCborMap::Iterator::operator!=(const ConstIterator &other) const
+ \fn bool QCborMap::Iterator::operator!=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator!=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the map than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the map than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborMap::Iterator::operator<(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator<(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator<(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator<(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator<=(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator<=(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator<=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator<=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator>(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator>(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator>(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator>(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::Iterator::operator>=(const Iterator& other) const
- \fn bool QCborMap::Iterator::operator>=(const ConstIterator& other) const
+ \fn bool QCborMap::Iterator::operator>=(const Iterator &lhs, const Iterator &rhs)
+ \fn bool QCborMap::Iterator::operator>=(const Iterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborMap::Iterator &QCborMap::Iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the next item in
the map and returns this iterator.
Calling this function on QCborMap::end() leads to undefined results.
@@ -1426,14 +1431,14 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::Iterator QCborMap::Iterator::operator++(int)
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the next item in
the map and returns an iterator to the previously current item.
*/
/*!
\fn QCborMap::Iterator QCborMap::Iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--i}, makes the preceding item current and
returns this iterator.
Calling this function on QCborMap::begin() leads to undefined results.
@@ -1445,7 +1450,7 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::Iterator QCborMap::Iterator::operator--(int)
\overload
- The postfix -- operator, \c{i--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{i--}, makes the preceding item current and
returns an iterator pointing to the previously current item.
*/
@@ -1503,6 +1508,10 @@ void QCborMap::detach(qsizetype reserved)
\brief The QCborMap::ConstIterator class provides an STL-style const iterator for QCborMap.
+ \compares strong
+ \compareswith strong Iterator
+ \endcompareswith
+
QCborMap::ConstIterator allows you to iterate over a QCborMap. If you want
to modify the QCborMap as you iterate over it, you must use
QCborMap::Iterator instead. It is generally good practice to use
@@ -1591,7 +1600,7 @@ void QCborMap::detach(qsizetype reserved)
/*!
\fn QCborMap::ConstIterator::value_type QCborMap::ConstIterator::operator*() const
- Returns a pair containing the curent item's key and value.
+ Returns a pair containing the current item's key and value.
\sa key(), value()
*/
@@ -1603,63 +1612,57 @@ void QCborMap::detach(qsizetype reserved)
*/
/*!
- \fn bool QCborMap::ConstIterator::operator==(const ConstIterator &other) const
- \fn bool QCborMap::ConstIterator::operator==(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator==(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to the same entry in the map as this
+ Returns \c true if \a lhs points to the same entry in the map as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QCborMap::ConstIterator::operator!=(const ConstIterator &other) const
- \fn bool QCborMap::ConstIterator::operator!=(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator!=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if \a other points to a different entry in the map than
- this iterator; otherwise returns \c false.
+ Returns \c true if \a lhs points to a different entry in the map than
+ \a rhs iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QCborMap::ConstIterator::operator<(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator<=(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs before or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs before or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator>(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after the entry pointed to by the \a other iterator.
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after the entry pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QCborMap::ConstIterator::operator>=(const Iterator &other) const
- \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &lhs, const ConstIterator &rhs)
- Returns \c true if the entry in the map pointed to by this iterator
- occurs after or is the same entry as is pointed to by the \a other
+ Returns \c true if the entry in the map pointed to by \a lhs iterator
+ occurs after or is the same entry as is pointed to by the \a rhs
iterator.
*/
/*!
\fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the next item in
the map and returns this iterator.
Calling this function on QCborMap::end() leads to undefined results.
@@ -1671,14 +1674,14 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::ConstIterator QCborMap::ConstIterator::operator++(int)
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the next item in
the map and returns an iterator to the previously current item.
*/
/*!
\fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item current and
+ The prefix \c{--} operator, \c{--i}, makes the preceding item current and
returns this iterator.
Calling this function on QCborMap::begin() leads to undefined results.
@@ -1690,7 +1693,7 @@ void QCborMap::detach(qsizetype reserved)
\fn QCborMap::ConstIterator QCborMap::ConstIterator::operator--(int)
\overload
- The postfix -- operator, \c{i--}, makes the preceding item current and
+ The postfix \c{--} operator, \c{i--}, makes the preceding item current and
returns an iterator pointing to the previously current item.
*/
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 7e1a4cb485..d2fd769240 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORMAP_H
#define QCBORMAP_H
@@ -47,37 +11,36 @@
QT_BEGIN_NAMESPACE
-template <class Key, class T> class QMap;
-typedef QMap<QString, QVariant> QVariantMap;
-template <class Key, class T> class QHash;
-typedef QHash<QString, QVariant> QVariantHash;
class QJsonObject;
class QDataStream;
+namespace QJsonPrivate { class Variant; }
+
class QCborContainerPrivate;
class Q_CORE_EXPORT QCborMap
{
public:
- typedef QPair<QCborValue, QCborValue> value_type;
+ typedef std::pair<QCborValue, QCborValue> value_type;
typedef QCborValue key_type;
typedef QCborValue mapped_type;
typedef qsizetype size_type;
class ConstIterator;
class Iterator {
- mutable QCborValueRef item; // points to the value
+ QCborValueRef item {}; // points to the value
friend class ConstIterator;
friend class QCborMap;
Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
typedef qsizetype difference_type;
- typedef QPair<const QCborValueRef, QCborValueRef> value_type;
- typedef QPair<const QCborValueRef, QCborValueRef> reference;
- typedef QPair<const QCborValueRef, QCborValueRef> pointer;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> value_type;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> reference;
+ typedef std::pair<QCborValueConstRef, QCborValueRef> pointer;
- Q_DECL_CONSTEXPR Iterator() = default;
- Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ constexpr Iterator() = default;
+ constexpr Iterator(const Iterator &) = default;
+ ~Iterator() = default;
Iterator &operator=(const Iterator &other)
{
// rebind the reference
@@ -86,23 +49,32 @@ public:
return *this;
}
- value_type operator*() const { return { {item.d, item.i - 1}, item }; }
- QCborValueRef *operator->() const { return &item; }
- QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
+ value_type operator*() const { return { QCborValueRef{item.d, item.i - 1}, item }; }
+ value_type operator[](qsizetype j) const { return *(*this + j); }
+ QCborValueRef *operator->() { return &item; }
+ const QCborValueConstRef *operator->() const { return &item; }
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
+ QCborValueConstRef
+#else
+ QCborValue
+#endif
+ key() const { return QCborValueRef(item.d, item.i - 1); }
QCborValueRef value() const { return item; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
Iterator &operator++() { item.i += 2; return *this; }
Iterator operator++(int) { Iterator n = *this; item.i += 2; return n; }
Iterator &operator--() { item.i -= 2; return *this; }
@@ -112,24 +84,74 @@ public:
Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + 2 * j }); }
Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - 2 * j }); }
qsizetype operator-(Iterator j) const { return (item.i - j.item.i) / 2; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static bool comparesEqual_helper(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const Iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator)
+ friend bool comparesEqual(const Iterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const Iterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(Iterator, ConstIterator)
};
class ConstIterator {
- QCborValueRef item; // points to the value
+ QCborValueConstRef item; // points to the value
friend class Iterator;
friend class QCborMap;
friend class QCborValue;
friend class QCborValueRef;
+ constexpr ConstIterator(QCborValueConstRef it) : item{it} {}
ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
public:
typedef std::random_access_iterator_tag iterator_category;
typedef qsizetype difference_type;
- typedef QPair<const QCborValueRef, const QCborValueRef> value_type;
- typedef QPair<const QCborValueRef, const QCborValueRef> reference;
- typedef QPair<const QCborValueRef, const QCborValueRef> pointer;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> value_type;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> reference;
+ typedef std::pair<QCborValueConstRef, QCborValueConstRef> pointer;
- Q_DECL_CONSTEXPR ConstIterator() = default;
- Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ constexpr ConstIterator() = default;
+ constexpr ConstIterator(const ConstIterator &) = default;
+ ~ConstIterator() = default;
ConstIterator &operator=(const ConstIterator &other)
{
// rebind the reference
@@ -138,32 +160,65 @@ public:
return *this;
}
- value_type operator*() const { return { {item.d, item.i - 1}, item }; }
- const QCborValueRef *operator->() const { return &item; }
- QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
- QCborValueRef value() const { return item; }
+ value_type operator*() const { return { QCborValueRef(item.d, item.i - 1), item }; }
+ value_type operator[](qsizetype j) const { return *(*this + j); }
+ const QCborValueConstRef *operator->() const { return &item; }
+#if QT_VERSION >= QT_VERSION_CHECK(7,0,0)
+ QCborValueConstRef
+#else
+ QCborValue
+#endif
+ key() const { return QCborValueRef(item.d, item.i - 1); }
+ QCborValueConstRef value() const { return item; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator!=(const Iterator &o) const { return !operator==(o); }
bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
- bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator!=(const ConstIterator &o) const { return !operator==(o); }
bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+#endif
ConstIterator &operator++() { item.i += 2; return *this; }
ConstIterator operator++(int) { ConstIterator n = *this; item.i += 2; return n; }
ConstIterator &operator--() { item.i -= 2; return *this; }
ConstIterator operator--(int) { ConstIterator n = *this; item.i -= 2; return n; }
ConstIterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
ConstIterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
- ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + 2 * j }); }
- ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - 2 * j }); }
+ ConstIterator operator+(qsizetype j) const { return ConstIterator{ item.d, item.i + 2 * j }; }
+ ConstIterator operator-(qsizetype j) const { return ConstIterator{ item.d, item.i - 2 * j }; }
qsizetype operator-(ConstIterator j) const { return (item.i - j.item.i) / 2; }
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.i == rhs.item.i;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.i, rhs.item.i);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const ConstIterator &lhs, const ConstIterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const ConstIterator &lhs,
+ const ConstIterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(ConstIterator)
};
QCborMap() noexcept;
@@ -180,7 +235,7 @@ public:
void swap(QCborMap &other) noexcept
{
- qSwap(d, other.d);
+ d.swap(other.d);
}
QCborValue toCborValue() const { return *this; }
@@ -191,73 +246,65 @@ public:
QList<QCborValue> keys() const;
QCborValue value(qint64 key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
- QCborValue value(QLatin1String key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
+ QCborValue value(QLatin1StringView key) const
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
QCborValue value(const QString & key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
QCborValue value(const QCborValue &key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
template<size_t N> QT_ASCII_CAST_WARN const QCborValue value(const char (&key)[N]) const
{ return value(QString::fromUtf8(key, N - 1)); }
#endif
const QCborValue operator[](qint64 key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
- const QCborValue operator[](QLatin1String key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
+ const QCborValue operator[](QLatin1StringView key) const
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
const QCborValue operator[](const QString & key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
const QCborValue operator[](const QCborValue &key) const
- { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ { const_iterator it = find(key); return comparesEqual(it, end()) ? QCborValue() : it.value(); }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
template<size_t N> QT_ASCII_CAST_WARN const QCborValue operator[](const char (&key)[N]) const
{ return operator[](QString::fromUtf8(key, N - 1)); }
#endif
QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](QLatin1StringView key);
QCborValueRef operator[](const QString & key);
QCborValueRef operator[](const QCborValue &key);
QCborValue take(qint64 key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
- QCborValue take(QLatin1String key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
+ QCborValue take(QLatin1StringView key)
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
QCborValue take(const QString &key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
QCborValue take(const QCborValue &key)
- { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) return extract(it); return QCborValue(); }
void remove(qint64 key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
- void remove(QLatin1String key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
+ void remove(QLatin1StringView key)
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
void remove(const QString & key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
void remove(const QCborValue &key)
- { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ { const_iterator it = constFind(key); if (!comparesEqual(it, constEnd())) erase(it); }
bool contains(qint64 key) const
- { const_iterator it = find(key); return it != end(); }
- bool contains(QLatin1String key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
+ bool contains(QLatin1StringView key) const
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
bool contains(const QString & key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
bool contains(const QCborValue &key) const
- { const_iterator it = find(key); return it != end(); }
+ { const_iterator it = find(key); return !comparesEqual(it, end()); }
int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborMap &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborMap &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborMap &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborMap &other) const
{ return compare(other) < 0; }
#endif
@@ -279,15 +326,15 @@ public:
bool empty() const { return isEmpty(); }
iterator find(qint64 key);
- iterator find(QLatin1String key);
+ iterator find(QLatin1StringView key);
iterator find(const QString & key);
iterator find(const QCborValue &key);
const_iterator constFind(qint64 key) const;
- const_iterator constFind(QLatin1String key) const;
+ const_iterator constFind(QLatin1StringView key) const;
const_iterator constFind(const QString & key) const;
const_iterator constFind(const QCborValue &key) const;
const_iterator find(qint64 key) const { return constFind(key); }
- const_iterator find(QLatin1String key) const { return constFind(key); }
+ const_iterator find(QLatin1StringView key) const { return constFind(key); }
const_iterator find(const QString & key) const { return constFind(key); }
const_iterator find(const QCborValue &key) const { return constFind(key); }
@@ -297,7 +344,7 @@ public:
v = value_;
return { d.data(), v.i };
}
- iterator insert(QLatin1String key, const QCborValue &value_)
+ iterator insert(QLatin1StringView key, const QCborValue &value_)
{
QCborValueRef v = operator[](key); // detaches
v = value_;
@@ -320,15 +367,60 @@ public:
static QCborMap fromVariantMap(const QVariantMap &map);
static QCborMap fromVariantHash(const QVariantHash &hash);
static QCborMap fromJsonObject(const QJsonObject &o);
+ static QCborMap fromJsonObject(QJsonObject &&o) noexcept;
QVariantMap toVariantMap() const;
QVariantHash toVariantHash() const;
QJsonObject toJsonObject() const;
private:
+ friend class QCborContainerPrivate;
friend class QCborValue;
friend class QCborValueRef;
+ friend class QJsonPrivate::Variant;
void detach(qsizetype reserve = 0);
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual(const QCborMap &lhs, const QCborMap &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborMap &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborMap &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap, QCborValue)
+
+ static Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept;
+ static Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborMap &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborMap &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborMap, QCborValueConstRef)
+
explicit QCborMap(QCborContainerPrivate &dd) noexcept;
QExplicitlySharedDataPointer<QCborContainerPrivate> d;
};
@@ -340,6 +432,7 @@ inline QCborValue::QCborValue(QCborMap &&m)
{
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
inline QCborMap QCborValueRef::toMap() const
{
return concrete().toMap();
@@ -349,6 +442,17 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
{
return concrete().toMap(m);
}
+#endif
+
+inline QCborMap QCborValueConstRef::toMap() const
+{
+ return concrete().toMap();
+}
+
+inline QCborMap QCborValueConstRef::toMap(const QCborMap &m) const
+{
+ return concrete().toMap(m);
+}
Q_CORE_EXPORT size_t qHash(const QCborMap &map, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
index f2b88820cd..7850d26663 100644
--- a/src/corelib/serialization/qcborstream.h
+++ b/src/corelib/serialization/qcborstream.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAM_H
#define QCBORSTREAM_H
diff --git a/src/corelib/serialization/qcborstreamreader.cpp b/src/corelib/serialization/qcborstreamreader.cpp
index 308fbe9ae9..863c24534a 100644
--- a/src/corelib/serialization/qcborstreamreader.cpp
+++ b/src/corelib/serialization/qcborstreamreader.cpp
@@ -1,52 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborstreamreader.h"
#define CBOR_NO_ENCODER_API
#include <private/qcborcommon_p.h>
-#include <private/qbytearray_p.h>
#include <private/qnumeric_p.h>
#include <private/qstringconverter_p.h>
+#include <qiodevice.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
@@ -63,6 +28,7 @@ static CborError qt_cbor_decoder_transfer_string(void *token, const void **userp
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+QT_WARNING_DISABLE_GCC("-Wimplicit-fallthrough")
#include <cborparser.c>
@@ -70,13 +36,11 @@ QT_WARNING_POP
static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
-static CborError Q_DECL_UNUSED cbor_value_get_half_float_as_float(const CborValue *, float *)
+[[maybe_unused]] static CborError cbor_value_get_half_float_as_float(const CborValue *, float *)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
// confirm our constants match TinyCBOR's
@@ -96,6 +60,7 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
\class QCborStreamReader
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
@@ -107,7 +72,7 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
Representation, a very compact form of binary data encoding that is
compatible with JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ be used alongside the \l{RFC 7252}{CoAP
protocol}.
QCborStreamReader provides a StAX-like API, similar to that of
@@ -185,7 +150,9 @@ static_assert(int(QCborStreamReader::Invalid) == CborInvalidType);
parsing from a QByteArray, or reparse(), if it is instead reading directly
a the QIDOevice that now has more data available (see setDevice()).
- \sa QCborStreamWriter, QCborValue, QXmlStreamReader
+ \sa QCborStreamWriter, QCborValue, QXmlStreamReader,
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
/*!
@@ -563,7 +530,7 @@ public:
CborValue currentElement;
QCborError lastError = {};
- QByteArray::size_type bufferStart;
+ QByteArray::size_type bufferStart = 0;
bool corrupt = false;
QCborStreamReaderPrivate(const QByteArray &data)
@@ -645,27 +612,30 @@ public:
lastError = QCborError { QCborError::Code(int(err)) };
}
- void updateBufferAfterString(qsizetype offset, qsizetype size)
- {
- Q_ASSERT(device);
-
- bufferStart += offset;
- qsizetype newStart = bufferStart + size;
- qsizetype remainingInBuffer = buffer.size() - newStart;
-
- if (remainingInBuffer <= 0) {
- // We've read from the QIODevice more than what was in the buffer.
- buffer.truncate(0);
- } else {
- // There's still data buffered, but we need to move it around.
- char *ptr = buffer.data();
- memmove(ptr, ptr + newStart, remainingInBuffer);
- buffer.truncate(remainingInBuffer);
- }
-
- bufferStart = 0;
- }
+ struct ReadStringChunk {
+ union {
+ char *ptr;
+ QByteArray *array;
+ QString *string;
+ };
+ enum Type { ByteArray = -1, String = -3, Utf8String = -5 };
+ qsizetype maxlen_or_type;
+
+ ReadStringChunk(char *ptr, qsizetype maxlen) : ptr(ptr), maxlen_or_type(maxlen) {}
+ ReadStringChunk(QByteArray *array, Type type = ByteArray) : array(array), maxlen_or_type(type) {}
+ ReadStringChunk(QString *str) : string(str), maxlen_or_type(String) {}
+ bool isString() const { return maxlen_or_type == String; }
+ bool isUtf8String() const { return maxlen_or_type == Utf8String; }
+ bool isByteArray() const { return maxlen_or_type == ByteArray; }
+ bool isPlainPointer() const { return maxlen_or_type >= 0; }
+ };
+ static QCborStreamReader::StringResultCode appendStringChunk(QCborStreamReader &reader, QByteArray *data);
+ bool readFullString(ReadStringChunk params);
+ QCborStreamReader::StringResult<qsizetype> readStringChunk(ReadStringChunk params);
+ qsizetype readStringChunk_byte(ReadStringChunk params, qsizetype len);
+ qsizetype readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len);
+ qsizetype readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len);
bool ensureStringIteration();
};
@@ -715,7 +685,7 @@ static CborError qt_cbor_decoder_transfer_string(void *token, const void **userp
// (otherwise, we'd lose the length information)
qsizetype total;
if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
- || add_overflow<qsizetype>(offset, len, &total))
+ || qAddOverflow<qsizetype>(offset, len, &total))
return CborErrorDataTooLarge;
// our string transfer is just saving the offset to the userptr
@@ -785,7 +755,7 @@ inline void QCborStreamReader::preparse()
\sa addData(), isValid()
*/
QCborStreamReader::QCborStreamReader()
- : QCborStreamReader(QByteArray())
+ : d(new QCborStreamReaderPrivate({})), type_(Invalid)
{
}
@@ -828,7 +798,7 @@ QCborStreamReader::QCborStreamReader(const QByteArray &data)
Creates a QCborStreamReader object that will parse the CBOR stream found by
reading from \a device. QCborStreamReader does not take ownership of \a
- device, so it must remain valid until this oject is destroyed.
+ device, so it must remain valid until this object is destroyed.
*/
QCborStreamReader::QCborStreamReader(QIODevice *device)
: d(new QCborStreamReaderPrivate(device))
@@ -962,7 +932,7 @@ void QCborStreamReader::reset()
\sa isValid()
*/
-QCborError QCborStreamReader::lastError()
+QCborError QCborStreamReader::lastError() const
{
return d->lastError;
}
@@ -1003,7 +973,7 @@ QCborStreamReader::Type QCborStreamReader::parentContainerType() const
{
if (d->containerStack.isEmpty())
return Invalid;
- return Type(cbor_value_get_type(&qAsConst(d->containerStack).top()));
+ return Type(cbor_value_get_type(&std::as_const(d->containerStack).top()));
}
/*!
@@ -1053,19 +1023,18 @@ bool QCborStreamReader::next(int maxRecursion)
next(maxRecursion - 1);
if (lastError() == QCborError::NoError)
leaveContainer();
- } else if (isString() || isByteArray()) {
- auto r = _readByteArray_helper();
- while (r.status == Ok) {
- if (isString() && r.data.size() > MaxStringSize) {
- d->handleError(CborErrorDataTooLarge);
- break;
- }
- if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
- d->handleError(CborErrorInvalidUtf8TextString);
- break;
- }
- r = _readByteArray_helper();
- }
+ } else if (isByteArray()) {
+ char c;
+ StringResult<qsizetype> r;
+ do {
+ r = readStringChunk(&c, 1);
+ } while (r.status == Ok);
+ } else if (isString()) {
+ // we need to use actual readString so we get UTF-8 validation
+ StringResult<QString> r;
+ do {
+ r = readString();
+ } while (r.status == Ok);
} else {
// fixed types
CborError err = cbor_value_advance_fixed(&d->currentElement);
@@ -1324,77 +1293,104 @@ bool QCborStreamReader::leaveContainer()
Decodes one string chunk from the CBOR string and returns it. This function
is used for both regular and chunked string contents, so the caller must
- always loop around calling this function, even if isLengthKnown() has
+ always loop around calling this function, even if isLengthKnown()
is true. The typical use of this function is as follows:
\snippet code/src_corelib_serialization_qcborstream.cpp 27
+ The readAllString() function implements the above loop and some extra checks.
+
+//! [string-no-type-conversions]
This function does not perform any type conversions, including from integers
or from byte arrays. Therefore, it may only be called if isString() returned
true; calling it in any other condition is an error.
+//! [string-no-type-conversions]
- \sa readByteArray(), isString(), readStringChunk()
+ \sa readAllString(), readByteArray(), isString(), readStringChunk()
*/
QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
{
- auto r = _readByteArray_helper();
QCborStreamReader::StringResult<QString> result;
+ auto r = d->readStringChunk(&result.data);
result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
+ }
- if (r.status == Ok) {
- // See QUtf8::convertToUnicode() a detailed explanation of why this
- // conversion uses the same number of words or less.
- CborError err = CborNoError;
- if (r.data.size() > MaxStringSize) {
- err = CborErrorDataTooLarge;
- } else {
- QStringConverter::State cs(QStringConverter::Flag::Stateless);
- result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
- if (cs.invalidChars != 0 || cs.remainingChars != 0)
- err = CborErrorInvalidUtf8TextString;
- }
+ return result;
+}
- if (err) {
- d->handleError(err);
- result.data.clear();
- result.status = Error;
- }
+/*!
+ \fn QCborStreamReader::StringResult<QByteArray> QCborStreamReader::readUtf8String()
+ \since 6.7
+
+ Decodes one string chunk from the CBOR string and returns it. This function
+ is used for both regular and chunked string contents, so the caller must
+ always loop around calling this function, even if isLengthKnown() is true.
+ The typical use of this function is as for readString() in the following:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 27
+
+ The readAllUtf8String() function implements the above loop and some extra checks.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \sa readAllString(), readByteArray(), isString(), readStringChunk()
+ */
+QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readUtf8String_helper()
+{
+ using P = QCborStreamReaderPrivate::ReadStringChunk;
+ QCborStreamReader::StringResult<QByteArray> result;
+ auto r = d->readStringChunk(P{ &result.data, P::Utf8String });
+ result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
}
+
return result;
}
/*!
- \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readByteArray()
+ \fn QCborStreamReader::StringResult<QByteArray> QCborStreamReader::readByteArray()
Decodes one byte array chunk from the CBOR string and returns it. This
function is used for both regular and chunked contents, so the caller must
- always loop around calling this function, even if isLengthKnown() has
+ always loop around calling this function, even if isLengthKnown()
is true. The typical use of this function is as follows:
\snippet code/src_corelib_serialization_qcborstream.cpp 28
+ The readAllByteArray() function implements the above loop and some extra checks.
+
+//! [bytearray-no-type-conversions]
This function does not perform any type conversions, including from integers
or from strings. Therefore, it may only be called if isByteArray() is true;
calling it in any other condition is an error.
+//! [bytearray-no-type-conversions]
- \sa readString(), isByteArray(), readStringChunk()
+ \sa readAllByteArray(), readString(), isByteArray(), readStringChunk()
*/
QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
{
QCborStreamReader::StringResult<QByteArray> result;
- result.status = Error;
- qsizetype len = _currentStringChunkSize();
- if (len < 0)
- return result;
- if (len > MaxByteArraySize) {
- d->handleError(CborErrorDataTooLarge);
- return result;
+ auto r = d->readStringChunk(&result.data);
+ result.status = r.status;
+ if (r.status == Error) {
+ result.data.clear();
+ } else {
+ Q_ASSERT(r.data == result.data.size());
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
}
- result.data.resize(len);
- auto r = readStringChunk(result.data.data(), len);
- Q_ASSERT(r.status != Ok || r.data == len);
- result.status = r.status;
return result;
}
@@ -1429,6 +1425,147 @@ qsizetype QCborStreamReader::_currentStringChunkSize() const
return -1;
}
+bool QCborStreamReaderPrivate::readFullString(ReadStringChunk params)
+{
+ auto r = readStringChunk(params);
+ while (r.status == QCborStreamReader::Ok) {
+ // keep appending
+ r = readStringChunk(params);
+ }
+
+ bool ok = r.status == QCborStreamReader::EndOfString;
+ Q_ASSERT(ok == !lastError);
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllString()
+ \since 6.7
+
+ Decodes the current text string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QString(), but
+ that may not be distinguishable from certain empty text strings. Instead,
+ check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+//! [note-not-restartable]
+ \note This function cannot be resumed. That is, this function should not
+ be used in contexts where the CBOR data may still be received, for example
+ from a socket or pipe. It should only be used when the full data has
+ already been received and is available in the input QByteArray or
+ QIODevice.
+//! [note-not-restartable]
+
+ \sa readString(), readStringChunk(), isString(), readAllByteArray()
+ */
+/*!
+ \fn QCborStreamReader::readAndAppendToString(QString &dst)
+ \since 6.7
+
+ Decodes the current text string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAndAppendToByteArray()
+ */
+bool QCborStreamReader::_readAndAppendToString_helper(QString &dst)
+{
+ bool ok = d->readFullString(&dst);
+ if (ok)
+ preparse();
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllUtf8String()
+ \since 6.7
+
+ Decodes the current text string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QString(), but
+ that may not be distinguishable from certain empty text strings. Instead,
+ check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAllByteArray()
+ */
+/*!
+ \fn QCborStreamReader::readAndAppendToUtf8String(QByteArray &dst)
+ \since 6.7
+
+ Decodes the current text string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp string-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readString(), readStringChunk(), isString(), readAndAppendToByteArray()
+ */
+bool QCborStreamReader::_readAndAppendToUtf8String_helper(QByteArray &dst)
+{
+ using P = QCborStreamReaderPrivate::ReadStringChunk;
+ bool ok = d->readFullString({ &dst, P::Utf8String });
+ if (ok)
+ preparse();
+ return ok;
+}
+
+/*!
+ \fn QCborStreamReader::readAllByteArray()
+ \since 6.7
+
+ Decodes the current byte string and returns it. If the string is chunked,
+ this function will iterate over all chunks and concatenate them. If an
+ error happens, this function returns a default-constructed QByteArray(),
+ but that may not be distinguishable from certain empty byte strings.
+ Instead, check lastError() to determine if an error has happened.
+
+ \include qcborstreamreader.cpp bytearray-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readByteArray(), readStringChunk(), isByteArray(), readAllString()
+ */
+
+/*!
+ \fn QCborStreamReader::readAndAppendToByteArray(QByteArray &dst)
+ \since 6.7
+
+ Decodes the current byte string and appends to \a dst. If the string is
+ chunked, this function will iterate over all chunks and concatenate them.
+ If an error happens during decoding, other chunks that could be decoded
+ successfully may have been written to \a dst nonetheless. Returns \c true
+ if the decoding happened without errors, \c false otherwise.
+
+ \include qcborstreamreader.cpp bytearray-no-type-conversions
+
+ \include qcborstreamreader.cpp note-not-restartable
+
+ \sa readByteArray(), readStringChunk(), isByteArray(), readAndAppendToString()
+ */
+bool QCborStreamReader::_readAndAppendToByteArray_helper(QByteArray &dst)
+{
+ bool ok = d->readFullString(&dst);
+ if (ok)
+ preparse();
+ return ok;
+}
+
/*!
Reads the current string chunk into the buffer pointed to by \a ptr, whose
size is \a maxlen. This function returns a \l StringResult object, with the
@@ -1460,28 +1597,64 @@ qsizetype QCborStreamReader::_currentStringChunkSize() const
QCborStreamReader::StringResult<qsizetype>
QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
{
+ auto r = d->readStringChunk({ptr, maxlen});
+ if (r.status == EndOfString && lastError() == QCborError::NoError)
+ preparse();
+ return r;
+}
+
+// used by qcborvalue.cpp
+QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data)
+{
+ return QCborStreamReaderPrivate::appendStringChunk(reader, data);
+}
+
+inline QCborStreamReader::StringResultCode
+QCborStreamReaderPrivate::appendStringChunk(QCborStreamReader &reader, QByteArray *data)
+{
+ auto status = reader.d->readStringChunk(data).status;
+ if (status == QCborStreamReader::EndOfString && reader.lastError() == QCborError::NoError)
+ reader.preparse();
+ return status;
+}
+
+Q_NEVER_INLINE QCborStreamReader::StringResult<qsizetype>
+QCborStreamReaderPrivate::readStringChunk(ReadStringChunk params)
+{
CborError err;
size_t len;
const void *content = nullptr;
QCborStreamReader::StringResult<qsizetype> result;
result.data = 0;
- result.status = Error;
+ result.status = QCborStreamReader::Error;
- d->lastError = {};
- if (!d->ensureStringIteration())
+ lastError = {};
+ if (!ensureStringIteration())
return result;
+ // Note: in the current implementation, the call into TinyCBOR below only
+ // succeeds if we *already* have all the data in memory. That's obvious for
+ // the case of direct memory (no QIODevice), whereas for QIODevices
+ // qt_cbor_decoder_transfer_string() enforces that
+ // QIODevice::bytesAvailable() be bigger than the amount we're about to
+ // read.
+ //
+ // This is an important security gate: if the CBOR stream is corrupt or
+ // malicious, and has an impossibly large string size, we only go past it
+ // if the transfer to the destination buffer will succeed (modulo QIODevice
+ // I/O failures).
+
#if 1
// Using internal TinyCBOR API!
- err = _cbor_value_get_string_chunk(&d->currentElement, &content, &len, &d->currentElement);
+ err = _cbor_value_get_string_chunk(&currentElement, &content, &len, &currentElement);
#else
// the above is effectively the same as:
if (cbor_value_is_byte_string(&currentElement))
- err = cbor_value_get_byte_string_chunk(&d->currentElement, reinterpret_cast<const uint8_t **>(&content),
- &len, &d->currentElement);
+ err = cbor_value_get_byte_string_chunk(&currentElement, reinterpret_cast<const uint8_t **>(&content),
+ &len, &currentElement);
else
- err = cbor_value_get_text_string_chunk(&d->currentElement, reinterpret_cast<const char **>(&content),
- &len, &d->currentElement);
+ err = cbor_value_get_text_string_chunk(&currentElement, reinterpret_cast<const char **>(&content),
+ &len, &currentElement);
#endif
// Range check: using implementation-defined behavior in converting an
@@ -1493,56 +1666,190 @@ QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
if (err) {
if (err == CborErrorNoMoreStringChunks) {
- d->preread();
- err = cbor_value_finish_string_iteration(&d->currentElement);
- result.status = EndOfString;
+ preread();
+ err = cbor_value_finish_string_iteration(&currentElement);
+ result.status = QCborStreamReader::EndOfString;
}
if (err)
- d->handleError(err);
- else
- preparse();
+ handleError(err);
+ // caller musts call preparse()
return result;
}
- // Read the chunk into the user's buffer.
- qint64 actuallyRead;
qptrdiff offset = qptrdiff(content);
+ bufferStart += offset;
+ if (device) {
+ // This first skip can't fail because we've already read this many bytes.
+ device->skip(bufferStart);
+ }
+
+ if (params.isString()) {
+ // readString()
+ result.data = readStringChunk_unicode(params, qsizetype(len));
+ } else if (params.isUtf8String()) {
+ result.data = readStringChunk_utf8(params, qsizetype(len));
+ } else {
+ // readByteArray() or readStringChunk()
+ result.data = readStringChunk_byte(params, qsizetype(len));
+ }
+
+ if (result.data < 0)
+ return result; // error
+
+ // adjust the buffers after we're done reading the string
+ bufferStart += len;
+ if (device) {
+ qsizetype remainingInBuffer = buffer.size() - bufferStart;
+
+ if (remainingInBuffer <= 0) {
+ // We've read from the QIODevice more than what was in the buffer.
+ buffer.truncate(0);
+ } else {
+ // There's still data buffered, but we need to move it around.
+ char *ptr = buffer.data();
+ memmove(ptr, ptr + bufferStart, remainingInBuffer);
+ buffer.truncate(remainingInBuffer);
+ }
+
+ bufferStart = 0;
+ }
+
+ preread();
+ result.status = QCborStreamReader::Ok;
+ return result;
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_byte(ReadStringChunk params, qsizetype len)
+{
+ qint64 actuallyRead;
qsizetype toRead = qsizetype(len);
- qsizetype left = toRead - maxlen;
- if (left < 0)
- left = 0; // buffer bigger than string
- else
- toRead = maxlen; // buffer smaller than string
+ qsizetype left = 0; // bytes from the chunk not copied to the user buffer, to discard
+ char *ptr = nullptr;
- if (d->device) {
- // This first skip can't fail because we've already read this many bytes.
- d->device->skip(d->bufferStart + qptrdiff(content));
- actuallyRead = d->device->read(ptr, toRead);
+ if (params.isPlainPointer()) {
+ left = toRead - params.maxlen_or_type;
+ if (left < 0)
+ left = 0; // buffer bigger than string
+ else
+ toRead = params.maxlen_or_type; // buffer smaller than string
+ ptr = params.ptr;
+ } else if (!params.isString()) {
+ // See note above on having ensured there is enough incoming data.
+ auto oldSize = params.array->size();
+ auto newSize = oldSize;
+ if (qAddOverflow<decltype(newSize)>(oldSize, toRead, &newSize)) {
+ handleError(CborErrorDataTooLarge);
+ return -1;
+ }
+ QT_TRY {
+ params.array->resize(newSize);
+ } QT_CATCH (const std::bad_alloc &) {
+ // the distinction between DataTooLarge and OOM is mostly for
+ // compatibility with Qt 5; in Qt 6, we could consider everything
+ // to be OOM.
+ handleError(newSize > QByteArray::max_size() ? CborErrorDataTooLarge: CborErrorOutOfMemory);
+ return -1;
+ }
+
+ ptr = const_cast<char *>(params.array->constData()) + oldSize;
+ }
+
+ if (device) {
+ actuallyRead = device->read(ptr, toRead);
if (actuallyRead != toRead) {
actuallyRead = -1;
} else if (left) {
- qint64 skipped = d->device->skip(left);
+ qint64 skipped = device->skip(left);
if (skipped != left)
actuallyRead = -1;
}
if (actuallyRead < 0) {
- d->handleError(CborErrorIO);
- return result;
+ handleError(CborErrorIO);
+ return -1;
}
-
- d->updateBufferAfterString(offset, len);
} else {
actuallyRead = toRead;
- memcpy(ptr, d->buffer.constData() + d->bufferStart + offset, toRead);
- d->bufferStart += QByteArray::size_type(offset + len);
+ memcpy(ptr, buffer.constData() + bufferStart, toRead);
}
- d->preread();
- result.data = actuallyRead;
- result.status = Ok;
- return result;
+ return actuallyRead;
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_unicode(ReadStringChunk params, qsizetype utf8len)
+{
+ Q_ASSERT(params.isString());
+
+ // See QUtf8::convertToUnicode() a detailed explanation of why this
+ // conversion uses the same number of words or less.
+ qsizetype currentSize = params.string->size();
+ size_t newSize = size_t(utf8len) + size_t(currentSize); // can't overflow
+ if (utf8len > QString::max_size() || qsizetype(newSize) < 0) {
+ handleError(CborErrorDataTooLarge);
+ return -1;
+ }
+ QT_TRY {
+ params.string->resize(qsizetype(newSize));
+ } QT_CATCH (const std::bad_alloc &) {
+ handleError(CborErrorOutOfMemory);
+ return -1;
+ }
+
+ QChar *begin = const_cast<QChar *>(params.string->constData());
+ QChar *ptr = begin + currentSize;
+ QStringConverter::State cs(QStringConverter::Flag::Stateless);
+ if (device == nullptr) {
+ // Easy case: we can decode straight from the buffer we already have
+ ptr = QUtf8::convertToUnicode(ptr, { buffer.constData() + bufferStart, utf8len }, &cs);
+ } else {
+ // read in chunks, to avoid creating large, intermediate buffers
+ constexpr qsizetype StringChunkSize = 16384;
+ qsizetype chunkSize = qMin(StringChunkSize, utf8len);
+ QVarLengthArray<char> chunk(chunkSize);
+
+ cs = { QStringConverter::Flag::ConvertInitialBom };
+ while (utf8len > 0 && cs.invalidChars == 0) {
+ qsizetype toRead = qMin(chunkSize, utf8len);
+ qint64 actuallyRead = device->read(chunk.data(), toRead);
+ if (actuallyRead == toRead)
+ ptr = QUtf8::convertToUnicode(ptr, { chunk.data(), toRead }, &cs);
+
+ if (actuallyRead != toRead) {
+ handleError(CborErrorIO);
+ return -1;
+ }
+ utf8len -= toRead;
+ }
+ }
+
+ if (cs.invalidChars != 0 || cs.remainingChars != 0) {
+ handleError(CborErrorInvalidUtf8TextString);
+ return -1;
+ }
+
+ qsizetype size = ptr - begin;
+ params.string->truncate(ptr - begin);
+ return size - currentSize; // how many bytes we added
+}
+
+inline qsizetype
+QCborStreamReaderPrivate::readStringChunk_utf8(ReadStringChunk params, qsizetype utf8len)
+{
+ qsizetype result = readStringChunk_byte(params, utf8len);
+ if (result < 0)
+ return result;
+
+ // validate the UTF-8 content we've just read
+ QByteArrayView chunk = *params.array;
+ chunk = chunk.last(result);
+ if (QtPrivate::isValidUtf8(chunk))
+ return result;
+
+ handleError(CborErrorInvalidUtf8TextString);
+ return -1;
}
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborstreamreader.h b/src/corelib/serialization/qcborstreamreader.h
index 6d5feccfcf..2666b7c7b2 100644
--- a/src/corelib/serialization/qcborstreamreader.h
+++ b/src/corelib/serialization/qcborstreamreader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAMREADER_H
#define QCBORSTREAMREADER_H
@@ -49,8 +13,8 @@
QT_REQUIRE_CONFIG(cborstreamreader);
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
@@ -113,7 +77,10 @@ public:
void clear();
void reset();
+#if QT_CORE_REMOVED_SINCE(6, 7)
QCborError lastError();
+#endif
+ QCborError lastError() const;
qint64 currentOffset() const;
@@ -153,7 +120,14 @@ public:
bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
bool leaveContainer();
+ bool readAndAppendToString(QString &dst)
+ { Q_ASSERT(isString()); return _readAndAppendToString_helper(dst); }
+ bool readAndAppendToUtf8String(QByteArray &dst)
+ { Q_ASSERT(isString()); return _readAndAppendToUtf8String_helper(dst); }
+ bool readAndAppendToByteArray(QByteArray &dst)
+ { Q_ASSERT(isByteArray()); return _readAndAppendToByteArray_helper(dst); }
StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
+ StringResult<QByteArray> readUtf8String() { Q_ASSERT(isString()); return _readUtf8String_helper(); }
StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
@@ -175,13 +149,38 @@ public:
return -v - 1;
return v;
}
+ QString readAllString()
+ {
+ QString dst;
+ if (!readAndAppendToString(dst))
+ dst = QString{};
+ return dst;
+ }
+ QByteArray readAllUtf8String()
+ {
+ QByteArray dst;
+ if (!readAndAppendToUtf8String(dst))
+ dst = QByteArray{};
+ return dst;
+ }
+ QByteArray readAllByteArray()
+ {
+ QByteArray dst;
+ if (!readAndAppendToByteArray(dst))
+ dst = QByteArray{};
+ return dst;
+ }
private:
void preparse();
bool _enterContainer_helper();
StringResult<QString> _readString_helper();
+ StringResult<QByteArray> _readUtf8String_helper();
StringResult<QByteArray> _readByteArray_helper();
qsizetype _currentStringChunkSize() const;
+ bool _readAndAppendToString_helper(QString &);
+ bool _readAndAppendToUtf8String_helper(QByteArray &);
+ bool _readAndAppendToByteArray_helper(QByteArray &);
template <typename FP> FP _toFloatingPoint() const noexcept
{
diff --git a/src/corelib/serialization/qcborstreamwriter.cpp b/src/corelib/serialization/qcborstreamwriter.cpp
index 4d6f323e9a..7b5099567e 100644
--- a/src/corelib/serialization/qcborstreamwriter.cpp
+++ b/src/corelib/serialization/qcborstreamwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborstreamwriter.h"
@@ -43,9 +7,11 @@
#include <private/qcborcommon_p.h>
#include <private/qnumeric_p.h>
+#include <private/qstringconverter_p.h>
#include <qbuffer.h>
#include <qdebug.h>
#include <qstack.h>
+#include <qvarlengtharray.h>
QT_BEGIN_NAMESPACE
@@ -63,16 +29,14 @@ QT_WARNING_POP
// silence compilers that complain about this being a static function declared
// but never defined
-static CborError Q_DECL_UNUSED cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
+[[maybe_unused]] static CborError cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
-static CborError Q_DECL_UNUSED cbor_encode_float_as_half_float(CborEncoder *, float)
+[[maybe_unused]] static CborError cbor_encode_float_as_half_float(CborEncoder *, float)
{
- Q_UNREACHABLE();
- return CborErrorInternalError;
+ Q_UNREACHABLE_RETURN(CborErrorInternalError);
}
Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
@@ -81,6 +45,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\class QCborStreamWriter
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
@@ -92,8 +57,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
Representation, a very compact form of binary data encoding that is
compatible with JSON. It was created by the IETF Constrained RESTful
Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
- be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
- protocol}.
+ be used alongside the \l{RFC 7252}{CoAP protocol}.
QCborStreamWriter provides a StAX-like API, similar to that of
\l{QXmlStreamWriter}. It is rather low-level and requires a bit of knowledge
@@ -123,7 +87,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
QCborStreamWriter supports all CBOR features required to create canonical
and strict streams. It implements almost all of the features specified in
- \l {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+ \l {RFC 7049}.
The following table lists the CBOR features that QCborStreamWriter supports.
@@ -151,7 +115,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\section2 Canonical CBOR encoding
Canonical CBOR encoding is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.9}{Section 3.9 of RFC
+ \l{RFC 7049, section 3.9}{Section 3.9 of RFC
7049}. Canonical encoding is not a requirement for Qt's CBOR decoding
functionality, but it may be required for some protocols. In particular,
protocols that require the ability to reproduce the same stream identically
@@ -181,7 +145,7 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\section2 Strict CBOR mode
Strict mode is defined by
- \l{https://tools.ietf.org/html/rfc7049#section-3.10}{Section 3.10 of RFC
+ \l{RFC 7049, section 3.10}{Section 3.10 of RFC
7049}. As for Canonical encoding above, QCborStreamWriter makes it possible
to create strict CBOR streams, but does not require them or validate that
the output is so.
@@ -212,12 +176,14 @@ Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
\endlist
\sa QCborStreamReader, QCborValue, QXmlStreamWriter
+ {Parsing and displaying CBOR data}, {Serialization Converter},
+ {Saving and Loading a Game}
*/
class QCborStreamWriterPrivate
{
public:
- static Q_CONSTEXPR quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
+ static constexpr quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
QIODevice *device;
CborEncoder encoder;
@@ -450,11 +416,11 @@ void QCborStreamWriter::append(QCborNegativeInteger n)
/*!
\overload
- Appends the text string \a str to the stream, creating a CBOR Text String
- value. QCborStreamWriter will attempt to write the entire string in one
- chunk.
+ Appends the Latin-1 string viewed by \a str to the stream, creating a CBOR
+ Text String value. QCborStreamWriter will attempt to write the entire string
+ in one chunk.
- The following example appends a simple string to the stream:
+ The following example appends a simple Latin-1 string literal to the stream:
\snippet code/src_corelib_serialization_qcborstream.cpp 8
@@ -467,7 +433,7 @@ void QCborStreamWriter::append(QCborNegativeInteger n)
\sa QCborStreamReader::isString(), QCborStreamReader::readString()
*/
-void QCborStreamWriter::append(QLatin1String str)
+void QCborStreamWriter::append(QLatin1StringView str)
{
// We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
// common subset (US-ASCII).
@@ -475,8 +441,10 @@ void QCborStreamWriter::append(QLatin1String str)
// it is plain US-ASCII
appendTextString(str.latin1(), str.size());
} else {
- // non-ASCII, so we need a pass-through UTF-16
- append(QString(str));
+ // non-ASCII, convert:
+ QVarLengthArray<char> utf8(str.size() * 2); // each L1 char gives at most two U8 units
+ const qsizetype written = QUtf8::convertFromLatin1(utf8.data(), str) - utf8.data();
+ appendTextString(utf8.data(), written);
}
}
@@ -640,11 +608,11 @@ void QCborStreamWriter::appendByteString(const char *data, qsizetype len)
The string pointed to by \a utf8 is expected to be properly encoded UTF-8.
QCborStreamWriter performs no validation that this is the case.
- Unlike the QLatin1String overload of append(), this function is not limited
+ Unlike the QLatin1StringView overload of append(), this function is not limited
to 2 GB. However, note that neither QCborStreamReader::readString() nor
QCborValue support reading CBOR streams with text strings larger than 2 GB.
- \sa append(QLatin1String), append(QStringView),
+ \sa append(QLatin1StringView), append(QStringView),
QCborStreamReader::isString(), QCborStreamReader::readString()
*/
void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
@@ -664,11 +632,11 @@ void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
The string pointed to by \a str is expected to be properly encoded UTF-8.
QCborStreamWriter performs no validation that this is the case.
- Unlike the QLatin1String overload of append(), this function is not limited
+ Unlike the QLatin1StringView overload of append(), this function is not limited
to 2 GB. However, note that neither QCborStreamReader nor QCborValue support
reading CBOR streams with text strings larger than 2 GB.
- \sa append(QLatin1String), append(QStringView),
+ \sa append(QLatin1StringView), append(QStringView),
QCborStreamReader::isString(), QCborStreamReader::readString()
*/
@@ -763,7 +731,8 @@ void QCborStreamWriter::startArray()
seem to allow up to 2\sup{64}-1 elements in the array. However, both
QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{32}-2
items on 32-bit systems and 2\sup{64}-2 items on 64-bit ones. Also note that
- QCborArray is currently limited to 2\sup{27} elements in any platform.
+ QCborArray is currently limited to 2\sup{27} elements on 32-bit platforms and
+ 2\sup{59} elements on 64-bit ones.
\sa startArray(), endArray(), startMap(), QCborStreamReader::isArray(),
QCborStreamReader::isLengthKnown()
@@ -836,7 +805,8 @@ void QCborStreamWriter::startMap()
seem to allow up to 2\sup{64}-1 pairs in the map. However, both
QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{31}-1
items on 32-bit systems and 2\sup{63}-1 items on 64-bit ones. Also note that
- QCborMap is currently limited to 2\sup{26} elements in any platform.
+ QCborMap is currently limited to 2\sup{26} elements on 32-bit platforms and
+ 2\sup{58} on 64-bit ones.
\sa startMap(), endMap(), startArray(), QCborStreamReader::isMap(),
QCborStreamReader::isLengthKnown()
@@ -866,3 +836,7 @@ bool QCborStreamWriter::endMap()
}
QT_END_NAMESPACE
+
+#undef CBOR_ENCODER_WRITER_CONTROL
+#undef CBOR_ENCODER_WRITE_FUNCTION
+#undef CBOR_ENCODER_NO_CHECK_USER
diff --git a/src/corelib/serialization/qcborstreamwriter.h b/src/corelib/serialization/qcborstreamwriter.h
index f8c94ceb93..1018646c99 100644
--- a/src/corelib/serialization/qcborstreamwriter.h
+++ b/src/corelib/serialization/qcborstreamwriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORSTREAMWRITER_H
#define QCBORSTREAMWRITER_H
@@ -51,8 +15,8 @@
QT_REQUIRE_CONFIG(cborstreamwriter);
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
@@ -77,7 +41,7 @@ public:
void append(qint64 i);
void append(QCborNegativeInteger n);
void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
- void append(QLatin1String str);
+ void append(QLatin1StringView str);
void append(QStringView str);
void append(QCborTag tag);
void append(QCborKnownTags tag) { append(QCborTag(tag)); }
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
index 7e2d8003c7..cd0b842111 100644
--- a/src/corelib/serialization/qcborvalue.cpp
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -53,7 +17,8 @@
#include <qendian.h>
#include <qlocale.h>
-#include <private/qbytearray_p.h>
+#include <qdatetime.h>
+#include <qtimezone.h>
#include <private/qnumeric_p.h>
#include <private/qsimd_p.h>
@@ -61,21 +26,39 @@
QT_BEGIN_NAMESPACE
+// Worst case memory allocation for a corrupt stream: 256 MB for 32-bit, 1 GB for 64-bit
+static constexpr quint64 MaxAcceptableMemoryUse = (sizeof(void*) == 4 ? 256 : 1024) * 1024 * 1024;
+
+// Internal limits to ensure we don't blow up the memory when parsing a corrupt
+// (possibly crafted to exploit) CBOR stream. The recursion impacts both the
+// maps/arrays we'll open when parsing and the thread's stack, as the parser is
+// itself recursive. If someone really needs more than 1024 layers of nesting,
+// they probably have a weird use-case for which custom parsing and
+// serialisation code would make sense. The limit on element count is the
+// preallocated limit: if the stream does actually have more elements, we will
+// grow the container.
+Q_DECL_UNUSED static constexpr int MaximumRecursionDepth = 1024;
+Q_DECL_UNUSED static constexpr quint64 MaximumPreallocatedElementCount =
+ MaxAcceptableMemoryUse / MaximumRecursionDepth / sizeof(QtCbor::Element) - 1;
+
/*!
\class QCborValue
\inmodule QtCore
\ingroup cbor
+ \ingroup qtserialization
\reentrant
\since 5.12
\brief The QCborValue class encapsulates a value in CBOR.
+ \compares strong
+
This class can be used to hold one of the many types available in CBOR.
CBOR is the Concise Binary Object Representation, a very compact form of
binary data encoding that is a superset of JSON. It was created by the IETF
Constrained RESTful Environments (CoRE) WG, which has used it in many
new RFCs. It is meant to be used alongside the
- \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+ \l{RFC 7252}{CoAP protocol}.
CBOR has three groups of built-in types:
@@ -159,7 +142,7 @@ QT_BEGIN_NAMESPACE
QCborValue supports all CBOR features required to create canonical and
strict streams. It implements almost all of the features specified in \l
- {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+ {RFC 7049}.
The following table lists the CBOR features that QCborValue supports.
@@ -209,8 +192,9 @@ QT_BEGIN_NAMESPACE
array or map it refers to will be modified with the new value. In all other
aspects, its API is identical to QCborValue.
- \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter
- QJsonValue, QJsonDocument
+ \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter,
+ QJsonValue, QJsonDocument, {Serialization Converter}, {Saving and Loading a Game}
+ {Parsing and displaying CBOR data}
*/
/*!
@@ -421,7 +405,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn QCborValue::QCborValue(QCborSimpleType st)
- Creates a QCborValue of simple type \a st. The type can later later be retrieved
+ Creates a QCborValue of simple type \a st. The type can later be retrieved
using toSimpleType() as well as isSimpleType(st).
CBOR simple types are types that do not have any associated value, like
@@ -766,6 +750,17 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor;
+static QCborContainerPrivate *assignContainer(QCborContainerPrivate *&d, QCborContainerPrivate *x)
+{
+ if (d == x)
+ return d;
+ if (d)
+ d->deref();
+ if (x)
+ x->ref.ref();
+ return d = x;
+}
+
static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
{
qint64 tag = d->elements.at(0).value;
@@ -793,9 +788,9 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
bool ok = false;
if (e.type == QCborValue::Integer) {
#if QT_POINTER_SIZE == 8
- // we don't have a fast 64-bit mul_overflow implementation on
+ // we don't have a fast 64-bit qMulOverflow implementation on
// 32-bit architectures.
- ok = !mul_overflow(e.value, qint64(1000), &msecs);
+ ok = !qMulOverflow(e.value, qint64(1000), &msecs);
#else
static const qint64 Limit = std::numeric_limits<qint64>::max() / 1000;
ok = (e.value > -Limit && e.value < Limit);
@@ -806,7 +801,7 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d)
ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs);
}
if (ok)
- dt = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC);
+ dt = QDateTime::fromMSecsSinceEpoch(msecs, QTimeZone::UTC);
}
if (dt.isValid()) {
QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
@@ -895,7 +890,7 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
// no data loss, we could use float
#ifndef QT_BOOTSTRAPPED
if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
- qfloat16 f16 = f;
+ qfloat16 f16 = qfloat16(f);
if (f16 == f)
return writer.append(f16);
}
@@ -909,12 +904,12 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E
}
#endif // QT_CONFIG(cborstreamwriter)
-static inline int typeOrder(Element e1, Element e2)
+static inline int typeOrder(QCborValue::Type e1, QCborValue::Type e2)
{
- auto comparable = [](Element e) {
- if (e.type >= 0x10000) // see QCborValue::isTag_helper()
+ auto comparable = [](QCborValue::Type type) {
+ if (type >= 0x10000) // see QCborValue::isTag_helper()
return QCborValue::Tag;
- return e.type;
+ return type;
};
return comparable(e1) - comparable(e2);
}
@@ -928,14 +923,24 @@ QCborContainerPrivate::~QCborContainerPrivate()
}
}
-void QCborContainerPrivate::compact(qsizetype reserved)
+void QCborContainerPrivate::compact()
{
if (usedData > data.size() / 2)
return;
// 50% savings if we recreate the byte data
- // ### TBD
- Q_UNUSED(reserved);
+ QByteArray newData;
+ QByteArray::size_type newUsedData = 0;
+ // Compact only elements that have byte data.
+ // Nested containers will be compacted when their data changes.
+ for (auto &e : elements) {
+ if (e.flags & Element::HasByteData) {
+ if (const ByteData *b = byteData(e))
+ e.value = addByteDataImpl(newData, newUsedData, b->byte(), b->len);
+ }
+ }
+ data = newData;
+ usedData = newUsedData;
}
QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qsizetype reserved)
@@ -943,12 +948,17 @@ QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qs
if (!d) {
d = new QCborContainerPrivate;
} else {
- d = new QCborContainerPrivate(*d);
+ // in case QList::reserve throws
+ QExplicitlySharedDataPointer u(new QCborContainerPrivate(*d));
if (reserved >= 0) {
- d->elements.reserve(reserved);
- d->compact(reserved);
+ u->elements.reserve(reserved);
+ u->compact();
}
- for (auto &e : qAsConst(d->elements)) {
+
+ d = u.take();
+ d->ref.storeRelaxed(0);
+
+ for (auto &e : std::as_const(d->elements)) {
if (e.flags & Element::IsContainer)
e.container->ref.ref();
}
@@ -974,7 +984,7 @@ QCborContainerPrivate *QCborContainerPrivate::grow(QCborContainerPrivate *d, qsi
Q_ASSERT(index >= 0);
d = detach(d, index + 1);
Q_ASSERT(d);
- int j = d->elements.size();
+ qsizetype j = d->elements.size();
while (j++ < index)
d->append(Undefined());
return d;
@@ -1014,10 +1024,23 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
// Copy string data, if any
if (const ByteData *b = value.container->byteData(value.n)) {
- if (this == value.container)
- e.value = addByteData(b->toByteArray(), b->len);
- else
+ const auto flags = e.flags;
+ // The element e has an invalid e.value, because it is copied from
+ // value. It means that calling compact() will trigger an assertion
+ // or just silently corrupt the data.
+ // Temporarily unset the Element::HasByteData flag in order to skip
+ // the element e in the call to compact().
+ e.flags = e.flags & ~Element::HasByteData;
+ if (this == value.container) {
+ const QByteArray valueData = b->toByteArray();
+ compact();
+ e.value = addByteData(valueData, valueData.size());
+ } else {
+ compact();
e.value = addByteData(b->byte(), b->len);
+ }
+ // restore the flags
+ e.flags = flags;
}
if (disp == MoveContainer)
@@ -1042,6 +1065,12 @@ Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(QStringView s)
qt_to_latin1_unchecked(l, s.utf16(), len);
}
+void QCborContainerPrivate::appendNonAsciiString(QStringView s)
+{
+ appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
+ QCborValue::String, QtCbor::Element::StringIsUtf16);
+}
+
QCborValue QCborContainerPrivate::extractAt_complex(Element e)
{
// create a new container for the returned value, containing the byte data
@@ -1054,7 +1083,7 @@ QCborValue QCborContainerPrivate::extractAt_complex(Element e)
// make a shallow copy of the byte data
container->appendByteData(b->byte(), b->len, e.type, e.flags);
usedData -= b->len + qsizetype(sizeof(*b));
- compact(elements.size());
+ compact();
} else {
// just share with the original byte data
container->data = data;
@@ -1065,9 +1094,127 @@ QCborValue QCborContainerPrivate::extractAt_complex(Element e)
return makeValue(e.type, 0, container);
}
+// Similar to QStringIterator::next() but returns malformed surrogate pair
+// itself when one is detected, and returns the length in UTF-8.
+static auto nextUtf32Character(const char16_t *&ptr, const char16_t *end) noexcept
+{
+ Q_ASSERT(ptr != end);
+ struct R {
+ char32_t c;
+ qsizetype len = 1; // in UTF-8 code units (bytes)
+ } r = { *ptr++ };
+
+ if (r.c < 0x0800) {
+ if (r.c >= 0x0080)
+ ++r.len;
+ } else if (!QChar::isHighSurrogate(r.c) || ptr == end) {
+ r.len += 2;
+ } else {
+ r.len += 3;
+ r.c = QChar::surrogateToUcs4(r.c, *ptr++);
+ }
+
+ return r;
+}
+
+static qsizetype stringLengthInUtf8(const char16_t *ptr, const char16_t *end) noexcept
+{
+ qsizetype len = 0;
+ while (ptr < end)
+ len += nextUtf32Character(ptr, end).len;
+ return len;
+}
+
+static int compareStringsInUtf8(QStringView lhs, QStringView rhs, Comparison mode) noexcept
+{
+ if (mode == Comparison::ForEquality)
+ return lhs == rhs ? 0 : 1;
+
+ // The UTF-16 length is *usually* comparable, but not always. There are
+ // pathological cases where they can be wrong, so we need to compare as if
+ // we were doing it in UTF-8. That includes the case of UTF-16 surrogate
+ // pairs, because qstring.cpp sorts them before U+E000-U+FFFF.
+ int diff = 0;
+ qsizetype len1 = 0;
+ qsizetype len2 = 0;
+ const char16_t *src1 = lhs.utf16();
+ const char16_t *src2 = rhs.utf16();
+ const char16_t *end1 = src1 + lhs.size();
+ const char16_t *end2 = src2 + rhs.size();
+
+ // first, scan until we find a difference (if any)
+ do {
+ auto r1 = nextUtf32Character(src1, end1);
+ auto r2 = nextUtf32Character(src2, end2);
+ len1 += r1.len;
+ len2 += r2.len;
+ diff = int(r1.c) - int(r2.c); // no underflow due to limited range
+ } while (src1 < end1 && src2 < end2 && diff == 0);
+
+ // compute the full length past this first difference
+ len1 += stringLengthInUtf8(src1, end1);
+ len2 += stringLengthInUtf8(src2, end2);
+ if (len1 == len2)
+ return diff;
+ return len1 < len2 ? -1 : 1;
+}
+
+static int compareStringsInUtf8(QUtf8StringView lhs, QStringView rhs, Comparison mode) noexcept
+{
+ // CBOR requires that the shortest of the two strings be sorted first, so
+ // we have to calculate the UTF-8 length of the UTF-16 string while
+ // comparing. Unlike the UTF-32 comparison above, we convert the UTF-16
+ // string to UTF-8 so we only need to decode one string.
+
+ const qsizetype len1 = lhs.size();
+ const auto src1 = reinterpret_cast<const uchar *>(lhs.data());
+ const char16_t *src2 = rhs.utf16();
+ const char16_t *const end2 = src2 + rhs.size();
+
+ // Compare the two strings until we find a difference.
+ int diff = 0;
+ qptrdiff idx1 = 0;
+ qsizetype len2 = 0;
+ do {
+ uchar utf8[4]; // longest possible Unicode character in UTF-8
+ uchar *ptr = utf8;
+ char16_t uc = *src2++;
+ int r = QUtf8Functions::toUtf8<QUtf8BaseTraits>(uc, ptr, src2, end2);
+ Q_UNUSED(r); // ignore failure to encode proper UTF-16 surrogates
+
+ qptrdiff n = ptr - utf8;
+ len2 += n;
+ if (len1 - idx1 < n)
+ return -1; // lhs is definitely shorter
+ diff = memcmp(src1 + idx1, utf8, n);
+ idx1 += n;
+ } while (diff == 0 && idx1 < len1 && src2 < end2);
+
+ if (mode == Comparison::ForEquality && diff)
+ return diff;
+ if ((idx1 == len1) != (src2 == end2)) {
+ // One of the strings ended earlier than the other
+ return idx1 == len1 ? -1 : 1;
+ }
+
+ // We found a difference and neither string ended, so continue calculating
+ // the UTF-8 length of rhs.
+ len2 += stringLengthInUtf8(src2, end2);
+
+ if (len1 != len2)
+ return len1 < len2 ? -1 : 1;
+ return diff;
+}
+
+static int compareStringsInUtf8(QStringView lhs, QUtf8StringView rhs, Comparison mode) noexcept
+{
+ return -compareStringsInUtf8(rhs, lhs, mode);
+}
+
QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
-static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2);
-static int compareElementNoData(const Element &e1, const Element &e2)
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2,
+ Comparison mode) noexcept;
+static int compareElementNoData(const Element &e1, const Element &e2) noexcept
{
Q_ASSERT(e1.type == e2.type);
@@ -1080,7 +1227,7 @@ static int compareElementNoData(const Element &e1, const Element &e2)
// -1 -> INT64_MAX + 1 = INT64_MAX - (-1)
// -2 -> INT64_MAX + 2 = INT64_MAX - (-2)
// INT64_MIN -> UINT64_MAX = INT64_MAX - INT64_MIN
- // Note how the unsigned arithmethic is well defined in C++ (it's
+ // Note how the unsigned arithmetic is well defined in C++ (it's
// always performed modulo 2^64).
auto makeSortable = [](qint64 v) {
quint64 u = quint64(v);
@@ -1111,15 +1258,16 @@ static int compareElementNoData(const Element &e1, const Element &e2)
}
static int compareElementRecursive(const QCborContainerPrivate *c1, const Element &e1,
- const QCborContainerPrivate *c2, const Element &e2)
+ const QCborContainerPrivate *c2, const Element &e2,
+ Comparison mode) noexcept
{
- int cmp = typeOrder(e1, e2);
+ int cmp = typeOrder(e1.type, e2.type);
if (cmp != 0)
return cmp;
if ((e1.flags & Element::IsContainer) || (e2.flags & Element::IsContainer))
return compareContainer(e1.flags & Element::IsContainer ? e1.container : nullptr,
- e2.flags & Element::IsContainer ? e2.container : nullptr);
+ e2.flags & Element::IsContainer ? e2.container : nullptr, mode);
// string data?
const ByteData *b1 = c1 ? c1->byteData(e1) : nullptr;
@@ -1127,11 +1275,6 @@ static int compareElementRecursive(const QCborContainerPrivate *c1, const Elemen
if (b1 || b2) {
auto len1 = b1 ? b1->len : 0;
auto len2 = b2 ? b2->len : 0;
-
- if (e1.flags & Element::StringIsUtf16)
- len1 /= 2;
- if (e2.flags & Element::StringIsUtf16)
- len2 /= 2;
if (len1 == 0 || len2 == 0)
return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
@@ -1140,57 +1283,37 @@ static int compareElementRecursive(const QCborContainerPrivate *c1, const Elemen
Q_ASSERT(b2);
// Officially with CBOR, we sort first the string with the shortest
- // UTF-8 length. The length of an ASCII string is the same as its UTF-8
- // and UTF-16 ones, but the UTF-8 length of a string is bigger than the
- // UTF-16 equivalent. Combinations are:
- // 1) UTF-16 and UTF-16
- // 2) UTF-16 and UTF-8 <=== this is the problem case
- // 3) UTF-16 and US-ASCII
- // 4) UTF-8 and UTF-8
- // 5) UTF-8 and US-ASCII
- // 6) US-ASCII and US-ASCII
- if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16)) {
- // Case 1: both UTF-16, so lengths are comparable.
- // (we can't use memcmp in little-endian machines)
- if (len1 == len2)
- return QtPrivate::compareStrings(b1->asStringView(), b2->asStringView());
- return len1 < len2 ? -1 : 1;
- }
+ // UTF-8 length. Since US-ASCII is just a subset of UTF-8, its length
+ // is the UTF-8 length. But the UTF-16 length may not be directly
+ // comparable.
+ if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16))
+ return compareStringsInUtf8(b1->asStringView(), b2->asStringView(), mode);
if (!(e1.flags & Element::StringIsUtf16) && !(e2.flags & Element::StringIsUtf16)) {
- // Cases 4, 5 and 6: neither is UTF-16, so lengths are comparable too
+ // Neither is UTF-16, so lengths are comparable too
// (this case includes byte arrays too)
- if (len1 == len2)
+ if (len1 == len2) {
+ if (mode == Comparison::ForEquality) {
+ // GCC optimizes this to __memcmpeq(); Clang to bcmp()
+ return memcmp(b1->byte(), b2->byte(), size_t(len1)) == 0 ? 0 : 1;
+ }
return memcmp(b1->byte(), b2->byte(), size_t(len1));
+ }
return len1 < len2 ? -1 : 1;
}
- if (!(e1.flags & Element::StringIsAscii) || !(e2.flags & Element::StringIsAscii)) {
- // Case 2: one of them is UTF-8 and the other is UTF-16, so lengths
- // are NOT comparable. We need to convert to UTF-16 first...
- auto string = [](const Element &e, const ByteData *b) {
- return e.flags & Element::StringIsUtf16 ? b->asQStringRaw() : b->toUtf8String();
- };
-
- QString s1 = string(e1, b1);
- QString s2 = string(e2, b2);
- if (s1.size() == s2.size())
- return s1.compare(s2);
- return s1.size() < s2.size() ? -1 : 1;
- }
-
- // Case 3 (UTF-16 and US-ASCII) remains, so lengths are comparable again
- if (len1 != len2)
- return len1 < len2 ? -1 : 1;
+ // Only one is UTF-16
if (e1.flags & Element::StringIsUtf16)
- return QtPrivate::compareStrings(b1->asStringView(), b2->asLatin1());
- return QtPrivate::compareStrings(b1->asLatin1(), b2->asStringView());
+ return compareStringsInUtf8(b1->asStringView(), b2->asUtf8StringView(), mode);
+ else
+ return compareStringsInUtf8(b1->asUtf8StringView(), b2->asStringView(), mode);
}
return compareElementNoData(e1, e2);
}
-static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2)
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2,
+ Comparison mode) noexcept
{
auto len1 = c1 ? c1->elements.size() : 0;
auto len2 = c2 ? c2->elements.size() : 0;
@@ -1202,7 +1325,7 @@ static int compareContainer(const QCborContainerPrivate *c1, const QCborContaine
for (qsizetype i = 0; i < len1; ++i) {
const Element &e1 = c1->elements.at(i);
const Element &e2 = c2->elements.at(i);
- int cmp = QCborContainerPrivate::compareElement_helper(c1, e1, c2, e2);
+ int cmp = compareElementRecursive(c1, e1, c2, e2, mode);
if (cmp)
return cmp;
}
@@ -1211,15 +1334,16 @@ static int compareContainer(const QCborContainerPrivate *c1, const QCborContaine
}
inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPrivate *c1, Element e1,
- const QCborContainerPrivate *c2, Element e2)
+ const QCborContainerPrivate *c2, Element e2,
+ Comparison mode) noexcept
{
- return compareElementRecursive(c1, e1, c2, e2);
+ return compareElementRecursive(c1, e1, c2, e2, mode);
}
/*!
- \fn bool QCborValue::operator==(const QCborValue &other) const
+ \fn bool QCborValue::operator==(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if they hold the same
+ Compares \a lhs and \a rhs, and returns true if they hold the same
contents, false otherwise. If each QCborValue contains an array or map, the
comparison is recursive to elements contained in them.
@@ -1230,9 +1354,9 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
*/
/*!
- \fn bool QCborValue::operator!=(const QCborValue &other) const
+ \fn bool QCborValue::operator!=(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if contents differ,
+ Compares \a lhs and \a rhs, and returns true if contents differ,
false otherwise. If each QCborValue contains an array or map, the comparison
is recursive to elements contained in them.
@@ -1241,12 +1365,20 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
\sa compare(), QCborValue::operator==(), QCborMap::operator==(),
operator==(), operator<()
*/
+bool comparesEqual(const QCborValue &lhs,
+ const QCborValue &rhs) noexcept
+{
+ Element e1 = QCborContainerPrivate::elementFromValue(lhs);
+ Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ return compareElementRecursive(lhs.container, e1, rhs.container, e2,
+ Comparison::ForEquality) == 0;
+}
/*!
- \fn bool QCborValue::operator<(const QCborValue &other) const
+ \fn bool QCborValue::operator<(const QCborValue &lhs, const QCborValue &rhs)
- Compares this value and \a other, and returns true if this value should be
- sorted before \a other, false otherwise. If each QCborValue contains an
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted before \a rhs, false otherwise. If each QCborValue contains an
array or map, the comparison is recursive to elements contained in them.
For more information on CBOR sorting order, see QCborValue::compare().
@@ -1256,6 +1388,47 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
*/
/*!
+ \fn bool QCborValue::operator<=(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted before \a rhs or is being equal to \a rhs, false otherwise.
+ If each QCborValue contains an array or map, the comparison is recursive
+ to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator<(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborValue::operator>(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted after \a rhs, false otherwise. If each QCborValue contains an
+ array or map, the comparison is recursive to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator>=(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
+ \fn bool QCborValue::operator>=(const QCborValue &lhs, const QCborValue &rhs)
+
+ Compares \a lhs and \a rhs, and returns true if \a lhs should be
+ sorted after \a rhs or is being equal to \a rhs, false otherwise.
+ If each QCborValue contains an array or map, the comparison is recursive
+ to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator>(), QCborMap::operator==(),
+ operator==(), operator!=()
+*/
+
+/*!
Compares this value and \a other, and returns an integer that indicates
whether this value should be sorted prior to (if the result is negative) or
after \a other (if the result is positive). If this function returns 0, the
@@ -1282,8 +1455,8 @@ inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPriv
\section3 Sorting order
- Sorting order in CBOR is defined in RFC 7049
- {https://tools.ietf.org/html/rfc7049#section-3.9}{section 3.9}, which
+ Sorting order in CBOR is defined in
+ \l{RFC 7049, section 3.9}, which
discusses the sorting of keys in a map when following the Canonical
encoding. According to the specification, "sorting is performed on the
bytes of the representation of the key data items" and lists as
@@ -1320,17 +1493,59 @@ int QCborValue::compare(const QCborValue &other) const
{
Element e1 = QCborContainerPrivate::elementFromValue(*this);
Element e2 = QCborContainerPrivate::elementFromValue(other);
- return compareElementRecursive(container, e1, other.container, e2);
+ return compareElementRecursive(container, e1, other.container, e2, Comparison::ForOrdering);
+}
+
+bool comparesEqual(const QCborArray &lhs, const QCborArray &rhs) noexcept
+{
+ return compareContainer(lhs.d.constData(), rhs.d.constData(), Comparison::ForEquality) == 0;
}
int QCborArray::compare(const QCborArray &other) const noexcept
{
- return compareContainer(d.data(), other.d.data());
+ return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
+}
+
+bool QCborArray::comparesEqual_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept
+{
+ if (typeOrder(QCborValue::Array, rhs.type()))
+ return false;
+ return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborArray::compareThreeWay_helper(const QCborArray &lhs, const QCborValue &rhs) noexcept
+{
+ int c = typeOrder(QCborValue::Array, rhs.type());
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool comparesEqual(const QCborMap &lhs, const QCborMap &rhs) noexcept
+{
+ return compareContainer(lhs.d.constData(), rhs.d.constData(), Comparison::ForEquality) == 0;
}
int QCborMap::compare(const QCborMap &other) const noexcept
{
- return compareContainer(d.data(), other.d.data());
+ return compareContainer(d.data(), other.d.data(), Comparison::ForOrdering);
+}
+
+bool QCborMap::comparesEqual_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept
+{
+ if (typeOrder(QCborValue::Map, rhs.type()))
+ return false;
+ return compareContainer(lhs.d.constData(), rhs.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborMap::compareThreeWay_helper(const QCborMap &lhs, const QCborValue &rhs) noexcept
+{
+ int c = typeOrder(QCborValue::Map, rhs.type());
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), rhs.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
}
#if QT_CONFIG(cborstreamwriter)
@@ -1353,6 +1568,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
else
writer.endMap();
} else if (idx < 0) {
+ Q_ASSERT_X(d != nullptr, "QCborValue", "Unexpected null container");
if (d->elements.size() != 2) {
// invalid state!
qWarning("QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
@@ -1363,6 +1579,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
writer.append(QCborTag(d->elements.at(0).value));
encodeToCbor(writer, d, 1, opt);
} else {
+ Q_ASSERT_X(d != nullptr, "QCborValue", "Unexpected null container");
// just one element
auto e = d->elements.at(idx);
const ByteData *b = d->byteData(idx);
@@ -1381,7 +1598,7 @@ static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate
return writer.append(b->asStringView());
return writer.appendTextString(b->byte(), b->len);
}
- return writer.append(QLatin1String());
+ return writer.append(QLatin1StringView());
case QCborValue::Array:
case QCborValue::Map:
@@ -1480,6 +1697,19 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
return e;
}
+// Clamp allocation to avoid crashing due to corrupt stream. This also
+// ensures we never overflow qsizetype. The returned length is doubled for Map
+// entries to account for key-value pairs.
+static qsizetype clampedContainerLength(const QCborStreamReader &reader)
+{
+ if (!reader.isLengthKnown())
+ return 0;
+ int mapShift = reader.isMap() ? 1 : 0;
+ quint64 shiftedMaxElements = MaximumPreallocatedElementCount >> mapShift;
+ qsizetype len = qsizetype(qMin(reader.length(), shiftedMaxElements));
+ return len << mapShift;
+}
+
static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
{
if (Q_UNLIKELY(remainingRecursionDepth == 0)) {
@@ -1488,33 +1718,27 @@ static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &
}
QCborContainerPrivate *d = nullptr;
- int mapShift = reader.isMap() ? 1 : 0;
- if (reader.isLengthKnown()) {
- quint64 len = reader.length();
-
- // Clamp allocation to 1M elements (avoids crashing due to corrupt
- // stream or loss of precision when converting from quint64 to
- // QList::size_type).
- len = qMin(len, quint64(1024 * 1024 - 1));
- if (len) {
- d = new QCborContainerPrivate;
- d->ref.storeRelaxed(1);
- d->elements.reserve(qsizetype(len) << mapShift);
- }
- } else {
- d = new QCborContainerPrivate;
- d->ref.storeRelaxed(1);
+ {
+ // in case QList::reserve throws
+ QExplicitlySharedDataPointer u(new QCborContainerPrivate);
+ if (qsizetype len = clampedContainerLength(reader))
+ u->elements.reserve(len);
+ d = u.take();
}
reader.enterContainer();
- if (reader.lastError() != QCborError::NoError)
+ if (reader.lastError() != QCborError::NoError) {
+ d->elements.clear();
return d;
+ }
while (reader.hasNext() && reader.lastError() == QCborError::NoError)
d->decodeValueFromCbor(reader, remainingRecursionDepth - 1);
if (reader.lastError() == QCborError::NoError)
reader.leaveContainer();
+ else
+ d->elements.squeeze();
return d;
}
@@ -1555,41 +1779,10 @@ inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, Q
qt_cbor_stream_set_error(reader.d.data(), error);
}
+extern QCborStreamReader::StringResultCode qt_cbor_append_string_chunk(QCborStreamReader &reader, QByteArray *data);
+
void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
{
- auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
- // this duplicates a lot of addByteData, but with overflow checking
- QByteArray::size_type newSize;
- QByteArray::size_type increment = sizeof(QtCbor::ByteData);
- QByteArray::size_type alignment = alignof(QtCbor::ByteData);
- QByteArray::size_type offset = data.size();
-
- // calculate the increment we want
- if (add_overflow(increment, len, &increment))
- return -1;
-
- // align offset
- if (add_overflow(offset, alignment - 1, &offset))
- return -1;
- offset &= ~(alignment - 1);
-
- // and calculate the final size
- if (add_overflow(offset, increment, &newSize))
- return -1;
- if (newSize > MaxByteArraySize)
- return -1;
-
- data.resize(newSize);
- return offset;
- };
- auto dataPtr = [this]() {
- // Null happens when we're reading zero bytes.
- Q_ASSERT(data.isNull() || data.isDetached());
- return const_cast<char *>(data.constData());
- };
-
- Element e = {};
- e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
if (reader.lastError() != QCborError::NoError)
return;
@@ -1603,56 +1796,73 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
return;
}
- // allocate space, but only if there will be data
- if (len != 0 || !reader.isLengthKnown()) {
- e.flags = Element::HasByteData;
- e.value = addByteData_local(len);
- if (e.value < 0) {
+ Element e = {};
+ e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
+ if (len || !reader.isLengthKnown()) {
+ // The use of size_t means none of the operations here can overflow because
+ // all inputs are less than half SIZE_MAX.
+ constexpr size_t EstimatedOverhead = 16;
+ constexpr size_t MaxMemoryIncrement = 16384;
+ size_t offset = data.size();
+
+ // add space for aligned ByteData (this can't overflow)
+ offset += sizeof(QtCbor::ByteData) + alignof(QtCbor::ByteData);
+ offset &= ~(alignof(QtCbor::ByteData) - 1);
+ if (offset > size_t(QByteArray::max_size())) {
// overflow
setErrorInReader(reader, { QCborError::DataTooLarge });
return;
}
+
+ // and calculate the size we want to have
+ size_t newCapacity = offset + len; // can't overflow
+ if (size_t(len) > MaxMemoryIncrement - EstimatedOverhead) {
+ // there's a non-zero chance that we won't need this memory at all,
+ // so capa how much we allocate
+ newCapacity = offset + MaxMemoryIncrement - EstimatedOverhead;
+ }
+ if (newCapacity > size_t(QByteArray::max_size())) {
+ // this may cause an allocation failure
+ newCapacity = QByteArray::max_size();
+ }
+ if (newCapacity > size_t(data.capacity()))
+ data.reserve(newCapacity);
+ data.resize(offset + sizeof(QtCbor::ByteData));
+ e.value = offset;
+ e.flags = Element::HasByteData;
}
// read chunks
bool isAscii = (e.type == QCborValue::String);
- auto r = reader.readStringChunk(dataPtr() + e.value + sizeof(ByteData), len);
- while (r.status == QCborStreamReader::Ok) {
+ QCborStreamReader::StringResultCode status = qt_cbor_append_string_chunk(reader, &data);
+ while (status == QCborStreamReader::Ok) {
if (e.type == QCborValue::String && len) {
// verify UTF-8 string validity
- auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
+ auto utf8result = QUtf8::isValidUtf8(QByteArrayView(data).last(len));
if (!utf8result.isValidUtf8) {
- r.status = QCborStreamReader::Error;
+ status = QCborStreamReader::Error;
setErrorInReader(reader, { QCborError::InvalidUtf8String });
break;
}
isAscii = isAscii && utf8result.isValidAscii;
}
- // allocate space for the next chunk
rawlen = reader.currentStringChunkSize();
len = rawlen;
if (len == rawlen) {
- auto oldSize = data.size();
- auto newSize = oldSize;
- if (!add_overflow(newSize, len, &newSize) && newSize < MaxByteArraySize) {
- if (newSize != oldSize)
- data.resize(newSize);
-
- // read the chunk
- r = reader.readStringChunk(dataPtr() + oldSize, len);
- continue;
- }
+ status = qt_cbor_append_string_chunk(reader, &data);
+ } else {
+ // error
+ status = QCborStreamReader::Error;
+ setErrorInReader(reader, { QCborError::DataTooLarge });
}
-
- // error
- r.status = QCborStreamReader::Error;
- setErrorInReader(reader, { QCborError::DataTooLarge });
}
// update size
- if (r.status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
- auto b = new (dataPtr() + e.value) ByteData;
+ if (status == QCborStreamReader::EndOfString && e.flags & Element::HasByteData) {
+ Q_ASSERT(data.isDetached());
+ const char *ptr = data.constData() + e.value;
+ auto b = new (const_cast<char *>(ptr)) ByteData;
b->len = data.size() - e.value - int(sizeof(*b));
usedData += b->len;
@@ -1664,21 +1874,18 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
// check that this UTF-8 text string can be loaded onto a QString
if (e.type == QCborValue::String) {
- if (Q_UNLIKELY(b->len > MaxStringSize)) {
+ if (Q_UNLIKELY(b->len > QString::max_size())) {
setErrorInReader(reader, { QCborError::DataTooLarge });
- r.status = QCborStreamReader::Error;
+ status = QCborStreamReader::Error;
}
}
}
- if (r.status == QCborStreamReader::Error) {
- // There can only be errors if there was data to be read.
- Q_ASSERT(e.flags & Element::HasByteData);
+ if (status == QCborStreamReader::Error) {
data.truncate(e.value);
- return;
+ } else {
+ elements.append(e);
}
-
- elements.append(e);
}
void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth)
@@ -1727,7 +1934,6 @@ QCborValue::QCborValue(const QByteArray &ba)
container->ref.storeRelaxed(1);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Creates a QCborValue with string value \a s. The value can later be
retrieved using toString().
@@ -1735,7 +1941,6 @@ QCborValue::QCborValue(const QByteArray &ba)
\sa toString(), isString(), isByteArray()
*/
QCborValue::QCborValue(const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
-#endif
/*!
Creates a QCborValue with string value \a s. The value can later be
@@ -1753,12 +1958,12 @@ QCborValue::QCborValue(QStringView s)
/*!
\overload
- Creates a QCborValue with string value \a s. The value can later be
- retrieved using toString().
+ Creates a QCborValue with the Latin-1 string viewed by \a s.
+ The value can later be retrieved using toString().
\sa toString(), isString(), isByteArray()
*/
-QCborValue::QCborValue(QLatin1String s)
+QCborValue::QCborValue(QLatin1StringView s)
: n(0), container(new QCborContainerPrivate), t(String)
{
container->append(s);
@@ -1819,7 +2024,7 @@ QCborValue::QCborValue(QCborTag tag, const QCborValue &tv)
/*!
Copies the contents of \a other into this object.
*/
-QCborValue::QCborValue(const QCborValue &other)
+QCborValue::QCborValue(const QCborValue &other) noexcept
: n(other.n), container(other.container), t(other.t)
{
if (container)
@@ -1864,7 +2069,6 @@ QCborValue::QCborValue(const QUrl &url)
t = Url;
container->elements[1].type = String;
}
-#endif
#if QT_CONFIG(regularexpression)
/*!
@@ -1903,6 +2107,7 @@ QCborValue::QCborValue(const QUuid &uuid)
// change our type
t = Uuid;
}
+#endif
// destructor
void QCborValue::dispose()
@@ -1913,15 +2118,10 @@ void QCborValue::dispose()
/*!
Replaces the contents of this QCborObject with a copy of \a other.
*/
-QCborValue &QCborValue::operator=(const QCborValue &other)
+QCborValue &QCborValue::operator=(const QCborValue &other) noexcept
{
- if (other.container)
- other.container->ref.ref();
- if (container)
- container->deref();
-
n = other.n;
- container = other.container;
+ assignContainer(container, other.container);
t = other.t;
return *this;
}
@@ -2039,7 +2239,6 @@ QUrl QCborValue::toUrl(const QUrl &defaultValue) const
return QUrl::fromEncoded(byteData->asByteArrayView());
}
-#endif
#if QT_CONFIG(regularexpression)
/*!
@@ -2082,6 +2281,7 @@ QUuid QCborValue::toUuid(const QUuid &defaultValue) const
return QUuid::fromRfc4122(byteData->asByteArrayView());
}
+#endif
/*!
\fn QCborArray QCborValue::toArray() const
@@ -2122,7 +2322,8 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborArray(*dd) : defaultValue;
+ // return QCborArray(*dd); but that's UB if dd is nullptr
+ return dd ? QCborArray(*dd) : QCborArray();
}
/*!
@@ -2164,7 +2365,8 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
Q_ASSERT(n == -1 || container == nullptr);
if (n < 0)
dd = container;
- return dd ? QCborMap(*dd) : defaultValue;
+ // return QCborMap(*dd); but that's UB if dd is nullptr
+ return dd ? QCborMap(*dd) : QCborMap();
}
/*!
@@ -2181,9 +2383,7 @@ QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
*/
const QCborValue QCborValue::operator[](const QString &key) const
{
- if (isMap())
- return toMap().value(key);
- return QCborValue();
+ return QCborContainerPrivate::findCborMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2200,11 +2400,9 @@ const QCborValue QCborValue::operator[](const QString &key) const
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-const QCborValue QCborValue::operator[](QLatin1String key) const
+const QCborValue QCborValue::operator[](QLatin1StringView key) const
{
- if (isMap())
- return toMap().value(key);
- return QCborValue();
+ return QCborContainerPrivate::findCborMapKey(*this, key);
}
/*!
@@ -2220,44 +2418,53 @@ const QCborValue QCborValue::operator[](QLatin1String key) const
*/
const QCborValue QCborValue::operator[](qint64 key) const
{
- if (isMap())
- return toMap().value(key);
- if (isArray())
- return toArray().at(key);
- return QCborValue();
+ if (isArray() && container && quint64(key) < quint64(container->elements.size()))
+ return container->valueAt(key);
+ return QCborContainerPrivate::findCborMapKey(*this, key);
}
-/*!
- \internal
- */
-static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array)
-{
- if (array.size())
- qWarning("Using CBOR array as map forced conversion");
- QCborMap map;
- for (qsizetype i = array.size(); i-- > 0; ) {
- QCborValue entry = array.at(i);
- // Ignore padding entries that may have been added to grow the array
- // when inserting past its end:
- if (!entry.isInvalid())
- map[i] = entry;
- }
- return map;
+static bool shouldArrayRemainArray(qint64 key, QCborValue::Type t, QCborContainerPrivate *container)
+{
+ constexpr qint64 LargeKey = 0x10000;
+ if (t != QCborValue::Array)
+ return false;
+ if (key < 0)
+ return false; // negative keys can't be an array index
+ if (key < LargeKey)
+ return true;
+
+ // Only convert to map if key is greater than array size + 1
+ qsizetype currentSize = container ? container->elements.size() : 0;
+ return key <= currentSize;
}
/*!
\internal
*/
-static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size)
+static void convertArrayToMap(QCborContainerPrivate *&array)
{
- auto replace = QCborContainerPrivate::detach(container, size);
- Q_ASSERT(replace);
- if (replace != container) {
- if (container)
- container->deref();
- replace->ref.ref();
+ if (Q_LIKELY(!array || array->elements.isEmpty()))
+ return;
+
+ // The Q_LIKELY and the qWarning mark the rest of this function as unlikely
+ qWarning("Using CBOR array as map forced conversion");
+
+ qsizetype size = array->elements.size();
+ QCborContainerPrivate *map = QCborContainerPrivate::detach(array, size * 2);
+ map->elements.resize(size * 2);
+
+ // this may be an in-place copy, so we have to do it from the end
+ auto dst = map->elements.begin();
+ auto src = array->elements.constBegin();
+ for (qsizetype i = size - 1; i >= 0; --i) {
+ Q_ASSERT(src->type != QCborValue::Invalid);
+ dst[i * 2 + 1] = src[i];
}
- return replace;
+ for (qsizetype i = 0; i < size; ++i)
+ dst[i * 2] = { i, QCborValue::Integer };
+
+ // update reference counts
+ assignContainer(array, map);
}
/*!
@@ -2267,16 +2474,48 @@ static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizet
{
auto replace = QCborContainerPrivate::grow(container, index);
Q_ASSERT(replace);
- if (replace != container) {
- if (container)
- container->deref();
- replace->ref.ref();
- }
if (replace->elements.size() == index)
replace->append(Undefined());
else
Q_ASSERT(replace->elements.size() > index);
- return replace;
+ return assignContainer(container, replace);
+}
+
+template <typename KeyType> inline QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborValue &self, KeyType key)
+{
+ // we need a map, so convert if necessary
+ if (self.isArray())
+ convertArrayToMap(self.container);
+ else if (!self.isMap())
+ self = QCborValue(QCborValue::Map);
+ self.t = QCborValue::Map;
+ self.n = -1;
+
+ QCborValueRef result = findOrAddMapKey<KeyType>(self.container, key);
+ assignContainer(self.container, result.d);
+ return result;
+}
+
+template<typename KeyType> QCborValueRef
+QCborContainerPrivate::findOrAddMapKey(QCborValueRef self, KeyType key)
+{
+ auto &e = self.d->elements[self.i];
+
+ // we need a map, so convert if necessary
+ if (e.type == QCborValue::Array) {
+ convertArrayToMap(e.container);
+ } else if (e.type != QCborValue::Map) {
+ if (e.flags & QtCbor::Element::IsContainer)
+ e.container->deref();
+ e.container = nullptr;
+ }
+ e.flags = QtCbor::Element::IsContainer;
+ e.type = QCborValue::Map;
+
+ QCborValueRef result = findOrAddMapKey<KeyType>(e.container, key);
+ assignContainer(e.container, result.d);
+ return result;
}
/*!
@@ -2294,30 +2533,7 @@ static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizet
*/
QCborValueRef QCborValue::operator[](const QString &key)
{
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2335,32 +2551,9 @@ QCborValueRef QCborValue::operator[](const QString &key)
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-QCborValueRef QCborValue::operator[](QLatin1String key)
+QCborValueRef QCborValue::operator[](QLatin1StringView key)
{
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -2381,40 +2574,14 @@ QCborValueRef QCborValue::operator[](QLatin1String key)
*/
QCborValueRef QCborValue::operator[](qint64 key)
{
- if (isArray() && key >= 0 && key < 0x10000) {
+ if (shouldArrayRemainArray(key, t, container)) {
container = maybeGrow(container, key);
return { container, qsizetype(key) };
}
- if (!isMap())
- *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap());
-
- const qsizetype size = container ? container->elements.size() : 0;
- Q_ASSERT(!(size & 1));
- qsizetype index = size + 1;
- bool found = false;
- if (container) {
- QCborMap proxy(*container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- container = maybeDetach(container, size + (found ? 0 : 2));
- Q_ASSERT(container);
- if (!found) {
- container->append(key);
- container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(container->elements.size() & 1));
- Q_ASSERT(index < container->elements.size());
- return { container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
#if QT_CONFIG(cborstreamreader)
-enum { MaximumRecursionDepth = 1024 };
-
/*!
Decodes one item from the CBOR stream found in \a reader and returns the
equivalent representation. This function is recursive: if the item is a map
@@ -2650,10 +2817,12 @@ Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOption
}
}
+# if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
{
concrete().toCbor(writer, opt);
}
+# endif
#endif // QT_CONFIG(cborstreamwriter)
void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
@@ -2672,6 +2841,151 @@ void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other)
that = other.concrete();
}
+bool QCborValueConstRef::concreteBoolean(QCborValueConstRef self, bool defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::False && e.type != QCborValue::True)
+ return defaultValue;
+ return e.type == QCborValue::True;
+}
+
+double QCborValueConstRef::concreteDouble(QCborValueConstRef self, double defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type == QCborValue::Integer)
+ return e.value;
+ if (e.type != QCborValue::Double)
+ return defaultValue;
+ return e.fpvalue();
+}
+
+qint64 QCborValueConstRef::concreteIntegral(QCborValueConstRef self, qint64 defaultValue) noexcept
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ QCborValue::Type t = e.type;
+ if (t == QCborValue::Double)
+ return e.fpvalue();
+ if (t != QCborValue::Integer)
+ return defaultValue;
+ return e.value;
+}
+
+QByteArray QCborValueConstRef::concreteByteArray(QCborValueConstRef self,
+ const QByteArray &defaultValue)
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::ByteArray)
+ return defaultValue;
+ return self.d->byteArrayAt(self.i);
+}
+
+QString QCborValueConstRef::concreteString(QCborValueConstRef self, const QString &defaultValue)
+{
+ QtCbor::Element e = self.d->elements.at(self.i);
+ if (e.type != QCborValue::String)
+ return defaultValue;
+ return self.d->stringAt(self.i);
+}
+
+bool
+QCborValueConstRef::comparesEqual_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ return compareElementRecursive(lhs.d, e1, rhs.d, e2, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborValueConstRef::compareThreeWay_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = compareElementRecursive(lhs.d, e1, rhs.d, e2, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool
+QCborValueConstRef::comparesEqual_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ return compareElementRecursive(lhs.d, e1, rhs.container, e2, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborValueConstRef::compareThreeWay_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept
+{
+ QtCbor::Element e1 = lhs.d->elements.at(lhs.i);
+ QtCbor::Element e2 = QCborContainerPrivate::elementFromValue(rhs);
+ int c = compareElementRecursive(lhs.d, e1, rhs.container, e2, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool QCborArray::comparesEqual_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ if (typeOrder(QCborValue::Array, e2.type))
+ return false;
+ return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborArray::compareThreeWay_helper(const QCborArray &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = typeOrder(QCborValue::Array, e2.type);
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+bool QCborMap::comparesEqual_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ if (typeOrder(QCborValue::Array, e2.type))
+ return false;
+ return compareContainer(lhs.d.constData(), e2.container, Comparison::ForEquality) == 0;
+}
+
+Qt::strong_ordering
+QCborMap::compareThreeWay_helper(const QCborMap &lhs, QCborValueConstRef rhs) noexcept
+{
+ QtCbor::Element e2 = rhs.d->elements.at(rhs.i);
+ int c = typeOrder(QCborValue::Map, e2.type);
+ if (c == 0)
+ c = compareContainer(lhs.d.constData(), e2.container, Comparison::ForOrdering);
+ return Qt::compareThreeWay(c, 0);
+}
+
+QCborValue QCborValueConstRef::concrete(QCborValueConstRef self) noexcept
+{
+ return self.d->valueAt(self.i);
+}
+
+QCborValue::Type QCborValueConstRef::concreteType(QCborValueConstRef self) noexcept
+{
+ return self.d->elements.at(self.i).type;
+}
+
+const QCborValue QCborValueConstRef::operator[](const QString &key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+const QCborValue QCborValueConstRef::operator[](const QLatin1StringView key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+const QCborValue QCborValueConstRef::operator[](qint64 key) const
+{
+ const QCborValue item = d->valueAt(i);
+ return item[key];
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QCborValue QCborValueRef::concrete(QCborValueRef self) noexcept
{
return self.d->valueAt(self.i);
@@ -2698,8 +3012,7 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
*/
const QCborValue QCborValueRef::operator[](const QString &key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2718,10 +3031,9 @@ const QCborValue QCborValueRef::operator[](const QString &key) const
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-const QCborValue QCborValueRef::operator[](QLatin1String key) const
+const QCborValue QCborValueRef::operator[](QLatin1StringView key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2738,8 +3050,7 @@ const QCborValue QCborValueRef::operator[](QLatin1String key) const
*/
const QCborValue QCborValueRef::operator[](qint64 key) const
{
- const QCborValue item = d->valueAt(i);
- return item[key];
+ return QCborValueConstRef::operator[](key);
}
/*!
@@ -2758,48 +3069,7 @@ const QCborValue QCborValueRef::operator[](qint64 key) const
*/
QCborValueRef QCborValueRef::operator[](const QString &key)
{
- auto &e = d->elements[i];
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, qToStringViewIgnoringNull(key));
}
/*!
@@ -2817,50 +3087,9 @@ QCborValueRef QCborValueRef::operator[](const QString &key)
\sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
QCborMap::find()
*/
-QCborValueRef QCborValueRef::operator[](QLatin1String key)
+QCborValueRef QCborValueRef::operator[](QLatin1StringView key)
{
- auto &e = d->elements[i];
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
/*!
@@ -2882,54 +3111,14 @@ QCborValueRef QCborValueRef::operator[](QLatin1String key)
QCborValueRef QCborValueRef::operator[](qint64 key)
{
auto &e = d->elements[i];
- if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) {
+ if (shouldArrayRemainArray(key, e.type, e.container)) {
e.container = maybeGrow(e.container, key);
+ e.flags |= QtCbor::Element::IsContainer;
return { e.container, qsizetype(key) };
}
- qsizetype size = 0;
- if (e.flags & QtCbor::Element::IsContainer) {
- if (e.container) {
- if (e.type == QCborValue::Array) {
- QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container)));
- qSwap(e.container, repack.container);
- } else if (e.type != QCborValue::Map) {
- e.container->deref();
- e.container = nullptr;
- }
- }
- e.type = QCborValue::Map;
- if (e.container)
- size = e.container->elements.size();
- } else {
- // Stomp any prior e.value, replace with a map (that we'll grow)
- e.container = nullptr;
- e.type = QCborValue::Map;
- e.flags = QtCbor::Element::IsContainer;
- }
- Q_ASSERT(!(size & 1));
-
- qsizetype index = size + 1;
- bool found = false;
- if (e.container) {
- QCborMap proxy(*e.container);
- auto it = proxy.constFind(key);
- if (it < proxy.constEnd()) {
- found = true;
- index = it.item.i;
- }
- }
-
- e.container = maybeDetach(e.container, size + (found ? 0 : 2));
- Q_ASSERT(e.container);
- if (!found) {
- e.container->append(key);
- e.container->append(QCborValue());
- }
- Q_ASSERT(index & 1 && !(e.container->elements.size() & 1));
- Q_ASSERT(index < e.container->elements.size());
- return { e.container, index };
+ return QCborContainerPrivate::findOrAddMapKey(*this, key);
}
-
+#endif // < Qt 7
inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
: d(&dd)
@@ -2977,13 +3166,13 @@ size_t qHash(const QCborValue &value, size_t seed)
#ifndef QT_BOOTSTRAPPED
case QCborValue::Url:
return qHash(value.toUrl(), seed);
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
case QCborValue::RegularExpression:
return qHash(value.toRegularExpression(), seed);
-#endif
+# endif
case QCborValue::Uuid:
return qHash(value.toUuid(), seed);
+#endif
case QCborValue::Invalid:
return seed;
default:
@@ -2994,68 +3183,6 @@ size_t qHash(const QCborValue &value, size_t seed)
return qHash(value.toSimpleType(), seed);
}
-#if !defined(QT_NO_DEBUG_STREAM)
-static QDebug debugContents(QDebug &dbg, const QCborValue &v)
-{
- switch (v.type()) {
- case QCborValue::Integer:
- return dbg << v.toInteger();
- case QCborValue::ByteArray:
- return dbg << "QByteArray(" << v.toByteArray() << ')';
- case QCborValue::String:
- return dbg << v.toString();
- case QCborValue::Array:
- return dbg << v.toArray();
- case QCborValue::Map:
- return dbg << v.toMap();
- case QCborValue::Tag:
- dbg << v.tag() << ", ";
- return debugContents(dbg, v.taggedValue());
- case QCborValue::SimpleType:
- break;
- case QCborValue::True:
- return dbg << true;
- case QCborValue::False:
- return dbg << false;
- case QCborValue::Null:
- return dbg << "nullptr";
- case QCborValue::Undefined:
- return dbg;
- case QCborValue::Double: {
- qint64 i = qint64(v.toDouble());
- if (i == v.toDouble())
- return dbg << i << ".0";
- else
- return dbg << v.toDouble();
- }
- case QCborValue::DateTime:
- return dbg << v.toDateTime();
-#ifndef QT_BOOTSTRAPPED
- case QCborValue::Url:
- return dbg << v.toUrl();
-#endif
-#if QT_CONFIG(regularexpression)
- case QCborValue::RegularExpression:
- return dbg << v.toRegularExpression();
-#endif
- case QCborValue::Uuid:
- return dbg << v.toUuid();
- case QCborValue::Invalid:
- return dbg << "<invalid>";
- default:
- break;
- }
- if (v.isSimpleType())
- return dbg << v.toSimpleType();
- return dbg << "<unknown type " << Qt::hex << int(v.type()) << Qt::dec << '>';
-}
-QDebug operator<<(QDebug dbg, const QCborValue &v)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QCborValue(";
- return debugContents(dbg, v) << ')';
-}
-
Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
{
switch (st) {
@@ -3071,16 +3198,6 @@ Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
return nullptr;
}
-QDebug operator<<(QDebug dbg, QCborSimpleType st)
-{
- QDebugStateSaver saver(dbg);
- const char *id = qt_cbor_simpletype_id(st);
- if (id)
- return dbg.nospace() << "QCborSimpleType::" << id;
-
- return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
-}
-
Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
{
// Casting to QCborKnownTags's underlying type will make the comparison
@@ -3139,6 +3256,84 @@ Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
return nullptr;
}
+#if !defined(QT_NO_DEBUG_STREAM)
+static QDebug debugContents(QDebug &dbg, const QCborValue &v)
+{
+ switch (v.type()) {
+ case QCborValue::Integer:
+ return dbg << v.toInteger();
+ case QCborValue::ByteArray:
+ return dbg << "QByteArray(" << v.toByteArray() << ')';
+ case QCborValue::String:
+ return dbg << v.toString();
+ case QCborValue::Array:
+ return dbg << v.toArray();
+ case QCborValue::Map:
+ return dbg << v.toMap();
+ case QCborValue::Tag: {
+ QCborTag tag = v.tag();
+ const char *id = qt_cbor_tag_id(tag);
+ if (id)
+ dbg.nospace() << "QCborKnownTags::" << id << ", ";
+ else
+ dbg.nospace() << "QCborTag(" << quint64(tag) << "), ";
+ return dbg << v.taggedValue();
+ }
+ case QCborValue::SimpleType:
+ break;
+ case QCborValue::True:
+ return dbg << true;
+ case QCborValue::False:
+ return dbg << false;
+ case QCborValue::Null:
+ return dbg << "nullptr";
+ case QCborValue::Undefined:
+ return dbg;
+ case QCborValue::Double: {
+ qint64 i;
+ if (convertDoubleTo(v.toDouble(), &i))
+ return dbg << i << ".0";
+ else
+ return dbg << v.toDouble();
+ }
+ case QCborValue::DateTime:
+ return dbg << v.toDateTime();
+#ifndef QT_BOOTSTRAPPED
+ case QCborValue::Url:
+ return dbg << v.toUrl();
+#if QT_CONFIG(regularexpression)
+ case QCborValue::RegularExpression:
+ return dbg << v.toRegularExpression();
+#endif
+ case QCborValue::Uuid:
+ return dbg << v.toUuid();
+#endif
+ case QCborValue::Invalid:
+ return dbg << "<invalid>";
+ default:
+ break;
+ }
+ if (v.isSimpleType())
+ return dbg << v.toSimpleType();
+ return dbg << "<unknown type 0x" << Qt::hex << int(v.type()) << Qt::dec << '>';
+}
+QDebug operator<<(QDebug dbg, const QCborValue &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCborValue(";
+ return debugContents(dbg, v) << ')';
+}
+
+QDebug operator<<(QDebug dbg, QCborSimpleType st)
+{
+ QDebugStateSaver saver(dbg);
+ const char *id = qt_cbor_simpletype_id(st);
+ if (id)
+ return dbg.nospace() << "QCborSimpleType::" << id;
+
+ return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
+}
+
QDebug operator<<(QDebug dbg, QCborTag tag)
{
QDebugStateSaver saver(dbg);
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index b8c3dce294..93adbec344 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORVALUE_H
#define QCBORVALUE_H
#include <QtCore/qbytearray.h>
-#include <QtCore/qdatetime.h>
#include <QtCore/qcborcommon.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qdatetime.h>
#if QT_CONFIG(regularexpression)
# include <QtCore/qregularexpression.h>
#endif
@@ -52,16 +17,12 @@
#include <QtCore/quuid.h>
#include <QtCore/qvariant.h>
-// See qcborcommon.h for why we check
-#if defined(QT_X11_DEFINES_FOUND)
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
# undef True
# undef False
#endif
-#if 0 && __has_include(<compare>)
-# include <compare>
-#endif
-
QT_BEGIN_NAMESPACE
class QCborArray;
@@ -146,11 +107,9 @@ public:
QCborValue(QCborSimpleType st) : t(type_helper(st)) {}
QCborValue(const QByteArray &ba);
-#if QT_STRINGVIEW_LEVEL < 2
QCborValue(const QString &s);
-#endif
QCborValue(QStringView s);
- QCborValue(QLatin1String s);
+ QCborValue(QLatin1StringView s);
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN QCborValue(const char *s) : QCborValue(QString::fromUtf8(s)) {}
#endif
@@ -166,37 +125,30 @@ public:
explicit QCborValue(const QDateTime &dt);
#ifndef QT_BOOTSTRAPPED
explicit QCborValue(const QUrl &url);
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
explicit QCborValue(const QRegularExpression &rx);
-#endif
+# endif
explicit QCborValue(const QUuid &uuid);
+#endif
~QCborValue() { if (container) dispose(); }
// make sure const char* doesn't go call the bool constructor
QCborValue(const void *) = delete;
- QCborValue(const QCborValue &other);
+ QCborValue(const QCborValue &other) noexcept;
QCborValue(QCborValue &&other) noexcept
- : n(other.n), container(other.container), t(other.t)
+ : n(other.n), container(std::exchange(other.container, nullptr)), t(std::exchange(other.t, Undefined))
{
- other.t = Undefined;
- other.container = nullptr;
- }
- QCborValue &operator=(const QCborValue &other);
- QCborValue &operator=(QCborValue &&other) noexcept
- {
- QCborValue tmp(std::move(other));
- swap(tmp);
- return *this;
}
+ QCborValue &operator=(const QCborValue &other) noexcept;
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCborValue)
void swap(QCborValue &other) noexcept
{
- qSwap(n, other.n);
- qSwap(container, other.container);
- qSwap(t, other.t);
+ std::swap(n, other.n);
+ qt_ptr_swap(container, other.container);
+ std::swap(t, other.t);
}
Type type() const { return t; }
@@ -245,11 +197,13 @@ public:
QByteArray toByteArray(const QByteArray &defaultValue = {}) const;
QString toString(const QString &defaultValue = {}) const;
QDateTime toDateTime(const QDateTime &defaultValue = {}) const;
+#ifndef QT_BOOTSTRAPPED
QUrl toUrl(const QUrl &defaultValue = {}) const;
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const;
-#endif
+# endif
QUuid toUuid(const QUuid &defaultValue = {}) const;
+#endif
// only forward-declared, need split functions
QCborArray toArray() const;
@@ -258,26 +212,18 @@ public:
QCborMap toMap(const QCborMap &defaultValue) const;
const QCborValue operator[](const QString &key) const;
- const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](QLatin1StringView key) const;
const QCborValue operator[](qint64 key) const;
QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](QLatin1StringView key);
QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborValue &other) const
- {
- int c = compare(other);
- if (c > 0) return std::partial_ordering::greater;
- if (c == 0) return std::partial_ordering::equivalent;
- return std::partial_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborValue &other) const noexcept
{ return compare(other) == 0; }
bool operator!=(const QCborValue &other) const noexcept
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborValue &other) const
{ return compare(other) < 0; }
#endif
@@ -303,6 +249,19 @@ public:
QString toDiagnosticNotation(DiagnosticNotationOptions opts = Compact) const;
private:
+ friend Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+ bool comparesEqual(const QCborValue &lhs, const QCborValue &rhs) noexcept;
+ friend Qt::strong_ordering compareThreeWay(const QCborValue &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ int c = lhs.compare(rhs);
+ return Qt::compareThreeWay(c, 0);
+ }
+
+ Q_DECLARE_STRONGLY_ORDERED(QCborValue)
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborValueConstRef;
friend class QCborValueRef;
friend class QCborContainerPrivate;
friend class QJsonPrivate::Value;
@@ -325,23 +284,172 @@ private:
return d;
}
- Q_DECL_CONSTEXPR static Type type_helper(QCborSimpleType st)
+ constexpr static Type type_helper(QCborSimpleType st)
{
return Type(quint8(st) | SimpleType);
}
- Q_DECL_CONSTEXPR static bool isTag_helper(Type tt)
+ constexpr static bool isTag_helper(Type tt)
{
return tt == Tag || tt >= 0x10000;
}
};
Q_DECLARE_SHARED(QCborValue)
-class Q_CORE_EXPORT QCborValueRef
+class QCborValueConstRef
{
public:
+ QCborValueConstRef(const QCborValueConstRef &) = default;
+ QCborValueConstRef &operator=(const QCborValueConstRef &) = delete;
operator QCborValue() const { return concrete(); }
+ QCborValue::Type type() const { return concreteType(*this); }
+ bool isInteger() const { return type() == QCborValue::Integer; }
+ bool isByteArray() const { return type() == QCborValue::ByteArray; }
+ bool isString() const { return type() == QCborValue::String; }
+ bool isArray() const { return type() == QCborValue::Array; }
+ bool isMap() const { return type() == QCborValue::Map; }
+ bool isTag() const { return concrete().isTag(); }
+ bool isFalse() const { return type() == QCborValue::False; }
+ bool isTrue() const { return type() == QCborValue::True; }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return type() == QCborValue::Null; }
+ bool isUndefined() const { return type() == QCborValue::Undefined; }
+ bool isDouble() const { return type() == QCborValue::Double; }
+ bool isDateTime() const { return type() == QCborValue::DateTime; }
+ bool isUrl() const { return type() == QCborValue::Url; }
+ bool isRegularExpression() const { return type() == QCborValue::RegularExpression; }
+ bool isUuid() const { return type() == QCborValue::Uuid; }
+ bool isInvalid() const { return type() == QCborValue::Invalid; }
+ bool isContainer() const { return isMap() || isArray(); }
+ bool isSimpleType() const { return concrete().isSimpleType(); }
+ bool isSimpleType(QCborSimpleType st) const { return concrete().isSimpleType(st); }
+
+ QCborSimpleType toSimpleType(QCborSimpleType defaultValue = QCborSimpleType::Undefined) const
+ {
+ return concrete().toSimpleType(defaultValue);
+ }
+
+ QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const
+ { return concrete().tag(defaultValue); }
+ QCborValue taggedValue(const QCborValue &defaultValue = QCborValue()) const
+ { return concrete().taggedValue(defaultValue); }
+
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return concrete().toInteger(defaultValue); }
+ bool toBool(bool defaultValue = false) const
+ { return concrete().toBool(defaultValue); }
+ double toDouble(double defaultValue = 0) const
+ { return concrete().toDouble(defaultValue); }
+
+ QByteArray toByteArray(const QByteArray &defaultValue = {}) const
+ { return concrete().toByteArray(defaultValue); }
+ QString toString(const QString &defaultValue = {}) const
+ { return concrete().toString(defaultValue); }
+ QDateTime toDateTime(const QDateTime &defaultValue = {}) const
+ { return concrete().toDateTime(defaultValue); }
+#ifndef QT_BOOTSTRAPPED
+ QUrl toUrl(const QUrl &defaultValue = {}) const
+ { return concrete().toUrl(defaultValue); }
+# if QT_CONFIG(regularexpression)
+ QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const
+ { return concrete().toRegularExpression(defaultValue); }
+# endif
+ QUuid toUuid(const QUuid &defaultValue = {}) const
+ { return concrete().toUuid(defaultValue); }
+#endif
+
+ // only forward-declared, need split functions. Implemented in qcbor{array,map}.h
+ inline QCborArray toArray() const;
+ inline QCborArray toArray(const QCborArray &a) const;
+ inline QCborMap toMap() const;
+ inline QCborMap toMap(const QCborMap &m) const;
+
+ Q_CORE_EXPORT const QCborValue operator[](const QString &key) const;
+ Q_CORE_EXPORT const QCborValue operator[](QLatin1StringView key) const;
+ Q_CORE_EXPORT const QCborValue operator[](qint64 key) const;
+
+ int compare(const QCborValue &other) const
+ { return concrete().compare(other); }
+
+ QVariant toVariant() const { return concrete().toVariant(); }
+ inline QJsonValue toJsonValue() const; // in qjsonvalue.h
+
+#if QT_CONFIG(cborstreamwriter)
+ QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation) const
+ { return concrete().toCbor(opt); }
+ void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation) const
+ { return concrete().toCbor(writer, opt); }
+#endif
+
+ QString toDiagnosticNotation(QCborValue::DiagnosticNotationOptions opt = QCborValue::Compact) const
+ { return concrete().toDiagnosticNotation(opt); }
+
+protected:
+ friend class QCborValue;
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborContainerPrivate;
+
+ QCborValue concrete() const noexcept { return concrete(*this); }
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept;
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(QCborValueConstRef lhs, QCborValueConstRef rhs) noexcept;
+ friend bool comparesEqual(const QCborValueConstRef &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs,
+ const QCborValueConstRef &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef)
+
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool
+ comparesEqual_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept;
+ static Q_CORE_EXPORT Q_DECL_PURE_FUNCTION Qt::strong_ordering
+ compareThreeWay_helper(QCborValueConstRef lhs, const QCborValue &rhs) noexcept;
+ friend bool comparesEqual(const QCborValueConstRef &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const QCborValueConstRef &lhs,
+ const QCborValue &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(QCborValueConstRef, QCborValue)
+
+ static Q_CORE_EXPORT QCborValue concrete(QCborValueConstRef that) noexcept;
+ static Q_CORE_EXPORT QCborValue::Type concreteType(QCborValueConstRef that) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT bool
+ concreteBoolean(QCborValueConstRef that, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT double
+ concreteDouble(QCborValueConstRef that, double defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT qint64
+ concreteIntegral(QCborValueConstRef that, qint64 defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ static Q_CORE_EXPORT QByteArray
+ concreteByteArray(QCborValueConstRef that, const QByteArray &defaultValue);
+ static Q_CORE_EXPORT QString
+ concreteString(QCborValueConstRef that, const QString &defaultValue);
+
+ constexpr QCborValueConstRef() : d(nullptr), i(0) {} // this will actually be invalid
+ constexpr QCborValueConstRef(QCborContainerPrivate *dd, qsizetype ii)
+ : d(dd), i(ii)
+ {}
+ QCborContainerPrivate *d;
+ qsizetype i;
+};
+
+QT_WARNING_PUSH
+QT6_ONLY(QT_WARNING_DISABLE_MSVC(4275)) // non dll-interface class 'QJsonValueConstRef' used as base for dll-interface class 'QJsonValueRef'
+class QT6_ONLY(Q_CORE_EXPORT) QCborValueRef : public QCborValueConstRef
+{
+public:
QCborValueRef(const QCborValueRef &) noexcept = default;
QCborValueRef(QCborValueRef &&) noexcept = default;
QCborValueRef &operator=(const QCborValue &other)
@@ -351,6 +459,15 @@ public:
QCborValueRef &operator=(const QCborValueRef &other)
{ assign(*this, other); return *this; }
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](qint64 key);
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](QLatin1StringView key);
+ QT7_ONLY(Q_CORE_EXPORT) QCborValueRef operator[](const QString & key);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // retained for binary compatibility (due to the Q_CORE_EXPORT) because at
+ // least one compiler emits and exports all inlines in an exported class
+
+ operator QCborValue() const { return concrete(); }
QCborValue::Type type() const { return concreteType(); }
bool isInteger() const { return type() == QCborValue::Integer; }
bool isByteArray() const { return type() == QCborValue::ByteArray; }
@@ -378,6 +495,10 @@ public:
{
return type() == QCborValue::type_helper(st);
}
+ QCborSimpleType toSimpleType(QCborSimpleType defaultValue = QCborSimpleType::Undefined) const
+ {
+ return isSimpleType() ? QCborSimpleType(type() & 0xff) : defaultValue;
+ }
QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const
{ return concrete().tag(defaultValue); }
@@ -385,28 +506,28 @@ public:
{ return concrete().taggedValue(defaultValue); }
qint64 toInteger(qint64 defaultValue = 0) const
- { return concrete().toInteger(defaultValue); }
+ { return concreteIntegral(*this, defaultValue); }
bool toBool(bool defaultValue = false) const
- { return concrete().toBool(defaultValue); }
+ { return concreteBoolean(*this, defaultValue); }
double toDouble(double defaultValue = 0) const
- { return concrete().toDouble(defaultValue); }
+ { return concreteDouble(*this, defaultValue); }
QByteArray toByteArray(const QByteArray &defaultValue = {}) const
- { return concrete().toByteArray(defaultValue); }
+ { return concreteByteArray(*this, defaultValue); }
QString toString(const QString &defaultValue = {}) const
- { return concrete().toString(defaultValue); }
+ { return concreteString(*this, defaultValue); }
QDateTime toDateTime(const QDateTime &defaultValue = {}) const
{ return concrete().toDateTime(defaultValue); }
#ifndef QT_BOOTSTRAPPED
QUrl toUrl(const QUrl &defaultValue = {}) const
{ return concrete().toUrl(defaultValue); }
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const
{ return concrete().toRegularExpression(defaultValue); }
-#endif
+# endif
QUuid toUuid(const QUuid &defaultValue = {}) const
{ return concrete().toUuid(defaultValue); }
+#endif
// only forward-declared, need split functions. Implemented in qcbor{array,map}.h
QCborArray toArray() const;
@@ -415,27 +536,16 @@ public:
QCborMap toMap(const QCborMap &m) const;
const QCborValue operator[](const QString &key) const;
- const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](QLatin1StringView key) const;
const QCborValue operator[](qint64 key) const;
- QCborValueRef operator[](qint64 key);
- QCborValueRef operator[](QLatin1String key);
- QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
-#if 0 && __has_include(<compare>)
- std::strong_ordering operator<=>(const QCborValue &other) const
- {
- int c = compare(other);
- if (c > 0) return std::strong_ordering::greater;
- if (c == 0) return std::strong_ordering::equivalent;
- return std::strong_ordering::less;
- }
-#else
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QCborValue &other) const
{ return compare(other) == 0; }
bool operator!=(const QCborValue &other) const
- { return !(*this == other); }
+ { return !operator==(other); }
bool operator<(const QCborValue &other) const
{ return compare(other) < 0; }
#endif
@@ -444,25 +554,17 @@ public:
QJsonValue toJsonValue() const;
#if QT_CONFIG(cborstreamwriter)
+ using QCborValueConstRef::toCbor;
QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation)
- { return concrete().toCbor(opt); }
+ { return std::as_const(*this).toCbor(opt); }
void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation);
#endif
+ using QCborValueConstRef::toDiagnosticNotation;
QString toDiagnosticNotation(QCborValue::DiagnosticNotationOptions opt = QCborValue::Compact)
- { return concrete().toDiagnosticNotation(opt); }
+ { return std::as_const(*this).toDiagnosticNotation(opt); }
private:
- friend class QCborValue;
- friend class QCborArray;
- friend class QCborMap;
- friend class QCborContainerPrivate;
- friend class QCborValueRefPtr;
-
- // static so we can pass this by value
- static void assign(QCborValueRef that, const QCborValue &other);
- static void assign(QCborValueRef that, QCborValue &&other);
- static void assign(QCborValueRef that, const QCborValueRef other);
static QCborValue concrete(QCborValueRef that) noexcept;
QCborValue concrete() const noexcept { return concrete(*this); }
@@ -470,14 +572,30 @@ private:
QCborValue::Type concreteType() const noexcept { return concreteType(*this); }
// this will actually be invalid...
- Q_DECL_CONSTEXPR QCborValueRef() : d(nullptr), i(0) {}
+ constexpr QCborValueRef() : QCborValueConstRef(nullptr, 0) {}
QCborValueRef(QCborContainerPrivate *dd, qsizetype ii)
- : d(dd), i(ii)
+ : QCborValueConstRef(dd, ii)
{}
- QCborContainerPrivate *d;
- qsizetype i;
+#else
+private:
+ using QCborValueConstRef::QCborValueConstRef;
+#endif // < Qt 7
+
+ friend class QCborValue;
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborContainerPrivate;
+ friend class QCborValueConstRef;
+
+ // static so we can pass this by value
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, const QCborValue &other);
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, QCborValue &&other);
+ QT7_ONLY(Q_CORE_EXPORT) static void assign(QCborValueRef that, const QCborValueRef other);
};
+QT_WARNING_POP
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCborValue::EncodingOptions)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QCborValue::DiagnosticNotationOptions)
Q_CORE_EXPORT size_t qHash(const QCborValue &value, size_t seed = 0);
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index 3b1e45a2a8..33eb912a6d 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCBORVALUE_P_H
#define QCBORVALUE_P_H
@@ -53,6 +17,10 @@
#include "qcborvalue.h"
+#if QT_CONFIG(cborstreamreader)
+# include "qcborstreamreader.h"
+#endif
+
#include <private/qglobal_p.h>
#include <private/qstringconverter_p.h>
@@ -61,6 +29,11 @@
QT_BEGIN_NAMESPACE
namespace QtCbor {
+enum class Comparison {
+ ForEquality,
+ ForOrdering,
+};
+
struct Undefined {};
struct Element
{
@@ -111,7 +84,8 @@ struct ByteData
QString toUtf8String() const { return QString::fromUtf8(byte(), len); }
QByteArray asByteArrayView() const { return QByteArray::fromRawData(byte(), len); }
- QLatin1String asLatin1() const { return QLatin1String(byte(), len); }
+ QLatin1StringView asLatin1() const { return {byte(), len}; }
+ QUtf8StringView asUtf8StringView() const { return QUtf8StringView(byte(), len); }
QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
};
@@ -134,18 +108,19 @@ public:
QList<QtCbor::Element> elements;
void deref() { if (!ref.deref()) delete this; }
- void compact(qsizetype reserved);
+ void compact();
static QCborContainerPrivate *clone(QCborContainerPrivate *d, qsizetype reserved = -1);
static QCborContainerPrivate *detach(QCborContainerPrivate *d, qsizetype reserved);
static QCborContainerPrivate *grow(QCborContainerPrivate *d, qsizetype index);
- qptrdiff addByteData(const char *block, qsizetype len)
+ static qptrdiff addByteDataImpl(QByteArray &target, QByteArray::size_type &targetUsed,
+ const char *block, qsizetype len)
{
// This function does not do overflow checking, since the len parameter
// is expected to be trusted. There's another version of this function
// in decodeStringFromCbor(), which checks.
- qptrdiff offset = data.size();
+ qptrdiff offset = target.size();
// align offset
offset += alignof(QtCbor::ByteData) - 1;
@@ -153,10 +128,10 @@ public:
qptrdiff increment = qptrdiff(sizeof(QtCbor::ByteData)) + len;
- usedData += increment;
- data.resize(offset + increment);
+ targetUsed += increment;
+ target.resize(offset + increment);
- char *ptr = data.begin() + offset;
+ char *ptr = target.begin() + offset;
auto b = new (ptr) QtCbor::ByteData;
b->len = len;
if (block)
@@ -165,6 +140,11 @@ public:
return offset;
}
+ qptrdiff addByteData(const char *block, qsizetype len)
+ {
+ return addByteDataImpl(data, usedData, block, len);
+ }
+
const QtCbor::ByteData *byteData(QtCbor::Element e) const
{
if ((e.flags & QtCbor::Element::HasByteData) == 0)
@@ -215,7 +195,7 @@ public:
}
void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
{
- replaceAt_internal(*elements.insert(elements.begin() + int(idx), {}), value, disp);
+ replaceAt_internal(*elements.insert(idx, {}), value, disp);
}
void append(QtCbor::Undefined)
@@ -245,31 +225,29 @@ public:
{
appendByteData(str, len, QCborValue::String);
}
- void append(QLatin1String s)
+ void append(QLatin1StringView s)
{
if (!QtPrivate::isAscii(s))
- return append(QString(s));
+ return appendNonAsciiString(QString(s));
// US-ASCII is a subset of UTF-8, so we can keep in 8-bit
appendByteData(s.latin1(), s.size(), QCborValue::String,
QtCbor::Element::StringIsAscii);
}
void appendAsciiString(QStringView s);
+ void appendNonAsciiString(QStringView s);
-#if QT_STRINGVIEW_LEVEL < 2
void append(const QString &s)
{
append(qToStringViewIgnoringNull(s));
}
-#endif
void append(QStringView s)
{
if (QtPrivate::isAscii(s))
appendAsciiString(s);
else
- appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
- QCborValue::String, QtCbor::Element::StringIsUtf16);
+ appendNonAsciiString(s);
}
void append(const QCborValue &v)
{
@@ -362,18 +340,18 @@ public:
return e;
}
- static int compareUtf8(const QtCbor::ByteData *b, const QLatin1String &s)
+ static int compareUtf8(const QtCbor::ByteData *b, QLatin1StringView s)
{
- return QUtf8::compareUtf8(b->byte(), b->len, s);
+ return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
}
static int compareUtf8(const QtCbor::ByteData *b, QStringView s)
{
- return QUtf8::compareUtf8(b->byte(), b->len, s.data(), s.size());
+ return QUtf8::compareUtf8(QByteArrayView(b->byte(), b->len), s);
}
template<typename String>
- int stringCompareElement(const QtCbor::Element &e, String s) const
+ int stringCompareElement(const QtCbor::Element &e, String s, QtCbor::Comparison mode) const
{
if (e.type != QCborValue::String)
return int(e.type) - int(QCborValue::String);
@@ -382,15 +360,18 @@ public:
if (!b)
return s.isEmpty() ? 0 : -1;
- if (e.flags & QtCbor::Element::StringIsUtf16)
+ if (e.flags & QtCbor::Element::StringIsUtf16) {
+ if (mode == QtCbor::Comparison::ForEquality)
+ return QtPrivate::equalStrings(b->asStringView(), s) ? 0 : 1;
return QtPrivate::compareStrings(b->asStringView(), s);
+ }
return compareUtf8(b, s);
}
template<typename String>
bool stringEqualsElement(const QtCbor::Element &e, String s) const
{
- return stringCompareElement(e, s) == 0;
+ return stringCompareElement(e, s, QtCbor::Comparison::ForEquality) == 0;
}
template<typename String>
@@ -400,12 +381,13 @@ public:
}
static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1,
- const QCborContainerPrivate *c2, QtCbor::Element e2);
- int compareElement(qsizetype idx, const QCborValue &value) const
+ const QCborContainerPrivate *c2, QtCbor::Element e2,
+ QtCbor::Comparison mode) noexcept;
+ int compareElement(qsizetype idx, const QCborValue &value, QtCbor::Comparison mode) const
{
auto &e1 = elements.at(idx);
auto e2 = elementFromValue(value);
- return compareElement_helper(this, e1, value.container, e2);
+ return compareElement_helper(this, e1, value.container, e2, mode);
}
void removeAt(qsizetype idx)
@@ -414,9 +396,67 @@ public:
elements.remove(idx);
}
- void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth);
+ // doesn't apply to JSON
+ template <typename KeyType> QCborValueConstRef findCborMapKey(KeyType key)
+ {
+ qsizetype i = 0;
+ for ( ; i < elements.size(); i += 2) {
+ const auto &e = elements.at(i);
+ bool equals;
+ if constexpr (std::is_same_v<std::decay_t<KeyType>, QCborValue>) {
+ equals = (compareElement(i, key, QtCbor::Comparison::ForEquality) == 0);
+ } else if constexpr (std::is_integral_v<KeyType>) {
+ equals = (e.type == QCborValue::Integer && e.value == key);
+ } else {
+ // assume it's a string
+ equals = stringEqualsElement(i, key);
+ }
+ if (equals)
+ break;
+ }
+ return { this, i + 1 };
+ }
+ template <typename KeyType> static QCborValue findCborMapKey(const QCborValue &self, KeyType key)
+ {
+ if (self.isMap() && self.container) {
+ qsizetype idx = self.container->findCborMapKey(key).i;
+ if (idx < self.container->elements.size())
+ return self.container->valueAt(idx);
+ }
+ return QCborValue();
+ }
+ template <typename KeyType> static QCborValueRef
+ findOrAddMapKey(QCborContainerPrivate *container, KeyType key)
+ {
+ qsizetype size = 0;
+ qsizetype index = size + 1;
+ if (container) {
+ size = container->elements.size();
+ index = container->findCborMapKey<KeyType>(key).i; // returns size + 1 if not found
+ }
+ Q_ASSERT(index & 1);
+ Q_ASSERT((size & 1) == 0);
+
+ container = detach(container, qMax(index + 1, size));
+ Q_ASSERT(container);
+ Q_ASSERT((container->elements.size() & 1) == 0);
+
+ if (index >= size) {
+ container->append(key);
+ container->append(QCborValue());
+ }
+ Q_ASSERT(index < container->elements.size());
+ return { container, index };
+ }
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborMap &map, KeyType key);
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValue &self, KeyType key);
+ template <typename KeyType> static QCborValueRef findOrAddMapKey(QCborValueRef self, KeyType key);
+
+#if QT_CONFIG(cborstreamreader)
+ void decodeValueFromCbor(QCborStreamReader &reader, int remainingStackDepth);
void decodeStringFromCbor(QCborStreamReader &reader);
static inline void setErrorInReader(QCborStreamReader &reader, QCborError error);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 7888296b85..d35e871de0 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdatastream.h"
#include "qdatastream_p.h"
@@ -51,9 +15,13 @@
QT_BEGIN_NAMESPACE
+constexpr quint32 QDataStream::NullCode;
+constexpr quint32 QDataStream::ExtendedSize;
+
/*!
\class QDataStream
\inmodule QtCore
+ \ingroup qtserialization
\reentrant
\brief The QDataStream class provides serialization of binary data
to a QIODevice.
@@ -102,17 +70,30 @@ QT_BEGIN_NAMESPACE
need of manually defining streaming operators. Enum classes are
serialized using the declared size.
- To take one example, a \c{char *} string is written as a 32-bit
- integer equal to the length of the string including the '\\0' byte,
- followed by all the characters of the string including the
- '\\0' byte. When reading a \c{char *} string, 4 bytes are read to
- create the 32-bit length value, then that many characters for the
- \c {char *} string including the '\\0' terminator are read.
-
The initial I/O device is usually set in the constructor, but can be
changed with setDevice(). If you've reached the end of the data
(or if there is no I/O device set) atEnd() will return true.
+ \section1 Serializing containers and strings
+
+ The serialization format is a length specifier first, then \a l bytes of data.
+ The length specifier is one quint32 if the version is less than 6.7 or if the
+ number of elements is less than 0xfffffffe (2^32 -2). Otherwise there is
+ an extend value 0xfffffffe followed by one quint64 with the actual value.
+ In addition for containers that support isNull(), it is encoded as a single
+ quint32 with all bits set and no data.
+
+ To take one example, if the string size fits into 32 bits, a \c{char *} string
+ is written as a 32-bit integer equal to the length of the string, including
+ the '\\0' byte, followed by all the characters of the string, including the
+ '\\0' byte. If the string size is greater, the value 0xffffffffe is written
+ as a marker of an extended size, followed by 64 bits of the actual size.
+ When reading a \c {char *} string, 4 bytes are read first. If the value is
+ not equal to 0xffffffffe (the marker of extended size), then these 4 bytes
+ are treated as the 32 bit size of the string. Otherwise, the next 8 bytes are
+ read and treated as a 64 bit size of the string. Then, all the characters for
+ the \c {char *} string, including the '\\0' terminator, are read.
+
\section1 Versioning
QDataStream's binary format has evolved since Qt 1.0, and is
@@ -138,9 +119,9 @@ QT_BEGIN_NAMESPACE
\snippet code/src_corelib_io_qdatastream.cpp 4
You can select which byte order to use when serializing data. The
- default setting is big endian (MSB first). Changing it to little
- endian breaks the portability (unless the reader also changes to
- little endian). We recommend keeping this setting unless you have
+ default setting is big-endian (MSB first). Changing it to little-endian
+ breaks the portability (unless the reader also changes to
+ little-endian). We recommend keeping this setting unless you have
special requirements.
\target raw
@@ -199,6 +180,27 @@ QT_BEGIN_NAMESPACE
If no full packet is received, this code restores the stream to the
initial position, after which you need to wait for more data to arrive.
+ \section1 Corruption and Security
+
+ QDataStream is not resilient against corrupted data inputs and should
+ therefore not be used for security-sensitive situations, even when using
+ transactions. Transactions will help determine if a valid input can
+ currently be decoded with the data currently available on an asynchronous
+ device, but will assume that the data that is available is correctly
+ formed.
+
+ Additionally, many QDataStream demarshalling operators will allocate memory
+ based on information found in the stream. Those operators perform no
+ verification on whether the requested amount of memory is reasonable or if
+ it is compatible with the amount of data available in the stream (example:
+ demarshalling a QByteArray or QString may see the request for allocation of
+ several gigabytes of data).
+
+ QDataStream should not be used on content whose provenance cannot be
+ trusted. Applications should be designed to attempt to decode only streams
+ whose provenance is at least as trustworthy as that of the application
+ itself or its plugins.
+
\sa QTextStream, QVariant
*/
@@ -236,6 +238,11 @@ QT_BEGIN_NAMESPACE
data in the underlying device.
\value ReadCorruptData The data stream has read corrupt data.
\value WriteFailed The data stream cannot write to the underlying device.
+ \value [since 6.7] SizeLimitExceeded The data stream cannot read or write
+ the data because its size is larger than supported
+ by the current platform. This can happen, for
+ example, when trying to read more that 2 GiB of
+ data on a 32-bit platform.
*/
/*****************************************************************************
@@ -264,7 +271,7 @@ QT_BEGIN_NAMESPACE
return retVal;
#define CHECK_STREAM_TRANSACTION_PRECOND(retVal) \
- if (!d || d->transactionDepth == 0) { \
+ if (transactionDepth == 0) { \
qWarning("QDataStream: No transaction in progress"); \
return retVal; \
}
@@ -277,12 +284,6 @@ QT_BEGIN_NAMESPACE
QDataStream::QDataStream()
{
- dev = nullptr;
- owndev = false;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -294,15 +295,10 @@ QDataStream::QDataStream()
QDataStream::QDataStream(QIODevice *d)
{
dev = d; // set device
- owndev = false;
- byteorder = BigEndian; // default byte order
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
- \fn QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode mode)
+ \fn QDataStream::QDataStream(QByteArray *a, OpenMode mode)
Constructs a data stream that operates on a byte array, \a a. The
\a mode describes how the device is to be used.
@@ -314,7 +310,7 @@ QDataStream::QDataStream(QIODevice *d)
is created to wrap the byte array.
*/
-QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
+QDataStream::QDataStream(QByteArray *a, OpenMode flags)
{
QBuffer *buf = new QBuffer(a);
#ifndef QT_NO_QOBJECT
@@ -323,10 +319,6 @@ QDataStream::QDataStream(QByteArray *a, QIODevice::OpenMode flags)
buf->open(flags);
dev = buf;
owndev = true;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -347,10 +339,6 @@ QDataStream::QDataStream(const QByteArray &a)
buf->open(QIODevice::ReadOnly);
dev = buf;
owndev = true;
- byteorder = BigEndian;
- ver = Qt_DefaultCompiledVersion;
- noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
- q_status = Ok;
}
/*!
@@ -396,19 +384,6 @@ void QDataStream::setDevice(QIODevice *d)
dev = d;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- \obsolete
- Unsets the I/O device.
- Use setDevice(nullptr) instead.
-*/
-
-void QDataStream::unsetDevice()
-{
- setDevice(nullptr);
-}
-#endif
-
/*!
\fn bool QDataStream::atEnd() const
@@ -425,16 +400,14 @@ bool QDataStream::atEnd() const
}
/*!
+ \fn QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
+
Returns the floating point precision of the data stream.
\since 4.6
\sa FloatingPointPrecision, setFloatingPointPrecision()
*/
-QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
-{
- return d ? d->floatingPointPrecision : QDataStream::DoublePrecision;
-}
/*!
Sets the floating point precision of the data stream to \a precision. If the floating point precision is
@@ -458,22 +431,17 @@ QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
*/
void QDataStream::setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
{
- if (!d)
- d.reset(new QDataStreamPrivate());
- d->floatingPointPrecision = precision;
+ fpPrecision = precision;
}
/*!
+ \fn QDataStream::status() const
+
Returns the status of the data stream.
\sa Status, setStatus(), resetStatus()
*/
-QDataStream::Status QDataStream::status() const
-{
- return q_status;
-}
-
/*!
Resets the status of the data stream.
@@ -513,7 +481,7 @@ void QDataStream::setStatus(Status status)
The \a bo parameter can be QDataStream::BigEndian or
QDataStream::LittleEndian.
- The default setting is big endian. We recommend leaving this
+ The default setting is big-endian. We recommend leaving this
setting unless you have special requirements.
\sa byteOrder()
@@ -521,11 +489,14 @@ void QDataStream::setStatus(Status status)
void QDataStream::setByteOrder(ByteOrder bo)
{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // accessed by inline byteOrder() prior to Qt 6.8
byteorder = bo;
+#endif
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- noswap = (byteorder == BigEndian);
+ noswap = (bo == BigEndian);
else
- noswap = (byteorder == LittleEndian);
+ noswap = (bo == LittleEndian);
}
@@ -567,6 +538,15 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_13 Version 19 (Qt 5.13)
\value Qt_5_14 Same as Qt_5_13
\value Qt_5_15 Same as Qt_5_13
+ \value Qt_6_0 Version 20 (Qt 6.0)
+ \value Qt_6_1 Same as Qt_6_0
+ \value Qt_6_2 Same as Qt_6_0
+ \value Qt_6_3 Same as Qt_6_0
+ \value Qt_6_4 Same as Qt_6_0
+ \value Qt_6_5 Same as Qt_6_0
+ \value Qt_6_6 Version 21 (Qt 6.6)
+ \value Qt_6_7 Version 22 (Qt 6.7)
+ \value Qt_6_8 Same as Qt_6_7
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
@@ -640,10 +620,7 @@ void QDataStream::startTransaction()
{
CHECK_STREAM_PRECOND(Q_VOID)
- if (!d)
- d.reset(new QDataStreamPrivate());
-
- if (++d->transactionDepth == 1) {
+ if (++transactionDepth == 1) {
dev->startTransaction();
resetStatus();
}
@@ -672,7 +649,7 @@ void QDataStream::startTransaction()
bool QDataStream::commitTransaction()
{
CHECK_STREAM_TRANSACTION_PRECOND(false)
- if (--d->transactionDepth == 0) {
+ if (--transactionDepth == 0) {
CHECK_STREAM_PRECOND(false)
if (q_status == ReadPastEnd) {
@@ -712,7 +689,7 @@ void QDataStream::rollbackTransaction()
setStatus(ReadPastEnd);
CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID)
- if (--d->transactionDepth != 0)
+ if (--transactionDepth != 0)
return;
CHECK_STREAM_PRECOND(Q_VOID)
@@ -748,13 +725,21 @@ void QDataStream::abortTransaction()
q_status = ReadCorruptData;
CHECK_STREAM_TRANSACTION_PRECOND(Q_VOID)
- if (--d->transactionDepth != 0)
+ if (--transactionDepth != 0)
return;
CHECK_STREAM_PRECOND(Q_VOID)
dev->commitTransaction();
}
+/*!
+ \internal
+*/
+bool QDataStream::isDeviceTransactionStarted() const
+{
+ return dev && dev->isTransactionStarted();
+}
+
/*****************************************************************************
QDataStream read functions
*****************************************************************************/
@@ -763,13 +748,13 @@ void QDataStream::abortTransaction()
\internal
*/
-int QDataStream::readBlock(char *data, int len)
+qint64 QDataStream::readBlock(char *data, qint64 len)
{
// Disable reads on failure in transacted stream
if (q_status != Ok && dev->isTransactionStarted())
return -1;
- const int readResult = dev->read(data, len);
+ const qint64 readResult = dev->read(data, len);
if (readResult != len)
setStatus(ReadPastEnd);
return readResult;
@@ -993,25 +978,12 @@ QDataStream &QDataStream::operator>>(double &f)
/*!
\overload
- \since 5.9
-
- Reads a floating point number from the stream into \a f,
- using the standard IEEE 754 format. Returns a reference to the
- stream.
-*/
-QDataStream &QDataStream::operator>>(qfloat16 &f)
-{
- return *this >> reinterpret_cast<qint16&>(f);
-}
-
-
-/*!
- \overload
- Reads the '\\0'-terminated string \a s from the stream and returns
- a reference to the stream.
+ Reads string \a s from the stream and returns a reference to the stream.
- The string is deserialized using \c{readBytes()}.
+ The string is deserialized using \c{readBytes()} where the serialization
+ format is a \c quint32 length specifier first, followed by that many bytes
+ of data. The resulting string is always '\\0'-terminated.
Space for the string is allocated using \c{new []} -- the caller must
destroy it with \c{delete []}.
@@ -1021,14 +993,16 @@ QDataStream &QDataStream::operator>>(qfloat16 &f)
QDataStream &QDataStream::operator>>(char *&s)
{
- uint len = 0;
+ qint64 len = 0;
return readBytes(s, len);
}
/*!
- \overload
+ \overload
+ \since 6.0
- Reads a char from the stream into char \a chr.
+ Reads a 16bit wide char from the stream into \a c and
+ returns a reference to the stream.
*/
QDataStream &QDataStream::operator>>(char16_t &c)
{
@@ -1039,9 +1013,11 @@ QDataStream &QDataStream::operator>>(char16_t &c)
}
/*!
- \overload
+ \overload
+ \since 6.0
- Reads a char from the stream into char \a chr.
+ Reads a 32bit wide character from the stream into \a c and
+ returns a reference to the stream.
*/
QDataStream &QDataStream::operator>>(char32_t &c)
{
@@ -1051,7 +1027,29 @@ QDataStream &QDataStream::operator>>(char32_t &c)
return *this;
}
+#if QT_DEPRECATED_SINCE(6, 11)
+
+/*
+ \deprecated [6.11] Use an overload that takes qint64 length instead.
+*/
+QDataStream &QDataStream::readBytes(char *&s, uint &l)
+{
+ qint64 length = 0;
+ (void)readBytes(s, length);
+ if (length != qint64(uint(length))) {
+ setStatus(SizeLimitExceeded); // Cannot store length in l
+ delete[] s;
+ l = 0;
+ return *this;
+ }
+ l = uint(length);
+ return *this;
+}
+
+#endif // QT_DEPRECATED_SINCE(6, 11)
+
/*!
+ \since 6.7
Reads the buffer \a s from the stream and returns a reference to
the stream.
@@ -1061,30 +1059,40 @@ QDataStream &QDataStream::operator>>(char32_t &c)
The \a l parameter is set to the length of the buffer. If the
string read is empty, \a l is set to 0 and \a s is set to \nullptr.
- The serialization format is a quint32 length specifier first,
- then \a l bytes of data.
+ The serialization format is a length specifier first, then \a l
+ bytes of data. The length specifier is one quint32 if the version
+ is less than 6.7 or if the number of elements is less than 0xfffffffe
+ (2^32 -2), otherwise there is an extend value 0xfffffffe followed by
+ one quint64 with the actual value. In addition for containers that
+ support isNull(), it is encoded as a single quint32 with all bits
+ set and no data.
\sa readRawData(), writeBytes()
*/
-QDataStream &QDataStream::readBytes(char *&s, uint &l)
+QDataStream &QDataStream::readBytes(char *&s, qint64 &l)
{
s = nullptr;
l = 0;
CHECK_STREAM_PRECOND(*this)
- quint32 len;
- *this >> len;
- if (len == 0)
+ qint64 length = readQSizeType(*this);
+ if (length == 0)
return *this;
- const quint32 Step = 1024 * 1024;
- quint32 allocated = 0;
+ qsizetype len = qsizetype(length);
+ if (length != len || length < 0) {
+ setStatus(SizeLimitExceeded); // Cannot store len
+ return *this;
+ }
+
+ qsizetype step = (dev->bytesAvailable() >= len) ? len : 1024 * 1024;
+ qsizetype allocated = 0;
char *prevBuf = nullptr;
char *curBuf = nullptr;
do {
- int blockSize = qMin(Step, len - allocated);
+ qsizetype blockSize = qMin(step, len - allocated);
prevBuf = curBuf;
curBuf = new char[allocated + blockSize + 1];
if (prevBuf) {
@@ -1096,11 +1104,12 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l)
return *this;
}
allocated += blockSize;
+ step *= 2;
} while (allocated < len);
s = curBuf;
s[len] = '\0';
- l = (uint)len;
+ l = len;
return *this;
}
@@ -1113,7 +1122,7 @@ QDataStream &QDataStream::readBytes(char *&s, uint &l)
\sa readBytes(), QIODevice::read(), writeRawData()
*/
-int QDataStream::readRawData(char *s, int len)
+qint64 QDataStream::readRawData(char *s, qint64 len)
{
CHECK_STREAM_PRECOND(-1)
return readBlock(s, len);
@@ -1251,18 +1260,13 @@ QDataStream &QDataStream::operator<<(qint64 i)
*/
/*!
+ \fn QDataStream &QDataStream::operator<<(bool i)
+ \overload
+
Writes a boolean value, \a i, to the stream. Returns a reference
to the stream.
*/
-QDataStream &QDataStream::operator<<(bool i)
-{
- CHECK_STREAM_WRITE_PRECOND(*this)
- if (!dev->putChar(qint8(i)))
- q_status = WriteFailed;
- return *this;
-}
-
/*!
\overload
@@ -1337,19 +1341,6 @@ QDataStream &QDataStream::operator<<(double f)
/*!
- \fn QDataStream &QDataStream::operator<<(qfloat16 f)
- \overload
- \since 5.9
-
- Writes a floating point number, \a f, to the stream using
- the standard IEEE 754 format. Returns a reference to the stream.
-*/
-QDataStream &QDataStream::operator<<(qfloat16 f)
-{
- return *this << reinterpret_cast<qint16&>(f);
-}
-
-/*!
\overload
Writes the '\\0'-terminated string \a s to the stream and returns a
@@ -1362,13 +1353,9 @@ QDataStream &QDataStream::operator<<(qfloat16 f)
QDataStream &QDataStream::operator<<(const char *s)
{
- if (!s) {
- *this << (quint32)0;
- return *this;
- }
- uint len = qstrlen(s) + 1; // also write null terminator
- *this << (quint32)len; // write length specifier
- writeRawData(s, len);
+ // Include null terminator, unless s itself is null
+ const qint64 len = s ? qint64(qstrlen(s)) + 1 : 0;
+ writeBytes(s, len);
return *this;
}
@@ -1400,22 +1387,26 @@ QDataStream &QDataStream::operator<<(char32_t c)
Writes the length specifier \a len and the buffer \a s to the
stream and returns a reference to the stream.
- The \a len is serialized as a quint32, followed by \a len bytes
- from \a s. Note that the data is \e not encoded.
+ The \a len is serialized as a quint32 and an optional quint64,
+ followed by \a len bytes from \a s. Note that the data is
+ \e not encoded.
\sa writeRawData(), readBytes()
*/
-QDataStream &QDataStream::writeBytes(const char *s, uint len)
+QDataStream &QDataStream::writeBytes(const char *s, qint64 len)
{
+ if (len < 0) {
+ q_status = WriteFailed;
+ return *this;
+ }
CHECK_STREAM_WRITE_PRECOND(*this)
- *this << (quint32)len; // write length specifier
- if (len)
+ // Write length then, if any, content
+ if (writeQSizeType(*this, len) && len > 0)
writeRawData(s, len);
return *this;
}
-
/*!
Writes \a len bytes from \a s to the stream. Returns the
number of bytes actually written, or -1 on error.
@@ -1424,10 +1415,10 @@ QDataStream &QDataStream::writeBytes(const char *s, uint len)
\sa writeBytes(), QIODevice::write(), readRawData()
*/
-int QDataStream::writeRawData(const char *s, int len)
+qint64 QDataStream::writeRawData(const char *s, qint64 len)
{
CHECK_STREAM_WRITE_PRECOND(-1)
- int ret = dev->write(s, len);
+ qint64 ret = dev->write(s, len);
if (ret != len)
q_status = WriteFailed;
return ret;
@@ -1444,13 +1435,13 @@ int QDataStream::writeRawData(const char *s, int len)
\sa QIODevice::seek()
*/
-int QDataStream::skipRawData(int len)
+qint64 QDataStream::skipRawData(qint64 len)
{
CHECK_STREAM_PRECOND(-1)
if (q_status != Ok && dev->isTransactionStarted())
return -1;
- const int skipResult = dev->skip(len);
+ const qint64 skipResult = dev->skip(len);
if (skipResult != len)
setStatus(ReadPastEnd);
return skipResult;
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index d00fb5e7d8..cf37df71d7 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -1,49 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATASTREAM_H
#define QDATASTREAM_H
#include <QtCore/qscopedpointer.h>
-#include <QtCore/qiodevice.h>
-#include <QtCore/qpair.h>
+#include <QtCore/qiodevicebase.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qnamespace.h>
+
+#include <iterator> // std::distance(), std::next()
#ifdef Status
#error qdatastream.h must be included before any header file that defines Status
@@ -51,19 +17,35 @@
QT_BEGIN_NAMESPACE
+#if QT_CORE_REMOVED_SINCE(6, 3)
class qfloat16;
+#endif
class QByteArray;
+class QDataStream;
class QIODevice;
+class QString;
-#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
+#if !defined(QT_NO_DATASTREAM)
class QDataStreamPrivate;
namespace QtPrivate {
class StreamStateSaver;
+template <typename Container>
+QDataStream &readArrayBasedContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &readListBasedContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &readAssociativeContainer(QDataStream &s, Container &c);
+template <typename Container>
+QDataStream &writeSequentialContainer(QDataStream &s, const Container &c);
+template <typename Container>
+QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c);
+template <typename Container>
+QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c);
}
-class Q_CORE_EXPORT QDataStream
+class Q_CORE_EXPORT QDataStream : public QIODeviceBase
{
public:
- enum Version {
+ enum Version QT7_ONLY(: quint8) {
Qt_1_0 = 1,
Qt_2_0 = 2,
Qt_2_1 = 3,
@@ -97,8 +79,16 @@ public:
Qt_5_14 = Qt_5_13,
Qt_5_15 = Qt_5_14,
Qt_6_0 = 20,
- Qt_DefaultCompiledVersion = Qt_6_0
-#if QT_VERSION >= 0x060100
+ Qt_6_1 = Qt_6_0,
+ Qt_6_2 = Qt_6_0,
+ Qt_6_3 = Qt_6_0,
+ Qt_6_4 = Qt_6_0,
+ Qt_6_5 = Qt_6_0,
+ Qt_6_6 = 21,
+ Qt_6_7 = 22,
+ Qt_6_8 = Qt_6_7,
+ Qt_DefaultCompiledVersion = Qt_6_8
+#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
};
@@ -108,37 +98,36 @@ public:
LittleEndian = QSysInfo::LittleEndian
};
- enum Status {
+ enum Status QT7_ONLY(: quint8) {
Ok,
ReadPastEnd,
ReadCorruptData,
- WriteFailed
+ WriteFailed,
+ SizeLimitExceeded,
};
- enum FloatingPointPrecision {
+ enum FloatingPointPrecision QT7_ONLY(: quint8) {
SinglePrecision,
DoublePrecision
};
QDataStream();
explicit QDataStream(QIODevice *);
- QDataStream(QByteArray *, QIODevice::OpenMode flags);
+ QDataStream(QByteArray *, OpenMode flags);
QDataStream(const QByteArray &);
~QDataStream();
QIODevice *device() const;
void setDevice(QIODevice *);
-#if QT_DEPRECATED_SINCE(5, 13)
- QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead")
- void unsetDevice();
-#endif
bool atEnd() const;
+ QT_CORE_INLINE_SINCE(6, 8)
Status status() const;
void setStatus(Status status);
void resetStatus();
+ QT_CORE_INLINE_SINCE(6, 8)
FloatingPointPrecision floatingPointPrecision() const;
void setFloatingPointPrecision(FloatingPointPrecision precision);
@@ -148,6 +137,7 @@ public:
int version() const;
void setVersion(int);
+ QDataStream &operator>>(char &i);
QDataStream &operator>>(qint8 &i);
QDataStream &operator>>(quint8 &i);
QDataStream &operator>>(qint16 &i);
@@ -159,13 +149,16 @@ public:
QDataStream &operator>>(std::nullptr_t &ptr) { ptr = nullptr; return *this; }
QDataStream &operator>>(bool &i);
+#if QT_CORE_REMOVED_SINCE(6, 3)
QDataStream &operator>>(qfloat16 &f);
+#endif
QDataStream &operator>>(float &f);
QDataStream &operator>>(double &f);
QDataStream &operator>>(char *&str);
QDataStream &operator>>(char16_t &c);
QDataStream &operator>>(char32_t &c);
+ QDataStream &operator<<(char i);
QDataStream &operator<<(qint8 i);
QDataStream &operator<<(quint8 i);
QDataStream &operator<<(qint16 i);
@@ -175,52 +168,105 @@ public:
QDataStream &operator<<(qint64 i);
QDataStream &operator<<(quint64 i);
QDataStream &operator<<(std::nullptr_t) { return *this; }
+#if QT_CORE_REMOVED_SINCE(6, 8) || defined(Q_QDOC)
QDataStream &operator<<(bool i);
+#endif
+#if !defined(Q_QDOC)
+ // Disable implicit conversions to bool (e.g. for pointers)
+ template <typename T,
+ std::enable_if_t<std::is_same_v<T, bool>, bool> = true>
+ QDataStream &operator<<(T i)
+ {
+ return (*this << qint8(i));
+ }
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 3)
QDataStream &operator<<(qfloat16 f);
+#endif
QDataStream &operator<<(float f);
QDataStream &operator<<(double f);
QDataStream &operator<<(const char *str);
QDataStream &operator<<(char16_t c);
QDataStream &operator<<(char32_t c);
-
+#if QT_DEPRECATED_SINCE(6, 11)
+ QT_DEPRECATED_VERSION_X_6_11("Use an overload that takes qint64 length.")
QDataStream &readBytes(char *&, uint &len);
- int readRawData(char *, int len);
-
+#endif
+#if QT_CORE_REMOVED_SINCE(6, 7)
QDataStream &writeBytes(const char *, uint len);
- int writeRawData(const char *, int len);
-
int skipRawData(int len);
+ int readRawData(char *, int len);
+ int writeRawData(const char *, int len);
+#endif
+ QDataStream &readBytes(char *&, qint64 &len);
+ qint64 readRawData(char *, qint64 len);
+ QDataStream &writeBytes(const char *, qint64 len);
+ qint64 writeRawData(const char *, qint64 len);
+ qint64 skipRawData(qint64 len);
void startTransaction();
bool commitTransaction();
void rollbackTransaction();
void abortTransaction();
+ bool isDeviceTransactionStarted() const;
private:
Q_DISABLE_COPY(QDataStream)
QScopedPointer<QDataStreamPrivate> d;
- QIODevice *dev;
- bool owndev;
- bool noswap;
- ByteOrder byteorder;
- int ver;
- Status q_status;
+ QIODevice *dev = nullptr;
+ bool owndev = false;
+ bool noswap = QSysInfo::ByteOrder == QSysInfo::BigEndian;
+ quint8 fpPrecision = QDataStream::DoublePrecision;
+ quint8 q_status = Ok;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ ByteOrder byteorder = BigEndian;
+ int ver = Qt_DefaultCompiledVersion;
+#else
+ Version ver = Qt_DefaultCompiledVersion;
+#endif
+ quint16 transactionDepth = 0;
+#if QT_CORE_REMOVED_SINCE(6, 7)
int readBlock(char *data, int len);
+#endif
+ qint64 readBlock(char *data, qint64 len);
+ static inline qint64 readQSizeType(QDataStream &s);
+ static inline bool writeQSizeType(QDataStream &s, qint64 value);
+ static constexpr quint32 NullCode = 0xffffffffu;
+ static constexpr quint32 ExtendedSize = 0xfffffffeu;
+
friend class QtPrivate::StreamStateSaver;
+ Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QString &str);
+ Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QString &str);
+ Q_CORE_EXPORT friend QDataStream &operator<<(QDataStream &out, const QByteArray &ba);
+ Q_CORE_EXPORT friend QDataStream &operator>>(QDataStream &in, QByteArray &ba);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readArrayBasedContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readListBasedContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::readAssociativeContainer(QDataStream &s, Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeSequentialContainer(QDataStream &s, const Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeAssociativeContainer(QDataStream &s, const Container &c);
+ template <typename Container>
+ friend QDataStream &QtPrivate::writeAssociativeMultiContainer(QDataStream &s,
+ const Container &c);
};
namespace QtPrivate {
class StreamStateSaver
{
+ Q_DISABLE_COPY_MOVE(StreamStateSaver)
public:
inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status())
{
- if (!stream->dev || !stream->dev->isTransactionStarted())
+ if (!stream->isDeviceTransactionStarted())
stream->resetStatus();
}
inline ~StreamStateSaver()
@@ -242,10 +288,14 @@ QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
c.reserve(n);
- for (quint32 i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
@@ -264,9 +314,13 @@ QDataStream &readListBasedContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
- for (quint32 i = 0; i < n; ++i) {
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::value_type t;
s >> t;
if (s.status() != QDataStream::Ok) {
@@ -285,9 +339,13 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
StreamStateSaver stateSaver(&s);
c.clear();
- quint32 n;
- s >> n;
- for (quint32 i = 0; i < n; ++i) {
+ qint64 size = QDataStream::readQSizeType(s);
+ qsizetype n = size;
+ if (size != n || size < 0) {
+ s.setStatus(QDataStream::SizeLimitExceeded);
+ return s;
+ }
+ for (qsizetype i = 0; i < n; ++i) {
typename Container::key_type k;
typename Container::mapped_type t;
s >> k >> t;
@@ -304,7 +362,8 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
template <typename Container>
QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
for (const typename Container::value_type &t : c)
s << t;
@@ -314,7 +373,8 @@ QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
template <typename Container>
QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
auto it = c.constBegin();
auto end = c.constEnd();
while (it != end) {
@@ -328,7 +388,8 @@ QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
template <typename Container>
QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
{
- s << quint32(c.size());
+ if (!QDataStream::writeQSizeType(s, c.size()))
+ return s;
auto it = c.constBegin();
auto end = c.constEnd();
while (it != end) {
@@ -347,6 +408,20 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
} // QtPrivate namespace
+template<typename ...T>
+using QDataStreamIfHasOStreamOperators =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator<QDataStream, T>...>, QDataStream &>;
+template<typename Container, typename ...T>
+using QDataStreamIfHasOStreamOperatorsContainer =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_ostream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
+
+template<typename ...T>
+using QDataStreamIfHasIStreamOperators =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator<QDataStream, T>...>, QDataStream &>;
+template<typename Container, typename ...T>
+using QDataStreamIfHasIStreamOperatorsContainer =
+ std::enable_if_t<std::conjunction_v<QTypeTraits::has_istream_operator_container<QDataStream, Container, T>...>, QDataStream &>;
+
/*****************************************************************************
QDataStream inline functions
*****************************************************************************/
@@ -354,14 +429,61 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c)
inline QIODevice *QDataStream::device() const
{ return dev; }
+#if QT_CORE_INLINE_IMPL_SINCE(6, 8)
+QDataStream::Status QDataStream::status() const
+{
+ return Status(q_status);
+}
+
+QDataStream::FloatingPointPrecision QDataStream::floatingPointPrecision() const
+{
+ return FloatingPointPrecision(fpPrecision);
+}
+#endif // INLINE_SINCE 6.8
+
inline QDataStream::ByteOrder QDataStream::byteOrder() const
-{ return byteorder; }
+{
+ if constexpr (QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ return noswap ? BigEndian : LittleEndian;
+ return noswap ? LittleEndian : BigEndian;
+}
inline int QDataStream::version() const
{ return ver; }
inline void QDataStream::setVersion(int v)
-{ ver = v; }
+{ ver = Version(v); }
+
+qint64 QDataStream::readQSizeType(QDataStream &s)
+{
+ quint32 first;
+ s >> first;
+ if (first == NullCode)
+ return -1;
+ if (first < ExtendedSize || s.version() < QDataStream::Qt_6_7)
+ return qint64(first);
+ qint64 extendedLen;
+ s >> extendedLen;
+ return extendedLen;
+}
+
+bool QDataStream::writeQSizeType(QDataStream &s, qint64 value)
+{
+ if (value < qint64(ExtendedSize)) {
+ s << quint32(value);
+ } else if (s.version() >= QDataStream::Qt_6_7) {
+ s << ExtendedSize << value;
+ } else if (value == qint64(ExtendedSize)) {
+ s << ExtendedSize;
+ } else {
+ s.setStatus(QDataStream::SizeLimitExceeded); // value is too big for old format
+ return false;
+ }
+ return true;
+}
+
+inline QDataStream &QDataStream::operator>>(char &i)
+{ return *this >> reinterpret_cast<qint8&>(i); }
inline QDataStream &QDataStream::operator>>(quint8 &i)
{ return *this >> reinterpret_cast<qint8&>(i); }
@@ -375,6 +497,9 @@ inline QDataStream &QDataStream::operator>>(quint32 &i)
inline QDataStream &QDataStream::operator>>(quint64 &i)
{ return *this >> reinterpret_cast<qint64&>(i); }
+inline QDataStream &QDataStream::operator<<(char i)
+{ return *this << qint8(i); }
+
inline QDataStream &QDataStream::operator<<(quint8 i)
{ return *this << qint8(i); }
@@ -389,110 +514,174 @@ inline QDataStream &QDataStream::operator<<(quint64 i)
template <typename Enum>
inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e)
-{ return s << e.i; }
+{ return s << typename QFlags<Enum>::Int(e); }
template <typename Enum>
inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
-{ return s >> e.i; }
+{
+ typename QFlags<Enum>::Int i;
+ s >> i;
+ e = QFlag(i);
+ return s;
+}
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
operator<<(QDataStream &s, const T &t)
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
template <typename T>
-typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
+typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
+#ifndef Q_QDOC
+
template<typename T>
-inline QDataStream &operator>>(QDataStream &s, QList<T> &v)
+inline QDataStreamIfHasIStreamOperatorsContainer<QList<T>, T> operator>>(QDataStream &s, QList<T> &v)
{
return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
-inline QDataStream &operator<<(QDataStream &s, const QList<T> &v)
+inline QDataStreamIfHasOStreamOperatorsContainer<QList<T>, T> operator<<(QDataStream &s, const QList<T> &v)
{
return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
-inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
+inline QDataStreamIfHasIStreamOperatorsContainer<QSet<T>, T> operator>>(QDataStream &s, QSet<T> &set)
{
return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
-inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
+inline QDataStreamIfHasOStreamOperatorsContainer<QSet<T>, T> operator<<(QDataStream &s, const QSet<T> &set)
{
return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
+inline QDataStreamIfHasIStreamOperatorsContainer<QHash<Key, T>, Key, T> operator>>(QDataStream &s, QHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
+inline QDataStreamIfHasOStreamOperatorsContainer<QHash<Key, T>, Key, T> operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator>>(QDataStream &s, QMultiHash<Key, T> &hash)
{
return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMultiHash<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiHash<Key, T> &hash)
{
return QtPrivate::writeAssociativeMultiContainer(s, hash);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMap<Key, T>, Key, T> operator>>(QDataStream &s, QMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMap<Key, T> &map)
{
return QtPrivate::writeAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map)
+inline QDataStreamIfHasIStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator>>(QDataStream &s, QMultiMap<Key, T> &map)
{
return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-inline QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
+inline QDataStreamIfHasOStreamOperatorsContainer<QMultiMap<Key, T>, Key, T> operator<<(QDataStream &s, const QMultiMap<Key, T> &map)
{
return QtPrivate::writeAssociativeMultiContainer(s, map);
}
-#ifndef QT_NO_DATASTREAM
template <class T1, class T2>
-inline QDataStream& operator>>(QDataStream& s, std::pair<T1, T2> &p)
+inline QDataStreamIfHasIStreamOperators<T1, T2> operator>>(QDataStream& s, std::pair<T1, T2> &p)
{
s >> p.first >> p.second;
return s;
}
template <class T1, class T2>
-inline QDataStream& operator<<(QDataStream& s, const std::pair<T1, T2> &p)
+inline QDataStreamIfHasOStreamOperators<T1, T2> operator<<(QDataStream& s, const std::pair<T1, T2> &p)
{
s << p.first << p.second;
return s;
}
-#endif
+
+#else
+
+template <class T>
+QDataStream &operator>>(QDataStream &s, QList<T> &l);
+
+template <class T>
+QDataStream &operator<<(QDataStream &s, const QList<T> &l);
+
+template <class T>
+QDataStream &operator>>(QDataStream &s, QSet<T> &set);
+
+template <class T>
+QDataStream &operator<<(QDataStream &s, const QSet<T> &set);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMultiHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMultiHash<Key, T> &hash);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator>>(QDataStream &s, QMultiMap<Key, T> &map);
+
+template <class Key, class T>
+QDataStream &operator<<(QDataStream &s, const QMultiMap<Key, T> &map);
+
+template <class T1, class T2>
+QDataStream &operator>>(QDataStream& s, std::pair<T1, T2> &p);
+
+template <class T1, class T2>
+QDataStream &operator<<(QDataStream& s, const std::pair<T1, T2> &p);
+
+#endif // Q_QDOC
+
+inline QDataStream &operator>>(QDataStream &s, QKeyCombination &combination)
+{
+ int combined;
+ s >> combined;
+ combination = QKeyCombination::fromCombined(combined);
+ return s;
+}
+
+inline QDataStream &operator<<(QDataStream &s, QKeyCombination combination)
+{
+ return s << combination.toCombined();
+}
#endif // QT_NO_DATASTREAM
diff --git a/src/corelib/serialization/qdatastream_p.h b/src/corelib/serialization/qdatastream_p.h
index 3ca0ae840e..c4fe7c784c 100644
--- a/src/corelib/serialization/qdatastream_p.h
+++ b/src/corelib/serialization/qdatastream_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATASTREAM_P_H
#define QDATASTREAM_P_H
@@ -60,11 +24,6 @@ QT_BEGIN_NAMESPACE
class QDataStreamPrivate
{
public:
- QDataStreamPrivate() : floatingPointPrecision(QDataStream::DoublePrecision),
- transactionDepth(0) { }
-
- QDataStream::FloatingPointPrecision floatingPointPrecision;
- int transactionDepth;
};
#endif
diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h
index 4589284ef3..5a5b6926be 100644
--- a/src/corelib/serialization/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSON_P_H
#define QJSON_P_H
@@ -56,6 +20,11 @@
#include <qcborvalue.h>
#include <private/qcborvalue_p.h>
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+# include <qjsonarray.h>
+# include <qjsonobject.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QJsonPrivate {
@@ -129,14 +98,13 @@ struct ObjectIterator
ObjectIterator &operator-=(difference_type n) { it -= 2 * n; return *this; }
reference operator*() const { return *it; }
- reference operator[](int n) const { return it[n * 2]; }
+ reference operator[](qsizetype n) const { return it[n * 2]; }
bool operator<(ObjectIterator other) const { return it < other.it; }
bool operator>(ObjectIterator other) const { return it > other.it; }
bool operator<=(ObjectIterator other) const { return it <= other.it; }
bool operator>=(ObjectIterator other) const { return it >= other.it; }
-private:
ElementsIterator it;
};
@@ -149,7 +117,7 @@ inline ObjectIterator<Element, ElementsIterator> operator+(
}
template<typename Element, typename ElementsIterator>
inline ObjectIterator<Element, ElementsIterator> operator+(
- int n, ObjectIterator<Element, ElementsIterator> a)
+ qsizetype n, ObjectIterator<Element, ElementsIterator> a)
{
return {a.elementsIterator() + 2 * n};
}
@@ -161,7 +129,7 @@ inline ObjectIterator<Element, ElementsIterator> operator-(
return {a.elementsIterator() - 2 * n};
}
template<typename Element, typename ElementsIterator>
-inline int operator-(
+inline qsizetype operator-(
ObjectIterator<Element, ElementsIterator> a,
ObjectIterator<Element, ElementsIterator> b)
{
@@ -203,18 +171,47 @@ inline void swap(KeyIterator::reference a, KeyIterator::reference b)
class Value
{
public:
+ static qint64 valueHelper(const QCborValue &v) { return v.n; }
static QCborContainerPrivate *container(const QCborValue &v) { return v.container; }
+ static const QCborContainerPrivate *container(QJsonValueConstRef r) noexcept
+ {
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ return (r.is_object ? r.o->o : r.a->a).data();
+#else
+ return r.d;
+#endif
+ }
+ static QCborContainerPrivate *container(QJsonValueRef r) noexcept
+ {
+ return const_cast<QCborContainerPrivate *>(container(QJsonValueConstRef(r)));
+ }
+ static qsizetype indexHelper(QJsonValueConstRef r) noexcept
+ {
+ qsizetype index = r.index;
+ if (r.is_object)
+ index = index * 2 + 1;
+ return index;
+ }
+ static const QtCbor::Element &elementHelper(QJsonValueConstRef r) noexcept
+ {
+ return container(r)->elements.at(indexHelper(r));
+ }
static QJsonValue fromTrustedCbor(const QCborValue &v)
{
QJsonValue result;
- result.d = v.container;
- result.n = v.n;
- result.t = v.t;
+ result.value = v;
return result;
}
};
+class Variant
+{
+public:
+ static QJsonObject toJsonObject(const QVariantMap &map);
+ static QJsonArray toJsonArray(const QVariantList &list);
+};
+
} // namespace QJsonPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 98ace021fc..0c1b0ac7c8 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -58,11 +22,16 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonArray class encapsulates a JSON array.
+ \compares equality
+ \compareswith equality QJsonValue
+ \endcompareswith
+
A JSON array is a list of values. The list can be manipulated by inserting and
removing QJsonValue's from the array.
@@ -75,7 +44,7 @@ QT_BEGIN_NAMESPACE
You can convert the array to and from text based JSON through QJsonDocument.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -93,7 +62,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonArray::size_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
/*!
@@ -105,7 +74,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonArray::difference_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
/*!
@@ -155,23 +124,6 @@ QJsonArray::QJsonArray() = default;
QJsonArray::QJsonArray(QCborContainerPrivate *array)
: a(array)
{
- Q_ASSERT(array);
-}
-
-/*!
- This method replaces part of QJsonArray(std::initializer_list<QJsonValue> args) .
- The constructor needs to be inline, but we do not want to leak implementation details
- of this class.
- \note this method is called for an uninitialized object
- \internal
- */
-void QJsonArray::initialize()
-{
- // Because we're being called with uninitialized state, we can't do:
- // a = nullptr;
- // QExplicitlyDataSharedPointer::operator= will read the current value
- void *ptr = &a;
- memset(ptr, 0, sizeof(a));
}
/*!
@@ -191,11 +143,13 @@ QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args)
Since QJsonArray is implicitly shared, the copy is shallow
as long as the object doesn't get modified.
*/
-QJsonArray::QJsonArray(const QJsonArray &other)
-{
- a = other.a;
-}
+QJsonArray::QJsonArray(const QJsonArray &other) noexcept = default;
+/*!
+ \since 5.10
+
+ Move-constructs a QJsonArray from \a other.
+*/
QJsonArray::QJsonArray(QJsonArray &&other) noexcept
: a(other.a)
{
@@ -205,18 +159,7 @@ QJsonArray::QJsonArray(QJsonArray &&other) noexcept
/*!
Assigns \a other to this array.
*/
-QJsonArray &QJsonArray::operator =(const QJsonArray &other)
-{
- a = other.a;
- return *this;
-}
-
-/*!
- \fn QJsonArray::QJsonArray(QJsonArray &&other)
- \since 5.10
-
- Move-constructs a QJsonArray from \a other.
-*/
+QJsonArray &QJsonArray::operator =(const QJsonArray &other) noexcept = default;
/*!
\fn QJsonArray &QJsonArray::operator =(QJsonArray &&other)
@@ -272,16 +215,20 @@ QJsonArray QJsonArray::fromStringList(const QStringList &list)
return array;
}
+#ifndef QT_NO_VARIANT
/*!
Converts the variant list \a list to a QJsonArray.
The QVariant values in \a list will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa toVariantList(), QJsonValue::fromVariant()
*/
QJsonArray QJsonArray::fromVariantList(const QVariantList &list)
{
- return QCborArray::fromVariantList(list).toJsonArray();
+ return QJsonPrivate::Variant::toJsonArray(list);
}
/*!
@@ -293,12 +240,13 @@ QVariantList QJsonArray::toVariantList() const
{
return QCborArray::fromJsonArray(*this).toVariantList();
}
+#endif // !QT_NO_VARIANT
/*!
Returns the number of values stored in the array.
*/
-int QJsonArray::size() const
+qsizetype QJsonArray::size() const
{
return a ? a->elements.size() : 0;
}
@@ -327,7 +275,7 @@ bool QJsonArray::isEmpty() const
The returned QJsonValue is \c Undefined, if \a i is out of bounds.
*/
-QJsonValue QJsonArray::at(int i) const
+QJsonValue QJsonArray::at(qsizetype i) const
{
if (!a || i < 0 || i >= a->elements.size())
return QJsonValue(QJsonValue::Undefined);
@@ -387,11 +335,11 @@ void QJsonArray::append(const QJsonValue &value)
\sa insert(), replace()
*/
-void QJsonArray::removeAt(int i)
+void QJsonArray::removeAt(qsizetype i)
{
- if (!a || i < 0 || i >= a->elements.length())
+ if (!a || i < 0 || i >= a->elements.size())
return;
- detach2();
+ detach();
a->removeAt(i);
}
@@ -423,12 +371,12 @@ void QJsonArray::removeAt(int i)
\sa removeAt()
*/
-QJsonValue QJsonArray::takeAt(int i)
+QJsonValue QJsonArray::takeAt(qsizetype i)
{
- if (!a || i < 0 || i >= a->elements.length())
+ if (!a || i < 0 || i >= a->elements.size())
return QJsonValue(QJsonValue::Undefined);
- detach2();
+ detach();
const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(a->extractAt(i));
a->removeAt(i);
return v;
@@ -441,14 +389,14 @@ QJsonValue QJsonArray::takeAt(int i)
\sa append(), prepend(), replace(), removeAt()
*/
-void QJsonArray::insert(int i, const QJsonValue &value)
+void QJsonArray::insert(qsizetype i, const QJsonValue &value)
{
if (a)
- detach2(a->elements.length() + 1);
+ detach(a->elements.size() + 1);
else
a = new QCborContainerPrivate;
- Q_ASSERT (i >= 0 && i <= a->elements.length());
+ Q_ASSERT (i >= 0 && i <= a->elements.size());
a->insertAt(i, value.type() == QJsonValue::Undefined ? QCborValue(nullptr)
: QCborValue::fromJsonValue(value));
}
@@ -477,10 +425,10 @@ void QJsonArray::insert(int i, const QJsonValue &value)
\sa operator[](), removeAt()
*/
-void QJsonArray::replace(int i, const QJsonValue &value)
+void QJsonArray::replace(qsizetype i, const QJsonValue &value)
{
- Q_ASSERT (a && i >= 0 && i < a->elements.length());
- detach2();
+ Q_ASSERT (a && i >= 0 && i < a->elements.size());
+ detach();
a->replaceAt(i, QCborValue::fromJsonValue(value));
}
@@ -491,7 +439,7 @@ void QJsonArray::replace(int i, const QJsonValue &value)
*/
bool QJsonArray::contains(const QJsonValue &value) const
{
- for (int i = 0; i < size(); i++) {
+ for (qsizetype i = 0; i < size(); i++) {
if (at(i) == value)
return true;
}
@@ -511,9 +459,9 @@ bool QJsonArray::contains(const QJsonValue &value) const
\sa at()
*/
-QJsonValueRef QJsonArray::operator [](int i)
+QJsonValueRef QJsonArray::operator [](qsizetype i)
{
- Q_ASSERT(a && i >= 0 && i < a->elements.length());
+ Q_ASSERT(a && i >= 0 && i < a->elements.size());
return QJsonValueRef(this, i);
}
@@ -522,41 +470,45 @@ QJsonValueRef QJsonArray::operator [](int i)
Same as at().
*/
-QJsonValue QJsonArray::operator[](int i) const
+QJsonValue QJsonArray::operator[](qsizetype i) const
{
return at(i);
}
-/*!
- Returns \c true if this array is equal to \a other.
- */
-bool QJsonArray::operator==(const QJsonArray &other) const
+bool comparesEqual(const QJsonArray &lhs, const QJsonArray &rhs) noexcept
{
- if (a == other.a)
+ if (lhs.a == rhs.a)
return true;
- if (!a)
- return !other.a->elements.length();
- if (!other.a)
- return !a->elements.length();
- if (a->elements.length() != other.a->elements.length())
+ if (!lhs.a)
+ return !rhs.a->elements.size();
+ if (!rhs.a)
+ return !lhs.a->elements.size();
+ if (lhs.a->elements.size() != rhs.a->elements.size())
return false;
- for (int i = 0; i < a->elements.length(); ++i) {
- if (a->valueAt(i) != other.a->valueAt(i))
+ for (qsizetype i = 0; i < lhs.a->elements.size(); ++i) {
+ if (lhs.a->valueAt(i) != rhs.a->valueAt(i))
return false;
}
return true;
}
-/*!
- Returns \c true if this array is not equal to \a other.
- */
-bool QJsonArray::operator!=(const QJsonArray &other) const
+bool comparesEqual(const QJsonArray &lhs, const QJsonValue &rhs) noexcept
{
- return !(*this == other);
+ return lhs == rhs.toArray();
}
+/*! \fn bool QJsonArray::operator==(const QJsonArray &lhs, const QJsonArray &rhs)
+
+ Returns \c true if \a lhs array is equal to \a rhs, \c false otherwise.
+*/
+
+/*! \fn bool QJsonArray::operator!=(const QJsonArray &lhs, const QJsonArray &rhs)
+
+ Returns \c true if \a lhs array is not equal to \a rhs, \c false otherwise.
+*/
+
/*! \fn QJsonArray::iterator QJsonArray::begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in
@@ -651,6 +603,10 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\inmodule QtCore
\brief The QJsonArray::iterator class provides an STL-style non-const iterator for QJsonArray.
+ \compares strong
+ \compareswith strong QJsonArray::const_iterator
+ \endcompareswith
+
QJsonArray::iterator allows you to iterate over a QJsonArray
and to modify the array item associated with the
iterator. If you want to iterate over a const QJsonArray, use
@@ -713,7 +669,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa QJsonArray::begin(), QJsonArray::end()
*/
-/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, int index)
+/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, qsizetype index)
\internal
*/
@@ -737,7 +693,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
Returns a pointer to a modifiable reference to the current item.
*/
-/*! \fn QJsonValueRef QJsonArray::iterator::operator[](int j) const
+/*! \fn QJsonValueRef QJsonArray::iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at offset \a j from the
item pointed to by this iterator (the item at position \c{*this + j}).
@@ -755,60 +711,60 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
*/
/*!
- \fn bool QJsonArray::iterator::operator==(const iterator &other) const
- \fn bool QJsonArray::iterator::operator==(const const_iterator &other) const
+ \fn bool QJsonArray::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator==(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QJsonArray::iterator::operator!=(const iterator &other) const
- \fn bool QJsonArray::iterator::operator!=(const const_iterator &other) const
+ \fn bool QJsonArray::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator!=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonArray::iterator::operator<(const iterator& other) const
- \fn bool QJsonArray::iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator<(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator<(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator<=(const iterator& other) const
- \fn bool QJsonArray::iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator<=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator<=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator>(const iterator& other) const
- \fn bool QJsonArray::iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator>(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator>(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::iterator::operator>=(const iterator& other) const
- \fn bool QJsonArray::iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonArray::iterator::operator>=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonArray::iterator::operator>=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the
next item in the array and returns an iterator to the new current
item.
@@ -821,14 +777,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the
next item in the array and returns an iterator to the previously
current item.
*/
/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item
+ The prefix \c{--} operator, \c{--it}, makes the preceding item
current and returns an iterator to the new current item.
Calling this function on QJsonArray::begin() leads to undefined results.
@@ -840,11 +796,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix -- operator, \c{it--}, makes the preceding item
+ The postfix \c{--} operator, \c{it--}, makes the preceding item
current and returns an iterator to the previously current item.
*/
-/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(int j)
+/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -852,7 +808,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(int j)
+/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -860,7 +816,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+=(), operator-()
*/
-/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(int j) const
+/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -868,7 +824,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-(), operator+=()
*/
-/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(int j) const
+/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -876,7 +832,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+(), operator-=()
*/
-/*! \fn int QJsonArray::iterator::operator-(iterator other) const
+/*! \fn qsizetype QJsonArray::iterator::operator-(iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -886,6 +842,10 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\inmodule QtCore
\brief The QJsonArray::const_iterator class provides an STL-style const iterator for QJsonArray.
+ \compares strong
+ \compareswith strong QJsonArray::iterator
+ \endcompareswith
+
QJsonArray::const_iterator allows you to iterate over a
QJsonArray. If you want to modify the QJsonArray as
you iterate over it, use QJsonArray::iterator instead. It is generally a
@@ -922,7 +882,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa QJsonArray::constBegin(), QJsonArray::constEnd()
*/
-/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, int index)
+/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, qsizetype index)
\internal
*/
@@ -952,27 +912,22 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\internal
*/
-/*! \fn QJsonArray::const_iterator::const_iterator(const const_iterator &other)
-
- Constructs a copy of \a other.
-*/
-
/*! \fn QJsonArray::const_iterator::const_iterator(const iterator &other)
Constructs a copy of \a other.
*/
-/*! \fn QJsonValue QJsonArray::const_iterator::operator*() const
+/*! \fn const QJsonValueRef QJsonArray::const_iterator::operator*() const
Returns the current item.
*/
-/*! \fn QJsonValue *QJsonArray::const_iterator::operator->() const
+/*! \fn const QJsonValueRef *QJsonArray::const_iterator::operator->() const
Returns a pointer to the current item.
*/
-/*! \fn QJsonValue QJsonArray::const_iterator::operator[](int j) const
+/*! \fn QJsonValue QJsonArray::const_iterator::operator[](qsizetype j) const
Returns the item at offset \a j from the item pointed to by this iterator (the item at
position \c{*this + j}).
@@ -983,53 +938,53 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+()
*/
-/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &other) const
+/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
-/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &other) const
+/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonArray::const_iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator<(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator<=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator>(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonArray::const_iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonArray::const_iterator::operator>=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator++()
- The prefix ++ operator, \c{++it}, advances the iterator to the
+ The prefix \c{++} operator, \c{++it}, advances the iterator to the
next item in the array and returns an iterator to the new current
item.
@@ -1042,14 +997,14 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix ++ operator, \c{it++}, advances the iterator to the
+ The postfix \c{++} operator, \c{it++}, advances the iterator to the
next item in the array and returns an iterator to the previously
current item.
*/
/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator--()
- The prefix -- operator, \c{--it}, makes the preceding item
+ The prefix \c{--} operator, \c{--it}, makes the preceding item
current and returns an iterator to the new current item.
Calling this function on QJsonArray::begin() leads to undefined results.
@@ -1061,11 +1016,11 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\overload
- The postfix -- operator, \c{it--}, makes the preceding item
+ The postfix \c{--} operator, \c{it--}, makes the preceding item
current and returns an iterator to the previously current item.
*/
-/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(int j)
+/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1073,7 +1028,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(int j)
+/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1081,7 +1036,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+=(), operator-()
*/
-/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(int j) const
+/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1089,7 +1044,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator-(), operator+=()
*/
-/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(int j) const
+/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1097,27 +1052,16 @@ bool QJsonArray::operator!=(const QJsonArray &other) const
\sa operator+(), operator-=()
*/
-/*! \fn int QJsonArray::const_iterator::operator-(const_iterator other) const
+/*! \fn qsizetype QJsonArray::const_iterator::operator-(const_iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
*/
-
-/*!
- \internal
- */
-void QJsonArray::detach(uint reserve)
-{
- Q_UNUSED(reserve)
- Q_ASSERT(!reserve);
- detach2(0);
-}
-
/*!
\internal
*/
-bool QJsonArray::detach2(uint reserve)
+bool QJsonArray::detach(qsizetype reserve)
{
if (!a)
return true;
@@ -1125,14 +1069,6 @@ bool QJsonArray::detach2(uint reserve)
return a;
}
-/*!
- \internal
- */
-void QJsonArray::compact()
-{
- a->compact(a->elements.size());
-}
-
size_t qHash(const QJsonArray &array, size_t seed)
{
return qHashRange(array.begin(), array.end(), seed);
@@ -1158,9 +1094,7 @@ QDebug operator<<(QDebug dbg, const QJsonArray &a)
#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &stream, const QJsonArray &array)
{
- QJsonDocument doc{array};
- stream << doc.toJson(QJsonDocument::Compact);
- return stream;
+ return stream << QJsonDocument{array};
}
QDataStream &operator>>(QDataStream &stream, QJsonArray &array)
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 4466210ce6..26a04e9196 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONARRAY_H
#define QJSONARRAY_H
@@ -48,7 +12,6 @@
QT_BEGIN_NAMESPACE
class QDebug;
-class QStringList;
typedef QList<QVariant> QVariantList;
class Q_CORE_EXPORT QJsonArray
@@ -60,8 +23,8 @@ public:
~QJsonArray();
- QJsonArray(const QJsonArray &other);
- QJsonArray &operator =(const QJsonArray &other);
+ QJsonArray(const QJsonArray &other) noexcept;
+ QJsonArray &operator =(const QJsonArray &other) noexcept;
QJsonArray(QJsonArray &&other) noexcept;
@@ -75,136 +38,233 @@ public:
static QJsonArray fromVariantList(const QVariantList &list);
QVariantList toVariantList() const;
- int size() const;
- inline int count() const { return size(); }
+ qsizetype size() const;
+ inline qsizetype count() const { return size(); }
bool isEmpty() const;
- QJsonValue at(int i) const;
+ QJsonValue at(qsizetype i) const;
QJsonValue first() const;
QJsonValue last() const;
void prepend(const QJsonValue &value);
void append(const QJsonValue &value);
- void removeAt(int i);
- QJsonValue takeAt(int i);
+ void removeAt(qsizetype i);
+ QJsonValue takeAt(qsizetype i);
inline void removeFirst() { removeAt(0); }
inline void removeLast() { removeAt(size() - 1); }
- void insert(int i, const QJsonValue &value);
- void replace(int i, const QJsonValue &value);
+ void insert(qsizetype i, const QJsonValue &value);
+ void replace(qsizetype i, const QJsonValue &value);
bool contains(const QJsonValue &element) const;
- QJsonValueRef operator[](int i);
- QJsonValue operator[](int i) const;
+ QJsonValueRef operator[](qsizetype i);
+ QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonArray &other) const;
bool operator!=(const QJsonArray &other) const;
-
+#endif
void swap(QJsonArray &other) noexcept
{
- qSwap(a, other.a);
+ a.swap(other.a);
}
class const_iterator;
class iterator {
public:
- QJsonArray *a;
- int i;
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
- typedef QJsonValueRefPtr pointer;
-
- inline iterator() : a(nullptr), i(0) { }
- explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { }
-
- inline QJsonValueRef operator*() const { return QJsonValueRef(a, i); }
-#ifdef Q_QDOC
- inline QJsonValueRef* operator->() const;
-#else
- inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(a, i); }
+ typedef QJsonValueRef *pointer;
+
+ inline iterator() : item(static_cast<QJsonArray *>(nullptr), 0) { }
+ explicit inline iterator(QJsonArray *array, qsizetype index) : item(array, index) { }
+
+ constexpr iterator(const iterator &other) = default;
+ iterator &operator=(const iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QJsonValueRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueRef *operator->() { return &item; }
+ inline QJsonValueRef operator[](qsizetype j) const { return *(*this + j); }
+
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const iterator &o) const { return !operator==(o); }
+ inline bool operator<(const iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const iterator &other) const { return !operator<(other); }
+ inline bool operator==(const const_iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const const_iterator &o) const { return !operator==(o); }
+ inline bool operator<(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const const_iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const const_iterator &other) const { return !operator<(other); }
#endif
- inline QJsonValueRef operator[](int j) const { return QJsonValueRef(a, i + j); }
-
- inline bool operator==(const iterator &o) const { return i == o.i; }
- inline bool operator!=(const iterator &o) const { return i != o.i; }
- inline bool operator<(const iterator& other) const { return i < other.i; }
- inline bool operator<=(const iterator& other) const { return i <= other.i; }
- inline bool operator>(const iterator& other) const { return i > other.i; }
- inline bool operator>=(const iterator& other) const { return i >= other.i; }
- inline bool operator==(const const_iterator &o) const { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const { return i != o.i; }
- inline bool operator<(const const_iterator& other) const { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { iterator n = *this; ++i; return n; }
- inline iterator &operator--() { i--; return *this; }
- inline iterator operator--(int) { iterator n = *this; i--; return n; }
- inline iterator &operator+=(int j) { i+=j; return *this; }
- inline iterator &operator-=(int j) { i-=j; return *this; }
- inline iterator operator+(int j) const { return iterator(a, i+j); }
- inline iterator operator-(int j) const { return iterator(a, i-j); }
- inline int operator-(iterator j) const { return i - j.i; }
+ inline iterator &operator++() { ++item.index; return *this; }
+ inline iterator operator++(int) { iterator n = *this; ++item.index; return n; }
+ inline iterator &operator--() { item.index--; return *this; }
+ inline iterator operator--(int) { iterator n = *this; item.index--; return n; }
+ inline iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ inline iterator operator+(qsizetype j) const { iterator r = *this; return r += j; }
+ inline iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline qsizetype operator-(iterator j) const { return item.index - j.item.index; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static bool comparesEqual_helper(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator)
+ friend bool comparesEqual(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator, const_iterator)
+
+ QJsonValueRef item;
+ friend class QJsonArray;
};
friend class iterator;
class const_iterator {
public:
- const QJsonArray *a;
- int i;
typedef std::random_access_iterator_tag iterator_category;
typedef qptrdiff difference_type;
typedef QJsonValue value_type;
- typedef QJsonValue reference;
- typedef QJsonValuePtr pointer;
-
- inline const_iterator() : a(nullptr), i(0) { }
- explicit inline const_iterator(const QJsonArray *array, int index) : a(array), i(index) { }
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- inline const_iterator(const const_iterator &o) : a(o.a), i(o.i) {} // ### Qt 6: Removed so class can be trivially-copyable
-#endif
- inline const_iterator(const iterator &o) : a(o.a), i(o.i) {}
-
- inline QJsonValue operator*() const { return a->at(i); }
-#ifdef Q_QDOC
- inline QJsonValue* operator->() const;
-#else
- inline QJsonValuePtr operator->() const { return QJsonValuePtr(a->at(i)); }
+ typedef const QJsonValueRef reference;
+ typedef const QJsonValueRef *pointer;
+
+ inline const_iterator() : item(static_cast<QJsonArray *>(nullptr), 0) { }
+ explicit inline const_iterator(const QJsonArray *array, qsizetype index)
+ : item(const_cast<QJsonArray *>(array), index) { }
+ inline const_iterator(const iterator &o) : item(o.item) { }
+
+ constexpr const_iterator(const const_iterator &other) = default;
+ const_iterator &operator=(const const_iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline const QJsonValueConstRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+
+ inline QJsonValueConstRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &o) const
+ { return item.d == o.item.d && item.index == o.item.index; }
+ inline bool operator!=(const const_iterator &o) const { return !operator==(o); }
+ inline bool operator<(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ inline bool operator<=(const const_iterator &other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ inline bool operator>(const const_iterator &other) const { return !operator<=(other); }
+ inline bool operator>=(const const_iterator &other) const { return !operator<(other); }
#endif
- inline QJsonValue operator[](int j) const { return a->at(i+j); }
- inline bool operator==(const const_iterator &o) const { return i == o.i; }
- inline bool operator!=(const const_iterator &o) const { return i != o.i; }
- inline bool operator<(const const_iterator& other) const { return i < other.i; }
- inline bool operator<=(const const_iterator& other) const { return i <= other.i; }
- inline bool operator>(const const_iterator& other) const { return i > other.i; }
- inline bool operator>=(const const_iterator& other) const { return i >= other.i; }
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { const_iterator n = *this; ++i; return n; }
- inline const_iterator &operator--() { i--; return *this; }
- inline const_iterator operator--(int) { const_iterator n = *this; i--; return n; }
- inline const_iterator &operator+=(int j) { i+=j; return *this; }
- inline const_iterator &operator-=(int j) { i-=j; return *this; }
- inline const_iterator operator+(int j) const { return const_iterator(a, i+j); }
- inline const_iterator operator-(int j) const { return const_iterator(a, i-j); }
- inline int operator-(const_iterator j) const { return i - j.i; }
+ inline const_iterator &operator++() { ++item.index; return *this; }
+ inline const_iterator operator++(int) { const_iterator n = *this; ++item.index; return n; }
+ inline const_iterator &operator--() { item.index--; return *this; }
+ inline const_iterator operator--(int) { const_iterator n = *this; item.index--; return n; }
+ inline const_iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline const_iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ inline const_iterator operator+(qsizetype j) const { const_iterator r = *this; return r += j; }
+ inline const_iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline qsizetype operator-(const_iterator j) const { return item.index - j.item.index; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(const_iterator)
+ QJsonValueConstRef item;
+ friend class QJsonArray;
};
friend class const_iterator;
// stl style
- inline iterator begin() { detach2(); return iterator(this, 0); }
+ inline iterator begin() { detach(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
inline const_iterator cbegin() const { return const_iterator(this, 0); }
- inline iterator end() { detach2(); return iterator(this, size()); }
+ inline iterator end() { detach(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
inline const_iterator cend() const { return const_iterator(this, size()); }
- iterator insert(iterator before, const QJsonValue &value) { insert(before.i, value); return before; }
- iterator erase(iterator it) { removeAt(it.i); return it; }
+ iterator insert(iterator before, const QJsonValue &value)
+ { insert(before.item.index, value); return before; }
+ iterator erase(iterator it)
+ { removeAt(it.item.index); return it; }
// more Qt
typedef iterator Iterator;
@@ -224,34 +284,45 @@ public:
inline void pop_front() { removeFirst(); }
inline void pop_back() { removeLast(); }
inline bool empty() const { return isEmpty(); }
- typedef int size_type;
+ typedef qsizetype size_type;
typedef QJsonValue value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef QJsonValueRef reference;
typedef QJsonValue const_reference;
- typedef int difference_type;
+ typedef qsizetype difference_type;
private:
friend class QJsonValue;
+ friend class QJsonValueConstRef;
+ friend class QJsonValueRef;
+ friend class QJsonPrivate::Value;
friend class QJsonDocument;
friend class QCborArray;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonArray &lhs,
+ const QJsonArray &rhs) noexcept;
+
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonArray &lhs,
+ const QJsonValue &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonArray)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonArray, QJsonValue)
+
QJsonArray(QCborContainerPrivate *array);
- void initialize();
- void compact();
- // ### Qt 6: remove me and merge with detach2
- void detach(uint reserve = 0);
- bool detach2(uint reserve = 0);
-
- // ### Qt 6: remove
- void *dead = nullptr;
+ bool detach(qsizetype reserve = 0);
+
QExplicitlySharedDataPointer<QCborContainerPrivate> a;
};
Q_DECLARE_SHARED(QJsonArray)
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+inline QJsonValueConstRef::QJsonValueConstRef(QJsonArray *a, qsizetype idx)
+ : d(a ? a->a.data() : nullptr), is_object(false), index(idx)
+{}
+#endif
+
Q_CORE_EXPORT size_t qHash(const QJsonArray &array, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
index e0eab74a02..da07eca8a7 100644
--- a/src/corelib/serialization/qjsoncbor.cpp
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcborvalue.h"
#include "qcborvalue_p.h"
@@ -48,6 +12,9 @@
#include "qjsondocument.h"
#include "qjson_p.h"
+#include <qmap.h>
+#include <qhash.h>
+
#include <private/qnumeric_p.h>
#include <quuid.h>
@@ -55,6 +22,8 @@ QT_BEGIN_NAMESPACE
using namespace QtCbor;
+enum class ConversionMode { FromRaw, FromVariantToJson };
+
static QJsonValue fpToJson(double v)
{
return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
@@ -89,13 +58,13 @@ static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QC
return QString::fromLatin1(data, data.size());
}
-static QString makeString(const QCborContainerPrivate *d, qsizetype idx);
+static QString makeString(const QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode = ConversionMode::FromRaw);
static QString maybeEncodeTag(const QCborContainerPrivate *d)
{
qint64 tag = d->elements.at(0).value;
const Element &e = d->elements.at(1);
- const ByteData *b = d->byteData(e);
switch (tag) {
case qint64(QCborKnownTags::DateTimeString):
@@ -112,8 +81,12 @@ static QString maybeEncodeTag(const QCborContainerPrivate *d)
break;
case qint64(QCborKnownTags::Uuid):
- if (e.type == QCborValue::ByteArray && b->len == sizeof(QUuid))
+#ifndef QT_BOOTSTRAPPED
+ if (const ByteData *b = d->byteData(e); e.type == QCborValue::ByteArray && b
+ && b->len == sizeof(QUuid))
return QUuid::fromRfc4122(b->asByteArrayView()).toString(QUuid::WithoutBraces);
+#endif
+ break;
}
// don't know what to do, bail out
@@ -134,7 +107,8 @@ static QString encodeTag(const QCborContainerPrivate *d)
return s;
}
-static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizetype idx)
+static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode)
{
const auto &e = d->elements.at(idx);
@@ -146,7 +120,9 @@ static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizety
return QString::number(e.fpvalue());
case QCborValue::ByteArray:
- return encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
+ return mode == ConversionMode::FromVariantToJson
+ ? d->stringAt(idx)
+ : encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
case QCborValue::String:
return d->stringAt(idx);
@@ -190,19 +166,23 @@ static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizety
return simpleTypeString(e.type);
}
-QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx);
+QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx,
+ ConversionMode mode = ConversionMode::FromRaw);
static QJsonValue convertExtendedTypeToJson(QCborContainerPrivate *d)
{
-#ifndef QT_BUILD_QMAKE
qint64 tag = d->elements.at(0).value;
switch (tag) {
case qint64(QCborKnownTags::Url):
- // use the fullly-encoded URL form
+#ifdef QT_BOOTSTRAPPED
+ break;
+#else
+ // use the fully-encoded URL form
if (d->elements.at(1).type == QCborValue::String)
return QUrl::fromEncoded(d->byteData(1)->asByteArrayView()).toString(QUrl::FullyEncoded);
Q_FALLTHROUGH();
+#endif
case qint64(QCborKnownTags::DateTimeString):
case qint64(QCborKnownTags::ExpectedBase64url):
@@ -215,42 +195,43 @@ static QJsonValue convertExtendedTypeToJson(QCborContainerPrivate *d)
return s;
}
}
-#endif
// for all other tags, ignore it and return the converted tagged item
return qt_convertToJson(d, 1);
}
// We need to do this because sub-objects may need conversion.
-static QJsonArray convertToJsonArray(QCborContainerPrivate *d)
+static QJsonArray convertToJsonArray(QCborContainerPrivate *d,
+ ConversionMode mode = ConversionMode::FromRaw)
{
QJsonArray a;
if (d) {
for (qsizetype idx = 0; idx < d->elements.size(); ++idx)
- a.append(qt_convertToJson(d, idx));
+ a.append(qt_convertToJson(d, idx, mode));
}
return a;
}
// We need to do this because the keys need to be sorted and converted to strings
// and sub-objects may need recursive conversion.
-static QJsonObject convertToJsonObject(QCborContainerPrivate *d)
+static QJsonObject convertToJsonObject(QCborContainerPrivate *d,
+ ConversionMode mode = ConversionMode::FromRaw)
{
QJsonObject o;
if (d) {
for (qsizetype idx = 0; idx < d->elements.size(); idx += 2)
- o.insert(makeString(d, idx), qt_convertToJson(d, idx + 1));
+ o.insert(makeString(d, idx), qt_convertToJson(d, idx + 1, mode));
}
return o;
}
-QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
+QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx, ConversionMode mode)
{
// encoding the container itself
if (idx == -QCborValue::Array)
- return convertToJsonArray(d);
+ return convertToJsonArray(d, mode);
if (idx == -QCborValue::Map)
- return convertToJsonObject(d);
+ return convertToJsonObject(d, mode);
if (idx < 0) {
// tag-like type
if (!d || d->elements.size() != 2)
@@ -264,6 +245,15 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
case QCborValue::Integer:
return QJsonValue(e.value);
case QCborValue::ByteArray:
+ if (mode == ConversionMode::FromVariantToJson) {
+ const auto value = makeString(d, idx, mode);
+ return value.isEmpty() ? QJsonValue() : QJsonPrivate::Value::fromTrustedCbor(value);
+ }
+ break;
+ case QCborValue::RegularExpression:
+ if (mode == ConversionMode::FromVariantToJson)
+ return QJsonValue();
+ break;
case QCborValue::String:
case QCborValue::SimpleType:
// make string
@@ -274,10 +264,10 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
case QCborValue::Tag:
case QCborValue::DateTime:
case QCborValue::Url:
- case QCborValue::RegularExpression:
case QCborValue::Uuid:
// recurse
- return qt_convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type);
+ return qt_convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type,
+ mode);
case QCborValue::Null:
case QCborValue::Undefined:
@@ -294,7 +284,7 @@ QJsonValue qt_convertToJson(QCborContainerPrivate *d, qsizetype idx)
return fpToJson(e.fpvalue());
}
- return QJsonPrivate::Value::fromTrustedCbor(makeString(d, idx));
+ return QJsonPrivate::Value::fromTrustedCbor(makeString(d, idx, mode));
}
/*!
@@ -408,10 +398,12 @@ QJsonValue QCborValue::toJsonValue() const
return QJsonPrivate::Value::fromTrustedCbor(simpleTypeString(type()));
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QJsonValue QCborValueRef::toJsonValue() const
{
return qt_convertToJson(d, i);
}
+#endif
/*!
Recursively converts every \l QCborValue element in this array to JSON
@@ -429,6 +421,14 @@ QJsonArray QCborArray::toJsonArray() const
return convertToJsonArray(d.data());
}
+#ifndef QT_NO_VARIANT
+QJsonArray QJsonPrivate::Variant::toJsonArray(const QVariantList &list)
+{
+ const auto cborArray = QCborArray::fromVariantList(list);
+ return convertToJsonArray(cborArray.d.data(), ConversionMode::FromVariantToJson);
+}
+#endif // !QT_NO_VARIANT
+
/*!
Recursively converts every \l QCborValue value in this map to JSON using
QCborValue::toJsonValue() and creates a string key for all keys that aren't
@@ -471,6 +471,13 @@ QJsonObject QCborMap::toJsonObject() const
return convertToJsonObject(d.data());
}
+#ifndef QT_NO_VARIANT
+QJsonObject QJsonPrivate::Variant::toJsonObject(const QVariantMap &map)
+{
+ const auto cborMap = QCborMap::fromVariantMap(map);
+ return convertToJsonObject(cborMap.d.data(), ConversionMode::FromVariantToJson);
+}
+
/*!
Converts this value to a native Qt type and returns the corresponding QVariant.
@@ -552,15 +559,15 @@ QVariant QCborValue::toVariant() const
#ifndef QT_BOOTSTRAPPED
case Url:
return toUrl();
-#endif
-#if QT_CONFIG(regularexpression)
+# if QT_CONFIG(regularexpression)
case RegularExpression:
return toRegularExpression();
-#endif
+# endif
case Uuid:
return toUuid();
+#endif
case Invalid:
return QVariant();
@@ -572,9 +579,9 @@ QVariant QCborValue::toVariant() const
if (isSimpleType())
return QVariant::fromValue(toSimpleType());
- Q_UNREACHABLE();
- return QVariant();
+ Q_UNREACHABLE_RETURN(QVariant());
}
+#endif // !QT_NO_VARIANT
/*!
Converts the JSON value contained in \a v into its corresponding CBOR value
@@ -610,7 +617,7 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
case QJsonValue::Bool:
return v.toBool();
case QJsonValue::Double: {
- if (v.t == Integer)
+ if (v.value.t == Integer)
return v.toInteger();
return v.toDouble();
}
@@ -628,11 +635,12 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
return QCborValue();
}
+#ifndef QT_NO_VARIANT
static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
{
// Handle strings and byte arrays directly, to avoid creating a temporary
// dummy container to hold their data.
- int type = variant.userType();
+ int type = variant.metaType().id();
if (type == QMetaType::QString) {
d->append(variant.toString());
} else if (type == QMetaType::QByteArray) {
@@ -698,7 +706,7 @@ static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
*/
QCborValue QCborValue::fromVariant(const QVariant &variant)
{
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::UnknownType:
return {};
case QMetaType::Nullptr:
@@ -729,9 +737,9 @@ QCborValue QCborValue::fromVariant(const QVariant &variant)
#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
return QCborValue(variant.toUrl());
-#endif
case QMetaType::QUuid:
return QCborValue(variant.toUuid());
+#endif
case QMetaType::QVariantList:
return QCborArray::fromVariantList(variant.toList());
case QMetaType::QVariantMap:
@@ -828,6 +836,7 @@ QCborArray QCborArray::fromVariantList(const QVariantList &list)
appendVariant(a.d.data(), v);
return a;
}
+#endif // !QT_NO_VARIANT
/*!
Converts all JSON items found in the \a array array to CBOR using
@@ -848,6 +857,19 @@ QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
}
/*!
+ \overload
+ \since 6.3
+ */
+QCborArray QCborArray::fromJsonArray(QJsonArray &&array) noexcept
+{
+ QCborArray result;
+ result.d = std::exchange(array.a, {});
+ return result;
+
+}
+
+#ifndef QT_NO_VARIANT
+/*!
Converts the CBOR values to QVariant using QCborValue::toVariant() and
"stringifies" all the CBOR keys in this map, returning the QVariantMap that
results from that association list.
@@ -943,6 +965,7 @@ QCborMap QCborMap::fromVariantHash(const QVariantHash &hash)
}
return m;
}
+#endif // !QT_NO_VARIANT
/*!
Converts all JSON items found in the \a obj object to CBOR using
@@ -961,4 +984,15 @@ QCborMap QCborMap::fromJsonObject(const QJsonObject &obj)
return result;
}
+/*!
+ \overload
+ \since 6.3
+ */
+QCborMap QCborMap::fromJsonObject(QJsonObject &&obj) noexcept
+{
+ QCborMap result;
+ result.d = std::exchange(obj.o, {});
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 338b752f13..e2528f18dc 100644
--- a/src/corelib/serialization/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsondocument.h>
#include <qjsonobject.h>
@@ -43,6 +7,8 @@
#include <qjsonarray.h>
#include <qstringlist.h>
#include <qvariant.h>
+#include <qmap.h>
+#include <qhash.h>
#include <qdebug.h>
#include <qcbormap.h>
#include <qcborarray.h>
@@ -52,28 +18,23 @@
#include "qjson_p.h"
#include "qdatastream.h"
-#if QT_CONFIG(binaryjson)
-#include "qbinaryjson_p.h"
-#include "qbinaryjsonobject_p.h"
-#include "qbinaryjsonarray_p.h"
-#endif
-
-#include <private/qmemory_p.h>
-
QT_BEGIN_NAMESPACE
/*! \class QJsonDocument
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonDocument class provides a way to read and write JSON documents.
- QJsonDocument is a class that wraps a complete JSON document and can read and
- write this document both from a UTF-8 encoded text based representation as well
- as Qt's own binary format.
+ \compares equality
+
+ QJsonDocument is a class that wraps a complete JSON document and can read
+ this document from, and write it to, a UTF-8 encoded text-based
+ representation.
A JSON document can be converted from its text-based representation to a QJsonDocument
using QJsonDocument::fromJson(). toJson() converts it back to text. The parser is very
@@ -85,10 +46,7 @@ QT_BEGIN_NAMESPACE
and isObject(). The array or object contained in the document can be retrieved using
array() or object() and then read or manipulated.
- A document can also be created from a stored binary representation using fromBinaryData() or
- fromRawData().
-
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
@@ -148,7 +106,7 @@ QJsonDocument::QJsonDocument(const QJsonArray &array)
\internal
*/
QJsonDocument::QJsonDocument(const QCborValue &data)
- : d(qt_make_unique<QJsonDocumentPrivate>(data))
+ : d(std::make_unique<QJsonDocumentPrivate>(data))
{
Q_ASSERT(d);
}
@@ -167,7 +125,7 @@ QJsonDocument::QJsonDocument(const QJsonDocument &other)
{
if (other.d) {
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
d->value = other.d->value;
} else {
d.reset();
@@ -193,7 +151,7 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
if (this != &other) {
if (other.d) {
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
d->value = other.d->value;
@@ -225,180 +183,7 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
Swaps the document \a other with this. This operation is very fast and never fails.
*/
-
-/*! \enum QJsonDocument::DataValidation
-
- This value is used to tell QJsonDocument whether to validate the binary data
- when converting to a QJsonDocument using fromBinaryData() or fromRawData().
-
- \value Validate Validate the data before using it. This is the default.
- \value BypassValidation Bypasses data validation. Only use if you received the
- data from a trusted place and know it's valid, as using of invalid data can crash
- the application.
- */
-
-#if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-/*!
- \deprecated
-
- Creates a QJsonDocument that uses the first \a size bytes from
- \a data. It assumes \a data contains a binary encoded JSON document.
- The created document does not take ownership of \a data. The data is
- copied into a different data structure, and the original data can be
- deleted or modified afterwards.
-
- \a data has to be aligned to a 4 byte boundary.
-
- \a validation decides whether the data is checked for validity before being used.
- By default the data is validated. If the \a data is not valid, the method returns
- a null document.
-
- Returns a QJsonDocument representing the data.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \note Before Qt 5.15, the caller had to guarantee that \a data would not be
- deleted or modified as long as any QJsonDocument, QJsonObject or QJsonArray
- still referenced the data. From Qt 5.15 on, this is not necessary anymore.
-
- \sa rawData(), fromBinaryData(), isNull(), DataValidation, QCborValue
- */
-QJsonDocument QJsonDocument::fromRawData(const char *data, int size, DataValidation validation)
-{
- if (quintptr(data) & 3) {
- qWarning("QJsonDocument::fromRawData: data has to have 4 byte alignment");
- return QJsonDocument();
- }
-
- if (size < 0 || uint(size) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base))
- return QJsonDocument();
-
- std::unique_ptr<QBinaryJsonPrivate::ConstData> binaryData
- = qt_make_unique<QBinaryJsonPrivate::ConstData>(data, size);
-
- return (validation == BypassValidation || binaryData->isValid())
- ? binaryData->toJsonDocument()
- : QJsonDocument();
-}
-
-/*!
- \deprecated
-
- Returns the raw binary representation of the data
- \a size will contain the size of the returned data.
-
- This method is useful to e.g. stream the JSON document
- in its binary form to a file.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa QCborValue
- */
-const char *QJsonDocument::rawData(int *size) const
-{
- if (!d) {
- *size = 0;
- return nullptr;
- }
-
- if (!d->rawData) {
- if (isObject()) {
- QBinaryJsonObject o = QBinaryJsonObject::fromJsonObject(object());
- d->rawData = o.takeRawData(&(d->rawDataSize));
- } else {
- QBinaryJsonArray a = QBinaryJsonArray::fromJsonArray(array());
- d->rawData = a.takeRawData(&(d->rawDataSize));
- }
- }
-
- // It would be quite miraculous if not, as we should have hit the 128MB limit then.
- Q_ASSERT(d->rawDataSize <= uint(std::numeric_limits<int>::max()));
-
- *size = d->rawDataSize;
- return d->rawData;
-}
-
-/*!
- \deprecated
- Creates a QJsonDocument from \a data.
-
- \a validation decides whether the data is checked for validity before being used.
- By default the data is validated. If the \a data is not valid, the method returns
- a null document.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa toBinaryData(), fromRawData(), isNull(), DataValidation, QCborValue
- */
-QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation)
-{
- if (uint(data.size()) < sizeof(QBinaryJsonPrivate::Header) + sizeof(QBinaryJsonPrivate::Base))
- return QJsonDocument();
-
- QBinaryJsonPrivate::Header h;
- memcpy(&h, data.constData(), sizeof(QBinaryJsonPrivate::Header));
- QBinaryJsonPrivate::Base root;
- memcpy(&root, data.constData() + sizeof(QBinaryJsonPrivate::Header),
- sizeof(QBinaryJsonPrivate::Base));
-
- const uint size = sizeof(QBinaryJsonPrivate::Header) + root.size;
- if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1U || size > uint(data.size()))
- return QJsonDocument();
-
- std::unique_ptr<QBinaryJsonPrivate::ConstData> d
- = qt_make_unique<QBinaryJsonPrivate::ConstData>(data.constData(), size);
-
- return (validation == BypassValidation || d->isValid())
- ? d->toJsonDocument()
- : QJsonDocument();
-}
-
-/*!
- \deprecated
- Returns a binary representation of the document.
-
- The binary representation is also the native format used internally in Qt,
- and is very efficient and fast to convert to and from.
-
- The binary format can be stored on disk and interchanged with other applications
- or computers. fromBinaryData() can be used to convert it back into a
- JSON document.
-
- \note Deprecated in Qt 5.15. The binary JSON encoding is only retained for backwards
- compatibility. It is undocumented and restrictive in the maximum size of JSON
- documents that can be encoded. Qt JSON types can be converted to Qt CBOR types,
- which can in turn be serialized into the CBOR binary format and vice versa. The
- CBOR format is a well-defined and less restrictive binary representation for a
- superset of JSON.
-
- \sa fromBinaryData(), QCborValue
- */
-QByteArray QJsonDocument::toBinaryData() const
-{
- int size = 0;
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- const char *raw = rawData(&size);
-QT_WARNING_POP
- return QByteArray(raw, size);
-}
-#endif // QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-
+#ifndef QT_NO_VARIANT
/*!
Creates a QJsonDocument from the QVariant \a variant.
@@ -411,7 +196,7 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
{
QJsonDocument doc;
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::QVariantMap:
doc.setObject(QJsonObject::fromVariantMap(variant.toMap()));
break;
@@ -422,7 +207,7 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
doc.setArray(QJsonArray::fromVariantList(variant.toList()));
break;
case QMetaType::QStringList:
- doc.d = qt_make_unique<QJsonDocumentPrivate>();
+ doc.d = std::make_unique<QJsonDocumentPrivate>();
doc.d->value = QCborArray::fromStringList(variant.toStringList());
break;
default:
@@ -449,18 +234,7 @@ QVariant QJsonDocument::toVariant() const
return QJsonArray(container).toVariantList();
return QJsonObject(container).toVariantMap();
}
-
-/*!
- Converts the QJsonDocument to an indented, UTF-8 encoded JSON document.
-
- \sa fromJson()
- */
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
-QByteArray QJsonDocument::toJson() const
-{
- return toJson(Indented);
-}
-#endif
+#endif // !QT_NO_VARIANT
/*!
\enum QJsonDocument::JsonFormat
@@ -482,7 +256,7 @@ QByteArray QJsonDocument::toJson() const
\sa fromJson(), JsonFormat
*/
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
+#if !defined(QT_JSON_READONLY) || defined(Q_QDOC)
QByteArray QJsonDocument::toJson(JsonFormat format) const
{
QByteArray json;
@@ -511,11 +285,11 @@ QByteArray QJsonDocument::toJson(JsonFormat format) const
*/
QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error)
{
- QJsonPrivate::Parser parser(json.constData(), json.length());
+ QJsonPrivate::Parser parser(json.constData(), json.size());
QJsonDocument result;
const QCborValue val = parser.parse(error);
if (val.isArray() || val.isMap()) {
- result.d = qt_make_unique<QJsonDocumentPrivate>();
+ result.d = std::make_unique<QJsonDocumentPrivate>();
result.d->value = val;
}
return result;
@@ -600,7 +374,7 @@ QJsonArray QJsonDocument::array() const
void QJsonDocument::setObject(const QJsonObject &object)
{
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
@@ -615,14 +389,13 @@ void QJsonDocument::setObject(const QJsonObject &object)
void QJsonDocument::setArray(const QJsonArray &array)
{
if (!d)
- d = qt_make_unique<QJsonDocumentPrivate>();
+ d = std::make_unique<QJsonDocumentPrivate>();
else
d->clearRawData();
d->value = QCborValue::fromJsonValue(array);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -639,7 +412,6 @@ const QJsonValue QJsonDocument::operator[](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -657,7 +429,7 @@ const QJsonValue QJsonDocument::operator[](QStringView key) const
\overload
\since 5.10
*/
-const QJsonValue QJsonDocument::operator[](QLatin1String key) const
+const QJsonValue QJsonDocument::operator[](QLatin1StringView key) const
{
if (!isObject())
return QJsonValue(QJsonValue::Undefined);
@@ -677,7 +449,7 @@ const QJsonValue QJsonDocument::operator[](QLatin1String key) const
\sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
*/
-const QJsonValue QJsonDocument::operator[](int i) const
+const QJsonValue QJsonDocument::operator[](qsizetype i) const
{
if (!isArray())
return QJsonValue(QJsonValue::Undefined);
@@ -686,18 +458,22 @@ const QJsonValue QJsonDocument::operator[](int i) const
}
/*!
- Returns \c true if the \a other document is equal to this document.
- */
-bool QJsonDocument::operator==(const QJsonDocument &other) const
+ \fn bool QJsonDocument::operator==(const QJsonDocument &lhs, const QJsonDocument &rhs)
+
+ Returns \c true if the \a lhs document is equal to \a rhs document, \c false otherwise.
+*/
+bool comparesEqual(const QJsonDocument &lhs, const QJsonDocument &rhs) noexcept
{
- return (!d) ? (!other.d) : (d->value == other.d->value);
+ if (lhs.d && rhs.d)
+ return lhs.d->value == rhs.d->value;
+ return !lhs.d == !rhs.d;
}
/*!
- \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const
+ \fn bool QJsonDocument::operator!=(const QJsonDocument &lhs, const QJsonDocument &rhs)
- returns \c true if \a other is not equal to this document
- */
+ Returns \c true if the \a lhs document is not equal to \a rhs document, \c false otherwise.
+*/
/*!
returns \c true if this document is null.
diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index 8c2840eda7..3659f7b5cb 100644
--- a/src/corelib/serialization/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONDOCUMENT_H
#define QJSONDOCUMENT_H
+#include <QtCore/qcompare.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qscopedpointer.h>
@@ -106,25 +71,6 @@ public:
void swap(QJsonDocument &other) noexcept;
- enum DataValidation {
- Validate,
- BypassValidation
- };
-
-#if QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use CBOR format instead")
- static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate);
-
- QT_DEPRECATED_X("Use CBOR format instead")
- const char *rawData(int *size) const;
-
- QT_DEPRECATED_X("Use CBOR format instead")
- static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate);
-
- QT_DEPRECATED_X("Use CBOR format instead")
- QByteArray toBinaryData() const;
-#endif // QT_CONFIG(binaryjson) && QT_DEPRECATED_SINCE(5, 15)
-
static QJsonDocument fromVariant(const QVariant &variant);
QVariant toVariant() const;
@@ -135,9 +81,8 @@ public:
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error = nullptr);
-#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC)
- QByteArray toJson() const; //### Merge in Qt6
- QByteArray toJson(JsonFormat format) const;
+#if !defined(QT_JSON_READONLY) || defined(Q_QDOC)
+ QByteArray toJson(JsonFormat format = Indented) const;
#endif
bool isEmpty() const;
@@ -150,22 +95,23 @@ public:
void setObject(const QJsonObject &object);
void setArray(const QJsonArray &array);
-#if QT_STRINGVIEW_LEVEL < 2
const QJsonValue operator[](const QString &key) const;
-#endif
const QJsonValue operator[](QStringView key) const;
- const QJsonValue operator[](QLatin1String key) const;
- const QJsonValue operator[](int i) const;
-
+ const QJsonValue operator[](QLatin1StringView key) const;
+ const QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonDocument &other) const;
- bool operator!=(const QJsonDocument &other) const { return !(*this == other); }
-
+ bool operator!=(const QJsonDocument &other) const { return !operator==(other); }
+#endif
bool isNull() const;
private:
friend class QJsonValue;
friend class QJsonPrivate::Parser;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonDocument &lhs,
+ const QJsonDocument &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonDocument)
QJsonDocument(const QCborValue &data);
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index bf2bdb957d..2f61de0824 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -45,6 +9,8 @@
#include <qdebug.h>
#include <qvariant.h>
#include <qcbormap.h>
+#include <qmap.h>
+#include <qhash.h>
#include <private/qcborvalue_p.h>
#include "qjsonwriter_p.h"
@@ -59,11 +25,16 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonObject class encapsulates a JSON object.
+ \compares equality
+ \compareswith equality QJsonValue QJsonValueConstRef
+ \endcompareswith
+
A JSON object is a list of key value pairs, where the keys are unique strings
and the values are represented by a QJsonValue.
@@ -76,7 +47,7 @@ QT_BEGIN_NAMESPACE
You can convert the object to and from text based JSON through QJsonDocument.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -106,7 +77,7 @@ QT_BEGIN_NAMESPACE
/*!
\typedef QJsonObject::size_type
- Typedef for int. Provided for STL compatibility.
+ Typedef for qsizetype. Provided for STL compatibility.
*/
@@ -118,7 +89,7 @@ QT_BEGIN_NAMESPACE
QJsonObject::QJsonObject() = default;
/*!
- \fn QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+ \fn QJsonObject::QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args)
\since 5.4
Constructs a QJsonObject instance initialized from \a args initialization list.
For example:
@@ -137,24 +108,6 @@ QJsonObject::QJsonObject() = default;
QJsonObject::QJsonObject(QCborContainerPrivate *object)
: o(object)
{
- Q_ASSERT(o);
-}
-
-/*!
- This method replaces part of the QJsonObject(std::initializer_list<QPair<QString, QJsonValue>> args) body.
- The constructor needs to be inline, but we do not want to leak implementation details
- of this class.
- \note this method is called for an uninitialized object
- \internal
- */
-
-void QJsonObject::initialize()
-{
- // Because we're being called with uninitialized state, we can't do:
- // o = nullptr;
- // QExplicitlyDataSharedPointer::operator= will read the current value
- void *ptr = &o;
- memset(ptr, 0, sizeof(o));
}
/*!
@@ -162,7 +115,7 @@ void QJsonObject::initialize()
*/
QJsonObject::~QJsonObject() = default;
-QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args)
+QJsonObject::QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args)
{
for (const auto &arg : args)
insert(arg.first, arg.second);
@@ -174,11 +127,13 @@ QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args
Since QJsonObject is implicitly shared, the copy is shallow
as long as the object does not get modified.
*/
-QJsonObject::QJsonObject(const QJsonObject &other)
-{
- o = other.o;
-}
+QJsonObject::QJsonObject(const QJsonObject &other) noexcept = default;
+
+/*!
+ \since 5.10
+ Move-constructs a QJsonObject from \a other.
+*/
QJsonObject::QJsonObject(QJsonObject &&other) noexcept
: o(other.o)
{
@@ -188,18 +143,8 @@ QJsonObject::QJsonObject(QJsonObject &&other) noexcept
/*!
Assigns \a other to this object.
*/
-QJsonObject &QJsonObject::operator =(const QJsonObject &other)
-{
- o = other.o;
- return *this;
-}
+QJsonObject &QJsonObject::operator =(const QJsonObject &other) noexcept = default;
-/*!
- \fn QJsonObject::QJsonObject(QJsonObject &&other)
- \since 5.10
-
- Move-constructs a QJsonObject from \a other.
-*/
/*!
\fn QJsonObject &QJsonObject::operator =(QJsonObject &&other)
@@ -215,18 +160,21 @@ QJsonObject &QJsonObject::operator =(const QJsonObject &other)
Swaps the object \a other with this. This operation is very fast and never fails.
*/
-
+#ifndef QT_NO_VARIANT
/*!
Converts the variant map \a map to a QJsonObject.
The keys in \a map will be used as the keys in the JSON object,
and the QVariant values will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa fromVariantHash(), toVariantMap(), QJsonValue::fromVariant()
*/
QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map)
{
- return QCborMap::fromVariantMap(map).toJsonObject();
+ return QJsonPrivate::Variant::toJsonObject(map);
}
/*!
@@ -248,6 +196,9 @@ QVariantMap QJsonObject::toVariantMap() const
The keys in \a hash will be used as the keys in the JSON object,
and the QVariant values will be converted to JSON values.
+ \note Conversion from \l QVariant is not completely lossless. Please see
+ the documentation in QJsonValue::fromVariant() for more information.
+
\sa fromVariantMap(), toVariantHash(), QJsonValue::fromVariant()
*/
QJsonObject QJsonObject::fromVariantHash(const QVariantHash &hash)
@@ -272,18 +223,19 @@ QVariantHash QJsonObject::toVariantHash() const
{
return QCborMap::fromJsonObject(*this).toVariantHash();
}
+#endif // !QT_NO_VARIANT
/*!
Returns a list of all keys in this object.
- The list is sorted lexographically.
+ The list is sorted alphabetically.
*/
QStringList QJsonObject::keys() const
{
QStringList keys;
if (o) {
- keys.reserve(o->elements.length() / 2);
- for (int i = 0, end = o->elements.length(); i < end; i += 2)
+ keys.reserve(o->elements.size() / 2);
+ for (qsizetype i = 0, end = o->elements.size(); i < end; i += 2)
keys.append(o->stringAt(i));
}
return keys;
@@ -292,9 +244,9 @@ QStringList QJsonObject::keys() const
/*!
Returns the number of (key, value) pairs stored in the object.
*/
-int QJsonObject::size() const
+qsizetype QJsonObject::size() const
{
- return o ? o->elements.length() / 2 : 0;
+ return o ? o->elements.size() / 2 : 0;
}
/*!
@@ -308,8 +260,8 @@ bool QJsonObject::isEmpty() const
}
template<typename String>
-static int indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
- String key, bool *keyExists)
+static qsizetype indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
+ String key, bool *keyExists)
{
const auto begin = QJsonPrivate::ConstKeyIterator(o->elements.constBegin());
const auto end = QJsonPrivate::ConstKeyIterator(o->elements.constEnd());
@@ -317,14 +269,13 @@ static int indexOf(const QExplicitlySharedDataPointer<QCborContainerPrivate> &o,
const auto it = std::lower_bound(
begin, end, key,
[&](const QJsonPrivate::ConstKeyIterator::value_type &e, const String &key) {
- return o->stringCompareElement(e.key(), key) < 0;
+ return o->stringCompareElement(e.key(), key, QtCbor::Comparison::ForOrdering) < 0;
});
*keyExists = (it != end) && o->stringEqualsElement((*it).key(), key);
- return (it - begin) * 2;
+ return it.it - begin.it;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -336,7 +287,6 @@ QJsonValue QJsonObject::value(const QString &key) const
{
return value(QStringView(key));
}
-#endif
/*!
\overload
@@ -351,7 +301,7 @@ QJsonValue QJsonObject::value(QStringView key) const
\overload
\since 5.7
*/
-QJsonValue QJsonObject::value(QLatin1String key) const
+QJsonValue QJsonObject::value(QLatin1StringView key) const
{
return valueImpl(key);
}
@@ -366,13 +316,12 @@ QJsonValue QJsonObject::valueImpl(T key) const
return QJsonValue(QJsonValue::Undefined);
bool keyExists;
- int i = indexOf(o, key, &keyExists);
+ auto i = indexOf(o, key, &keyExists);
if (!keyExists)
return QJsonValue(QJsonValue::Undefined);
return QJsonPrivate::Value::fromTrustedCbor(o->valueAt(i + 1));
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -386,7 +335,6 @@ QJsonValue QJsonObject::operator [](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\fn QJsonValue QJsonObject::operator [](QStringView key) const
@@ -396,13 +344,12 @@ QJsonValue QJsonObject::operator [](const QString &key) const
*/
/*!
- \fn QJsonValue QJsonObject::operator [](QLatin1String key) const
+ \fn QJsonValue QJsonObject::operator [](QLatin1StringView key) const
\overload
\since 5.7
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a reference to the value for \a key. If there is no value with key
\a key in the object, one is created with a QJsonValue::Null value and then
@@ -420,7 +367,6 @@ QJsonValueRef QJsonObject::operator [](const QString &key)
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -435,7 +381,7 @@ QJsonValueRef QJsonObject::operator [](QStringView key)
\overload
\since 5.7
*/
-QJsonValueRef QJsonObject::operator [](QLatin1String key)
+QJsonValueRef QJsonObject::operator [](QLatin1StringView key)
{
return atImpl(key);
}
@@ -450,9 +396,9 @@ QJsonValueRef QJsonObject::atImpl(T key)
o = new QCborContainerPrivate;
bool keyExists = false;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists) {
- detach2(o->elements.length() / 2 + 1);
+ detach(o->elements.size() / 2 + 1);
o->insertAt(index, key);
o->insertAt(index + 1, QCborValue::fromJsonValue(QJsonValue()));
}
@@ -460,7 +406,6 @@ QJsonValueRef QJsonObject::atImpl(T key)
return QJsonValueRef(this, index / 2);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Inserts a new item with the key \a key and a value of \a value.
@@ -478,7 +423,6 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &
{
return insert(QStringView(key), value);
}
-#endif
/*!
\overload
@@ -493,7 +437,7 @@ QJsonObject::iterator QJsonObject::insert(QStringView key, const QJsonValue &val
\overload
\since 5.14
*/
-QJsonObject::iterator QJsonObject::insert(QLatin1String key, const QJsonValue &value)
+QJsonObject::iterator QJsonObject::insert(QLatin1StringView key, const QJsonValue &value)
{
return insertImpl(key, value);
}
@@ -509,7 +453,7 @@ QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
return end();
}
bool keyExists = false;
- int pos = o ? indexOf(o, key, &keyExists) : 0;
+ auto pos = o ? indexOf(o, key, &keyExists) : 0;
return insertAt(pos, key, value, keyExists);
}
@@ -517,10 +461,10 @@ QJsonObject::iterator QJsonObject::insertImpl(T key, const QJsonValue &value)
\internal
*/
template <typename T>
-QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &value, bool keyExists)
+QJsonObject::iterator QJsonObject::insertAt(qsizetype pos, T key, const QJsonValue &value, bool keyExists)
{
if (o)
- detach2(o->elements.length() / 2 + (keyExists ? 0 : 1));
+ detach(o->elements.size() / 2 + (keyExists ? 0 : 1));
else
o = new QCborContainerPrivate;
@@ -533,7 +477,6 @@ QJsonObject::iterator QJsonObject::insertAt(int pos, T key, const QJsonValue &va
return {this, pos / 2};
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Removes \a key from the object.
@@ -543,7 +486,6 @@ void QJsonObject::remove(const QString &key)
{
remove(QStringView(key));
}
-#endif
/*!
\overload
@@ -558,7 +500,7 @@ void QJsonObject::remove(QStringView key)
\overload
\since 5.14
*/
-void QJsonObject::remove(QLatin1String key)
+void QJsonObject::remove(QLatin1StringView key)
{
removeImpl(key);
}
@@ -573,14 +515,13 @@ void QJsonObject::removeImpl(T key)
return;
bool keyExists;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists)
return;
- removeAt(index / 2);
+ removeAt(index);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Removes \a key from the object.
@@ -594,7 +535,6 @@ QJsonValue QJsonObject::take(const QString &key)
{
return take(QStringView(key));
}
-#endif
/*!
\overload
@@ -609,7 +549,7 @@ QJsonValue QJsonObject::take(QStringView key)
\overload
\since 5.14
*/
-QJsonValue QJsonObject::take(QLatin1String key)
+QJsonValue QJsonObject::take(QLatin1StringView key)
{
return takeImpl(key);
}
@@ -624,16 +564,16 @@ QJsonValue QJsonObject::takeImpl(T key)
return QJsonValue(QJsonValue::Undefined);
bool keyExists;
- int index = indexOf(o, key, &keyExists);
+ auto index = indexOf(o, key, &keyExists);
if (!keyExists)
return QJsonValue(QJsonValue::Undefined);
+ detach();
const QJsonValue v = QJsonPrivate::Value::fromTrustedCbor(o->extractAt(index + 1));
- removeAt(index / 2);
+ removeAt(index);
return v;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns \c true if the object contains key \a key.
@@ -643,7 +583,6 @@ bool QJsonObject::contains(const QString &key) const
{
return contains(QStringView(key));
}
-#endif
/*!
\overload
@@ -658,7 +597,7 @@ bool QJsonObject::contains(QStringView key) const
\overload
\since 5.7
*/
-bool QJsonObject::contains(QLatin1String key) const
+bool QJsonObject::contains(QLatin1StringView key) const
{
return containsImpl(key);
}
@@ -678,22 +617,24 @@ bool QJsonObject::containsImpl(T key) const
}
/*!
- Returns \c true if \a other is equal to this object.
- */
-bool QJsonObject::operator==(const QJsonObject &other) const
+ \fn bool QJsonObject::operator==(const QJsonObject &lhs, const QJsonObject &rhs)
+
+ Returns \c true if \a lhs object is equal to \a rhs, \c false otherwise.
+*/
+bool comparesEqual(const QJsonObject &lhs, const QJsonObject &rhs) noexcept
{
- if (o == other.o)
+ if (lhs.o == rhs.o)
return true;
- if (!o)
- return !other.o->elements.length();
- if (!other.o)
- return !o->elements.length();
- if (o->elements.length() != other.o->elements.length())
+ if (!lhs.o)
+ return !rhs.o->elements.size();
+ if (!rhs.o)
+ return !lhs.o->elements.size();
+ if (lhs.o->elements.size() != rhs.o->elements.size())
return false;
- for (int i = 0, end = o->elements.length(); i < end; ++i) {
- if (o->valueAt(i) != other.o->valueAt(i))
+ for (qsizetype i = 0, end = lhs.o->elements.size(); i < end; ++i) {
+ if (lhs.o->valueAt(i) != rhs.o->valueAt(i))
return false;
}
@@ -701,12 +642,10 @@ bool QJsonObject::operator==(const QJsonObject &other) const
}
/*!
- Returns \c true if \a other is not equal to this object.
- */
-bool QJsonObject::operator!=(const QJsonObject &other) const
-{
- return !(*this == other);
-}
+ \fn bool QJsonObject::operator!=(const QJsonObject &lhs, const QJsonObject &rhs)
+
+ Returns \c true if \a lhs object is not equal to \a rhs, \c false otherwise.
+*/
/*!
Removes the (key, value) pair pointed to by the iterator \a it
@@ -717,18 +656,14 @@ bool QJsonObject::operator!=(const QJsonObject &other) const
*/
QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it)
{
- if (it.o != this || it.i < 0 || it.i >= o->elements.length())
- return {this, o->elements.length()};
-
- int index = it.i;
-
- removeAt(index);
+ removeAt(it.item.index * 2);
- // iterator hasn't changed
- return it;
+ // index hasn't changed; the container pointer shouldn't have changed
+ // because we shouldn't have detached (detaching happens on obtaining a
+ // non-const iterator). But just in case we did, reload the pointer.
+ return { this, qsizetype(it.item.index) };
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns an iterator pointing to the item with key \a key in the
map.
@@ -740,7 +675,6 @@ QJsonObject::iterator QJsonObject::find(const QString &key)
{
return find(QStringView(key));
}
-#endif
/*!
\overload
@@ -755,7 +689,7 @@ QJsonObject::iterator QJsonObject::find(QStringView key)
\overload
\since 5.7
*/
-QJsonObject::iterator QJsonObject::find(QLatin1String key)
+QJsonObject::iterator QJsonObject::find(QLatin1StringView key)
{
return findImpl(key);
}
@@ -767,19 +701,17 @@ template <typename T>
QJsonObject::iterator QJsonObject::findImpl(T key)
{
bool keyExists = false;
- int index = o ? indexOf(o, key, &keyExists) : 0;
+ auto index = o ? indexOf(o, key, &keyExists) : 0;
if (!keyExists)
return end();
- detach2();
+ detach();
return {this, index / 2};
}
-#if QT_STRINGVIEW_LEVEL < 2
/*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const
\overload
*/
-#endif
/*! \fn QJsonObject::const_iterator QJsonObject::find(QStringView key) const
@@ -787,13 +719,12 @@ QJsonObject::iterator QJsonObject::findImpl(T key)
\since 5.14
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const
+/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1StringView key) const
\overload
\since 5.7
*/
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a const iterator pointing to the item with key \a key in the
map.
@@ -805,7 +736,6 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
{
return constFind(QStringView(key));
}
-#endif
/*!
\overload
@@ -820,7 +750,7 @@ QJsonObject::const_iterator QJsonObject::constFind(QStringView key) const
\overload
\since 5.7
*/
-QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const
+QJsonObject::const_iterator QJsonObject::constFind(QLatin1StringView key) const
{
return constFindImpl(key);
}
@@ -832,20 +762,20 @@ template <typename T>
QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
{
bool keyExists = false;
- int index = o ? indexOf(o, key, &keyExists) : 0;
+ auto index = o ? indexOf(o, key, &keyExists) : 0;
if (!keyExists)
return end();
return {this, index / 2};
}
-/*! \fn int QJsonObject::count() const
+/*! \fn qsizetype QJsonObject::count() const
\overload
Same as size().
*/
-/*! \fn int QJsonObject::length() const
+/*! \fn qsizetype QJsonObject::length() const
\overload
@@ -910,6 +840,10 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject.
+ \compares strong
+ \compareswith strong QJsonObject::const_iterator
+ \endcompareswith
+
QJsonObject::iterator allows you to iterate over a QJsonObject
and to modify the value (but not the key) stored under
a particular key. If you want to iterate over a const QJsonObject, you
@@ -926,7 +860,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Multiple iterators can be used on the same object. Existing iterators will however
become dangling once the object gets modified.
- \sa QJsonObject::const_iterator, {JSON Support in Qt}, {JSON Save Game Example}
+ \sa QJsonObject::const_iterator, {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*! \typedef QJsonObject::iterator::difference_type
@@ -969,7 +903,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa QJsonObject::begin(), QJsonObject::end()
*/
-/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index)
+/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, qsizetype index)
\internal
*/
@@ -1015,12 +949,17 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa key()
*/
-/*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const
+/*! \fn QJsonValueRef *QJsonObject::iterator::operator->()
Returns a pointer to a modifiable reference to the current item.
*/
-/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](int j)
+/*! \fn const QJsonValueConstRef *QJsonObject::iterator::operator->() const
+
+ Returns a pointer to a constant reference to the current item.
+*/
+
+/*! \fn const QJsonValueRef QJsonObject::iterator::operator[](qsizetype j) const
Returns a modifiable reference to the item at offset \a j from the
item pointed to by this iterator (the item at position \c{*this + j}).
@@ -1038,60 +977,60 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
/*!
- \fn bool QJsonObject::iterator::operator==(const iterator &other) const
- \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const
+ \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator==(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
/*!
- \fn bool QJsonObject::iterator::operator!=(const iterator &other) const
- \fn bool QJsonObject::iterator::operator!=(const const_iterator &other) const
+ \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator!=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonObject::iterator::operator<(const iterator& other) const
- \fn bool QJsonObject::iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator<(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator<=(const iterator& other) const
- \fn bool QJsonObject::iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator<=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator>(const iterator& other) const
- \fn bool QJsonObject::iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator>(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::iterator::operator>=(const iterator& other) const
- \fn bool QJsonObject::iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const iterator &rhs)
+ \fn bool QJsonObject::iterator::operator>=(const iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the
next item in the object and returns an iterator to the new current
item.
@@ -1104,14 +1043,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the
next item in the object and returns an iterator to the previously
current item.
*/
/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item
+ The prefix \c{--} operator, \c{--i}, makes the preceding item
current and returns an iterator pointing to the new current item.
Calling this function on QJsonObject::begin() leads to undefined
@@ -1124,12 +1063,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix -- operator, \c{i--}, makes the preceding item
+ The postfix \c{--} operator, \c{i--}, makes the preceding item
current and returns an iterator pointing to the previously
current item.
*/
-/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(int j) const
+/*! \fn QJsonObject::iterator QJsonObject::iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1138,7 +1077,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
-/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int j) const
+/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1146,7 +1085,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+()
*/
-/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j)
+/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1154,7 +1093,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j)
+/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1162,7 +1101,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+=(), operator-()
*/
-/*! \fn int QJsonObject::iterator::operator-(iterator other) const
+/*! \fn qsizetype QJsonObject::iterator::operator-(iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -1175,6 +1114,10 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\since 5.0
\brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject.
+ \compares strong
+ \compareswith strong QJsonObject::iterator
+ \endcompareswith
+
QJsonObject::const_iterator allows you to iterate over a QJsonObject.
If you want to modify the QJsonObject as you iterate
over it, you must use QJsonObject::iterator instead. It is generally
@@ -1191,7 +1134,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
Multiple iterators can be used on the same object. Existing iterators
will however become dangling if the object gets modified.
- \sa QJsonObject::iterator, {JSON Support in Qt}, {JSON Save Game Example}
+ \sa QJsonObject::iterator, {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*! \typedef QJsonObject::const_iterator::difference_type
@@ -1234,7 +1177,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa QJsonObject::constBegin(), QJsonObject::constEnd()
*/
-/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index)
+/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, qsizetype index)
\internal
*/
@@ -1250,14 +1193,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa value()
*/
-/*! \fn QJsonValue QJsonObject::const_iterator::value() const
+/*! \fn QJsonValueConstRef QJsonObject::const_iterator::value() const
Returns the current item's value.
\sa key(), operator*()
*/
-/*! \fn QJsonValue QJsonObject::const_iterator::operator*() const
+/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator*() const
Returns the current item's value.
@@ -1266,12 +1209,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa key()
*/
-/*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const
+/*! \fn const QJsonValueConstRef *QJsonObject::const_iterator::operator->() const
Returns a pointer to the current item.
*/
-/*! \fn const QJsonValue QJsonObject::const_iterator::operator[](int j)
+/*! \fn const QJsonValueConstRef QJsonObject::const_iterator::operator[](qsizetype j) const
Returns the item at offset \a j from the item pointed to by this iterator (the item at
position \c{*this + j}).
@@ -1283,55 +1226,53 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
*/
-/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const
- \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const
+/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to the same item as this
+ Returns \c true if \a lhs points to the same item as \a rhs
iterator; otherwise returns \c false.
\sa operator!=()
*/
-/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &other) const
- \fn bool QJsonObject::const_iterator::operator!=(const iterator &other) const
+/*! \fn bool QJsonObject::const_iterator::operator!=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if \a other points to a different item than this
+ Returns \c true if \a lhs points to a different item than \a rhs
iterator; otherwise returns \c false.
\sa operator==()
*/
/*!
- \fn bool QJsonObject::const_iterator::operator<(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator<(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator<=(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator<=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is less than
- or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is less than
+ or equal to the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator>(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator>(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than the item pointed to by the \a rhs iterator.
*/
/*!
- \fn bool QJsonObject::const_iterator::operator>=(const const_iterator& other) const
+ \fn bool QJsonObject::const_iterator::operator>=(const const_iterator &lhs, const const_iterator &rhs)
- Returns \c true if the item pointed to by this iterator is greater
- than or equal to the item pointed to by the \a other iterator.
+ Returns \c true if the item pointed to by \a lhs iterator is greater
+ than or equal to the item pointed to by the \a rhs iterator.
*/
/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++()
- The prefix ++ operator, \c{++i}, advances the iterator to the
+ The prefix \c{++} operator, \c{++i}, advances the iterator to the
next item in the object and returns an iterator to the new current
item.
@@ -1344,14 +1285,14 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix ++ operator, \c{i++}, advances the iterator to the
+ The postfix \c{++} operator, \c{i++}, advances the iterator to the
next item in the object and returns an iterator to the previously
current item.
*/
/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator--()
- The prefix -- operator, \c{--i}, makes the preceding item
+ The prefix \c{--} operator, \c{--i}, makes the preceding item
current and returns an iterator pointing to the new current item.
Calling this function on QJsonObject::begin() leads to undefined
@@ -1364,12 +1305,12 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\overload
- The postfix -- operator, \c{i--}, makes the preceding item
+ The postfix \c{--} operator, \c{i--}, makes the preceding item
current and returns an iterator pointing to the previously
current item.
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(int j) const
+/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator+(qsizetype j) const
Returns an iterator to the item at \a j positions forward from
this iterator. If \a j is negative, the iterator goes backward.
@@ -1379,7 +1320,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-()
*/
-/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int j) const
+/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(qsizetype j) const
Returns an iterator to the item at \a j positions backward from
this iterator. If \a j is negative, the iterator goes forward.
@@ -1389,7 +1330,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+()
*/
-/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j)
+/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(qsizetype j)
Advances the iterator by \a j items. If \a j is negative, the
iterator goes backward.
@@ -1399,7 +1340,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator-=(), operator+()
*/
-/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j)
+/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(qsizetype j)
Makes the iterator go back by \a j items. If \a j is negative,
the iterator goes forward.
@@ -1409,7 +1350,7 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
\sa operator+=(), operator-()
*/
-/*! \fn int QJsonObject::const_iterator::operator-(const_iterator other) const
+/*! \fn qsizetype QJsonObject::const_iterator::operator-(const_iterator other) const
Returns the number of items between the item pointed to by \a
other and the item pointed to by this iterator.
@@ -1419,48 +1360,30 @@ QJsonObject::const_iterator QJsonObject::constFindImpl(T key) const
/*!
\internal
*/
-void QJsonObject::detach(uint reserve)
-{
- Q_UNUSED(reserve)
- Q_ASSERT(!reserve);
- detach2(reserve);
-}
-
-bool QJsonObject::detach2(uint reserve)
+bool QJsonObject::detach(qsizetype reserve)
{
if (!o)
return true;
- o = QCborContainerPrivate::detach(o.data(), reserve ? reserve * 2 : o->elements.length());
+ o = QCborContainerPrivate::detach(o.data(), reserve ? reserve * 2 : o->elements.size());
return o;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
/*!
\internal
*/
-void QJsonObject::compact()
-{
- if (!o)
- return;
-
- detach2();
- o->compact(o->elements.length());
-}
-
-/*!
- \internal
- */
-QString QJsonObject::keyAt(int i) const
+QString QJsonObject::keyAt(qsizetype i) const
{
- Q_ASSERT(o && i >= 0 && i * 2 < o->elements.length());
+ Q_ASSERT(o && i >= 0 && i * 2 < o->elements.size());
return o->stringAt(i * 2);
}
/*!
\internal
*/
-QJsonValue QJsonObject::valueAt(int i) const
+QJsonValue QJsonObject::valueAt(qsizetype i) const
{
- if (!o || i < 0 || 2 * i + 1 >= o->elements.length())
+ if (!o || i < 0 || 2 * i + 1 >= o->elements.size())
return QJsonValue(QJsonValue::Undefined);
return QJsonPrivate::Value::fromTrustedCbor(o->valueAt(2 * i + 1));
}
@@ -1468,10 +1391,10 @@ QJsonValue QJsonObject::valueAt(int i) const
/*!
\internal
*/
-void QJsonObject::setValueAt(int i, const QJsonValue &val)
+void QJsonObject::setValueAt(qsizetype i, const QJsonValue &val)
{
- Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.length());
- detach2();
+ Q_ASSERT(o && i >= 0 && 2 * i + 1 < o->elements.size());
+ detach();
if (val.isUndefined()) {
o->removeAt(2 * i + 1);
o->removeAt(2 * i);
@@ -1479,15 +1402,16 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
o->replaceAt(2 * i + 1, QCborValue::fromJsonValue(val));
}
}
+#endif // Qt 7
/*!
\internal
*/
-void QJsonObject::removeAt(int index)
+void QJsonObject::removeAt(qsizetype index)
{
- detach2();
- o->removeAt(2 * index + 1);
- o->removeAt(2 * index);
+ detach();
+ o->removeAt(index + 1);
+ o->removeAt(index);
}
size_t qHash(const QJsonObject &object, size_t seed)
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index 4002a8bc24..4cdbf4511d 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONOBJECT_H
#define QJSONOBJECT_H
@@ -49,10 +13,6 @@
QT_BEGIN_NAMESPACE
class QDebug;
-template <class Key, class T> class QMap;
-typedef QMap<QString, QVariant> QVariantMap;
-template <class Key, class T> class QHash;
-typedef QHash<QString, QVariant> QVariantHash;
class QCborContainerPrivate;
@@ -61,12 +21,12 @@ class Q_CORE_EXPORT QJsonObject
public:
QJsonObject();
- QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args);
+ QJsonObject(std::initializer_list<std::pair<QString, QJsonValue> > args);
~QJsonObject();
- QJsonObject(const QJsonObject &other);
- QJsonObject &operator =(const QJsonObject &other);
+ QJsonObject(const QJsonObject &other) noexcept;
+ QJsonObject &operator =(const QJsonObject &other) noexcept;
QJsonObject(QJsonObject &&other) noexcept;
@@ -78,7 +38,7 @@ public:
void swap(QJsonObject &other) noexcept
{
- qSwap(o, other.o);
+ o.swap(other.o);
}
static QJsonObject fromVariantMap(const QVariantMap &map);
@@ -87,156 +47,243 @@ public:
QVariantHash toVariantHash() const;
QStringList keys() const;
- int size() const;
- inline int count() const { return size(); }
- inline int length() const { return size(); }
+ qsizetype size() const;
+ inline qsizetype count() const { return size(); }
+ inline qsizetype length() const { return size(); }
bool isEmpty() const;
-#if QT_STRINGVIEW_LEVEL < 2
QJsonValue value(const QString &key) const;
QJsonValue operator[] (const QString &key) const;
QJsonValueRef operator[] (const QString &key);
-#endif
QJsonValue value(QStringView key) const;
- QJsonValue value(QLatin1String key) const;
+ QJsonValue value(QLatin1StringView key) const;
QJsonValue operator[] (QStringView key) const { return value(key); }
- QJsonValue operator[] (QLatin1String key) const { return value(key); }
+ QJsonValue operator[] (QLatin1StringView key) const { return value(key); }
QJsonValueRef operator[] (QStringView key);
- QJsonValueRef operator[] (QLatin1String key);
+ QJsonValueRef operator[] (QLatin1StringView key);
-#if QT_STRINGVIEW_LEVEL < 2
void remove(const QString &key);
QJsonValue take(const QString &key);
bool contains(const QString &key) const;
-#endif
void remove(QStringView key);
- void remove(QLatin1String key);
+ void remove(QLatin1StringView key);
QJsonValue take(QStringView key);
- QJsonValue take(QLatin1String key);
+ QJsonValue take(QLatin1StringView key);
bool contains(QStringView key) const;
- bool contains(QLatin1String key) const;
+ bool contains(QLatin1StringView key) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonObject &other) const;
bool operator!=(const QJsonObject &other) const;
-
+#endif
class const_iterator;
class iterator
{
friend class const_iterator;
friend class QJsonObject;
- QJsonObject *o;
- int i;
+ QJsonValueRef item;
public:
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
- typedef QJsonValuePtr pointer;
-
- Q_DECL_CONSTEXPR inline iterator() : o(nullptr), i(0) {}
- Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
-
- inline QString key() const { return o->keyAt(i); }
- inline QJsonValueRef value() const { return QJsonValueRef(o, i); }
- inline QJsonValueRef operator*() const { return QJsonValueRef(o, i); }
-#ifdef Q_QDOC
- inline QJsonValueRef* operator->() const;
-#else
- inline QJsonValueRefPtr operator->() const { return QJsonValueRefPtr(o, i); }
+ typedef QJsonValueRef *pointer;
+
+ inline iterator() : item(static_cast<QJsonObject*>(nullptr), 0) { }
+ inline iterator(QJsonObject *obj, qsizetype index) : item(obj, index) { }
+
+ constexpr iterator(const iterator &other) = default;
+ iterator &operator=(const iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QString key() const { return item.objectKey(); }
+ inline QJsonValueRef value() const { return item; }
+ inline QJsonValueRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueRef *operator->() { return &item; }
+ inline QJsonValueRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const iterator &other) const { return !operator==(other); }
+ bool operator<(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const iterator& other) const { return !operator<=(other); }
+ bool operator>=(const iterator& other) const { return !operator<(other); }
#endif
- const QJsonValueRef operator[](int j) { return QJsonValueRef(o, i + j); }
-
- inline bool operator==(const iterator &other) const { return i == other.i; }
- inline bool operator!=(const iterator &other) const { return i != other.i; }
- bool operator<(const iterator& other) const { return i < other.i; }
- bool operator<=(const iterator& other) const { return i <= other.i; }
- bool operator>(const iterator& other) const { return i > other.i; }
- bool operator>=(const iterator& other) const { return i >= other.i; }
-
- inline iterator &operator++() { ++i; return *this; }
- inline iterator operator++(int) { iterator r = *this; ++i; return r; }
- inline iterator &operator--() { --i; return *this; }
- inline iterator operator--(int) { iterator r = *this; --i; return r; }
- inline iterator operator+(int j) const
- { iterator r = *this; r.i += j; return r; }
- inline iterator operator-(int j) const { return operator+(-j); }
- inline iterator &operator+=(int j) { i += j; return *this; }
- inline iterator &operator-=(int j) { i -= j; return *this; }
- int operator-(iterator j) const { return i - j.i; }
+ inline iterator &operator++() { ++item.index; return *this; }
+ inline iterator operator++(int) { iterator r = *this; ++item.index; return r; }
+ inline iterator &operator--() { --item.index; return *this; }
+ inline iterator operator--(int) { iterator r = *this; --item.index; return r; }
+ inline iterator operator+(qsizetype j) const { iterator r = *this; return r += j; }
+ inline iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ qsizetype operator-(iterator j) const { return item.index - j.item.index; }
public:
- inline bool operator==(const const_iterator &other) const { return i == other.i; }
- inline bool operator!=(const const_iterator &other) const { return i != other.i; }
- bool operator<(const const_iterator& other) const { return i < other.i; }
- bool operator<=(const const_iterator& other) const { return i <= other.i; }
- bool operator>(const const_iterator& other) const { return i > other.i; }
- bool operator>=(const const_iterator& other) const { return i >= other.i; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const const_iterator &other) const { return !operator==(other); }
+ bool operator<(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const const_iterator& other) const { return operator<=(other); }
+ bool operator>=(const const_iterator& other) const { return operator<(other); }
+#endif
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static bool comparesEqual_helper(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const iterator &lhs, const iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator)
+
+ friend bool comparesEqual(const iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(iterator, const_iterator)
};
friend class iterator;
class const_iterator
{
friend class iterator;
- const QJsonObject *o;
- int i;
+ QJsonValueConstRef item;
public:
typedef std::random_access_iterator_tag iterator_category;
- typedef int difference_type;
+ typedef qsizetype difference_type;
typedef QJsonValue value_type;
- typedef QJsonValue reference;
- typedef QJsonValuePtr pointer;
+ typedef const QJsonValueConstRef reference;
+ typedef const QJsonValueConstRef *pointer;
- Q_DECL_CONSTEXPR inline const_iterator() : o(nullptr), i(0) {}
- Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)
- : o(obj), i(index) {}
+ inline const_iterator() : item(static_cast<QJsonObject*>(nullptr), 0) { }
+ inline const_iterator(const QJsonObject *obj, qsizetype index)
+ : item(const_cast<QJsonObject*>(obj), index) { }
inline const_iterator(const iterator &other)
- : o(other.o), i(other.i) {}
-
- inline QString key() const { return o->keyAt(i); }
- inline QJsonValue value() const { return o->valueAt(i); }
- inline QJsonValue operator*() const { return o->valueAt(i); }
-#ifdef Q_QDOC
- inline QJsonValue* operator->() const;
-#else
- inline QJsonValuePtr operator->() const { return QJsonValuePtr(o->valueAt(i)); }
+ : item(other.item) { }
+
+ constexpr const_iterator(const const_iterator &other) = default;
+ const_iterator &operator=(const const_iterator &other)
+ {
+ item.rebind(other.item);
+ return *this;
+ }
+
+ inline QString key() const { return item.objectKey(); }
+ inline QJsonValueConstRef value() const { return item; }
+ inline const QJsonValueConstRef operator*() const { return item; }
+ inline const QJsonValueConstRef *operator->() const { return &item; }
+ inline QJsonValueConstRef operator[](qsizetype j) const { return *(*this + j); }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const const_iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const const_iterator &other) const { return !operator==(other); }
+ bool operator<(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const const_iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const const_iterator& other) const { return !operator<=(other); }
+ bool operator>=(const const_iterator& other) const { return !operator<(other); }
+#endif
+ inline const_iterator &operator++() { ++item.index; return *this; }
+ inline const_iterator operator++(int) { const_iterator r = *this; ++item.index; return r; }
+ inline const_iterator &operator--() { --item.index; return *this; }
+ inline const_iterator operator--(int) { const_iterator r = *this; --item.index; return r; }
+ inline const_iterator operator+(qsizetype j) const { const_iterator r = *this; return r += j; }
+ inline const_iterator operator-(qsizetype j) const { return operator+(-j); }
+ inline const_iterator &operator+=(qsizetype j) { item.index += quint64(j); return *this; }
+ inline const_iterator &operator-=(qsizetype j) { item.index -= quint64(j); return *this; }
+ qsizetype operator-(const_iterator j) const { return item.index - j.item.index; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const iterator &other) const
+ { return item.d == other.item.d && item.index == other.item.index; }
+ inline bool operator!=(const iterator &other) const { return !operator==(other); }
+ bool operator<(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index < other.item.index; }
+ bool operator<=(const iterator& other) const
+ { Q_ASSERT(item.d == other.item.d); return item.index <= other.item.index; }
+ bool operator>(const iterator& other) const { return !operator<=(other); }
+ bool operator>=(const iterator& other) const { return !operator<(other); }
#endif
- const QJsonValue operator[](int j) { return o->valueAt(i + j); }
-
- inline bool operator==(const const_iterator &other) const { return i == other.i; }
- inline bool operator!=(const const_iterator &other) const { return i != other.i; }
- bool operator<(const const_iterator& other) const { return i < other.i; }
- bool operator<=(const const_iterator& other) const { return i <= other.i; }
- bool operator>(const const_iterator& other) const { return i > other.i; }
- bool operator>=(const const_iterator& other) const { return i >= other.i; }
-
- inline const_iterator &operator++() { ++i; return *this; }
- inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; }
- inline const_iterator &operator--() { --i; return *this; }
- inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; }
- inline const_iterator operator+(int j) const
- { const_iterator r = *this; r.i += j; return r; }
- inline const_iterator operator-(int j) const { return operator+(-j); }
- inline const_iterator &operator+=(int j) { i += j; return *this; }
- inline const_iterator &operator-=(int j) { i -= j; return *this; }
- int operator-(const_iterator j) const { return i - j.i; }
-
- inline bool operator==(const iterator &other) const { return i == other.i; }
- inline bool operator!=(const iterator &other) const { return i != other.i; }
- bool operator<(const iterator& other) const { return i < other.i; }
- bool operator<=(const iterator& other) const { return i <= other.i; }
- bool operator>(const iterator& other) const { return i > other.i; }
- bool operator>=(const iterator& other) const { return i >= other.i; }
+
+ private:
+ // Helper functions
+ static bool comparesEqual_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return lhs.item.d == rhs.item.d && lhs.item.index == rhs.item.index;
+ }
+ static Qt::strong_ordering compareThreeWay_helper(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ Q_ASSERT(lhs.item.d == rhs.item.d);
+ return Qt::compareThreeWay(lhs.item.index, rhs.item.index);
+ }
+
+ // Compare friends
+ friend bool comparesEqual(const const_iterator &lhs, const const_iterator &rhs) noexcept
+ {
+ return comparesEqual_helper(lhs, rhs);
+ }
+ friend Qt::strong_ordering compareThreeWay(const const_iterator &lhs,
+ const const_iterator &rhs) noexcept
+ {
+ return compareThreeWay_helper(lhs, rhs);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(const_iterator)
};
friend class const_iterator;
// STL style
- inline iterator begin() { detach2(); return iterator(this, 0); }
+ inline iterator begin() { detach(); return iterator(this, 0); }
inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator constBegin() const { return const_iterator(this, 0); }
- inline iterator end() { detach2(); return iterator(this, size()); }
+ inline iterator end() { detach(); return iterator(this, size()); }
inline const_iterator end() const { return const_iterator(this, size()); }
inline const_iterator constEnd() const { return const_iterator(this, size()); }
iterator erase(iterator it);
@@ -244,41 +291,52 @@ public:
// more Qt
typedef iterator Iterator;
typedef const_iterator ConstIterator;
-#if QT_STRINGVIEW_LEVEL < 2
iterator find(const QString &key);
const_iterator find(const QString &key) const { return constFind(key); }
const_iterator constFind(const QString &key) const;
iterator insert(const QString &key, const QJsonValue &value);
-#endif
iterator find(QStringView key);
- iterator find(QLatin1String key);
+ iterator find(QLatin1StringView key);
const_iterator find(QStringView key) const { return constFind(key); }
- const_iterator find(QLatin1String key) const { return constFind(key); }
+ const_iterator find(QLatin1StringView key) const { return constFind(key); }
const_iterator constFind(QStringView key) const;
- const_iterator constFind(QLatin1String key) const;
+ const_iterator constFind(QLatin1StringView key) const;
iterator insert(QStringView key, const QJsonValue &value);
- iterator insert(QLatin1String key, const QJsonValue &value);
+ iterator insert(QLatin1StringView key, const QJsonValue &value);
// STL compatibility
typedef QJsonValue mapped_type;
typedef QString key_type;
- typedef int size_type;
+ typedef qsizetype size_type;
inline bool empty() const { return isEmpty(); }
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonObject &lhs,
+ const QJsonObject &rhs) noexcept;
+ friend bool comparesEqual(const QJsonObject &lhs,
+ const QJsonValue &rhs) noexcept
+ {
+ return comparesEqual(lhs, rhs.toObject());
+ }
+ friend bool comparesEqual(const QJsonObject &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(lhs, rhs.toObject());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject, QJsonValue)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject, QJsonValueConstRef)
friend class QJsonValue;
friend class QJsonDocument;
+ friend class QJsonPrivate::Value;
+ friend class QJsonValueConstRef;
friend class QJsonValueRef;
friend class QCborMap;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
QJsonObject(QCborContainerPrivate *object);
- void initialize();
- // ### Qt 6: remove me and merge with detach2
- void detach(uint reserve = 0);
- bool detach2(uint reserve = 0);
- void compact();
+ bool detach(qsizetype reserve = 0);
template <typename T> QJsonValue valueImpl(T key) const;
template <typename T> QJsonValueRef atImpl(T key);
@@ -289,19 +347,25 @@ private:
template <typename T> const_iterator constFindImpl(T key) const;
template <typename T> iterator insertImpl(T key, const QJsonValue &value);
- QString keyAt(int i) const;
- QJsonValue valueAt(int i) const;
- void setValueAt(int i, const QJsonValue &val);
- void removeAt(int i);
- template <typename T> iterator insertAt(int i, T key, const QJsonValue &val, bool exists);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QString keyAt(qsizetype i) const;
+ QJsonValue valueAt(qsizetype i) const;
+ void setValueAt(qsizetype i, const QJsonValue &val);
+#endif
+ void removeAt(qsizetype i);
+ template <typename T> iterator insertAt(qsizetype i, T key, const QJsonValue &val, bool exists);
- // ### Qt 6: remove
- void *dead = nullptr;
QExplicitlySharedDataPointer<QCborContainerPrivate> o;
};
Q_DECLARE_SHARED(QJsonObject)
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
+inline QJsonValueConstRef::QJsonValueConstRef(QJsonObject *o, qsizetype idx)
+ : d(o ? o->o.data() : nullptr), is_object(true), index(idx)
+{}
+#endif
+
Q_CORE_EXPORT size_t qHash(const QJsonObject &object, size_t seed = 0);
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 116e7f6995..ba4887225d 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
@@ -47,23 +11,30 @@
#include "private/qstringconverter_p.h"
#include "private/qcborvalue_p.h"
#include "private/qnumeric_p.h"
+#include <private/qtools_p.h>
//#define PARSER_DEBUG
#ifdef PARSER_DEBUG
-static int indent = 0;
-#define BEGIN qDebug() << QByteArray(4*indent++, ' ').constData() << "pos=" << current
-#define END --indent
-#define DEBUG qDebug() << QByteArray(4*indent, ' ').constData()
+# error currently broken after `current` was moved to StashedContainer
+Q_CONSTINIT static int indent = 0;
+# define QT_PARSER_TRACING_BEGIN \
+ qDebug() << QByteArray(4 * indent++, ' ').constData() << "pos=" << current
+# define QT_PARSER_TRACING_END --indent
+# define QT_PARSER_TRACING_DEBUG qDebug() << QByteArray(4 * indent, ' ').constData()
#else
-#define BEGIN if (1) ; else qDebug()
-#define END do {} while (0)
-#define DEBUG if (1) ; else qDebug()
+# define QT_PARSER_TRACING_BEGIN QT_NO_QDEBUG_MACRO()
+# define QT_PARSER_TRACING_END \
+ do { \
+ } while (0)
+# define QT_PARSER_TRACING_DEBUG QT_NO_QDEBUG_MACRO()
#endif
static const int nestingLimit = 1024;
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
// error strings for the JSON parser
#define JSONERR_OK QT_TRANSLATE_NOOP("QJsonParseError", "no error occurred")
#define JSONERR_UNTERM_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "unterminated object")
@@ -86,12 +57,13 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonParseError class is used to report errors during JSON parsing.
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -193,7 +165,7 @@ QString QJsonParseError::errorString() const
#ifndef QT_BOOTSTRAPPED
return QCoreApplication::translate("QJsonParseError", sz);
#else
- return QLatin1String(sz);
+ return QLatin1StringView(sz);
#endif
}
@@ -333,7 +305,7 @@ QCborValue Parser::parse(QJsonParseError *error)
QCborValue data;
- DEBUG << Qt::hex << (uint)token;
+ QT_PARSER_TRACING_DEBUG << Qt::hex << (uint)token;
if (token == BeginArray) {
container = new QCborContainerPrivate;
if (!parseArray())
@@ -357,7 +329,7 @@ QCborValue Parser::parse(QJsonParseError *error)
goto error;
}
- END;
+ QT_PARSER_TRACING_END;
{
if (error) {
error->offset = 0;
@@ -379,12 +351,42 @@ error:
return QCborValue();
}
+// We need to retain the _last_ value for any duplicate keys and we need to deref containers.
+// Therefore the manual implementation of std::unique().
+template<typename Iterator, typename Compare, typename Assign>
+static Iterator customAssigningUniqueLast(Iterator first, Iterator last,
+ Compare compare, Assign assign)
+{
+ first = std::adjacent_find(first, last, compare);
+ if (first == last)
+ return last;
+
+ // After adjacent_find, we know that *first and *(first+1) compare equal,
+ // and that first+1 != last.
+ Iterator result = first++;
+ Q_ASSERT(compare(*result, *first));
+ assign(*result, *first);
+ Q_ASSERT(first != last);
+
+ while (++first != last) {
+ if (!compare(*result, *first))
+ ++result;
+ // Due to adjacent_find above, we know that we've at least eliminated one element.
+ // Therefore we have to move each further element across the gap.
+ Q_ASSERT(result != first);
+
+ // We have to overwrite each element we want to eliminate, to deref() the container.
+ // Therefore we don't try to optimize the number of assignments here.
+ assign(*result, *first);
+ }
+
+ return ++result;
+}
static void sortContainer(QCborContainerPrivate *container)
{
using Forward = QJsonPrivate::KeyIterator;
- using Reverse = std::reverse_iterator<Forward>;
using Value = Forward::value_type;
auto compare = [container](const Value &a, const Value &b)
@@ -403,52 +405,47 @@ static void sortContainer(QCborContainerPrivate *container)
if (!bData)
return 1;
- // If StringIsAscii is set, we can use either the UTF-8 or the latin1 comparison
- // for the string as ASCII is a subset of both. If nothing is set, that means UTF-8.
-
- // We are currently missing an efficient comparison between UTF-8 and UTF-16 strings.
- // Therefore, we need to convert the UTF-8 string if we encounter such a case.
-
- if (aKey.flags & QtCbor::Element::StringIsAscii) {
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QtPrivate::compareStrings(aData->asLatin1(), bData->asLatin1());
- if (bKey.flags & QtCbor::Element::StringIsUtf16)
- return QtPrivate::compareStrings(aData->asLatin1(), bData->asStringView());
-
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
- }
+ // US-ASCII (StringIsAscii flag) is just a special case of UTF-8
+ // string, so we can safely ignore the flag.
if (aKey.flags & QtCbor::Element::StringIsUtf16) {
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QtPrivate::compareStrings(aData->asStringView(), bData->asLatin1());
if (bKey.flags & QtCbor::Element::StringIsUtf16)
return QtPrivate::compareStrings(aData->asStringView(), bData->asStringView());
- // Nasty case. a is UTF-16 and b is UTF-8
- return QtPrivate::compareStrings(aData->asStringView(), bData->toUtf8String());
+ return -QCborContainerPrivate::compareUtf8(bData, aData->asStringView());
+ } else {
+ if (bKey.flags & QtCbor::Element::StringIsUtf16)
+ return QCborContainerPrivate::compareUtf8(aData, bData->asStringView());
+
+ return QtPrivate::compareStrings(aData->asUtf8StringView(), bData->asUtf8StringView());
}
+ };
- if (bKey.flags & QtCbor::Element::StringIsAscii)
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
+ // The elements' containers are owned by the outer container, not by the elements themselves.
+ auto move = [](Forward::reference target, Forward::reference source)
+ {
+ QtCbor::Element &targetValue = target.value();
+
+ // If the target has a container, deref it before overwriting, so that we don't leak.
+ if (targetValue.flags & QtCbor::Element::IsContainer)
+ targetValue.container->deref();
- // Nasty case. a is UTF-8 and b is UTF-16
- if (bKey.flags & QtCbor::Element::StringIsUtf16)
- return QtPrivate::compareStrings(aData->toUtf8String(), bData->asStringView());
+ // Do not move, so that we can clear the value afterwards.
+ target = source;
- return QCborContainerPrivate::compareUtf8(aData, bData->asLatin1());
+ // Clear the source value, so that we don't store the same container twice.
+ source.value() = QtCbor::Element();
};
- std::sort(Forward(container->elements.begin()), Forward(container->elements.end()),
- [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
+ std::stable_sort(
+ Forward(container->elements.begin()), Forward(container->elements.end()),
+ [&compare](const Value &a, const Value &b) { return compare(a, b) < 0; });
- // We need to retain the _last_ value for any duplicate keys. Therefore the reverse dance here.
- auto it = std::unique(Reverse(container->elements.end()), Reverse(container->elements.begin()),
- [&compare](const Value &a, const Value &b) {
- return compare(a, b) == 0;
- }).base().elementsIterator();
+ Forward result = customAssigningUniqueLast(
+ Forward(container->elements.begin()), Forward(container->elements.end()),
+ [&compare](const Value &a, const Value &b) { return compare(a, b) == 0; }, move);
- // The erase from beginning is expensive but hopefully rare.
- container->elements.erase(container->elements.begin(), it);
+ container->elements.erase(result.elementsIterator(), container->elements.end());
}
@@ -464,7 +461,7 @@ bool Parser::parseObject()
return false;
}
- BEGIN << "parseObject" << json;
+ QT_PARSER_TRACING_BEGIN << "parseObject" << json;
char token = nextToken();
while (token == Quote) {
@@ -482,13 +479,13 @@ bool Parser::parseObject()
}
}
- DEBUG << "end token=" << token;
+ QT_PARSER_TRACING_DEBUG << "end token=" << token;
if (token != EndObject) {
lastError = QJsonParseError::UnterminatedObject;
return false;
}
- END;
+ QT_PARSER_TRACING_END;
--nestingLevel;
@@ -502,7 +499,7 @@ bool Parser::parseObject()
*/
bool Parser::parseMember()
{
- BEGIN << "parseMember";
+ QT_PARSER_TRACING_BEGIN << "parseMember";
if (!parseString())
return false;
@@ -518,7 +515,7 @@ bool Parser::parseMember()
if (!parseValue())
return false;
- END;
+ QT_PARSER_TRACING_END;
return true;
}
@@ -527,7 +524,7 @@ bool Parser::parseMember()
*/
bool Parser::parseArray()
{
- BEGIN << "parseArray";
+ QT_PARSER_TRACING_BEGIN << "parseArray";
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
@@ -563,8 +560,8 @@ bool Parser::parseArray()
}
}
- DEBUG << "size =" << (container ? container->elements.length() : 0);
- END;
+ QT_PARSER_TRACING_DEBUG << "size =" << (container ? container->elements.size() : 0);
+ QT_PARSER_TRACING_END;
--nestingLevel;
@@ -578,7 +575,7 @@ value = false / null / true / object / array / number / string
bool Parser::parseValue()
{
- BEGIN << "parse Value" << json;
+ QT_PARSER_TRACING_BEGIN << "parse Value" << json;
switch (*json++) {
case 'n':
@@ -590,8 +587,8 @@ bool Parser::parseValue()
*json++ == 'l' &&
*json++ == 'l') {
container->append(QCborValue(QCborValue::Null));
- DEBUG << "value: null";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: null";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -605,8 +602,8 @@ bool Parser::parseValue()
*json++ == 'u' &&
*json++ == 'e') {
container->append(QCborValue(true));
- DEBUG << "value: true";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: true";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -621,8 +618,8 @@ bool Parser::parseValue()
*json++ == 's' &&
*json++ == 'e') {
container->append(QCborValue(false));
- DEBUG << "value: false";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: false";
+ QT_PARSER_TRACING_END;
return true;
}
lastError = QJsonParseError::IllegalValue;
@@ -630,24 +627,24 @@ bool Parser::parseValue()
case Quote: {
if (!parseString())
return false;
- DEBUG << "value: string";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: string";
+ QT_PARSER_TRACING_END;
return true;
}
case BeginArray: {
StashedContainer stashedContainer(&container, QCborValue::Array);
if (!parseArray())
return false;
- DEBUG << "value: array";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: array";
+ QT_PARSER_TRACING_END;
return true;
}
case BeginObject: {
StashedContainer stashedContainer(&container, QCborValue::Map);
if (!parseObject())
return false;
- DEBUG << "value: object";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: object";
+ QT_PARSER_TRACING_END;
return true;
}
case ValueSeparator:
@@ -663,8 +660,8 @@ bool Parser::parseValue()
--json;
if (!parseNumber())
return false;
- DEBUG << "value: number";
- END;
+ QT_PARSER_TRACING_DEBUG << "value: number";
+ QT_PARSER_TRACING_END;
}
return true;
@@ -690,7 +687,7 @@ bool Parser::parseValue()
bool Parser::parseNumber()
{
- BEGIN << "parseNumber" << json;
+ QT_PARSER_TRACING_BEGIN << "parseNumber" << json;
const char *start = json;
bool isInt = true;
@@ -703,14 +700,14 @@ bool Parser::parseNumber()
if (json < end && *json == '0') {
++json;
} else {
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && isAsciiDigit(*json))
++json;
}
// frac = decimal-point 1*DIGIT
if (json < end && *json == '.') {
++json;
- while (json < end && *json >= '0' && *json <= '9') {
+ while (json < end && isAsciiDigit(*json)) {
isInt = isInt && *json == '0';
++json;
}
@@ -722,7 +719,7 @@ bool Parser::parseNumber()
++json;
if (json < end && (*json == '-' || *json == '+'))
++json;
- while (json < end && *json >= '0' && *json <= '9')
+ while (json < end && isAsciiDigit(*json))
++json;
}
@@ -732,14 +729,14 @@ bool Parser::parseNumber()
}
const QByteArray number = QByteArray::fromRawData(start, json - start);
- DEBUG << "numberstring" << number;
+ QT_PARSER_TRACING_DEBUG << "numberstring" << number;
if (isInt) {
bool ok;
qlonglong n = number.toLongLong(&ok);
if (ok) {
container->append(QCborValue(n));
- END;
+ QT_PARSER_TRACING_END;
return true;
}
}
@@ -758,7 +755,7 @@ bool Parser::parseNumber()
else
container->append(QCborValue(d));
- END;
+ QT_PARSER_TRACING_END;
return true;
}
@@ -784,28 +781,26 @@ bool Parser::parseNumber()
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
*/
-static inline bool addHexDigit(char digit, uint *result)
+static inline bool addHexDigit(char digit, char32_t *result)
{
*result <<= 4;
- if (digit >= '0' && digit <= '9')
- *result |= (digit - '0');
- else if (digit >= 'a' && digit <= 'f')
- *result |= (digit - 'a') + 10;
- else if (digit >= 'A' && digit <= 'F')
- *result |= (digit - 'A') + 10;
- else
- return false;
- return true;
+ const int h = fromHex(digit);
+ if (h != -1) {
+ *result |= h;
+ return true;
+ }
+
+ return false;
}
-static inline bool scanEscapeSequence(const char *&json, const char *end, uint *ch)
+static inline bool scanEscapeSequence(const char *&json, const char *end, char32_t *ch)
{
++json;
if (json >= end)
return false;
- DEBUG << "scan escape" << (char)*json;
- uint escaped = *json++;
+ QT_PARSER_TRACING_DEBUG << "scan escape" << (char)*json;
+ uchar escaped = *json++;
switch (escaped) {
case '"':
*ch = '"'; break;
@@ -843,12 +838,12 @@ static inline bool scanEscapeSequence(const char *&json, const char *end, uint *
return true;
}
-static inline bool scanUtf8Char(const char *&json, const char *end, uint *result)
+static inline bool scanUtf8Char(const char *&json, const char *end, char32_t *result)
{
const auto *usrc = reinterpret_cast<const uchar *>(json);
const auto *uend = reinterpret_cast<const uchar *>(end);
const uchar b = *usrc++;
- int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend);
+ qsizetype res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, usrc, uend);
if (res < 0)
return false;
@@ -862,11 +857,11 @@ bool Parser::parseString()
// try to parse a utf-8 string without escape sequences, and note whether it's 7bit ASCII.
- BEGIN << "parse string" << json;
+ QT_PARSER_TRACING_BEGIN << "parse string" << json;
bool isUtf8 = true;
bool isAscii = true;
while (json < end) {
- uint ch = 0;
+ char32_t ch = 0;
if (*json == '"')
break;
if (*json == '\\') {
@@ -883,10 +878,10 @@ bool Parser::parseString()
}
if (ch > 0x7f)
isAscii = false;
- DEBUG << " " << ch << char(ch);
+ QT_PARSER_TRACING_DEBUG << " " << ch << char(ch);
}
++json;
- DEBUG << "end of string";
+ QT_PARSER_TRACING_DEBUG << "end of string";
if (json >= end) {
lastError = QJsonParseError::UnterminatedString;
return false;
@@ -898,17 +893,17 @@ bool Parser::parseString()
container->appendAsciiString(start, json - start - 1);
else
container->appendUtf8String(start, json - start - 1);
- END;
+ QT_PARSER_TRACING_END;
return true;
}
- DEBUG << "has escape sequences";
+ QT_PARSER_TRACING_DEBUG << "has escape sequences";
json = start;
QString ucs4;
while (json < end) {
- uint ch = 0;
+ char32_t ch = 0;
if (*json == '"')
break;
else if (*json == '\\') {
@@ -931,10 +926,14 @@ bool Parser::parseString()
return false;
}
- container->appendByteData(reinterpret_cast<const char *>(ucs4.utf16()), ucs4.size() * 2,
+ container->appendByteData(reinterpret_cast<const char *>(ucs4.constData()), ucs4.size() * 2,
QCborValue::String, QtCbor::Element::StringIsUtf16);
- END;
+ QT_PARSER_TRACING_END;
return true;
}
QT_END_NAMESPACE
+
+#undef QT_PARSER_TRACING_BEGIN
+#undef QT_PARSER_TRACING_END
+#undef QT_PARSER_TRACING_DEBUG
diff --git a/src/corelib/serialization/qjsonparser_p.h b/src/corelib/serialization/qjsonparser_p.h
index 14d9705447..47830a108e 100644
--- a/src/corelib/serialization/qjsonparser_p.h
+++ b/src/corelib/serialization/qjsonparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONPARSER_P_H
#define QJSONPARSER_P_H
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 34fa84cdc1..6c2656d89f 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2022 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qjsonobject.h>
#include <qjsonvalue.h>
@@ -45,6 +10,8 @@
#include <quuid.h>
#include <qvariant.h>
#include <qstringlist.h>
+#include <qmap.h>
+#include <qhash.h>
#include <qdebug.h>
#include "qdatastream.h"
@@ -58,16 +25,44 @@
QT_BEGIN_NAMESPACE
+static QJsonValue::Type convertFromCborType(QCborValue::Type type) noexcept
+{
+ switch (type) {
+ case QCborValue::Null:
+ return QJsonValue::Null;
+ case QCborValue::True:
+ case QCborValue::False:
+ return QJsonValue::Bool;
+ case QCborValue::Double:
+ case QCborValue::Integer:
+ return QJsonValue::Double;
+ case QCborValue::String:
+ return QJsonValue::String;
+ case QCborValue::Array:
+ return QJsonValue::Array;
+ case QCborValue::Map:
+ return QJsonValue::Object;
+ case QCborValue::Undefined:
+ default:
+ return QJsonValue::Undefined;
+ }
+}
+
/*!
\class QJsonValue
\inmodule QtCore
\ingroup json
\ingroup shared
+ \ingroup qtserialization
\reentrant
\since 5.0
\brief The QJsonValue class encapsulates a value in JSON.
+ \compares equality
+ \compareswith equality QJsonValueConstRef QJsonValueRef
+ \endcompareswith
+
A value in JSON can be one of 6 basic types:
JSON is a format to store structured data. It has 6 basic data types:
@@ -101,11 +96,11 @@ QT_BEGIN_NAMESPACE
The following methods return QJsonValueRef:
\list
- \li \l {QJsonArray}::operator[](int i)
+ \li \l {QJsonArray}::operator[](qsizetype i)
\li \l {QJsonObject}::operator[](const QString & key) const
\endlist
- \sa {JSON Support in Qt}, {JSON Save Game Example}
+ \sa {JSON Support in Qt}, {Saving and Loading a Game}
*/
/*!
@@ -114,26 +109,25 @@ QT_BEGIN_NAMESPACE
The default is to create a Null value.
*/
QJsonValue::QJsonValue(Type type)
- : d(nullptr), t(QCborValue::Undefined)
{
switch (type) {
case Null:
- t = QCborValue::Null;
+ value = QCborValue::Null;
break;
case Bool:
- t = QCborValue::False;
+ value = QCborValue::False;
break;
case Double:
- t = QCborValue::Double;
+ value = QCborValue::Double;
break;
case String:
- t = QCborValue::String;
+ value = QCborValue::String;
break;
case Array:
- t = QCborValue::Array;
+ value = QCborValue::Array;
break;
case Object:
- t = QCborValue::Map;
+ value = QCborValue::Map;
break;
case Undefined:
break;
@@ -144,24 +138,27 @@ QJsonValue::QJsonValue(Type type)
Creates a value of type Bool, with value \a b.
*/
QJsonValue::QJsonValue(bool b)
- : t(b ? QCborValue::True : QCborValue::False)
+ : value(b)
{
}
+static inline QCborValue doubleValueHelper(double v)
+{
+ qint64 n = 0;
+ // Convert to integer if the number is an integer and changing wouldn't
+ // introduce additional digit precision not present in the double.
+ if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */))
+ return n;
+ else
+ return v;
+}
+
/*!
Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(double v)
- : d(nullptr)
+ : value(doubleValueHelper(v))
{
- // Convert to integer if the number is an integer and changing wouldn't
- // introduce additional digit precision not present in the double.
- if (convertDoubleTo<qint64>(v, &n, false /* allow_precision_upgrade */)) {
- t = QCborValue::Integer;
- } else {
- memcpy(&n, &v, sizeof(n));
- t = QCborValue::Double;
- }
}
/*!
@@ -169,7 +166,7 @@ QJsonValue::QJsonValue(double v)
Creates a value of type Double, with value \a v.
*/
QJsonValue::QJsonValue(int v)
- : n(v), t(QCborValue::Integer)
+ : value(v)
{
}
@@ -180,7 +177,7 @@ QJsonValue::QJsonValue(int v)
If you pass in values outside this range expect a loss of precision to occur.
*/
QJsonValue::QJsonValue(qint64 v)
- : n(v), t(QCborValue::Integer)
+ : value(v)
{
}
@@ -188,7 +185,7 @@ QJsonValue::QJsonValue(qint64 v)
Creates a value of type String, with value \a s.
*/
QJsonValue::QJsonValue(const QString &s)
- : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(s))
+ : value(s)
{
}
@@ -204,25 +201,28 @@ QJsonValue::QJsonValue(const QString &s)
\since 5.3
*/
-// ### Qt6: remove
-void QJsonValue::stringDataFromQStringHelper(const QString &string)
+/*!
+ Creates a value of type String, with the Latin-1 string viewed by \a s.
+ */
+QJsonValue::QJsonValue(QLatin1StringView s)
+ : value(s)
{
- *this = QJsonValue(string);
}
/*!
- Creates a value of type String, with value \a s.
+ Creates a value of type Array, with value \a a.
*/
-QJsonValue::QJsonValue(QLatin1String s)
- : QJsonValue(QJsonPrivate::Value::fromTrustedCbor(s))
+QJsonValue::QJsonValue(const QJsonArray &a)
+ : value(QCborArray::fromJsonArray(a))
{
}
/*!
- Creates a value of type Array, with value \a a.
+ \overload
+ \since 6.3
*/
-QJsonValue::QJsonValue(const QJsonArray &a)
- : n(-1), d(a.a), t(QCborValue::Array)
+QJsonValue::QJsonValue(QJsonArray &&a) noexcept
+ : value(QCborArray::fromJsonArray(std::move(a)))
{
}
@@ -230,7 +230,16 @@ QJsonValue::QJsonValue(const QJsonArray &a)
Creates a value of type Object, with value \a o.
*/
QJsonValue::QJsonValue(const QJsonObject &o)
- : n(-1), d(o.o), t(QCborValue::Map)
+ : value(QCborMap::fromJsonObject(o))
+{
+}
+
+/*!
+ \overload
+ \since 6.3
+ */
+QJsonValue::QJsonValue(QJsonObject &&o) noexcept
+ : value(QCborMap::fromJsonObject(std::move(o)))
{
}
@@ -243,38 +252,27 @@ QJsonValue::~QJsonValue() = default;
/*!
Creates a copy of \a other.
*/
-QJsonValue::QJsonValue(const QJsonValue &other)
-{
- n = other.n;
- t = other.t;
- d = other.d;
-}
+QJsonValue::QJsonValue(const QJsonValue &other) noexcept = default;
/*!
Assigns the value stored in \a other to this object.
*/
-QJsonValue &QJsonValue::operator =(const QJsonValue &other)
+QJsonValue &QJsonValue::operator =(const QJsonValue &other) noexcept
{
QJsonValue copy(other);
swap(copy);
return *this;
}
-QJsonValue::QJsonValue(QJsonValue &&other) noexcept :
- n(other.n),
- d(other.d),
- t(other.t)
+QJsonValue::QJsonValue(QJsonValue &&other) noexcept
+ : value(std::move(other.value))
{
- other.n = 0;
- other.d = nullptr;
- other.t = QCborValue::Null;
+ other.value = QCborValue(nullptr);
}
void QJsonValue::swap(QJsonValue &other) noexcept
{
- qSwap(n, other.n);
- qSwap(d, other.d);
- qSwap(t, other.t);
+ value.swap(other.value);
}
/*!
@@ -351,7 +349,7 @@ void QJsonValue::swap(QJsonValue &other) noexcept
error cases as e.g. accessing a non existing key in a QJsonObject.
*/
-
+#ifndef QT_NO_VARIANT
/*!
Converts \a variant to a QJsonValue and returns it.
@@ -461,7 +459,11 @@ void QJsonValue::swap(QJsonValue &other) noexcept
For other types not listed above, a conversion to string will be attempted,
usually but not always by calling QVariant::toString(). If the conversion
fails the value is replaced by a null JSON value. Note that
- QVariant::toString() is also lossy for the majority of types.
+ QVariant::toString() is also lossy for the majority of types. For example,
+ if the passed QVariant is representing raw byte array data, it is recommended
+ to pre-encode it to \l {RFC 4686}{Base64} (or
+ another lossless encoding), otherwise a lossy conversion using QString::fromUtf8()
+ will be used.
Please note that the conversions via QVariant::toString() are subject to
change at any time. Both QVariant and QJsonValue may be extended in the
@@ -472,7 +474,7 @@ void QJsonValue::swap(QJsonValue &other) noexcept
*/
QJsonValue QJsonValue::fromVariant(const QVariant &variant)
{
- switch (variant.userType()) {
+ switch (variant.metaType().id()) {
case QMetaType::Nullptr:
return QJsonValue(Null);
case QMetaType::Bool:
@@ -488,8 +490,10 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
return QJsonValue(variant.toLongLong());
Q_FALLTHROUGH();
case QMetaType::Float:
- case QMetaType::Double:
- return QJsonValue(variant.toDouble());
+ case QMetaType::Double: {
+ double v = variant.toDouble();
+ return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
+ }
case QMetaType::QString:
return QJsonValue(variant.toString());
case QMetaType::QStringList:
@@ -548,7 +552,7 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
*/
QVariant QJsonValue::toVariant() const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::True:
return true;
case QCborValue::False:
@@ -560,13 +564,9 @@ QVariant QJsonValue::toVariant() const
case QCborValue::String:
return toString();
case QCborValue::Array:
- return d ?
- QJsonArray(d.data()).toVariantList() :
- QVariantList();
+ return toArray().toVariantList();
case QCborValue::Map:
- return d ?
- QJsonObject(d.data()).toVariantMap() :
- QVariantMap();
+ return toObject().toVariantMap();
case QCborValue::Null:
return QVariant::fromValue(nullptr);
case QCborValue::Undefined:
@@ -592,6 +592,7 @@ QVariant QJsonValue::toVariant() const
error condition, when trying to read an out of bounds value
in an array or a non existent key in an object.
*/
+#endif // !QT_NO_VARIANT
/*!
Returns the type of the value.
@@ -600,25 +601,7 @@ QVariant QJsonValue::toVariant() const
*/
QJsonValue::Type QJsonValue::type() const
{
- switch (t) {
- case QCborValue::Null:
- return QJsonValue::Null;
- case QCborValue::True:
- case QCborValue::False:
- return QJsonValue::Bool;
- case QCborValue::Double:
- case QCborValue::Integer:
- return QJsonValue::Double;
- case QCborValue::String:
- return QJsonValue::String;
- case QCborValue::Array:
- return QJsonValue::Array;
- case QCborValue::Map:
- return QJsonValue::Object;
- case QCborValue::Undefined:
- default:
- return QJsonValue::Undefined;
- }
+ return convertFromCborType(value.type());
}
/*!
@@ -628,7 +611,7 @@ QJsonValue::Type QJsonValue::type() const
*/
bool QJsonValue::toBool(bool defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::True:
return true;
case QCborValue::False:
@@ -647,17 +630,19 @@ bool QJsonValue::toBool(bool defaultValue) const
*/
int QJsonValue::toInt(int defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::Double: {
int dblInt;
if (convertDoubleTo<int>(toDouble(), &dblInt))
return dblInt;
break;
}
- case QCborValue::Integer:
+ case QCborValue::Integer: {
+ const auto n = value.toInteger();
if (qint64(int(n)) == n)
return int(n);
break;
+ }
default:
break;
}
@@ -673,9 +658,9 @@ int QJsonValue::toInt(int defaultValue) const
*/
qint64 QJsonValue::toInteger(qint64 defaultValue) const
{
- switch (t) {
+ switch (value.type()) {
case QCborValue::Integer:
- return n;
+ return value.toInteger();
case QCborValue::Double: {
qint64 dblInt;
if (convertDoubleTo<qint64>(toDouble(), &dblInt))
@@ -695,17 +680,7 @@ qint64 QJsonValue::toInteger(qint64 defaultValue) const
*/
double QJsonValue::toDouble(double defaultValue) const
{
- switch (t) {
- case QCborValue::Double: {
- double d;
- memcpy(&d, &n, sizeof(d));
- return d;
- }
- case QCborValue::Integer:
- return double(n);
- default:
- return defaultValue;
- }
+ return value.toDouble(defaultValue);
}
/*!
@@ -715,7 +690,7 @@ double QJsonValue::toDouble(double defaultValue) const
*/
QString QJsonValue::toString(const QString &defaultValue) const
{
- return (t == QCborValue::String && d) ? d->stringAt(n) : defaultValue;
+ return value.toString(defaultValue);
}
/*!
@@ -727,7 +702,7 @@ QString QJsonValue::toString(const QString &defaultValue) const
*/
QString QJsonValue::toString() const
{
- return (t == QCborValue::String && d) ? d->stringAt(n) : QString();
+ return value.toString();
}
/*!
@@ -737,10 +712,15 @@ QString QJsonValue::toString() const
*/
QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const
{
- if (t != QCborValue::Array || n >= 0 || !d)
+ if (!isArray())
return defaultValue;
-
- return QJsonArray(d.data());
+ QCborContainerPrivate *dd = nullptr;
+ const auto n = QJsonPrivate::Value::valueHelper(value);
+ const auto container = QJsonPrivate::Value::container(value);
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return QJsonArray(dd);
}
/*!
@@ -762,10 +742,15 @@ QJsonArray QJsonValue::toArray() const
*/
QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const
{
- if (t != QCborValue::Map || n >= 0 || !d)
+ if (!isObject())
return defaultValue;
-
- return QJsonObject(d.data());
+ QCborContainerPrivate *dd = nullptr;
+ const auto container = QJsonPrivate::Value::container(value);
+ const auto n = QJsonPrivate::Value::valueHelper(value);
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return QJsonObject(dd);
}
/*!
@@ -780,7 +765,6 @@ QJsonObject QJsonValue::toObject() const
return toObject(QJsonObject());
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a QJsonValue representing the value for the key \a key.
@@ -797,7 +781,6 @@ const QJsonValue QJsonValue::operator[](const QString &key) const
{
return (*this)[QStringView(key)];
}
-#endif
/*!
\overload
@@ -815,7 +798,7 @@ const QJsonValue QJsonValue::operator[](QStringView key) const
\overload
\since 5.10
*/
-const QJsonValue QJsonValue::operator[](QLatin1String key) const
+const QJsonValue QJsonValue::operator[](QLatin1StringView key) const
{
if (!isObject())
return QJsonValue(QJsonValue::Undefined);
@@ -835,7 +818,7 @@ const QJsonValue QJsonValue::operator[](QLatin1String key) const
\sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
*/
-const QJsonValue QJsonValue::operator[](int i) const
+const QJsonValue QJsonValue::operator[](qsizetype i) const
{
if (!isArray())
return QJsonValue(QJsonValue::Undefined);
@@ -844,42 +827,37 @@ const QJsonValue QJsonValue::operator[](int i) const
}
/*!
- Returns \c true if the value is equal to \a other.
- */
-bool QJsonValue::operator==(const QJsonValue &other) const
+ \fn bool QJsonValue::operator==(const QJsonValue &lhs, const QJsonValue &rhs)
+
+ Returns \c true if the \a lhs value is equal to \a rhs value, \c false otherwise.
+*/
+bool comparesEqual(const QJsonValue &lhs, const QJsonValue &rhs) noexcept
{
- if (t != other.t) {
- if (isDouble() && other.isDouble()) {
+ if (lhs.value.type() != rhs.value.type()) {
+ if (lhs.isDouble() && rhs.isDouble()) {
// One value Cbor integer, one Cbor double, should interact as doubles.
- return toDouble() == other.toDouble();
+ return lhs.toDouble() == rhs.toDouble();
}
return false;
}
- switch (t) {
+ switch (lhs.value.type()) {
case QCborValue::Undefined:
case QCborValue::Null:
case QCborValue::True:
case QCborValue::False:
break;
case QCborValue::Double:
- return toDouble() == other.toDouble();
+ return lhs.toDouble() == rhs.toDouble();
case QCborValue::Integer:
- return n == other.n;
+ return QJsonPrivate::Value::valueHelper(lhs.value)
+ == QJsonPrivate::Value::valueHelper(rhs.value);
case QCborValue::String:
- return toString() == other.toString();
+ return lhs.toString() == rhs.toString();
case QCborValue::Array:
- if (!d)
- return !other.d || other.d->elements.length() == 0;
- if (!other.d)
- return d->elements.length() == 0;
- return QJsonArray(d.data()) == QJsonArray(other.d.data());
+ return lhs.toArray() == rhs.toArray();
case QCborValue::Map:
- if (!d)
- return !other.d || other.d->elements.length() == 0;
- if (!other.d)
- return d->elements.length() == 0;
- return QJsonObject(d.data()) == QJsonObject(other.d.data());
+ return lhs.toObject() == rhs.toObject();
default:
return false;
}
@@ -887,21 +865,10 @@ bool QJsonValue::operator==(const QJsonValue &other) const
}
/*!
- Returns \c true if the value is not equal to \a other.
- */
-bool QJsonValue::operator!=(const QJsonValue &other) const
-{
- return !(*this == other);
-}
-
-/*!
- \internal
- */
-void QJsonValue::detach()
-{
- d.detach();
-}
+ \fn bool QJsonValue::operator!=(const QJsonValue &lhs, const QJsonValue &rhs)
+ Returns \c true if the \a lhs value is not equal to \a rhs value, \c false otherwise.
+*/
/*!
\class QJsonValueRef
@@ -926,48 +893,200 @@ void QJsonValue::detach()
However, they are not explicitly documented here.
*/
-
-QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
+void QJsonValueRef::detach()
{
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QCborContainerPrivate *d = QJsonPrivate::Value::container(*this);
+ d = QCborContainerPrivate::detach(d, d->elements.size());
+
if (is_object)
- o->setValueAt(index, val);
+ o->o.reset(d);
else
- a->replace(index, val);
+ a->a.reset(d);
+#else
+ d = QCborContainerPrivate::detach(d, d->elements.size());
+#endif
+}
- return *this;
+static QJsonValueRef &assignToRef(QJsonValueRef &ref, const QCborValue &value, bool is_object)
+{
+ QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
+ qsizetype index = QJsonPrivate::Value::indexHelper(ref);
+ if (is_object && value.isUndefined()) {
+ d->removeAt(index);
+ d->removeAt(index - 1);
+ } else {
+ d->replaceAt(index, value);
+ }
+
+ return ref;
+}
+
+QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val)
+{
+ detach();
+ return assignToRef(*this, QCborValue::fromJsonValue(val), is_object);
}
QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref)
{
- if (is_object)
- o->setValueAt(index, ref);
- else
- a->replace(index, ref);
+ // ### optimize more?
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(ref);
+ qsizetype index = QJsonPrivate::Value::indexHelper(ref);
- return *this;
+ if (d == QJsonPrivate::Value::container(*this) &&
+ index == QJsonPrivate::Value::indexHelper(*this))
+ return *this; // self assignment
+
+ detach();
+ return assignToRef(*this, d->valueAt(index), is_object);
+}
+
+#ifndef QT_NO_VARIANT
+QVariant QJsonValueConstRef::toVariant() const
+{
+ return concrete(*this).toVariant();
+}
+#endif // !QT_NO_VARIANT
+
+QJsonArray QJsonValueConstRef::toArray() const
+{
+ return concrete(*this).toArray();
+}
+
+QJsonObject QJsonValueConstRef::toObject() const
+{
+ return concrete(*this).toObject();
}
+QJsonValue::Type QJsonValueConstRef::concreteType(QJsonValueConstRef self) noexcept
+{
+ return convertFromCborType(QJsonPrivate::Value::elementHelper(self).type);
+}
+
+bool QJsonValueConstRef::concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::False)
+ return false;
+ if (e.type == QCborValue::True)
+ return true;
+ return defaultValue;
+}
+
+qint64 QJsonValueConstRef::concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ qint64 v = defaultValue;
+ if (e.type == QCborValue::Double) {
+ // convertDoubleTo modifies the output even on returning false
+ if (!convertDoubleTo<qint64>(e.fpvalue(), &v))
+ v = defaultValue;
+ } else if (e.type == QCborValue::Integer) {
+ v = e.value;
+ }
+ if (clamp && qint64(int(v)) != v)
+ return defaultValue;
+ return v;
+}
+
+double QJsonValueConstRef::concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept
+{
+ auto &e = QJsonPrivate::Value::elementHelper(self);
+ if (e.type == QCborValue::Double)
+ return e.fpvalue();
+ if (e.type == QCborValue::Integer)
+ return e.value;
+ return defaultValue;
+}
+
+QString QJsonValueConstRef::concreteString(QJsonValueConstRef self, const QString &defaultValue)
+{
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+ if (d->elements.at(index).type != QCborValue::String)
+ return defaultValue;
+ return d->stringAt(index);
+}
+
+QJsonValue QJsonValueConstRef::concrete(QJsonValueConstRef self) noexcept
+{
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+ return QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index));
+}
+
+QString QJsonValueConstRef::objectKey(QJsonValueConstRef self)
+{
+ Q_ASSERT(self.is_object);
+ Q_ASSERT(self.is_object);
+ const QCborContainerPrivate *d = QJsonPrivate::Value::container(self);
+ qsizetype index = QJsonPrivate::Value::indexHelper(self);
+
+ Q_ASSERT(d);
+ Q_ASSERT(index < d->elements.size());
+ return d->stringAt(index - 1);
+}
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
QVariant QJsonValueRef::toVariant() const
{
- return toValue().toVariant();
+ return QJsonValueConstRef::toVariant();
}
QJsonArray QJsonValueRef::toArray() const
{
- return toValue().toArray();
+ return QJsonValueConstRef::toArray();
}
QJsonObject QJsonValueRef::toObject() const
{
- return toValue().toObject();
+ return QJsonValueConstRef::toObject();
}
QJsonValue QJsonValueRef::toValue() const
{
- if (!is_object)
- return a->at(index);
- return o->valueAt(index);
+ return concrete(*this);
+}
+#else
+QJsonValueRef QJsonValueRef::operator[](qsizetype key)
+{
+ if (d->elements.at(index).type != QCborValue::Array)
+ d->replaceAt(index, QCborValue::Array);
+
+ auto &e = d->elements[index];
+ e.container = QCborContainerPrivate::grow(e.container, key); // detaches
+ e.flags |= QtCbor::Element::IsContainer;
+
+ return QJsonValueRef(e.container, key, false);
+}
+
+QJsonValueRef QJsonValueRef::operator[](QAnyStringView key)
+{
+ // must go through QJsonObject because some of the machinery is non-static
+ // member or file-static in qjsonobject.cpp
+ QJsonObject o = QJsonPrivate::Value::fromTrustedCbor(d->valueAt(index)).toObject();
+ QJsonValueRef ret = key.visit([&](auto v) {
+ if constexpr (std::is_same_v<decltype(v), QUtf8StringView>)
+ return o[QString::fromUtf8(v)];
+ else
+ return o[v];
+ });
+
+ // ### did the QJsonObject::operator[] above detach?
+ QCborContainerPrivate *x = o.o.take();
+ Q_ASSERT(x->ref.loadRelaxed() == 1);
+
+ auto &e = d->elements[index];
+ if (e.flags & QtCbor::Element::IsContainer && e.container != x)
+ o.o.reset(e.container); // might not an object!
+
+ e.flags |= QtCbor::Element::IsContainer;
+ e.container = x;
+
+ return ret;
}
+#endif
size_t qHash(const QJsonValue &value, size_t seed)
{
@@ -987,15 +1106,14 @@ size_t qHash(const QJsonValue &value, size_t seed)
case QJsonValue::Undefined:
return seed;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{
QDebugStateSaver saver(dbg);
- switch (o.t) {
+ switch (o.value.type()) {
case QCborValue::Undefined:
dbg << "QJsonValue(undefined)";
break;
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 205ee31dd5..d71dadf837 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -1,49 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONVALUE_H
#define QJSONVALUE_H
+#include <QtCore/qcborvalue.h>
+#include <QtCore/qcompare.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qshareddata.h>
-#include <QtCore/qcborvalue.h>
QT_BEGIN_NAMESPACE
@@ -75,18 +40,20 @@ public:
QJsonValue(int n);
QJsonValue(qint64 v);
QJsonValue(const QString &s);
- QJsonValue(QLatin1String s);
+ QJsonValue(QLatin1StringView s);
#ifndef QT_NO_CAST_FROM_ASCII
- inline QT_ASCII_CAST_WARN QJsonValue(const char *s)
+ QT_ASCII_CAST_WARN inline QJsonValue(const char *s)
: QJsonValue(QString::fromUtf8(s)) {}
#endif
QJsonValue(const QJsonArray &a);
+ QJsonValue(QJsonArray &&a) noexcept;
QJsonValue(const QJsonObject &o);
+ QJsonValue(QJsonObject &&o) noexcept;
~QJsonValue();
- QJsonValue(const QJsonValue &other);
- QJsonValue &operator =(const QJsonValue &other);
+ QJsonValue(const QJsonValue &other) noexcept;
+ QJsonValue &operator =(const QJsonValue &other) noexcept;
QJsonValue(QJsonValue &&other) noexcept;
@@ -121,17 +88,21 @@ public:
QJsonObject toObject() const;
QJsonObject toObject(const QJsonObject &defaultValue) const;
-#if QT_STRINGVIEW_LEVEL < 2
const QJsonValue operator[](const QString &key) const;
-#endif
const QJsonValue operator[](QStringView key) const;
- const QJsonValue operator[](QLatin1String key) const;
- const QJsonValue operator[](int i) const;
+ const QJsonValue operator[](QLatin1StringView key) const;
+ const QJsonValue operator[](qsizetype i) const;
+#if QT_CORE_REMOVED_SINCE(6, 8)
bool operator==(const QJsonValue &other) const;
bool operator!=(const QJsonValue &other) const;
+#endif
private:
+ friend Q_CORE_EXPORT bool comparesEqual(const QJsonValue &lhs,
+ const QJsonValue &rhs) noexcept;
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValue)
+
// avoid implicit conversions from char * to bool
QJsonValue(const void *) = delete;
friend class QJsonPrivate::Value;
@@ -141,35 +112,148 @@ private:
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &);
- // ### Qt6: Remove this.
- void stringDataFromQStringHelper(const QString &string);
-
- void detach();
-
- // ### Qt6: change to an actual QCborValue
- qint64 n = 0;
- QExplicitlySharedDataPointer<QCborContainerPrivate> d; // needed for Objects, Arrays, Strings
- QCborValue::Type t;
+ QCborValue value;
// Assert binary compatibility with pre-5.15 QJsonValue
static_assert(sizeof(QExplicitlySharedDataPointer<QCborContainerPrivate>) == sizeof(void *));
static_assert(sizeof(QCborValue::Type) == sizeof(QJsonValue::Type));
};
-class Q_CORE_EXPORT QJsonValueRef
+Q_DECLARE_SHARED(QJsonValue)
+
+class QJsonValueConstRef
{
public:
- QJsonValueRef(QJsonArray *array, int idx)
- : a(array), is_object(false), index(static_cast<uint>(idx)) {}
- QJsonValueRef(QJsonObject *object, int idx)
- : o(object), is_object(true), index(static_cast<uint>(idx)) {}
+ QJsonValueConstRef(const QJsonValueConstRef &) = default;
+ QJsonValueConstRef &operator=(const QJsonValueConstRef &) = delete;
+ inline operator QJsonValue() const { return concrete(*this); }
+
+ Q_CORE_EXPORT QVariant toVariant() const;
+ QJsonValue::Type type() const { return concreteType(*this); }
+ bool isNull() const { return type() == QJsonValue::Null; }
+ bool isBool() const { return type() == QJsonValue::Bool; }
+ bool isDouble() const { return type() == QJsonValue::Double; }
+ bool isString() const { return type() == QJsonValue::String; }
+ bool isArray() const { return type() == QJsonValue::Array; }
+ bool isObject() const { return type() == QJsonValue::Object; }
+ bool isUndefined() const { return type() == QJsonValue::Undefined; }
+
+ bool toBool(bool defaultValue = false) const
+ { return concreteBool(*this, defaultValue); }
+ int toInt(int defaultValue = 0) const
+ { return int(concreteInt(*this, defaultValue, true)); }
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return concreteInt(*this, defaultValue, false); }
+ double toDouble(double defaultValue = 0) const
+ { return concreteDouble(*this, defaultValue); }
+ QString toString(const QString &defaultValue = {}) const
+ { return concreteString(*this, defaultValue); }
+ Q_CORE_EXPORT QJsonArray toArray() const;
+ Q_CORE_EXPORT QJsonObject toObject() const;
+
+ const QJsonValue operator[](QStringView key) const { return concrete(*this)[key]; }
+ const QJsonValue operator[](QLatin1StringView key) const { return concrete(*this)[key]; }
+ const QJsonValue operator[](qsizetype i) const { return concrete(*this)[i]; }
+
+protected:
+ friend bool comparesEqual(const QJsonValueConstRef &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(concrete(lhs), concrete(rhs));
+ }
+ friend bool comparesEqual(const QJsonValueConstRef &lhs,
+ const QJsonValue &rhs) noexcept
+ {
+ return comparesEqual(concrete(lhs), rhs);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueConstRef)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueConstRef, QJsonValue)
+
+ Q_CORE_EXPORT static QJsonValue::Type
+ concreteType(QJsonValueConstRef self) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static bool
+ concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static qint64
+ concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static double
+ concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept Q_DECL_PURE_FUNCTION;
+ Q_CORE_EXPORT static QString concreteString(QJsonValueConstRef self, const QString &defaultValue);
+ Q_CORE_EXPORT static QJsonValue concrete(QJsonValueConstRef self) noexcept;
+
+ // for iterators
+ Q_CORE_EXPORT static QString objectKey(QJsonValueConstRef self);
+ QString objectKey() const { return objectKey(*this); }
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QJsonValueConstRef(QJsonArray *array, qsizetype idx)
+ : a(array), is_object(false), index(static_cast<quint64>(idx)) {}
+ QJsonValueConstRef(QJsonObject *object, qsizetype idx)
+ : o(object), is_object(true), index(static_cast<quint64>(idx)) {}
+
+ void rebind(QJsonValueConstRef other)
+ {
+ Q_ASSERT(is_object == other.is_object);
+ if (is_object)
+ o = other.o;
+ else
+ a = other.a;
+ index = other.index;
+ }
- inline operator QJsonValue() const { return toValue(); }
- QJsonValueRef &operator = (const QJsonValue &val);
- QJsonValueRef &operator = (const QJsonValueRef &val);
+ union {
+ QJsonArray *a;
+ QJsonObject *o;
+ void *d;
+ };
+ quint64 is_object : 1;
+ quint64 index : 63;
+#else
+ constexpr QJsonValueConstRef(QCborContainerPrivate *d, size_t index, bool is_object)
+ : d(d), is_object(is_object), index(index)
+ {}
+
+ // implemented in qjsonarray.h & qjsonobject.h, to get their d
+ QJsonValueConstRef(QJsonArray *array, qsizetype idx);
+ QJsonValueConstRef(QJsonObject *object, qsizetype idx);
+
+ void rebind(QJsonValueConstRef other)
+ {
+ d = other.d;
+ index = other.index;
+ }
+
+ QCborContainerPrivate *d = nullptr;
+ size_t is_object : 1;
+ size_t index : std::numeric_limits<size_t>::digits - 1;
+#endif
+
+ friend class QJsonArray;
+ friend class QJsonObject;
+ friend class QJsonPrivate::Value;
+};
+
+QT_WARNING_PUSH
+QT6_ONLY(QT_WARNING_DISABLE_MSVC(4275)) // non dll-interface class 'QJsonValueConstRef' used as base for dll-interface class 'QJsonValueRef'
+class QT6_ONLY(Q_CORE_EXPORT) QJsonValueRef : public QJsonValueConstRef
+{
+public:
+ QJsonValueRef(const QJsonValueRef &) = default;
+ QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValue &val);
+ QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValueRef &val);
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ // retained for binary compatibility (due to the Q_CORE_EXPORT) because at
+ // least one compiler emits and exports all inlines in an exported class
+
+ QJsonValueRef(QJsonArray *array, qsizetype idx)
+ : QJsonValueConstRef(array, idx) {}
+ QJsonValueRef(QJsonObject *object, qsizetype idx)
+ : QJsonValueConstRef(object, idx) {}
+
+ operator QJsonValue() const { return toValue(); }
QVariant toVariant() const;
- inline QJsonValue::Type type() const { return toValue().type(); }
+ inline QJsonValue::Type type() const { return QJsonValueConstRef::type(); }
inline bool isNull() const { return type() == QJsonValue::Null; }
inline bool isBool() const { return type() == QJsonValue::Bool; }
inline bool isDouble() const { return type() == QJsonValue::Double; }
@@ -178,59 +262,57 @@ public:
inline bool isObject() const { return type() == QJsonValue::Object; }
inline bool isUndefined() const { return type() == QJsonValue::Undefined; }
- inline bool toBool() const { return toValue().toBool(); }
- inline int toInt() const { return toValue().toInt(); }
- inline double toDouble() const { return toValue().toDouble(); }
- inline QString toString() const { return toValue().toString(); }
+ inline bool toBool(bool defaultValue = false) const { return QJsonValueConstRef::toBool(defaultValue); }
+ inline int toInt(int defaultValue = 0) const { return QJsonValueConstRef::toInt(defaultValue); }
+ inline qint64 toInteger(qint64 defaultValue = 0) const { return QJsonValueConstRef::toInteger(defaultValue); }
+ inline double toDouble(double defaultValue = 0) const { return QJsonValueConstRef::toDouble(defaultValue); }
+ inline QString toString(const QString &defaultValue = {}) const { return QJsonValueConstRef::toString(defaultValue); }
QJsonArray toArray() const;
QJsonObject toObject() const;
- // ### Qt 6: Add default values
- inline bool toBool(bool defaultValue) const { return toValue().toBool(defaultValue); }
- inline int toInt(int defaultValue) const { return toValue().toInt(defaultValue); }
- inline double toDouble(double defaultValue) const { return toValue().toDouble(defaultValue); }
- inline QString toString(const QString &defaultValue) const { return toValue().toString(defaultValue); }
+ const QJsonValue operator[](QStringView key) const { return QJsonValueConstRef::operator[](key); }
+ const QJsonValue operator[](QLatin1StringView key) const { return QJsonValueConstRef::operator[](key); }
+ const QJsonValue operator[](qsizetype i) const { return QJsonValueConstRef::operator[](i); }
- inline bool operator==(const QJsonValue &other) const { return toValue() == other; }
- inline bool operator!=(const QJsonValue &other) const { return toValue() != other; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QJsonValue &other) const { return comparesEqual(*this, other); }
+ inline bool operator!=(const QJsonValue &other) const { return !comparesEqual(*this, other); }
+#endif
private:
- QJsonValue toValue() const;
+ friend bool comparesEqual(const QJsonValueRef &lhs,
+ const QJsonValueRef &rhs) noexcept
+ {
+ return comparesEqual(QJsonValue(lhs), QJsonValue(rhs));
+ }
+ friend bool comparesEqual(const QJsonValueRef &lhs,
+ const QJsonValueConstRef &rhs) noexcept
+ {
+ return comparesEqual(QJsonValue(lhs), QJsonValue(rhs));
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueRef)
+ Q_DECLARE_EQUALITY_COMPARABLE(QJsonValueRef, QJsonValueConstRef)
- union {
- QJsonArray *a;
- QJsonObject *o;
- };
- uint is_object : 1;
- uint index : 31;
-};
+ QJsonValue toValue() const;
+#else
+ using QJsonValueConstRef::operator[];
+ Q_CORE_EXPORT QJsonValueRef operator[](QAnyStringView key);
+ Q_CORE_EXPORT QJsonValueRef operator[](qsizetype i);
-// ### Qt 6: Get rid of these fake pointer classes
-class QJsonValuePtr
-{
- QJsonValue value;
-public:
- explicit QJsonValuePtr(const QJsonValue& val)
- : value(val) {}
+private:
+ using QJsonValueConstRef::QJsonValueConstRef;
+#endif // < Qt 7
- QJsonValue& operator*() { return value; }
- QJsonValue* operator->() { return &value; }
+ QT7_ONLY(Q_CORE_EXPORT) void detach();
+ friend class QJsonArray;
+ friend class QJsonObject;
};
+QT_WARNING_POP
-class QJsonValueRefPtr
+inline QJsonValue QCborValueConstRef::toJsonValue() const
{
- QJsonValueRef valueRef;
-public:
- QJsonValueRefPtr(QJsonArray *array, int idx)
- : valueRef(array, idx) {}
- QJsonValueRefPtr(QJsonObject *object, int idx)
- : valueRef(object, idx) {}
-
- QJsonValueRef& operator*() { return valueRef; }
- QJsonValueRef* operator->() { return &valueRef; }
-};
-
-Q_DECLARE_SHARED(QJsonValue)
+ return concrete().toJsonValue();
+}
Q_CORE_EXPORT size_t qHash(const QJsonValue &value, size_t seed = 0);
diff --git a/src/corelib/serialization/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 8610cdff7e..ab34e9228d 100644
--- a/src/corelib/serialization/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <cmath>
#include <qlocale.h>
@@ -58,26 +22,27 @@ static inline uchar hexdig(uint u)
return (u < 0xa ? '0' + u : 'a' + u - 0xa);
}
-static QByteArray escapedString(const QString &s)
+static QByteArray escapedString(QStringView s)
{
// give it a minimum size to ensure the resize() below always adds enough space
- QByteArray ba(qMax(s.length(), 16), Qt::Uninitialized);
+ QByteArray ba(qMax(s.size(), 16), Qt::Uninitialized);
+ auto ba_const_start = [&]() { return reinterpret_cast<const uchar *>(ba.constData()); };
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
- const uchar *ba_end = cursor + ba.length();
- const ushort *src = reinterpret_cast<const ushort *>(s.constBegin());
- const ushort *const end = reinterpret_cast<const ushort *>(s.constEnd());
+ const uchar *ba_end = cursor + ba.size();
+ const char16_t *src = s.utf16();
+ const char16_t *const end = s.utf16() + s.size();
while (src != end) {
if (cursor >= ba_end - 6) {
// ensure we have enough space
- int pos = cursor - (const uchar *)ba.constData();
+ qptrdiff pos = cursor - ba_const_start();
ba.resize(ba.size()*2);
- cursor = (uchar *)ba.data() + pos;
- ba_end = (const uchar *)ba.constData() + ba.length();
+ cursor = reinterpret_cast<uchar *>(ba.data()) + pos;
+ ba_end = ba_const_start() + ba.size();
}
- uint u = *src++;
+ char16_t u = *src++;
if (u < 0x80) {
if (u < 0x20 || u == 0x22 || u == 0x5c) {
*cursor++ = '\\';
@@ -124,7 +89,7 @@ static QByteArray escapedString(const QString &s)
}
}
- ba.resize(cursor - (const uchar *)ba.constData());
+ ba.resize(cursor - ba_const_start());
return ba;
}
@@ -143,7 +108,7 @@ static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool
break;
case QCborValue::Double: {
const double d = v.toDouble();
- if (qIsFinite(d))
+ if (qt_is_finite(d))
json += QByteArray::number(d, 'g', QLocale::FloatingPointShortest);
else
json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
diff --git a/src/corelib/serialization/qjsonwriter_p.h b/src/corelib/serialization/qjsonwriter_p.h
index 8c263bb7c3..f61840247f 100644
--- a/src/corelib/serialization/qjsonwriter_p.h
+++ b/src/corelib/serialization/qjsonwriter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QJSONWRITER_P_H
#define QJSONWRITER_P_H
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index 3f0c25fd17..e9d650b3e2 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QTEXTSTREAM_DEBUG
static const int QTEXTSTREAM_BUFFERSIZE = 16384;
@@ -50,6 +14,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
\ingroup io
\ingroup string-processing
+ \ingroup qtserialization
\reentrant
QTextStream can operate on a QIODevice, a QByteArray or a
@@ -230,6 +195,9 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include "qfile.h"
#include "qnumeric.h"
#include "qvarlengtharray.h"
+#include <private/qdebug_p.h>
+#include <private/qnumeric_p.h>
+#include <private/qtools_p.h>
#include <locale.h>
#include "private/qlocale_p.h"
@@ -239,48 +207,6 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384;
#include <limits.h>
#include <new>
-#if defined QTEXTSTREAM_DEBUG
-#include <ctype.h>
-#include "private/qtools_p.h"
-
-QT_BEGIN_NAMESPACE
-
-// Returns a human readable representation of the first \a len
-// characters in \a data.
-static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
-{
- if (!data) return "(null)";
- QByteArray out;
- for (int i = 0; i < len; ++i) {
- char c = data[i];
- if (isprint(int(uchar(c)))) {
- out += c;
- } else switch (c) {
- case '\n': out += "\\n"; break;
- case '\r': out += "\\r"; break;
- case '\t': out += "\\t"; break;
- default: {
- const char buf[] = {
- '\\',
- 'x',
- QtMiscUtils::toHexLower(uchar(c) / 16),
- QtMiscUtils::toHexLower(uchar(c) % 16),
- 0
- };
- out += buf;
- }
- }
- }
-
- if (len < maxSize)
- out += "...";
-
- return out;
-}
-QT_END_NAMESPACE
-
-#endif
-
// A precondition macro
#define Q_VOID
#define CHECK_VALID_STREAM(x) do { \
@@ -320,6 +246,9 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
//-------------------------------------------------------------------
/*!
@@ -351,7 +280,7 @@ void QTextStreamPrivate::Params::reset()
realNumberPrecision = 6;
integerBase = 0;
fieldWidth = 0;
- padChar = QLatin1Char(' ');
+ padChar = u' ';
fieldAlignment = QTextStream::AlignRight;
realNumberNotation = QTextStream::SmartNotation;
numberFlags = { };
@@ -368,7 +297,7 @@ void QTextStreamPrivate::reset()
deleteDevice = false;
string = nullptr;
stringOffset = 0;
- stringOpenMode = QIODevice::NotOpen;
+ stringOpenMode = QTextStream::NotOpen;
readBufferOffset = 0;
readBufferStartDevicePos = 0;
@@ -431,10 +360,11 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
if (bytesRead <= 0)
return false;
+#ifndef QT_BOOTSTRAPPED
if (autoDetectUnicode) {
autoDetectUnicode = false;
- auto e = QStringConverter::encodingForData(buf, bytesRead);
+ auto e = QStringConverter::encodingForData(QByteArrayView(buf, bytesRead));
// QStringConverter::Locale implies unknown, so keep the current encoding
if (e) {
encoding = *e;
@@ -445,18 +375,19 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer(), using %s encoding", QStringConverter::nameForEncoding(encoding));
#endif
+#endif
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d",
- qt_prettyDebug(buf, qMin(32,int(bytesRead)) , int(bytesRead)).constData(), int(sizeof(buf)), int(bytesRead));
+ QtDebugUtils::toPrintable(buf, bytesRead, 32).constData(), int(sizeof(buf)), int(bytesRead));
#endif
int oldReadBufferSize = readBuffer.size();
- readBuffer += toUtf16(buf, bytesRead);
+ readBuffer += toUtf16(QByteArrayView(buf, bytesRead));
// remove all '\r\n' in the string.
if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
- QChar CR = QLatin1Char('\r');
+ QChar CR = u'\r';
QChar *writePtr = readBuffer.data() + oldReadBufferSize;
QChar *readPtr = readBuffer.data() + oldReadBufferSize;
QChar *endPtr = readBuffer.data() + readBuffer.size();
@@ -486,7 +417,7 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::fillReadBuffer() read %d bytes from device. readBuffer = [%s]", int(bytesRead),
- qt_prettyDebug(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).data());
+ QtDebugUtils::toPrintable(readBuffer.toLatin1(), readBuffer.size(), readBuffer.size()).constData());
#endif
return true;
}
@@ -524,7 +455,7 @@ void QTextStreamPrivate::flushWriteBuffer()
bool textModeEnabled = device->isTextModeEnabled();
if (textModeEnabled) {
device->setTextModeEnabled(false);
- writeBuffer.replace(QLatin1Char('\n'), QLatin1String("\r\n"));
+ writeBuffer.replace(u'\n', "\r\n"_L1);
}
#endif
@@ -536,7 +467,7 @@ void QTextStreamPrivate::flushWriteBuffer()
qint64 bytesWritten = device->write(data);
#if defined (QTEXTSTREAM_DEBUG)
qDebug("QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d",
- qt_prettyDebug(data.constData(), qMin(data.size(),32), data.size()).constData(), int(bytesWritten));
+ QtDebugUtils::toPrintable(data.constData(), data.size(), 32).constData(), int(bytesWritten));
#endif
#if defined (Q_OS_WIN)
@@ -601,7 +532,6 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
int startOffset = device ? readBufferOffset : stringOffset;
QChar lastChar;
- bool canStillReadFromDevice = true;
do {
int endOffset;
const QChar *chPtr;
@@ -632,9 +562,9 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
}
break;
case EndOfLine:
- if (ch == QLatin1Char('\n')) {
+ if (ch == u'\n') {
foundToken = true;
- delimSize = (lastChar == QLatin1Char('\r')) ? 2 : 1;
+ delimSize = (lastChar == u'\r') ? 2 : 1;
consumeDelimiter = true;
}
lastChar = ch;
@@ -643,7 +573,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
}
} while (!foundToken
&& (!maxlen || totalSize < maxlen)
- && (device && (canStillReadFromDevice = fillReadBuffer())));
+ && device && fillReadBuffer());
if (totalSize == 0) {
#if defined (QTEXTSTREAM_DEBUG)
@@ -656,7 +586,7 @@ bool QTextStreamPrivate::scan(const QChar **ptr, int *length, int maxlen, TokenD
// don't make it part of the line.
if (delimiter == EndOfLine && totalSize > 0 && !foundToken) {
if (((string && stringOffset + totalSize == string->size()) || (device && device->atEnd()))
- && lastChar == QLatin1Char('\r')) {
+ && lastChar == u'\r') {
consumeDelimiter = true;
++delimSize;
}
@@ -754,7 +684,7 @@ inline void QTextStreamPrivate::restoreToSavedConverterState()
/*!
\internal
*/
-void QTextStreamPrivate::write(const QChar *data, int len)
+void QTextStreamPrivate::write(const QChar *data, qsizetype len)
{
if (string) {
// ### What about seek()??
@@ -784,7 +714,7 @@ inline void QTextStreamPrivate::write(QChar ch)
/*!
\internal
*/
-void QTextStreamPrivate::write(QLatin1String data)
+void QTextStreamPrivate::write(QLatin1StringView data)
{
if (string) {
// ### What about seek()??
@@ -799,7 +729,7 @@ void QTextStreamPrivate::write(QLatin1String data)
/*!
\internal
*/
-void QTextStreamPrivate::writePadding(int len)
+void QTextStreamPrivate::writePadding(qsizetype len)
{
if (string) {
// ### What about seek()??
@@ -864,7 +794,7 @@ inline void QTextStreamPrivate::putChar(QChar ch)
/*!
\internal
*/
-QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const
+QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(qsizetype len) const
{
Q_ASSERT(params.fieldWidth > len); // calling padding() when no padding is needed is an error
@@ -891,7 +821,7 @@ QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const
/*!
\internal
*/
-void QTextStreamPrivate::putString(const QChar *data, int len, bool number)
+void QTextStreamPrivate::putString(const QChar *data, qsizetype len, bool number)
{
if (Q_UNLIKELY(params.fieldWidth > len)) {
@@ -920,7 +850,7 @@ void QTextStreamPrivate::putString(const QChar *data, int len, bool number)
/*!
\internal
*/
-void QTextStreamPrivate::putString(QLatin1String data, bool number)
+void QTextStreamPrivate::putString(QLatin1StringView data, bool number)
{
if (Q_UNLIKELY(params.fieldWidth > data.size())) {
@@ -933,7 +863,7 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number)
if (sign == locale.negativeSign() || sign == locale.positiveSign()) {
// write the sign before the padding, then skip it later
write(&sign, 1);
- data = QLatin1String(data.data() + 1, data.size() - 1);
+ data = QLatin1StringView(data.data() + 1, data.size() - 1);
}
}
@@ -945,6 +875,11 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number)
}
}
+void QTextStreamPrivate::putString(QUtf8StringView data, bool number)
+{
+ putString(data.toString(), number);
+}
+
/*!
Constructs a QTextStream. Before you can use it for reading or
writing, you must assign a device or a string.
@@ -983,7 +918,7 @@ QTextStream::QTextStream(QIODevice *device)
Constructs a QTextStream that operates on \a string, using \a
openMode to define the open mode.
*/
-QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(QString *string, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1001,7 +936,7 @@ QTextStream::QTextStream(QString *string, QIODevice::OpenMode openMode)
openMode to define the open mode. Internally, the array is wrapped
by a QBuffer.
*/
-QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(QByteArray *array, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1028,7 +963,7 @@ QTextStream::QTextStream(QByteArray *array, QIODevice::OpenMode openMode)
\snippet code/src_corelib_io_qtextstream.cpp 3
*/
-QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(const QByteArray &array, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1059,7 +994,7 @@ QTextStream::QTextStream(const QByteArray &array, QIODevice::OpenMode openMode)
\snippet code/src_corelib_io_qtextstream.cpp 4
*/
-QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
+QTextStream::QTextStream(FILE *fileHandle, OpenMode openMode)
: d_ptr(new QTextStreamPrivate(this))
{
#if defined (QTEXTSTREAM_DEBUG)
@@ -1067,7 +1002,10 @@ QTextStream::QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode)
fileHandle, int(openMode));
#endif
QFile *file = new QFile;
- file->open(fileHandle, openMode);
+ // Discarding the return value of open; even if it failed
+ // (and the file is not open), QTextStream still reports `Ok`
+ // for closed QIODevices, so there's nothing really to do here.
+ (void)file->open(fileHandle, openMode);
Q_D(QTextStream);
d->device = file;
@@ -1272,7 +1210,7 @@ QIODevice *QTextStream::device() const
\sa string(), setDevice()
*/
-void QTextStream::setString(QString *string, QIODevice::OpenMode openMode)
+void QTextStream::setString(QString *string, OpenMode openMode)
{
Q_D(QTextStream);
flush();
@@ -1470,7 +1408,8 @@ QTextStream::RealNumberNotation QTextStream::realNumberNotation() const
/*!
Sets the precision of real numbers to \a precision. This value
describes the number of fraction digits QTextStream should
- write when generating real numbers.
+ write when generating real numbers (FixedNotation, ScientificNotation), or
+ the maximum number of significant digits (SmartNotation).
The precision cannot be a negative value. The default value is 6.
@@ -1489,7 +1428,9 @@ void QTextStream::setRealNumberPrecision(int precision)
/*!
Returns the current real number precision, or the number of fraction
- digits QTextStream will write when generating real numbers.
+ digits QTextStream will write when generating real numbers
+ (FixedNotation, ScientificNotation), or the maximum number of significant
+ digits (SmartNotation).
\sa setRealNumberNotation(), realNumberNotation(), numberFlags(), integerBase()
*/
@@ -1683,7 +1624,7 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
QChar ch;
if (!getChar(&ch))
return npsInvalidPrefix;
- if (ch == QLatin1Char('0')) {
+ if (ch == u'0') {
QChar ch2;
if (!getChar(&ch2)) {
// Result is the number 0
@@ -1692,9 +1633,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
}
ch2 = ch2.toLower();
- if (ch2 == QLatin1Char('x')) {
+ if (ch2 == u'x') {
base = 16;
- } else if (ch2 == QLatin1Char('b')) {
+ } else if (ch2 == u'b') {
base = 2;
} else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) {
base = 8;
@@ -1719,9 +1660,9 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 2: {
QChar pf1, pf2, dig;
// Parse prefix '0b'
- if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ if (!getChar(&pf1) || pf1 != u'0')
return npsInvalidPrefix;
- if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('b'))
+ if (!getChar(&pf2) || pf2.toLower() != u'b')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
@@ -1747,13 +1688,13 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 8: {
QChar pf, dig;
// Parse prefix '0'
- if (!getChar(&pf) || pf != QLatin1Char('0'))
+ if (!getChar(&pf) || pf != u'0')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
while (getChar(&dig)) {
int n = dig.toLower().unicode();
- if (n >= '0' && n <= '7') {
+ if (isOctalDigit(n)) {
val *= 8;
val += n - '0';
} else {
@@ -1810,20 +1751,17 @@ QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong
case 16: {
QChar pf1, pf2, dig;
// Parse prefix ' 0x'
- if (!getChar(&pf1) || pf1 != QLatin1Char('0'))
+ if (!getChar(&pf1) || pf1 != u'0')
return npsInvalidPrefix;
- if (!getChar(&pf2) || pf2.toLower() != QLatin1Char('x'))
+ if (!getChar(&pf2) || pf2.toLower() != u'x')
return npsInvalidPrefix;
// Parse digits
int ndigits = 0;
while (getChar(&dig)) {
- int n = dig.toLower().unicode();
- if (n >= '0' && n <= '9') {
- val <<= 4;
- val += n - '0';
- } else if (n >= 'a' && n <= 'f') {
+ const int h = fromHex(dig.unicode());
+ if (h != -1) {
val <<= 4;
- val += 10 + (n - 'a');
+ val += h;
} else {
ungetChar(dig);
break;
@@ -1979,13 +1917,13 @@ bool QTextStreamPrivate::getReal(double *f)
// nan/+inf/-inf, so here we also check for uppercase and mixed
// case versions.
if (!qstricmp(buf, "nan") || !qstricmp(buf, "+nan") || !qstricmp(buf, "-nan")) {
- *f = qQNaN();
+ *f = qt_qnan();
return true;
} else if (!qstricmp(buf, "+inf") || !qstricmp(buf, "inf")) {
- *f = qInf();
+ *f = qt_inf();
return true;
} else if (!qstricmp(buf, "-inf")) {
- *f = -qInf();
+ *f = -qt_inf();
return true;
}
bool ok;
@@ -2017,7 +1955,7 @@ QTextStream &QTextStream::operator>>(QChar &c)
\overload
Reads a character from the stream and stores it in \a c. The
- character from the stream is converted to ISO-5589-1 before it is
+ character from the stream is converted to ISO-8859-1 before it is
stored.
\sa QChar::toLatin1()
@@ -2031,6 +1969,14 @@ QTextStream &QTextStream::operator>>(char &c)
}
/*!
+ \fn QTextStream &QTextStream::operator>>(char16_t &c)
+ \overload
+ \since 6.4
+
+ Reads a character from the stream and stores it in \a c.
+*/
+
+/*!
Reads an integer from the stream and stores it in \a i, then
returns a reference to the QTextStream. The number is cast to
the correct type before it is stored. If no number was detected on
@@ -2186,7 +2132,7 @@ QTextStream &QTextStream::operator>>(QString &str)
/*!
\overload
- Converts the word to ISO-8859-1, then stores it in \a array.
+ Converts the word to UTF-8, then stores it in \a array.
\sa QString::toLatin1()
*/
@@ -2195,7 +2141,6 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- array.clear();
d->scan(nullptr, nullptr, 0, QTextStreamPrivate::NotSpace);
d->consumeLastToken();
@@ -2203,11 +2148,11 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
int length;
if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
setStatus(ReadPastEnd);
+ array.clear();
return *this;
}
- for (int i = 0; i < length; ++i)
- array += ptr[i].toLatin1();
+ array = QStringView(ptr, length).toUtf8();
d->consumeLastToken();
return *this;
@@ -2216,13 +2161,14 @@ QTextStream &QTextStream::operator>>(QByteArray &array)
/*!
\overload
- Stores the word in \a c, terminated by a '\\0' character. If no word is
- available, only the '\\0' character is stored.
+ Converts the word to UTF-8 and stores it in \a c, terminated by a '\\0'
+ character. If no word is available, only the '\\0' character is stored.
Warning: Although convenient, this operator is dangerous and must
be used with care. QTextStream assumes that \a c points to a
buffer with enough space to hold the word. If the buffer is too
- small, your application may crash.
+ small, your application may crash. For a word consisting of \c{n} QChars,
+ the buffer needs to be at least \c{3*n+1} characters long.
If possible, use the QByteArray operator instead.
*/
@@ -2241,9 +2187,9 @@ QTextStream &QTextStream::operator>>(char *c)
return *this;
}
- for (int i = 0; i < length; ++i)
- *c++ = ptr[i].toLatin1();
- *c = '\0';
+ QStringEncoder encoder(QStringConverter::Utf8);
+ char *e = encoder.appendToBuffer(c, QStringView(ptr, length));
+ *e = '\0';
d->consumeLastToken();
return *this;
}
@@ -2269,7 +2215,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// add thousands group separators. For backward compatibility we
// don't add a group separator for C locale.
if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
const QLocaleData *dd = locale.d->m_data;
int base = params.integerBase ? params.integerBase : 10;
@@ -2288,8 +2234,8 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// workaround for backward compatibility - in octal form with
// ShowBase flag set zero should be written as '00'
if (number == 0 && base == 8 && params.numberFlags & QTextStream::ShowBase
- && result == QLatin1String("0")) {
- result.prepend(QLatin1Char('0'));
+ && result == "0"_L1) {
+ result.prepend(u'0');
}
}
putString(result, true);
@@ -2323,6 +2269,15 @@ QTextStream &QTextStream::operator<<(char c)
}
/*!
+ \fn QTextStream &QTextStream::operator<<(char16_t c)
+ \overload
+ \since 6.3.1
+
+ Writes the Unicode character \a c to the stream, then returns a
+ reference to the QTextStream.
+*/
+
+/*!
Writes the integer number \a i to the stream, then returns a
reference to the QTextStream. By default, the number is stored in
decimal form, but you can also set the base by calling
@@ -2485,7 +2440,7 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase;
}
if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator))
- flags |= QLocaleData::ThousandsGroup;
+ flags |= QLocaleData::GroupDigits;
if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
@@ -2533,7 +2488,7 @@ QTextStream &QTextStream::operator<<(QStringView string)
Writes \a string to the stream, and returns a reference to the
QTextStream.
*/
-QTextStream &QTextStream::operator<<(QLatin1String string)
+QTextStream &QTextStream::operator<<(QLatin1StringView string)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
@@ -2551,7 +2506,7 @@ QTextStream &QTextStream::operator<<(const QByteArray &array)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- d->putString(QString::fromUtf8(array.constData(), array.length()));
+ d->putString(QString::fromUtf8(array.constData(), array.size()));
return *this;
}
@@ -2559,7 +2514,7 @@ QTextStream &QTextStream::operator<<(const QByteArray &array)
\overload
Writes the constant string pointed to by \a string to the stream. \a
- string is assumed to be in ISO-8859-1 encoding. This operator
+ string is assumed to be in UTF-8 encoding. This operator
is convenient when working with constant string data. Example:
\snippet code/src_corelib_io_qtextstream.cpp 8
@@ -2572,8 +2527,7 @@ QTextStream &QTextStream::operator<<(const char *string)
{
Q_D(QTextStream);
CHECK_VALID_STREAM(*this);
- // ### Qt6: consider changing to UTF-8
- d->putString(QLatin1String(string));
+ d->putString(QUtf8StringView(string));
return *this;
}
@@ -2600,12 +2554,6 @@ QTextStream &QTextStream::operator<<(const void *ptr)
namespace Qt {
/*!
- \fn QTextStream &bin(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::bin() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(2) on \a stream and returns \a
stream.
@@ -2620,12 +2568,6 @@ QTextStream &bin(QTextStream &stream)
}
/*!
- \fn QTextStream &oct(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::oct() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(8) on \a stream and returns \a
stream.
@@ -2640,12 +2582,6 @@ QTextStream &oct(QTextStream &stream)
}
/*!
- \fn QTextStream &dec(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::dec() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(10) on \a stream and returns \a
stream.
@@ -2660,12 +2596,6 @@ QTextStream &dec(QTextStream &stream)
}
/*!
- \fn QTextStream &hex(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::hex() instead.
-*/
-
-/*!
Calls QTextStream::setIntegerBase(16) on \a stream and returns \a
stream.
@@ -2681,12 +2611,6 @@ QTextStream &hex(QTextStream &stream)
}
/*!
- \fn QTextStream &showbase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::showbase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ShowBase) on \a stream and returns \a stream.
@@ -2701,12 +2625,6 @@ QTextStream &showbase(QTextStream &stream)
}
/*!
- \fn QTextStream &forcesign(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::forcesign() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ForceSign) on \a stream and returns \a stream.
@@ -2721,12 +2639,6 @@ QTextStream &forcesign(QTextStream &stream)
}
/*!
- \fn QTextStream &forcepoint(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::forcepoint() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::ForcePoint) on \a stream and returns \a stream.
@@ -2741,12 +2653,6 @@ QTextStream &forcepoint(QTextStream &stream)
}
/*!
- \fn QTextStream &noshowbase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noshowbase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ShowBase) on \a stream and returns \a stream.
@@ -2761,12 +2667,6 @@ QTextStream &noshowbase(QTextStream &stream)
}
/*!
- \fn QTextStream &noforcesign(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noforcesign() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ForceSign) on \a stream and returns \a stream.
@@ -2781,12 +2681,6 @@ QTextStream &noforcesign(QTextStream &stream)
}
/*!
- \fn QTextStream &noforcepoint(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::noforcepoint() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::ForcePoint) on \a stream and returns \a stream.
@@ -2801,12 +2695,6 @@ QTextStream &noforcepoint(QTextStream &stream)
}
/*!
- \fn QTextStream &uppercasebase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::uppercasebase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::UppercaseBase) on \a stream and returns \a stream.
@@ -2821,12 +2709,6 @@ QTextStream &uppercasebase(QTextStream &stream)
}
/*!
- \fn QTextStream &uppercasedigits(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::uppercasedigits() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() |
QTextStream::UppercaseDigits) on \a stream and returns \a stream.
@@ -2841,12 +2723,6 @@ QTextStream &uppercasedigits(QTextStream &stream)
}
/*!
- \fn QTextStream &lowercasebase(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::lowercasebase() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::UppercaseBase) on \a stream and returns \a stream.
@@ -2861,12 +2737,6 @@ QTextStream &lowercasebase(QTextStream &stream)
}
/*!
- \fn QTextStream &lowercasedigits(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::lowercasedigits() instead.
-*/
-
-/*!
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() &
~QTextStream::UppercaseDigits) on \a stream and returns \a stream.
@@ -2881,12 +2751,6 @@ QTextStream &lowercasedigits(QTextStream &stream)
}
/*!
- \fn QTextStream &fixed(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::fixed() instead.
-*/
-
-/*!
Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation)
on \a stream and returns \a stream.
@@ -2901,12 +2765,6 @@ QTextStream &fixed(QTextStream &stream)
}
/*!
- \fn QTextStream &scientific(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::scientific() instead.
-*/
-
-/*!
Calls QTextStream::setRealNumberNotation(QTextStream::ScientificNotation)
on \a stream and returns \a stream.
@@ -2921,18 +2779,12 @@ QTextStream &scientific(QTextStream &stream)
}
/*!
- \fn QTextStream &left(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::left() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{right()}, {QTextStream::}{center()}, {QTextStream manipulators}
+ \sa right(), center(), {QTextStream manipulators}
*/
QTextStream &left(QTextStream &stream)
{
@@ -2941,18 +2793,12 @@ QTextStream &left(QTextStream &stream)
}
/*!
- \fn QTextStream &right(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::right() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{left()}, {QTextStream::}{center()}, {QTextStream manipulators}
+ \sa left(), center(), {QTextStream manipulators}
*/
QTextStream &right(QTextStream &stream)
{
@@ -2961,18 +2807,12 @@ QTextStream &right(QTextStream &stream)
}
/*!
- \fn QTextStream &center(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::center() instead.
-*/
-
-/*!
Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter)
on \a stream and returns \a stream.
\since 5.14
- \sa {QTextStream::}{left()}, {QTextStream::}{right()}, {QTextStream manipulators}
+ \sa left(), right(), {QTextStream manipulators}
*/
QTextStream &center(QTextStream &stream)
{
@@ -2981,12 +2821,6 @@ QTextStream &center(QTextStream &stream)
}
/*!
- \fn QTextStream &endl(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::endl() instead.
-*/
-
-/*!
Writes '\\n' to the \a stream and flushes the stream.
Equivalent to
@@ -3002,16 +2836,10 @@ QTextStream &center(QTextStream &stream)
*/
QTextStream &endl(QTextStream &stream)
{
- return stream << QLatin1Char('\n') << Qt::flush;
+ return stream << '\n'_L1 << Qt::flush;
}
/*!
- \fn QTextStream &flush(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::flush() instead.
-*/
-
-/*!
Calls QTextStream::flush() on \a stream and returns \a stream.
\since 5.14
@@ -3025,12 +2853,6 @@ QTextStream &flush(QTextStream &stream)
}
/*!
- \fn QTextStream &reset(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::reset() instead.
-*/
-
-/*!
Calls QTextStream::reset() on \a stream and returns \a stream.
\since 5.14
@@ -3044,12 +2866,6 @@ QTextStream &reset(QTextStream &stream)
}
/*!
- \fn QTextStream &ws(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::ws() instead.
-*/
-
-/*!
Calls \l {QTextStream::}{skipWhiteSpace()} on \a stream and returns \a stream.
\since 5.14
@@ -3088,12 +2904,6 @@ QTextStream &ws(QTextStream &stream)
namespace Qt {
/*!
- \fn QTextStream &bom(QTextStream &stream)
- \relates QTextStream
- \obsolete Use Qt::bom() instead.
-*/
-
-/*!
Toggles insertion of the Byte Order Mark on \a stream when QTextStream is
used with a UTF encoding.
@@ -3140,7 +2950,7 @@ void QTextStream::setEncoding(QStringConverter::Encoding encoding)
d->encoding = encoding;
d->toUtf16 = QStringDecoder(d->encoding);
- bool generateBOM = d->hasWrittenData && d->generateBOM;
+ bool generateBOM = !d->hasWrittenData && d->generateBOM;
d->fromUtf16 = QStringEncoder(d->encoding,
generateBOM ? QStringEncoder::Flag::WriteBom : QStringEncoder::Flag::Default);
@@ -3194,7 +3004,7 @@ bool QTextStream::autoDetectUnicode() const
device. If \a generate is false, no BOM will be inserted. This function
must be called before any data is written. Otherwise, it does nothing.
- \sa generateByteOrderMark(), bom()
+ \sa generateByteOrderMark(), {Qt::}{bom()}
*/
void QTextStream::setGenerateByteOrderMark(bool generate)
{
@@ -3249,78 +3059,6 @@ QLocale QTextStream::locale() const
return d->locale;
}
-#if QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC)
-// Deprecated source compatible migration versions:
-namespace QTextStreamFunctions {
-QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
-QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
-QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
-QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
-
-QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
-QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
-QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
-QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
-QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
-QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
-
-QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
-QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
-QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
-QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
-
-QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
-QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
-
-QTextStream &left(QTextStream &s) { return Qt::left(s); }
-QTextStream &right(QTextStream &s) { return Qt::right(s); }
-QTextStream &center(QTextStream &s) { return Qt::center(s); }
-
-QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
-QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
-QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
-
-QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-
-QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
-} // namespace QTextStreamFunctions
-#endif
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC)
-// Binary compatible definitions for Qt<5.14
-Q_CORE_EXPORT QTextStream &bin(QTextStream &s) { return Qt::bin(s); }
-Q_CORE_EXPORT QTextStream &oct(QTextStream &s) { return Qt::oct(s); }
-Q_CORE_EXPORT QTextStream &dec(QTextStream &s) { return Qt::dec(s); }
-Q_CORE_EXPORT QTextStream &hex(QTextStream &s) { return Qt::hex(s); }
-
-Q_CORE_EXPORT QTextStream &showbase(QTextStream &s) { return Qt::showbase(s); }
-Q_CORE_EXPORT QTextStream &forcesign(QTextStream &s) { return Qt::forcesign(s); }
-Q_CORE_EXPORT QTextStream &forcepoint(QTextStream &s) { return Qt::forcepoint(s); }
-Q_CORE_EXPORT QTextStream &noshowbase(QTextStream &s) { return Qt::noshowbase(s); }
-Q_CORE_EXPORT QTextStream &noforcesign(QTextStream &s) { return Qt::noforcesign(s); }
-Q_CORE_EXPORT QTextStream &noforcepoint(QTextStream &s) { return Qt::noforcepoint(s); }
-
-Q_CORE_EXPORT QTextStream &uppercasebase(QTextStream &s) { return Qt::uppercasebase(s); }
-Q_CORE_EXPORT QTextStream &uppercasedigits(QTextStream &s) { return Qt::uppercasedigits(s); }
-Q_CORE_EXPORT QTextStream &lowercasebase(QTextStream &s) { return Qt::lowercasebase(s); }
-Q_CORE_EXPORT QTextStream &lowercasedigits(QTextStream &s) { return Qt::lowercasedigits(s); }
-
-Q_CORE_EXPORT QTextStream &fixed(QTextStream &s) { return Qt::fixed(s); }
-Q_CORE_EXPORT QTextStream &scientific(QTextStream &s) { return Qt::scientific(s); }
-
-Q_CORE_EXPORT QTextStream &left(QTextStream &s) { return Qt::left(s); }
-Q_CORE_EXPORT QTextStream &right(QTextStream &s) { return Qt::right(s); }
-Q_CORE_EXPORT QTextStream &center(QTextStream &s) { return Qt::center(s); }
-
-Q_CORE_EXPORT QTextStream &endl(QTextStream &s) { return Qt::endl(s); }
-Q_CORE_EXPORT QTextStream &flush(QTextStream &s) { return Qt::flush(s); }
-Q_CORE_EXPORT QTextStream &reset(QTextStream &s) { return Qt::reset(s); }
-
-Q_CORE_EXPORT QTextStream &ws(QTextStream &s) { return Qt::ws(s); }
-
-Q_CORE_EXPORT QTextStream &bom(QTextStream &s) { return Qt::bom(s); }
-#endif
-
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index 1d13ed896c..7a0fc42a68 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -1,62 +1,43 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTSTREAM_H
#define QTEXTSTREAM_H
-#include <QtCore/qiodevice.h>
-#include <QtCore/qstring.h>
+#include <QtCore/qiodevicebase.h>
#include <QtCore/qchar.h>
-#include <QtCore/qlocale.h>
#include <QtCore/qscopedpointer.h>
-#include <QtCore/qstringconverter.h>
+#include <QtCore/qstringconverter_base.h>
#include <stdio.h>
+#if 0
+// the macros around the class name throw off syncqt:
+#pragma qt_class(QTextStream)
+#endif
+
#ifdef Status
#error qtextstream.h must be included before any header file that defines Status
#endif
QT_BEGIN_NAMESPACE
+class QIODevice;
+class QLocale;
+class QString;
+
+#if !QT_DEPRECATED_SINCE(6, 9)
+# define QT_NO_INHERITABLE_TEXT_STREAM
+#endif
+
+#ifdef QT_NO_INHERITABLE_TEXT_STREAM
+# define QT_TEXT_STREAM_FINAL final
+#else
+# define QT_TEXT_STREAM_FINAL
+#endif
+
class QTextStreamPrivate;
-class Q_CORE_EXPORT QTextStream // text stream class
+class Q_CORE_EXPORT QTextStream QT_TEXT_STREAM_FINAL : public QIODeviceBase
{
Q_DECLARE_PRIVATE(QTextStream)
@@ -89,11 +70,12 @@ public:
QTextStream();
explicit QTextStream(QIODevice *device);
- explicit QTextStream(FILE *fileHandle, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(QString *string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(QByteArray *array, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
- explicit QTextStream(const QByteArray &array, QIODevice::OpenMode openMode = QIODevice::ReadOnly);
- virtual ~QTextStream();
+ explicit QTextStream(FILE *fileHandle, OpenMode openMode = ReadWrite);
+ explicit QTextStream(QString *string, OpenMode openMode = ReadWrite);
+ explicit QTextStream(QByteArray *array, OpenMode openMode = ReadWrite);
+ explicit QTextStream(const QByteArray &array, OpenMode openMode = ReadOnly);
+ QT6_ONLY(virtual)
+ ~QTextStream();
void setEncoding(QStringConverter::Encoding encoding);
QStringConverter::Encoding encoding() const;
@@ -108,7 +90,7 @@ public:
void setDevice(QIODevice *device);
QIODevice *device() const;
- void setString(QString *string, QIODevice::OpenMode openMode = QIODevice::ReadWrite);
+ void setString(QString *string, OpenMode openMode = ReadWrite);
QString *string() const;
Status status() const;
@@ -151,6 +133,8 @@ public:
QTextStream &operator>>(QChar &ch);
QTextStream &operator>>(char &ch);
+ QTextStream &operator>>(char16_t &ch)
+ { QChar c; *this >> c; ch = c.unicode(); return *this; }
QTextStream &operator>>(signed short &i);
QTextStream &operator>>(unsigned short &i);
QTextStream &operator>>(signed int &i);
@@ -167,6 +151,7 @@ public:
QTextStream &operator<<(QChar ch);
QTextStream &operator<<(char ch);
+ QTextStream &operator<<(char16_t ch) { return *this << QChar(ch); }
QTextStream &operator<<(signed short i);
QTextStream &operator<<(unsigned short i);
QTextStream &operator<<(signed int i);
@@ -179,7 +164,7 @@ public:
QTextStream &operator<<(double f);
QTextStream &operator<<(const QString &s);
QTextStream &operator<<(QStringView s);
- QTextStream &operator<<(QLatin1String s);
+ QTextStream &operator<<(QLatin1StringView s);
QTextStream &operator<<(const QByteArray &array);
QTextStream &operator<<(const char *c);
QTextStream &operator<<(const void *ptr);
@@ -206,8 +191,8 @@ typedef void (QTextStream::*QTSMFC)(QChar); // manipulator w/QChar argument
class Q_CORE_EXPORT QTextStreamManipulator
{
public:
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFI m, int a) noexcept : mf(m), mc(nullptr), arg(a), ch() {}
- Q_DECL_CONSTEXPR QTextStreamManipulator(QTSMFC m, QChar c) noexcept : mf(nullptr), mc(m), arg(-1), ch(c) {}
+ constexpr QTextStreamManipulator(QTSMFI m, int a) noexcept : mf(m), mc(nullptr), arg(a), ch() {}
+ constexpr QTextStreamManipulator(QTSMFC m, QChar c) noexcept : mf(nullptr), mc(m), arg(-1), ch(c) {}
void exec(QTextStream &s) { if (mf) { (s.*mf)(arg); } else { (s.*mc)(ch); } }
private:
@@ -261,43 +246,6 @@ Q_CORE_EXPORT QTextStream &ws(QTextStream &s);
} // namespace Qt
-#if QT_DEPRECATED_SINCE(5, 15)
-// This namespace only exists for 'using namespace' declarations.
-namespace QTextStreamFunctions {
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::bin") QTextStream &bin(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::oct") QTextStream &oct(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::dec") QTextStream &dec(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::hex") QTextStream &hex(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::showbase") QTextStream &showbase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::forcesign") QTextStream &forcesign(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::forcepoint") QTextStream &forcepoint(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noshowbase") QTextStream &noshowbase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noforcesign") QTextStream &noforcesign(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::noforcepoint") QTextStream &noforcepoint(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::uppercasebase") QTextStream &uppercasebase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::uppercasedigits") QTextStream &uppercasedigits(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::lowercasebase") QTextStream &lowercasebase(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::lowercasedigits") QTextStream &lowercasedigits(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::fixed") QTextStream &fixed(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::scientific") QTextStream &scientific(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::left") QTextStream &left(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::right") QTextStream &right(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::center") QTextStream &center(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::endl") QTextStream &endl(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::flush") QTextStream &flush(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::reset") QTextStream &reset(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::bom") QTextStream &bom(QTextStream &s);
-Q_CORE_EXPORT QT_DEPRECATED_VERSION_X(5, 15, "Use Qt::ws") QTextStream &ws(QTextStream &s);
-} // namespace QTextStreamFunctions
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
-// We use 'using namespace' as that doesn't cause
-// conflicting definitions compiler errors.
-using namespace QTextStreamFunctions;
-QT_WARNING_POP
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
inline QTextStreamManipulator qSetFieldWidth(int width)
{
QTSMFI func = &QTextStream::setFieldWidth;
diff --git a/src/corelib/serialization/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h
index cee79a7ecf..909b75d0de 100644
--- a/src/corelib/serialization/qtextstream_p.h
+++ b/src/corelib/serialization/qtextstream_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTSTREAM_P_H
#define QTEXTSTREAM_P_H
@@ -53,6 +17,9 @@
//
#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qstringconverter.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qlocale.h>
#include "qtextstream.h"
QT_BEGIN_NAMESPACE
@@ -68,8 +35,13 @@ public:
inline void setupDevice(QTextStream *stream, QIODevice *device)
{
disconnect();
- if (device)
- connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()));
+ if (device) {
+ // Force direct connection here so that QTextStream can be used
+ // from multiple threads when the application code is handling
+ // synchronization (see also QTBUG-12055).
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(flushStream()),
+ Qt::DirectConnection);
+ }
this->stream = stream;
}
@@ -167,21 +139,25 @@ public:
NumberParsingStatus getNumber(qulonglong *l);
bool getReal(double *f);
- inline void write(const QString &data) { write(data.begin(), data.length()); }
+ inline void write(QStringView data) { write(data.begin(), data.size()); }
inline void write(QChar ch);
- void write(const QChar *data, int len);
- void write(QLatin1String data);
- void writePadding(int len);
- inline void putString(const QString &ch, bool number = false) { putString(ch.constData(), ch.length(), number); }
- void putString(const QChar *data, int len, bool number = false);
- void putString(QLatin1String data, bool number = false);
+ void write(const QChar *data, qsizetype len);
+ void write(QLatin1StringView data);
+ void writePadding(qsizetype len);
+ inline void putString(QStringView string, bool number = false)
+ {
+ putString(string.constData(), string.size(), number);
+ }
+ void putString(const QChar *data, qsizetype len, bool number = false);
+ void putString(QLatin1StringView data, bool number = false);
+ void putString(QUtf8StringView data, bool number = false);
inline void putChar(QChar ch);
void putNumber(qulonglong number, bool negative);
struct PaddingResult {
int left, right;
};
- PaddingResult padding(int len) const;
+ PaddingResult padding(qsizetype len) const;
// buffers
bool fillReadBuffer(qint64 maxBytes = -1);
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 21f80eec66..0fe8c87779 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "QtCore/qxmlstream.h"
-#ifndef QT_NO_XMLSTREAM
+#if QT_CONFIG(xmlstream)
#include "qxmlutils_p.h"
#include <qdebug.h>
@@ -49,31 +13,22 @@
#include <qstack.h>
#include <qbuffer.h>
#include <qscopeguard.h>
-#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
-#else
-// This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
-// because that header depends on QObject being available, which is not the
-// case for most bootstrapped applications.
-#define Q_DECLARE_TR_FUNCTIONS(context) \
-public: \
- static inline QString tr(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
- static inline QString trUtf8(const char *sourceText, const char *comment = nullptr) \
- { Q_UNUSED(comment); return QString::fromUtf8(sourceText); } \
- static inline QString tr(const char *sourceText, const char*, int) \
- { return QString::fromUtf8(sourceText); } \
- static inline QString trUtf8(const char *sourceText, const char*, int) \
- { return QString::fromUtf8(sourceText); } \
-private:
-#endif
-#include <private/qmemory_p.h>
+
+#include <private/qoffsetstringarray_p.h>
+#include <private/qtools_p.h>
#include <iterator>
+#include "qxmlstream_p.h"
+#include "qxmlstreamparser_p.h"
+#include <private/qstringconverter_p.h>
+#include <private/qstringiterator_p.h>
QT_BEGIN_NAMESPACE
-#include "qxmlstream_p.h"
+using namespace QtPrivate;
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
enum { StreamEOF = ~0U };
@@ -92,8 +47,62 @@ auto reversed(Range &r)
template <typename Range>
void reversed(const Range &&) = delete;
+
+// implementation of missing QUtf8StringView methods for ASCII-only needles:
+auto transform(QLatin1StringView haystack, char needle)
+{
+ struct R { QLatin1StringView haystack; char16_t needle; };
+ return R{haystack, uchar(needle)};
+}
+
+auto transform(QStringView haystack, char needle)
+{
+ struct R { QStringView haystack; char16_t needle; };
+ return R{haystack, uchar(needle)};
+}
+
+auto transform(QUtf8StringView haystack, char needle)
+{
+ struct R { QByteArrayView haystack; char needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QLatin1StringView haystack, QLatin1StringView needle)
+{
+ struct R { QLatin1StringView haystack; QLatin1StringView needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QStringView haystack, QLatin1StringView needle)
+{
+ struct R { QStringView haystack; QLatin1StringView needle; };
+ return R{haystack, needle};
+}
+
+auto transform(QUtf8StringView haystack, QLatin1StringView needle)
+{
+ struct R { QLatin1StringView haystack; QLatin1StringView needle; };
+ return R{QLatin1StringView{QByteArrayView{haystack}}, needle};
}
+#define WRAP(method, Needle) \
+ auto method (QAnyStringView s, Needle needle) noexcept \
+ { \
+ return s.visit([needle](auto s) { \
+ auto r = transform(s, needle); \
+ return r.haystack. method (r.needle); \
+ }); \
+ } \
+ /*end*/
+
+WRAP(count, char)
+WRAP(contains, char)
+WRAP(contains, QLatin1StringView)
+WRAP(endsWith, char)
+WRAP(indexOf, QLatin1StringView)
+
+} // unnamed namespace
+
/*!
\enum QXmlStreamReader::TokenType
@@ -132,7 +141,7 @@ void reversed(const Range &&) = delete;
\value DTD The reader reports a DTD in text(), notation
declarations in notationDeclarations(), and entity declarations in
entityDeclarations(). Details of the DTD declaration are reported
- in in dtdName(), dtdPublicId(), and dtdSystemId().
+ in dtdName(), dtdPublicId(), and dtdSystemId().
\value EntityReference The reader reports an entity reference that
could not be resolved. The name of the reference is reported in
@@ -177,7 +186,7 @@ void reversed(const Range &&) = delete;
addData() or by waiting for it to arrive on the device().
\value UnexpectedElementError The parser encountered an element
- that was different to those it expected.
+ or token that was different to those it expected.
*/
@@ -224,7 +233,7 @@ QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*
return QString();
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
{
@@ -280,6 +289,8 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
\ingroup xml-tools
+ \ingroup qtserialization
+
QXmlStreamReader provides a simple streaming API to parse well-formed
XML. It is an alternative to first loading the complete XML into a
DOM tree (see \l QDomDocument). QXmlStreamReader reads data either
@@ -312,13 +323,34 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
include external parsed entities. As long as no error occurs, the
- application code can thus be assured that the data provided by the
- stream reader satisfies the W3C's criteria for well-formed XML. For
- example, you can be certain that all tags are indeed nested and
- closed properly, that references to internal entities have been
- replaced with the correct replacement text, and that attributes have
- been normalized or added according to the internal subset of the
- DTD.
+ application code can thus be assured, that
+ \list
+ \li the data provided by the stream reader satisfies the W3C's
+ criteria for well-formed XML,
+ \li tokens are provided in a valid order.
+ \endlist
+
+ Unless QXmlStreamReader raises an error, it guarantees the following:
+ \list
+ \li All tags are nested and closed properly.
+ \li References to internal entities have been replaced with the
+ correct replacement text.
+ \li Attributes have been normalized or added according to the
+ internal subset of the \l DTD.
+ \li Tokens of type \l StartDocument happen before all others,
+ aside from comments and processing instructions.
+ \li At most one DOCTYPE element (a token of type \l DTD) is present.
+ \li If present, the DOCTYPE appears before all other elements,
+ aside from StartDocument, comments and processing instructions.
+ \endlist
+
+ In particular, once any token of type \l StartElement, \l EndElement,
+ \l Characters, \l EntityReference or \l EndDocument is seen, no
+ tokens of type StartDocument or DTD will be seen. If one is present in
+ the input stream, out of order, an error is raised.
+
+ \note The token types \l Comment and \l ProcessingInstruction may appear
+ anywhere in the stream.
If an error occurs while parsing, atEnd() and hasError() return
true, and error() returns the error that occurred. The functions
@@ -384,13 +416,9 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
token at the time it is reported. In addition, QXmlStreamReader
avoids the many small string allocations that it normally takes to
map an XML document to a convenient and Qt-ish API. It does this by
- reporting all string data as QStringRef rather than real QString
- objects. QStringRef is a thin wrapper around QString substrings that
- provides a subset of the QString API without the memory allocation
- and reference-counting overhead. Calling
- \l{QStringRef::toString()}{toString()} on any of those objects
- returns an equivalent real QString object.
-
+ reporting all string data as QStringView rather than real QString
+ objects. Calling \l{QStringView::toString()}{toString()} on any of
+ those objects returns an equivalent real QString object.
*/
@@ -415,41 +443,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, PrivateConstructorTag)
: d_ptr(new QXmlStreamReaderPrivate(this))
{
Q_D(QXmlStreamReader);
- d->dataBuffer = QByteArray(data);
+ d->dataBuffer = data;
}
/*!
@@ -498,47 +540,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([this, d](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;
}
/*!
@@ -625,6 +681,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::readNext()
d->token = -1;
return readNext();
}
+ d->checkToken();
return d->type;
}
@@ -665,7 +722,7 @@ QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
bool QXmlStreamReader::readNextStartElement()
{
while (readNext() != Invalid) {
- if (isEndElement())
+ if (isEndElement() || isEndDocument())
return false;
else if (isStartElement())
return true;
@@ -695,59 +752,28 @@ void QXmlStreamReader::skipCurrentElement()
}
}
-/*
- * Use the following Perl script to generate the error string index list:
-===== PERL SCRIPT ====
-print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
-$counter = 0;
-$i = 0;
-while (<STDIN>) {
- chomp;
- print " \"$_\\0\"\n";
- $sizes[$i++] = $counter;
- $counter += length 1 + $_;
-}
-print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
-for ($j = 0; $j < $i; ++$j) {
- printf "$sizes[$j], ";
-}
-print "0\n};\n";
-===== PERL SCRIPT ====
-
- * The input data is as follows (copied from qxmlstream.h):
-NoToken
-Invalid
-StartDocument
-EndDocument
-StartElement
-EndElement
-Characters
-Comment
-DTD
-EntityReference
-ProcessingInstruction
-*/
-static const char QXmlStreamReader_tokenTypeString_string[] =
- "NoToken\0"
- "Invalid\0"
- "StartDocument\0"
- "EndDocument\0"
- "StartElement\0"
- "EndElement\0"
- "Characters\0"
- "Comment\0"
- "DTD\0"
- "EntityReference\0"
- "ProcessingInstruction\0";
-
-static const short QXmlStreamReader_tokenTypeString_indices[] = {
- 0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
-};
+static constexpr auto QXmlStreamReader_tokenTypeString = qOffsetStringArray(
+ "NoToken",
+ "Invalid",
+ "StartDocument",
+ "EndDocument",
+ "StartElement",
+ "EndElement",
+ "Characters",
+ "Comment",
+ "DTD",
+ "EntityReference",
+ "ProcessingInstruction"
+);
+static constexpr auto QXmlStreamReader_XmlContextString = qOffsetStringArray(
+ "Prolog",
+ "Body"
+);
/*!
\property QXmlStreamReader::namespaceProcessing
- The namespace-processing flag of the stream reader
+ \brief the namespace-processing flag of the stream reader.
This property controls whether or not the stream reader processes
namespaces. If enabled, the reader processes namespaces, otherwise
@@ -776,11 +802,19 @@ bool QXmlStreamReader::namespaceProcessing() const
QString QXmlStreamReader::tokenString() const
{
Q_D(const QXmlStreamReader);
- return QLatin1String(QXmlStreamReader_tokenTypeString_string +
- QXmlStreamReader_tokenTypeString_indices[d->type]);
+ return QLatin1StringView(QXmlStreamReader_tokenTypeString.at(d->type));
+}
+
+/*!
+ \internal
+ \return \param ctxt (Prolog/Body) as a string.
+ */
+static constexpr QLatin1StringView contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
+{
+ return QLatin1StringView(QXmlStreamReader_XmlContextString.at(static_cast<int>(ctxt)));
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
{
@@ -791,9 +825,10 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
namespaceDeclaration.prefix = addToStringStorage(u"xml");
namespaceDeclaration.namespaceUri = addToStringStorage(u"http://www.w3.org/XML/1998/namespace");
initialTagStackStringStorageSize = tagStackStringStorageSize;
+ tagsDone = false;
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
:q_ptr(q)
@@ -808,7 +843,7 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
init();
#define ADD_PREDEFINED(n, v) \
do { \
- Entity e = Entity::createLiteral(QLatin1String(n), QLatin1String(v)); \
+ Entity e = Entity::createLiteral(n##_L1, v##_L1); \
entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \
} while (false)
ADD_PREDEFINED("lt", "<");
@@ -822,12 +857,14 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
void QXmlStreamReaderPrivate::init()
{
scanDtd = false;
+ lastAttributeIsCData = false;
token = -1;
token_char = 0;
isEmptyElement = false;
isWhitespace = true;
isCDATA = false;
standalone = false;
+ hasStandalone = false;
tos = 0;
resumeReduction = 0;
state_stack[tos++] = 0;
@@ -864,6 +901,8 @@ void QXmlStreamReaderPrivate::init()
type = QXmlStreamReader::NoToken;
error = QXmlStreamReader::NoError;
+ currentContext = XmlContext::Prolog;
+ foundDTD = false;
}
/*
@@ -879,7 +918,7 @@ void QXmlStreamReaderPrivate::parseEntity(const QString &value)
if (!entityParser)
- entityParser = qt_make_unique<QXmlStreamReaderPrivate>(q);
+ entityParser = std::make_unique<QXmlStreamReaderPrivate>(q);
else
entityParser->init();
entityParser->inParseEntity = true;
@@ -974,8 +1013,8 @@ inline uint QXmlStreamReaderPrivate::peekChar()
*/
bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
{
- int pos = textBuffer.size();
- int oldLineNumber = lineNumber;
+ const qsizetype pos = textBuffer.size();
+ const auto oldLineNumber = lineNumber;
uint c;
while ((c = getChar()) != StreamEOF) {
@@ -1022,7 +1061,7 @@ bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
{
- int n = 0;
+ qsizetype n = 0;
while (str[n]) {
uint c = getChar();
if (c != ushort(str[n])) {
@@ -1035,12 +1074,11 @@ bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, b
}
++n;
}
- for (int i = 0; i < n; ++i)
- textBuffer += QChar(ushort(str[i]));
+ textBuffer += QLatin1StringView(str, n);
if (requireSpace) {
- int s = fastScanSpace();
+ const qsizetype s = fastScanSpace();
if (!s || atEnd) {
- int pos = textBuffer.size() - n - s;
+ qsizetype pos = textBuffer.size() - n - s;
putString(textBuffer, pos);
textBuffer.resize(pos);
return false;
@@ -1150,9 +1188,9 @@ bool QXmlStreamReaderPrivate::scanAttType()
encountered.
*/
-inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
+inline qsizetype QXmlStreamReaderPrivate::fastScanLiteralContent()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (ushort(c)) {
@@ -1174,7 +1212,7 @@ inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
case ' ':
case '\t':
if (normalizeLiterals)
- textBuffer += QLatin1Char(' ');
+ textBuffer += u' ';
else
textBuffer += QChar(c);
++n;
@@ -1193,16 +1231,16 @@ inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
putChar(c);
return n;
}
- textBuffer += QChar(c);
+ textBuffer += QChar(ushort(c));
++n;
}
}
return n;
}
-inline int QXmlStreamReaderPrivate::fastScanSpace()
+inline qsizetype QXmlStreamReaderPrivate::fastScanSpace()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (c) {
@@ -1233,9 +1271,9 @@ inline int QXmlStreamReaderPrivate::fastScanSpace()
Used for text nodes essentially. That is, characters appearing
inside elements.
*/
-inline int QXmlStreamReaderPrivate::fastScanContentCharList()
+inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
switch (ushort(c)) {
@@ -1246,7 +1284,7 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
return n;
case ']': {
isWhitespace = false;
- int pos = textBuffer.size();
+ const qsizetype pos = textBuffer.size();
textBuffer += QChar(ushort(c));
++n;
while ((c = getChar()) == ']') {
@@ -1256,7 +1294,7 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
if (c == 0) {
putString(textBuffer, pos);
textBuffer.resize(pos);
- } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
+ } else if (c == '>' && textBuffer.at(textBuffer.size() - 2) == u']') {
raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
} else {
putChar(c);
@@ -1297,11 +1335,18 @@ inline int QXmlStreamReaderPrivate::fastScanContentCharList()
return n;
}
-inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
+// Fast scan an XML attribute name (e.g. "xml:lang").
+inline std::optional<qsizetype> QXmlStreamReaderPrivate::fastScanName(Value *val)
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
+ if (n >= 4096) {
+ // This is too long to be a sensible name, and
+ // can exhaust memory, or the range of decltype(*prefix)
+ raiseNamePrefixTooLongError();
+ return std::nullopt;
+ }
switch (c) {
case '\n':
case ' ':
@@ -1329,16 +1374,16 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
case '+':
case '*':
putChar(c);
- if (prefix && *prefix == n+1) {
- *prefix = 0;
+ if (val && val->prefix == n + 1) {
+ val->prefix = 0;
putChar(':');
--n;
}
return n;
case ':':
- if (prefix) {
- if (*prefix == 0) {
- *prefix = n+2;
+ if (val) {
+ if (val->prefix == 0) {
+ val->prefix = qint16(n + 2);
} else { // only one colon allowed according to the namespace spec.
putChar(c);
return n;
@@ -1349,14 +1394,14 @@ inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
}
Q_FALLTHROUGH();
default:
- textBuffer += QChar(c);
+ textBuffer += QChar(ushort(c));
++n;
}
}
- if (prefix)
- *prefix = 0;
- int pos = textBuffer.size() - n;
+ if (val)
+ val->prefix = 0;
+ qsizetype pos = textBuffer.size() - n;
putString(textBuffer, pos);
textBuffer.resize(pos);
return 0;
@@ -1413,9 +1458,9 @@ static inline NameChar fastDetermineNameChar(QChar ch)
return NotName;
}
-inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
+inline qsizetype QXmlStreamReaderPrivate::fastScanNMTOKEN()
{
- int n = 0;
+ qsizetype n = 0;
uint c;
while ((c = getChar()) != StreamEOF) {
if (fastDetermineNameChar(QChar(c)) == NotName) {
@@ -1427,7 +1472,7 @@ inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
}
}
- int pos = textBuffer.size() - n;
+ qsizetype pos = textBuffer.size() - n;
putString(textBuffer, pos);
textBuffer.resize(pos);
@@ -1479,10 +1524,11 @@ void QXmlStreamReaderPrivate::putReplacementInAttributeValue(QStringView s)
uint QXmlStreamReaderPrivate::getChar_helper()
{
- const int BUFFER_SIZE = 8192;
+ constexpr qsizetype BUFFER_SIZE = 8192;
characterOffset += readBufferPos;
readBufferPos = 0;
- readBuffer.resize(0);
+ if (readBuffer.size())
+ readBuffer.resize(0);
if (decoder.isValid())
nbytesread = 0;
if (device) {
@@ -1508,14 +1554,14 @@ uint QXmlStreamReaderPrivate::getChar_helper()
atEnd = true;
return StreamEOF;
}
- auto encoding = QStringDecoder::encodingForData(rawReadBuffer.constData(), rawReadBuffer.size(), char16_t('<'));
+ auto encoding = QStringDecoder::encodingForData(rawReadBuffer, char16_t('<'));
if (!encoding)
// assume utf-8
encoding = QStringDecoder::Utf8;
decoder = QStringDecoder(*encoding);
}
- readBuffer = decoder(rawReadBuffer.constData(), nbytesread);
+ readBuffer = decoder(QByteArrayView(rawReadBuffer).first(nbytesread));
if (lockEncoding && decoder.hasError()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
@@ -1534,7 +1580,7 @@ uint QXmlStreamReaderPrivate::getChar_helper()
return StreamEOF;
}
-QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
+XmlStringRef QXmlStreamReaderPrivate::namespaceForPrefix(QStringView prefix)
{
for (const NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.prefix == prefix) {
@@ -1547,7 +1593,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix));
#endif
- return QStringRef();
+ return XmlStringRef();
}
/*
@@ -1570,25 +1616,25 @@ void QXmlStreamReaderPrivate::resolveTag()
++i;
if (i != n)
continue;
- if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
+ if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == "xmlns"_L1) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
- const QStringRef ns(dtdAttribute.defaultValue);
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ const XmlStringRef ns(dtdAttribute.defaultValue);
+ if (ns == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns == "http://www.w3.org/XML/1998/namespace"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
else
namespaceDeclaration.namespaceUri = ns;
- } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
+ } else if (dtdAttribute.attributePrefix == "xmlns"_L1) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = dtdAttribute.attributeName;
- QStringRef namespaceUri = dtdAttribute.defaultValue;
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
+ XmlStringRef namespacePrefix = dtdAttribute.attributeName;
+ XmlStringRef namespaceUri = dtdAttribute.defaultValue;
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
|| namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
+ || namespacePrefix == "xmlns"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
namespaceDeclaration.prefix = namespacePrefix;
@@ -1604,18 +1650,18 @@ void QXmlStreamReaderPrivate::resolveTag()
for (qsizetype i = 0; i < n; ++i) {
QXmlStreamAttribute &attribute = attributes[i];
Attribute &attrib = attributeStack[i];
- QStringRef prefix(symPrefix(attrib.key));
- QStringRef name(symString(attrib.key));
- QStringRef qualifiedName(symName(attrib.key));
- QStringRef value(symString(attrib.value));
+ XmlStringRef prefix(symPrefix(attrib.key));
+ XmlStringRef name(symString(attrib.key));
+ XmlStringRef qualifiedName(symName(attrib.key));
+ XmlStringRef value(symString(attrib.value));
- attribute.m_name = QXmlStreamStringRef(name);
- attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
- attribute.m_value = QXmlStreamStringRef(value);
+ attribute.m_name = name;
+ attribute.m_qualifiedName = qualifiedName;
+ attribute.m_value = value;
if (!prefix.isEmpty()) {
- QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
- attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ XmlStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
+ attribute.m_namespaceUri = XmlStringRef(attributeNamespaceUri);
}
for (qsizetype j = 0; j < i; ++j) {
@@ -1644,13 +1690,13 @@ void QXmlStreamReaderPrivate::resolveTag()
QXmlStreamAttribute attribute;
- attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
- attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
- attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
+ attribute.m_name = dtdAttribute.attributeName;
+ attribute.m_qualifiedName = dtdAttribute.attributeQualifiedName;
+ attribute.m_value = dtdAttribute.defaultValue;
if (!dtdAttribute.attributePrefix.isEmpty()) {
- QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
- attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
+ XmlStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
+ attribute.m_namespaceUri = XmlStringRef(attributeNamespaceUri);
}
attribute.m_isDefault = true;
attributes.append(std::move(attribute));
@@ -1665,8 +1711,8 @@ void QXmlStreamReaderPrivate::resolvePublicNamespaces()
for (qsizetype i = 0; i < n; ++i) {
const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
- publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
- publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
+ publicNamespaceDeclaration.m_prefix = namespaceDeclaration.prefix;
+ publicNamespaceDeclaration.m_namespaceUri = namespaceDeclaration.namespaceUri;
}
}
@@ -1676,9 +1722,9 @@ void QXmlStreamReaderPrivate::resolveDtd()
for (qsizetype i = 0; i < notationDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
- publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
- publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
- publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
+ publicNotationDeclaration.m_name = notationDeclaration.name;
+ publicNotationDeclaration.m_systemId = notationDeclaration.systemId;
+ publicNotationDeclaration.m_publicId = notationDeclaration.publicId;
}
notationDeclarations.clear();
@@ -1686,11 +1732,11 @@ void QXmlStreamReaderPrivate::resolveDtd()
for (qsizetype i = 0; i < entityDeclarations.size(); ++i) {
const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
- publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
- publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
- publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
- publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
- publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
+ publicEntityDeclaration.m_name = entityDeclaration.name;
+ publicEntityDeclaration.m_notationName = entityDeclaration.notationName;
+ publicEntityDeclaration.m_systemId = entityDeclaration.systemId;
+ publicEntityDeclaration.m_publicId = entityDeclaration.publicId;
+ publicEntityDeclaration.m_value = entityDeclaration.value;
}
entityDeclarations.clear();
parameterEntityHash.clear();
@@ -1700,11 +1746,11 @@ uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
{
bool ok = true;
uint s;
- // ### add toXShort to QStringRef?
+ // ### add toXShort to XmlString?
if (sym(symbolIndex).c == 'x')
- s = symString(symbolIndex, 1).toUInt(&ok, 16);
+ s = symString(symbolIndex, 1).view().toUInt(&ok, 16);
else
- s = symString(symbolIndex).toUInt(&ok, 10);
+ s = symString(symbolIndex).view().toUInt(&ok, 10);
ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
|| (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= QChar::LastValidCodePoint));
@@ -1713,13 +1759,13 @@ uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
}
-void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
+void QXmlStreamReaderPrivate::checkPublicLiteral(QStringView publicId)
{
//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
- const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
+ const char16_t *data = publicId.utf16();
uchar c = 0;
- int i;
+ qsizetype i;
for (i = publicId.size() - 1; i >= 0; --i) {
if (data[i] < 256)
switch ((c = data[i])) {
@@ -1729,9 +1775,7 @@ void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
case '$': case '_': case '%': case '\'': case '\"':
continue;
default:
- if ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9'))
+ if (isAsciiLetterOrNumber(c))
continue;
}
break;
@@ -1763,8 +1807,8 @@ bool QXmlStreamReaderPrivate::checkStartDocument()
void QXmlStreamReaderPrivate::startDocument()
{
QString err;
- if (documentVersion != QLatin1String("1.0")) {
- if (documentVersion.contains(QLatin1Char(' ')))
+ if (documentVersion != "1.0"_L1) {
+ if (documentVersion.view().contains(u' '))
err = QXmlStream::tr("Invalid XML version string.");
else
err = QXmlStream::tr("Unsupported XML version.");
@@ -1775,18 +1819,17 @@ void QXmlStreamReaderPrivate::startDocument()
* proper order:
*
* [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
- bool hasStandalone = false;
for (qsizetype i = 0; err.isNull() && i < n; ++i) {
Attribute &attrib = attributeStack[i];
- QStringRef prefix(symPrefix(attrib.key));
- QStringRef key(symString(attrib.key));
- QStringRef value(symString(attrib.value));
+ XmlStringRef prefix(symPrefix(attrib.key));
+ XmlStringRef key(symString(attrib.key));
+ XmlStringRef value(symString(attrib.value));
- if (prefix.isEmpty() && key == QLatin1String("encoding")) {
+ if (prefix.isEmpty() && key == "encoding"_L1) {
documentEncoding = value;
- if(hasStandalone)
+ if (hasStandalone)
err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
if (!QXmlUtils::isEncName(value))
err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
@@ -1797,20 +1840,20 @@ void QXmlStreamReaderPrivate::startDocument()
if (!decoder.isValid()) {
err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
} else {
- readBuffer = decoder(rawReadBuffer.data(), nbytesread);
+ readBuffer = decoder(QByteArrayView(rawReadBuffer).first(nbytesread));
}
}
}
- } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
+ } else if (prefix.isEmpty() && key == "standalone"_L1) {
hasStandalone = true;
- if (value == QLatin1String("yes"))
+ if (value == "yes"_L1)
standalone = true;
- else if (value == QLatin1String("no"))
+ else if (value == "no"_L1)
standalone = false;
else
err = QXmlStream::tr("Standalone accepts only yes or no.");
} else {
- err = QXmlStream::tr("Invalid attribute in XML declaration.");
+ err = QXmlStream::tr("Invalid attribute in XML declaration: %1 = %2").arg(key).arg(value);
}
}
@@ -1839,6 +1882,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
raiseError(QXmlStreamReader::NotWellFormedError, message);
}
+void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
+{
+ // TODO: add a ImplementationLimitsExceededError and use it instead
+ raiseError(QXmlStreamReader::NotWellFormedError,
+ QXmlStream::tr("Length of XML attribute name exceeds implementation limits (4KiB "
+ "characters)."));
+}
+
void QXmlStreamReaderPrivate::parseError()
{
@@ -1851,7 +1902,7 @@ void QXmlStreamReaderPrivate::parseError()
int ers = state_stack[tos];
int nexpected = 0;
int expected[nmax];
- if (token != ERROR)
+ if (token != XML_ERROR)
for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
int k = t_action(ers, tk);
if (k <= 0)
@@ -1864,22 +1915,27 @@ void QXmlStreamReaderPrivate::parseError()
if (nexpected && nexpected < nmax) {
//: '<first option>'
- QString exp_str = QXmlStream::tr("'%1'", "expected").arg(QLatin1String(spell[expected[0]]));
+ QString exp_str = QXmlStream::tr("'%1'", "expected")
+ .arg(QLatin1StringView(spell[expected[0]]));
if (nexpected == 2) {
//: <first option>, '<second option>'
- exp_str = QXmlStream::tr("%1 or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[1]]));
+ exp_str = QXmlStream::tr("%1 or '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[1]]));
} else if (nexpected > 2) {
int s = 1;
for (; s < nexpected - 1; ++s) {
//: <options so far>, '<next option>'
- exp_str = QXmlStream::tr("%1, '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
+ exp_str = QXmlStream::tr("%1, '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[s]]));
}
//: <options so far>, or '<final option>'
- exp_str = QXmlStream::tr("%1, or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
+ exp_str = QXmlStream::tr("%1, or '%2'", "expected")
+ .arg(exp_str, QLatin1StringView(spell[expected[s]]));
}
- error_message = QXmlStream::tr("Expected %1, but got '%2'.").arg(exp_str, QLatin1String(spell[token]));
+ error_message = QXmlStream::tr("Expected %1, but got '%2'.")
+ .arg(exp_str, QLatin1StringView(spell[token]));
} else {
- error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1String(spell[token]));
+ error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1StringView(spell[token]));
}
raiseWellFormedError(error_message);
@@ -1925,7 +1981,7 @@ qint64 QXmlStreamReader::characterOffset() const
/*! Returns the text of \l Characters, \l Comment, \l DTD, or
EntityReference.
*/
-QStringRef QXmlStreamReader::text() const
+QStringView QXmlStreamReader::text() const
{
Q_D(const QXmlStreamReader);
return d->text;
@@ -1968,12 +2024,12 @@ QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
name. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdName() const
+QStringView QXmlStreamReader::dtdName() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdName;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -1983,12 +2039,12 @@ QStringRef QXmlStreamReader::dtdName() const
public identifier. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdPublicId() const
+QStringView QXmlStreamReader::dtdPublicId() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdPublicId;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -1998,12 +2054,12 @@ QStringRef QXmlStreamReader::dtdPublicId() const
system identifier. Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::dtdSystemId() const
+QStringView QXmlStreamReader::dtdSystemId() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::DTD)
return d->dtdSystemId;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -2118,7 +2174,7 @@ QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
switch (readNext()) {
case Characters:
case EntityReference:
- result.insert(result.size(), d->text.unicode(), d->text.size());
+ result.insert(result.size(), d->text);
break;
case EndElement:
return result;
@@ -2184,7 +2240,7 @@ QXmlStreamReader::Error QXmlStreamReader::error() const
/*!
Returns the target of a ProcessingInstruction.
*/
-QStringRef QXmlStreamReader::processingInstructionTarget() const
+QStringView QXmlStreamReader::processingInstructionTarget() const
{
Q_D(const QXmlStreamReader);
return d->processingInstructionTarget;
@@ -2193,7 +2249,7 @@ QStringRef QXmlStreamReader::processingInstructionTarget() const
/*!
Returns the data of a ProcessingInstruction.
*/
-QStringRef QXmlStreamReader::processingInstructionData() const
+QStringView QXmlStreamReader::processingInstructionData() const
{
Q_D(const QXmlStreamReader);
return d->processingInstructionData;
@@ -2206,7 +2262,7 @@ QStringRef QXmlStreamReader::processingInstructionData() const
\sa namespaceUri(), qualifiedName()
*/
-QStringRef QXmlStreamReader::name() const
+QStringView QXmlStreamReader::name() const
{
Q_D(const QXmlStreamReader);
return d->name;
@@ -2217,7 +2273,7 @@ QStringRef QXmlStreamReader::name() const
\sa name(), qualifiedName()
*/
-QStringRef QXmlStreamReader::namespaceUri() const
+QStringView QXmlStreamReader::namespaceUri() const
{
Q_D(const QXmlStreamReader);
return d->namespaceUri;
@@ -2235,7 +2291,7 @@ QStringRef QXmlStreamReader::namespaceUri() const
\sa name(), prefix(), namespaceUri()
*/
-QStringRef QXmlStreamReader::qualifiedName() const
+QStringView QXmlStreamReader::qualifiedName() const
{
Q_D(const QXmlStreamReader);
return d->qualifiedName;
@@ -2250,7 +2306,7 @@ QStringRef QXmlStreamReader::qualifiedName() const
\sa name(), qualifiedName()
*/
-QStringRef QXmlStreamReader::prefix() const
+QStringView QXmlStreamReader::prefix() const
{
Q_D(const QXmlStreamReader);
return d->prefix;
@@ -2265,7 +2321,7 @@ QXmlStreamAttributes QXmlStreamReader::attributes() const
return d->attributes;
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
/*!
\class QXmlStreamAttribute
@@ -2276,6 +2332,8 @@ QXmlStreamAttributes QXmlStreamReader::attributes() const
\ingroup xml-tools
+ \compares equality
+
An attribute consists of an optionally empty namespaceUri(), a
name(), a value(), and an isDefault() attribute.
@@ -2290,24 +2348,15 @@ QXmlStreamAttribute::QXmlStreamAttribute()
m_isDefault = false;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Destructs an attribute.
- */
-QXmlStreamAttribute::~QXmlStreamAttribute()
-{
-}
-#endif
-
/*! Constructs an attribute in the namespace described with \a
namespaceUri with \a name and value \a value.
*/
QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value)
{
- m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
- m_name = m_qualifiedName = QXmlStreamStringRef(QStringRef(&name));
- m_value = QXmlStreamStringRef(QStringRef(&value));
- m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
+ m_namespaceUri = namespaceUri;
+ m_name = m_qualifiedName = name;
+ m_value = value;
+ m_namespaceUri = namespaceUri;
}
/*!
@@ -2315,23 +2364,21 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QStr
*/
QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QString &value)
{
- int colon = qualifiedName.indexOf(QLatin1Char(':'));
- m_name = QXmlStreamStringRef(QStringRef(&qualifiedName,
- colon + 1,
- qualifiedName.size() - (colon + 1)));
- m_qualifiedName = QXmlStreamStringRef(QStringRef(&qualifiedName));
- m_value = QXmlStreamStringRef(QStringRef(&value));
+ qsizetype colon = qualifiedName.indexOf(u':');
+ m_name = qualifiedName.mid(colon + 1);
+ m_qualifiedName = qualifiedName;
+ m_value = value;
}
-/*! \fn QStringRef QXmlStreamAttribute::namespaceUri() const
+/*! \fn QStringView QXmlStreamAttribute::namespaceUri() const
Returns the attribute's resolved namespaceUri, or an empty string
reference if the attribute does not have a defined namespace.
*/
-/*! \fn QStringRef QXmlStreamAttribute::name() const
+/*! \fn QStringView QXmlStreamAttribute::name() const
Returns the attribute's local name.
*/
-/*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
+/*! \fn QStringView QXmlStreamAttribute::qualifiedName() const
Returns the attribute's qualified name.
A qualified name is the raw name of an attribute in the XML
@@ -2343,7 +2390,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
the attribute's local name().
*/
/*!
- \fn QStringRef QXmlStreamAttribute::prefix() const
+ \fn QStringView QXmlStreamAttribute::prefix() const
\since 4.4
Returns the attribute's namespace prefix.
@@ -2351,7 +2398,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
*/
-/*! \fn QStringRef QXmlStreamAttribute::value() const
+/*! \fn QStringView QXmlStreamAttribute::value() const
Returns the attribute's value.
*/
@@ -2361,41 +2408,17 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt
value following an ATTLIST declaration in the DTD; otherwise
returns \c false.
*/
-/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
+/*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &lhs, const QXmlStreamAttribute &rhs)
- Compares this attribute with \a other and returns \c true if they are
+ Compares \a lhs attribute with \a rhs and returns \c true if they are
equal; otherwise returns \c false.
*/
-/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
+/*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &lhs, const QXmlStreamAttribute &rhs)
- Compares this attribute with \a other and returns \c true if they are
+ Compares \a lhs attribute with \a rhs and returns \c true if they are
not equal; otherwise returns \c false.
*/
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this attribute.
- */
-QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
-{
- m_name = other.m_name;
- m_namespaceUri = other.m_namespaceUri;
- m_qualifiedName = other.m_qualifiedName;
- m_value = other.m_value;
- m_isDefault = other.m_isDefault;
- return *this;
-}
-#endif
-
/*!
\class QXmlStreamAttributes
\inmodule QtCore
@@ -2441,6 +2464,8 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o
\ingroup xml-tools
+ \compares equality
+
An notation declaration consists of a name(), a systemId(), and a publicId().
*/
@@ -2451,55 +2476,27 @@ QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
{
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this notation declaration.
- */
-QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
-{
- m_name = other.m_name;
- m_systemId = other.m_systemId;
- m_publicId = other.m_publicId;
- return *this;
-}
-
-/*!
-Destructs this notation declaration.
-*/
-QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
-{
-}
-#endif
-
-/*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::name() const
Returns the notation name.
*/
-/*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::systemId() const
Returns the system identifier.
*/
-/*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
+/*! \fn QStringView QXmlStreamNotationDeclaration::publicId() const
Returns the public identifier.
*/
-/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &lhs, const QXmlStreamNotationDeclaration &rhs)
- Compares this notation declaration with \a other and returns \c true
+ Compares \a lhs notation declaration with \a rhs and returns \c true
if they are equal; otherwise returns \c false.
*/
-/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
+/*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &lhs, const QXmlStreamNotationDeclaration &rhs)
- Compares this notation declaration with \a other and returns \c true
+ Compares \a lhs notation declaration with \a rhs and returns \c true
if they are not equal; otherwise returns \c false.
*/
@@ -2519,16 +2516,18 @@ Returns the public identifier.
\ingroup xml-tools
+ \compares equality
+
An namespace declaration consists of a prefix() and a namespaceUri().
*/
-/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &lhs, const QXmlStreamNamespaceDeclaration &rhs)
- Compares this namespace declaration with \a other and returns \c true
+ Compares \a lhs namespace declaration with \a rhs and returns \c true
if they are equal; otherwise returns \c false.
*/
-/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
+/*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &lhs, const QXmlStreamNamespaceDeclaration &rhs)
- Compares this namespace declaration with \a other and returns \c true
+ Compares \a lhs namespace declaration with \a rhs and returns \c true
if they are not equal; otherwise returns \c false.
*/
@@ -2550,37 +2549,11 @@ QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &pr
m_namespaceUri = namespaceUri;
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this namespace declaration.
- */
-QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
-{
- m_prefix = other.m_prefix;
- m_namespaceUri = other.m_namespaceUri;
- return *this;
-}
-/*!
-Destructs this namespace declaration.
-*/
-QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
-{
-}
-#endif
-
-/*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
+/*! \fn QStringView QXmlStreamNamespaceDeclaration::prefix() const
Returns the prefix.
*/
-/*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
+/*! \fn QStringView QXmlStreamNamespaceDeclaration::namespaceUri() const
Returns the namespaceUri.
*/
@@ -2596,9 +2569,9 @@ Returns the namespaceUri.
*/
/*!
- \class QXmlStreamStringRef
+ \class QXmlString
\inmodule QtCore
- \since 4.3
+ \since 6.0
\internal
*/
@@ -2611,6 +2584,7 @@ Returns the namespaceUri.
\ingroup xml-tools
+ \compares equality
An entity declaration consists of a name(), a notationName(), a
systemId(), a publicId(), and a value().
*/
@@ -2622,114 +2596,52 @@ QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
{
}
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-/*!
- Creates a copy of \a other.
- */
-QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
-{
- *this = other;
-}
-
-/*!
- Assigns \a other to this entity declaration.
- */
-QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
-{
- m_name = other.m_name;
- m_notationName = other.m_notationName;
- m_systemId = other.m_systemId;
- m_publicId = other.m_publicId;
- m_value = other.m_value;
- return *this;
-}
-
-/*!
- Destructs this entity declaration.
-*/
-QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
-{
-}
-#endif
-
-/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other)
- \since 5.6
-
- Swaps this string reference's contents with \a other.
- This function is very fast and never fails.
-*/
-
-/*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::name() const
Returns the entity name.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::notationName() const
Returns the notation name.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::systemId() const
Returns the system identifier.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::publicId() const
Returns the public identifier.
*/
-/*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
+/*! \fn QStringView QXmlStreamEntityDeclaration::value() const
Returns the entity's value.
*/
-/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
+/*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &lhs, const QXmlStreamEntityDeclaration &rhs)
- Compares this entity declaration with \a other and returns \c true if
+ Compares \a lhs entity declaration with \a rhs and returns \c true if
they are equal; otherwise returns \c false.
*/
-/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
+/*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &lhs, const QXmlStreamEntityDeclaration &rhs)
- Compares this entity declaration with \a other and returns \c true if
+ Compares \a lhs entity declaration with \a rhs and returns \c true if
they are not equal; otherwise returns \c false.
*/
/*! Returns the value of the attribute \a name in the namespace
described with \a namespaceUri, or an empty string reference if the
attribute is not defined. The \a namespaceUri can be empty.
- */
-QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
- return attribute.value();
- }
- return QStringRef();
-}
-
-/*!\overload
- Returns the value of the attribute \a name in the namespace
- described with \a namespaceUri, or an empty string reference if the
- attribute is not defined. The \a namespaceUri can be empty.
- */
-QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, QLatin1String name) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
- return attribute.value();
- }
- return QStringRef();
-}
-/*!\overload
- Returns the value of the attribute \a name in the namespace
- described with \a namespaceUri, or an empty string reference if the
- attribute is not defined. The \a namespaceUri can be empty.
+ \note In Qt versions prior to 6.6, this function was implemented as an
+ overload set accepting combinations of QString and QLatin1StringView only.
*/
-QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String name) const
+QStringView QXmlStreamAttributes::value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept
{
for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
return attribute.value();
}
- return QStringRef();
+ return QStringView();
}
/*!\overload
@@ -2743,35 +2655,18 @@ QStringRef QXmlStreamAttributes::value(QLatin1String namespaceUri, QLatin1String
different prefixes can point to the same namespace), you shouldn't
use qualified names, but a resolved namespaceUri and the attribute's
local name.
- */
-QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
-{
- for (const QXmlStreamAttribute &attribute : *this) {
- if (attribute.qualifiedName() == qualifiedName)
- return attribute.value();
- }
- return QStringRef();
-}
-/*!\overload
+ \note In Qt versions prior to 6.6, this function was implemented as an
+ overload set accepting QString and QLatin1StringView only.
- Returns the value of the attribute with qualified name \a
- qualifiedName , or an empty string reference if the attribute is not
- defined. A qualified name is the raw name of an attribute in the XML
- data. It consists of the namespace prefix, followed by colon,
- followed by the attribute's local name. Since the namespace prefix
- is not unique (the same prefix can point to different namespaces and
- different prefixes can point to the same namespace), you shouldn't
- use qualified names, but a resolved namespaceUri and the attribute's
- local name.
*/
-QStringRef QXmlStreamAttributes::value(QLatin1String qualifiedName) const
+QStringView QXmlStreamAttributes::value(QAnyStringView qualifiedName) const noexcept
{
for (const QXmlStreamAttribute &attribute : *this) {
if (attribute.qualifiedName() == qualifiedName)
return attribute.value();
}
- return QStringRef();
+ return QStringView();
}
/*!Appends a new attribute with \a name in the namespace
@@ -2792,7 +2687,7 @@ void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &v
append(QXmlStreamAttribute(qualifiedName, value));
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
/*! \fn bool QXmlStreamReader::isStartDocument() const
Returns \c true if tokenType() equals \l StartDocument; otherwise returns \c false.
@@ -2853,6 +2748,8 @@ bool QXmlStreamReader::isCDATA() const
XML declaration; otherwise returns \c false.
If no XML declaration has been parsed, this function returns \c false.
+
+ \sa hasStandaloneDeclaration()
*/
bool QXmlStreamReader::isStandaloneDocument() const
{
@@ -2860,6 +2757,21 @@ bool QXmlStreamReader::isStandaloneDocument() const
return d->standalone;
}
+/*!
+ \since 6.6
+
+ Returns \c true if this document has an explicit standalone
+ declaration (can be 'yes' or 'no'); otherwise returns \c false;
+
+ If no XML declaration has been parsed, this function returns \c false.
+
+ \sa isStandaloneDocument()
+ */
+bool QXmlStreamReader::hasStandaloneDeclaration() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->hasStandalone;
+}
/*!
\since 4.4
@@ -2868,12 +2780,12 @@ bool QXmlStreamReader::isStandaloneDocument() const
version string as specified in the XML declaration.
Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::documentVersion() const
+QStringView QXmlStreamReader::documentVersion() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::StartDocument)
return d->documentVersion;
- return QStringRef();
+ return QStringView();
}
/*!
@@ -2883,15 +2795,15 @@ QStringRef QXmlStreamReader::documentVersion() const
encoding string as specified in the XML declaration.
Otherwise an empty string is returned.
*/
-QStringRef QXmlStreamReader::documentEncoding() const
+QStringView QXmlStreamReader::documentEncoding() const
{
Q_D(const QXmlStreamReader);
if (d->type == QXmlStreamReader::StartDocument)
return d->documentEncoding;
- return QStringRef();
+ return QStringView();
}
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
/*!
\class QXmlStreamWriter
@@ -2903,6 +2815,7 @@ QStringRef QXmlStreamReader::documentEncoding() const
simple streaming API.
\ingroup xml-tools
+ \ingroup qtserialization
QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
XML. Like its related class, it operates on a QIODevice specified
@@ -2967,25 +2880,29 @@ QStringRef QXmlStreamReader::documentEncoding() const
*/
-#ifndef QT_NO_XMLSTREAMWRITER
+#if QT_CONFIG(xmlstreamwriter)
-class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
+class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack
+{
QXmlStreamWriter *q_ptr;
Q_DECLARE_PUBLIC(QXmlStreamWriter)
public:
+ enum class StartElementOption {
+ KeepEverything = 0, // write out every attribute, namespace, &c.
+ OmitNamespaceDeclarations = 1,
+ };
+
QXmlStreamWriterPrivate(QXmlStreamWriter *q);
~QXmlStreamWriterPrivate() {
if (deleteDevice)
delete device;
}
- void write(const QStringRef &);
- void write(const QString &);
- void writeEscaped(const QString &, bool escapeWhitespace = false);
- void write(const char *s, int len);
- template <int N> void write(const char (&s)[N]) { write(s, N - 1); }
+ void write(QAnyStringView s);
+ void writeEscaped(QAnyStringView, bool escapeWhitespace = false);
bool finishStartElement(bool contents = true);
- void writeStartElement(const QString &namespaceUri, const QString &name);
+ void writeStartElement(QAnyStringView namespaceUri, QAnyStringView name,
+ StartElementOption option = StartElementOption::KeepEverything);
QIODevice *device;
QString *stringDevice;
uint deleteDevice :1;
@@ -2996,23 +2913,26 @@ public:
uint hasIoError :1;
uint hasEncodingError :1;
uint autoFormatting :1;
- QByteArray autoFormattingIndent;
+ std::string autoFormattingIndent;
NamespaceDeclaration emptyNamespace;
qsizetype lastNamespaceDeclaration;
- QStringEncoder toUtf8;
- NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
+ NamespaceDeclaration &addExtraNamespace(QAnyStringView namespaceUri, QAnyStringView prefix);
+ NamespaceDeclaration &findNamespace(QAnyStringView namespaceUri, bool writeDeclaration = false, bool noDefault = false);
void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
int namespacePrefixCount;
void indent(int level);
+private:
+ void doWriteToDevice(QStringView s);
+ void doWriteToDevice(QUtf8StringView s);
+ void doWriteToDevice(QLatin1StringView s);
};
QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
- : autoFormattingIndent(4, ' '),
- toUtf8(QStringEncoder::Utf8, QStringEncoder::Flag::Stateless)
+ : autoFormattingIndent(4, ' ')
{
q_ptr = q;
device = nullptr;
@@ -3028,108 +2948,109 @@ QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
namespacePrefixCount = 0;
}
-void QXmlStreamWriterPrivate::write(const QStringRef &s)
+void QXmlStreamWriterPrivate::write(QAnyStringView s)
{
if (device) {
if (hasIoError)
return;
- QByteArray bytes = toUtf8(s);
- if (toUtf8.hasError()) {
- hasEncodingError = true;
- return;
- }
- if (device->write(bytes) != bytes.size())
- hasIoError = true;
- }
- else if (stringDevice)
- s.appendTo(stringDevice);
- else
+
+ s.visit([&] (auto s) { doWriteToDevice(s); });
+ } else if (stringDevice) {
+ s.visit([&] (auto s) { stringDevice->append(s); });
+ } else {
qWarning("QXmlStreamWriter: No device");
+ }
}
-void QXmlStreamWriterPrivate::write(const QString &s)
+void QXmlStreamWriterPrivate::writeEscaped(QAnyStringView s, bool escapeWhitespace)
{
- if (device) {
- if (hasIoError)
- return;
- QByteArray bytes = toUtf8(s);
- if (toUtf8.hasError()) {
- hasEncodingError = true;
- return;
+ struct NextLatin1 {
+ char32_t operator()(const char *&it, const char *) const
+ { return uchar(*it++); }
+ };
+ struct NextUtf8 {
+ char32_t operator()(const char *&it, const char *end) const
+ {
+ uchar uc = *it++;
+ char32_t utf32 = 0;
+ char32_t *output = &utf32;
+ qsizetype n = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(uc, output, it, end);
+ return n < 0 ? 0 : utf32;
}
- if (device->write(bytes) != bytes.size())
- hasIoError = true;
- }
- else if (stringDevice)
- stringDevice->append(s);
- else
- qWarning("QXmlStreamWriter: No device");
-}
+ };
+ struct NextUtf16 {
+ char32_t operator()(const QChar *&it, const QChar *end) const
+ {
+ QStringIterator decoder(it, end);
+ char32_t result = decoder.next(u'\0');
+ it = decoder.position();
+ return result;
+ }
+ };
-void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespace)
-{
QString escaped;
escaped.reserve(s.size());
- for ( int i = 0; i < s.size(); ++i ) {
- QChar c = s.at(i);
- switch (c.unicode()) {
- case '<':
- escaped.append(QLatin1String("&lt;"));
- break;
- case '>':
- escaped.append(QLatin1String("&gt;"));
- break;
- case '&':
- escaped.append(QLatin1String("&amp;"));
- break;
- case '\"':
- escaped.append(QLatin1String("&quot;"));
- break;
- case '\t':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#9;"));
- else
- escaped += c;
- break;
- case '\n':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#10;"));
- else
- escaped += c;
- break;
- case '\v':
- case '\f':
- hasEncodingError = true;
- break;
- case '\r':
- if (escapeWhitespace)
- escaped.append(QLatin1String("&#13;"));
- else
- escaped += c;
- break;
- default:
- if (c.unicode() > 0x1f && c.unicode() < 0xfffe)
- escaped += c;
- else
- hasEncodingError = true;
- break;
- }
- }
- write(escaped);
-}
+ s.visit([&] (auto s) {
+ using View = decltype(s);
+ using Decoder = std::conditional_t<std::is_same_v<View, QLatin1StringView>, NextLatin1,
+ std::conditional_t<std::is_same_v<View, QUtf8StringView>, NextUtf8, NextUtf16>>;
+
+ auto it = s.begin();
+ const auto end = s.end();
+ Decoder decoder;
+
+ while (it != end) {
+ QLatin1StringView replacement;
+ auto mark = it;
+
+ while (it != end) {
+ auto next_it = it;
+ char32_t uc = decoder(next_it, end);
+ if (uc == u'<') {
+ replacement = "&lt;"_L1;
+ break;
+ } else if (uc == u'>') {
+ replacement = "&gt;"_L1;
+ break;
+ } else if (uc == u'&') {
+ replacement = "&amp;"_L1;
+ break;
+ } else if (uc == u'\"') {
+ replacement = "&quot;"_L1;
+ break;
+ } else if (uc == u'\t') {
+ if (escapeWhitespace) {
+ replacement = "&#9;"_L1;
+ break;
+ }
+ } else if (uc == u'\n') {
+ if (escapeWhitespace) {
+ replacement = "&#10;"_L1;
+ break;
+ }
+ } else if (uc == u'\v' || uc == u'\f') {
+ hasEncodingError = true;
+ break;
+ } else if (uc == u'\r') {
+ if (escapeWhitespace) {
+ replacement = "&#13;"_L1;
+ break;
+ }
+ } else if (uc <= u'\x1F' || uc == u'\uFFFE' || uc == u'\uFFFF') {
+ hasEncodingError = true;
+ break;
+ }
+ it = next_it;
+ }
-// Writes utf8
-void QXmlStreamWriterPrivate::write(const char *s, int len)
-{
- if (device) {
- if (hasIoError)
- return;
- if (device->write(s, len) != len)
- hasIoError = true;
- return;
- }
+ escaped.append(View{mark, it});
+ escaped.append(replacement);
+ if (it != end)
+ ++it;
+ }
+ } );
- write(QString::fromUtf8(s, len));
+ write(escaped);
}
void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
@@ -3155,7 +3076,7 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
if (inEmptyElement) {
write("/>");
- QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = tagStack_pop();
lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
lastWasStartElement = false;
} else {
@@ -3166,7 +3087,33 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
return hadSomethingWritten;
}
-QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
+QXmlStreamPrivateTagStack::NamespaceDeclaration &
+QXmlStreamWriterPrivate::addExtraNamespace(QAnyStringView namespaceUri, QAnyStringView prefix)
+{
+ const bool prefixIsXml = prefix == "xml"_L1;
+ const bool namespaceUriIsXml = namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1;
+ if (prefixIsXml && !namespaceUriIsXml) {
+ qWarning("Reserved prefix 'xml' must not be bound to a different namespace name "
+ "than 'http://www.w3.org/XML/1998/namespace'");
+ } else if (!prefixIsXml && namespaceUriIsXml) {
+ const QString prefixString = prefix.toString();
+ qWarning("The prefix '%ls' must not be bound to namespace name "
+ "'http://www.w3.org/XML/1998/namespace' which 'xml' is already bound to",
+ qUtf16Printable(prefixString));
+ }
+ if (namespaceUri == "http://www.w3.org/2000/xmlns/"_L1) {
+ const QString prefixString = prefix.toString();
+ qWarning("The prefix '%ls' must not be bound to namespace name "
+ "'http://www.w3.org/2000/xmlns/'",
+ qUtf16Printable(prefixString));
+ }
+ auto &namespaceDeclaration = namespaceDeclarations.push();
+ namespaceDeclaration.prefix = addToStringStorage(prefix);
+ namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+ return namespaceDeclaration;
+}
+
+QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(QAnyStringView namespaceUri, bool writeDeclaration, bool noDefault)
{
for (NamespaceDeclaration &namespaceDeclaration : reversed(namespaceDeclarations)) {
if (namespaceDeclaration.namespaceUri == namespaceUri) {
@@ -3183,7 +3130,7 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
QString s;
int n = ++namespacePrefixCount;
forever {
- s = QLatin1Char('n') + QString::number(n++);
+ s = u'n' + QString::number(n++);
qsizetype j = namespaceDeclarations.size() - 2;
while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
--j;
@@ -3203,10 +3150,43 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
void QXmlStreamWriterPrivate::indent(int level)
{
write("\n");
- for (int i = level; i > 0; --i)
- write(autoFormattingIndent.constData(), autoFormattingIndent.length());
+ for (int i = 0; i < level; ++i)
+ write(autoFormattingIndent);
}
+void QXmlStreamWriterPrivate::doWriteToDevice(QStringView s)
+{
+ constexpr qsizetype MaxChunkSize = 512;
+ char buffer [3 * MaxChunkSize];
+ QStringEncoder::State state;
+ while (!s.isEmpty()) {
+ const qsizetype chunkSize = std::min(s.size(), MaxChunkSize);
+ char *end = QUtf8::convertFromUnicode(buffer, s.first(chunkSize), &state);
+ doWriteToDevice(QUtf8StringView{buffer, end});
+ s = s.sliced(chunkSize);
+ }
+ if (state.remainingChars > 0)
+ hasEncodingError = true;
+}
+
+void QXmlStreamWriterPrivate::doWriteToDevice(QUtf8StringView s)
+{
+ QByteArrayView bytes = s;
+ if (device->write(bytes.data(), bytes.size()) != bytes.size())
+ hasIoError = true;
+}
+
+void QXmlStreamWriterPrivate::doWriteToDevice(QLatin1StringView s)
+{
+ constexpr qsizetype MaxChunkSize = 512;
+ char buffer [2 * MaxChunkSize];
+ while (!s.isEmpty()) {
+ const qsizetype chunkSize = std::min(s.size(), MaxChunkSize);
+ char *end = QUtf8::convertFromLatin1(buffer, s.first(chunkSize));
+ doWriteToDevice(QUtf8StringView{buffer, end});
+ s = s.sliced(chunkSize);
+ }
+}
/*!
Constructs a stream writer.
@@ -3294,7 +3274,7 @@ QIODevice *QXmlStreamWriter::device() const
/*!
\property QXmlStreamWriter::autoFormatting
\since 4.4
- The auto-formatting flag of the stream writer
+ \brief the auto-formatting flag of the stream writer.
This property controls whether or not the stream writer
automatically formats the generated XML data. If enabled, the
@@ -3324,7 +3304,7 @@ void QXmlStreamWriter::setAutoFormatting(bool enable)
/*!
\since 4.4
- Returns \c true if auto formattting is enabled, otherwise \c false.
+ Returns \c true if auto formatting is enabled, otherwise \c false.
*/
bool QXmlStreamWriter::autoFormatting() const
{
@@ -3349,13 +3329,14 @@ bool QXmlStreamWriter::autoFormatting() const
void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
{
Q_D(QXmlStreamWriter);
- d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
+ d->autoFormattingIndent.assign(size_t(qAbs(spacesOrTabs)), spacesOrTabs >= 0 ? ' ' : '\t');
}
int QXmlStreamWriter::autoFormattingIndent() const
{
Q_D(const QXmlStreamWriter);
- return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
+ const QLatin1StringView indent(d->autoFormattingIndent);
+ return indent.count(u' ') - indent.count(u'\t');
}
/*!
@@ -3380,12 +3361,15 @@ bool QXmlStreamWriter::hasError() const
This function can only be called after writeStartElement() before
any content is written, or after writeEmptyElement().
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
+void QXmlStreamWriter::writeAttribute(QAnyStringView qualifiedName, QAnyStringView value)
{
Q_D(QXmlStreamWriter);
Q_ASSERT(d->inStartElement);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
d->write(" ");
d->write(qualifiedName);
d->write("=\"");
@@ -3400,12 +3384,15 @@ void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QStrin
This function can only be called after writeStartElement() before
any content is written, or after writeEmptyElement().
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
+void QXmlStreamWriter::writeAttribute(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView value)
{
Q_D(QXmlStreamWriter);
Q_ASSERT(d->inStartElement);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
d->write(" ");
if (!namespaceDeclaration.prefix.isEmpty()) {
@@ -3429,12 +3416,9 @@ void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString
void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
{
if (attribute.namespaceUri().isEmpty())
- writeAttribute(attribute.qualifiedName().toString(),
- attribute.value().toString());
+ writeAttribute(attribute.qualifiedName(), attribute.value());
else
- writeAttribute(attribute.namespaceUri().toString(),
- attribute.name().toString(),
- attribute.value().toString());
+ writeAttribute(attribute.namespaceUri(), attribute.name(), attribute.value());
}
@@ -3464,15 +3448,26 @@ void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
This function mainly exists for completeness. Normally you should
not need use it, because writeCharacters() automatically escapes all
non-content characters.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeCDATA(const QString &text)
+void QXmlStreamWriter::writeCDATA(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
- QString copy(text);
- copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
d->write("<![CDATA[");
- d->write(copy);
+ while (!text.isEmpty()) {
+ const auto idx = indexOf(text, "]]>"_L1);
+ if (idx < 0)
+ break; // no forbidden sequence found
+ d->write(text.first(idx));
+ d->write("]]" // text[idx, idx + 2)
+ "]]><![CDATA[" // escape sequence to separate ]] and >
+ ">"); // text[idx + 2, idx + 3)
+ text = text.sliced(idx + 3); // skip over "]]>"
+ }
+ d->write(text); // write remainder
d->write("]]>");
}
@@ -3482,8 +3477,11 @@ void QXmlStreamWriter::writeCDATA(const QString &text)
"]]>", ">" is also escaped as "&gt;".
\sa writeEntityReference()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeCharacters(const QString &text)
+void QXmlStreamWriter::writeCharacters(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3492,13 +3490,16 @@ void QXmlStreamWriter::writeCharacters(const QString &text)
/*! Writes \a text as XML comment, where \a text must not contain the
- forbidden sequence "--" or end with "-". Note that XML does not
- provide any way to escape "-" in a comment.
+ forbidden sequence \c{--} or end with \c{-}. Note that XML does not
+ provide any way to escape \c{-} in a comment.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeComment(const QString &text)
+void QXmlStreamWriter::writeComment(QAnyStringView text)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
+ Q_ASSERT(!contains(text, "--"_L1) && !endsWith(text, '-'));
if (!d->finishStartElement(false) && d->autoFormatting)
d->indent(d->tagStack.size());
d->write("<!--");
@@ -3510,8 +3511,11 @@ void QXmlStreamWriter::writeComment(const QString &text)
/*! Writes a DTD section. The \a dtd represents the entire
doctypedecl production from the XML 1.0 specification.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeDTD(const QString &dtd)
+void QXmlStreamWriter::writeDTD(QAnyStringView dtd)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3527,12 +3531,15 @@ void QXmlStreamWriter::writeDTD(const QString &dtd)
/*! \overload
Writes an empty element with qualified name \a qualifiedName.
Subsequent calls to writeAttribute() will add attributes to this element.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
+void QXmlStreamWriter::writeEmptyElement(QAnyStringView qualifiedName)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
- d->writeStartElement(QString(), qualifiedName);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
+ d->writeStartElement({}, qualifiedName);
d->inEmptyElement = true;
}
@@ -3543,11 +3550,14 @@ void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
Subsequent calls to writeAttribute() will add attributes to this element.
\sa writeNamespace()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriter::writeEmptyElement(QAnyStringView namespaceUri, QAnyStringView name)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
d->writeStartElement(namespaceUri, name);
d->inEmptyElement = true;
}
@@ -3560,8 +3570,10 @@ void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QStr
This is a convenience function equivalent to:
\snippet code/src_corelib_xml_qxmlstream.cpp 1
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
+void QXmlStreamWriter::writeTextElement(QAnyStringView qualifiedName, QAnyStringView text)
{
writeStartElement(qualifiedName);
writeCharacters(text);
@@ -3577,8 +3589,10 @@ void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QStr
This is a convenience function equivalent to:
\snippet code/src_corelib_xml_qxmlstream.cpp 2
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
+void QXmlStreamWriter::writeTextElement(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView text)
{
writeStartElement(namespaceUri, name);
writeCharacters(text);
@@ -3614,7 +3628,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->inStartElement && !d->inEmptyElement) {
d->write("/>");
d->lastWasStartElement = d->inStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
return;
}
@@ -3624,7 +3638,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->tagStack.isEmpty())
return;
d->lastWasStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
d->write("</");
if (!tag.namespaceDeclaration.prefix.isEmpty()) {
@@ -3639,8 +3653,11 @@ void QXmlStreamWriter::writeEndElement()
/*!
Writes the entity reference \a name to the stream, as "&\a{name};".
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeEntityReference(const QString &name)
+void QXmlStreamWriter::writeEntityReference(QAnyStringView name)
{
Q_D(QXmlStreamWriter);
d->finishStartElement();
@@ -3664,19 +3681,17 @@ void QXmlStreamWriter::writeEntityReference(const QString &name)
\e http://www.w3.org/2000/xmlns/ are used for the namespace mechanism
itself and thus completely forbidden in declarations.
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
+void QXmlStreamWriter::writeNamespace(QAnyStringView namespaceUri, QAnyStringView prefix)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(prefix != QLatin1String("xmlns"));
+ Q_ASSERT(prefix != "xmlns"_L1);
if (prefix.isEmpty()) {
d->findNamespace(namespaceUri, d->inStartElement);
} else {
- Q_ASSERT(!((prefix == QLatin1String("xml")) ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))));
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
- QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
- namespaceDeclaration.prefix = d->addToStringStorage(prefix);
- namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
+ auto &namespaceDeclaration = d->addExtraNamespace(namespaceUri, prefix);
if (d->inStartElement)
d->writeNamespaceDeclaration(namespaceDeclaration);
}
@@ -3692,12 +3707,15 @@ void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString
Note that the namespaces \e http://www.w3.org/XML/1998/namespace
(bound to \e xmlns) and \e http://www.w3.org/2000/xmlns/ (bound to
\e xml) by definition cannot be declared as default.
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
+void QXmlStreamWriter::writeDefaultNamespace(QAnyStringView namespaceUri)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/XML/1998/namespace"));
- Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
+ Q_ASSERT(namespaceUri != "http://www.w3.org/XML/1998/namespace"_L1);
+ Q_ASSERT(namespaceUri != "http://www.w3.org/2000/xmlns/"_L1);
QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
@@ -3709,11 +3727,14 @@ void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
/*!
Writes an XML processing instruction with \a target and \a data,
where \a data must not contain the sequence "?>".
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
+void QXmlStreamWriter::writeProcessingInstruction(QAnyStringView target, QAnyStringView data)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!data.contains(QLatin1String("?>")));
+ Q_ASSERT(!contains(data, "?>"_L1));
if (!d->finishStartElement(false) && d->autoFormatting)
d->indent(d->tagStack.size());
d->write("<?");
@@ -3736,7 +3757,7 @@ void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const Q
*/
void QXmlStreamWriter::writeStartDocument()
{
- writeStartDocument(QLatin1String("1.0"));
+ writeStartDocument("1.0"_L1);
}
@@ -3744,8 +3765,11 @@ void QXmlStreamWriter::writeStartDocument()
Writes a document start with the XML version number \a version.
\sa writeEndDocument()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartDocument(const QString &version)
+void QXmlStreamWriter::writeStartDocument(QAnyStringView version)
{
Q_D(QXmlStreamWriter);
d->finishStartElement(false);
@@ -3761,8 +3785,11 @@ void QXmlStreamWriter::writeStartDocument(const QString &version)
\sa writeEndDocument()
\since 4.5
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
+void QXmlStreamWriter::writeStartDocument(QAnyStringView version, bool standalone)
{
Q_D(QXmlStreamWriter);
d->finishStartElement(false);
@@ -3783,12 +3810,15 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon
writeAttribute() will add attributes to this element.
\sa writeEndElement(), writeEmptyElement()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
+void QXmlStreamWriter::writeStartElement(QAnyStringView qualifiedName)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
- d->writeStartElement(QString(), qualifiedName);
+ Q_ASSERT(count(qualifiedName, ':') <= 1);
+ d->writeStartElement({}, qualifiedName);
}
@@ -3799,15 +3829,19 @@ void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
element.
\sa writeNamespace(), writeEndElement(), writeEmptyElement()
+
+ \note In Qt versions prior to 6.5, this function took QString, not
+ QAnyStringView.
*/
-void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriter::writeStartElement(QAnyStringView namespaceUri, QAnyStringView name)
{
Q_D(QXmlStreamWriter);
- Q_ASSERT(!name.contains(QLatin1Char(':')));
+ Q_ASSERT(!contains(name, ':'));
d->writeStartElement(namespaceUri, name);
}
-void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, const QString &name)
+void QXmlStreamWriterPrivate::writeStartElement(QAnyStringView namespaceUri, QAnyStringView name,
+ StartElementOption option)
{
if (!finishStartElement(false) && autoFormatting)
indent(tagStack.size());
@@ -3823,12 +3857,14 @@ void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, con
write(tag.name);
inStartElement = lastWasStartElement = true;
- for (qsizetype i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
- writeNamespaceDeclaration(namespaceDeclarations[i]);
+ if (option != StartElementOption::OmitNamespaceDeclarations) {
+ for (qsizetype i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
+ writeNamespaceDeclaration(namespaceDeclarations[i]);
+ }
tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
}
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
/*! Writes the current state of the \a reader. All possible valid
states are supported.
@@ -3838,6 +3874,7 @@ void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, con
*/
void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
{
+ Q_D(QXmlStreamWriter);
switch (reader.tokenType()) {
case QXmlStreamReader::NoToken:
break;
@@ -3848,13 +3885,19 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
writeEndDocument();
break;
case QXmlStreamReader::StartElement: {
- writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
- QXmlStreamNamespaceDeclarations namespaceDeclarations = reader.namespaceDeclarations();
- for (int i = 0; i < namespaceDeclarations.size(); ++i) {
- const QXmlStreamNamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(i);
- writeNamespace(namespaceDeclaration.namespaceUri().toString(),
- namespaceDeclaration.prefix().toString());
+ // Namespaces must be added before writeStartElement is called so new prefixes are found
+ QList<QXmlStreamPrivateTagStack::NamespaceDeclaration> extraNamespaces;
+ for (const auto &namespaceDeclaration : reader.namespaceDeclarations()) {
+ auto &extraNamespace = d->addExtraNamespace(namespaceDeclaration.namespaceUri(),
+ namespaceDeclaration.prefix());
+ extraNamespaces.append(extraNamespace);
}
+ d->writeStartElement(
+ reader.namespaceUri(), reader.name(),
+ QXmlStreamWriterPrivate::StartElementOption::OmitNamespaceDeclarations);
+ // Namespace declarations are written afterwards
+ for (const auto &extraNamespace : std::as_const(extraNamespaces))
+ d->writeNamespaceDeclaration(extraNamespace);
writeAttributes(reader.attributes());
} break;
case QXmlStreamReader::EndElement:
@@ -3862,22 +3905,22 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
break;
case QXmlStreamReader::Characters:
if (reader.isCDATA())
- writeCDATA(reader.text().toString());
+ writeCDATA(reader.text());
else
- writeCharacters(reader.text().toString());
+ writeCharacters(reader.text());
break;
case QXmlStreamReader::Comment:
- writeComment(reader.text().toString());
+ writeComment(reader.text());
break;
case QXmlStreamReader::DTD:
- writeDTD(reader.text().toString());
+ writeDTD(reader.text());
break;
case QXmlStreamReader::EntityReference:
- writeEntityReference(reader.name().toString());
+ writeEntityReference(reader.name());
break;
case QXmlStreamReader::ProcessingInstruction:
- writeProcessingInstruction(reader.processingInstructionTarget().toString(),
- reader.processingInstructionData().toString());
+ writeProcessingInstruction(reader.processingInstructionTarget(),
+ reader.processingInstructionData());
break;
default:
Q_ASSERT(reader.tokenType() != QXmlStreamReader::Invalid);
@@ -3886,9 +3929,99 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
}
}
+static constexpr bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
+ QXmlStreamReaderPrivate::XmlContext ctxt)
+{
+ switch (type) {
+ case QXmlStreamReader::StartDocument:
+ case QXmlStreamReader::DTD:
+ return ctxt == QXmlStreamReaderPrivate::XmlContext::Prolog;
+
+ case QXmlStreamReader::StartElement:
+ case QXmlStreamReader::EndElement:
+ case QXmlStreamReader::Characters:
+ case QXmlStreamReader::EntityReference:
+ case QXmlStreamReader::EndDocument:
+ return ctxt == QXmlStreamReaderPrivate::XmlContext::Body;
+
+ case QXmlStreamReader::Comment:
+ case QXmlStreamReader::ProcessingInstruction:
+ return true;
+
+ case QXmlStreamReader::NoToken:
+ case QXmlStreamReader::Invalid:
+ return false;
+ }
+
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ Q_UNREACHABLE_RETURN(false);
+#else
+ return false;
+#endif
+}
+
/*!
- \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
- \since 4.5
+ \internal
+ \brief QXmlStreamReader::isValidToken
+ \return \c true if \param type is a valid token type.
+ \return \c false if \param type is an unexpected token,
+ which indicates a non-well-formed or invalid XML stream.
+ */
+bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
+{
+ // Don't change currentContext, if Invalid or NoToken occur in the prolog
+ if (type == QXmlStreamReader::Invalid || type == QXmlStreamReader::NoToken)
+ return false;
+
+ // If a token type gets rejected in the body, there is no recovery
+ const bool result = isTokenAllowedInContext(type, currentContext);
+ if (result || currentContext == XmlContext::Body)
+ return result;
+
+ // First non-Prolog token observed => switch context to body and check again.
+ currentContext = XmlContext::Body;
+ return isTokenAllowedInContext(type, currentContext);
+}
+
+/*!
+ \internal
+ Checks token type and raises an error, if it is invalid
+ in the current context (prolog/body).
+ */
+void QXmlStreamReaderPrivate::checkToken()
+{
+ Q_Q(QXmlStreamReader);
+
+ // The token type must be consumed, to keep track if the body has been reached.
+ const XmlContext context = currentContext;
+ const bool ok = isValidToken(type);
+
+ // Do nothing if an error has been raised already (going along with an unexpected token)
+ if (error != QXmlStreamReader::Error::NoError)
+ return;
+
+ if (!ok) {
+ raiseError(QXmlStreamReader::UnexpectedElementError,
+ QXmlStream::tr("Unexpected token type %1 in %2.")
+ .arg(q->tokenString(), contextString(context)));
+ return;
+ }
+
+ if (type != QXmlStreamReader::DTD)
+ return;
+
+ // Raise error on multiple DTD tokens
+ if (foundDTD) {
+ raiseError(QXmlStreamReader::UnexpectedElementError,
+ QXmlStream::tr("Found second DTD token in %1.").arg(contextString(context)));
+ } else {
+ foundDTD = true;
+ }
+}
+
+/*!
+ \fn bool QXmlStreamAttributes::hasAttribute(QAnyStringView qualifiedName) const
Returns \c true if this QXmlStreamAttributes has an attribute whose
qualified name is \a qualifiedName; otherwise returns \c false.
@@ -3902,25 +4035,18 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
*/
/*!
- \fn bool QXmlStreamAttributes::hasAttribute(QLatin1String qualifiedName) const
- \overload
- \since 4.5
-*/
-
-/*!
- \fn bool QXmlStreamAttributes::hasAttribute(const QString &namespaceUri,
- const QString &name) const
+ \fn bool QXmlStreamAttributes::hasAttribute(QAnyStringView namespaceUri,
+ QAnyStringView name) const
\overload
- \since 4.5
Returns \c true if this QXmlStreamAttributes has an attribute whose
namespace URI and name correspond to \a namespaceUri and \a name;
otherwise returns \c false.
*/
-#endif // QT_NO_XMLSTREAMREADER
-#endif // QT_NO_XMLSTREAMWRITER
+#endif // feature xmlstreamreader
+#endif // feature xmlstreamwriter
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAM
+#endif // feature xmlstream
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 876157a9e6..860b7fd727 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -1,45 +1,8 @@
-----------------------------------------------------------------------------
---
--- Copyright (C) 2016 The Qt Company Ltd.
--- Contact: https://www.qt.io/licensing/
---
--- This file is part of the QtCore module of the Qt Toolkit.
---
--- $QT_BEGIN_LICENSE:LGPL$
--- 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 Lesser General Public License Usage
--- Alternatively, this file may be used under the terms of the GNU Lesser
--- General Public License version 3 as published by the Free Software
--- Foundation and appearing in the file LICENSE.LGPL3 included in the
--- packaging of this file. Please review the following information to
--- ensure the GNU Lesser General Public License version 3 requirements
--- will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
---
--- GNU General Public License Usage
--- Alternatively, this file may be used under the terms of the GNU
--- General Public License version 2.0 or (at your option) the GNU General
--- Public license version 3 or any later version approved by the KDE Free
--- Qt Foundation. The licenses are as published by the Free Software
--- Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
--- 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-2.0.html and
--- https://www.gnu.org/licenses/gpl-3.0.html.
---
--- $QT_END_LICENSE$
---
-----------------------------------------------------------------------------
-
-%parser QXmlStreamReader_Table
-
-%merged_output qxmlstream_p.h
+-- Copyright (C) 2020 The Qt Company Ltd.
+-- SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+%parser QXmlStreamGrammar
+%impl qxmlstreamparser_p.h
%expect 4
@@ -89,13 +52,13 @@
%token IMPLIED "IMPLIED"
%token FIXED "FIXED"
--- conent spec
+-- content spec
%token EMPTY "EMPTY"
%token ANY "ANY"
%token PCDATA "PCDATA"
-- error
-%token ERROR
+%token XML_ERROR
-- entities
%token PARSE_ENTITY
@@ -146,412 +109,54 @@
%start document
-
-
-/.
+/.// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is automatically generated from qxmlstream.g.
+// Changes should be made to that file, not here. Any change to this file will
+// be lost!
+//
+// To regenerate this file, run:
+// qlalr --no-debug --no-lines --qt qxmlstream.g
+//
#include <QtCore/private/qglobal_p.h>
+#include <qxmlstream.h>
+#include "qxmlstream_p.h"
+#include "qxmlutils_p.h"
#include <qstringconverter.h>
-template <typename T> class QXmlStreamSimpleStack {
- T *data;
- qsizetype tos, cap;
-public:
- inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
-
- inline void reserve(qsizetype extraCapacity) {
- if (tos + extraCapacity + 1 > cap) {
- cap = qMax(tos + extraCapacity + 1, cap << 1 );
- void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
- data = reinterpret_cast<T *>(ptr);
- Q_CHECK_PTR(data);
- }
- }
-
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
- inline const T &top() const { return data[tos]; }
- inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
- inline T &operator[](qsizetype index) { return data[index]; }
- inline const T &at(qsizetype index) const { return data[index]; }
- inline qsizetype size() const { return tos + 1; }
- inline void resize(qsizetype s) { tos = s - 1; }
- inline bool isEmpty() const { return tos < 0; }
- inline void clear() { tos = -1; }
-
- using const_iterator = const T*;
- using iterator = T*;
- T *begin() { return data; }
- const T *begin() const { return data; }
- const T *cbegin() const { return begin(); }
- T *end() { return data + size(); }
- const T *end() const { return data + size(); }
- const T *cend() const { return end(); }
-};
-
-
-class QXmlStream
-{
- Q_DECLARE_TR_FUNCTIONS(QXmlStream)
-};
-
-class QXmlStreamPrivateTagStack {
-public:
- struct NamespaceDeclaration
- {
- QStringRef prefix;
- QStringRef namespaceUri;
- };
-
- struct Tag
- {
- QStringRef name;
- QStringRef qualifiedName;
- NamespaceDeclaration namespaceDeclaration;
- int tagStackStringStorageSize;
- qsizetype namespaceDeclarationsSize;
- };
-
-
- QXmlStreamPrivateTagStack();
- QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
- QString tagStackStringStorage;
- int tagStackStringStorageSize;
- int initialTagStackStringStorageSize;
- bool tagsDone;
-
- inline QStringRef addToStringStorage(const QStringRef &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- inline QStringRef addToStringStorage(const QString &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- QStringRef addToStringStorage(QStringView s)
- {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.append(s.data(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
- }
-
- QXmlStreamSimpleStack<Tag> tagStack;
+#include <memory>
+#ifndef QXMLSTREAMPARSER_P_H
+#define QXMLSTREAMPARSER_P_H
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
- tagStackStringStorageSize = tag.tagStackStringStorageSize;
- namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
- tagsDone = tagStack.isEmpty();
- return tag;
- }
- inline Tag &tagStack_push() {
- Tag &tag = tagStack.push();
- tag.tagStackStringStorageSize = tagStackStringStorageSize;
- tag.namespaceDeclarationsSize = namespaceDeclarations.size();
- return tag;
- }
-};
-
-
-class QXmlStreamEntityResolver;
-#ifndef QT_NO_XMLSTREAMREADER
-class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
- QXmlStreamReader *q_ptr;
- Q_DECLARE_PUBLIC(QXmlStreamReader)
-public:
- QXmlStreamReaderPrivate(QXmlStreamReader *q);
- ~QXmlStreamReaderPrivate();
- void init();
-
- QByteArray rawReadBuffer;
- QByteArray dataBuffer;
- uchar firstByte;
- qint64 nbytesread;
- QString readBuffer;
- int readBufferPos;
- QXmlStreamSimpleStack<uint> putStack;
- struct Entity {
- Entity() = default;
- Entity(const QString &name, const QString &value)
- : name(name), value(value), external(false), unparsed(false), literal(false),
- hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(QLatin1String name, QLatin1String value)
- { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
- QString name, value;
- uint external : 1;
- uint unparsed : 1;
- uint literal : 1;
- uint hasBeenParsed : 1;
- uint isCurrentlyReferenced : 1;
- };
- // these hash tables use a QStringView as a key to avoid creating QStrings
- // just for lookup. The keys are usually views into Entity::name and thus
- // are guaranteed to have the same lifetime as the referenced data:
- QHash<QStringView, Entity> entityHash;
- QHash<QStringView, Entity> parameterEntityHash;
- QXmlStreamSimpleStack<Entity *>entityReferenceStack;
- int entityExpansionLimit = 4096;
- int entityLength = 0;
- inline bool referenceEntity(Entity &entity) {
- if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
- return false;
- }
- // entityLength represents the amount of additional characters the
- // entity expands into (can be negative for e.g. &amp;). It's used to
- // avoid DoS attacks through recursive entity expansions
- entityLength += entity.value.size() - entity.name.size() - 2;
- if (entityLength > entityExpansionLimit) {
- raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
- return false;
- }
- entity.isCurrentlyReferenced = true;
- entityReferenceStack.push() = &entity;
- injectToken(ENTITY_DONE);
- return true;
- }
-
+QT_BEGIN_NAMESPACE
- QIODevice *device;
- bool deleteDevice;
- QStringDecoder decoder;
- bool atEnd;
-
- /*!
- \sa setType()
- */
- QXmlStreamReader::TokenType type;
- QXmlStreamReader::Error error;
- QString errorString;
- QString unresolvedEntity;
-
- qint64 lineNumber, lastLineStart, characterOffset;
-
-
- void write(const QString &);
- void write(const char *);
-
-
- QXmlStreamAttributes attributes;
- QStringRef namespaceForPrefix(const QStringRef &prefix);
- void resolveTag();
- void resolvePublicNamespaces();
- void resolveDtd();
- uint resolveCharRef(int symbolIndex);
- bool checkStartDocument();
- void startDocument();
- void parseError();
- void checkPublicLiteral(const QStringRef &publicId);
-
- bool scanDtd;
- QStringRef lastAttributeValue;
- bool lastAttributeIsCData;
- struct DtdAttribute {
- QStringRef tagName;
- QStringRef attributeQualifiedName;
- QStringRef attributePrefix;
- QStringRef attributeName;
- QStringRef defaultValue;
- bool isCDATA;
- bool isNamespaceAttribute;
- };
- QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
- struct NotationDeclaration {
- QStringRef name;
- QStringRef publicId;
- QStringRef systemId;
- };
- QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
- QXmlStreamNotationDeclarations publicNotationDeclarations;
- QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
-
- struct EntityDeclaration {
- QStringRef name;
- QStringRef notationName;
- QStringRef publicId;
- QStringRef systemId;
- QStringRef value;
- bool parameter;
- bool external;
- inline void clear() {
- name.clear();
- notationName.clear();
- publicId.clear();
- systemId.clear();
- value.clear();
- parameter = external = false;
- }
- };
- QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
- QXmlStreamEntityDeclarations publicEntityDeclarations;
-
- QStringRef text;
-
- QStringRef prefix, namespaceUri, qualifiedName, name;
- QStringRef processingInstructionTarget, processingInstructionData;
- QStringRef dtdName, dtdPublicId, dtdSystemId;
- QStringRef documentVersion, documentEncoding;
- uint isEmptyElement : 1;
- uint isWhitespace : 1;
- uint isCDATA : 1;
- uint standalone : 1;
- uint hasCheckedStartDocument : 1;
- uint normalizeLiterals : 1;
- uint hasSeenTag : 1;
- uint inParseEntity : 1;
- uint referenceToUnparsedEntityDetected : 1;
- uint referenceToParameterEntityDetected : 1;
- uint hasExternalDtdSubset : 1;
- uint lockEncoding : 1;
- uint namespaceProcessing : 1;
-
- int resumeReduction;
- void resume(int rule);
-
- inline bool entitiesMustBeDeclared() const {
- return (!inParseEntity
- && (standalone
- || (!referenceToUnparsedEntityDetected
- && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25
- && !hasExternalDtdSubset)));
- }
-
- // qlalr parser
- int tos;
- int stack_size;
- struct Value {
- int pos;
- int len;
- int prefix;
- ushort c;
- };
-
- Value *sym_stack;
- int *state_stack;
- inline void reallocateStack();
- inline Value &sym(int index) const
- { return sym_stack[tos + index - 1]; }
- QString textBuffer;
- inline void clearTextBuffer() {
- if (!scanDtd) {
- textBuffer.resize(0);
- textBuffer.reserve(256);
- }
- }
- struct Attribute {
- Value key;
- Value value;
- };
- QXmlStreamSimpleStack<Attribute> attributeStack;
-
- inline QStringRef symString(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- QStringView symView(int index) const
- {
- const Value &symbol = sym(index);
- return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
- }
- inline QStringRef symName(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symString(int index, int offset) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
- }
- inline QStringRef symPrefix(int index) {
- const Value &symbol = sym(index);
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
- inline QStringRef symString(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- inline QStringRef symName(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symPrefix(const Value &symbol) {
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
-
- inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
-
-
- short token;
- uint token_char;
-
- uint filterCarriageReturn();
- inline uint getChar();
- inline uint peekChar();
- inline void putChar(uint c) { putStack.push() = c; }
- inline void putChar(QChar c) { putStack.push() = c.unicode(); }
- void putString(QStringView s, qsizetype from = 0);
- void putStringLiteral(QStringView s);
- void putReplacement(QStringView s);
- void putReplacementInAttributeValue(QStringView s);
- uint getChar_helper();
-
- bool scanUntil(const char *str, short tokenToInject = -1);
- bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
- inline void injectToken(ushort tokenToInject) {
- putChar(int(tokenToInject) << 16);
- }
-
- QString resolveUndeclaredEntity(const QString &name);
- void parseEntity(const QString &value);
- std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
-
- bool scanAfterLangleBang();
- bool scanPublicOrSystem();
- bool scanNData();
- bool scanAfterDefaultDecl();
- bool scanAttType();
-
-
- // scan optimization functions. Not strictly necessary but LALR is
- // not very well suited for scanning fast
- int fastScanLiteralContent();
- int fastScanSpace();
- int fastScanContentCharList();
- int fastScanName(int *prefix = nullptr);
- inline int fastScanNMTOKEN();
-
-
- bool parse();
- inline void consumeRule(int);
-
- void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
- void raiseWellFormedError(const QString &message);
-
- QXmlStreamEntityResolver *entityResolver;
-
-private:
- /*! \internal
- Never assign to variable type directly. Instead use this function.
-
- This prevents errors from being ignored.
- */
- inline void setType(const QXmlStreamReader::TokenType t)
- {
- if(type != QXmlStreamReader::Invalid)
- type = t;
- }
-};
+#if QT_CONFIG(xmlstreamreader)
bool QXmlStreamReaderPrivate::parse()
{
// cleanup currently reported token
+ using namespace Qt::StringLiterals;
+
switch (type) {
case QXmlStreamReader::StartElement:
name.clear();
@@ -562,8 +167,9 @@ bool QXmlStreamReaderPrivate::parse()
attributes.clear();
if (isEmptyElement) {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
name = tag.name;
qualifiedName = tag.qualifiedName;
isEmptyElement = false;
@@ -645,7 +251,7 @@ bool QXmlStreamReaderPrivate::parse()
} else switch (token_char) {
case 0xfffe:
case 0xffff:
- token = ERROR;
+ token = XML_ERROR;
break;
case '\r':
token = SPACE;
@@ -851,12 +457,15 @@ prolog ::=;
entity_done ::= ENTITY_DONE;
/.
- case $rule_number:
- entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ case $rule_number: {
+ auto reference = entityReferenceStack.pop();
+ auto it = reference.hash->find(reference.name);
+ Q_ASSERT(it != reference.hash->end());
+ it->isCurrentlyReferenced = false;
if (entityReferenceStack.isEmpty())
entityLength = 0;
clearSym();
- break;
+ } break;
./
@@ -1055,9 +664,9 @@ attdef ::= attdef_start att_type default_decl;
dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
dtdAttribute.attributeName = addToStringStorage(symString(1));
dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
- dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
+ dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
|| (dtdAttribute.attributePrefix.isEmpty()
- && dtdAttribute.attributeName == QLatin1String("xmlns")));
+ && dtdAttribute.attributeName == "xmlns"_L1));
if (lastAttributeValue.isNull()) {
dtdAttribute.defaultValue.clear();
} else {
@@ -1079,14 +688,14 @@ attlist_decl ::= langle_bang ATTLIST qname attdef_list space_opt RANGLE;
case $rule_number: {
if (referenceToUnparsedEntityDetected && !standalone)
break;
- int n = dtdAttributes.size();
- QStringRef tagName = addToStringStorage(symName(3));
+ qsizetype n = dtdAttributes.size();
+ XmlStringRef tagName = addToStringStorage(symName(3));
while (n--) {
DtdAttribute &dtdAttribute = dtdAttributes[n];
if (!dtdAttribute.tagName.isNull())
break;
dtdAttribute.tagName = tagName;
- for (int i = 0; i < n; ++i) {
+ for (qsizetype i = 0; i < n; ++i) {
if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
&& dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
@@ -1177,7 +786,7 @@ entity_decl ::= entity_decl_start entity_value space_opt RANGLE;
if (!entityDeclaration.external)
entityDeclaration.value = symString(2);
auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
+ if (!hash.contains(entityDeclaration.name)) {
Entity entity(entityDeclaration.name.toString(),
entityDeclaration.value.toString());
entity.unparsed = (!entityDeclaration.notationName.isNull());
@@ -1192,11 +801,11 @@ processing_instruction ::= LANGLE QUESTIONMARK name space;
/.
case $rule_number: {
setType(QXmlStreamReader::ProcessingInstruction);
- int pos = sym(4).pos + sym(4).len;
+ const qsizetype pos = sym(4).pos + sym(4).len;
processingInstructionTarget = symString(3);
if (scanUntil("?>")) {
- processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive)) {
raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
}
else if (!QXmlUtils::isNCName(processingInstructionTarget))
@@ -1214,7 +823,7 @@ processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE;
case $rule_number:
setType(QXmlStreamReader::ProcessingInstruction);
processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive))
raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
break;
./
@@ -1244,8 +853,8 @@ comment ::= comment_start RANGLE;
/.
case $rule_number: {
setType(QXmlStreamReader::Comment);
- int pos = sym(1).pos + 4;
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ const qsizetype pos = sym(1).pos + 4;
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
} break;
./
@@ -1256,9 +865,9 @@ cdata ::= langle_bang CDATA_START;
setType(QXmlStreamReader::Characters);
isCDATA = true;
isWhitespace = false;
- int pos = sym(2).pos;
+ const qsizetype pos = sym(2).pos;
if (scanUntil("]]>", -1)) {
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
} else {
resume($rule_number);
return false;
@@ -1392,7 +1001,7 @@ literal_content_start ::= SPACE;
/.
case $rule_number:
if (normalizeLiterals)
- textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
+ textBuffer.data()[textBuffer.size()-1] = u' ';
break;
./
@@ -1506,14 +1115,14 @@ attribute_value_content ::= literal_content | char_ref | entity_ref_in_attribute
attribute ::= qname space_opt EQ space_opt attribute_value;
/.
case $rule_number: {
- QStringRef prefix = symPrefix(1);
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
+ XmlStringRef prefix = symPrefix(1);
+ if (prefix.isEmpty() && symString(1) == "xmlns"_L1 && namespaceProcessing) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
namespaceDeclaration.prefix.clear();
- const QStringRef ns(symString(5));
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ const XmlStringRef ns(symString(5));
+ if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
else
namespaceDeclaration.namespaceUri = addToStringStorage(ns);
@@ -1522,10 +1131,9 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
attribute.key = sym(1);
attribute.value = sym(5);
- QStringRef attributeQualifiedName = symName(1);
+ XmlStringRef attributeQualifiedName = symName(1);
bool normalize = false;
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
+ for (const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
if (!dtdAttribute.isCDATA
&& dtdAttribute.tagName == qualifiedName
&& dtdAttribute.attributeQualifiedName == attributeQualifiedName
@@ -1536,10 +1144,10 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
}
if (normalize) {
// normalize attribute value (simplify and trim)
- int pos = textBuffer.size();
- int n = 0;
+ const qsizetype pos = textBuffer.size();
+ qsizetype n = 0;
bool wasSpace = true;
- for (int i = 0; i < attribute.value.len; ++i) {
+ for (qsizetype i = 0; i < attribute.value.len; ++i) {
QChar c = textBuffer.at(attribute.value.pos + i);
if (c.unicode() == ' ') {
if (wasSpace)
@@ -1557,16 +1165,16 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
attribute.value.pos = pos;
attribute.value.len = n;
}
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
+ if (prefix == "xmlns"_L1 && namespaceProcessing) {
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = symString(attribute.key);
- QStringRef namespaceUri = symString(attribute.value);
+ XmlStringRef namespacePrefix = symString(attribute.key);
+ XmlStringRef namespaceUri = symString(attribute.value);
attributeStack.pop();
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
|| namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
+ || namespacePrefix == "xmlns"_L1)
raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
@@ -1619,9 +1227,10 @@ etag ::= LANGLE SLASH qname space_opt RANGLE;
/.
case $rule_number: {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
name = tag.name;
qualifiedName = tag.qualifiedName;
if (qualifiedName != symName(3))
@@ -1658,7 +1267,7 @@ entity_ref ::= AMPERSAND name SEMICOLON;
}
if (entity.literal)
putStringLiteral(entity.value);
- else if (referenceEntity(entity))
+ else if (referenceEntity(&entityHash, entity))
putReplacement(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1695,7 +1304,7 @@ pereference ::= PERCENT name SEMICOLON;
if (entity.unparsed || entity.external) {
referenceToUnparsedEntityDetected = true;
} else {
- if (referenceEntity(entity))
+ if (referenceEntity(&parameterEntityHash, entity))
putString(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1732,7 +1341,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
}
if (entity.literal)
putStringLiteral(entity.value);
- else if (referenceEntity(entity))
+ else if (referenceEntity(&entityHash, entity))
putReplacementInAttributeValue(entity.value);
textBuffer.chop(2 + sym(2).len);
clearSym();
@@ -1810,7 +1419,12 @@ space_opt ::= space;
qname ::= LETTER;
/.
case $rule_number: {
- sym(1).len += fastScanName(&sym(1).prefix);
+ Value &val = sym(1);
+ if (auto res = fastScanName(&val))
+ val.len += *res;
+ else
+ return false;
+
if (atEnd) {
resume($rule_number);
return false;
@@ -1821,7 +1435,11 @@ qname ::= LETTER;
name ::= LETTER;
/.
case $rule_number:
- sym(1).len += fastScanName();
+ if (auto res = fastScanName())
+ sym(1).len += *res;
+ else
+ return false;
+
if (atEnd) {
resume($rule_number);
return false;
@@ -1868,6 +1486,11 @@ nmtoken ::= COLON;
}
return false;
}
-#endif //QT_NO_XMLSTREAMREADER.xml
+
+#endif // feature xmlstreamreader
+
+QT_END_NAMESPACE
+
+#endif
./
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index 44f33b111b..8a12c6d611 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -1,89 +1,48 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXMLSTREAM_H
#define QXMLSTREAM_H
#include <QtCore/qiodevice.h>
-#ifndef QT_NO_XMLSTREAM
+#if QT_CONFIG(xmlstream)
+#include <QtCore/qcompare.h>
#include <QtCore/qlist.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
-class Q_CORE_EXPORT QXmlStreamStringRef {
- QString m_string;
- int m_position, m_size;
+class QXmlString {
+ QStringPrivate m_string;
public:
- inline QXmlStreamStringRef():m_position(0), m_size(0){}
- inline QXmlStreamStringRef(const QStringRef &aString)
- :m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){}
- QXmlStreamStringRef(const QString &aString) : m_string(aString), m_position(0), m_size(m_string.size()) {}
- QXmlStreamStringRef(QString &&aString) noexcept : m_string(std::move(aString)), m_position(0), m_size(m_string.size()) {}
+ QXmlString(QStringPrivate &&d) : m_string(std::move(d)) {}
+ QXmlString(const QString &s) : m_string(s.data_ptr()) {}
+ QXmlString & operator=(const QString &s) { m_string = s.data_ptr(); return *this; }
+ QXmlString & operator=(QString &&s) { m_string.swap(s.data_ptr()); return *this; }
+ inline constexpr QXmlString() {}
- void swap(QXmlStreamStringRef &other) noexcept
+ void swap(QXmlString &other) noexcept
{
- qSwap(m_string, other.m_string);
- qSwap(m_position, other.m_position);
- qSwap(m_size, other.m_size);
+ m_string.swap(other.m_string);
}
- inline void clear() { m_string.clear(); m_position = m_size = 0; }
- inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); }
- inline const QString *string() const { return &m_string; }
- inline int position() const { return m_position; }
- inline int size() const { return m_size; }
+ inline operator QStringView() const { return QStringView(m_string.data(), m_string.size); }
+ inline qsizetype size() const { return m_string.size; }
};
-Q_DECLARE_SHARED(QXmlStreamStringRef)
+
+}
+Q_DECLARE_SHARED(QtPrivate::QXmlString)
class QXmlStreamReaderPrivate;
class QXmlStreamAttributes;
class Q_CORE_EXPORT QXmlStreamAttribute {
- QXmlStreamStringRef m_name, m_namespaceUri, m_qualifiedName, m_value;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_namespaceUri, m_qualifiedName, m_value;
uint m_isDefault : 1;
friend class QXmlStreamReaderPrivate;
friend class QXmlStreamAttributes;
@@ -92,50 +51,60 @@ public:
QXmlStreamAttribute(const QString &qualifiedName, const QString &value);
QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value);
- inline QStringRef namespaceUri() const { return m_namespaceUri; }
- inline QStringRef name() const { return m_name; }
- inline QStringRef qualifiedName() const { return m_qualifiedName; }
- inline QStringRef prefix() const {
- return QStringRef(m_qualifiedName.string(),
- m_qualifiedName.position(),
- qMax(0, m_qualifiedName.size() - m_name.size() - 1));
+ inline QStringView namespaceUri() const { return m_namespaceUri; }
+ inline QStringView name() const { return m_name; }
+ inline QStringView qualifiedName() const { return m_qualifiedName; }
+ inline QStringView prefix() const {
+ return QStringView(m_qualifiedName).left(qMax(0, m_qualifiedName.size() - m_name.size() - 1));
}
- inline QStringRef value() const { return m_value; }
+ inline QStringView value() const { return m_value; }
inline bool isDefault() const { return m_isDefault; }
- inline bool operator==(const QXmlStreamAttribute &other) const {
- return (value() == other.value()
- && (namespaceUri().isNull() ? (qualifiedName() == other.qualifiedName())
- : (namespaceUri() == other.namespaceUri() && name() == other.name())));
- }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamAttribute &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamAttribute &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+
+private:
+ friend bool comparesEqual(const QXmlStreamAttribute &lhs,
+ const QXmlStreamAttribute &rhs) noexcept
+ {
+ return (lhs.value() == rhs.value()
+ && (lhs.namespaceUri().isNull() ? (lhs.qualifiedName() == rhs.qualifiedName())
+ : (lhs.namespaceUri() == rhs.namespaceUri()
+ && lhs.name() == rhs.name())));
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamAttribute)
};
-Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_RELOCATABLE_TYPE);
-class Q_CORE_EXPORT QXmlStreamAttributes : public QList<QXmlStreamAttribute>
+// We export each out-of-line method individually to prevent MSVC from
+// exporting the whole QList class.
+class QXmlStreamAttributes : public QList<QXmlStreamAttribute>
{
public:
inline QXmlStreamAttributes() {}
- QStringRef value(const QString &namespaceUri, const QString &name) const;
- QStringRef value(const QString &namespaceUri, QLatin1String name) const;
- QStringRef value(QLatin1String namespaceUri, QLatin1String name) const;
- QStringRef value(const QString &qualifiedName) const;
- QStringRef value(QLatin1String qualifiedName) const;
- void append(const QString &namespaceUri, const QString &name, const QString &value);
- void append(const QString &qualifiedName, const QString &value);
-
- inline bool hasAttribute(const QString &qualifiedName) const
- {
- return !value(qualifiedName).isNull();
- }
+#if QT_CORE_REMOVED_SINCE(6, 6)
+ Q_CORE_EXPORT QStringView value(const QString &namespaceUri, const QString &name) const;
+ Q_CORE_EXPORT QStringView value(const QString &namespaceUri, QLatin1StringView name) const;
+ Q_CORE_EXPORT QStringView value(QLatin1StringView namespaceUri, QLatin1StringView name) const;
+ Q_CORE_EXPORT QStringView value(const QString &qualifiedName) const;
+ Q_CORE_EXPORT QStringView value(QLatin1StringView qualifiedName) const;
+#endif
+ Q_CORE_EXPORT QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept;
+ Q_CORE_EXPORT QStringView value(QAnyStringView qualifiedName) const noexcept;
+
+ Q_CORE_EXPORT void append(const QString &namespaceUri, const QString &name, const QString &value);
+ Q_CORE_EXPORT void append(const QString &qualifiedName, const QString &value);
- inline bool hasAttribute(QLatin1String qualifiedName) const
+ bool hasAttribute(QAnyStringView qualifiedName) const
{
return !value(qualifiedName).isNull();
}
- inline bool hasAttribute(const QString &namespaceUri, const QString &name) const
+ bool hasAttribute(QAnyStringView namespaceUri, QAnyStringView name) const
{
return !value(namespaceUri, name).isNull();
}
@@ -144,91 +113,110 @@ public:
};
class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration {
- QXmlStreamStringRef m_prefix, m_namespaceUri;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_prefix, m_namespaceUri;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamNamespaceDeclaration();
QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
- inline QStringRef prefix() const { return m_prefix; }
- inline QStringRef namespaceUri() const { return m_namespaceUri; }
- inline bool operator==(const QXmlStreamNamespaceDeclaration &other) const {
- return (prefix() == other.prefix() && namespaceUri() == other.namespaceUri());
- }
+ inline QStringView prefix() const { return m_prefix; }
+ inline QStringView namespaceUri() const { return m_namespaceUri; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamNamespaceDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamNamespaceDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+private:
+ friend bool comparesEqual(const QXmlStreamNamespaceDeclaration &lhs,
+ const QXmlStreamNamespaceDeclaration &rhs) noexcept
+ {
+ return (lhs.prefix() == rhs.prefix() && lhs.namespaceUri() == rhs.namespaceUri());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamNamespaceDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamNamespaceDeclaration> QXmlStreamNamespaceDeclarations;
class Q_CORE_EXPORT QXmlStreamNotationDeclaration {
- QXmlStreamStringRef m_name, m_systemId, m_publicId;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_systemId, m_publicId;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamNotationDeclaration();
- inline QStringRef name() const { return m_name; }
- inline QStringRef systemId() const { return m_systemId; }
- inline QStringRef publicId() const { return m_publicId; }
- inline bool operator==(const QXmlStreamNotationDeclaration &other) const {
- return (name() == other.name() && systemId() == other.systemId()
- && publicId() == other.publicId());
- }
+ inline QStringView name() const { return m_name; }
+ inline QStringView systemId() const { return m_systemId; }
+ inline QStringView publicId() const { return m_publicId; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamNotationDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamNotationDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+private:
+ friend bool comparesEqual(const QXmlStreamNotationDeclaration &lhs,
+ const QXmlStreamNotationDeclaration &rhs) noexcept
+ {
+ return (lhs.name() == rhs.name() && lhs.systemId() == rhs.systemId()
+ && lhs.publicId() == rhs.publicId());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamNotationDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamNotationDeclaration> QXmlStreamNotationDeclarations;
class Q_CORE_EXPORT QXmlStreamEntityDeclaration {
- QXmlStreamStringRef m_name, m_notationName, m_systemId, m_publicId, m_value;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- void *reserved;
-#endif
+ QtPrivate::QXmlString m_name, m_notationName, m_systemId, m_publicId, m_value;
friend class QXmlStreamReaderPrivate;
public:
QXmlStreamEntityDeclaration();
- inline QStringRef name() const { return m_name; }
- inline QStringRef notationName() const { return m_notationName; }
- inline QStringRef systemId() const { return m_systemId; }
- inline QStringRef publicId() const { return m_publicId; }
- inline QStringRef value() const { return m_value; }
- inline bool operator==(const QXmlStreamEntityDeclaration &other) const {
- return (name() == other.name()
- && notationName() == other.notationName()
- && systemId() == other.systemId()
- && publicId() == other.publicId()
- && value() == other.value());
- }
+ inline QStringView name() const { return m_name; }
+ inline QStringView notationName() const { return m_notationName; }
+ inline QStringView systemId() const { return m_systemId; }
+ inline QStringView publicId() const { return m_publicId; }
+ inline QStringView value() const { return m_value; }
+#if QT_CORE_REMOVED_SINCE(6, 8)
+ inline bool operator==(const QXmlStreamEntityDeclaration &other) const
+ { return comparesEqual(*this, other); }
inline bool operator!=(const QXmlStreamEntityDeclaration &other) const
- { return !operator==(other); }
+ { return !operator==(other); }
+#endif
+
+private:
+ friend bool comparesEqual(const QXmlStreamEntityDeclaration &lhs,
+ const QXmlStreamEntityDeclaration &rhs) noexcept
+ {
+ return (lhs.name() == rhs.name()
+ && lhs.notationName() == rhs.notationName()
+ && lhs.systemId() == rhs.systemId()
+ && lhs.publicId() == rhs.publicId()
+ && lhs.value() == rhs.value());
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(QXmlStreamEntityDeclaration)
};
-Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_RELOCATABLE_TYPE);
typedef QList<QXmlStreamEntityDeclaration> QXmlStreamEntityDeclarations;
class Q_CORE_EXPORT QXmlStreamEntityResolver
{
+ Q_DISABLE_COPY_MOVE(QXmlStreamEntityResolver)
public:
+ QXmlStreamEntityResolver() = default;
virtual ~QXmlStreamEntityResolver();
virtual QString resolveEntity(const QString& publicId, const QString& systemId);
virtual QString resolveUndeclaredEntity(const QString &name);
};
-#ifndef QT_NO_XMLSTREAMREADER
-class Q_CORE_EXPORT QXmlStreamReader {
+#if QT_CONFIG(xmlstreamreader)
+class Q_CORE_EXPORT QXmlStreamReader
+{
QDOC_PROPERTY(bool namespaceProcessing READ namespaceProcessing WRITE setNamespaceProcessing)
public:
enum TokenType {
@@ -248,16 +236,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, PrivateConstructorTag{}) { }
+ 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();
@@ -286,8 +285,9 @@ public:
inline bool isProcessingInstruction() const { return tokenType() == ProcessingInstruction; }
bool isStandaloneDocument() const;
- QStringRef documentVersion() const;
- QStringRef documentEncoding() const;
+ bool hasStandaloneDeclaration() const;
+ QStringView documentVersion() const;
+ QStringView documentEncoding() const;
qint64 lineNumber() const;
qint64 columnNumber() const;
@@ -302,24 +302,24 @@ public:
};
QString readElementText(ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement);
- QStringRef name() const;
- QStringRef namespaceUri() const;
- QStringRef qualifiedName() const;
- QStringRef prefix() const;
+ QStringView name() const;
+ QStringView namespaceUri() const;
+ QStringView qualifiedName() const;
+ QStringView prefix() const;
- QStringRef processingInstructionTarget() const;
- QStringRef processingInstructionData() const;
+ QStringView processingInstructionTarget() const;
+ QStringView processingInstructionData() const;
- QStringRef text() const;
+ QStringView text() const;
QXmlStreamNamespaceDeclarations namespaceDeclarations() const;
void addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaraction);
void addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclaractions);
QXmlStreamNotationDeclarations notationDeclarations() const;
QXmlStreamEntityDeclarations entityDeclarations() const;
- QStringRef dtdName() const;
- QStringRef dtdPublicId() const;
- QStringRef dtdSystemId() const;
+ QStringView dtdName() const;
+ QStringView dtdPublicId() const;
+ QStringView dtdSystemId() const;
int entityExpansionLimit() const;
void setEntityExpansionLimit(int limit);
@@ -344,14 +344,18 @@ public:
QXmlStreamEntityResolver *entityResolver() const;
private:
+ struct PrivateConstructorTag { };
+ QXmlStreamReader(const QByteArray &data, PrivateConstructorTag);
+ void addDataImpl(const QByteArray &data);
+
Q_DISABLE_COPY(QXmlStreamReader)
Q_DECLARE_PRIVATE(QXmlStreamReader)
QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
};
-#endif // QT_NO_XMLSTREAMREADER
+#endif // feature xmlstreamreader
-#ifndef QT_NO_XMLSTREAMWRITER
+#if QT_CONFIG(xmlstreamwriter)
class QXmlStreamWriterPrivate;
@@ -375,11 +379,17 @@ public:
void setAutoFormattingIndent(int spacesOrTabs);
int autoFormattingIndent() const;
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeAttribute(const QString &qualifiedName, const QString &value);
void writeAttribute(const QString &namespaceUri, const QString &name, const QString &value);
+#endif
+ void writeAttribute(QAnyStringView qualifiedName, QAnyStringView value);
+ void writeAttribute(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView value);
+
void writeAttribute(const QXmlStreamAttribute& attribute);
void writeAttributes(const QXmlStreamAttributes& attributes);
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeCDATA(const QString &text);
void writeCharacters(const QString &text);
void writeComment(const QString &text);
@@ -391,22 +401,47 @@ public:
void writeTextElement(const QString &qualifiedName, const QString &text);
void writeTextElement(const QString &namespaceUri, const QString &name, const QString &text);
+#endif
+ void writeCDATA(QAnyStringView text);
+ void writeCharacters(QAnyStringView text);
+ void writeComment(QAnyStringView text);
+
+ void writeDTD(QAnyStringView dtd);
+
+ void writeEmptyElement(QAnyStringView qualifiedName);
+ void writeEmptyElement(QAnyStringView namespaceUri, QAnyStringView name);
+
+ void writeTextElement(QAnyStringView qualifiedName, QAnyStringView text);
+ void writeTextElement(QAnyStringView namespaceUri, QAnyStringView name, QAnyStringView text);
+
void writeEndDocument();
void writeEndElement();
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeEntityReference(const QString &name);
- void writeNamespace(const QString &namespaceUri, const QString &prefix = QString());
+ void writeNamespace(const QString &namespaceUri, const QString &prefix);
void writeDefaultNamespace(const QString &namespaceUri);
- void writeProcessingInstruction(const QString &target, const QString &data = QString());
+ void writeProcessingInstruction(const QString &target, const QString &data);
+#endif
+ void writeEntityReference(QAnyStringView name);
+ void writeNamespace(QAnyStringView namespaceUri, QAnyStringView prefix = {});
+ void writeDefaultNamespace(QAnyStringView namespaceUri);
+ void writeProcessingInstruction(QAnyStringView target, QAnyStringView data = {});
void writeStartDocument();
+#if QT_CORE_REMOVED_SINCE(6,5)
void writeStartDocument(const QString &version);
void writeStartDocument(const QString &version, bool standalone);
void writeStartElement(const QString &qualifiedName);
void writeStartElement(const QString &namespaceUri, const QString &name);
+#endif
+ void writeStartDocument(QAnyStringView version);
+ void writeStartDocument(QAnyStringView version, bool standalone);
+ void writeStartElement(QAnyStringView qualifiedName);
+ void writeStartElement(QAnyStringView namespaceUri, QAnyStringView name);
-#ifndef QT_NO_XMLSTREAMREADER
+#if QT_CONFIG(xmlstreamreader)
void writeCurrentToken(const QXmlStreamReader &reader);
#endif
@@ -417,9 +452,10 @@ private:
Q_DECLARE_PRIVATE(QXmlStreamWriter)
QScopedPointer<QXmlStreamWriterPrivate> d_ptr;
};
-#endif // QT_NO_XMLSTREAMWRITER
+#endif // feature xmlstreamwriter
QT_END_NAMESPACE
-#endif // QT_NO_XMLSTREAM
+#endif // feature xmlstream
+
#endif // QXMLSTREAM_H
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index c9239eb410..a29ee656e9 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
@@ -50,606 +14,128 @@
#include <QtCore/private/qglobal_p.h>
#include <qstringconverter.h>
+#include <qxmlstream.h>
+#include "qxmlstreamgrammar_p.h"
+#include <QtCore/qhash.h>
+#include <QCoreApplication> // Q_DECLARE_TR_FUNCTIONS
+
+
+#include <memory>
+#include <optional>
-// This file was generated by qlalr - DO NOT EDIT!
#ifndef QXMLSTREAM_P_H
#define QXMLSTREAM_P_H
-#if defined(ERROR)
-# undef ERROR
-#endif
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
-class QXmlStreamReader_Table
+class XmlStringRef
{
public:
- enum VariousConstants {
- EOF_SYMBOL = 0,
- AMPERSAND = 5,
- ANY = 41,
- ATTLIST = 31,
- BANG = 25,
- CDATA = 47,
- CDATA_START = 28,
- COLON = 17,
- COMMA = 19,
- DASH = 20,
- DBLQUOTE = 8,
- DIGIT = 27,
- DOCTYPE = 29,
- DOT = 23,
- ELEMENT = 30,
- EMPTY = 40,
- ENTITIES = 51,
- ENTITY = 32,
- ENTITY_DONE = 45,
- EQ = 14,
- ERROR = 43,
- FIXED = 39,
- HASH = 6,
- ID = 48,
- IDREF = 49,
- IDREFS = 50,
- IMPLIED = 38,
- LANGLE = 3,
- LBRACK = 9,
- LETTER = 26,
- LPAREN = 11,
- NDATA = 36,
- NMTOKEN = 52,
- NMTOKENS = 53,
- NOTATION = 33,
- NOTOKEN = 1,
- PARSE_ENTITY = 44,
- PCDATA = 42,
- PERCENT = 15,
- PIPE = 13,
- PLUS = 21,
- PUBLIC = 35,
- QUESTIONMARK = 24,
- QUOTE = 7,
- RANGLE = 4,
- RBRACK = 10,
- REQUIRED = 37,
- RPAREN = 12,
- SEMICOLON = 18,
- SHIFT_THERE = 56,
- SLASH = 16,
- SPACE = 2,
- STAR = 22,
- SYSTEM = 34,
- UNRESOLVED_ENTITY = 46,
- VERSION = 55,
- XML = 54,
-
- ACCEPT_STATE = 416,
- RULE_COUNT = 270,
- STATE_COUNT = 427,
- TERMINAL_COUNT = 57,
- NON_TERMINAL_COUNT = 84,
-
- GOTO_INDEX_OFFSET = 427,
- GOTO_INFO_OFFSET = 1017,
- GOTO_CHECK_OFFSET = 1017
- };
-
- static const char *const spell [];
- static const short lhs [];
- static const short rhs [];
- static const short goto_default [];
- static const short action_default [];
- static const short action_index [];
- static const short action_info [];
- static const short action_check [];
-
- static inline int nt_action (int state, int nt)
- {
- const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
- if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
- return goto_default [nt];
-
- return action_info [GOTO_INFO_OFFSET + yyn];
- }
-
- static inline int t_action (int state, int token)
- {
- const int yyn = action_index [state] + token;
-
- if (yyn < 0 || action_check [yyn] != token)
- return - action_default [state];
-
- return action_info [yyn];
- }
+ const QString *m_string = nullptr;
+ qsizetype m_pos = 0;
+ qsizetype m_size = 0;
+
+ constexpr XmlStringRef() = default;
+ constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
+ : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length))
+ {
+ }
+ XmlStringRef(const QString *string)
+ : XmlStringRef(string, 0, string->size())
+ {
+ }
+
+ operator QXmlString() const {
+ if (!m_string)
+ return QXmlString();
+ QStringPrivate d = m_string->data_ptr();
+ d.setBegin(d.data() + m_pos);
+ d.size = m_size;
+ return QXmlString(std::move(d));
+ }
+
+ void clear() { m_string = nullptr; m_pos = 0; m_size= 0; }
+ QStringView view() const { return m_string ? QStringView(m_string->data() + m_pos, m_size) : QStringView(); }
+ bool isEmpty() const { return m_size == 0; }
+ bool isNull() const { return !m_string; }
+ QString toString() const { return view().toString(); }
+
+ using value_type = QStringView::value_type;
+ using size_type = QStringView::size_type;
+ using difference_type = QStringView::difference_type;
+ using pointer = QStringView::pointer;
+ using const_pointer = QStringView::const_pointer;
+ using reference = QStringView::reference;
+ using const_reference = QStringView::const_reference;
+ using iterator = QStringView::iterator;
+ using const_iterator = QStringView::const_iterator;
+ using reverse_iterator = QStringView::reverse_iterator;
+ using const_reverse_iterator = QStringView::const_reverse_iterator;
+
+#define MAKE_MEMBER(name) \
+ auto name () const noexcept { return view(). name (); }
+ MAKE_MEMBER(data)
+ MAKE_MEMBER(size)
+ MAKE_MEMBER(empty)
+ MAKE_MEMBER(begin)
+ MAKE_MEMBER(end)
+ MAKE_MEMBER(cbegin)
+ MAKE_MEMBER(cend)
+ MAKE_MEMBER(rbegin)
+ MAKE_MEMBER(rend)
+ MAKE_MEMBER(crbegin)
+ MAKE_MEMBER(crend)
+#undef MAKE_MEMBER
+
+#define MAKE_OP(op) \
+ friend auto operator op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); } \
+ /*end*/
+ MAKE_OP(==)
+ MAKE_OP(!=)
+ MAKE_OP(<=)
+ MAKE_OP(>=)
+ MAKE_OP(<)
+ MAKE_OP(>)
+#undef MAKE_OP
+#define MAKE_OP(op) \
+ friend auto operator op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; } \
+ friend auto operator op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); } \
+ /*end*/
+ MAKE_OP(==)
+ MAKE_OP(!=)
+ MAKE_OP(<=)
+ MAKE_OP(>=)
+ MAKE_OP(<)
+ MAKE_OP(>)
+#undef MAKE_OP
};
+}
+
+using namespace QtPrivate;
+
+template <typename T> class QXmlStreamSimpleStack
+{
+ Q_DISABLE_COPY_MOVE(QXmlStreamSimpleStack)
-const char *const QXmlStreamReader_Table::spell [] = {
- "end of file", nullptr, " ", "<", ">", "&", "#", "\'", "\"", "[",
- "]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
- "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
- "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
- "EMPTY", "ANY", "PCDATA", nullptr, nullptr, nullptr, nullptr, "CDATA", "ID", "IDREF",
- "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", nullptr};
-
-const short QXmlStreamReader_Table::lhs [] = {
- 57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
- 67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
- 66, 79, 78, 80, 80, 80, 80, 80, 80, 80,
- 81, 81, 81, 81, 81, 81, 81, 87, 83, 88,
- 88, 88, 88, 91, 92, 93, 93, 93, 93, 94,
- 94, 96, 96, 96, 97, 97, 98, 98, 99, 99,
- 100, 100, 89, 89, 95, 90, 101, 101, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 104, 105,
- 105, 105, 105, 107, 108, 109, 109, 84, 84, 110,
- 110, 112, 112, 85, 85, 85, 65, 65, 76, 114,
- 63, 115, 116, 86, 86, 86, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 118,
- 118, 119, 119, 119, 119, 119, 119, 119, 119, 122,
- 70, 70, 70, 70, 123, 124, 123, 124, 123, 124,
- 123, 124, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 125, 73, 113, 113, 113, 113,
- 127, 128, 127, 128, 127, 128, 127, 128, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 106, 106, 106, 106, 131, 132, 131,
- 132, 131, 131, 132, 132, 133, 133, 133, 133, 135,
- 71, 71, 71, 136, 136, 137, 62, 60, 61, 138,
- 121, 82, 130, 134, 120, 139, 139, 139, 139, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 74,
- 69, 69, 77, 111, 102, 102, 102, 102, 102, 140};
-
-const short QXmlStreamReader_Table::rhs [] = {
- 2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
- 1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
- 4, 1, 3, 1, 1, 1, 2, 2, 2, 0,
- 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 1, 1, 1, 1, 2, 1, 1, 1, 0, 2,
- 2, 2, 6, 6, 1, 5, 1, 5, 3, 5,
- 0, 1, 6, 8, 4, 2, 1, 5, 1, 1,
- 1, 1, 1, 1, 1, 1, 6, 7, 1, 2,
- 2, 1, 4, 3, 3, 1, 2, 5, 6, 4,
- 6, 3, 5, 5, 3, 4, 4, 5, 2, 3,
- 2, 2, 4, 5, 5, 7, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
- 2, 2, 3, 3, 2, 2, 2, 2, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
- 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 2, 3, 3, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 5,
- 0, 1, 3, 1, 3, 2, 4, 3, 5, 1,
- 3, 3, 3, 3, 4, 1, 1, 2, 2, 2,
- 4, 2, 2, 2, 2, 2, 2, 2, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 2};
-
-const short QXmlStreamReader_Table::action_default [] = {
- 10, 259, 0, 2, 1, 0, 125, 117, 119, 120,
- 127, 129, 123, 11, 114, 108, 0, 109, 128, 111,
- 115, 113, 121, 124, 126, 107, 110, 112, 118, 116,
- 131, 122, 240, 12, 254, 136, 250, 253, 0, 130,
- 140, 257, 16, 252, 138, 137, 0, 256, 139, 259,
- 231, 258, 255, 0, 0, 264, 0, 247, 246, 0,
- 249, 248, 245, 241, 99, 263, 0, 236, 0, 0,
- 260, 97, 98, 101, 0, 132, 134, 133, 135, 0,
- 0, 261, 0, 0, 176, 0, 173, 165, 167, 168,
- 142, 154, 171, 162, 156, 157, 153, 159, 163, 161,
- 169, 172, 152, 155, 158, 160, 166, 164, 174, 170,
- 150, 175, 0, 144, 148, 146, 151, 141, 149, 0,
- 147, 143, 145, 0, 15, 14, 262, 0, 22, 21,
- 261, 30, 0, 20, 0, 0, 32, 37, 31, 0,
- 33, 261, 0, 34, 0, 24, 0, 35, 0, 26,
- 36, 25, 0, 242, 41, 40, 261, 43, 49, 261,
- 42, 0, 44, 261, 49, 261, 0, 261, 0, 49,
- 0, 48, 46, 47, 51, 52, 261, 261, 0, 57,
- 261, 54, 261, 0, 58, 0, 55, 261, 53, 261,
- 0, 56, 65, 0, 261, 61, 261, 0, 59, 62,
- 63, 0, 261, 0, 0, 60, 64, 45, 50, 66,
- 0, 39, 0, 0, 261, 0, 94, 95, 0, 0,
- 0, 0, 261, 0, 210, 201, 203, 205, 178, 190,
- 208, 199, 193, 191, 194, 189, 196, 198, 206, 209,
- 188, 192, 195, 197, 202, 200, 204, 207, 211, 213,
- 212, 186, 0, 0, 243, 180, 184, 182, 0, 0,
- 93, 187, 177, 185, 0, 183, 179, 181, 92, 0,
- 96, 0, 0, 0, 0, 0, 261, 86, 261, 0,
- 262, 0, 87, 0, 89, 69, 74, 73, 70, 71,
- 72, 261, 75, 76, 0, 0, 0, 269, 268, 266,
- 267, 265, 67, 261, 0, 261, 0, 0, 68, 77,
- 261, 0, 261, 0, 0, 78, 0, 79, 0, 82,
- 85, 0, 0, 215, 225, 224, 0, 227, 229, 228,
- 226, 0, 244, 217, 221, 219, 223, 214, 222, 0,
- 220, 216, 218, 0, 81, 80, 0, 83, 0, 84,
- 88, 100, 0, 38, 0, 0, 0, 0, 91, 90,
- 0, 103, 23, 27, 29, 28, 0, 0, 261, 262,
- 0, 261, 0, 106, 105, 261, 0, 104, 102, 0,
- 0, 18, 261, 17, 0, 19, 0, 0, 251, 0,
- 261, 0, 239, 0, 232, 238, 0, 237, 234, 261,
- 261, 262, 233, 235, 0, 261, 0, 230, 261, 0,
- 261, 0, 231, 0, 0, 13, 270, 9, 5, 8,
- 4, 0, 7, 259, 6, 0, 3};
-
-const short QXmlStreamReader_Table::goto_default [] = {
- 2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
- 249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
- 169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
- 139, 159, 160, 157, 168, 167, 209, 165, 164, 166,
- 187, 180, 196, 200, 303, 302, 295, 321, 320, 319,
- 279, 277, 278, 142, 56, 141, 222, 38, 34, 148,
- 39, 48, 40, 248, 45, 36, 119, 112, 330, 111,
- 264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
- 50, 51, 59, 0};
-
-const short QXmlStreamReader_Table::action_index [] = {
- -21, -57, 33, 119, 960, 70, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, 105, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, 40, -57,
- 795, -57, 47, -57, -57, -57, 107, -57, -57, -57,
- 84, -57, -57, -38, 80, -57, 12, -57, -57, 97,
- -57, -57, -57, -57, -57, -57, 13, -57, 56, 34,
- -57, -57, -57, -57, 51, -57, -57, -57, -57, 53,
- 57, 84, 300, 255, -57, 84, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 355, -57, -57, -57, -57, -57, -57, 326,
- -57, -57, -57, 48, -57, -57, -57, 50, -57, -57,
- 84, 155, 32, -57, 38, 22, -57, -57, -57, 115,
- -57, 35, 156, -57, 173, -57, 245, -57, 44, -57,
- -57, -57, 16, -57, -57, -57, 29, -57, 116, 29,
- -57, 133, -57, 29, 129, 84, 15, 29, -22, 121,
- 74, -57, -57, -57, -57, 82, 29, 29, 88, -57,
- 29, 7, 29, 86, -57, 83, -57, 27, 19, 26,
- 94, -57, -57, 106, 29, 3, 29, -8, -57, -57,
- -57, 104, 29, -6, -7, -57, -57, -57, -57, -57,
- 17, -57, -2, 11, 29, 18, -57, -57, 850, 65,
- 465, 67, 84, 135, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 630, 24, -57, -57, -57, -57, 84, 76,
- -57, -57, -57, -57, 740, -57, -57, -57, -57, 39,
- -57, 23, 21, 14, 78, 22, 84, -57, 84, 184,
- 20, 31, -57, 41, -57, -57, -57, -57, -57, -57,
- -57, 84, -57, -57, 36, 126, 162, -57, -57, -57,
- -57, -57, -57, 29, 79, 29, 29, 160, -57, -57,
- 29, 145, 29, 75, 29, -57, 575, -57, 410, -57,
- -57, 110, 64, -57, -57, -57, 685, -57, -57, -57,
- -57, -17, -57, -57, -57, -57, -57, -57, -57, 520,
- -57, -57, -57, 29, -57, -57, 61, -57, 29, -57,
- -57, -57, 29, -57, 29, 29, -15, 29, -57, -57,
- 29, -57, -57, -57, -57, -57, 95, 43, 29, 45,
- 9, 29, 10, -57, -57, 29, 2, -57, -57, -24,
- 190, -57, 29, -57, 1, -57, 905, 150, -57, -26,
- 29, 0, -57, 109, -26, -57, 8, -57, -57, 29,
- 29, -19, -57, -57, -11, 29, 59, -57, 29, -5,
- 29, 103, 29, -16, 6, -57, -57, -57, -57, -57,
- -57, 69, -57, -57, -57, 905, -57,
-
- -84, -84, -84, 204, 75, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 7, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 101, -84, -84, -84, -84, -84, -84, -84, -84, 64,
- 54, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 68, -84, 30, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 32, -84, -16, -7, -84, 42, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, 45, -84, -84, -84, -84, -84, -84, 44,
- -84, -84, -84, 33, -84, -84, -84, -84, -84, -84,
- 36, 108, -84, -84, -84, 69, -84, -84, -84, 62,
- -84, 63, -84, -84, -84, -84, 118, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -2, -84, -84, -10,
- -84, -84, -84, 25, -21, 11, -84, 20, -84, -25,
- -84, -84, -84, -84, -84, -84, 1, 2, -36, -84,
- -9, -84, 5, -13, -84, -8, -84, 6, -84, 8,
- 12, -84, -84, -84, 23, -84, 4, -1, -84, -84,
- -84, -84, 0, -84, -14, -84, -84, -84, -84, -84,
- -84, -84, 55, -84, 58, -84, -84, -84, -84, 53,
- 47, 123, 67, 66, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -15, -84, -84, -84, -84, -84, 41, 40,
- -84, -84, -84, -84, -46, -84, -84, -84, -84, -84,
- -84, 35, -84, 34, 37, 18, 70, -84, 89, -84,
- 43, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, 48, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 31, -84, 29, 27, 17, -84, -84,
- 38, 24, 39, -84, 49, -84, 71, -84, 93, -84,
- -84, -84, -12, -84, -84, -84, 94, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, 78,
- -84, -84, -84, 50, -84, -84, 46, -84, 56, -84,
- -84, -84, 60, -84, 61, 59, 51, 57, -84, -84,
- 14, -84, -84, -84, -84, -84, -11, -6, 72, -5,
- -84, -3, -84, -84, -84, 52, -84, -84, -84, -20,
- 77, -84, 21, -84, -84, -84, 76, 16, -84, 19,
- 26, -84, -84, -84, 10, -84, -84, -84, -84, 80,
- 13, 73, -84, -84, -84, 22, -27, -84, 9, -84,
- 28, 15, 82, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 3, -84, 98, -84};
-
-const short QXmlStreamReader_Table::action_info [] = {
- 65, 332, 65, 405, 392, 385, 377, 65, 414, 410,
- 415, 55, 397, 374, 373, 217, 206, 408, 65, 65,
- 207, 211, 216, 1, 55, 199, 182, 192, 70, 70,
- 63, 70, 189, 416, 153, 350, 133, 70, 72, 55,
- 65, 351, 254, 270, 73, 284, 65, 310, 55, 65,
- 83, 82, 83, 82, 129, 83, 82, 54, 70, 128,
- 83, 82, 66, 64, 83, 82, 318, 316, 318, 316,
- 54, 212, 83, 82, 83, 82, 54, 55, 367, 366,
- 69, 80, 79, 83, 82, 163, 70, 314, 305, 272,
- 55, 306, 305, 354, 163, 177, 55, 163, 379, 163,
- 65, 176, 83, 82, 55, 163, 58, 57, 0, 65,
- 83, 82, 65, 395, 65, 62, 203, 202, 195, 194,
- 65, 417, 16, 61, 60, 396, 156, 272, 0, 66,
- 64, 65, 317, 318, 316, 378, 379, 171, 173, 162,
- 172, 54, 171, 173, 163, 172, 0, 345, 344, 343,
- 171, 173, 0, 172, 0, 155, 154, 70, 134, 65,
- 0, 55, 297, 220, 218, 298, 389, 0, 300, 0,
- 135, 301, 299, 33, 66, 64, 65, 297, 0, 297,
- 298, 0, 298, 300, 0, 300, 301, 299, 301, 299,
- 221, 219, 70, 272, 381, 291, 0, 0, 0, 128,
- 13, 0, 0, 273, 271, 274, 275, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 287, 294, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 285, 288, 289, 290, 286, 292, 293, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 70, 134, 0,
- 0, 0, 0, 0, 0, 362, 0, 108, 0, 103,
- 135, 94, 117, 116, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 0, 94, 102, 90, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 108, 0,
- 103, 0, 94, 121, 120, 95, 104, 97, 105, 99,
- 93, 98, 107, 87, 106, 88, 89, 100, 109, 92,
- 101, 86, 96, 91, 0, 0, 0, 108, 0, 103,
- 0, 94, 114, 113, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 337, 336, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 246, 233, 241,
- 223, 232, 262, 261, 234, 242, 236, 243, 237, 231,
- 0, 245, 225, 244, 226, 227, 238, 247, 230, 239,
- 224, 235, 229, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 341, 340, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 324, 323, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 256, 255, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 334, 333, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 266, 265, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 0, 25,
- 74, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 240, 228, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 387, 25,
- 5, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 32, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 30, 16, 25, 5, 15, 24, 10, 17,
- 26, 19, 27, 21, 14, 20, 29, 7, 28, 8,
- 9, 22, 31, 12, 23, 6, 18, 11, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 32, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 0,
-
- 380, 179, 210, 181, 425, 368, 205, 375, 371, 372,
- 161, 208, 204, 178, 185, 174, 201, 183, 188, 198,
- 190, 409, 407, 175, 184, 404, 267, 67, 412, 186,
- 400, 361, 193, 384, 406, 197, 67, 170, 391, 390,
- 411, 307, 331, 304, 309, 125, 124, 71, 132, 191,
- 311, 313, 110, 260, 352, 276, 0, 257, 259, 123,
- 296, 118, 308, 348, 376, 386, 315, 346, 312, 258,
- 215, 394, 360, 349, 358, 213, 359, 353, 356, 269,
- 0, 328, 281, 0, 370, 44, 44, 280, 328, 369,
- 0, 355, 402, 400, 383, 347, 413, 401, 382, 394,
- 158, 283, 426, 328, 328, 357, 280, 0, 44, 214,
- 0, 76, 122, 115, 137, 0, 150, 0, 143, 263,
- 253, 0, 68, 152, 137, 151, 150, 144, 143, 0,
- 0, 0, 0, 0, 327, 365, 268, 144, 35, 35,
- 282, 327, 363, 364, 0, 0, 0, 0, 0, 0,
- 0, 403, 0, 0, 342, 0, 327, 327, 0, 0,
- 0, 35, 78, 0, 75, 77, 0, 0, 0, 338,
- 335, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 423, 0, 420,
- 418, 424, 422, 419, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 421, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0};
-
-const short QXmlStreamReader_Table::action_check [] = {
- 26, 18, 26, 14, 4, 4, 4, 26, 24, 14,
- 4, 26, 4, 4, 4, 4, 22, 55, 26, 26,
- 42, 4, 4, 44, 26, 22, 19, 12, 2, 2,
- 18, 2, 13, 0, 18, 4, 4, 2, 4, 26,
- 26, 20, 18, 4, 4, 4, 26, 11, 26, 26,
- 7, 8, 7, 8, 4, 7, 8, 6, 2, 9,
- 7, 8, 24, 25, 7, 8, 7, 8, 7, 8,
- 6, 36, 7, 8, 7, 8, 6, 26, 34, 35,
- 24, 34, 35, 7, 8, 11, 2, 12, 13, 20,
- 26, 12, 13, 15, 11, 13, 26, 11, 29, 11,
- 26, 19, 7, 8, 26, 11, 26, 27, -1, 26,
- 7, 8, 26, 4, 26, 18, 12, 13, 12, 13,
- 26, 2, 3, 26, 27, 16, 11, 20, -1, 24,
- 25, 26, 6, 7, 8, 28, 29, 21, 22, 6,
- 24, 6, 21, 22, 11, 24, -1, 37, 38, 39,
- 21, 22, -1, 24, -1, 40, 41, 2, 3, 26,
- -1, 26, 17, 7, 8, 20, 16, -1, 23, -1,
- 15, 26, 27, 54, 24, 25, 26, 17, -1, 17,
- 20, -1, 20, 23, -1, 23, 26, 27, 26, 27,
- 34, 35, 2, 20, 4, 11, -1, -1, -1, 9,
- 45, -1, -1, 30, 31, 32, 33, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 32, 33, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 47, 48, 49, 50, 51, 52, 53, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, -1,
- -1, -1, -1, -1, -1, 10, -1, 2, -1, 4,
- 15, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, -1, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 2, -1,
- 4, -1, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, -1, -1, -1, 2, -1, 4,
- -1, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, 46, -1, -1, -1, -1, -1, -1, -1, 54,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, 46, -1, -1, -1,
- -1, -1, -1, -1, 54, -1, -1,
-
- 20, 37, 12, 12, 1, 16, 20, 13, 13, 12,
- 12, 36, 12, 12, 12, 36, 12, 12, 12, 20,
- 12, 12, 49, 12, 37, 12, 72, 20, 13, 37,
- 20, 17, 12, 12, 12, 12, 20, 12, 12, 20,
- 12, 12, 54, 12, 17, 13, 13, 17, 12, 37,
- 12, 12, 68, 13, 20, 20, -1, 72, 17, 17,
- 12, 68, 45, 20, 12, 1, 17, 17, 44, 16,
- 12, 17, 54, 17, 17, 12, 17, 17, 17, 12,
- -1, 10, 12, -1, 12, 10, 10, 17, 10, 17,
- -1, 54, 12, 20, 17, 49, 14, 17, 21, 17,
- 38, 12, 4, 10, 10, 54, 17, -1, 10, 54,
- -1, 10, 68, 68, 6, -1, 8, -1, 10, 72,
- 54, -1, 54, 54, 6, 17, 8, 19, 10, -1,
- -1, -1, -1, -1, 63, 17, 13, 19, 63, 63,
- 51, 63, 24, 25, -1, -1, -1, -1, -1, -1,
- -1, 78, -1, -1, 76, -1, 63, 63, -1, -1,
- -1, 63, 61, -1, 63, 64, -1, -1, -1, 76,
- 76, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3, -1, 5,
- 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 19, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
-
-
-template <typename T> class QXmlStreamSimpleStack {
T *data;
qsizetype tos, cap;
public:
- inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
+ inline QXmlStreamSimpleStack()
+ : data(nullptr), tos(-1), cap(0)
+ {}
+ inline ~QXmlStreamSimpleStack()
+ {
+ if (data) {
+ std::destroy_n(data, size());
+ free(data);
+ }
+ }
- inline void reserve(qsizetype extraCapacity) {
+ inline void reserve(qsizetype extraCapacity)
+ {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
@@ -658,11 +144,11 @@ public:
}
}
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
+ inline T &push() { reserve(1); return rawPush(); }
+ inline T &rawPush() { return *new (data + (++tos)) T; }
inline const T &top() const { return data[tos]; }
inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
+ inline T pop() { T t = std::move(data[tos]); std::destroy_at(data + tos); --tos; return t; }
inline T &operator[](qsizetype index) { return data[index]; }
inline const T &at(qsizetype index) const { return data[index]; }
inline qsizetype size() const { return tos + 1; }
@@ -680,7 +166,6 @@ public:
const T *cend() const { return end(); }
};
-
class QXmlStream
{
Q_DECLARE_TR_FUNCTIONS(QXmlStream)
@@ -690,16 +175,16 @@ class QXmlStreamPrivateTagStack {
public:
struct NamespaceDeclaration
{
- QStringRef prefix;
- QStringRef namespaceUri;
+ XmlStringRef prefix;
+ XmlStringRef namespaceUri;
};
struct Tag
{
- QStringRef name;
- QStringRef qualifiedName;
+ XmlStringRef name;
+ XmlStringRef qualifiedName;
NamespaceDeclaration namespaceDeclaration;
- int tagStackStringStorageSize;
+ qsizetype tagStackStringStorageSize;
qsizetype namespaceDeclarationsSize;
};
@@ -707,32 +192,26 @@ public:
QXmlStreamPrivateTagStack();
QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
QString tagStackStringStorage;
- int tagStackStringStorageSize;
- int initialTagStackStringStorageSize;
+ qsizetype tagStackStringStorageSize;
+ qsizetype initialTagStackStringStorageSize;
bool tagsDone;
- inline QStringRef addToStringStorage(const QStringRef &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- inline QStringRef addToStringStorage(const QString &s) {
- return addToStringStorage(qToStringViewIgnoringNull(s));
- }
- QStringRef addToStringStorage(QStringView s)
+ XmlStringRef addToStringStorage(QAnyStringView s)
{
- int pos = tagStackStringStorageSize;
- int sz = s.size();
+ qsizetype pos = tagStackStringStorageSize;
if (pos != tagStackStringStorage.size())
tagStackStringStorage.resize(pos);
- tagStackStringStorage.append(s.data(), sz);
+ s.visit([&](auto s) { tagStackStringStorage.append(s); });
+ qsizetype sz = (tagStackStringStorage.size() - pos);
tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
+ return XmlStringRef(&tagStackStringStorage, pos, sz);
}
QXmlStreamSimpleStack<Tag> tagStack;
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
+ inline Tag tagStack_pop() {
+ Tag tag = tagStack.pop();
tagStackStringStorageSize = tag.tagStackStringStorageSize;
namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
tagsDone = tagStack.isEmpty();
@@ -748,8 +227,8 @@ public:
class QXmlStreamEntityResolver;
-#ifndef QT_NO_XMLSTREAMREADER
-class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
+class QXmlStreamReaderPrivate : public QXmlStreamGrammar, public QXmlStreamPrivateTagStack
+{
QXmlStreamReader *q_ptr;
Q_DECLARE_PUBLIC(QXmlStreamReader)
public:
@@ -762,14 +241,14 @@ public:
uchar firstByte;
qint64 nbytesread;
QString readBuffer;
- int readBufferPos;
+ qsizetype readBufferPos;
QXmlStreamSimpleStack<uint> putStack;
struct Entity {
Entity() = default;
Entity(const QString &name, const QString &value)
: name(name), value(value), external(false), unparsed(false), literal(false),
hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(QLatin1String name, QLatin1String value)
+ static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
{ Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
QString name, value;
uint external : 1;
@@ -783,10 +262,17 @@ public:
// are guaranteed to have the same lifetime as the referenced data:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
- QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ struct QEntityReference
+ {
+ QHash<QStringView, Entity> *hash;
+ QStringView name;
+ };
+ QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
int entityExpansionLimit = 4096;
int entityLength = 0;
- inline bool referenceEntity(Entity &entity) {
+ inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
+ {
+ Q_ASSERT(hash);
if (entity.isCurrentlyReferenced) {
raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
return false;
@@ -800,7 +286,7 @@ public:
return false;
}
entity.isCurrentlyReferenced = true;
- entityReferenceStack.push() = &entity;
+ entityReferenceStack.push() = { hash, entity.name };
injectToken(ENTITY_DONE);
return true;
}
@@ -811,6 +297,17 @@ public:
QStringDecoder decoder;
bool atEnd;
+ enum class XmlContext
+ {
+ Prolog,
+ Body,
+ };
+
+ XmlContext currentContext = XmlContext::Prolog;
+ bool foundDTD = false;
+ bool isValidToken(QXmlStreamReader::TokenType type);
+ void checkToken();
+
/*!
\sa setType()
*/
@@ -827,7 +324,7 @@ public:
QXmlStreamAttributes attributes;
- QStringRef namespaceForPrefix(const QStringRef &prefix);
+ XmlStringRef namespaceForPrefix(QStringView prefix);
void resolveTag();
void resolvePublicNamespaces();
void resolveDtd();
@@ -835,36 +332,36 @@ public:
bool checkStartDocument();
void startDocument();
void parseError();
- void checkPublicLiteral(const QStringRef &publicId);
+ void checkPublicLiteral(QStringView publicId);
bool scanDtd;
- QStringRef lastAttributeValue;
+ XmlStringRef lastAttributeValue;
bool lastAttributeIsCData;
struct DtdAttribute {
- QStringRef tagName;
- QStringRef attributeQualifiedName;
- QStringRef attributePrefix;
- QStringRef attributeName;
- QStringRef defaultValue;
+ XmlStringRef tagName;
+ XmlStringRef attributeQualifiedName;
+ XmlStringRef attributePrefix;
+ XmlStringRef attributeName;
+ XmlStringRef defaultValue;
bool isCDATA;
bool isNamespaceAttribute;
};
QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
struct NotationDeclaration {
- QStringRef name;
- QStringRef publicId;
- QStringRef systemId;
+ XmlStringRef name;
+ XmlStringRef publicId;
+ XmlStringRef systemId;
};
QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
QXmlStreamNotationDeclarations publicNotationDeclarations;
QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
struct EntityDeclaration {
- QStringRef name;
- QStringRef notationName;
- QStringRef publicId;
- QStringRef systemId;
- QStringRef value;
+ XmlStringRef name;
+ XmlStringRef notationName;
+ XmlStringRef publicId;
+ XmlStringRef systemId;
+ XmlStringRef value;
bool parameter;
bool external;
inline void clear() {
@@ -879,12 +376,12 @@ public:
QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
QXmlStreamEntityDeclarations publicEntityDeclarations;
- QStringRef text;
+ XmlStringRef text;
- QStringRef prefix, namespaceUri, qualifiedName, name;
- QStringRef processingInstructionTarget, processingInstructionData;
- QStringRef dtdName, dtdPublicId, dtdSystemId;
- QStringRef documentVersion, documentEncoding;
+ XmlStringRef prefix, namespaceUri, qualifiedName, name;
+ XmlStringRef processingInstructionTarget, processingInstructionData;
+ XmlStringRef dtdName, dtdPublicId, dtdSystemId;
+ XmlStringRef documentVersion, documentEncoding;
uint isEmptyElement : 1;
uint isWhitespace : 1;
uint isCDATA : 1;
@@ -898,6 +395,7 @@ public:
uint hasExternalDtdSubset : 1;
uint lockEncoding : 1;
uint namespaceProcessing : 1;
+ uint hasStandalone : 1; // TODO: expose in public API
int resumeReduction;
void resume(int rule);
@@ -914,9 +412,9 @@ public:
int tos;
int stack_size;
struct Value {
- int pos;
- int len;
- int prefix;
+ qsizetype pos; // offset into textBuffer
+ qsizetype len; // length incl. prefix (if any)
+ qint16 prefix; // prefix of a name (as in "prefix:name") limited to 4k in fastScanName()
ushort c;
};
@@ -938,39 +436,39 @@ public:
};
QXmlStreamSimpleStack<Attribute> attributeStack;
- inline QStringRef symString(int index) {
+ inline XmlStringRef symString(int index) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
QStringView symView(int index) const
{
const Value &symbol = sym(index);
return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
}
- inline QStringRef symName(int index) {
+ inline XmlStringRef symName(int index) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
}
- inline QStringRef symString(int index, int offset) {
+ inline XmlStringRef symString(int index, int offset) {
const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
}
- inline QStringRef symPrefix(int index) {
+ inline XmlStringRef symPrefix(int index) {
const Value &symbol = sym(index);
if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
+ return XmlStringRef();
}
- inline QStringRef symString(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
+ inline XmlStringRef symString(const Value &symbol) {
+ return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
- inline QStringRef symName(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
+ inline XmlStringRef symName(const Value &symbol) {
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
}
- inline QStringRef symPrefix(const Value &symbol) {
+ inline XmlStringRef symPrefix(const Value &symbol) {
if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
+ return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
+ return XmlStringRef();
}
inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
@@ -1009,11 +507,11 @@ public:
// scan optimization functions. Not strictly necessary but LALR is
// not very well suited for scanning fast
- int fastScanLiteralContent();
- int fastScanSpace();
- int fastScanContentCharList();
- int fastScanName(int *prefix = nullptr);
- inline int fastScanNMTOKEN();
+ qsizetype fastScanLiteralContent();
+ qsizetype fastScanSpace();
+ qsizetype fastScanContentCharList();
+ std::optional<qsizetype> fastScanName(Value *val = nullptr);
+ inline qsizetype fastScanNMTOKEN();
bool parse();
@@ -1021,6 +519,7 @@ public:
void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
void raiseWellFormedError(const QString &message);
+ void raiseNamePrefixTooLongError();
QXmlStreamEntityResolver *entityResolver;
@@ -1032,955 +531,12 @@ private:
*/
inline void setType(const QXmlStreamReader::TokenType t)
{
- if(type != QXmlStreamReader::Invalid)
+ if (type != QXmlStreamReader::Invalid)
type = t;
}
};
-bool QXmlStreamReaderPrivate::parse()
-{
- // cleanup currently reported token
-
- switch (type) {
- case QXmlStreamReader::StartElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- publicNamespaceDeclarations.clear();
- attributes.clear();
- if (isEmptyElement) {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- isEmptyElement = false;
- return true;
- }
- clearTextBuffer();
- break;
- case QXmlStreamReader::EndElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::DTD:
- publicNotationDeclarations.clear();
- publicEntityDeclarations.clear();
- dtdName.clear();
- dtdPublicId.clear();
- dtdSystemId.clear();
- Q_FALLTHROUGH();
- case QXmlStreamReader::Comment:
- case QXmlStreamReader::Characters:
- isCDATA = false;
- isWhitespace = true;
- text.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::EntityReference:
- text.clear();
- name.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::ProcessingInstruction:
- processingInstructionTarget.clear();
- processingInstructionData.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::NoToken:
- case QXmlStreamReader::Invalid:
- break;
- case QXmlStreamReader::StartDocument:
- lockEncoding = true;
- documentVersion.clear();
- documentEncoding.clear();
- if (decoder.isValid() && decoder.hasError()) {
- raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
- readBuffer.clear();
- return false;
- }
- Q_FALLTHROUGH();
- default:
- clearTextBuffer();
- ;
- }
-
- setType(QXmlStreamReader::NoToken);
-
-
- // the main parse loop
- int act, r;
-
- if (resumeReduction) {
- act = state_stack[tos-1];
- r = resumeReduction;
- resumeReduction = 0;
- goto ResumeReduction;
- }
-
- act = state_stack[tos];
-
- forever {
- if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
- uint cu = getChar();
- token = NOTOKEN;
- token_char = cu == ~0U ? cu : ushort(cu);
- if ((cu != ~0U) && (cu & 0xff0000)) {
- token = cu >> 16;
- } else switch (token_char) {
- case 0xfffe:
- case 0xffff:
- token = ERROR;
- break;
- case '\r':
- token = SPACE;
- if (cu == '\r') {
- if ((token_char = filterCarriageReturn())) {
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- break;
- }
- } else {
- break;
- }
- Q_FALLTHROUGH();
- case ~0U: {
- token = EOF_SYMBOL;
- if (!tagsDone && !inParseEntity) {
- int a = t_action(act, token);
- if (a < 0) {
- raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
- return false;
- }
- }
-
- } break;
- case '\n':
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- Q_FALLTHROUGH();
- case ' ':
- case '\t':
- token = SPACE;
- break;
- case '&':
- token = AMPERSAND;
- break;
- case '#':
- token = HASH;
- break;
- case '\'':
- token = QUOTE;
- break;
- case '\"':
- token = DBLQUOTE;
- break;
- case '<':
- token = LANGLE;
- break;
- case '>':
- token = RANGLE;
- break;
- case '[':
- token = LBRACK;
- break;
- case ']':
- token = RBRACK;
- break;
- case '(':
- token = LPAREN;
- break;
- case ')':
- token = RPAREN;
- break;
- case '|':
- token = PIPE;
- break;
- case '=':
- token = EQ;
- break;
- case '%':
- token = PERCENT;
- break;
- case '/':
- token = SLASH;
- break;
- case ':':
- token = COLON;
- break;
- case ';':
- token = SEMICOLON;
- break;
- case ',':
- token = COMMA;
- break;
- case '-':
- token = DASH;
- break;
- case '+':
- token = PLUS;
- break;
- case '*':
- token = STAR;
- break;
- case '.':
- token = DOT;
- break;
- case '?':
- token = QUESTIONMARK;
- break;
- case '!':
- token = BANG;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- token = DIGIT;
- break;
- default:
- if (cu < 0x20)
- token = NOTOKEN;
- else
- token = LETTER;
- break;
- }
- }
-
- act = t_action (act, token);
- if (act == ACCEPT_STATE) {
- // reset the parser in case someone resumes (process instructions can follow a valid document)
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return true;
- } else if (act > 0) {
- if (++tos >= stack_size-1)
- reallocateStack();
-
- Value &val = sym_stack[tos];
- val.c = token_char;
- val.pos = textBuffer.size();
- val.prefix = 0;
- val.len = 1;
- if (token_char)
- textBuffer += QChar(token_char);
-
- state_stack[tos] = act;
- token = -1;
-
-
- } else if (act < 0) {
- r = - act - 1;
-
-#if defined (QLALR_DEBUG)
- int ridx = rule_index[r];
- printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
- ++ridx;
- for (int i = ridx; i < ridx + rhs[r]; ++i) {
- int symbol = rule_info[i];
- if (const char *name = spell[symbol])
- printf (" %s", name);
- else
- printf (" #%d", symbol);
- }
- printf ("\n");
-#endif
-
- tos -= rhs[r];
- act = state_stack[tos++];
- ResumeReduction:
- switch (r) {
-
- case 0:
- setType(QXmlStreamReader::EndDocument);
- break;
-
- case 1:
- if (type != QXmlStreamReader::Invalid) {
- if (hasSeenTag || inParseEntity) {
- setType(QXmlStreamReader::EndDocument);
- } else {
- raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
- // reset the parser
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return false;
- }
- }
- break;
-
- case 10:
- entityReferenceStack.pop()->isCurrentlyReferenced = false;
- if (entityReferenceStack.isEmpty())
- entityLength = 0;
- clearSym();
- break;
-
- case 11:
- if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
- resume(11);
- return false;
- }
- break;
-
- case 12:
- setType(QXmlStreamReader::StartDocument);
- documentVersion = symString(6);
- startDocument();
- break;
-
- case 13:
- hasExternalDtdSubset = true;
- dtdSystemId = symString(2);
- break;
-
- case 14:
- checkPublicLiteral(symString(2));
- dtdPublicId = symString(2);
- dtdSystemId = symString(4);
- hasExternalDtdSubset = true;
- break;
-
- case 16:
- if (!scanPublicOrSystem() && atEnd) {
- resume(16);
- return false;
- }
- dtdName = symString(3);
- break;
-
- case 17:
- case 18:
- dtdName = symString(3);
- Q_FALLTHROUGH();
-
- case 19:
- case 20:
- setType(QXmlStreamReader::DTD);
- text = &textBuffer;
- break;
-
- case 21:
- scanDtd = true;
- break;
-
- case 22:
- scanDtd = false;
- break;
-
- case 37:
- if (!scanString(spell[EMPTY], EMPTY, false)
- && !scanString(spell[ANY], ANY, false)
- && atEnd) {
- resume(37);
- return false;
- }
- break;
-
- case 43:
- if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
- resume(43);
- return false;
- }
- break;
-
- case 68: {
- lastAttributeIsCData = true;
- } break;
-
- case 78:
- if (!scanAfterDefaultDecl() && atEnd) {
- resume(78);
- return false;
- }
- break;
-
- case 83:
- sym(1) = sym(2);
- lastAttributeValue.clear();
- lastAttributeIsCData = false;
- if (!scanAttType() && atEnd) {
- resume(83);
- return false;
- }
- break;
-
- case 84: {
- DtdAttribute &dtdAttribute = dtdAttributes.push();
- dtdAttribute.tagName.clear();
- dtdAttribute.isCDATA = lastAttributeIsCData;
- dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
- dtdAttribute.attributeName = addToStringStorage(symString(1));
- dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
- dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
- || (dtdAttribute.attributePrefix.isEmpty()
- && dtdAttribute.attributeName == QLatin1String("xmlns")));
- if (lastAttributeValue.isNull()) {
- dtdAttribute.defaultValue.clear();
- } else {
- if (dtdAttribute.isCDATA)
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
- else
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
-
- }
- } break;
-
- case 88: {
- if (referenceToUnparsedEntityDetected && !standalone)
- break;
- int n = dtdAttributes.size();
- QStringRef tagName = addToStringStorage(symName(3));
- while (n--) {
- DtdAttribute &dtdAttribute = dtdAttributes[n];
- if (!dtdAttribute.tagName.isNull())
- break;
- dtdAttribute.tagName = tagName;
- for (int i = 0; i < n; ++i) {
- if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
- && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
- dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
- break;
- }
- }
- }
- } break;
-
- case 89: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(89);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(3);
- } break;
-
- case 90: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(90);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(5);
- entityDeclaration.parameter = true;
- } break;
-
- case 91: {
- if (!scanNData() && atEnd) {
- resume(91);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.systemId = symString(3);
- entityDeclaration.external = true;
- } break;
-
- case 92: {
- if (!scanNData() && atEnd) {
- resume(92);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- checkPublicLiteral((entityDeclaration.publicId = symString(3)));
- entityDeclaration.systemId = symString(5);
- entityDeclaration.external = true;
- } break;
-
- case 93: {
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.notationName = symString(3);
- if (entityDeclaration.parameter)
- raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
- }
- Q_FALLTHROUGH();
-
- case 94:
- case 95: {
- if (referenceToUnparsedEntityDetected && !standalone) {
- entityDeclarations.pop();
- break;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- if (!entityDeclaration.external)
- entityDeclaration.value = symString(2);
- auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
- Entity entity(entityDeclaration.name.toString(),
- entityDeclaration.value.toString());
- entity.unparsed = (!entityDeclaration.notationName.isNull());
- entity.external = entityDeclaration.external;
- hash.insert(qToStringViewIgnoringNull(entity.name), entity);
- }
- } break;
-
- case 96: {
- setType(QXmlStreamReader::ProcessingInstruction);
- int pos = sym(4).pos + sym(4).len;
- processingInstructionTarget = symString(3);
- if (scanUntil("?>")) {
- processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
- raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
- }
- else if (!QXmlUtils::isNCName(processingInstructionTarget))
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
- .arg(processingInstructionTarget));
- } else if (type != QXmlStreamReader::Invalid){
- resume(96);
- return false;
- }
- } break;
-
- case 97:
- setType(QXmlStreamReader::ProcessingInstruction);
- processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
- raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
- break;
-
- case 98:
- if (!scanAfterLangleBang() && atEnd) {
- resume(98);
- return false;
- }
- break;
-
- case 99:
- if (!scanUntil("--")) {
- resume(99);
- return false;
- }
- break;
-
- case 100: {
- setType(QXmlStreamReader::Comment);
- int pos = sym(1).pos + 4;
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } break;
-
- case 101: {
- setType(QXmlStreamReader::Characters);
- isCDATA = true;
- isWhitespace = false;
- int pos = sym(2).pos;
- if (scanUntil("]]>", -1)) {
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } else {
- resume(101);
- return false;
- }
- } break;
-
- case 102: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(102);
- return false;
- }
- NotationDeclaration &notationDeclaration = notationDeclarations.push();
- notationDeclaration.name = symString(3);
- } break;
-
- case 103: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId = symString(3);
- notationDeclaration.publicId.clear();
- } break;
-
- case 104: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId.clear();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- } break;
-
- case 105: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- notationDeclaration.systemId = symString(5);
- } break;
-
- case 129:
- isWhitespace = false;
- Q_FALLTHROUGH();
-
- case 130:
- sym(1).len += fastScanContentCharList();
- if (atEnd && !inParseEntity) {
- resume(130);
- return false;
- }
- break;
-
- case 139:
- if (!textBuffer.isEmpty()) {
- setType(QXmlStreamReader::Characters);
- text = &textBuffer;
- }
- break;
-
- case 140:
- case 141:
- clearSym();
- break;
-
- case 142:
- case 143:
- sym(1) = sym(2);
- break;
-
- case 144:
- case 145:
- case 146:
- case 147:
- sym(1).len += sym(2).len;
- break;
-
- case 173:
- if (normalizeLiterals)
- textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
- break;
-
- case 174:
- sym(1).len += fastScanLiteralContent();
- if (atEnd) {
- resume(174);
- return false;
- }
- break;
-
- case 175: {
- if (!QXmlUtils::isPublicID(symString(1))) {
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
- resume(175);
- return false;
- }
- } break;
-
- case 176:
- case 177:
- clearSym();
- break;
-
- case 178:
- case 179:
- sym(1) = sym(2);
- break;
-
- case 180:
- case 181:
- case 182:
- case 183:
- sym(1).len += sym(2).len;
- break;
-
- case 213:
- case 214:
- clearSym();
- break;
-
- case 215:
- case 216:
- sym(1) = sym(2);
- lastAttributeValue = symString(1);
- break;
-
- case 217:
- case 218:
- case 219:
- case 220:
- sym(1).len += sym(2).len;
- break;
-
- case 229: {
- QStringRef prefix = symPrefix(1);
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- namespaceDeclaration.prefix.clear();
-
- const QStringRef ns(symString(5));
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
- else
- namespaceDeclaration.namespaceUri = addToStringStorage(ns);
- } else {
- Attribute &attribute = attributeStack.push();
- attribute.key = sym(1);
- attribute.value = sym(5);
-
- QStringRef attributeQualifiedName = symName(1);
- bool normalize = false;
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
- if (!dtdAttribute.isCDATA
- && dtdAttribute.tagName == qualifiedName
- && dtdAttribute.attributeQualifiedName == attributeQualifiedName
- ) {
- normalize = true;
- break;
- }
- }
- if (normalize) {
- // normalize attribute value (simplify and trim)
- int pos = textBuffer.size();
- int n = 0;
- bool wasSpace = true;
- for (int i = 0; i < attribute.value.len; ++i) {
- QChar c = textBuffer.at(attribute.value.pos + i);
- if (c.unicode() == ' ') {
- if (wasSpace)
- continue;
- wasSpace = true;
- } else {
- wasSpace = false;
- }
- textBuffer += textBuffer.at(attribute.value.pos + i);
- ++n;
- }
- if (wasSpace)
- while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
- --n;
- attribute.value.pos = pos;
- attribute.value.len = n;
- }
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = symString(attribute.key);
- QStringRef namespaceUri = symString(attribute.value);
- attributeStack.pop();
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
- || namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
-
- namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
- namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
- }
- }
- } break;
-
- case 235: {
- normalizeLiterals = true;
- Tag &tag = tagStack_push();
- prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
- name = tag.name = addToStringStorage(symString(2));
- qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
- if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
- raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
- } break;
-
- case 236:
- isEmptyElement = true;
- Q_FALLTHROUGH();
-
- case 237:
- setType(QXmlStreamReader::StartElement);
- resolveTag();
- if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
- raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
- hasSeenTag = true;
- break;
-
- case 238: {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
-
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- if (qualifiedName != symName(3))
- raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
- } break;
-
- case 239:
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
- break;
- }
- setType(QXmlStreamReader::EntityReference);
- name = &unresolvedEntity;
- break;
-
- case 240: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = entityHash.find(reference); it != entityHash.end()) {
- Entity &entity = *it;
- if (entity.unparsed) {
- raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
- } else {
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacement(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference.toString());
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
-
- injectToken(UNRESOLVED_ENTITY);
- unresolvedEntity = symString(2).toString();
- textBuffer.chop(2 + sym(2).len);
- clearSym();
-
- } break;
-
- case 241: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
- referenceToParameterEntityDetected = true;
- Entity &entity = *it;
- if (entity.unparsed || entity.external) {
- referenceToUnparsedEntityDetected = true;
- } else {
- if (referenceEntity(entity))
- putString(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- } else if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
- }
- } break;
-
- case 242:
- sym(1).len += sym(2).len + 1;
- break;
-
- case 243: {
- sym(1).len += sym(2).len + 1;
- QStringView reference = symView(2);
- if (const auto it = entityHash.find(reference); it != entityHash.end()) {
- Entity &entity = *it;
- if (entity.unparsed || entity.value.isNull()) {
- raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
- break;
- }
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacementInAttributeValue(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference.toString());
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
- }
- } break;
-
- case 244: {
- if (char32_t s = resolveCharRef(3)) {
- putStringLiteral(QChar::fromUcs4(s));
- textBuffer.chop(3 + sym(3).len);
- clearSym();
- } else {
- raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
- }
- } break;
-
- case 247:
- case 248:
- sym(1).len += sym(2).len;
- break;
-
- case 259:
- sym(1).len += fastScanSpace();
- if (atEnd) {
- resume(259);
- return false;
- }
- break;
-
- case 262: {
- sym(1).len += fastScanName(&sym(1).prefix);
- if (atEnd) {
- resume(262);
- return false;
- }
- } break;
-
- case 263:
- sym(1).len += fastScanName();
- if (atEnd) {
- resume(263);
- return false;
- }
- break;
-
- case 264:
- case 265:
- case 266:
- case 267:
- case 268:
- sym(1).len += fastScanNMTOKEN();
- if (atEnd) {
- resume(268);
- return false;
- }
-
- break;
-
- default:
- ;
- } // switch
- act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
- if (type != QXmlStreamReader::NoToken)
- return true;
- } else {
- parseError();
- break;
- }
- }
- return false;
-}
-#endif //QT_NO_XMLSTREAMREADER.xml
-
+QT_END_NAMESPACE
#endif // QXMLSTREAM_P_H
diff --git a/src/corelib/serialization/qxmlstreamgrammar.cpp b/src/corelib/serialization/qxmlstreamgrammar.cpp
new file mode 100644
index 0000000000..074b9023ce
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamgrammar.cpp
@@ -0,0 +1,496 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+// This file was generated by qlalr - DO NOT EDIT!
+#include "qxmlstreamgrammar_p.h"
+
+QT_BEGIN_NAMESPACE
+
+const char *const QXmlStreamGrammar::spell [] = {
+ "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[",
+ "]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
+ "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
+ "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
+ "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF",
+ "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0
+};
+
+const short QXmlStreamGrammar::lhs [] = {
+ 57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
+ 67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
+ 66, 79, 78, 80, 80, 80, 80, 80, 80, 80,
+ 81, 81, 81, 81, 81, 81, 81, 87, 83, 88,
+ 88, 88, 88, 91, 92, 93, 93, 93, 93, 94,
+ 94, 96, 96, 96, 97, 97, 98, 98, 99, 99,
+ 100, 100, 89, 89, 95, 90, 101, 101, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 104, 105,
+ 105, 105, 105, 107, 108, 109, 109, 84, 84, 110,
+ 110, 112, 112, 85, 85, 85, 65, 65, 76, 114,
+ 63, 115, 116, 86, 86, 86, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 118,
+ 118, 119, 119, 119, 119, 119, 119, 119, 119, 122,
+ 70, 70, 70, 70, 123, 124, 123, 124, 123, 124,
+ 123, 124, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 125, 73, 113, 113, 113, 113,
+ 127, 128, 127, 128, 127, 128, 127, 128, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 106, 106, 106, 106, 131, 132, 131,
+ 132, 131, 131, 132, 132, 133, 133, 133, 133, 135,
+ 71, 71, 71, 136, 136, 137, 62, 60, 61, 138,
+ 121, 82, 130, 134, 120, 139, 139, 139, 139, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 74,
+ 69, 69, 77, 111, 102, 102, 102, 102, 102, 140
+};
+
+const short QXmlStreamGrammar::rhs [] = {
+ 2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
+ 1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
+ 4, 1, 3, 1, 1, 1, 2, 2, 2, 0,
+ 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
+ 1, 1, 1, 1, 2, 1, 1, 1, 0, 2,
+ 2, 2, 6, 6, 1, 5, 1, 5, 3, 5,
+ 0, 1, 6, 8, 4, 2, 1, 5, 1, 1,
+ 1, 1, 1, 1, 1, 1, 6, 7, 1, 2,
+ 2, 1, 4, 3, 3, 1, 2, 5, 6, 4,
+ 6, 3, 5, 5, 3, 4, 4, 5, 2, 3,
+ 2, 2, 4, 5, 5, 7, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
+ 2, 2, 3, 3, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
+ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 3, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 5,
+ 0, 1, 3, 1, 3, 2, 4, 3, 5, 1,
+ 3, 3, 3, 3, 4, 1, 1, 2, 2, 2,
+ 4, 2, 2, 2, 2, 2, 2, 2, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2
+};
+
+const short QXmlStreamGrammar::action_default [] = {
+ 10, 259, 0, 2, 1, 0, 125, 117, 119, 120,
+ 127, 129, 123, 11, 114, 108, 0, 109, 128, 111,
+ 115, 113, 121, 124, 126, 107, 110, 112, 118, 116,
+ 131, 122, 240, 12, 254, 136, 250, 253, 0, 130,
+ 140, 257, 16, 252, 138, 137, 0, 256, 139, 259,
+ 231, 258, 255, 0, 0, 264, 0, 247, 246, 0,
+ 249, 248, 245, 241, 99, 263, 0, 236, 0, 0,
+ 260, 97, 98, 101, 0, 132, 134, 133, 135, 0,
+ 0, 261, 0, 0, 176, 0, 173, 165, 167, 168,
+ 142, 154, 171, 162, 156, 157, 153, 159, 163, 161,
+ 169, 172, 152, 155, 158, 160, 166, 164, 174, 170,
+ 150, 175, 0, 144, 148, 146, 151, 141, 149, 0,
+ 147, 143, 145, 0, 15, 14, 262, 0, 22, 21,
+ 261, 30, 0, 20, 0, 0, 32, 37, 31, 0,
+ 33, 261, 0, 34, 0, 24, 0, 35, 0, 26,
+ 36, 25, 0, 242, 41, 40, 261, 43, 49, 261,
+ 42, 0, 44, 261, 49, 261, 0, 261, 0, 49,
+ 0, 48, 46, 47, 51, 52, 261, 261, 0, 57,
+ 261, 54, 261, 0, 58, 0, 55, 261, 53, 261,
+ 0, 56, 65, 0, 261, 61, 261, 0, 59, 62,
+ 63, 0, 261, 0, 0, 60, 64, 45, 50, 66,
+ 0, 39, 0, 0, 261, 0, 94, 95, 0, 0,
+ 0, 0, 261, 0, 210, 201, 203, 205, 178, 190,
+ 208, 199, 193, 191, 194, 189, 196, 198, 206, 209,
+ 188, 192, 195, 197, 202, 200, 204, 207, 211, 213,
+ 212, 186, 0, 0, 243, 180, 184, 182, 0, 0,
+ 93, 187, 177, 185, 0, 183, 179, 181, 92, 0,
+ 96, 0, 0, 0, 0, 0, 261, 86, 261, 0,
+ 262, 0, 87, 0, 89, 69, 74, 73, 70, 71,
+ 72, 261, 75, 76, 0, 0, 0, 269, 268, 266,
+ 267, 265, 67, 261, 0, 261, 0, 0, 68, 77,
+ 261, 0, 261, 0, 0, 78, 0, 79, 0, 82,
+ 85, 0, 0, 215, 225, 224, 0, 227, 229, 228,
+ 226, 0, 244, 217, 221, 219, 223, 214, 222, 0,
+ 220, 216, 218, 0, 81, 80, 0, 83, 0, 84,
+ 88, 100, 0, 38, 0, 0, 0, 0, 91, 90,
+ 0, 103, 23, 27, 29, 28, 0, 0, 261, 262,
+ 0, 261, 0, 106, 105, 261, 0, 104, 102, 0,
+ 0, 18, 261, 17, 0, 19, 0, 0, 251, 0,
+ 261, 0, 239, 0, 232, 238, 0, 237, 234, 261,
+ 261, 262, 233, 235, 0, 261, 0, 230, 261, 0,
+ 261, 0, 231, 0, 0, 13, 270, 9, 5, 8,
+ 4, 0, 7, 259, 6, 0, 3
+};
+
+const short QXmlStreamGrammar::goto_default [] = {
+ 2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
+ 249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
+ 169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
+ 139, 159, 160, 157, 168, 167, 209, 165, 164, 166,
+ 187, 180, 196, 200, 303, 302, 295, 321, 320, 319,
+ 279, 277, 278, 142, 56, 141, 222, 38, 34, 148,
+ 39, 48, 40, 248, 45, 36, 119, 112, 330, 111,
+ 264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
+ 50, 51, 59, 0
+};
+
+const short QXmlStreamGrammar::action_index [] = {
+ -39, -57, 7, 112, 918, 40, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, 113, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, 9, -57,
+ 753, -57, 70, -57, -57, -57, 88, -57, -57, -57,
+ 53, -57, -57, -37, 69, -57, -7, -57, -57, 128,
+ -57, -57, -57, -57, -57, -57, 32, -57, 55, 31,
+ -57, -57, -57, -57, 75, -57, -57, -57, -57, 77,
+ 92, 53, 313, 284, -57, 53, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, 258, -57, -57, -57, -57, -57, -57, 368,
+ -57, -57, -57, 153, -57, -57, -57, 71, -57, -57,
+ 53, 150, 21, -57, 39, -3, -57, -57, -57, 101,
+ -57, 46, 203, -57, 148, -57, 173, -57, 35, -57,
+ -57, -57, 29, -57, -57, -57, 53, -57, 108, 53,
+ -57, 125, -57, 53, 126, 53, 24, 53, -1, 104,
+ 57, -57, -57, -57, -57, 54, 53, 37, 66, -57,
+ 53, 5, 53, 61, -57, 60, -57, 53, 15, 53,
+ 48, -57, -57, 49, 53, 16, 53, 18, -57, -57,
+ -57, 38, 53, 20, 19, -57, -57, -57, -57, -57,
+ 27, -57, 17, 26, 53, 25, -57, -57, 533, 153,
+ 643, 153, 53, 97, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
+ -57, -57, 863, 14, -57, -57, -57, -57, 53, 153,
+ -57, -57, -57, -57, 808, -57, -57, -57, -57, 23,
+ -57, -5, 2, 34, 87, 32, 53, -57, 53, 175,
+ 28, 33, -57, 30, -57, -57, -57, -57, -57, -57,
+ -57, 53, -57, -57, 22, 137, 167, -57, -57, -57,
+ -57, -57, -57, 53, 78, 53, 53, 179, -57, -57,
+ 53, 147, 53, 81, -2, -57, 423, -57, 478, -57,
+ -57, 82, 83, -57, -57, -57, 588, -57, -57, -57,
+ -57, 1, -57, -57, -57, -57, -57, -57, -57, 698,
+ -57, -57, -57, 53, -57, -57, 99, -57, 53, -57,
+ -57, -57, 53, -57, 53, 53, -20, 53, -57, -57,
+ 53, -57, -57, -57, -57, -57, 153, 153, 53, 90,
+ 8, 53, 11, -57, -57, 53, 13, -57, -57, -25,
+ 131, -57, 53, -57, 10, -57, 973, 133, -57, -6,
+ 53, 4, -57, 72, -17, -57, 6, -57, -57, 53,
+ 53, -10, -57, -57, 12, 53, 103, -57, 53, -12,
+ 53, 45, 53, -21, 0, -57, -57, -57, -57, -57,
+ -57, 36, -57, -57, -57, 973, -57,
+
+ -84, -84, -84, 118, 69, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 12, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ 103, -84, -84, -84, -84, -84, -84, -84, -84, 71,
+ 64, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 15, -84, 35, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ 48, -84, -5, -34, -84, 38, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, 52, -84, -84, -84, -84, -84, -84, -19,
+ -84, -84, -84, 47, -84, -84, -84, -84, -84, -84,
+ 116, 194, -84, -84, -84, 28, -84, -84, -84, 24,
+ -84, 36, -84, -84, -84, -84, 130, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, 4, -84, -84, -1,
+ -84, -84, -84, 29, 17, 27, -84, 18, -84, 0,
+ -84, -84, -84, -84, -84, -84, -3, -4, -36, -84,
+ 25, -84, 9, -8, -84, -11, -84, 19, -84, 26,
+ 14, -84, -84, -84, 30, -84, -9, -16, -84, -84,
+ -84, -84, 1, -84, -2, -84, -84, -84, -84, -84,
+ -84, -84, 50, -84, 58, -84, -84, -84, -84, 68,
+ -13, 62, 33, -7, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -26, -84, -84, -84, -84, -84, 51, 37,
+ -84, -84, -84, -84, -57, -84, -84, -84, -84, -84,
+ -84, 3, -84, -20, -49, -47, 79, -84, 99, -84,
+ 20, -84, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, 42, -84, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, 55, -84, 53, 49, 41, -84, -84,
+ 46, 34, 45, -84, 39, -84, 85, -84, 96, -84,
+ -84, -84, 31, -84, -84, -84, 97, -84, -84, -84,
+ -84, -84, -84, -84, -84, -84, -84, -84, -84, 100,
+ -84, -84, -84, 66, -84, -84, 43, -84, 60, -84,
+ -84, -84, 57, -84, 54, 56, 40, 59, -84, -84,
+ 63, -84, -84, -84, -84, -84, 8, 7, 76, 6,
+ -84, 5, -84, -84, -84, 2, -84, -84, -84, -10,
+ 80, -84, -6, -84, -84, -84, 89, -18, -84, 44,
+ 32, -84, -84, -84, 23, -84, -84, -84, -84, 88,
+ 21, 78, -84, -84, -84, 16, -22, -84, 13, -84,
+ 10, 22, 73, -84, -84, -84, -84, -84, -84, -84,
+ -84, -84, -84, 11, -84, 98, -84
+};
+
+const short QXmlStreamGrammar::action_info [] = {
+ 70, 65, 410, 414, 415, 1, 55, 416, 392, 65,
+ 397, 63, 374, 73, 385, 373, 65, 377, 408, 332,
+ 65, 65, 351, 55, 182, 133, 405, 270, 189, 216,
+ 217, 211, 254, 310, 284, 72, 192, 350, 199, 70,
+ 0, 207, 206, 55, 65, 65, 54, 153, 70, 0,
+ 203, 202, 83, 82, 65, 70, 272, 70, 55, 163,
+ 65, 195, 194, 66, 64, 379, 55, 177, 163, 367,
+ 366, 163, 163, 176, 65, 129, 395, 163, 0, 69,
+ 128, 54, 212, 65, 83, 82, 65, 65, 396, 54,
+ 306, 305, 65, 314, 305, 58, 57, 83, 82, 83,
+ 82, 55, 354, 54, 80, 79, 318, 316, 272, 55,
+ 318, 316, 156, 55, 417, 16, 378, 379, 0, 345,
+ 344, 343, 0, 55, 0, 171, 173, 0, 172, 171,
+ 173, 162, 172, 70, 0, 381, 163, 66, 64, 65,
+ 128, 155, 154, 317, 318, 316, 62, 171, 173, 389,
+ 172, 65, 70, 134, 61, 60, 0, 66, 64, 65,
+ 83, 82, 0, 0, 297, 135, 33, 298, 272, 0,
+ 300, 0, 0, 301, 299, 70, 134, 0, 273, 271,
+ 274, 275, 0, 362, 297, 0, 291, 298, 135, 0,
+ 300, 0, 0, 301, 299, 13, 297, 0, 0, 298,
+ 0, 0, 300, 0, 0, 301, 299, 287, 294, 0,
+ 220, 218, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 285, 288, 289, 290, 286, 292, 293, 0,
+ 0, 0, 0, 0, 0, 0, 0, 221, 219, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 0, 94, 114, 113, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 108, 0, 103, 0,
+ 94, 117, 116, 95, 104, 97, 105, 99, 93, 98,
+ 107, 87, 106, 88, 89, 100, 109, 92, 101, 86,
+ 96, 91, 0, 0, 0, 108, 0, 103, 0, 94,
+ 102, 90, 95, 104, 97, 105, 99, 93, 98, 107,
+ 87, 106, 88, 89, 100, 109, 92, 101, 86, 96,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 0, 94, 121, 120, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 108, 0, 103, 322, 94,
+ 324, 323, 95, 104, 97, 105, 99, 93, 98, 107,
+ 87, 106, 88, 89, 100, 109, 92, 101, 86, 96,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 337, 336, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 240, 228, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 334, 333, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 262, 261, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 108, 0, 103, 322, 94, 341, 340, 95, 104, 97,
+ 105, 99, 93, 98, 107, 87, 106, 88, 89, 100,
+ 109, 92, 101, 86, 96, 91, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 30, 0, 25, 74, 15,
+ 24, 10, 17, 26, 19, 27, 21, 14, 20, 29,
+ 7, 28, 8, 9, 22, 31, 12, 23, 6, 18,
+ 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 246, 233, 241, 223, 232, 266, 265, 234, 242, 236,
+ 243, 237, 231, 0, 245, 225, 244, 226, 227, 238,
+ 247, 230, 239, 224, 235, 229, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 246, 233, 241, 223, 232,
+ 256, 255, 234, 242, 236, 243, 237, 231, 0, 245,
+ 225, 244, 226, 227, 238, 247, 230, 239, 224, 235,
+ 229, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 30, 16, 25, 5, 15, 24, 10, 17, 26, 19,
+ 27, 21, 14, 20, 29, 7, 28, 8, 9, 22,
+ 31, 12, 23, 6, 18, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 32, 0, 0, 0, 0, 0,
+ 0, 0, 33, 0, 0, 30, 387, 25, 5, 15,
+ 24, 10, 17, 26, 19, 27, 21, 14, 20, 29,
+ 7, 28, 8, 9, 22, 31, 12, 23, 6, 18,
+ 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 32,
+ 0, 0, 0, 0, 0, 0, 0, 33, 0, 0,
+
+ 352, 179, 67, 201, 198, 355, 384, 360, 185, 178,
+ 380, 210, 425, 204, 376, 267, 161, 372, 205, 371,
+ 375, 183, 411, 276, 368, 409, 186, 407, 406, 184,
+ 193, 188, 67, 404, 118, 412, 208, 181, 190, 175,
+ 348, 170, 197, 400, 391, 269, 257, 253, 213, 122,
+ 260, 191, 71, 174, 296, 123, 315, 313, 311, 263,
+ 124, 125, 158, 110, 390, 307, 309, 304, 259, 68,
+ 215, 356, 386, 359, 353, 268, 358, 349, 312, 44,
+ 361, 394, 152, 346, 258, 331, 308, 413, 370, 0,
+ 394, 281, 347, 369, 357, 328, 280, 383, 400, 44,
+ 402, 382, 426, 0, 214, 401, 328, 328, 44, 0,
+ 328, 283, 0, 76, 0, 0, 280, 0, 0, 0,
+ 115, 423, 0, 420, 418, 424, 422, 419, 132, 0,
+ 0, 0, 35, 0, 0, 0, 137, 421, 150, 0,
+ 143, 0, 0, 0, 0, 0, 0, 365, 327, 144,
+ 282, 0, 35, 0, 363, 364, 403, 0, 0, 327,
+ 327, 35, 0, 327, 78, 0, 75, 77, 0, 0,
+ 0, 0, 338, 335, 0, 0, 342, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 137, 0, 150, 0, 143, 0, 0, 0, 0, 0,
+ 0, 151, 0, 144, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const short QXmlStreamGrammar::action_check [] = {
+ 2, 26, 14, 24, 4, 44, 26, 0, 4, 26,
+ 4, 18, 4, 4, 4, 4, 26, 4, 55, 18,
+ 26, 26, 20, 26, 19, 4, 14, 4, 13, 4,
+ 4, 4, 18, 11, 4, 4, 12, 4, 22, 2,
+ -1, 42, 22, 26, 26, 26, 6, 18, 2, -1,
+ 12, 13, 7, 8, 26, 2, 20, 2, 26, 11,
+ 26, 12, 13, 24, 25, 29, 26, 13, 11, 34,
+ 35, 11, 11, 19, 26, 4, 4, 11, -1, 24,
+ 9, 6, 36, 26, 7, 8, 26, 26, 16, 6,
+ 12, 13, 26, 12, 13, 26, 27, 7, 8, 7,
+ 8, 26, 15, 6, 34, 35, 7, 8, 20, 26,
+ 7, 8, 11, 26, 2, 3, 28, 29, -1, 37,
+ 38, 39, -1, 26, -1, 21, 22, -1, 24, 21,
+ 22, 6, 24, 2, -1, 4, 11, 24, 25, 26,
+ 9, 40, 41, 6, 7, 8, 18, 21, 22, 16,
+ 24, 26, 2, 3, 26, 27, -1, 24, 25, 26,
+ 7, 8, -1, -1, 17, 15, 54, 20, 20, -1,
+ 23, -1, -1, 26, 27, 2, 3, -1, 30, 31,
+ 32, 33, -1, 10, 17, -1, 11, 20, 15, -1,
+ 23, -1, -1, 26, 27, 45, 17, -1, -1, 20,
+ -1, -1, 23, -1, -1, 26, 27, 32, 33, -1,
+ 7, 8, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, 47, 48, 49, 50, 51, 52, 53, -1,
+ -1, -1, -1, -1, -1, -1, -1, 34, 35, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, -1, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 2, -1, 4, -1,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, -1, -1, -1, 2, -1, 4, -1, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, -1, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, -1, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, -1, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, -1, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, -1, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, -1, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 45, 46, -1, -1, -1, -1, -1,
+ -1, -1, 54, -1, -1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 45, 46,
+ -1, -1, -1, -1, -1, -1, -1, 54, -1, -1,
+
+ 20, 37, 20, 12, 20, 54, 12, 54, 12, 12,
+ 20, 12, 1, 12, 12, 72, 12, 12, 20, 13,
+ 13, 12, 12, 20, 16, 12, 37, 49, 12, 37,
+ 12, 12, 20, 12, 68, 13, 36, 12, 12, 12,
+ 20, 12, 12, 20, 12, 12, 72, 54, 12, 68,
+ 13, 37, 17, 36, 12, 17, 17, 12, 12, 72,
+ 13, 13, 38, 68, 20, 12, 17, 12, 17, 54,
+ 12, 17, 1, 17, 17, 13, 17, 17, 44, 10,
+ 17, 17, 54, 17, 16, 54, 45, 14, 12, -1,
+ 17, 12, 49, 17, 54, 10, 17, 17, 20, 10,
+ 12, 21, 4, -1, 54, 17, 10, 10, 10, -1,
+ 10, 12, -1, 10, -1, -1, 17, -1, -1, -1,
+ 68, 3, -1, 5, 6, 7, 8, 9, 12, -1,
+ -1, -1, 63, -1, -1, -1, 6, 19, 8, -1,
+ 10, -1, -1, -1, -1, -1, -1, 17, 63, 19,
+ 51, -1, 63, -1, 24, 25, 78, -1, -1, 63,
+ 63, 63, -1, 63, 61, -1, 63, 64, -1, -1,
+ -1, -1, 76, 76, -1, -1, 76, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 6, -1, 8, -1, 10, -1, -1, -1, -1, -1,
+ -1, 17, -1, 19, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qxmlstreamgrammar_p.h b/src/corelib/serialization/qxmlstreamgrammar_p.h
new file mode 100644
index 0000000000..80ee8e929f
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamgrammar_p.h
@@ -0,0 +1,128 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// This file was generated by qlalr - DO NOT EDIT!
+#ifndef QXMLSTREAMGRAMMAR_P_H
+#define QXMLSTREAMGRAMMAR_P_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QXmlStreamGrammar
+{
+public:
+ enum VariousConstants {
+ EOF_SYMBOL = 0,
+ AMPERSAND = 5,
+ ANY = 41,
+ ATTLIST = 31,
+ BANG = 25,
+ CDATA = 47,
+ CDATA_START = 28,
+ COLON = 17,
+ COMMA = 19,
+ DASH = 20,
+ DBLQUOTE = 8,
+ DIGIT = 27,
+ DOCTYPE = 29,
+ DOT = 23,
+ ELEMENT = 30,
+ EMPTY = 40,
+ ENTITIES = 51,
+ ENTITY = 32,
+ ENTITY_DONE = 45,
+ EQ = 14,
+ FIXED = 39,
+ HASH = 6,
+ ID = 48,
+ IDREF = 49,
+ IDREFS = 50,
+ IMPLIED = 38,
+ LANGLE = 3,
+ LBRACK = 9,
+ LETTER = 26,
+ LPAREN = 11,
+ NDATA = 36,
+ NMTOKEN = 52,
+ NMTOKENS = 53,
+ NOTATION = 33,
+ NOTOKEN = 1,
+ PARSE_ENTITY = 44,
+ PCDATA = 42,
+ PERCENT = 15,
+ PIPE = 13,
+ PLUS = 21,
+ PUBLIC = 35,
+ QUESTIONMARK = 24,
+ QUOTE = 7,
+ RANGLE = 4,
+ RBRACK = 10,
+ REQUIRED = 37,
+ RPAREN = 12,
+ SEMICOLON = 18,
+ SHIFT_THERE = 56,
+ SLASH = 16,
+ SPACE = 2,
+ STAR = 22,
+ SYSTEM = 34,
+ UNRESOLVED_ENTITY = 46,
+ VERSION = 55,
+ XML = 54,
+ XML_ERROR = 43,
+
+ ACCEPT_STATE = 416,
+ RULE_COUNT = 270,
+ STATE_COUNT = 427,
+ TERMINAL_COUNT = 57,
+ NON_TERMINAL_COUNT = 84,
+
+ GOTO_INDEX_OFFSET = 427,
+ GOTO_INFO_OFFSET = 1030,
+ GOTO_CHECK_OFFSET = 1030
+ };
+
+ static const char *const spell[];
+ static const short lhs[];
+ static const short rhs[];
+ static const short goto_default[];
+ static const short action_default[];
+ static const short action_index[];
+ static const short action_info[];
+ static const short action_check[];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
+ return goto_default [nt];
+
+ return action_info [GOTO_INFO_OFFSET + yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+QT_END_NAMESPACE
+#endif // QXMLSTREAMGRAMMAR_P_H
+
diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h
new file mode 100644
index 0000000000..1363bf4d41
--- /dev/null
+++ b/src/corelib/serialization/qxmlstreamparser_p.h
@@ -0,0 +1,1006 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is automatically generated from qxmlstream.g.
+// Changes should be made to that file, not here. Any change to this file will
+// be lost!
+//
+// To regenerate this file, run:
+// qlalr --no-debug --no-lines --qt qxmlstream.g
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <qxmlstream.h>
+#include "qxmlstream_p.h"
+#include "qxmlutils_p.h"
+#include <qstringconverter.h>
+
+#include <memory>
+
+#ifndef QXMLSTREAMPARSER_P_H
+#define QXMLSTREAMPARSER_P_H
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(xmlstreamreader)
+
+bool QXmlStreamReaderPrivate::parse()
+{
+ // cleanup currently reported token
+
+ using namespace Qt::StringLiterals;
+
+ switch (type) {
+ case QXmlStreamReader::StartElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ publicNamespaceDeclarations.clear();
+ attributes.clear();
+ if (isEmptyElement) {
+ setType(QXmlStreamReader::EndElement);
+ Tag tag = tagStack_pop();
+ namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
+ name = tag.name;
+ qualifiedName = tag.qualifiedName;
+ isEmptyElement = false;
+ return true;
+ }
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::EndElement:
+ name.clear();
+ prefix.clear();
+ qualifiedName.clear();
+ namespaceUri.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::DTD:
+ publicNotationDeclarations.clear();
+ publicEntityDeclarations.clear();
+ dtdName.clear();
+ dtdPublicId.clear();
+ dtdSystemId.clear();
+ Q_FALLTHROUGH();
+ case QXmlStreamReader::Comment:
+ case QXmlStreamReader::Characters:
+ isCDATA = false;
+ isWhitespace = true;
+ text.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::EntityReference:
+ text.clear();
+ name.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ processingInstructionTarget.clear();
+ processingInstructionData.clear();
+ clearTextBuffer();
+ break;
+ case QXmlStreamReader::NoToken:
+ case QXmlStreamReader::Invalid:
+ break;
+ case QXmlStreamReader::StartDocument:
+ lockEncoding = true;
+ documentVersion.clear();
+ documentEncoding.clear();
+ if (decoder.isValid() && decoder.hasError()) {
+ raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
+ readBuffer.clear();
+ return false;
+ }
+ Q_FALLTHROUGH();
+ default:
+ clearTextBuffer();
+ ;
+ }
+
+ setType(QXmlStreamReader::NoToken);
+
+
+ // the main parse loop
+ int act, r;
+
+ if (resumeReduction) {
+ act = state_stack[tos-1];
+ r = resumeReduction;
+ resumeReduction = 0;
+ goto ResumeReduction;
+ }
+
+ act = state_stack[tos];
+
+ forever {
+ if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
+ uint cu = getChar();
+ token = NOTOKEN;
+ token_char = cu == ~0U ? cu : ushort(cu);
+ if ((cu != ~0U) && (cu & 0xff0000)) {
+ token = cu >> 16;
+ } else switch (token_char) {
+ case 0xfffe:
+ case 0xffff:
+ token = XML_ERROR;
+ break;
+ case '\r':
+ token = SPACE;
+ if (cu == '\r') {
+ if ((token_char = filterCarriageReturn())) {
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ break;
+ }
+ } else {
+ break;
+ }
+ Q_FALLTHROUGH();
+ case ~0U: {
+ token = EOF_SYMBOL;
+ if (!tagsDone && !inParseEntity) {
+ int a = t_action(act, token);
+ if (a < 0) {
+ raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
+ return false;
+ }
+ }
+
+ } break;
+ case '\n':
+ ++lineNumber;
+ lastLineStart = characterOffset + readBufferPos;
+ Q_FALLTHROUGH();
+ case ' ':
+ case '\t':
+ token = SPACE;
+ break;
+ case '&':
+ token = AMPERSAND;
+ break;
+ case '#':
+ token = HASH;
+ break;
+ case '\'':
+ token = QUOTE;
+ break;
+ case '\"':
+ token = DBLQUOTE;
+ break;
+ case '<':
+ token = LANGLE;
+ break;
+ case '>':
+ token = RANGLE;
+ break;
+ case '[':
+ token = LBRACK;
+ break;
+ case ']':
+ token = RBRACK;
+ break;
+ case '(':
+ token = LPAREN;
+ break;
+ case ')':
+ token = RPAREN;
+ break;
+ case '|':
+ token = PIPE;
+ break;
+ case '=':
+ token = EQ;
+ break;
+ case '%':
+ token = PERCENT;
+ break;
+ case '/':
+ token = SLASH;
+ break;
+ case ':':
+ token = COLON;
+ break;
+ case ';':
+ token = SEMICOLON;
+ break;
+ case ',':
+ token = COMMA;
+ break;
+ case '-':
+ token = DASH;
+ break;
+ case '+':
+ token = PLUS;
+ break;
+ case '*':
+ token = STAR;
+ break;
+ case '.':
+ token = DOT;
+ break;
+ case '?':
+ token = QUESTIONMARK;
+ break;
+ case '!':
+ token = BANG;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ token = DIGIT;
+ break;
+ default:
+ if (cu < 0x20)
+ token = NOTOKEN;
+ else
+ token = LETTER;
+ break;
+ }
+ }
+
+ act = t_action (act, token);
+ if (act == ACCEPT_STATE) {
+ // reset the parser in case someone resumes (process instructions can follow a valid document)
+ tos = 0;
+ state_stack[tos++] = 0;
+ state_stack[tos] = 0;
+ return true;
+ } else if (act > 0) {
+ if (++tos >= stack_size-1)
+ reallocateStack();
+
+ Value &val = sym_stack[tos];
+ val.c = token_char;
+ val.pos = textBuffer.size();
+ val.prefix = 0;
+ val.len = 1;
+ if (token_char)
+ textBuffer += QChar(token_char);
+
+ state_stack[tos] = act;
+ token = -1;
+
+
+ } else if (act < 0) {
+ r = - act - 1;
+
+#if defined (QLALR_DEBUG)
+ int ridx = rule_index[r];
+ printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
+ ++ridx;
+ for (int i = ridx; i < ridx + rhs[r]; ++i) {
+ int symbol = rule_info[i];
+ if (const char *name = spell[symbol])
+ printf (" %s", name);
+ else
+ printf (" #%d", symbol);
+ }
+ printf ("\n");
+#endif
+
+ tos -= rhs[r];
+ act = state_stack[tos++];
+ ResumeReduction:
+ switch (r) {
+
+ case 0:
+ setType(QXmlStreamReader::EndDocument);
+ break;
+
+ case 1:
+ if (type != QXmlStreamReader::Invalid) {
+ if (hasSeenTag || inParseEntity) {
+ setType(QXmlStreamReader::EndDocument);
+ } else {
+ raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
+ // reset the parser
+ tos = 0;
+ state_stack[tos++] = 0;
+ state_stack[tos] = 0;
+ return false;
+ }
+ }
+ break;
+
+ case 10: {
+ auto reference = entityReferenceStack.pop();
+ auto it = reference.hash->find(reference.name);
+ Q_ASSERT(it != reference.hash->end());
+ it->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
+ clearSym();
+ } break;
+
+ case 11:
+ if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
+ resume(11);
+ return false;
+ }
+ break;
+
+ case 12:
+ setType(QXmlStreamReader::StartDocument);
+ documentVersion = symString(6);
+ startDocument();
+ break;
+
+ case 13:
+ hasExternalDtdSubset = true;
+ dtdSystemId = symString(2);
+ break;
+
+ case 14:
+ checkPublicLiteral(symString(2));
+ dtdPublicId = symString(2);
+ dtdSystemId = symString(4);
+ hasExternalDtdSubset = true;
+ break;
+
+ case 16:
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(16);
+ return false;
+ }
+ dtdName = symString(3);
+ break;
+
+ case 17:
+ case 18:
+ dtdName = symString(3);
+ Q_FALLTHROUGH();
+
+ case 19:
+ case 20:
+ setType(QXmlStreamReader::DTD);
+ text = &textBuffer;
+ break;
+
+ case 21:
+ scanDtd = true;
+ break;
+
+ case 22:
+ scanDtd = false;
+ break;
+
+ case 37:
+ if (!scanString(spell[EMPTY], EMPTY, false)
+ && !scanString(spell[ANY], ANY, false)
+ && atEnd) {
+ resume(37);
+ return false;
+ }
+ break;
+
+ case 43:
+ if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
+ resume(43);
+ return false;
+ }
+ break;
+
+ case 68: {
+ lastAttributeIsCData = true;
+ } break;
+
+ case 78:
+ if (!scanAfterDefaultDecl() && atEnd) {
+ resume(78);
+ return false;
+ }
+ break;
+
+ case 83:
+ sym(1) = sym(2);
+ lastAttributeValue.clear();
+ lastAttributeIsCData = false;
+ if (!scanAttType() && atEnd) {
+ resume(83);
+ return false;
+ }
+ break;
+
+ case 84: {
+ DtdAttribute &dtdAttribute = dtdAttributes.push();
+ dtdAttribute.tagName.clear();
+ dtdAttribute.isCDATA = lastAttributeIsCData;
+ dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
+ dtdAttribute.attributeName = addToStringStorage(symString(1));
+ dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
+ dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == "xmlns"_L1
+ || (dtdAttribute.attributePrefix.isEmpty()
+ && dtdAttribute.attributeName == "xmlns"_L1));
+ if (lastAttributeValue.isNull()) {
+ dtdAttribute.defaultValue.clear();
+ } else {
+ if (dtdAttribute.isCDATA)
+ dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
+ else
+ dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
+
+ }
+ } break;
+
+ case 88: {
+ if (referenceToUnparsedEntityDetected && !standalone)
+ break;
+ qsizetype n = dtdAttributes.size();
+ XmlStringRef tagName = addToStringStorage(symName(3));
+ while (n--) {
+ DtdAttribute &dtdAttribute = dtdAttributes[n];
+ if (!dtdAttribute.tagName.isNull())
+ break;
+ dtdAttribute.tagName = tagName;
+ for (qsizetype i = 0; i < n; ++i) {
+ if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
+ && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
+ dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
+ break;
+ }
+ }
+ }
+ } break;
+
+ case 89: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(89);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(3);
+ } break;
+
+ case 90: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(90);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.push();
+ entityDeclaration.clear();
+ entityDeclaration.name = symString(5);
+ entityDeclaration.parameter = true;
+ } break;
+
+ case 91: {
+ if (!scanNData() && atEnd) {
+ resume(91);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.systemId = symString(3);
+ entityDeclaration.external = true;
+ } break;
+
+ case 92: {
+ if (!scanNData() && atEnd) {
+ resume(92);
+ return false;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ checkPublicLiteral((entityDeclaration.publicId = symString(3)));
+ entityDeclaration.systemId = symString(5);
+ entityDeclaration.external = true;
+ } break;
+
+ case 93: {
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ entityDeclaration.notationName = symString(3);
+ if (entityDeclaration.parameter)
+ raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
+ }
+ Q_FALLTHROUGH();
+
+ case 94:
+ case 95: {
+ if (referenceToUnparsedEntityDetected && !standalone) {
+ entityDeclarations.pop();
+ break;
+ }
+ EntityDeclaration &entityDeclaration = entityDeclarations.top();
+ if (!entityDeclaration.external)
+ entityDeclaration.value = symString(2);
+ auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(entityDeclaration.name)) {
+ Entity entity(entityDeclaration.name.toString(),
+ entityDeclaration.value.toString());
+ entity.unparsed = (!entityDeclaration.notationName.isNull());
+ entity.external = entityDeclaration.external;
+ hash.insert(qToStringViewIgnoringNull(entity.name), entity);
+ }
+ } break;
+
+ case 96: {
+ setType(QXmlStreamReader::ProcessingInstruction);
+ const qsizetype pos = sym(4).pos + sym(4).len;
+ processingInstructionTarget = symString(3);
+ if (scanUntil("?>")) {
+ processingInstructionData = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive)) {
+ raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
+ }
+ else if (!QXmlUtils::isNCName(processingInstructionTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
+ .arg(processingInstructionTarget));
+ } else if (type != QXmlStreamReader::Invalid){
+ resume(96);
+ return false;
+ }
+ } break;
+
+ case 97:
+ setType(QXmlStreamReader::ProcessingInstruction);
+ processingInstructionTarget = symString(3);
+ if (!processingInstructionTarget.view().compare("xml"_L1, Qt::CaseInsensitive))
+ raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
+ break;
+
+ case 98:
+ if (!scanAfterLangleBang() && atEnd) {
+ resume(98);
+ return false;
+ }
+ break;
+
+ case 99:
+ if (!scanUntil("--")) {
+ resume(99);
+ return false;
+ }
+ break;
+
+ case 100: {
+ setType(QXmlStreamReader::Comment);
+ const qsizetype pos = sym(1).pos + 4;
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ } break;
+
+ case 101: {
+ setType(QXmlStreamReader::Characters);
+ isCDATA = true;
+ isWhitespace = false;
+ const qsizetype pos = sym(2).pos;
+ if (scanUntil("]]>", -1)) {
+ text = XmlStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
+ } else {
+ resume(101);
+ return false;
+ }
+ } break;
+
+ case 102: {
+ if (!scanPublicOrSystem() && atEnd) {
+ resume(102);
+ return false;
+ }
+ NotationDeclaration &notationDeclaration = notationDeclarations.push();
+ notationDeclaration.name = symString(3);
+ } break;
+
+ case 103: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId = symString(3);
+ notationDeclaration.publicId.clear();
+ } break;
+
+ case 104: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ notationDeclaration.systemId.clear();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ } break;
+
+ case 105: {
+ NotationDeclaration &notationDeclaration = notationDeclarations.top();
+ checkPublicLiteral((notationDeclaration.publicId = symString(3)));
+ notationDeclaration.systemId = symString(5);
+ } break;
+
+ case 129:
+ isWhitespace = false;
+ Q_FALLTHROUGH();
+
+ case 130:
+ sym(1).len += fastScanContentCharList();
+ if (atEnd && !inParseEntity) {
+ resume(130);
+ return false;
+ }
+ break;
+
+ case 139:
+ if (!textBuffer.isEmpty()) {
+ setType(QXmlStreamReader::Characters);
+ text = &textBuffer;
+ }
+ break;
+
+ case 140:
+ case 141:
+ clearSym();
+ break;
+
+ case 142:
+ case 143:
+ sym(1) = sym(2);
+ break;
+
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 173:
+ if (normalizeLiterals)
+ textBuffer.data()[textBuffer.size()-1] = u' ';
+ break;
+
+ case 174:
+ sym(1).len += fastScanLiteralContent();
+ if (atEnd) {
+ resume(174);
+ return false;
+ }
+ break;
+
+ case 175: {
+ if (!QXmlUtils::isPublicID(symString(1))) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
+ resume(175);
+ return false;
+ }
+ } break;
+
+ case 176:
+ case 177:
+ clearSym();
+ break;
+
+ case 178:
+ case 179:
+ sym(1) = sym(2);
+ break;
+
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 213:
+ case 214:
+ clearSym();
+ break;
+
+ case 215:
+ case 216:
+ sym(1) = sym(2);
+ lastAttributeValue = symString(1);
+ break;
+
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 229: {
+ XmlStringRef prefix = symPrefix(1);
+ if (prefix.isEmpty() && symString(1) == "xmlns"_L1 && namespaceProcessing) {
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ namespaceDeclaration.prefix.clear();
+
+ const XmlStringRef ns(symString(5));
+ if (ns.view() == "http://www.w3.org/2000/xmlns/"_L1 ||
+ ns.view() == "http://www.w3.org/XML/1998/namespace"_L1)
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+ else
+ namespaceDeclaration.namespaceUri = addToStringStorage(ns);
+ } else {
+ Attribute &attribute = attributeStack.push();
+ attribute.key = sym(1);
+ attribute.value = sym(5);
+
+ XmlStringRef attributeQualifiedName = symName(1);
+ bool normalize = false;
+ for (const DtdAttribute &dtdAttribute : std::as_const(dtdAttributes)) {
+ if (!dtdAttribute.isCDATA
+ && dtdAttribute.tagName == qualifiedName
+ && dtdAttribute.attributeQualifiedName == attributeQualifiedName
+ ) {
+ normalize = true;
+ break;
+ }
+ }
+ if (normalize) {
+ // normalize attribute value (simplify and trim)
+ const qsizetype pos = textBuffer.size();
+ qsizetype n = 0;
+ bool wasSpace = true;
+ for (qsizetype i = 0; i < attribute.value.len; ++i) {
+ QChar c = textBuffer.at(attribute.value.pos + i);
+ if (c.unicode() == ' ') {
+ if (wasSpace)
+ continue;
+ wasSpace = true;
+ } else {
+ wasSpace = false;
+ }
+ textBuffer += textBuffer.at(attribute.value.pos + i);
+ ++n;
+ }
+ if (wasSpace)
+ while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
+ --n;
+ attribute.value.pos = pos;
+ attribute.value.len = n;
+ }
+ if (prefix == "xmlns"_L1 && namespaceProcessing) {
+ NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
+ XmlStringRef namespacePrefix = symString(attribute.key);
+ XmlStringRef namespaceUri = symString(attribute.value);
+ attributeStack.pop();
+ if (((namespacePrefix == "xml"_L1)
+ ^ (namespaceUri == "http://www.w3.org/XML/1998/namespace"_L1))
+ || namespaceUri == "http://www.w3.org/2000/xmlns/"_L1
+ || namespaceUri.isEmpty()
+ || namespacePrefix == "xmlns"_L1)
+ raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
+
+ namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
+ namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
+ }
+ }
+ } break;
+
+ case 235: {
+ normalizeLiterals = true;
+ Tag &tag = tagStack_push();
+ prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
+ name = tag.name = addToStringStorage(symString(2));
+ qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
+ if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
+ raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
+ } break;
+
+ case 236:
+ isEmptyElement = true;
+ Q_FALLTHROUGH();
+
+ case 237:
+ setType(QXmlStreamReader::StartElement);
+ resolveTag();
+ if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
+ raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
+ hasSeenTag = true;
+ break;
+
+ case 238: {
+ setType(QXmlStreamReader::EndElement);
+ Tag tag = tagStack_pop();
+
+ namespaceUri = tag.namespaceDeclaration.namespaceUri;
+ prefix = tag.namespaceDeclaration.prefix;
+ name = tag.name;
+ qualifiedName = tag.qualifiedName;
+ if (qualifiedName != symName(3))
+ raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
+ } break;
+
+ case 239:
+ if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
+ break;
+ }
+ setType(QXmlStreamReader::EntityReference);
+ name = &unresolvedEntity;
+ break;
+
+ case 240: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
+ if (entity.unparsed) {
+ raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
+ } else {
+ if (!entity.hasBeenParsed) {
+ parseEntity(entity.value);
+ entity.hasBeenParsed = true;
+ }
+ if (entity.literal)
+ putStringLiteral(entity.value);
+ else if (referenceEntity(&entityHash, entity))
+ putReplacement(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ }
+ break;
+ }
+
+ if (entityResolver) {
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
+ if (!replacementText.isNull()) {
+ putReplacement(replacementText);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+ }
+
+ injectToken(UNRESOLVED_ENTITY);
+ unresolvedEntity = symString(2).toString();
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+
+ } break;
+
+ case 241: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) {
+ referenceToParameterEntityDetected = true;
+ Entity &entity = *it;
+ if (entity.unparsed || entity.external) {
+ referenceToUnparsedEntityDetected = true;
+ } else {
+ if (referenceEntity(&parameterEntityHash, entity))
+ putString(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ }
+ } else if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
+ }
+ } break;
+
+ case 242:
+ sym(1).len += sym(2).len + 1;
+ break;
+
+ case 243: {
+ sym(1).len += sym(2).len + 1;
+ QStringView reference = symView(2);
+ if (const auto it = entityHash.find(reference); it != entityHash.end()) {
+ Entity &entity = *it;
+ if (entity.unparsed || entity.value.isNull()) {
+ raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
+ break;
+ }
+ if (!entity.hasBeenParsed) {
+ parseEntity(entity.value);
+ entity.hasBeenParsed = true;
+ }
+ if (entity.literal)
+ putStringLiteral(entity.value);
+ else if (referenceEntity(&entityHash, entity))
+ putReplacementInAttributeValue(entity.value);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+
+ if (entityResolver) {
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
+ if (!replacementText.isNull()) {
+ putReplacement(replacementText);
+ textBuffer.chop(2 + sym(2).len);
+ clearSym();
+ break;
+ }
+ }
+ if (entitiesMustBeDeclared()) {
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
+ }
+ } break;
+
+ case 244: {
+ if (char32_t s = resolveCharRef(3)) {
+ putStringLiteral(QChar::fromUcs4(s));
+ textBuffer.chop(3 + sym(3).len);
+ clearSym();
+ } else {
+ raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
+ }
+ } break;
+
+ case 247:
+ case 248:
+ sym(1).len += sym(2).len;
+ break;
+
+ case 259:
+ sym(1).len += fastScanSpace();
+ if (atEnd) {
+ resume(259);
+ return false;
+ }
+ break;
+
+ case 262: {
+ Value &val = sym(1);
+ if (auto res = fastScanName(&val))
+ val.len += *res;
+ else
+ return false;
+
+ if (atEnd) {
+ resume(262);
+ return false;
+ }
+ } break;
+
+ case 263:
+ if (auto res = fastScanName())
+ sym(1).len += *res;
+ else
+ return false;
+
+ if (atEnd) {
+ resume(263);
+ return false;
+ }
+ break;
+
+ case 264:
+ case 265:
+ case 266:
+ case 267:
+ case 268:
+ sym(1).len += fastScanNMTOKEN();
+ if (atEnd) {
+ resume(268);
+ return false;
+ }
+
+ break;
+
+ default:
+ ;
+ } // switch
+ act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
+ if (type != QXmlStreamReader::NoToken)
+ return true;
+ } else {
+ parseError();
+ break;
+ }
+ }
+ return false;
+}
+
+#endif // feature xmlstreamreader
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/corelib/serialization/qxmlutils.cpp b/src/corelib/serialization/qxmlutils.cpp
index 01c84251fd..e6fae7c173 100644
--- a/src/corelib/serialization/qxmlutils.cpp
+++ b/src/corelib/serialization/qxmlutils.cpp
@@ -1,48 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qstring.h>
#include "qxmlutils_p.h"
+#include <private/qtools_p.h>
+
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
/* TODO:
* - isNameChar() doesn't have to be public, it's only needed in
* qdom.cpp -- refactor fixedXmlName() to use isNCName()
@@ -80,7 +48,7 @@ bool QXmlUtils::rangeContains(RangeIter begin, RangeIter end, const QChar c)
return cp >= begin->min;
while (begin != end) {
- int delta = (end - begin) / 2;
+ qptrdiff delta = (end - begin) / 2;
RangeIter mid = begin + delta;
if (mid->min > cp)
@@ -233,16 +201,12 @@ bool QXmlUtils::isEncName(QStringView encName)
if (encName.isEmpty())
return false;
const auto first = encName.front().unicode();
- if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
+ if (!(isAsciiLower(first) || isAsciiUpper(first)))
return false;
for (QChar ch : encName.mid(1)) {
const auto cp = ch.unicode();
- if ((cp >= 'a' && cp <= 'z')
- || (cp >= 'A' && cp <= 'Z')
- || (cp >= '0' && cp <= '9')
- || cp == '.' || cp == '_' || cp == '-') {
+ if (isAsciiLetterOrNumber(cp) || cp == '.' || cp == '_' || cp == '-')
continue;
- }
return false;
}
return true;
@@ -271,13 +235,16 @@ bool QXmlUtils::isLetter(const QChar c)
\sa {http://www.w3.org/TR/REC-xml/#NT-Char},
{Extensible Markup Language (XML) 1.0 (Fourth Edition), [2] Char}
*/
-bool QXmlUtils::isChar(const QChar c)
+bool QXmlUtils::isChar(const char32_t c)
{
- return (c.unicode() >= 0x0020 && c.unicode() <= 0xD7FF)
- || c.unicode() == 0x0009
- || c.unicode() == 0x000A
- || c.unicode() == 0x000D
- || (c.unicode() >= 0xE000 && c.unicode() <= 0xFFFD);
+ // The valid range is defined by https://www.w3.org/TR/REC-xml/#NT-Char as following:
+ // Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
+ return (c >= 0x0020 && c <= 0xD7FF)
+ || c == 0x0009
+ || c == 0x000A
+ || c == 0x000D
+ || (c >= 0xE000 && c <= 0xFFFD)
+ || (c >= 0x10000 && c <= 0x10FFFF);
}
/*!
@@ -318,12 +285,8 @@ bool QXmlUtils::isPublicID(QStringView candidate)
for (QChar ch : candidate) {
const ushort cp = ch.unicode();
- if ((cp >= 'a' && cp <= 'z')
- || (cp >= 'A' && cp <= 'Z')
- || (cp >= '0' && cp <= '9'))
- {
+ if (isAsciiLetterOrNumber(cp))
continue;
- }
switch (cp)
{
@@ -371,16 +334,16 @@ bool QXmlUtils::isPublicID(QStringView candidate)
*/
bool QXmlUtils::isNCName(QStringView ncName)
{
- if(ncName.isEmpty())
+ if (ncName.isEmpty())
return false;
const QChar first(ncName.at(0));
- if(!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
+ if (!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
return false;
for (QChar at : ncName) {
- if(!QXmlUtils::isNameChar(at) || at == QLatin1Char(':'))
+ if (!QXmlUtils::isNameChar(at) || at == u':')
return false;
}
diff --git a/src/corelib/serialization/qxmlutils_p.h b/src/corelib/serialization/qxmlutils_p.h
index db6bddd5be..0ad1758979 100644
--- a/src/corelib/serialization/qxmlutils_p.h
+++ b/src/corelib/serialization/qxmlutils_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXMLUTILS_P_H
#define QXMLUTILS_P_H
@@ -69,7 +33,7 @@ class Q_CORE_EXPORT QXmlUtils
{
public:
static bool isEncName(QStringView encName);
- static bool isChar(const QChar c);
+ static bool isChar(const char32_t c);
static bool isNameChar(const QChar c);
static bool isLetter(const QChar c);
static bool isNCName(QStringView ncName);
diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri
deleted file mode 100644
index ff653ca8f3..0000000000
--- a/src/corelib/serialization/serialization.pri
+++ /dev/null
@@ -1,76 +0,0 @@
-# Qt data formats core module
-
-HEADERS += \
- serialization/qcborarray.h \
- serialization/qcborcommon.h \
- serialization/qcborcommon_p.h \
- serialization/qcbormap.h \
- serialization/qcborstream.h \
- serialization/qcborvalue.h \
- serialization/qcborvalue_p.h \
- serialization/qdatastream.h \
- serialization/qdatastream_p.h \
- serialization/qjson_p.h \
- serialization/qjsondocument.h \
- serialization/qjsonobject.h \
- serialization/qjsonvalue.h \
- serialization/qjsonarray.h \
- serialization/qjsonwriter_p.h \
- serialization/qjsonparser_p.h \
- serialization/qtextstream.h \
- serialization/qtextstream_p.h \
- serialization/qxmlstream.h \
- serialization/qxmlstream_p.h \
- serialization/qxmlutils_p.h
-
-SOURCES += \
- serialization/qcborcommon.cpp \
- serialization/qcbordiagnostic.cpp \
- serialization/qcborvalue.cpp \
- serialization/qdatastream.cpp \
- serialization/qjsoncbor.cpp \
- serialization/qjsondocument.cpp \
- serialization/qjsonobject.cpp \
- serialization/qjsonarray.cpp \
- serialization/qjsonvalue.cpp \
- serialization/qjsonwriter.cpp \
- serialization/qjsonparser.cpp \
- serialization/qtextstream.cpp \
- serialization/qxmlstream.cpp \
- serialization/qxmlutils.cpp
-
-qtConfig(cborstreamreader): {
- SOURCES += \
- serialization/qcborstreamreader.cpp
-
- HEADERS += \
- serialization/qcborstreamreader.h
-}
-
-qtConfig(cborstreamwriter): {
- SOURCES += \
- serialization/qcborstreamwriter.cpp
-
- HEADERS += \
- serialization/qcborstreamwriter.h
-}
-
-qtConfig(binaryjson): {
- HEADERS += \
- serialization/qbinaryjson_p.h \
- serialization/qbinaryjsonarray_p.h \
- serialization/qbinaryjsonobject_p.h \
- serialization/qbinaryjsonvalue_p.h
-
- SOURCES += \
- serialization/qbinaryjson.cpp \
- serialization/qbinaryjsonarray.cpp \
- serialization/qbinaryjsonobject.cpp \
- serialization/qbinaryjsonvalue.cpp \
-}
-
-false: SOURCES += \
- serialization/qcborarray.cpp \
- serialization/qcbormap.cpp
-
-INCLUDEPATH += ../3rdparty/tinycbor/src