diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-12-12 18:32:19 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2018-01-26 20:59:50 +0000 |
commit | a6b697ca13945a174cff9f3e9b1af1cf61c0bea5 (patch) | |
tree | 78d5fad97ff8e89f079df29cc5a75b4e7197bfc7 /src/corelib/json | |
parent | 657894624521b580f59ff5f58b9c0e9be159dc1c (diff) |
Create corelib/serialization and move existing file formats into it
This is in preparation to adding CBOR support. We don't need yet another
dir for CBOR and placing it in src/corelib/json is just wrong.
Change-Id: I9741f017961b410c910dfffd14ffb9d870340fa6
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/json')
-rw-r--r-- | src/corelib/json/json.pri | 17 | ||||
-rw-r--r-- | src/corelib/json/qjson.cpp | 455 | ||||
-rw-r--r-- | src/corelib/json/qjson_p.h | 781 | ||||
-rw-r--r-- | src/corelib/json/qjsonarray.cpp | 1258 | ||||
-rw-r--r-- | src/corelib/json/qjsonarray.h | 274 | ||||
-rw-r--r-- | src/corelib/json/qjsondocument.cpp | 667 | ||||
-rw-r--r-- | src/corelib/json/qjsondocument.h | 177 | ||||
-rw-r--r-- | src/corelib/json/qjsonobject.cpp | 1312 | ||||
-rw-r--r-- | src/corelib/json/qjsonobject.h | 271 | ||||
-rw-r--r-- | src/corelib/json/qjsonparser.cpp | 1027 | ||||
-rw-r--r-- | src/corelib/json/qjsonparser_p.h | 128 | ||||
-rw-r--r-- | src/corelib/json/qjsonvalue.cpp | 863 | ||||
-rw-r--r-- | src/corelib/json/qjsonvalue.h | 255 | ||||
-rw-r--r-- | src/corelib/json/qjsonwriter.cpp | 231 | ||||
-rw-r--r-- | src/corelib/json/qjsonwriter_p.h | 73 |
15 files changed, 0 insertions, 7789 deletions
diff --git a/src/corelib/json/json.pri b/src/corelib/json/json.pri deleted file mode 100644 index 1a4e2a72bf..0000000000 --- a/src/corelib/json/json.pri +++ /dev/null @@ -1,17 +0,0 @@ -HEADERS += \ - json/qjson_p.h \ - json/qjsondocument.h \ - json/qjsonobject.h \ - json/qjsonvalue.h \ - json/qjsonarray.h \ - json/qjsonwriter_p.h \ - json/qjsonparser_p.h - -SOURCES += \ - json/qjson.cpp \ - json/qjsondocument.cpp \ - json/qjsonobject.cpp \ - json/qjsonarray.cpp \ - json/qjsonvalue.cpp \ - json/qjsonwriter.cpp \ - json/qjsonparser.cpp diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp deleted file mode 100644 index e4bca3bcd0..0000000000 --- a/src/corelib/json/qjson.cpp +++ /dev/null @@ -1,455 +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 "qjson_p.h" -#include <qalgorithms.h> - -QT_BEGIN_NAMESPACE - -namespace QJsonPrivate -{ - -static Q_CONSTEXPR Base emptyArray = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } }; -static Q_CONSTEXPR Base emptyObject = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } }; - -void Data::compact() -{ - Q_ASSERT(sizeof(Value) == sizeof(offset)); - - if (!compactionCounter) - return; - - Base *base = header->root(); - int reserve = 0; - if (base->is_object) { - Object *o = static_cast<Object *>(base); - for (int i = 0; i < (int)o->length; ++i) - reserve += o->entryAt(i)->usedStorage(o); - } else { - Array *a = static_cast<Array *>(base); - for (int i = 0; i < (int)a->length; ++i) - reserve += (*a)[i].usedStorage(a); - } - - int size = sizeof(Base) + reserve + base->length*sizeof(offset); - int alloc = sizeof(Header) + size; - Header *h = (Header *) malloc(alloc); - 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); - - int offset = sizeof(Base); - if (b->is_object) { - Object *o = static_cast<Object *>(base); - Object *no = static_cast<Object *>(b); - - for (int i = 0; i < (int)o->length; ++i) { - no->table()[i] = offset; - - const Entry *e = o->entryAt(i); - Entry *ne = no->entryAt(i); - int s = e->size(); - memcpy(ne, e, s); - offset += s; - int dataSize = e->value.usedStorage(o); - if (dataSize) { - memcpy((char *)no + offset, e->value.data(o), dataSize); - ne->value.value = offset; - offset += dataSize; - } - } - } else { - Array *a = static_cast<Array *>(base); - Array *na = static_cast<Array *>(b); - - for (int i = 0; i < (int)a->length; ++i) { - const Value &v = (*a)[i]; - Value &nv = (*na)[i]; - nv = v; - int dataSize = v.usedStorage(a); - if (dataSize) { - memcpy((char *)na + offset, v.data(a), dataSize); - nv.value = offset; - offset += dataSize; - } - } - } - Q_ASSERT(offset == (int)b->tableOffset); - - free(header); - header = h; - this->alloc = alloc; - compactionCounter = 0; -} - -bool Data::valid() const -{ - if (header->tag != QJsonDocument::BinaryFormatTag || header->version != 1u) - return false; - - bool res = false; - Base *root = header->root(); - int maxSize = alloc - sizeof(Header); - if (root->is_object) - res = static_cast<Object *>(root)->isValid(maxSize); - else - res = static_cast<Array *>(root)->isValid(maxSize); - - return res; -} - - -int Base::reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace) -{ - Q_ASSERT(posInTable >= 0 && posInTable <= (int)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((char *)(table()) + dataSize, table(), length*sizeof(offset)); - } else { - memmove((char *)(table() + posInTable + numItems) + dataSize, table() + posInTable, (length - posInTable)*sizeof(offset)); - memmove((char *)(table()) + dataSize, table(), posInTable*sizeof(offset)); - } - tableOffset += dataSize; - for (int i = 0; i < (int)numItems; ++i) - table()[posInTable + i] = off; - size += dataSize; - if (!replace) { - length += numItems; - size += numItems * sizeof(offset); - } - return off; -} - -void Base::removeItems(int pos, int numItems) -{ - Q_ASSERT(pos >= 0 && pos <= (int)length); - if (pos + numItems < (int)length) - memmove(table() + pos, table() + pos + numItems, (length - pos - numItems)*sizeof(offset)); - length -= numItems; -} - -int Object::indexOf(const QString &key, bool *exists) const -{ - int min = 0; - int n = length; - while (n > 0) { - int half = n >> 1; - int middle = min + half; - if (*entryAt(middle) >= key) { - n = half; - } else { - min = middle + 1; - n -= half + 1; - } - } - if (min < (int)length && *entryAt(min) == key) { - *exists = true; - return min; - } - *exists = false; - return min; -} - -int Object::indexOf(QLatin1String key, bool *exists) const -{ - int min = 0; - int n = length; - while (n > 0) { - int half = n >> 1; - int middle = min + half; - if (*entryAt(middle) >= key) { - n = half; - } else { - min = middle + 1; - n -= half + 1; - } - } - if (min < (int)length && *entryAt(min) == key) { - *exists = true; - return min; - } - *exists = false; - return min; -} - -bool Object::isValid(int maxSize) const -{ - if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size) - return false; - - QString lastKey; - for (uint i = 0; i < length; ++i) { - offset entryOffset = table()[i]; - if (entryOffset + sizeof(Entry) >= tableOffset) - return false; - Entry *e = entryAt(i); - if (!e->isValid(tableOffset - table()[i])) - return false; - QString key = e->key(); - if (key < lastKey) - return false; - if (!e->value.isValid(this)) - return false; - lastKey = key; - } - return true; -} - - - -bool Array::isValid(int maxSize) const -{ - if (size > (uint)maxSize || tableOffset + length*sizeof(offset) > size) - return false; - - for (uint i = 0; i < length; ++i) { - if (!at(i).isValid(this)) - return false; - } - return true; -} - - -bool Entry::operator ==(const QString &key) const -{ - if (value.latinKey) - return (shallowLatin1Key() == key); - else - return (shallowKey() == key); -} - -bool Entry::operator==(QLatin1String key) const -{ - if (value.latinKey) - return shallowLatin1Key() == key; - else - return shallowKey() == key; -} - -bool Entry::operator ==(const Entry &other) const -{ - if (value.latinKey) { - if (other.value.latinKey) - return shallowLatin1Key() == other.shallowLatin1Key(); - return shallowLatin1Key() == other.shallowKey(); - } else if (other.value.latinKey) { - return shallowKey() == other.shallowLatin1Key(); - } - return shallowKey() == other.shallowKey(); -} - -bool Entry::operator >=(const Entry &other) const -{ - if (value.latinKey) { - if (other.value.latinKey) - return shallowLatin1Key() >= other.shallowLatin1Key(); - return shallowLatin1Key() >= other.shallowKey(); - } else if (other.value.latinKey) { - return shallowKey() >= other.shallowLatin1Key(); - } - return shallowKey() >= other.shallowKey(); -} - - -int Value::usedStorage(const Base *b) const -{ - int s = 0; - switch (type) { - case QJsonValue::Double: - if (latinOrIntValue) - break; - s = sizeof(double); - break; - case QJsonValue::String: { - char *d = data(b); - if (latinOrIntValue) - s = sizeof(ushort) + qFromLittleEndian(*(ushort *)d); - else - s = sizeof(int) + sizeof(ushort) * qFromLittleEndian(*(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); -} - -bool Value::isValid(const Base *b) const -{ - int offset = 0; - switch (type) { - case QJsonValue::Double: - if (latinOrIntValue) - break; - Q_FALLTHROUGH(); - case QJsonValue::String: - case QJsonValue::Array: - case QJsonValue::Object: - offset = value; - break; - case QJsonValue::Null: - case QJsonValue::Bool: - default: - break; - } - - if (!offset) - return true; - if (offset + sizeof(uint) > b->tableOffset) - return false; - - int s = usedStorage(b); - if (!s) - return true; - if (s < 0 || s > (int)b->tableOffset - offset) - return false; - if (type == QJsonValue::Array) - return static_cast<Array *>(base(b))->isValid(s); - if (type == QJsonValue::Object) - return static_cast<Object *>(base(b))->isValid(s); - return true; -} - -/*! - \internal - */ -int Value::requiredStorage(QJsonValue &v, bool *compressed) -{ - *compressed = false; - switch (v.t) { - case QJsonValue::Double: - if (QJsonPrivate::compressedNumber(v.dbl) != INT_MAX) { - *compressed = true; - return 0; - } - return sizeof(double); - case QJsonValue::String: { - QString s = v.toString(); - *compressed = QJsonPrivate::useCompressed(s); - return QJsonPrivate::qStringSize(s, *compressed); - } - case QJsonValue::Array: - case QJsonValue::Object: - if (v.d && v.d->compactionCounter) { - v.detach(); - v.d->compact(); - v.base = static_cast<QJsonPrivate::Base *>(v.d->header->root()); - } - return v.base ? uint(v.base->size) : sizeof(QJsonPrivate::Base); - case QJsonValue::Undefined: - case QJsonValue::Null: - case QJsonValue::Bool: - break; - } - return 0; -} - -/*! - \internal - */ -uint Value::valueToStore(const QJsonValue &v, uint offset) -{ - switch (v.t) { - case QJsonValue::Undefined: - case QJsonValue::Null: - break; - case QJsonValue::Bool: - return v.b; - case QJsonValue::Double: { - int c = QJsonPrivate::compressedNumber(v.dbl); - if (c != INT_MAX) - return c; - } - Q_FALLTHROUGH(); - case QJsonValue::String: - case QJsonValue::Array: - case QJsonValue::Object: - return offset; - } - return 0; -} - -/*! - \internal - */ -void Value::copyData(const QJsonValue &v, char *dest, bool compressed) -{ - switch (v.t) { - case QJsonValue::Double: - if (!compressed) { - qToLittleEndian(v.ui, dest); - } - break; - case QJsonValue::String: { - QString str = v.toString(); - QJsonPrivate::copyString(dest, str, compressed); - break; - } - case QJsonValue::Array: - case QJsonValue::Object: { - const QJsonPrivate::Base *b = v.base; - if (!b) - b = (v.t == QJsonValue::Array ? &emptyArray : &emptyObject); - memcpy(dest, b, b->size); - break; - } - default: - break; - } -} - -} // namespace QJsonPrivate - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h deleted file mode 100644 index 131528376b..0000000000 --- a/src/corelib/json/qjson_p.h +++ /dev/null @@ -1,781 +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 QJSON_P_H -#define QJSON_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 <qjsonobject.h> -#include <qjsonvalue.h> -#include <qjsondocument.h> -#include <qjsonarray.h> -#include <qatomic.h> -#include <qstring.h> -#include <qendian.h> -#include <qnumeric.h> - -#include "private/qendian_p.h" -#include "private/qsimd_p.h" - -#include <limits.h> -#include <limits> - -QT_BEGIN_NAMESPACE - -/* - 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. -*/ -#define Q_DECLARE_JSONPRIVATE_TYPEINFO(Class, Flags) } Q_DECLARE_TYPEINFO(QJsonPrivate::Class, Flags); namespace QJsonPrivate { -namespace QJsonPrivate { - -class Array; -class Object; -class Value; -class Entry; - -template<typename T> -using q_littleendian = QLEInteger<T>; - -typedef q_littleendian<short> qle_short; -typedef q_littleendian<unsigned short> qle_ushort; -typedef q_littleendian<int> qle_int; -typedef q_littleendian<unsigned int> qle_uint; - -template<int pos, int width> -using qle_bitfield = QLEIntegerBitfield<uint, pos, width>; - -template<int pos, int width> -using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>; - -typedef qle_uint offset; - -// round the size up to the next 4 byte boundary -inline int alignedSize(int size) { return (size + 3) & ~3; } - -static inline bool useCompressed(const QString &s) -{ - if (s.length() >= 0x8000) - return false; - const ushort *uc = (const ushort *)s.constData(); - const ushort *e = uc + s.length(); - while (uc < e) { - if (*uc > 0xff) - return false; - ++uc; - } - return true; -} - -static inline int qStringSize(const QString &string, bool compress) -{ - int l = 2 + string.length(); - 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 INT_MAX; - - quint64 non_int = val & (fraction_mask >> exp); - if (non_int) - return 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 = (Data *)data; } - - struct Data { - qle_uint length; - qle_ushort utf16[1]; - }; - - Data *d; - - int byteSize() const { return sizeof(uint) + sizeof(ushort) * d->length; } - bool isValid(int maxSize) const { - // Check byteSize() <= maxSize, avoiding integer overflow - maxSize -= sizeof(uint); - return maxSize >= 0 && uint(d->length) <= maxSize / sizeof(ushort); - } - - inline String &operator=(const QString &str) - { - d->length = str.length(); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - const ushort *uc = (const ushort *)str.unicode(); - for (int i = 0; i < str.length(); ++i) - d->utf16[i] = uc[i]; -#else - memcpy(d->utf16, str.unicode(), str.length()*sizeof(ushort)); -#endif - if (str.length() & 1) - d->utf16[str.length()] = 0; - return *this; - } - - inline bool operator ==(const QString &str) const { - int slen = str.length(); - int l = d->length; - if (slen != l) - return false; - const ushort *s = (const ushort *)str.constData(); - const qle_ushort *a = d->utf16; - const ushort *b = s; - while (l-- && *a == *b) - a++,b++; - return (l == -1); - } - inline bool operator !=(const QString &str) const { - return !operator ==(str); - } - inline bool operator >=(const QString &str) const { - // ### - return toString() >= str; - } - - inline bool operator<(const Latin1String &str) const; - inline bool operator>=(const Latin1String &str) const { return !operator <(str); } - inline bool operator ==(const Latin1String &str) const; - - inline 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)); - } - inline bool operator<(const String &other) const; - inline bool operator >=(const String &other) const { return !(*this < other); } - - inline QString toString() const { -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - return QString((QChar *)d->utf16, d->length); -#else - int l = d->length; - QString str(l, Qt::Uninitialized); - QChar *ch = str.data(); - for (int i = 0; i < l; ++i) - ch[i] = QChar(d->utf16[i]); - return str; -#endif - } - -}; - -class Latin1String -{ -public: - explicit Latin1String(const char *data) { d = (Data *)data; } - - struct Data { - qle_ushort length; - char latin1[1]; - }; - Data *d; - - int byteSize() const { return sizeof(ushort) + sizeof(char)*(d->length); } - bool isValid(int maxSize) const { - return byteSize() <= maxSize; - } - - inline Latin1String &operator=(const QString &str) - { - int len = d->length = str.length(); - uchar *l = (uchar *)d->latin1; - const ushort *uc = (const ushort *)str.unicode(); - int i = 0; -#ifdef __SSE2__ - for ( ; i + 16 <= len; i += 16) { - __m128i chunk1 = _mm_loadu_si128((__m128i*)&uc[i]); // load - __m128i chunk2 = _mm_loadu_si128((__m128i*)&uc[i + 8]); // load - // pack the two vector to 16 x 8bits elements - const __m128i result = _mm_packus_epi16(chunk1, chunk2); - _mm_storeu_si128((__m128i*)&l[i], result); // store - } -# ifdef Q_PROCESSOR_X86_64 - // we can do one more round, of 8 characters - if (i + 8 <= len) { - __m128i chunk = _mm_loadu_si128((__m128i*)&uc[i]); // load - // pack with itself, we'll discard the high part anyway - chunk = _mm_packus_epi16(chunk, chunk); - // unaligned 64-bit store - qToUnaligned(_mm_cvtsi128_si64(chunk), l + i); - i += 8; - } -# endif -#endif - for ( ; i < len; ++i) - l[i] = uc[i]; - for ( ; (quintptr)(l+i) & 0x3; ++i) - l[i] = 0; - return *this; - } - - QLatin1String toQLatin1String() const Q_DECL_NOTHROW { - return QLatin1String(d->latin1, d->length); - } - - inline bool operator<(const String &str) const - { - const qle_ushort *uc = (qle_ushort *) str.d->utf16; - if (!uc || *uc == 0) - return false; - - const uchar *c = (uchar *)d->latin1; - const uchar *e = c + qMin((int)d->length, (int)str.d->length); - - while (c < e) { - if (*c != *uc) - break; - ++c; - ++uc; - } - return (c == e ? (int)d->length < (int)str.d->length : *c < *uc); - - } - inline bool operator ==(const String &str) const { - return (str == *this); - } - inline bool operator >=(const String &str) const { - return !(*this < str); - } - - inline QString toString() const { - return QString::fromLatin1(d->latin1, d->length); - } -}; - -#define DEF_OP(op) \ - inline bool operator op(Latin1String lhs, Latin1String rhs) Q_DECL_NOTHROW \ - { \ - return lhs.toQLatin1String() op rhs.toQLatin1String(); \ - } \ - inline bool operator op(QLatin1String lhs, Latin1String rhs) Q_DECL_NOTHROW \ - { \ - return lhs op rhs.toQLatin1String(); \ - } \ - inline bool operator op(Latin1String lhs, QLatin1String rhs) Q_DECL_NOTHROW \ - { \ - return lhs.toQLatin1String() op rhs; \ - } \ - inline bool operator op(const QString &lhs, Latin1String rhs) Q_DECL_NOTHROW \ - { \ - return lhs op rhs.toQLatin1String(); \ - } \ - inline bool operator op(Latin1String lhs, const QString &rhs) Q_DECL_NOTHROW \ - { \ - return lhs.toQLatin1String() op rhs; \ - } \ - /*end*/ -DEF_OP(==) -DEF_OP(!=) -DEF_OP(< ) -DEF_OP(> ) -DEF_OP(<=) -DEF_OP(>=) -#undef DEF_OP - -inline bool String::operator ==(const Latin1String &str) const -{ - if ((int)d->length != (int)str.d->length) - return false; - const qle_ushort *uc = d->utf16; - const qle_ushort *e = uc + d->length; - const uchar *c = (uchar *)str.d->latin1; - - while (uc < e) { - if (*uc != *c) - return false; - ++uc; - ++c; - } - return true; -} - -inline bool String::operator <(const String &other) const -{ - int alen = d->length; - int blen = other.d->length; - int l = qMin(alen, blen); - qle_ushort *a = d->utf16; - qle_ushort *b = other.d->utf16; - - while (l-- && *a == *b) - a++,b++; - if (l==-1) - return (alen < blen); - return (ushort)*a < (ushort)*b; -} - -inline bool String::operator<(const Latin1String &str) const -{ - const uchar *c = (uchar *) str.d->latin1; - if (!c || *c == 0) - return false; - - const qle_ushort *uc = d->utf16; - const qle_ushort *e = uc + qMin((int)d->length, (int)str.d->length); - - while (uc < e) { - if (*uc != *c) - break; - ++uc; - ++c; - } - return (uc == e ? (int)d->length < (int)str.d->length : (ushort)*uc < *c); - -} - -static inline void copyString(char *dest, const QString &str, bool compress) -{ - if (compress) { - Latin1String string(dest); - string = str; - } else { - String string(dest); - string = str; - } -} - - -/* - Base is the base class for both Object and Array. Both classe 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 - - inline bool isObject() const { return !!is_object; } - inline bool isArray() const { return !isObject(); } - - inline offset *table() const { return (offset *) (((char *) this) + tableOffset); } - - int reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace); - void removeItems(int pos, int numItems); -}; - -class Object : public Base -{ -public: - Entry *entryAt(int i) const { - return reinterpret_cast<Entry *>(((char *)this) + table()[i]); - } - int indexOf(const QString &key, bool *exists) const; - int indexOf(QLatin1String key, bool *exists) const; - - bool isValid(int maxSize) const; -}; - - -class Array : public Base -{ -public: - inline Value at(int i) const; - inline Value &operator [](int i); - - bool isValid(int 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 char *data(const Base *b) const { return ((char *)b) + value; } - int usedStorage(const Base *b) const; - - bool toBoolean() const; - double toDouble(const Base *b) const; - QString toString(const Base *b) const; - String asString(const Base *b) const; - Latin1String asLatin1String(const Base *b) const; - Base *base(const Base *b) const; - - bool isValid(const Base *b) const; - - static int requiredStorage(QJsonValue &v, bool *compressed); - static uint valueToStore(const QJsonValue &v, uint offset); - static void copyData(const QJsonValue &v, char *dest, bool compressed); -}; -Q_DECLARE_JSONPRIVATE_TYPEINFO(Value, Q_PRIMITIVE_TYPE) - -inline Value Array::at(int i) const -{ - return *(Value *) (table() + i); -} - -inline Value &Array::operator [](int i) -{ - return *(Value *) (table() + i); -} - - - -class Entry { -public: - Value value; - // key - // value data follows key - - uint size() const { - int s = sizeof(Entry); - if (value.latinKey) - s += shallowLatin1Key().byteSize(); - else - s += shallowKey().byteSize(); - return alignedSize(s); - } - - int usedStorage(Base *b) const { - return size() + value.usedStorage(b); - } - - String shallowKey() const - { - Q_ASSERT(!value.latinKey); - return String((const char *)this + sizeof(Entry)); - } - Latin1String shallowLatin1Key() const - { - Q_ASSERT(value.latinKey); - return Latin1String((const char *)this + sizeof(Entry)); - } - QString key() const - { - if (value.latinKey) { - return shallowLatin1Key().toString(); - } - return shallowKey().toString(); - } - - bool isValid(int maxSize) const { - if (maxSize < (int)sizeof(Entry)) - return false; - maxSize -= sizeof(Entry); - if (value.latinKey) - return shallowLatin1Key().isValid(maxSize); - return shallowKey().isValid(maxSize); - } - - bool operator ==(const QString &key) const; - inline bool operator !=(const QString &key) const { return !operator ==(key); } - inline bool operator >=(const QString &key) const; - - bool operator==(QLatin1String key) const; - inline bool operator!=(QLatin1String key) const { return !operator ==(key); } - inline bool operator>=(QLatin1String key) const; - - bool operator ==(const Entry &other) const; - bool operator >=(const Entry &other) const; -}; - -inline bool Entry::operator >=(const QString &key) const -{ - if (value.latinKey) - return (shallowLatin1Key() >= key); - else - return (shallowKey() >= key); -} - -inline bool Entry::operator >=(QLatin1String key) const -{ - if (value.latinKey) - return shallowLatin1Key() >= key; - else - return shallowKey() >= key; -} - -inline bool operator <(const QString &key, const Entry &e) -{ return e >= key; } - -inline bool operator<(QLatin1String key, const Entry &e) -{ return e >= key; } - - -class Header { -public: - qle_uint tag; // 'qbjs' - qle_uint version; // 1 - Base *root() { return (Base *)(this + 1); } -}; - - -inline bool Value::toBoolean() const -{ - Q_ASSERT(type == QJsonValue::Bool); - return value != 0; -} - -inline double Value::toDouble(const Base *b) const -{ - Q_ASSERT(type == QJsonValue::Double); - if (latinOrIntValue) - return int_value; - - quint64 i = qFromLittleEndian<quint64>((const uchar *)b + value); - double d; - memcpy(&d, &i, sizeof(double)); - return d; -} - -inline String Value::asString(const Base *b) const -{ - Q_ASSERT(type == QJsonValue::String && !latinOrIntValue); - return String(data(b)); -} - -inline Latin1String Value::asLatin1String(const Base *b) const -{ - Q_ASSERT(type == QJsonValue::String && latinOrIntValue); - return Latin1String(data(b)); -} - -inline QString Value::toString(const Base *b) const -{ - if (latinOrIntValue) - return asLatin1String(b).toString(); - else - return asString(b).toString(); -} - -inline Base *Value::base(const Base *b) const -{ - Q_ASSERT(type == QJsonValue::Array || type == QJsonValue::Object); - return reinterpret_cast<Base *>(data(b)); -} - -class Data { -public: - enum Validation { - Unchecked, - Validated, - Invalid - }; - - QAtomicInt ref; - int alloc; - union { - char *rawData; - Header *header; - }; - uint compactionCounter : 31; - uint ownsData : 1; - - inline Data(char *raw, int a) - : alloc(a), rawData(raw), compactionCounter(0), ownsData(true) - { - } - inline Data(int reserved, QJsonValue::Type valueType) - : rawData(0), compactionCounter(0), ownsData(true) - { - Q_ASSERT(valueType == QJsonValue::Array || valueType == QJsonValue::Object); - - alloc = sizeof(Header) + sizeof(Base) + reserved + sizeof(offset); - header = (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; - } - inline ~Data() - { if (ownsData) free(rawData); } - - uint offsetOf(const void *ptr) const { return (uint)(((char *)ptr - rawData)); } - - QJsonObject toObject(Object *o) const - { - return QJsonObject(const_cast<Data *>(this), o); - } - - QJsonArray toArray(Array *a) const - { - return QJsonArray(const_cast<Data *>(this), a); - } - - Data *clone(Base *b, int reserve = 0) - { - int size = sizeof(Header) + b->size; - if (b == header->root() && ref.load() == 1 && alloc >= size + reserve) - return this; - - if (reserve) { - if (reserve < 128) - reserve = 128; - size = qMax(size + reserve, qMin(size *2, (int)Value::MaxSize)); - if (size > Value::MaxSize) { - qWarning("QJson: Document too large to store in data structure"); - return 0; - } - } - char *raw = (char *)malloc(size); - Q_CHECK_PTR(raw); - memcpy(raw + sizeof(Header), b, b->size); - Header *h = (Header *)raw; - h->tag = QJsonDocument::BinaryFormatTag; - h->version = 1; - Data *d = new Data(raw, size); - d->compactionCounter = (b == header->root()) ? compactionCounter : 0; - return d; - } - - void compact(); - bool valid() const; - -private: - Q_DISABLE_COPY(Data) -}; - -} - -QT_END_NAMESPACE - -#endif // QJSON_P_H diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp deleted file mode 100644 index c5a5aaf39d..0000000000 --- a/src/corelib/json/qjsonarray.cpp +++ /dev/null @@ -1,1258 +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 <qjsonobject.h> -#include <qjsonvalue.h> -#include <qjsonarray.h> -#include <qstringlist.h> -#include <qvariant.h> -#include <qdebug.h> - -#include "qjsonwriter_p.h" -#include "qjson_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QJsonArray - \inmodule QtCore - \ingroup json - \ingroup shared - \reentrant - \since 5.0 - - \brief The QJsonArray class encapsulates a JSON array. - - A JSON array is a list of values. The list can be manipulated by inserting and - removing QJsonValue's from the array. - - A QJsonArray can be converted to and from a QVariantList. You can query the - number of entries with size(), insert(), and removeAt() entries from it - and iterate over its content using the standard C++ iterator pattern. - - QJsonArray is an implicitly shared class and shares the data with the document - it has been created from as long as it is not being modified. - - You can convert the array to and from text based JSON through QJsonDocument. - - \sa {JSON Support in Qt}, {JSON Save Game Example} -*/ - -/*! - \typedef QJsonArray::Iterator - - Qt-style synonym for QJsonArray::iterator. -*/ - -/*! - \typedef QJsonArray::ConstIterator - - Qt-style synonym for QJsonArray::const_iterator. -*/ - -/*! - \typedef QJsonArray::size_type - - Typedef for int. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::value_type - - Typedef for QJsonValue. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::difference_type - - Typedef for int. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::pointer - - Typedef for QJsonValue *. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::const_pointer - - Typedef for const QJsonValue *. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::reference - - Typedef for QJsonValue &. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonArray::const_reference - - Typedef for const QJsonValue &. Provided for STL compatibility. -*/ - -/*! - Creates an empty array. - */ -QJsonArray::QJsonArray() - : d(0), a(0) -{ -} - -/*! - \fn QJsonArray::QJsonArray(std::initializer_list<QJsonValue> args) - \since 5.4 - Creates an array initialized from \a args initialization list. - - QJsonArray can be constructed in a way similar to JSON notation, - for example: - \code - QJsonArray array = { 1, 2.2, QString() }; - \endcode - */ - -/*! - \internal - */ -QJsonArray::QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array) - : d(data), a(array) -{ - Q_ASSERT(data); - Q_ASSERT(array); - d->ref.ref(); -} - -/*! - 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() -{ - d = 0; - a = 0; -} - -/*! - Deletes the array. - */ -QJsonArray::~QJsonArray() -{ - if (d && !d->ref.deref()) - delete d; -} - -/*! - Creates a copy of \a other. - - Since QJsonArray is implicitly shared, the copy is shallow - as long as the object doesn't get modified. - */ -QJsonArray::QJsonArray(const QJsonArray &other) -{ - d = other.d; - a = other.a; - if (d) - d->ref.ref(); -} - -/*! - Assigns \a other to this array. - */ -QJsonArray &QJsonArray::operator =(const QJsonArray &other) -{ - if (d != other.d) { - if (d && !d->ref.deref()) - delete d; - d = other.d; - if (d) - d->ref.ref(); - } - a = other.a; - - return *this; -} - -/*! - \fn QJsonArray::QJsonArray(QJsonArray &&other) - \since 5.10 - - Move-constructs a QJsonArray from \a other. -*/ - -/*! - \fn QJsonArray &QJsonArray::operator =(QJsonArray &&other) - \since 5.10 - - Move-assigns \a other to this array. -*/ - -/*! - \fn void QJsonArray::swap(QJsonArray &other) - \since 5.10 - - Swaps the array \a other with this. This operation is very fast and never fails. -*/ - -/*! \fn QJsonArray &QJsonArray::operator+=(const QJsonValue &value) - - Appends \a value to the array, and returns a reference to the array itself. - - \since 5.3 - \sa append(), operator<<() -*/ - -/*! \fn QJsonArray QJsonArray::operator+(const QJsonValue &value) const - - Returns an array that contains all the items in this array followed - by the provided \a value. - - \since 5.3 - \sa operator+=() -*/ - -/*! \fn QJsonArray &QJsonArray::operator<<(const QJsonValue &value) - - Appends \a value to the array, and returns a reference to the array itself. - - \since 5.3 - \sa operator+=(), append() -*/ - -/*! - Converts the string list \a list to a QJsonArray. - - The values in \a list will be converted to JSON values. - - \sa toVariantList(), QJsonValue::fromVariant() - */ -QJsonArray QJsonArray::fromStringList(const QStringList &list) -{ - QJsonArray array; - for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) - array.append(QJsonValue(*it)); - return array; -} - -/*! - Converts the variant list \a list to a QJsonArray. - - The QVariant values in \a list will be converted to JSON values. - - \sa toVariantList(), QJsonValue::fromVariant() - */ -QJsonArray QJsonArray::fromVariantList(const QVariantList &list) -{ - QJsonArray array; - if (list.isEmpty()) - return array; - - array.detach2(1024); - - QVector<QJsonPrivate::Value> values; - values.resize(list.size()); - QJsonPrivate::Value *valueData = values.data(); - uint currentOffset = sizeof(QJsonPrivate::Base); - - for (int i = 0; i < list.size(); ++i) { - QJsonValue val = QJsonValue::fromVariant(list.at(i)); - - bool latinOrIntValue; - int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); - - if (!array.detach2(valueSize)) - return QJsonArray(); - - QJsonPrivate::Value *v = valueData + i; - v->type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); - v->latinOrIntValue = latinOrIntValue; - v->latinKey = false; - v->value = QJsonPrivate::Value::valueToStore(val, currentOffset); - if (valueSize) - QJsonPrivate::Value::copyData(val, (char *)array.a + currentOffset, latinOrIntValue); - - currentOffset += valueSize; - array.a->size = currentOffset; - } - - // write table - array.a->tableOffset = currentOffset; - if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size())) - return QJsonArray(); - memcpy(array.a->table(), values.constData(), values.size()*sizeof(uint)); - array.a->length = values.size(); - array.a->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size(); - - return array; -} - -/*! - Converts this object to a QVariantList. - - Returns the created map. - */ -QVariantList QJsonArray::toVariantList() const -{ - QVariantList list; - - if (a) { - list.reserve(a->length); - for (int i = 0; i < (int)a->length; ++i) - list.append(QJsonValue(d, a, a->at(i)).toVariant()); - } - return list; -} - - -/*! - Returns the number of values stored in the array. - */ -int QJsonArray::size() const -{ - if (!d) - return 0; - - return (int)a->length; -} - -/*! - \fn QJsonArray::count() const - - Same as size(). - - \sa size() -*/ - -/*! - Returns \c true if the object is empty. This is the same as size() == 0. - - \sa size() - */ -bool QJsonArray::isEmpty() const -{ - if (!d) - return true; - - return !a->length; -} - -/*! - Returns a QJsonValue representing the value for index \a i. - - The returned QJsonValue is \c Undefined, if \a i is out of bounds. - - */ -QJsonValue QJsonArray::at(int i) const -{ - if (!a || i < 0 || i >= (int)a->length) - return QJsonValue(QJsonValue::Undefined); - - return QJsonValue(d, a, a->at(i)); -} - -/*! - Returns the first value stored in the array. - - Same as \c at(0). - - \sa at() - */ -QJsonValue QJsonArray::first() const -{ - return at(0); -} - -/*! - Returns the last value stored in the array. - - Same as \c{at(size() - 1)}. - - \sa at() - */ -QJsonValue QJsonArray::last() const -{ - return at(a ? (a->length - 1) : 0); -} - -/*! - Inserts \a value at the beginning of the array. - - This is the same as \c{insert(0, value)} and will prepend \a value to the array. - - \sa append(), insert() - */ -void QJsonArray::prepend(const QJsonValue &value) -{ - insert(0, value); -} - -/*! - Inserts \a value at the end of the array. - - \sa prepend(), insert() - */ -void QJsonArray::append(const QJsonValue &value) -{ - insert(a ? (int)a->length : 0, value); -} - -/*! - Removes the value at index position \a i. \a i must be a valid - index position in the array (i.e., \c{0 <= i < size()}). - - \sa insert(), replace() - */ -void QJsonArray::removeAt(int i) -{ - if (!a || i < 0 || i >= (int)a->length) - return; - - detach2(); - a->removeItems(i, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) - compact(); -} - -/*! \fn void QJsonArray::removeFirst() - - Removes the first item in the array. Calling this function is - equivalent to calling \c{removeAt(0)}. The array must not be empty. If - the array can be empty, call isEmpty() before calling this - function. - - \sa removeAt(), removeLast() -*/ - -/*! \fn void QJsonArray::removeLast() - - Removes the last item in the array. Calling this function is - equivalent to calling \c{removeAt(size() - 1)}. The array must not be - empty. If the array can be empty, call isEmpty() before calling - this function. - - \sa removeAt(), removeFirst() -*/ - -/*! - Removes the item at index position \a i and returns it. \a i must - be a valid index position in the array (i.e., \c{0 <= i < size()}). - - If you don't use the return value, removeAt() is more efficient. - - \sa removeAt() - */ -QJsonValue QJsonArray::takeAt(int i) -{ - if (!a || i < 0 || i >= (int)a->length) - return QJsonValue(QJsonValue::Undefined); - - QJsonValue v(d, a, a->at(i)); - removeAt(i); // detaches - return v; -} - -/*! - Inserts \a value at index position \a i in the array. If \a i - is \c 0, the value is prepended to the array. If \a i is size(), the - value is appended to the array. - - \sa append(), prepend(), replace(), removeAt() - */ -void QJsonArray::insert(int i, const QJsonValue &value) -{ - Q_ASSERT (i >= 0 && i <= (a ? (int)a->length : 0)); - QJsonValue val = value; - - bool compressed; - int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); - - if (!detach2(valueSize + sizeof(QJsonPrivate::Value))) - return; - - if (!a->length) - a->tableOffset = sizeof(QJsonPrivate::Array); - - int valueOffset = a->reserveSpace(valueSize, i, 1, false); - if (!valueOffset) - return; - - QJsonPrivate::Value &v = (*a)[i]; - v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); - v.latinOrIntValue = compressed; - v.latinKey = false; - v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); - if (valueSize) - QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); -} - -/*! - \fn QJsonArray::iterator QJsonArray::insert(iterator before, const QJsonValue &value) - - Inserts \a value before the position pointed to by \a before, and returns an iterator - pointing to the newly inserted item. - - \sa erase(), insert() -*/ - -/*! - \fn QJsonArray::iterator QJsonArray::erase(iterator it) - - Removes the item pointed to by \a it, and returns an iterator pointing to the - next item. - - \sa removeAt() -*/ - -/*! - Replaces the item at index position \a i with \a value. \a i must - be a valid index position in the array (i.e., \c{0 <= i < size()}). - - \sa operator[](), removeAt() - */ -void QJsonArray::replace(int i, const QJsonValue &value) -{ - Q_ASSERT (a && i >= 0 && i < (int)(a->length)); - QJsonValue val = value; - - bool compressed; - int valueSize = QJsonPrivate::Value::requiredStorage(val, &compressed); - - if (!detach2(valueSize)) - return; - - if (!a->length) - a->tableOffset = sizeof(QJsonPrivate::Array); - - int valueOffset = a->reserveSpace(valueSize, i, 1, true); - if (!valueOffset) - return; - - QJsonPrivate::Value &v = (*a)[i]; - v.type = (val.t == QJsonValue::Undefined ? QJsonValue::Null : val.t); - v.latinOrIntValue = compressed; - v.latinKey = false; - v.value = QJsonPrivate::Value::valueToStore(val, valueOffset); - if (valueSize) - QJsonPrivate::Value::copyData(val, (char *)a + valueOffset, compressed); - - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(a->length) / 2u) - compact(); -} - -/*! - Returns \c true if the array contains an occurrence of \a value, otherwise \c false. - - \sa count() - */ -bool QJsonArray::contains(const QJsonValue &value) const -{ - for (int i = 0; i < size(); i++) { - if (at(i) == value) - return true; - } - return false; -} - -/*! - Returns the value at index position \a i as a modifiable reference. - \a i must be a valid index position in the array (i.e., \c{0 <= i < - size()}). - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the character in the QJsonArray of QJsonObject - from which you got the reference. - - \sa at() - */ -QJsonValueRef QJsonArray::operator [](int i) -{ - Q_ASSERT(a && i >= 0 && i < (int)a->length); - return QJsonValueRef(this, i); -} - -/*! - \overload - - Same as at(). - */ -QJsonValue QJsonArray::operator[](int i) const -{ - return at(i); -} - -/*! - Returns \c true if this array is equal to \a other. - */ -bool QJsonArray::operator==(const QJsonArray &other) const -{ - if (a == other.a) - return true; - - if (!a) - return !other.a->length; - if (!other.a) - return !a->length; - if (a->length != other.a->length) - return false; - - for (int i = 0; i < (int)a->length; ++i) { - if (QJsonValue(d, a, a->at(i)) != QJsonValue(other.d, other.a, other.a->at(i))) - return false; - } - return true; -} - -/*! - Returns \c true if this array is not equal to \a other. - */ -bool QJsonArray::operator!=(const QJsonArray &other) const -{ - return !(*this == other); -} - -/*! \fn QJsonArray::iterator QJsonArray::begin() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in - the array. - - \sa constBegin(), end() -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::begin() const - - \overload -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::constBegin() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item - in the array. - - \sa begin(), constEnd() -*/ - -/*! \fn QJsonArray::iterator QJsonArray::end() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item - after the last item in the array. - - \sa begin(), constEnd() -*/ - -/*! \fn const_iterator QJsonArray::end() const - - \overload -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::constEnd() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary - item after the last item in the array. - - \sa constBegin(), end() -*/ - -/*! \fn void QJsonArray::push_back(const QJsonValue &value) - - This function is provided for STL compatibility. It is equivalent - to \l{QJsonArray::append()}{append(value)} and will append \a value to the array. -*/ - -/*! \fn void QJsonArray::push_front(const QJsonValue &value) - - This function is provided for STL compatibility. It is equivalent - to \l{QJsonArray::prepend()}{prepend(value)} and will prepend \a value to the array. -*/ - -/*! \fn void QJsonArray::pop_front() - - This function is provided for STL compatibility. It is equivalent - to removeFirst(). The array must not be empty. If the array can be - empty, call isEmpty() before calling this function. -*/ - -/*! \fn void QJsonArray::pop_back() - - This function is provided for STL compatibility. It is equivalent - to removeLast(). The array must not be empty. If the array can be - empty, call isEmpty() before calling this function. -*/ - -/*! \fn bool QJsonArray::empty() const - - This function is provided for STL compatibility. It is equivalent - to isEmpty() and returns \c true if the array is empty. -*/ - -/*! \class QJsonArray::iterator - \inmodule QtCore - \brief The QJsonArray::iterator class provides an STL-style non-const iterator for QJsonArray. - - 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 - QJsonArray::const_iterator instead. It is generally a good practice to - use QJsonArray::const_iterator on a non-const QJsonArray as well, unless - you need to change the QJsonArray through the iterator. Const - iterators are slightly faster and improves code readability. - - The default QJsonArray::iterator constructor creates an uninitialized - iterator. You must initialize it using a QJsonArray function like - QJsonArray::begin(), QJsonArray::end(), or QJsonArray::insert() before you can - start iterating. - - Most QJsonArray functions accept an integer index rather than an - iterator. For that reason, iterators are rarely useful in - connection with QJsonArray. One place where STL-style iterators do - make sense is as arguments to \l{generic algorithms}. - - Multiple iterators can be used on the same array. However, be - aware that any non-const function call performed on the QJsonArray - will render all existing iterators undefined. - - \sa QJsonArray::const_iterator -*/ - -/*! \typedef QJsonArray::iterator::iterator_category - - A synonym for \e {std::random_access_iterator_tag} indicating - this iterator is a random access iterator. -*/ - -/*! \typedef QJsonArray::iterator::difference_type - - \internal -*/ - -/*! \typedef QJsonArray::iterator::value_type - - \internal -*/ - -/*! \typedef QJsonArray::iterator::reference - - \internal -*/ - -/*! \typedef QJsonArray::iterator::pointer - - \internal -*/ - -/*! \fn QJsonArray::iterator::iterator() - - Constructs an uninitialized iterator. - - Functions like operator*() and operator++() should not be called - on an uninitialized iterator. Use operator=() to assign a value - to it before using it. - - \sa QJsonArray::begin(), QJsonArray::end() -*/ - -/*! \fn QJsonArray::iterator::iterator(QJsonArray *array, int index) - \internal -*/ - -/*! \fn QJsonValueRef QJsonArray::iterator::operator*() const - - - Returns a modifiable reference to the current item. - - You can change the value of an item by using operator*() on the - left side of an assignment. - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the character in the QJsonArray of QJsonObject - from which you got the reference. -*/ - -/*! \fn QJsonValueRef *QJsonArray::iterator::operator->() const - - Returns a pointer to a modifiable reference to the current item. -*/ - -/*! \fn QJsonValueRef QJsonArray::iterator::operator[](int 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}). - - This function is provided to make QJsonArray iterators behave like C++ - pointers. - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the character in the QJsonArray of QJsonObject - from which you got the reference. - - \sa operator+() -*/ - -/*! - \fn bool QJsonArray::iterator::operator==(const iterator &other) const - \fn bool QJsonArray::iterator::operator==(const const_iterator &other) const - - Returns \c true if \a other points to the same item as this - 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 - - Returns \c true if \a other points to a different item than this - 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 - - Returns \c true if the item pointed to by this iterator is less than - the item pointed to by the \a other iterator. -*/ - -/*! - \fn bool QJsonArray::iterator::operator<=(const iterator& other) const - \fn bool QJsonArray::iterator::operator<=(const const_iterator& other) const - - 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. -*/ - -/*! - \fn bool QJsonArray::iterator::operator>(const iterator& other) const - \fn bool QJsonArray::iterator::operator>(const const_iterator& other) const - - Returns \c true if the item pointed to by this iterator is greater - than the item pointed to by the \a other iterator. -*/ - -/*! - \fn bool QJsonArray::iterator::operator>=(const iterator& other) const - \fn bool QJsonArray::iterator::operator>=(const const_iterator& other) const - - 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. -*/ - -/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator++() - - The prefix ++ operator, \c{++it}, advances the iterator to the - next item in the array and returns an iterator to the new current - item. - - Calling this function on QJsonArray::end() leads to undefined results. - - \sa operator--() -*/ - -/*! \fn QJsonArray::iterator QJsonArray::iterator::operator++(int) - - \overload - - The postfix ++ 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 - current and returns an iterator to the new current item. - - Calling this function on QJsonArray::begin() leads to undefined results. - - \sa operator++() -*/ - -/*! \fn QJsonArray::iterator QJsonArray::iterator::operator--(int) - - \overload - - The postfix -- 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) - - Advances the iterator by \a j items. If \a j is negative, the - iterator goes backward. - - \sa operator-=(), operator+() -*/ - -/*! \fn QJsonArray::iterator &QJsonArray::iterator::operator-=(int j) - - Makes the iterator go back by \a j items. If \a j is negative, - the iterator goes forward. - - \sa operator+=(), operator-() -*/ - -/*! \fn QJsonArray::iterator QJsonArray::iterator::operator+(int 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. - - \sa operator-(), operator+=() -*/ - -/*! \fn QJsonArray::iterator QJsonArray::iterator::operator-(int 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. - - \sa operator+(), operator-=() -*/ - -/*! \fn int 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. -*/ - -/*! \class QJsonArray::const_iterator - \inmodule QtCore - \brief The QJsonArray::const_iterator class provides an STL-style const iterator for QJsonArray. - - 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 - good practice to use QJsonArray::const_iterator on a non-const QJsonArray - as well, unless you need to change the QJsonArray through the - iterator. Const iterators are slightly faster and improves - code readability. - - The default QJsonArray::const_iterator constructor creates an - uninitialized iterator. You must initialize it using a QJsonArray - function like QJsonArray::constBegin(), QJsonArray::constEnd(), or - QJsonArray::insert() before you can start iterating. - - Most QJsonArray functions accept an integer index rather than an - iterator. For that reason, iterators are rarely useful in - connection with QJsonArray. One place where STL-style iterators do - make sense is as arguments to \l{generic algorithms}. - - Multiple iterators can be used on the same array. However, be - aware that any non-const function call performed on the QJsonArray - will render all existing iterators undefined. - - \sa QJsonArray::iterator -*/ - -/*! \fn QJsonArray::const_iterator::const_iterator() - - Constructs an uninitialized iterator. - - Functions like operator*() and operator++() should not be called - on an uninitialized iterator. Use operator=() to assign a value - to it before using it. - - \sa QJsonArray::constBegin(), QJsonArray::constEnd() -*/ - -/*! \fn QJsonArray::const_iterator::const_iterator(const QJsonArray *array, int index) - \internal -*/ - -/*! \typedef QJsonArray::const_iterator::iterator_category - - A synonym for \e {std::random_access_iterator_tag} indicating - this iterator is a random access iterator. -*/ - -/*! \typedef QJsonArray::const_iterator::difference_type - - \internal -*/ - -/*! \typedef QJsonArray::const_iterator::value_type - - \internal -*/ - -/*! \typedef QJsonArray::const_iterator::reference - - \internal -*/ - -/*! \typedef QJsonArray::const_iterator::pointer - - \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 - - Returns the current item. -*/ - -/*! \fn QJsonValue *QJsonArray::const_iterator::operator->() const - - Returns a pointer to the current item. -*/ - -/*! \fn QJsonValue QJsonArray::const_iterator::operator[](int j) const - - Returns the item at offset \a j from the item pointed to by this iterator (the item at - position \c{*this + j}). - - This function is provided to make QJsonArray iterators behave like C++ - pointers. - - \sa operator+() -*/ - -/*! \fn bool QJsonArray::const_iterator::operator==(const const_iterator &other) const - - Returns \c true if \a other points to the same item as this - iterator; otherwise returns \c false. - - \sa operator!=() -*/ - -/*! \fn bool QJsonArray::const_iterator::operator!=(const const_iterator &other) const - - Returns \c true if \a other points to a different item than this - iterator; otherwise returns \c false. - - \sa operator==() -*/ - -/*! - \fn bool QJsonArray::const_iterator::operator<(const const_iterator& other) const - - Returns \c true if the item pointed to by this iterator is less than - the item pointed to by the \a other iterator. -*/ - -/*! - \fn bool QJsonArray::const_iterator::operator<=(const const_iterator& other) const - - 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. -*/ - -/*! - \fn bool QJsonArray::const_iterator::operator>(const const_iterator& other) const - - Returns \c true if the item pointed to by this iterator is greater - than the item pointed to by the \a other iterator. -*/ - -/*! - \fn bool QJsonArray::const_iterator::operator>=(const const_iterator& other) const - - 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. -*/ - -/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator++() - - The prefix ++ operator, \c{++it}, advances the iterator to the - next item in the array and returns an iterator to the new current - item. - - Calling this function on QJsonArray::end() leads to undefined results. - - \sa operator--() -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator++(int) - - \overload - - The postfix ++ 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 - current and returns an iterator to the new current item. - - Calling this function on QJsonArray::begin() leads to undefined results. - - \sa operator++() -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator--(int) - - \overload - - The postfix -- 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) - - Advances the iterator by \a j items. If \a j is negative, the - iterator goes backward. - - \sa operator-=(), operator+() -*/ - -/*! \fn QJsonArray::const_iterator &QJsonArray::const_iterator::operator-=(int j) - - Makes the iterator go back by \a j items. If \a j is negative, - the iterator goes forward. - - \sa operator+=(), operator-() -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator+(int 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. - - \sa operator-(), operator+=() -*/ - -/*! \fn QJsonArray::const_iterator QJsonArray::const_iterator::operator-(int 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. - - \sa operator+(), operator-=() -*/ - -/*! \fn int 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) -{ - if (!d) { - if (reserve >= QJsonPrivate::Value::MaxSize) { - qWarning("QJson: Document too large to store in data structure"); - return false; - } - d = new QJsonPrivate::Data(reserve, QJsonValue::Array); - a = static_cast<QJsonPrivate::Array *>(d->header->root()); - d->ref.ref(); - return true; - } - if (reserve == 0 && d->ref.load() == 1) - return true; - - QJsonPrivate::Data *x = d->clone(a, reserve); - if (!x) - return false; - x->ref.ref(); - if (!d->ref.deref()) - delete d; - d = x; - a = static_cast<QJsonPrivate::Array *>(d->header->root()); - return true; -} - -/*! - \internal - */ -void QJsonArray::compact() -{ - if (!d || !d->compactionCounter) - return; - - detach2(); - d->compact(); - a = static_cast<QJsonPrivate::Array *>(d->header->root()); -} - - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -QDebug operator<<(QDebug dbg, const QJsonArray &a) -{ - QDebugStateSaver saver(dbg); - if (!a.a) { - dbg << "QJsonArray()"; - return dbg; - } - QByteArray json; - QJsonPrivate::Writer::arrayToJson(a.a, json, 0, true); - dbg.nospace() << "QJsonArray(" - << json.constData() // print as utf-8 string without extra quotation marks - << ")"; - return dbg; -} -#endif - -QT_END_NAMESPACE - diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h deleted file mode 100644 index 8d41138c97..0000000000 --- a/src/corelib/json/qjsonarray.h +++ /dev/null @@ -1,274 +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$ -** -****************************************************************************/ - -#ifndef QJSONARRAY_H -#define QJSONARRAY_H - -#include <QtCore/qjsonvalue.h> -#include <QtCore/qiterator.h> -#if defined(Q_COMPILER_INITIALIZER_LISTS) -#include <initializer_list> -#endif - -QT_BEGIN_NAMESPACE - -class QDebug; -class QStringList; -template <typename T> class QList; -typedef QList<QVariant> QVariantList; - -class Q_CORE_EXPORT QJsonArray -{ -public: - QJsonArray(); - -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) - QJsonArray(std::initializer_list<QJsonValue> args) - { - initialize(); - for (std::initializer_list<QJsonValue>::const_iterator i = args.begin(); i != args.end(); ++i) - append(*i); - } -#endif - - ~QJsonArray(); - - QJsonArray(const QJsonArray &other); - QJsonArray &operator =(const QJsonArray &other); - - QJsonArray(QJsonArray &&other) Q_DECL_NOTHROW - : d(other.d), - a(other.a) - { - other.d = nullptr; - other.a = nullptr; - } - - QJsonArray &operator =(QJsonArray &&other) Q_DECL_NOTHROW - { - swap(other); - return *this; - } - - static QJsonArray fromStringList(const QStringList &list); - static QJsonArray fromVariantList(const QVariantList &list); - QVariantList toVariantList() const; - - int size() const; - inline int count() const { return size(); } - - bool isEmpty() const; - QJsonValue at(int 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); - 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); - - bool contains(const QJsonValue &element) const; - QJsonValueRef operator[](int i); - QJsonValue operator[](int i) const; - - bool operator==(const QJsonArray &other) const; - bool operator!=(const QJsonArray &other) const; - - void swap(QJsonArray &other) Q_DECL_NOTHROW - { - qSwap(d, other.d); - qSwap(a, 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 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); } -#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; } - }; - 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)); } -#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; } - }; - friend class const_iterator; - - // stl style - inline iterator begin() { detach2(); 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 const_iterator end() const { return const_iterator(this, size()); } - inline const_iterator constEnd() 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; } - - // more Qt - typedef iterator Iterator; - typedef const_iterator ConstIterator; - - // convenience - inline QJsonArray operator+(const QJsonValue &v) const - { QJsonArray n = *this; n += v; return n; } - inline QJsonArray &operator+=(const QJsonValue &v) - { append(v); return *this; } - inline QJsonArray &operator<< (const QJsonValue &v) - { append(v); return *this; } - - // stl compatibility - inline void push_back(const QJsonValue &t) { append(t); } - inline void push_front(const QJsonValue &t) { prepend(t); } - inline void pop_front() { removeFirst(); } - inline void pop_back() { removeLast(); } - inline bool empty() const { return isEmpty(); } - typedef int 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; - -private: - friend class QJsonPrivate::Data; - friend class QJsonValue; - friend class QJsonDocument; - friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &); - - QJsonArray(QJsonPrivate::Data *data, QJsonPrivate::Array *array); - void initialize(); - void compact(); - // ### Qt 6: remove me and merge with detach2 - void detach(uint reserve = 0); - bool detach2(uint reserve = 0); - - QJsonPrivate::Data *d; - QJsonPrivate::Array *a; -}; - -Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray) - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &); -#endif - -QT_END_NAMESPACE - -#endif // QJSONARRAY_H diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp deleted file mode 100644 index 9794bca60d..0000000000 --- a/src/corelib/json/qjsondocument.cpp +++ /dev/null @@ -1,667 +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 <qjsondocument.h> -#include <qjsonobject.h> -#include <qjsonvalue.h> -#include <qjsonarray.h> -#include <qstringlist.h> -#include <qvariant.h> -#include <qdebug.h> -#include "qjsonwriter_p.h" -#include "qjsonparser_p.h" -#include "qjson_p.h" - -QT_BEGIN_NAMESPACE - -/*! \class QJsonDocument - \inmodule QtCore - \ingroup json - \ingroup shared - \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. - - 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 - fast and efficient and converts the JSON to the binary representation used by Qt. - - Validity of the parsed document can be queried with !isNull() - - A document can be queried as to whether it contains an array or an object using isArray() - 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} -*/ - -/*! - * Constructs an empty and invalid document. - */ -QJsonDocument::QJsonDocument() - : d(0) -{ -} - -/*! - * Creates a QJsonDocument from \a object. - */ -QJsonDocument::QJsonDocument(const QJsonObject &object) - : d(0) -{ - setObject(object); -} - -/*! - * Constructs a QJsonDocument from \a array. - */ -QJsonDocument::QJsonDocument(const QJsonArray &array) - : d(0) -{ - setArray(array); -} - -/*! - \internal - */ -QJsonDocument::QJsonDocument(QJsonPrivate::Data *data) - : d(data) -{ - Q_ASSERT(d); - d->ref.ref(); -} - -/*! - Deletes the document. - - Binary data set with fromRawData is not freed. - */ -QJsonDocument::~QJsonDocument() -{ - if (d && !d->ref.deref()) - delete d; -} - -/*! - * Creates a copy of the \a other document. - */ -QJsonDocument::QJsonDocument(const QJsonDocument &other) -{ - d = other.d; - if (d) - d->ref.ref(); -} - -/*! - * Assigns the \a other document to this QJsonDocument. - * Returns a reference to this object. - */ -QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other) -{ - if (d != other.d) { - if (d && !d->ref.deref()) - delete d; - d = other.d; - if (d) - d->ref.ref(); - } - - return *this; -} - -/*! - \fn QJsonDocument::QJsonDocument(QJsonDocument &&other) - \since 5.10 - - Move-constructs a QJsonDocument from \a other. -*/ - -/*! - \fn QJsonDocument &QJsonDocument::operator =(QJsonDocument &&other) - \since 5.10 - - Move-assigns \a other to this document. -*/ - -/*! - \fn void QJsonDocument::swap(QJsonDocument &other) - \since 5.10 - - 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. - */ - -/*! - 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 and the caller - has to guarantee that \a data will not be deleted or modified as long as - any QJsonDocument, QJsonObject or QJsonArray still references the data. - - \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. - - \sa rawData(), fromBinaryData(), isNull(), DataValidation - */ -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(); - } - - QJsonPrivate::Data *d = new QJsonPrivate::Data((char *)data, size); - d->ownsData = false; - - if (validation != BypassValidation && !d->valid()) { - delete d; - return QJsonDocument(); - } - - return QJsonDocument(d); -} - -/*! - 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 it's binary form to a file. - */ -const char *QJsonDocument::rawData(int *size) const -{ - if (!d) { - *size = 0; - return 0; - } - *size = d->alloc; - return d->rawData; -} - -/*! - 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. - - \sa toBinaryData(), fromRawData(), isNull(), DataValidation - */ -QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidation validation) -{ - if (data.size() < (int)(sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base))) - return QJsonDocument(); - - QJsonPrivate::Header h; - memcpy(&h, data.constData(), sizeof(QJsonPrivate::Header)); - QJsonPrivate::Base root; - memcpy(&root, data.constData() + sizeof(QJsonPrivate::Header), sizeof(QJsonPrivate::Base)); - - // do basic checks here, so we don't try to allocate more memory than we can. - if (h.tag != QJsonDocument::BinaryFormatTag || h.version != 1u || - sizeof(QJsonPrivate::Header) + root.size > (uint)data.size()) - return QJsonDocument(); - - const uint size = sizeof(QJsonPrivate::Header) + root.size; - char *raw = (char *)malloc(size); - if (!raw) - return QJsonDocument(); - - memcpy(raw, data.constData(), size); - QJsonPrivate::Data *d = new QJsonPrivate::Data(raw, size); - - if (validation != BypassValidation && !d->valid()) { - delete d; - return QJsonDocument(); - } - - return QJsonDocument(d); -} - -/*! - Creates a QJsonDocument from the QVariant \a variant. - - If the \a variant contains any other type than a QVariantMap, - QVariantHash, QVariantList or QStringList, the returned document is invalid. - - \sa toVariant() - */ -QJsonDocument QJsonDocument::fromVariant(const QVariant &variant) -{ - QJsonDocument doc; - switch (variant.type()) { - case QVariant::Map: - doc.setObject(QJsonObject::fromVariantMap(variant.toMap())); - break; - case QVariant::Hash: - doc.setObject(QJsonObject::fromVariantHash(variant.toHash())); - break; - case QVariant::List: - doc.setArray(QJsonArray::fromVariantList(variant.toList())); - break; - case QVariant::StringList: - doc.setArray(QJsonArray::fromStringList(variant.toStringList())); - break; - default: - break; - } - return doc; -} - -/*! - Returns a QVariant representing the Json document. - - The returned variant will be a QVariantList if the document is - a QJsonArray and a QVariantMap if the document is a QJsonObject. - - \sa fromVariant(), QJsonValue::toVariant() - */ -QVariant QJsonDocument::toVariant() const -{ - if (!d) - return QVariant(); - - if (d->header->root()->isArray()) - return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root())).toVariantList(); - else - return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root())).toVariantMap(); -} - -/*! - Converts the QJsonDocument to a UTF-8 encoded JSON document. - - \sa fromJson() - */ -#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC) -QByteArray QJsonDocument::toJson() const -{ - return toJson(Indented); -} -#endif - -/*! - \enum QJsonDocument::JsonFormat - - This value defines the format of the JSON byte array produced - when converting to a QJsonDocument using toJson(). - - \value Indented Defines human readable output as follows: - \code - { - "Array": [ - true, - 999, - "string" - ], - "Key": "Value", - "null": null - } - \endcode - - \value Compact Defines a compact output as follows: - \code - {"Array":[true,999,"string"],"Key":"Value","null":null} - \endcode - */ - -/*! - Converts the QJsonDocument to a UTF-8 encoded JSON document in the provided \a format. - - \sa fromJson(), JsonFormat - */ -#if !defined(QT_JSON_READONLY) || defined(Q_CLANG_QDOC) -QByteArray QJsonDocument::toJson(JsonFormat format) const -{ - QByteArray json; - if (!d) - return json; - - if (d->header->root()->isArray()) - QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(d->header->root()), json, 0, (format == Compact)); - else - QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(d->header->root()), json, 0, (format == Compact)); - - return json; -} -#endif - -/*! - Parses \a json as a UTF-8 encoded JSON document, and creates a QJsonDocument - from it. - - Returns a valid (non-null) QJsonDocument if the parsing succeeds. If it fails, - the returned document will be null, and the optional \a error variable will contain - further details about the error. - - \sa toJson(), QJsonParseError, isNull() - */ -QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error) -{ - QJsonPrivate::Parser parser(json.constData(), json.length()); - return parser.parse(error); -} - -/*! - Returns \c true if the document doesn't contain any data. - */ -bool QJsonDocument::isEmpty() const -{ - if (!d) - return true; - - return false; -} - -/*! - 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. - - \sa fromBinaryData() - */ -QByteArray QJsonDocument::toBinaryData() const -{ - if (!d || !d->rawData) - return QByteArray(); - - return QByteArray(d->rawData, d->header->root()->size + sizeof(QJsonPrivate::Header)); -} - -/*! - Returns \c true if the document contains an array. - - \sa array(), isObject() - */ -bool QJsonDocument::isArray() const -{ - if (!d) - return false; - - QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData; - return h->root()->isArray(); -} - -/*! - Returns \c true if the document contains an object. - - \sa object(), isArray() - */ -bool QJsonDocument::isObject() const -{ - if (!d) - return false; - - QJsonPrivate::Header *h = (QJsonPrivate::Header *)d->rawData; - return h->root()->isObject(); -} - -/*! - Returns the QJsonObject contained in the document. - - Returns an empty object if the document contains an - array. - - \sa isObject(), array(), setObject() - */ -QJsonObject QJsonDocument::object() const -{ - if (d) { - QJsonPrivate::Base *b = d->header->root(); - if (b->isObject()) - return QJsonObject(d, static_cast<QJsonPrivate::Object *>(b)); - } - return QJsonObject(); -} - -/*! - Returns the QJsonArray contained in the document. - - Returns an empty array if the document contains an - object. - - \sa isArray(), object(), setArray() - */ -QJsonArray QJsonDocument::array() const -{ - if (d) { - QJsonPrivate::Base *b = d->header->root(); - if (b->isArray()) - return QJsonArray(d, static_cast<QJsonPrivate::Array *>(b)); - } - return QJsonArray(); -} - -/*! - Sets \a object as the main object of this document. - - \sa setArray(), object() - */ -void QJsonDocument::setObject(const QJsonObject &object) -{ - if (d && !d->ref.deref()) - delete d; - - d = object.d; - - if (!d) { - d = new QJsonPrivate::Data(0, QJsonValue::Object); - } else if (d->compactionCounter || object.o != d->header->root()) { - QJsonObject o(object); - if (d->compactionCounter) - o.compact(); - else - o.detach2(); - d = o.d; - d->ref.ref(); - return; - } - d->ref.ref(); -} - -/*! - Sets \a array as the main object of this document. - - \sa setObject(), array() - */ -void QJsonDocument::setArray(const QJsonArray &array) -{ - if (d && !d->ref.deref()) - delete d; - - d = array.d; - - if (!d) { - d = new QJsonPrivate::Data(0, QJsonValue::Array); - } else if (d->compactionCounter || array.a != d->header->root()) { - QJsonArray a(array); - if (d->compactionCounter) - a.compact(); - else - a.detach2(); - d = a.d; - d->ref.ref(); - return; - } - d->ref.ref(); -} - -/*! - Returns a QJsonValue representing the value for the key \a key. - - Equivalent to calling object().value(key). - - The returned QJsonValue is QJsonValue::Undefined if the key does not exist, - or if isObject() is false. - - \since 5.10 - - \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject - */ -const QJsonValue QJsonDocument::operator[](const QString &key) const -{ - if (!isObject()) - return QJsonValue(QJsonValue::Undefined); - - return object().value(key); -} - -/*! - \overload - \since 5.10 -*/ -const QJsonValue QJsonDocument::operator[](QLatin1String key) const -{ - if (!isObject()) - return QJsonValue(QJsonValue::Undefined); - - return object().value(key); -} - -/*! - Returns a QJsonValue representing the value for index \a i. - - Equivalent to calling array().at(i). - - The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds, - or if isArray() is false. - - \since 5.10 - - \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray - */ -const QJsonValue QJsonDocument::operator[](int i) const -{ - if (!isArray()) - return QJsonValue(QJsonValue::Undefined); - - return array().at(i); -} - -/*! - Returns \c true if the \a other document is equal to this document. - */ -bool QJsonDocument::operator==(const QJsonDocument &other) const -{ - if (d == other.d) - return true; - - if (!d || !other.d) - return false; - - if (d->header->root()->isArray() != other.d->header->root()->isArray()) - return false; - - if (d->header->root()->isObject()) - return QJsonObject(d, static_cast<QJsonPrivate::Object *>(d->header->root())) - == QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.d->header->root())); - else - return QJsonArray(d, static_cast<QJsonPrivate::Array *>(d->header->root())) - == QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.d->header->root())); -} - -/*! - \fn bool QJsonDocument::operator!=(const QJsonDocument &other) const - - returns \c true if \a other is not equal to this document - */ - -/*! - returns \c true if this document is null. - - Null documents are documents created through the default constructor. - - Documents created from UTF-8 encoded text or the binary format are - validated during parsing. If validation fails, the returned document - will also be null. - */ -bool QJsonDocument::isNull() const -{ - return (d == 0); -} - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -QDebug operator<<(QDebug dbg, const QJsonDocument &o) -{ - QDebugStateSaver saver(dbg); - if (!o.d) { - dbg << "QJsonDocument()"; - return dbg; - } - QByteArray json; - if (o.d->header->root()->isArray()) - QJsonPrivate::Writer::arrayToJson(static_cast<QJsonPrivate::Array *>(o.d->header->root()), json, 0, true); - else - QJsonPrivate::Writer::objectToJson(static_cast<QJsonPrivate::Object *>(o.d->header->root()), json, 0, true); - dbg.nospace() << "QJsonDocument(" - << json.constData() // print as utf-8 string without extra quotation marks - << ')'; - return dbg; -} -#endif - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjsondocument.h b/src/corelib/json/qjsondocument.h deleted file mode 100644 index b784890c54..0000000000 --- a/src/corelib/json/qjsondocument.h +++ /dev/null @@ -1,177 +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$ -** -****************************************************************************/ - -#ifndef QJSONDOCUMENT_H -#define QJSONDOCUMENT_H - -#include <QtCore/qjsonvalue.h> - -QT_BEGIN_NAMESPACE - -class QDebug; - -namespace QJsonPrivate { - class Parser; -} - -struct Q_CORE_EXPORT QJsonParseError -{ - enum ParseError { - NoError = 0, - UnterminatedObject, - MissingNameSeparator, - UnterminatedArray, - MissingValueSeparator, - IllegalValue, - TerminationByNumber, - IllegalNumber, - IllegalEscapeSequence, - IllegalUTF8String, - UnterminatedString, - MissingObject, - DeepNesting, - DocumentTooLarge, - GarbageAtEnd - }; - - QString errorString() const; - - int offset; - ParseError error; -}; - -class Q_CORE_EXPORT QJsonDocument -{ -public: -#ifdef Q_LITTLE_ENDIAN - static const uint BinaryFormatTag = ('q') | ('b' << 8) | ('j' << 16) | ('s' << 24); -#else - static const uint BinaryFormatTag = ('q' << 24) | ('b' << 16) | ('j' << 8) | ('s'); -#endif - - QJsonDocument(); - explicit QJsonDocument(const QJsonObject &object); - explicit QJsonDocument(const QJsonArray &array); - ~QJsonDocument(); - - QJsonDocument(const QJsonDocument &other); - QJsonDocument &operator =(const QJsonDocument &other); - - QJsonDocument(QJsonDocument &&other) Q_DECL_NOTHROW - : d(other.d) - { - other.d = nullptr; - } - - QJsonDocument &operator =(QJsonDocument &&other) Q_DECL_NOTHROW - { - swap(other); - return *this; - } - - void swap(QJsonDocument &other) Q_DECL_NOTHROW - { - qSwap(d, other.d); - } - - enum DataValidation { - Validate, - BypassValidation - }; - - static QJsonDocument fromRawData(const char *data, int size, DataValidation validation = Validate); - const char *rawData(int *size) const; - - static QJsonDocument fromBinaryData(const QByteArray &data, DataValidation validation = Validate); - QByteArray toBinaryData() const; - - static QJsonDocument fromVariant(const QVariant &variant); - QVariant toVariant() const; - - enum JsonFormat { - Indented, - Compact - }; - - 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; -#endif - - bool isEmpty() const; - bool isArray() const; - bool isObject() const; - - QJsonObject object() const; - QJsonArray array() const; - - void setObject(const QJsonObject &object); - void setArray(const QJsonArray &array); - - const QJsonValue operator[](const QString &key) const; - const QJsonValue operator[](QLatin1String key) const; - const QJsonValue operator[](int i) const; - - bool operator==(const QJsonDocument &other) const; - bool operator!=(const QJsonDocument &other) const { return !(*this == other); } - - bool isNull() const; - -private: - friend class QJsonValue; - friend class QJsonPrivate::Data; - friend class QJsonPrivate::Parser; - friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &); - - QJsonDocument(QJsonPrivate::Data *data); - - QJsonPrivate::Data *d; -}; - -Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonDocument) - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &); -#endif - -QT_END_NAMESPACE - -#endif // QJSONDOCUMENT_H diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp deleted file mode 100644 index 4a316c8a6f..0000000000 --- a/src/corelib/json/qjsonobject.cpp +++ /dev/null @@ -1,1312 +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 <qjsonobject.h> -#include <qjsonvalue.h> -#include <qjsonarray.h> -#include <qstringlist.h> -#include <qdebug.h> -#include <qvariant.h> -#include "qjson_p.h" -#include "qjsonwriter_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QJsonObject - \inmodule QtCore - \ingroup json - \ingroup shared - \reentrant - \since 5.0 - - \brief The QJsonObject class encapsulates a JSON object. - - A JSON object is a list of key value pairs, where the keys are unique strings - and the values are represented by a QJsonValue. - - A QJsonObject can be converted to and from a QVariantMap. You can query the - number of (key, value) pairs with size(), insert(), and remove() entries from it - and iterate over its content using the standard C++ iterator pattern. - - QJsonObject is an implicitly shared class, and shares the data with the document - it has been created from as long as it is not being modified. - - You can convert the object to and from text based JSON through QJsonDocument. - - \sa {JSON Support in Qt}, {JSON Save Game Example} -*/ - -/*! - \typedef QJsonObject::Iterator - - Qt-style synonym for QJsonObject::iterator. -*/ - -/*! - \typedef QJsonObject::ConstIterator - - Qt-style synonym for QJsonObject::const_iterator. -*/ - -/*! - \typedef QJsonObject::key_type - - Typedef for QString. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonObject::mapped_type - - Typedef for QJsonValue. Provided for STL compatibility. -*/ - -/*! - \typedef QJsonObject::size_type - - Typedef for int. Provided for STL compatibility. -*/ - - -/*! - Constructs an empty JSON object. - - \sa isEmpty() - */ -QJsonObject::QJsonObject() - : d(0), o(0) -{ -} - -/*! - \fn QJsonObject::QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args) - \since 5.4 - Constructs a QJsonObject instance initialized from \a args initialization list. - For example: - \code - QJsonObject object - { - {"property1", 1}, - {"property2", 2} - }; - \endcode -*/ - -/*! - \internal - */ -QJsonObject::QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object) - : d(data), o(object) -{ - Q_ASSERT(d); - Q_ASSERT(o); - d->ref.ref(); -} - -/*! - 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() -{ - d = 0; - o = 0; -} - -/*! - Destroys the object. - */ -QJsonObject::~QJsonObject() -{ - if (d && !d->ref.deref()) - delete d; -} - -/*! - Creates a copy of \a other. - - Since QJsonObject is implicitly shared, the copy is shallow - as long as the object does not get modified. - */ -QJsonObject::QJsonObject(const QJsonObject &other) -{ - d = other.d; - o = other.o; - if (d) - d->ref.ref(); -} - -/*! - Assigns \a other to this object. - */ -QJsonObject &QJsonObject::operator =(const QJsonObject &other) -{ - if (d != other.d) { - if (d && !d->ref.deref()) - delete d; - d = other.d; - if (d) - d->ref.ref(); - } - o = other.o; - - return *this; -} - -/*! - \fn QJsonObject::QJsonObject(QJsonObject &&other) - \since 5.10 - - Move-constructs a QJsonObject from \a other. -*/ - -/*! - \fn QJsonObject &QJsonObject::operator =(QJsonObject &&other) - \since 5.10 - - Move-assigns \a other to this object. -*/ - -/*! - \fn void QJsonObject::swap(QJsonObject &other) - \since 5.10 - - Swaps the object \a other with this. This operation is very fast and never fails. -*/ - - -/*! - 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. - - \sa fromVariantHash(), toVariantMap(), QJsonValue::fromVariant() - */ -QJsonObject QJsonObject::fromVariantMap(const QVariantMap &map) -{ - QJsonObject object; - if (map.isEmpty()) - return object; - - object.detach2(1024); - - QVector<QJsonPrivate::offset> offsets; - QJsonPrivate::offset currentOffset; - currentOffset = sizeof(QJsonPrivate::Base); - - // the map is already sorted, so we can simply append one entry after the other and - // write the offset table at the end - for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { - QString key = it.key(); - QJsonValue val = QJsonValue::fromVariant(it.value()); - - bool latinOrIntValue; - int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); - - bool latinKey = QJsonPrivate::useCompressed(key); - int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); - int requiredSize = valueOffset + valueSize; - - if (!object.detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry - return QJsonObject(); - - QJsonPrivate::Entry *e = reinterpret_cast<QJsonPrivate::Entry *>(reinterpret_cast<char *>(object.o) + currentOffset); - e->value.type = val.t; - e->value.latinKey = latinKey; - e->value.latinOrIntValue = latinOrIntValue; - e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)object.o + valueOffset); - QJsonPrivate::copyString((char *)(e + 1), key, latinKey); - if (valueSize) - QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); - - offsets << currentOffset; - currentOffset += requiredSize; - object.o->size = currentOffset; - } - - // write table - object.o->tableOffset = currentOffset; - if (!object.detach2(sizeof(QJsonPrivate::offset)*offsets.size())) - return QJsonObject(); - memcpy(object.o->table(), offsets.constData(), offsets.size()*sizeof(uint)); - object.o->length = offsets.size(); - object.o->size = currentOffset + sizeof(QJsonPrivate::offset)*offsets.size(); - - return object; -} - -/*! - Converts this object to a QVariantMap. - - Returns the created map. - - \sa toVariantHash() - */ -QVariantMap QJsonObject::toVariantMap() const -{ - QVariantMap map; - if (o) { - for (uint i = 0; i < o->length; ++i) { - QJsonPrivate::Entry *e = o->entryAt(i); - map.insert(e->key(), QJsonValue(d, o, e->value).toVariant()); - } - } - return map; -} - -/*! - Converts the variant hash \a hash to a QJsonObject. - \since 5.5 - - 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. - - \sa fromVariantMap(), toVariantHash(), QJsonValue::fromVariant() - */ -QJsonObject QJsonObject::fromVariantHash(const QVariantHash &hash) -{ - // ### this is implemented the trivial way, not the most efficient way - - QJsonObject object; - for (QVariantHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) - object.insert(it.key(), QJsonValue::fromVariant(it.value())); - return object; -} - -/*! - Converts this object to a QVariantHash. - \since 5.5 - - Returns the created hash. - - \sa toVariantMap() - */ -QVariantHash QJsonObject::toVariantHash() const -{ - QVariantHash hash; - if (o) { - hash.reserve(o->length); - for (uint i = 0; i < o->length; ++i) { - QJsonPrivate::Entry *e = o->entryAt(i); - hash.insert(e->key(), QJsonValue(d, o, e->value).toVariant()); - } - } - return hash; -} - -/*! - Returns a list of all keys in this object. - - The list is sorted lexographically. - */ -QStringList QJsonObject::keys() const -{ - QStringList keys; - if (o) { - keys.reserve(o->length); - for (uint i = 0; i < o->length; ++i) { - QJsonPrivate::Entry *e = o->entryAt(i); - keys.append(e->key()); - } - } - return keys; -} - -/*! - Returns the number of (key, value) pairs stored in the object. - */ -int QJsonObject::size() const -{ - if (!d) - return 0; - - return o->length; -} - -/*! - Returns \c true if the object is empty. This is the same as size() == 0. - - \sa size() - */ -bool QJsonObject::isEmpty() const -{ - if (!d) - return true; - - return !o->length; -} - -/*! - Returns a QJsonValue representing the value for the key \a key. - - The returned QJsonValue is QJsonValue::Undefined if the key does not exist. - - \sa QJsonValue, QJsonValue::isUndefined() - */ -QJsonValue QJsonObject::value(const QString &key) const -{ - if (!d) - return QJsonValue(QJsonValue::Undefined); - - bool keyExists; - int i = o->indexOf(key, &keyExists); - if (!keyExists) - return QJsonValue(QJsonValue::Undefined); - return QJsonValue(d, o, o->entryAt(i)->value); -} - -/*! - \overload - \since 5.7 -*/ -QJsonValue QJsonObject::value(QLatin1String key) const -{ - if (!d) - return QJsonValue(QJsonValue::Undefined); - - bool keyExists; - int i = o->indexOf(key, &keyExists); - if (!keyExists) - return QJsonValue(QJsonValue::Undefined); - return QJsonValue(d, o, o->entryAt(i)->value); -} - -/*! - Returns a QJsonValue representing the value for the key \a key. - - This does the same as value(). - - The returned QJsonValue is QJsonValue::Undefined if the key does not exist. - - \sa value(), QJsonValue, QJsonValue::isUndefined() - */ -QJsonValue QJsonObject::operator [](const QString &key) const -{ - return value(key); -} - -/*! - \fn QJsonValue QJsonObject::operator [](QLatin1String key) const - - \overload - \since 5.7 -*/ - -/*! - Returns a reference to the value for \a key. - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the element in the QJsonArray or QJsonObject - from which you got the reference. - - \sa value() - */ -QJsonValueRef QJsonObject::operator [](const QString &key) -{ - // ### somewhat inefficient, as we lookup the key twice if it doesn't yet exist - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : -1; - if (!keyExists) { - iterator i = insert(key, QJsonValue()); - index = i.i; - } - return QJsonValueRef(this, index); -} - -/*! - \overload - \since 5.7 -*/ -QJsonValueRef QJsonObject::operator [](QLatin1String key) -{ - // ### optimize me - return operator[](QString(key)); -} - -/*! - Inserts a new item with the key \a key and a value of \a value. - - If there is already an item with the key \a key, then that item's value - is replaced with \a value. - - Returns an iterator pointing to the inserted item. - - If the value is QJsonValue::Undefined, it will cause the key to get removed - from the object. The returned iterator will then point to end(). - - \sa remove(), take(), QJsonObject::iterator, end() - */ -QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue &value) -{ - if (value.t == QJsonValue::Undefined) { - remove(key); - return end(); - } - QJsonValue val = value; - - bool latinOrIntValue; - int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); - - bool latinKey = QJsonPrivate::useCompressed(key); - int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); - int requiredSize = valueOffset + valueSize; - - if (!detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry - return iterator(); - - if (!o->length) - o->tableOffset = sizeof(QJsonPrivate::Object); - - bool keyExists = false; - int pos = o->indexOf(key, &keyExists); - if (keyExists) - ++d->compactionCounter; - - uint off = o->reserveSpace(requiredSize, pos, 1, keyExists); - if (!off) - return end(); - - QJsonPrivate::Entry *e = o->entryAt(pos); - e->value.type = val.t; - e->value.latinKey = latinKey; - e->value.latinOrIntValue = latinOrIntValue; - e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)o + valueOffset); - QJsonPrivate::copyString((char *)(e + 1), key, latinKey); - if (valueSize) - QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); - - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); - - return iterator(this, pos); -} - -/*! - Removes \a key from the object. - - \sa insert(), take() - */ -void QJsonObject::remove(const QString &key) -{ - if (!d) - return; - - bool keyExists; - int index = o->indexOf(key, &keyExists); - if (!keyExists) - return; - - detach2(); - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); -} - -/*! - Removes \a key from the object. - - Returns a QJsonValue containing the value referenced by \a key. - If \a key was not contained in the object, the returned QJsonValue - is QJsonValue::Undefined. - - \sa insert(), remove(), QJsonValue - */ -QJsonValue QJsonObject::take(const QString &key) -{ - if (!o) - return QJsonValue(QJsonValue::Undefined); - - bool keyExists; - int index = o->indexOf(key, &keyExists); - if (!keyExists) - return QJsonValue(QJsonValue::Undefined); - - QJsonValue v(d, o, o->entryAt(index)->value); - detach2(); - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); - - return v; -} - -/*! - Returns \c true if the object contains key \a key. - - \sa insert(), remove(), take() - */ -bool QJsonObject::contains(const QString &key) const -{ - if (!o) - return false; - - bool keyExists; - o->indexOf(key, &keyExists); - return keyExists; -} - -/*! - \overload - \since 5.7 -*/ -bool QJsonObject::contains(QLatin1String key) const -{ - if (!o) - return false; - - bool keyExists; - o->indexOf(key, &keyExists); - return keyExists; -} - -/*! - Returns \c true if \a other is equal to this object. - */ -bool QJsonObject::operator==(const QJsonObject &other) const -{ - if (o == other.o) - return true; - - if (!o) - return !other.o->length; - if (!other.o) - return !o->length; - if (o->length != other.o->length) - return false; - - for (uint i = 0; i < o->length; ++i) { - QJsonPrivate::Entry *e = o->entryAt(i); - QJsonValue v(d, o, e->value); - if (other.value(e->key()) != v) - return false; - } - - return true; -} - -/*! - Returns \c true if \a other is not equal to this object. - */ -bool QJsonObject::operator!=(const QJsonObject &other) const -{ - return !(*this == other); -} - -/*! - Removes the (key, value) pair pointed to by the iterator \a it - from the map, and returns an iterator to the next item in the - map. - - \sa remove() - */ -QJsonObject::iterator QJsonObject::erase(QJsonObject::iterator it) -{ - Q_ASSERT(d && d->ref.load() == 1); - if (it.o != this || it.i < 0 || it.i >= (int)o->length) - return iterator(this, o->length); - - int index = it.i; - - o->removeItems(index, 1); - ++d->compactionCounter; - if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) - compact(); - - // iterator hasn't changed - return it; -} - -/*! - Returns an iterator pointing to the item with key \a key in the - map. - - If the map contains no item with key \a key, the function - returns end(). - */ -QJsonObject::iterator QJsonObject::find(const QString &key) -{ - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - detach2(); - return iterator(this, index); -} - -/*! - \overload - \since 5.7 -*/ -QJsonObject::iterator QJsonObject::find(QLatin1String key) -{ - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - detach2(); - return iterator(this, index); -} - -/*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const - - \overload -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const - - \overload - \since 5.7 -*/ - -/*! - Returns a const iterator pointing to the item with key \a key in the - map. - - If the map contains no item with key \a key, the function - returns constEnd(). - */ -QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const -{ - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - return const_iterator(this, index); -} - -/*! - \overload - \since 5.7 -*/ -QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const -{ - bool keyExists = false; - int index = o ? o->indexOf(key, &keyExists) : 0; - if (!keyExists) - return end(); - return const_iterator(this, index); -} - -/*! \fn int QJsonObject::count() const - - \overload - - Same as size(). -*/ - -/*! \fn int QJsonObject::length() const - - \overload - - Same as size(). -*/ - -/*! \fn QJsonObject::iterator QJsonObject::begin() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first item in - the object. - - \sa constBegin(), end() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::begin() const - - \overload -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::constBegin() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item - in the object. - - \sa begin(), constEnd() -*/ - -/*! \fn QJsonObject::iterator QJsonObject::end() - - Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item - after the last item in the object. - - \sa begin(), constEnd() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::end() const - - \overload -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::constEnd() const - - Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary - item after the last item in the object. - - \sa constBegin(), end() -*/ - -/*! - \fn bool QJsonObject::empty() const - - This function is provided for STL compatibility. It is equivalent - to isEmpty(), returning \c true if the object is empty; otherwise - returning \c false. -*/ - -/*! \class QJsonObject::iterator - \inmodule QtCore - \ingroup json - \reentrant - \since 5.0 - - \brief The QJsonObject::iterator class provides an STL-style non-const iterator for QJsonObject. - - 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 - should use QJsonObject::const_iterator. It is generally good practice to - use QJsonObject::const_iterator on a non-const QJsonObject as well, unless you - need to change the QJsonObject through the iterator. Const iterators are - slightly faster, and improve code readability. - - The default QJsonObject::iterator constructor creates an uninitialized - iterator. You must initialize it using a QJsonObject function like - QJsonObject::begin(), QJsonObject::end(), or QJsonObject::find() before you can - start iterating. - - 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} -*/ - -/*! \typedef QJsonObject::iterator::difference_type - - \internal -*/ - -/*! \typedef QJsonObject::iterator::iterator_category - - A synonym for \e {std::random_access_iterator_tag} indicating - this iterator is a random-access iterator. - - \note In Qt versions before 5.6, this was set by mistake to - \e {std::bidirectional_iterator_tag}. -*/ - -/*! \typedef QJsonObject::iterator::reference - - \internal -*/ - -/*! \typedef QJsonObject::iterator::value_type - - \internal -*/ - -/*! \typedef QJsonObject::iterator::pointer - - \internal -*/ - -/*! \fn QJsonObject::iterator::iterator() - - Constructs an uninitialized iterator. - - Functions like key(), value(), and operator++() must not be - called on an uninitialized iterator. Use operator=() to assign a - value to it before using it. - - \sa QJsonObject::begin(), QJsonObject::end() -*/ - -/*! \fn QJsonObject::iterator::iterator(QJsonObject *obj, int index) - \internal -*/ - -/*! \fn QString QJsonObject::iterator::key() const - - Returns the current item's key. - - There is no direct way of changing an item's key through an - iterator, although it can be done by calling QJsonObject::erase() - followed by QJsonObject::insert(). - - \sa value() -*/ - -/*! \fn QJsonValueRef QJsonObject::iterator::value() const - - Returns a modifiable reference to the current item's value. - - You can change the value of an item by using value() on - the left side of an assignment. - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the element in the QJsonArray or QJsonObject - from which you got the reference. - - \sa key(), operator*() -*/ - -/*! \fn QJsonValueRef QJsonObject::iterator::operator*() const - - Returns a modifiable reference to the current item's value. - - Same as value(). - - The return value is of type QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the element in the QJsonArray or QJsonObject - from which you got the reference. - - \sa key() -*/ - -/*! \fn QJsonValueRef *QJsonObject::iterator::operator->() const - - Returns a pointer to a modifiable reference to the current item. -*/ - -/*! - \fn bool QJsonObject::iterator::operator==(const iterator &other) const - \fn bool QJsonObject::iterator::operator==(const const_iterator &other) const - - Returns \c true if \a other points to the same item as this - 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 - - Returns \c true if \a other points to a different item than this - iterator; otherwise returns \c false. - - \sa operator==() -*/ - -/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++() - - The prefix ++ operator, \c{++i}, advances the iterator to the - next item in the object and returns an iterator to the new current - item. - - Calling this function on QJsonObject::end() leads to undefined results. - - \sa operator--() -*/ - -/*! \fn QJsonObject::iterator QJsonObject::iterator::operator++(int) - - \overload - - The postfix ++ 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 - current and returns an iterator pointing to the new current item. - - Calling this function on QJsonObject::begin() leads to undefined - results. - - \sa operator++() -*/ - -/*! \fn QJsonObject::iterator QJsonObject::iterator::operator--(int) - - \overload - - The postfix -- 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 - - Returns an iterator to the item at \a j positions forward from - this iterator. If \a j is negative, the iterator goes backward. - - \sa operator-() - -*/ - -/*! \fn QJsonObject::iterator QJsonObject::iterator::operator-(int 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. - - \sa operator+() -*/ - -/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator+=(int j) - - Advances the iterator by \a j items. If \a j is negative, the - iterator goes backward. - - \sa operator-=(), operator+() -*/ - -/*! \fn QJsonObject::iterator &QJsonObject::iterator::operator-=(int j) - - Makes the iterator go back by \a j items. If \a j is negative, - the iterator goes forward. - - \sa operator+=(), operator-() -*/ - -/*! - \class QJsonObject::const_iterator - \inmodule QtCore - \ingroup json - \since 5.0 - \brief The QJsonObject::const_iterator class provides an STL-style const iterator for QJsonObject. - - 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 - good practice to use QJsonObject::const_iterator on a non-const QJsonObject as - well, unless you need to change the QJsonObject through the iterator. - Const iterators are slightly faster and improve code - readability. - - The default QJsonObject::const_iterator constructor creates an - uninitialized iterator. You must initialize it using a QJsonObject - function like QJsonObject::constBegin(), QJsonObject::constEnd(), or - QJsonObject::find() before you can start iterating. - - 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} -*/ - -/*! \typedef QJsonObject::const_iterator::difference_type - - \internal -*/ - -/*! \typedef QJsonObject::const_iterator::iterator_category - - A synonym for \e {std::random_access_iterator_tag} indicating - this iterator is a random-access iterator. - - \note In Qt versions before 5.6, this was set by mistake to - \e {std::bidirectional_iterator_tag}. -*/ - -/*! \typedef QJsonObject::const_iterator::reference - - \internal -*/ - -/*! \typedef QJsonObject::const_iterator::value_type - - \internal -*/ - -/*! \typedef QJsonObject::const_iterator::pointer - - \internal -*/ - -/*! \fn QJsonObject::const_iterator::const_iterator() - - Constructs an uninitialized iterator. - - Functions like key(), value(), and operator++() must not be - called on an uninitialized iterator. Use operator=() to assign a - value to it before using it. - - \sa QJsonObject::constBegin(), QJsonObject::constEnd() -*/ - -/*! \fn QJsonObject::const_iterator::const_iterator(const QJsonObject *obj, int index) - \internal -*/ - -/*! \fn QJsonObject::const_iterator::const_iterator(const iterator &other) - - Constructs a copy of \a other. -*/ - -/*! \fn QString QJsonObject::const_iterator::key() const - - Returns the current item's key. - - \sa value() -*/ - -/*! \fn QJsonValue QJsonObject::const_iterator::value() const - - Returns the current item's value. - - \sa key(), operator*() -*/ - -/*! \fn QJsonValue QJsonObject::const_iterator::operator*() const - - Returns the current item's value. - - Same as value(). - - \sa key() -*/ - -/*! \fn QJsonValue *QJsonObject::const_iterator::operator->() const - - Returns a pointer to the current item. -*/ - -/*! \fn bool QJsonObject::const_iterator::operator==(const const_iterator &other) const - \fn bool QJsonObject::const_iterator::operator==(const iterator &other) const - - Returns \c true if \a other points to the same item as this - 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 - - Returns \c true if \a other points to a different item than this - iterator; otherwise returns \c false. - - \sa operator==() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++() - - The prefix ++ operator, \c{++i}, advances the iterator to the - next item in the object and returns an iterator to the new current - item. - - Calling this function on QJsonObject::end() leads to undefined results. - - \sa operator--() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator++(int) - - \overload - - The postfix ++ 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 - current and returns an iterator pointing to the new current item. - - Calling this function on QJsonObject::begin() leads to undefined - results. - - \sa operator++() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator--(int) - - \overload - - The postfix -- 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 - - Returns an iterator to the item at \a j positions forward from - this iterator. If \a j is negative, the iterator goes backward. - - This operation can be slow for large \a j values. - - \sa operator-() -*/ - -/*! \fn QJsonObject::const_iterator QJsonObject::const_iterator::operator-(int 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. - - This operation can be slow for large \a j values. - - \sa operator+() -*/ - -/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator+=(int j) - - Advances the iterator by \a j items. If \a j is negative, the - iterator goes backward. - - This operation can be slow for large \a j values. - - \sa operator-=(), operator+() -*/ - -/*! \fn QJsonObject::const_iterator &QJsonObject::const_iterator::operator-=(int j) - - Makes the iterator go back by \a j items. If \a j is negative, - the iterator goes forward. - - This operation can be slow for large \a j values. - - \sa operator+=(), operator-() -*/ - - -/*! - \internal - */ -void QJsonObject::detach(uint reserve) -{ - Q_UNUSED(reserve) - Q_ASSERT(!reserve); - detach2(reserve); -} - -bool QJsonObject::detach2(uint reserve) -{ - if (!d) { - if (reserve >= QJsonPrivate::Value::MaxSize) { - qWarning("QJson: Document too large to store in data structure"); - return false; - } - d = new QJsonPrivate::Data(reserve, QJsonValue::Object); - o = static_cast<QJsonPrivate::Object *>(d->header->root()); - d->ref.ref(); - return true; - } - if (reserve == 0 && d->ref.load() == 1) - return true; - - QJsonPrivate::Data *x = d->clone(o, reserve); - if (!x) - return false; - x->ref.ref(); - if (!d->ref.deref()) - delete d; - d = x; - o = static_cast<QJsonPrivate::Object *>(d->header->root()); - return true; -} - -/*! - \internal - */ -void QJsonObject::compact() -{ - if (!d || !d->compactionCounter) - return; - - detach2(); - d->compact(); - o = static_cast<QJsonPrivate::Object *>(d->header->root()); -} - -/*! - \internal - */ -QString QJsonObject::keyAt(int i) const -{ - Q_ASSERT(o && i >= 0 && i < (int)o->length); - - QJsonPrivate::Entry *e = o->entryAt(i); - return e->key(); -} - -/*! - \internal - */ -QJsonValue QJsonObject::valueAt(int i) const -{ - if (!o || i < 0 || i >= (int)o->length) - return QJsonValue(QJsonValue::Undefined); - - QJsonPrivate::Entry *e = o->entryAt(i); - return QJsonValue(d, o, e->value); -} - -/*! - \internal - */ -void QJsonObject::setValueAt(int i, const QJsonValue &val) -{ - Q_ASSERT(o && i >= 0 && i < (int)o->length); - - QJsonPrivate::Entry *e = o->entryAt(i); - insert(e->key(), val); -} - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -QDebug operator<<(QDebug dbg, const QJsonObject &o) -{ - QDebugStateSaver saver(dbg); - if (!o.o) { - dbg << "QJsonObject()"; - return dbg; - } - QByteArray json; - QJsonPrivate::Writer::objectToJson(o.o, json, 0, true); - dbg.nospace() << "QJsonObject(" - << json.constData() // print as utf-8 string without extra quotation marks - << ")"; - return dbg; -} -#endif - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h deleted file mode 100644 index 610bce694c..0000000000 --- a/src/corelib/json/qjsonobject.h +++ /dev/null @@ -1,271 +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$ -** -****************************************************************************/ - -#ifndef QJSONOBJECT_H -#define QJSONOBJECT_H - -#include <QtCore/qjsonvalue.h> -#include <QtCore/qiterator.h> -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include <QtCore/qpair.h> -#include <initializer_list> -#endif - -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 Q_CORE_EXPORT QJsonObject -{ -public: - QJsonObject(); - -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) - QJsonObject(std::initializer_list<QPair<QString, QJsonValue> > args) - { - initialize(); - for (std::initializer_list<QPair<QString, QJsonValue> >::const_iterator i = args.begin(); i != args.end(); ++i) - insert(i->first, i->second); - } -#endif - - ~QJsonObject(); - - QJsonObject(const QJsonObject &other); - QJsonObject &operator =(const QJsonObject &other); - - QJsonObject(QJsonObject &&other) Q_DECL_NOTHROW - : d(other.d), o(other.o) - { - other.d = nullptr; - other.o = nullptr; - } - - QJsonObject &operator =(QJsonObject &&other) Q_DECL_NOTHROW - { - swap(other); - return *this; - } - - void swap(QJsonObject &other) Q_DECL_NOTHROW - { - qSwap(d, other.d); - qSwap(o, other.o); - } - - static QJsonObject fromVariantMap(const QVariantMap &map); - QVariantMap toVariantMap() const; - static QJsonObject fromVariantHash(const QVariantHash &map); - QVariantHash toVariantHash() const; - - QStringList keys() const; - int size() const; - inline int count() const { return size(); } - inline int length() const { return size(); } - bool isEmpty() const; - - QJsonValue value(const QString &key) const; - QJsonValue value(QLatin1String key) const; - QJsonValue operator[] (const QString &key) const; - QJsonValue operator[] (QLatin1String key) const { return value(key); } - QJsonValueRef operator[] (const QString &key); - QJsonValueRef operator[] (QLatin1String key); - - void remove(const QString &key); - QJsonValue take(const QString &key); - bool contains(const QString &key) const; - bool contains(QLatin1String key) const; - - bool operator==(const QJsonObject &other) const; - bool operator!=(const QJsonObject &other) const; - - class const_iterator; - - class iterator - { - friend class const_iterator; - friend class QJsonObject; - QJsonObject *o; - int i; - - public: - typedef std::random_access_iterator_tag iterator_category; - typedef int 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); } -#endif - inline bool operator==(const iterator &other) const { return i == other.i; } - inline 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; } - - 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; } - }; - friend class iterator; - - class const_iterator - { - friend class iterator; - const QJsonObject *o; - int i; - - public: - typedef std::random_access_iterator_tag iterator_category; - typedef int difference_type; - typedef QJsonValue value_type; - typedef QJsonValue reference; - typedef QJsonValuePtr 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(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)); } -#endif - 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 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; } - - inline bool operator==(const iterator &other) const { return i == other.i; } - inline bool operator!=(const iterator &other) const { return i != other.i; } - }; - friend class const_iterator; - - // STL style - inline iterator begin() { detach2(); 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 const_iterator end() const { return const_iterator(this, size()); } - inline const_iterator constEnd() const { return const_iterator(this, size()); } - iterator erase(iterator it); - - // more Qt - typedef iterator Iterator; - typedef const_iterator ConstIterator; - iterator find(const QString &key); - iterator find(QLatin1String key); - const_iterator find(const QString &key) const { return constFind(key); } - const_iterator find(QLatin1String key) const { return constFind(key); } - const_iterator constFind(const QString &key) const; - const_iterator constFind(QLatin1String key) const; - iterator insert(const QString &key, const QJsonValue &value); - - // STL compatibility - typedef QJsonValue mapped_type; - typedef QString key_type; - typedef int size_type; - - inline bool empty() const { return isEmpty(); } - -private: - friend class QJsonPrivate::Data; - friend class QJsonValue; - friend class QJsonDocument; - friend class QJsonValueRef; - - friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &); - - QJsonObject(QJsonPrivate::Data *data, QJsonPrivate::Object *object); - void initialize(); - // ### Qt 6: remove me and merge with detach2 - void detach(uint reserve = 0); - bool detach2(uint reserve = 0); - void compact(); - - QString keyAt(int i) const; - QJsonValue valueAt(int i) const; - void setValueAt(int i, const QJsonValue &val); - - QJsonPrivate::Data *d; - QJsonPrivate::Object *o; -}; - -Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject) - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &); -#endif - -QT_END_NAMESPACE - -#endif // QJSONOBJECT_H diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp deleted file mode 100644 index 39738b90a8..0000000000 --- a/src/corelib/json/qjsonparser.cpp +++ /dev/null @@ -1,1027 +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 QT_BOOTSTRAPPED -#include <qcoreapplication.h> -#endif -#include <qdebug.h> -#include "qjsonparser_p.h" -#include "qjson_p.h" -#include "private/qutfcodec_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() -#else -#define BEGIN if (1) ; else qDebug() -#define END do {} while (0) -#define DEBUG if (1) ; else qDebug() -#endif - -static const int nestingLimit = 1024; - -QT_BEGIN_NAMESPACE - -// 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") -#define JSONERR_MISS_NSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing name separator") -#define JSONERR_UNTERM_AR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated array") -#define JSONERR_MISS_VSEP QT_TRANSLATE_NOOP("QJsonParseError", "missing value separator") -#define JSONERR_ILLEGAL_VAL QT_TRANSLATE_NOOP("QJsonParseError", "illegal value") -#define JSONERR_END_OF_NUM QT_TRANSLATE_NOOP("QJsonParseError", "invalid termination by number") -#define JSONERR_ILLEGAL_NUM QT_TRANSLATE_NOOP("QJsonParseError", "illegal number") -#define JSONERR_STR_ESC_SEQ QT_TRANSLATE_NOOP("QJsonParseError", "invalid escape sequence") -#define JSONERR_STR_UTF8 QT_TRANSLATE_NOOP("QJsonParseError", "invalid UTF8 string") -#define JSONERR_UTERM_STR QT_TRANSLATE_NOOP("QJsonParseError", "unterminated string") -#define JSONERR_MISS_OBJ QT_TRANSLATE_NOOP("QJsonParseError", "object is missing after a comma") -#define JSONERR_DEEP_NEST QT_TRANSLATE_NOOP("QJsonParseError", "too deeply nested document") -#define JSONERR_DOC_LARGE QT_TRANSLATE_NOOP("QJsonParseError", "too large document") -#define JSONERR_GARBAGEEND QT_TRANSLATE_NOOP("QJsonParseError", "garbage at the end of the document") - -/*! - \class QJsonParseError - \inmodule QtCore - \ingroup json - \ingroup shared - \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} -*/ - -/*! - \enum QJsonParseError::ParseError - - This enum describes the type of error that occurred during the parsing of a JSON document. - - \value NoError No error occurred - \value UnterminatedObject An object is not correctly terminated with a closing curly bracket - \value MissingNameSeparator A comma separating different items is missing - \value UnterminatedArray The array is not correctly terminated with a closing square bracket - \value MissingValueSeparator A colon separating keys from values inside objects is missing - \value IllegalValue The value is illegal - \value TerminationByNumber The input stream ended while parsing a number - \value IllegalNumber The number is not well formed - \value IllegalEscapeSequence An illegal escape sequence occurred in the input - \value IllegalUTF8String An illegal UTF8 sequence occurred in the input - \value UnterminatedString A string wasn't terminated with a quote - \value MissingObject An object was expected but couldn't be found - \value DeepNesting The JSON document is too deeply nested for the parser to parse it - \value DocumentTooLarge The JSON document is too large for the parser to parse it - \value GarbageAtEnd The parsed document contains additional garbage characters at the end - -*/ - -/*! - \variable QJsonParseError::error - - Contains the type of the parse error. Is equal to QJsonParseError::NoError if the document - was parsed correctly. - - \sa ParseError, errorString() -*/ - - -/*! - \variable QJsonParseError::offset - - Contains the offset in the input string where the parse error occurred. - - \sa error, errorString() -*/ - -/*! - Returns the human-readable message appropriate to the reported JSON parsing error. - - \sa error - */ -QString QJsonParseError::errorString() const -{ - const char *sz = ""; - switch (error) { - case NoError: - sz = JSONERR_OK; - break; - case UnterminatedObject: - sz = JSONERR_UNTERM_OBJ; - break; - case MissingNameSeparator: - sz = JSONERR_MISS_NSEP; - break; - case UnterminatedArray: - sz = JSONERR_UNTERM_AR; - break; - case MissingValueSeparator: - sz = JSONERR_MISS_VSEP; - break; - case IllegalValue: - sz = JSONERR_ILLEGAL_VAL; - break; - case TerminationByNumber: - sz = JSONERR_END_OF_NUM; - break; - case IllegalNumber: - sz = JSONERR_ILLEGAL_NUM; - break; - case IllegalEscapeSequence: - sz = JSONERR_STR_ESC_SEQ; - break; - case IllegalUTF8String: - sz = JSONERR_STR_UTF8; - break; - case UnterminatedString: - sz = JSONERR_UTERM_STR; - break; - case MissingObject: - sz = JSONERR_MISS_OBJ; - break; - case DeepNesting: - sz = JSONERR_DEEP_NEST; - break; - case DocumentTooLarge: - sz = JSONERR_DOC_LARGE; - break; - case GarbageAtEnd: - sz = JSONERR_GARBAGEEND; - break; - } -#ifndef QT_BOOTSTRAPPED - return QCoreApplication::translate("QJsonParseError", sz); -#else - return QLatin1String(sz); -#endif -} - -using namespace QJsonPrivate; - -Parser::Parser(const char *json, int length) - : head(json), json(json), data(0), dataLength(0), current(0), nestingLevel(0), lastError(QJsonParseError::NoError) -{ - end = json + length; -} - - - -/* - -begin-array = ws %x5B ws ; [ left square bracket - -begin-object = ws %x7B ws ; { left curly bracket - -end-array = ws %x5D ws ; ] right square bracket - -end-object = ws %x7D ws ; } right curly bracket - -name-separator = ws %x3A ws ; : colon - -value-separator = ws %x2C ws ; , comma - -Insignificant whitespace is allowed before or after any of the six -structural characters. - -ws = *( - %x20 / ; Space - %x09 / ; Horizontal tab - %x0A / ; Line feed or New line - %x0D ; Carriage return - ) - -*/ - -enum { - Space = 0x20, - Tab = 0x09, - LineFeed = 0x0a, - Return = 0x0d, - BeginArray = 0x5b, - BeginObject = 0x7b, - EndArray = 0x5d, - EndObject = 0x7d, - NameSeparator = 0x3a, - ValueSeparator = 0x2c, - Quote = 0x22 -}; - -void Parser::eatBOM() -{ - // eat UTF-8 byte order mark - uchar utf8bom[3] = { 0xef, 0xbb, 0xbf }; - if (end - json > 3 && - (uchar)json[0] == utf8bom[0] && - (uchar)json[1] == utf8bom[1] && - (uchar)json[2] == utf8bom[2]) - json += 3; -} - -bool Parser::eatSpace() -{ - while (json < end) { - if (*json > Space) - break; - if (*json != Space && - *json != Tab && - *json != LineFeed && - *json != Return) - break; - ++json; - } - return (json < end); -} - -char Parser::nextToken() -{ - if (!eatSpace()) - return 0; - char token = *json++; - switch (token) { - case BeginArray: - case BeginObject: - case NameSeparator: - case ValueSeparator: - case EndArray: - case EndObject: - case Quote: - break; - default: - token = 0; - break; - } - return token; -} - -/* - JSON-text = object / array -*/ -QJsonDocument Parser::parse(QJsonParseError *error) -{ -#ifdef PARSER_DEBUG - indent = 0; - qDebug(">>>>> parser begin"); -#endif - // allocate some space - dataLength = qMax(end - json, (ptrdiff_t) 256); - data = (char *)malloc(dataLength); - - // fill in Header data - QJsonPrivate::Header *h = (QJsonPrivate::Header *)data; - h->tag = QJsonDocument::BinaryFormatTag; - h->version = 1u; - - current = sizeof(QJsonPrivate::Header); - - eatBOM(); - char token = nextToken(); - - DEBUG << hex << (uint)token; - if (token == BeginArray) { - if (!parseArray()) - goto error; - } else if (token == BeginObject) { - if (!parseObject()) - goto error; - } else { - lastError = QJsonParseError::IllegalValue; - goto error; - } - - eatSpace(); - if (json < end) { - lastError = QJsonParseError::GarbageAtEnd; - goto error; - } - - END; - { - if (error) { - error->offset = 0; - error->error = QJsonParseError::NoError; - } - QJsonPrivate::Data *d = new QJsonPrivate::Data(data, current); - return QJsonDocument(d); - } - -error: -#ifdef PARSER_DEBUG - qDebug(">>>>> parser error"); -#endif - if (error) { - error->offset = json - head; - error->error = lastError; - } - free(data); - return QJsonDocument(); -} - - -void Parser::ParsedObject::insert(uint offset) { - const QJsonPrivate::Entry *newEntry = reinterpret_cast<const QJsonPrivate::Entry *>(parser->data + objectPosition + offset); - int min = 0; - int n = offsets.size(); - while (n > 0) { - int half = n >> 1; - int middle = min + half; - if (*entryAt(middle) >= *newEntry) { - n = half; - } else { - min = middle + 1; - n -= half + 1; - } - } - if (min < offsets.size() && *entryAt(min) == *newEntry) { - offsets[min] = offset; - } else { - offsets.insert(min, offset); - } -} - -/* - object = begin-object [ member *( value-separator member ) ] - end-object -*/ - -bool Parser::parseObject() -{ - if (++nestingLevel > nestingLimit) { - lastError = QJsonParseError::DeepNesting; - return false; - } - - int objectOffset = reserveSpace(sizeof(QJsonPrivate::Object)); - if (objectOffset < 0) - return false; - BEGIN << "parseObject pos=" << objectOffset << current << json; - - ParsedObject parsedObject(this, objectOffset); - - char token = nextToken(); - while (token == Quote) { - int off = current - objectOffset; - if (!parseMember(objectOffset)) - return false; - parsedObject.insert(off); - token = nextToken(); - if (token != ValueSeparator) - break; - token = nextToken(); - if (token == EndObject) { - lastError = QJsonParseError::MissingObject; - return false; - } - } - - DEBUG << "end token=" << token; - if (token != EndObject) { - lastError = QJsonParseError::UnterminatedObject; - return false; - } - - DEBUG << "numEntries" << parsedObject.offsets.size(); - int table = objectOffset; - // finalize the object - if (parsedObject.offsets.size()) { - int tableSize = parsedObject.offsets.size()*sizeof(uint); - table = reserveSpace(tableSize); - if (table < 0) - return false; - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - memcpy(data + table, parsedObject.offsets.constData(), tableSize); -#else - offset *o = (offset *)(data + table); - for (int i = 0; i < parsedObject.offsets.size(); ++i) - o[i] = parsedObject.offsets[i]; - -#endif - } - - QJsonPrivate::Object *o = (QJsonPrivate::Object *)(data + objectOffset); - o->tableOffset = table - objectOffset; - o->size = current - objectOffset; - o->is_object = true; - o->length = parsedObject.offsets.size(); - - DEBUG << "current=" << current; - END; - - --nestingLevel; - return true; -} - -/* - member = string name-separator value -*/ -bool Parser::parseMember(int baseOffset) -{ - int entryOffset = reserveSpace(sizeof(QJsonPrivate::Entry)); - if (entryOffset < 0) - return false; - BEGIN << "parseMember pos=" << entryOffset; - - bool latin1; - if (!parseString(&latin1)) - return false; - char token = nextToken(); - if (token != NameSeparator) { - lastError = QJsonParseError::MissingNameSeparator; - return false; - } - if (!eatSpace()) { - lastError = QJsonParseError::UnterminatedObject; - return false; - } - QJsonPrivate::Value val; - if (!parseValue(&val, baseOffset)) - return false; - - // finalize the entry - QJsonPrivate::Entry *e = (QJsonPrivate::Entry *)(data + entryOffset); - e->value = val; - e->value.latinKey = latin1; - - END; - return true; -} - -namespace { - struct ValueArray { - static const int prealloc = 128; - ValueArray() : data(stackValues), alloc(prealloc), size(0) {} - ~ValueArray() { if (data != stackValues) free(data); } - - inline bool grow() { - alloc *= 2; - if (data == stackValues) { - QJsonPrivate::Value *newValues = static_cast<QJsonPrivate::Value *>(malloc(alloc*sizeof(QJsonPrivate::Value))); - if (!newValues) - return false; - memcpy(newValues, data, size*sizeof(QJsonPrivate::Value)); - data = newValues; - } else { - void *newValues = realloc(data, alloc * sizeof(QJsonPrivate::Value)); - if (!newValues) - return false; - data = static_cast<QJsonPrivate::Value *>(newValues); - } - return true; - } - bool append(const QJsonPrivate::Value &v) { - if (alloc == size && !grow()) - return false; - data[size] = v; - ++size; - return true; - } - - QJsonPrivate::Value stackValues[prealloc]; - QJsonPrivate::Value *data; - int alloc; - int size; - }; -} - -/* - array = begin-array [ value *( value-separator value ) ] end-array -*/ -bool Parser::parseArray() -{ - BEGIN << "parseArray"; - - if (++nestingLevel > nestingLimit) { - lastError = QJsonParseError::DeepNesting; - return false; - } - - int arrayOffset = reserveSpace(sizeof(QJsonPrivate::Array)); - if (arrayOffset < 0) - return false; - - ValueArray values; - - if (!eatSpace()) { - lastError = QJsonParseError::UnterminatedArray; - return false; - } - if (*json == EndArray) { - nextToken(); - } else { - while (1) { - if (!eatSpace()) { - lastError = QJsonParseError::UnterminatedArray; - return false; - } - QJsonPrivate::Value val; - if (!parseValue(&val, arrayOffset)) - return false; - if (!values.append(val)) { - lastError = QJsonParseError::DocumentTooLarge; - return false; - } - char token = nextToken(); - if (token == EndArray) - break; - else if (token != ValueSeparator) { - if (!eatSpace()) - lastError = QJsonParseError::UnterminatedArray; - else - lastError = QJsonParseError::MissingValueSeparator; - return false; - } - } - } - - DEBUG << "size =" << values.size; - int table = arrayOffset; - // finalize the object - if (values.size) { - int tableSize = values.size*sizeof(QJsonPrivate::Value); - table = reserveSpace(tableSize); - if (table < 0) - return false; - memcpy(data + table, values.data, tableSize); - } - - QJsonPrivate::Array *a = (QJsonPrivate::Array *)(data + arrayOffset); - a->tableOffset = table - arrayOffset; - a->size = current - arrayOffset; - a->is_object = false; - a->length = values.size; - - DEBUG << "current=" << current; - END; - - --nestingLevel; - return true; -} - -/* -value = false / null / true / object / array / number / string - -*/ - -bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset) -{ - BEGIN << "parse Value" << json; - val->_dummy = 0; - - switch (*json++) { - case 'n': - if (end - json < 4) { - lastError = QJsonParseError::IllegalValue; - return false; - } - if (*json++ == 'u' && - *json++ == 'l' && - *json++ == 'l') { - val->type = QJsonValue::Null; - DEBUG << "value: null"; - END; - return true; - } - lastError = QJsonParseError::IllegalValue; - return false; - case 't': - if (end - json < 4) { - lastError = QJsonParseError::IllegalValue; - return false; - } - if (*json++ == 'r' && - *json++ == 'u' && - *json++ == 'e') { - val->type = QJsonValue::Bool; - val->value = true; - DEBUG << "value: true"; - END; - return true; - } - lastError = QJsonParseError::IllegalValue; - return false; - case 'f': - if (end - json < 5) { - lastError = QJsonParseError::IllegalValue; - return false; - } - if (*json++ == 'a' && - *json++ == 'l' && - *json++ == 's' && - *json++ == 'e') { - val->type = QJsonValue::Bool; - val->value = false; - DEBUG << "value: false"; - END; - return true; - } - lastError = QJsonParseError::IllegalValue; - return false; - case Quote: { - val->type = QJsonValue::String; - if (current - baseOffset >= Value::MaxSize) { - lastError = QJsonParseError::DocumentTooLarge; - return false; - } - val->value = current - baseOffset; - bool latin1; - if (!parseString(&latin1)) - return false; - val->latinOrIntValue = latin1; - DEBUG << "value: string"; - END; - return true; - } - case BeginArray: - val->type = QJsonValue::Array; - if (current - baseOffset >= Value::MaxSize) { - lastError = QJsonParseError::DocumentTooLarge; - return false; - } - val->value = current - baseOffset; - if (!parseArray()) - return false; - DEBUG << "value: array"; - END; - return true; - case BeginObject: - val->type = QJsonValue::Object; - if (current - baseOffset >= Value::MaxSize) { - lastError = QJsonParseError::DocumentTooLarge; - return false; - } - val->value = current - baseOffset; - if (!parseObject()) - return false; - DEBUG << "value: object"; - END; - return true; - case ValueSeparator: - // Essentially missing value, but after a colon, not after a comma - // like the other MissingObject errors. - lastError = QJsonParseError::IllegalValue; - return false; - case EndObject: - case EndArray: - lastError = QJsonParseError::MissingObject; - return false; - default: - --json; - if (!parseNumber(val, baseOffset)) - return false; - DEBUG << "value: number"; - END; - } - - return true; -} - - - - - -/* - number = [ minus ] int [ frac ] [ exp ] - decimal-point = %x2E ; . - digit1-9 = %x31-39 ; 1-9 - e = %x65 / %x45 ; e E - exp = e [ minus / plus ] 1*DIGIT - frac = decimal-point 1*DIGIT - int = zero / ( digit1-9 *DIGIT ) - minus = %x2D ; - - plus = %x2B ; + - zero = %x30 ; 0 - -*/ - -bool Parser::parseNumber(QJsonPrivate::Value *val, int baseOffset) -{ - BEGIN << "parseNumber" << json; - val->type = QJsonValue::Double; - - const char *start = json; - bool isInt = true; - - // minus - if (json < end && *json == '-') - ++json; - - // int = zero / ( digit1-9 *DIGIT ) - if (json < end && *json == '0') { - ++json; - } else { - while (json < end && *json >= '0' && *json <= '9') - ++json; - } - - // frac = decimal-point 1*DIGIT - if (json < end && *json == '.') { - isInt = false; - ++json; - while (json < end && *json >= '0' && *json <= '9') - ++json; - } - - // exp = e [ minus / plus ] 1*DIGIT - if (json < end && (*json == 'e' || *json == 'E')) { - isInt = false; - ++json; - if (json < end && (*json == '-' || *json == '+')) - ++json; - while (json < end && *json >= '0' && *json <= '9') - ++json; - } - - if (json >= end) { - lastError = QJsonParseError::TerminationByNumber; - return false; - } - - QByteArray number(start, json - start); - DEBUG << "numberstring" << number; - - if (isInt) { - bool ok; - int n = number.toInt(&ok); - if (ok && n < (1<<25) && n > -(1<<25)) { - val->int_value = n; - val->latinOrIntValue = true; - END; - return true; - } - } - - bool ok; - union { - quint64 ui; - double d; - }; - d = number.toDouble(&ok); - - if (!ok) { - lastError = QJsonParseError::IllegalNumber; - return false; - } - - int pos = reserveSpace(sizeof(double)); - if (pos < 0) - return false; - qToLittleEndian(ui, data + pos); - if (current - baseOffset >= Value::MaxSize) { - lastError = QJsonParseError::DocumentTooLarge; - return false; - } - val->value = pos - baseOffset; - val->latinOrIntValue = false; - - END; - return true; -} - -/* - - string = quotation-mark *char quotation-mark - - char = unescaped / - escape ( - %x22 / ; " quotation mark U+0022 - %x5C / ; \ reverse solidus U+005C - %x2F / ; / solidus U+002F - %x62 / ; b backspace U+0008 - %x66 / ; f form feed U+000C - %x6E / ; n line feed U+000A - %x72 / ; r carriage return U+000D - %x74 / ; t tab U+0009 - %x75 4HEXDIG ) ; uXXXX U+XXXX - - escape = %x5C ; \ - - quotation-mark = %x22 ; " - - unescaped = %x20-21 / %x23-5B / %x5D-10FFFF - */ -static inline bool addHexDigit(char digit, uint *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; -} - -static inline bool scanEscapeSequence(const char *&json, const char *end, uint *ch) -{ - ++json; - if (json >= end) - return false; - - DEBUG << "scan escape" << (char)*json; - uint escaped = *json++; - switch (escaped) { - case '"': - *ch = '"'; break; - case '\\': - *ch = '\\'; break; - case '/': - *ch = '/'; break; - case 'b': - *ch = 0x8; break; - case 'f': - *ch = 0xc; break; - case 'n': - *ch = 0xa; break; - case 'r': - *ch = 0xd; break; - case 't': - *ch = 0x9; break; - case 'u': { - *ch = 0; - if (json > end - 4) - return false; - for (int i = 0; i < 4; ++i) { - if (!addHexDigit(*json, ch)) - return false; - ++json; - } - return true; - } - default: - // this is not as strict as one could be, but allows for more Json files - // to be parsed correctly. - *ch = escaped; - return true; - } - return true; -} - -static inline bool scanUtf8Char(const char *&json, const char *end, uint *result) -{ - const uchar *&src = reinterpret_cast<const uchar *&>(json); - const uchar *uend = reinterpret_cast<const uchar *>(end); - uchar b = *src++; - int res = QUtf8Functions::fromUtf8<QUtf8BaseTraits>(b, result, src, uend); - if (res < 0) { - // decoding error, backtrack the character we read above - --json; - return false; - } - - return true; -} - -bool Parser::parseString(bool *latin1) -{ - *latin1 = true; - - const char *start = json; - int outStart = current; - - // try to write out a latin1 string - - int stringPos = reserveSpace(2); - if (stringPos < 0) - return false; - - BEGIN << "parse string stringPos=" << stringPos << json; - while (json < end) { - uint ch = 0; - if (*json == '"') - break; - else if (*json == '\\') { - if (!scanEscapeSequence(json, end, &ch)) { - lastError = QJsonParseError::IllegalEscapeSequence; - return false; - } - } else { - if (!scanUtf8Char(json, end, &ch)) { - lastError = QJsonParseError::IllegalUTF8String; - return false; - } - } - // bail out if the string is not pure latin1 or too long to hold as a latin1string (which has only 16 bit for the length) - if (ch > 0xff || json - start >= 0x8000) { - *latin1 = false; - break; - } - int pos = reserveSpace(1); - if (pos < 0) - return false; - DEBUG << " " << ch << (char)ch; - data[pos] = (uchar)ch; - } - ++json; - DEBUG << "end of string"; - if (json >= end) { - lastError = QJsonParseError::UnterminatedString; - return false; - } - - // no unicode string, we are done - if (*latin1) { - // write string length - *(QJsonPrivate::qle_ushort *)(data + stringPos) = ushort(current - outStart - sizeof(ushort)); - int pos = reserveSpace((4 - current) & 3); - if (pos < 0) - return false; - while (pos & 3) - data[pos++] = 0; - END; - return true; - } - - *latin1 = false; - DEBUG << "not latin"; - - json = start; - current = outStart + sizeof(int); - - while (json < end) { - uint ch = 0; - if (*json == '"') - break; - else if (*json == '\\') { - if (!scanEscapeSequence(json, end, &ch)) { - lastError = QJsonParseError::IllegalEscapeSequence; - return false; - } - } else { - if (!scanUtf8Char(json, end, &ch)) { - lastError = QJsonParseError::IllegalUTF8String; - return false; - } - } - if (QChar::requiresSurrogates(ch)) { - int pos = reserveSpace(4); - if (pos < 0) - return false; - *(QJsonPrivate::qle_ushort *)(data + pos) = QChar::highSurrogate(ch); - *(QJsonPrivate::qle_ushort *)(data + pos + 2) = QChar::lowSurrogate(ch); - } else { - int pos = reserveSpace(2); - if (pos < 0) - return false; - *(QJsonPrivate::qle_ushort *)(data + pos) = (ushort)ch; - } - } - ++json; - - if (json >= end) { - lastError = QJsonParseError::UnterminatedString; - return false; - } - - // write string length - *(QJsonPrivate::qle_int *)(data + stringPos) = (current - outStart - sizeof(int))/2; - int pos = reserveSpace((4 - current) & 3); - if (pos < 0) - return false; - while (pos & 3) - data[pos++] = 0; - END; - return true; -} - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjsonparser_p.h b/src/corelib/json/qjsonparser_p.h deleted file mode 100644 index 379256847f..0000000000 --- a/src/corelib/json/qjsonparser_p.h +++ /dev/null @@ -1,128 +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$ -** -****************************************************************************/ - -#ifndef QJSONPARSER_P_H -#define QJSONPARSER_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/private/qglobal_p.h> -#include <qjsondocument.h> -#include <qvarlengtharray.h> - -QT_BEGIN_NAMESPACE - -namespace QJsonPrivate { - -class Parser -{ -public: - Parser(const char *json, int length); - - QJsonDocument parse(QJsonParseError *error); - - class ParsedObject - { - public: - ParsedObject(Parser *p, int pos) : parser(p), objectPosition(pos) { - offsets.reserve(64); - } - void insert(uint offset); - - Parser *parser; - int objectPosition; - QVector<uint> offsets; - - inline QJsonPrivate::Entry *entryAt(int i) const { - return reinterpret_cast<QJsonPrivate::Entry *>(parser->data + objectPosition + offsets[i]); - } - }; - - -private: - inline void eatBOM(); - inline bool eatSpace(); - inline char nextToken(); - - bool parseObject(); - bool parseArray(); - bool parseMember(int baseOffset); - bool parseString(bool *latin1); - bool parseValue(QJsonPrivate::Value *val, int baseOffset); - bool parseNumber(QJsonPrivate::Value *val, int baseOffset); - const char *head; - const char *json; - const char *end; - - char *data; - int dataLength; - int current; - int nestingLevel; - QJsonParseError::ParseError lastError; - - inline int reserveSpace(int space) { - if (current + space >= dataLength) { - dataLength = 2*dataLength + space; - char *newData = (char *)realloc(data, dataLength); - if (!newData) { - lastError = QJsonParseError::DocumentTooLarge; - return -1; - } - data = newData; - } - int pos = current; - current += space; - return pos; - } -}; - -} - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp deleted file mode 100644 index 33707b6ec3..0000000000 --- a/src/corelib/json/qjsonvalue.cpp +++ /dev/null @@ -1,863 +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 <qjsonobject.h> -#include <qjsonvalue.h> -#include <qjsonarray.h> -#include <qvariant.h> -#include <qstringlist.h> -#include <qdebug.h> - -#include "qjson_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QJsonValue - \inmodule QtCore - \ingroup json - \ingroup shared - \reentrant - \since 5.0 - - \brief The QJsonValue class encapsulates a value in JSON. - - 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: - - \list - \li bool QJsonValue::Bool - \li double QJsonValue::Double - \li string QJsonValue::String - \li array QJsonValue::Array - \li object QJsonValue::Object - \li null QJsonValue::Null - \endlist - - A value can represent any of the above data types. In addition, QJsonValue has one special - flag to represent undefined values. This can be queried with isUndefined(). - - The type of the value can be queried with type() or accessors like isBool(), isString(), and so on. - Likewise, the value can be converted to the type stored in it using the toBool(), toString() and so on. - - Values are strictly typed internally and contrary to QVariant will not attempt to do any implicit type - conversions. This implies that converting to a type that is not stored in the value will return a default - constructed return value. - - \section1 QJsonValueRef - - QJsonValueRef is a helper class for QJsonArray and QJsonObject. - When you get an object of type QJsonValueRef, you can - use it as if it were a reference to a QJsonValue. If you assign to it, - the assignment will apply to the element in the QJsonArray or QJsonObject - from which you got the reference. - - The following methods return QJsonValueRef: - \list - \li \l {QJsonArray}::operator[](int i) - \li \l {QJsonObject}::operator[](const QString & key) const - \endlist - - \sa {JSON Support in Qt}, {JSON Save Game Example} -*/ - -/*! - Creates a QJsonValue of type \a type. - - The default is to create a Null value. - */ -QJsonValue::QJsonValue(Type type) - : ui(0), d(0), t(type) -{ -} - -/*! - \internal - */ -QJsonValue::QJsonValue(QJsonPrivate::Data *data, QJsonPrivate::Base *base, const QJsonPrivate::Value &v) - : d(0) -{ - t = (Type)(uint)v.type; - switch (t) { - case Undefined: - case Null: - dbl = 0; - break; - case Bool: - b = v.toBoolean(); - break; - case Double: - dbl = v.toDouble(base); - break; - case String: { - QString s = v.toString(base); - stringData = s.data_ptr(); - stringData->ref.ref(); - break; - } - case Array: - case Object: - d = data; - this->base = v.base(base); - break; - } - if (d) - d->ref.ref(); -} - -/*! - Creates a value of type Bool, with value \a b. - */ -QJsonValue::QJsonValue(bool b) - : d(0), t(Bool) -{ - this->b = b; -} - -/*! - Creates a value of type Double, with value \a n. - */ -QJsonValue::QJsonValue(double n) - : d(0), t(Double) -{ - this->dbl = n; -} - -/*! - \overload - Creates a value of type Double, with value \a n. - */ -QJsonValue::QJsonValue(int n) - : d(0), t(Double) -{ - this->dbl = n; -} - -/*! - \overload - Creates a value of type Double, with value \a n. - NOTE: the integer limits for IEEE 754 double precision data is 2^53 (-9007199254740992 to +9007199254740992). - If you pass in values outside this range expect a loss of precision to occur. - */ -QJsonValue::QJsonValue(qint64 n) - : d(0), t(Double) -{ - this->dbl = double(n); -} - -/*! - Creates a value of type String, with value \a s. - */ -QJsonValue::QJsonValue(const QString &s) - : d(0), t(String) -{ - stringDataFromQStringHelper(s); -} - -/*! - \fn QJsonValue::QJsonValue(const char *s) - - Creates a value of type String with value \a s, assuming - UTF-8 encoding of the input. - - You can disable this constructor by defining \c - QT_NO_CAST_FROM_ASCII when you compile your applications. - - \since 5.3 - */ - -void QJsonValue::stringDataFromQStringHelper(const QString &string) -{ - stringData = *(QStringData **)(&string); - stringData->ref.ref(); -} - -/*! - Creates a value of type String, with value \a s. - */ -QJsonValue::QJsonValue(QLatin1String s) - : d(0), t(String) -{ - // ### FIXME: Avoid creating the temp QString below - QString str(s); - stringDataFromQStringHelper(str); -} - -/*! - Creates a value of type Array, with value \a a. - */ -QJsonValue::QJsonValue(const QJsonArray &a) - : d(a.d), t(Array) -{ - base = a.a; - if (d) - d->ref.ref(); -} - -/*! - Creates a value of type Object, with value \a o. - */ -QJsonValue::QJsonValue(const QJsonObject &o) - : d(o.d), t(Object) -{ - base = o.o; - if (d) - d->ref.ref(); -} - - -/*! - Destroys the value. - */ -QJsonValue::~QJsonValue() -{ - if (t == String && stringData && !stringData->ref.deref()) - free(stringData); - - if (d && !d->ref.deref()) - delete d; -} - -/*! - Creates a copy of \a other. - */ -QJsonValue::QJsonValue(const QJsonValue &other) -{ - t = other.t; - d = other.d; - ui = other.ui; - if (d) - d->ref.ref(); - - if (t == String && stringData) - stringData->ref.ref(); -} - -/*! - Assigns the value stored in \a other to this object. - */ -QJsonValue &QJsonValue::operator =(const QJsonValue &other) -{ - QJsonValue copy(other); - swap(copy); - return *this; -} - -/*! - \fn QJsonValue::QJsonValue(QJsonValue &&other) - \since 5.10 - - Move-constructs a QJsonValue from \a other. -*/ - -/*! - \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other) - \since 5.10 - - Move-assigns \a other to this value. -*/ - -/*! - \fn void QJsonValue::swap(QJsonValue &other) - \since 5.10 - - Swaps the value \a other with this. This operation is very fast and never fails. -*/ - -/*! - \fn bool QJsonValue::isNull() const - - Returns \c true if the value is null. -*/ - -/*! - \fn bool QJsonValue::isBool() const - - Returns \c true if the value contains a boolean. - - \sa toBool() - */ - -/*! - \fn bool QJsonValue::isDouble() const - - Returns \c true if the value contains a double. - - \sa toDouble() - */ - -/*! - \fn bool QJsonValue::isString() const - - Returns \c true if the value contains a string. - - \sa toString() - */ - -/*! - \fn bool QJsonValue::isArray() const - - Returns \c true if the value contains an array. - - \sa toArray() - */ - -/*! - \fn bool QJsonValue::isObject() const - - Returns \c true if the value contains an object. - - \sa toObject() - */ - -/*! - \fn bool QJsonValue::isUndefined() const - - Returns \c true if the value is undefined. This can happen in certain - error cases as e.g. accessing a non existing key in a QJsonObject. - */ - - -/*! - Converts \a variant to a QJsonValue and returns it. - - The conversion will convert QVariant types as follows: - - \table - \header - \li Source type - \li Destination type - \row - \li - \list - \li QMetaType::Nullptr - \endlist - \li QJsonValue::Null - \row - \li - \list - \li QMetaType::Bool - \endlist - \li QJsonValue::Bool - \row - \li - \list - \li QMetaType::Int - \li QMetaType::UInt - \li QMetaType::LongLong - \li QMetaType::ULongLong - \li QMetaType::Float - \li QMetaType::Double - \endlist - \li QJsonValue::Double - \row - \li - \list - \li QMetaType::QString - \endlist - \li QJsonValue::String - \row - \li - \list - \li QMetaType::QStringList - \li QMetaType::QVariantList - \endlist - \li QJsonValue::Array - \row - \li - \list - \li QMetaType::QVariantMap - \li QMetaType::QVariantHash - \endlist - \li QJsonValue::Object - \endtable - - For all other QVariant types a conversion to a QString will be attempted. If the returned string - is empty, a Null QJsonValue will be stored, otherwise a String value using the returned QString. - - \sa toVariant() - */ -QJsonValue QJsonValue::fromVariant(const QVariant &variant) -{ - switch (variant.userType()) { - case QMetaType::Nullptr: - return QJsonValue(Null); - case QVariant::Bool: - return QJsonValue(variant.toBool()); - case QVariant::Int: - case QMetaType::Float: - case QVariant::Double: - case QVariant::LongLong: - case QVariant::ULongLong: - case QVariant::UInt: - return QJsonValue(variant.toDouble()); - case QVariant::String: - return QJsonValue(variant.toString()); - case QVariant::StringList: - return QJsonValue(QJsonArray::fromStringList(variant.toStringList())); - case QVariant::List: - return QJsonValue(QJsonArray::fromVariantList(variant.toList())); - case QVariant::Map: - return QJsonValue(QJsonObject::fromVariantMap(variant.toMap())); - case QVariant::Hash: - return QJsonValue(QJsonObject::fromVariantHash(variant.toHash())); -#ifndef QT_BOOTSTRAPPED - case QMetaType::QJsonValue: - return variant.toJsonValue(); - case QMetaType::QJsonObject: - return variant.toJsonObject(); - case QMetaType::QJsonArray: - return variant.toJsonArray(); - case QMetaType::QJsonDocument: { - QJsonDocument doc = variant.toJsonDocument(); - return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); - } -#endif - default: - break; - } - QString string = variant.toString(); - if (string.isEmpty()) - return QJsonValue(); - return QJsonValue(string); -} - -/*! - Converts the value to a \l {QVariant::}{QVariant()}. - - The QJsonValue types will be converted as follows: - - \value Null QMetaType::Nullptr - \value Bool QMetaType::Bool - \value Double QMetaType::Double - \value String QString - \value Array QVariantList - \value Object QVariantMap - \value Undefined \l {QVariant::}{QVariant()} - - \sa fromVariant() - */ -QVariant QJsonValue::toVariant() const -{ - switch (t) { - case Bool: - return b; - case Double: - return dbl; - case String: - return toString(); - case Array: - return d ? - QJsonArray(d, static_cast<QJsonPrivate::Array *>(base)).toVariantList() : - QVariantList(); - case Object: - return d ? - QJsonObject(d, static_cast<QJsonPrivate::Object *>(base)).toVariantMap() : - QVariantMap(); - case Null: - return QVariant::fromValue(nullptr); - case Undefined: - break; - } - return QVariant(); -} - -/*! - \enum QJsonValue::Type - - This enum describes the type of the JSON value. - - \value Null A Null value - \value Bool A boolean value. Use toBool() to convert to a bool. - \value Double A double. Use toDouble() to convert to a double. - \value String A string. Use toString() to convert to a QString. - \value Array An array. Use toArray() to convert to a QJsonArray. - \value Object An object. Use toObject() to convert to a QJsonObject. - \value Undefined The value is undefined. This is usually returned as an - error condition, when trying to read an out of bounds value - in an array or a non existent key in an object. -*/ - -/*! - Returns the type of the value. - - \sa QJsonValue::Type - */ -QJsonValue::Type QJsonValue::type() const -{ - return t; -} - -/*! - Converts the value to a bool and returns it. - - If type() is not bool, the \a defaultValue will be returned. - */ -bool QJsonValue::toBool(bool defaultValue) const -{ - if (t != Bool) - return defaultValue; - return b; -} - -/*! - Converts the value to an int and returns it. - - If type() is not Double or the value is not a whole number, - the \a defaultValue will be returned. - */ -int QJsonValue::toInt(int defaultValue) const -{ - if (t == Double && int(dbl) == dbl) - return int(dbl); - return defaultValue; -} - -/*! - Converts the value to a double and returns it. - - If type() is not Double, the \a defaultValue will be returned. - */ -double QJsonValue::toDouble(double defaultValue) const -{ - if (t != Double) - return defaultValue; - return dbl; -} - -/*! - Converts the value to a QString and returns it. - - If type() is not String, the \a defaultValue will be returned. - */ -QString QJsonValue::toString(const QString &defaultValue) const -{ - if (t != String) - return defaultValue; - stringData->ref.ref(); // the constructor below doesn't add a ref. - QStringDataPtr holder = { stringData }; - return QString(holder); -} - -/*! - Converts the value to a QString and returns it. - - If type() is not String, a null QString will be returned. - - \sa QString::isNull() - */ -QString QJsonValue::toString() const -{ - if (t != String) - return QString(); - stringData->ref.ref(); // the constructor below doesn't add a ref. - QStringDataPtr holder = { stringData }; - return QString(holder); -} - -/*! - Converts the value to an array and returns it. - - If type() is not Array, the \a defaultValue will be returned. - */ -QJsonArray QJsonValue::toArray(const QJsonArray &defaultValue) const -{ - if (!d || t != Array) - return defaultValue; - - return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base)); -} - -/*! - \overload - - Converts the value to an array and returns it. - - If type() is not Array, a \l{QJsonArray::}{QJsonArray()} will be returned. - */ -QJsonArray QJsonValue::toArray() const -{ - return toArray(QJsonArray()); -} - -/*! - Converts the value to an object and returns it. - - If type() is not Object, the \a defaultValue will be returned. - */ -QJsonObject QJsonValue::toObject(const QJsonObject &defaultValue) const -{ - if (!d || t != Object) - return defaultValue; - - return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base)); -} - -/*! - \overload - - Converts the value to an object and returns it. - - If type() is not Object, the \l {QJsonObject::}{QJsonObject()} will be returned. -*/ -QJsonObject QJsonValue::toObject() const -{ - return toObject(QJsonObject()); -} - -/*! - Returns a QJsonValue representing the value for the key \a key. - - Equivalent to calling toObject().value(key). - - The returned QJsonValue is QJsonValue::Undefined if the key does not exist, - or if isObject() is false. - - \since 5.10 - - \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject - */ -const QJsonValue QJsonValue::operator[](const QString &key) const -{ - if (!isObject()) - return QJsonValue(QJsonValue::Undefined); - - return toObject().value(key); -} - -/*! - \overload - \since 5.10 -*/ -const QJsonValue QJsonValue::operator[](QLatin1String key) const -{ - if (!isObject()) - return QJsonValue(QJsonValue::Undefined); - - return toObject().value(key); -} - -/*! - Returns a QJsonValue representing the value for index \a i. - - Equivalent to calling toArray().at(i). - - The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds, - or if isArray() is false. - - \since 5.10 - - \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray - */ -const QJsonValue QJsonValue::operator[](int i) const -{ - if (!isArray()) - return QJsonValue(QJsonValue::Undefined); - - return toArray().at(i); -} - -/*! - Returns \c true if the value is equal to \a other. - */ -bool QJsonValue::operator==(const QJsonValue &other) const -{ - if (t != other.t) - return false; - - switch (t) { - case Undefined: - case Null: - break; - case Bool: - return b == other.b; - case Double: - return dbl == other.dbl; - case String: - return toString() == other.toString(); - case Array: - if (base == other.base) - return true; - if (!base) - return !other.base->length; - if (!other.base) - return !base->length; - return QJsonArray(d, static_cast<QJsonPrivate::Array *>(base)) - == QJsonArray(other.d, static_cast<QJsonPrivate::Array *>(other.base)); - case Object: - if (base == other.base) - return true; - if (!base) - return !other.base->length; - if (!other.base) - return !base->length; - return QJsonObject(d, static_cast<QJsonPrivate::Object *>(base)) - == QJsonObject(other.d, static_cast<QJsonPrivate::Object *>(other.base)); - } - return true; -} - -/*! - 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() -{ - if (!d) - return; - - QJsonPrivate::Data *x = d->clone(base); - x->ref.ref(); - if (!d->ref.deref()) - delete d; - d = x; - base = static_cast<QJsonPrivate::Object *>(d->header->root()); -} - - -/*! - \class QJsonValueRef - \inmodule QtCore - \reentrant - \brief The QJsonValueRef class is a helper class for QJsonValue. - - \internal - - \ingroup json - - When you get an object of type QJsonValueRef, if you can assign to it, - the assignment will apply to the character in the string from - which you got the reference. That is its whole purpose in life. - - You can use it exactly in the same way as a reference to a QJsonValue. - - The QJsonValueRef becomes invalid once modifications are made to the - string: if you want to keep the character, copy it into a QJsonValue. - - Most of the QJsonValue member functions also exist in QJsonValueRef. - However, they are not explicitly documented here. -*/ - - -QJsonValueRef &QJsonValueRef::operator =(const QJsonValue &val) -{ - if (is_object) - o->setValueAt(index, val); - else - a->replace(index, val); - - return *this; -} - -QJsonValueRef &QJsonValueRef::operator =(const QJsonValueRef &ref) -{ - if (is_object) - o->setValueAt(index, ref); - else - a->replace(index, ref); - - return *this; -} - -QVariant QJsonValueRef::toVariant() const -{ - return toValue().toVariant(); -} - -QJsonArray QJsonValueRef::toArray() const -{ - return toValue().toArray(); -} - -QJsonObject QJsonValueRef::toObject() const -{ - return toValue().toObject(); -} - -QJsonValue QJsonValueRef::toValue() const -{ - if (!is_object) - return a->at(index); - return o->valueAt(index); -} - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -QDebug operator<<(QDebug dbg, const QJsonValue &o) -{ - QDebugStateSaver saver(dbg); - switch (o.t) { - case QJsonValue::Undefined: - dbg << "QJsonValue(undefined)"; - break; - case QJsonValue::Null: - dbg << "QJsonValue(null)"; - break; - case QJsonValue::Bool: - dbg.nospace() << "QJsonValue(bool, " << o.toBool() << ')'; - break; - case QJsonValue::Double: - dbg.nospace() << "QJsonValue(double, " << o.toDouble() << ')'; - break; - case QJsonValue::String: - dbg.nospace() << "QJsonValue(string, " << o.toString() << ')'; - break; - case QJsonValue::Array: - dbg.nospace() << "QJsonValue(array, "; - dbg << o.toArray(); - dbg << ')'; - break; - case QJsonValue::Object: - dbg.nospace() << "QJsonValue(object, "; - dbg << o.toObject(); - dbg << ')'; - break; - } - return dbg; -} -#endif - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h deleted file mode 100644 index 96538ebbf9..0000000000 --- a/src/corelib/json/qjsonvalue.h +++ /dev/null @@ -1,255 +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$ -** -****************************************************************************/ - -#ifndef QJSONVALUE_H -#define QJSONVALUE_H - -#include <QtCore/qglobal.h> -#include <QtCore/qstring.h> - -QT_BEGIN_NAMESPACE - -class QDebug; -class QVariant; -class QJsonArray; -class QJsonObject; - -namespace QJsonPrivate { - class Data; - class Base; - class Object; - class Header; - class Array; - class Value; - class Entry; -} - -class Q_CORE_EXPORT QJsonValue -{ -public: - enum Type { - Null = 0x0, - Bool = 0x1, - Double = 0x2, - String = 0x3, - Array = 0x4, - Object = 0x5, - Undefined = 0x80 - }; - - QJsonValue(Type = Null); - QJsonValue(bool b); - QJsonValue(double n); - QJsonValue(int n); - QJsonValue(qint64 n); - QJsonValue(const QString &s); - QJsonValue(QLatin1String s); -#ifndef QT_NO_CAST_FROM_ASCII - inline QT_ASCII_CAST_WARN QJsonValue(const char *s) - : d(nullptr), t(String) { stringDataFromQStringHelper(QString::fromUtf8(s)); } -#endif - QJsonValue(const QJsonArray &a); - QJsonValue(const QJsonObject &o); - - ~QJsonValue(); - - QJsonValue(const QJsonValue &other); - QJsonValue &operator =(const QJsonValue &other); - - QJsonValue(QJsonValue &&other) Q_DECL_NOTHROW - : ui(other.ui), - d(other.d), - t(other.t) - { - other.ui = 0; - other.d = nullptr; - other.t = Null; - } - - QJsonValue &operator =(QJsonValue &&other) Q_DECL_NOTHROW - { - swap(other); - return *this; - } - - void swap(QJsonValue &other) Q_DECL_NOTHROW - { - qSwap(ui, other.ui); - qSwap(d, other.d); - qSwap(t, other.t); - } - - static QJsonValue fromVariant(const QVariant &variant); - QVariant toVariant() const; - - Type type() const; - inline bool isNull() const { return type() == Null; } - inline bool isBool() const { return type() == Bool; } - inline bool isDouble() const { return type() == Double; } - inline bool isString() const { return type() == String; } - inline bool isArray() const { return type() == Array; } - inline bool isObject() const { return type() == Object; } - inline bool isUndefined() const { return type() == Undefined; } - - bool toBool(bool defaultValue = false) const; - int toInt(int defaultValue = 0) const; - double toDouble(double defaultValue = 0) const; - QString toString() const; - QString toString(const QString &defaultValue) const; - QJsonArray toArray() const; - QJsonArray toArray(const QJsonArray &defaultValue) const; - QJsonObject toObject() const; - QJsonObject toObject(const QJsonObject &defaultValue) const; - - const QJsonValue operator[](const QString &key) const; - const QJsonValue operator[](QLatin1String key) const; - const QJsonValue operator[](int i) const; - - bool operator==(const QJsonValue &other) const; - bool operator!=(const QJsonValue &other) const; - -private: - // avoid implicit conversions from char * to bool - inline QJsonValue(const void *) {} - friend class QJsonPrivate::Value; - friend class QJsonArray; - friend class QJsonObject; - friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); - - QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v); - void stringDataFromQStringHelper(const QString &string); - - void detach(); - - union { - quint64 ui; - bool b; - double dbl; - QStringData *stringData; - QJsonPrivate::Base *base; - }; - QJsonPrivate::Data *d; // needed for Objects and Arrays - Type t; -}; - -class Q_CORE_EXPORT QJsonValueRef -{ -public: - QJsonValueRef(QJsonArray *array, int idx) - : a(array), is_object(false), index(idx) {} - QJsonValueRef(QJsonObject *object, int idx) - : o(object), is_object(true), index(idx) {} - - inline operator QJsonValue() const { return toValue(); } - QJsonValueRef &operator = (const QJsonValue &val); - QJsonValueRef &operator = (const QJsonValueRef &val); - - QVariant toVariant() const; - inline QJsonValue::Type type() const { return toValue().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; } - inline bool isString() const { return type() == QJsonValue::String; } - inline bool isArray() const { return type() == QJsonValue::Array; } - 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(); } - 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); } - - inline bool operator==(const QJsonValue &other) const { return toValue() == other; } - inline bool operator!=(const QJsonValue &other) const { return toValue() != other; } - -private: - QJsonValue toValue() const; - - union { - QJsonArray *a; - QJsonObject *o; - }; - uint is_object : 1; - uint index : 31; -}; - -#ifndef Q_QDOC -// ### Qt 6: Get rid of these fake pointer classes -class QJsonValuePtr -{ - QJsonValue value; -public: - explicit QJsonValuePtr(const QJsonValue& val) - : value(val) {} - - QJsonValue& operator*() { return value; } - QJsonValue* operator->() { return &value; } -}; - -class QJsonValueRefPtr -{ - 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; } -}; -#endif - -Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue) - -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) -Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); -#endif - -QT_END_NAMESPACE - -#endif // QJSONVALUE_H diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/json/qjsonwriter.cpp deleted file mode 100644 index 12ce20ef09..0000000000 --- a/src/corelib/json/qjsonwriter.cpp +++ /dev/null @@ -1,231 +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$ -** -****************************************************************************/ - -#include <cmath> -#include <qlocale.h> -#include "qjsonwriter_p.h" -#include "qjson_p.h" -#include "private/qutfcodec_p.h" - -QT_BEGIN_NAMESPACE - -using namespace QJsonPrivate; - -static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact); -static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact); - -static inline uchar hexdig(uint u) -{ - return (u < 0xa ? '0' + u : 'a' + u - 0xa); -} - -static QByteArray escapedString(const QString &s) -{ - const uchar replacement = '?'; - QByteArray ba(s.length(), Qt::Uninitialized); - - 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()); - - while (src != end) { - if (cursor >= ba_end - 6) { - // ensure we have enough space - int pos = cursor - (const uchar *)ba.constData(); - ba.resize(ba.size()*2); - cursor = (uchar *)ba.data() + pos; - ba_end = (const uchar *)ba.constData() + ba.length(); - } - - uint u = *src++; - if (u < 0x80) { - if (u < 0x20 || u == 0x22 || u == 0x5c) { - *cursor++ = '\\'; - switch (u) { - case 0x22: - *cursor++ = '"'; - break; - case 0x5c: - *cursor++ = '\\'; - break; - case 0x8: - *cursor++ = 'b'; - break; - case 0xc: - *cursor++ = 'f'; - break; - case 0xa: - *cursor++ = 'n'; - break; - case 0xd: - *cursor++ = 'r'; - break; - case 0x9: - *cursor++ = 't'; - break; - default: - *cursor++ = 'u'; - *cursor++ = '0'; - *cursor++ = '0'; - *cursor++ = hexdig(u>>4); - *cursor++ = hexdig(u & 0xf); - } - } else { - *cursor++ = (uchar)u; - } - } else { - if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) - *cursor++ = replacement; - } - } - - ba.resize(cursor - (const uchar *)ba.constData()); - return ba; -} - -static void valueToJson(const QJsonPrivate::Base *b, const QJsonPrivate::Value &v, QByteArray &json, int indent, bool compact) -{ - QJsonValue::Type type = (QJsonValue::Type)(uint)v.type; - switch (type) { - case QJsonValue::Bool: - json += v.toBoolean() ? "true" : "false"; - break; - case QJsonValue::Double: { - const double d = v.toDouble(b); - if (qIsFinite(d)) { // +2 to format to ensure the expected precision - const double abs = std::abs(d); - json += QByteArray::number(d, abs == static_cast<quint64>(abs) ? 'f' : 'g', QLocale::FloatingPointShortest); - } else { - json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4) - } - break; - } - case QJsonValue::String: - json += '"'; - json += escapedString(v.toString(b)); - json += '"'; - break; - case QJsonValue::Array: - json += compact ? "[" : "[\n"; - arrayContentToJson(static_cast<QJsonPrivate::Array *>(v.base(b)), json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4*indent, ' '); - json += ']'; - break; - case QJsonValue::Object: - json += compact ? "{" : "{\n"; - objectContentToJson(static_cast<QJsonPrivate::Object *>(v.base(b)), json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4*indent, ' '); - json += '}'; - break; - case QJsonValue::Null: - default: - json += "null"; - } -} - -static void arrayContentToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact) -{ - if (!a || !a->length) - return; - - QByteArray indentString(4*indent, ' '); - - uint i = 0; - while (1) { - json += indentString; - valueToJson(a, a->at(i), json, indent, compact); - - if (++i == a->length) { - if (!compact) - json += '\n'; - break; - } - - json += compact ? "," : ",\n"; - } -} - - -static void objectContentToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact) -{ - if (!o || !o->length) - return; - - QByteArray indentString(4*indent, ' '); - - uint i = 0; - while (1) { - QJsonPrivate::Entry *e = o->entryAt(i); - json += indentString; - json += '"'; - json += escapedString(e->key()); - json += compact ? "\":" : "\": "; - valueToJson(o, e->value, json, indent, compact); - - if (++i == o->length) { - if (!compact) - json += '\n'; - break; - } - - json += compact ? "," : ",\n"; - } -} - -void Writer::objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact) -{ - json.reserve(json.size() + (o ? (int)o->size : 16)); - json += compact ? "{" : "{\n"; - objectContentToJson(o, json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4*indent, ' '); - json += compact ? "}" : "}\n"; -} - -void Writer::arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact) -{ - json.reserve(json.size() + (a ? (int)a->size : 16)); - json += compact ? "[" : "[\n"; - arrayContentToJson(a, json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4*indent, ' '); - json += compact ? "]" : "]\n"; -} - -QT_END_NAMESPACE diff --git a/src/corelib/json/qjsonwriter_p.h b/src/corelib/json/qjsonwriter_p.h deleted file mode 100644 index 76a8460449..0000000000 --- a/src/corelib/json/qjsonwriter_p.h +++ /dev/null @@ -1,73 +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$ -** -****************************************************************************/ - -#ifndef QJSONWRITER_P_H -#define QJSONWRITER_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/private/qglobal_p.h> -#include <qjsonvalue.h> - -QT_BEGIN_NAMESPACE - -namespace QJsonPrivate -{ - -class Writer -{ -public: - static void objectToJson(const QJsonPrivate::Object *o, QByteArray &json, int indent, bool compact = false); - static void arrayToJson(const QJsonPrivate::Array *a, QByteArray &json, int indent, bool compact = false); -}; - -} - -QT_END_NAMESPACE - -#endif |