1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QJSONVALUE_H |
5 | #define QJSONVALUE_H |
6 | |
7 | #include <QtCore/qglobal.h> |
8 | #include <QtCore/qstring.h> |
9 | #include <QtCore/qshareddata.h> |
10 | #include <QtCore/qcborvalue.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | class QVariant; |
15 | class QJsonArray; |
16 | class QJsonObject; |
17 | class QCborContainerPrivate; |
18 | |
19 | namespace QJsonPrivate { |
20 | class Value; |
21 | } |
22 | |
23 | class Q_CORE_EXPORT QJsonValue |
24 | { |
25 | public: |
26 | enum Type { |
27 | Null = 0x0, |
28 | Bool = 0x1, |
29 | Double = 0x2, |
30 | String = 0x3, |
31 | Array = 0x4, |
32 | Object = 0x5, |
33 | Undefined = 0x80 |
34 | }; |
35 | |
36 | QJsonValue(Type = Null); |
37 | QJsonValue(bool b); |
38 | QJsonValue(double n); |
39 | QJsonValue(int n); |
40 | QJsonValue(qint64 v); |
41 | QJsonValue(const QString &s); |
42 | QJsonValue(QLatin1StringView s); |
43 | #ifndef QT_NO_CAST_FROM_ASCII |
44 | QT_ASCII_CAST_WARN inline QJsonValue(const char *s) |
45 | : QJsonValue(QString::fromUtf8(s)) {} |
46 | #endif |
47 | QJsonValue(const QJsonArray &a); |
48 | QJsonValue(QJsonArray &&a) noexcept; |
49 | QJsonValue(const QJsonObject &o); |
50 | QJsonValue(QJsonObject &&o) noexcept; |
51 | |
52 | ~QJsonValue(); |
53 | |
54 | QJsonValue(const QJsonValue &other) noexcept; |
55 | QJsonValue &operator =(const QJsonValue &other) noexcept; |
56 | |
57 | QJsonValue(QJsonValue &&other) noexcept; |
58 | |
59 | QJsonValue &operator =(QJsonValue &&other) noexcept |
60 | { |
61 | swap(other); |
62 | return *this; |
63 | } |
64 | |
65 | void swap(QJsonValue &other) noexcept; |
66 | |
67 | static QJsonValue fromVariant(const QVariant &variant); |
68 | QVariant toVariant() const; |
69 | |
70 | Type type() const; |
71 | inline bool isNull() const { return type() == Null; } |
72 | inline bool isBool() const { return type() == Bool; } |
73 | inline bool isDouble() const { return type() == Double; } |
74 | inline bool isString() const { return type() == String; } |
75 | inline bool isArray() const { return type() == Array; } |
76 | inline bool isObject() const { return type() == Object; } |
77 | inline bool isUndefined() const { return type() == Undefined; } |
78 | |
79 | bool toBool(bool defaultValue = false) const; |
80 | int toInt(int defaultValue = 0) const; |
81 | qint64 toInteger(qint64 defaultValue = 0) const; |
82 | double toDouble(double defaultValue = 0) const; |
83 | QString toString() const; |
84 | QString toString(const QString &defaultValue) const; |
85 | QJsonArray toArray() const; |
86 | QJsonArray toArray(const QJsonArray &defaultValue) const; |
87 | QJsonObject toObject() const; |
88 | QJsonObject toObject(const QJsonObject &defaultValue) const; |
89 | |
90 | const QJsonValue operator[](const QString &key) const; |
91 | const QJsonValue operator[](QStringView key) const; |
92 | const QJsonValue operator[](QLatin1StringView key) const; |
93 | const QJsonValue operator[](qsizetype i) const; |
94 | |
95 | bool operator==(const QJsonValue &other) const; |
96 | bool operator!=(const QJsonValue &other) const; |
97 | |
98 | private: |
99 | // avoid implicit conversions from char * to bool |
100 | QJsonValue(const void *) = delete; |
101 | friend class QJsonPrivate::Value; |
102 | friend class QJsonArray; |
103 | friend class QJsonObject; |
104 | friend class QCborValue; |
105 | friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); |
106 | friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &); |
107 | |
108 | QCborValue value; |
109 | |
110 | // Assert binary compatibility with pre-5.15 QJsonValue |
111 | static_assert(sizeof(QExplicitlySharedDataPointer<QCborContainerPrivate>) == sizeof(void *)); |
112 | static_assert(sizeof(QCborValue::Type) == sizeof(QJsonValue::Type)); |
113 | }; |
114 | |
115 | Q_DECLARE_SHARED(QJsonValue) |
116 | |
117 | class QJsonValueConstRef |
118 | { |
119 | public: |
120 | QJsonValueConstRef(const QJsonValueConstRef &) = default; |
121 | QJsonValueConstRef &operator=(const QJsonValueConstRef &) = delete; |
122 | inline operator QJsonValue() const { return concrete(self: *this); } |
123 | |
124 | Q_CORE_EXPORT QVariant toVariant() const; |
125 | QJsonValue::Type type() const { return concreteType(self: *this); } |
126 | bool isNull() const { return type() == QJsonValue::Null; } |
127 | bool isBool() const { return type() == QJsonValue::Bool; } |
128 | bool isDouble() const { return type() == QJsonValue::Double; } |
129 | bool isString() const { return type() == QJsonValue::String; } |
130 | bool isArray() const { return type() == QJsonValue::Array; } |
131 | bool isObject() const { return type() == QJsonValue::Object; } |
132 | bool isUndefined() const { return type() == QJsonValue::Undefined; } |
133 | |
134 | bool toBool(bool defaultValue = false) const |
135 | { return concreteBool(self: *this, defaultValue); } |
136 | int toInt(int defaultValue = 0) const |
137 | { return int(concreteInt(self: *this, defaultValue, clamp: true)); } |
138 | qint64 toInteger(qint64 defaultValue = 0) const |
139 | { return concreteInt(self: *this, defaultValue, clamp: false); } |
140 | double toDouble(double defaultValue = 0) const |
141 | { return concreteDouble(self: *this, defaultValue); } |
142 | QString toString(const QString &defaultValue = {}) const |
143 | { return concreteString(self: *this, defaultValue); } |
144 | Q_CORE_EXPORT QJsonArray toArray() const; |
145 | Q_CORE_EXPORT QJsonObject toObject() const; |
146 | |
147 | const QJsonValue operator[](QStringView key) const { return concrete(self: *this)[key]; } |
148 | const QJsonValue operator[](QLatin1StringView key) const { return concrete(self: *this)[key]; } |
149 | const QJsonValue operator[](qsizetype i) const { return concrete(self: *this)[i]; } |
150 | |
151 | inline bool operator==(const QJsonValue &other) const { return concrete(self: *this) == other; } |
152 | inline bool operator!=(const QJsonValue &other) const { return concrete(self: *this) != other; } |
153 | |
154 | protected: |
155 | Q_CORE_EXPORT static QJsonValue::Type |
156 | concreteType(QJsonValueConstRef self) noexcept Q_DECL_PURE_FUNCTION; |
157 | Q_CORE_EXPORT static bool |
158 | concreteBool(QJsonValueConstRef self, bool defaultValue) noexcept Q_DECL_PURE_FUNCTION; |
159 | Q_CORE_EXPORT static qint64 |
160 | concreteInt(QJsonValueConstRef self, qint64 defaultValue, bool clamp) noexcept Q_DECL_PURE_FUNCTION; |
161 | Q_CORE_EXPORT static double |
162 | concreteDouble(QJsonValueConstRef self, double defaultValue) noexcept Q_DECL_PURE_FUNCTION; |
163 | Q_CORE_EXPORT static QString concreteString(QJsonValueConstRef self, const QString &defaultValue); |
164 | Q_CORE_EXPORT static QJsonValue concrete(QJsonValueConstRef self) noexcept; |
165 | |
166 | // for iterators |
167 | Q_CORE_EXPORT static QString objectKey(QJsonValueConstRef self); |
168 | QString objectKey() const { return objectKey(self: *this); } |
169 | |
170 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) |
171 | QJsonValueConstRef(QJsonArray *array, qsizetype idx) |
172 | : a(array), is_object(false), index(static_cast<quint64>(idx)) {} |
173 | QJsonValueConstRef(QJsonObject *object, qsizetype idx) |
174 | : o(object), is_object(true), index(static_cast<quint64>(idx)) {} |
175 | |
176 | void rebind(QJsonValueConstRef other) |
177 | { |
178 | Q_ASSERT(is_object == other.is_object); |
179 | if (is_object) |
180 | o = other.o; |
181 | else |
182 | a = other.a; |
183 | index = other.index; |
184 | } |
185 | |
186 | union { |
187 | QJsonArray *a; |
188 | QJsonObject *o; |
189 | void *d; |
190 | }; |
191 | quint64 is_object : 1; |
192 | quint64 index : 63; |
193 | #else |
194 | constexpr QJsonValueConstRef(QCborContainerPrivate *d, size_t index, bool is_object) |
195 | : d(d), is_object(is_object), index(index) |
196 | {} |
197 | |
198 | // implemented in qjsonarray.h & qjsonobject.h, to get their d |
199 | QJsonValueConstRef(QJsonArray *array, qsizetype idx); |
200 | QJsonValueConstRef(QJsonObject *object, qsizetype idx); |
201 | |
202 | void rebind(QJsonValueConstRef other) |
203 | { |
204 | d = other.d; |
205 | index = other.index; |
206 | } |
207 | |
208 | QCborContainerPrivate *d = nullptr; |
209 | size_t is_object : 1; |
210 | size_t index : std::numeric_limits<size_t>::digits - 1; |
211 | #endif |
212 | |
213 | friend class QJsonArray; |
214 | friend class QJsonObject; |
215 | friend class QJsonPrivate::Value; |
216 | }; |
217 | |
218 | QT_WARNING_PUSH |
219 | QT6_ONLY(QT_WARNING_DISABLE_MSVC(4275)) // non dll-interface class 'QJsonValueConstRef' used as base for dll-interface class 'QJsonValueRef' |
220 | class QT6_ONLY(Q_CORE_EXPORT) QJsonValueRef : public QJsonValueConstRef |
221 | { |
222 | public: |
223 | QJsonValueRef(const QJsonValueRef &) = default; |
224 | QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValue &val); |
225 | QT7_ONLY(Q_CORE_EXPORT) QJsonValueRef &operator = (const QJsonValueRef &val); |
226 | |
227 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED) |
228 | // retained for binary compatibility (due to the Q_CORE_EXPORT) because at |
229 | // least one compiler emits and exports all inlines in an exported class |
230 | |
231 | QJsonValueRef(QJsonArray *array, qsizetype idx) |
232 | : QJsonValueConstRef(array, idx) {} |
233 | QJsonValueRef(QJsonObject *object, qsizetype idx) |
234 | : QJsonValueConstRef(object, idx) {} |
235 | |
236 | operator QJsonValue() const { return toValue(); } |
237 | |
238 | QVariant toVariant() const; |
239 | inline QJsonValue::Type type() const { return QJsonValueConstRef::type(); } |
240 | inline bool isNull() const { return type() == QJsonValue::Null; } |
241 | inline bool isBool() const { return type() == QJsonValue::Bool; } |
242 | inline bool isDouble() const { return type() == QJsonValue::Double; } |
243 | inline bool isString() const { return type() == QJsonValue::String; } |
244 | inline bool isArray() const { return type() == QJsonValue::Array; } |
245 | inline bool isObject() const { return type() == QJsonValue::Object; } |
246 | inline bool isUndefined() const { return type() == QJsonValue::Undefined; } |
247 | |
248 | inline bool toBool(bool defaultValue = false) const { return QJsonValueConstRef::toBool(defaultValue); } |
249 | inline int toInt(int defaultValue = 0) const { return QJsonValueConstRef::toInt(defaultValue); } |
250 | inline qint64 toInteger(qint64 defaultValue = 0) const { return QJsonValueConstRef::toInteger(defaultValue); } |
251 | inline double toDouble(double defaultValue = 0) const { return QJsonValueConstRef::toDouble(defaultValue); } |
252 | inline QString toString(const QString &defaultValue = {}) const { return QJsonValueConstRef::toString(defaultValue); } |
253 | QJsonArray toArray() const; |
254 | QJsonObject toObject() const; |
255 | |
256 | const QJsonValue operator[](QStringView key) const { return QJsonValueConstRef::operator[](key); } |
257 | const QJsonValue operator[](QLatin1StringView key) const { return QJsonValueConstRef::operator[](key); } |
258 | const QJsonValue operator[](qsizetype i) const { return QJsonValueConstRef::operator[](i); } |
259 | |
260 | inline bool operator==(const QJsonValue &other) const { return QJsonValueConstRef::operator==(other); } |
261 | inline bool operator!=(const QJsonValue &other) const { return QJsonValueConstRef::operator!=(other); } |
262 | |
263 | private: |
264 | QJsonValue toValue() const; |
265 | #else |
266 | using QJsonValueConstRef::operator[]; |
267 | Q_CORE_EXPORT QJsonValueRef operator[](QAnyStringView key); |
268 | Q_CORE_EXPORT QJsonValueRef operator[](qsizetype i); |
269 | |
270 | private: |
271 | using QJsonValueConstRef::QJsonValueConstRef; |
272 | #endif // < Qt 7 |
273 | |
274 | QT7_ONLY(Q_CORE_EXPORT) void detach(); |
275 | friend class QJsonArray; |
276 | friend class QJsonObject; |
277 | }; |
278 | QT_WARNING_POP |
279 | |
280 | inline QJsonValue QCborValueConstRef::toJsonValue() const |
281 | { |
282 | return concrete().toJsonValue(); |
283 | } |
284 | |
285 | inline bool operator==(const QJsonValueConstRef &lhs, const QJsonValueRef &rhs) |
286 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
287 | inline bool operator!=(const QJsonValueConstRef &lhs, const QJsonValueRef &rhs) |
288 | { return !(lhs == rhs); } |
289 | |
290 | inline bool operator==(const QJsonValueRef &lhs, const QJsonValueConstRef &rhs) |
291 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
292 | inline bool operator!=(const QJsonValueRef &lhs, const QJsonValueConstRef &rhs) |
293 | { return !(lhs == rhs); } |
294 | |
295 | inline bool operator==(const QJsonValueRef &lhs, const QJsonValueRef &rhs) |
296 | { return QJsonValue(lhs) == QJsonValue(rhs); } |
297 | inline bool operator!=(const QJsonValueRef &lhs, const QJsonValueRef &rhs) |
298 | { return !(lhs == rhs); } |
299 | |
300 | Q_CORE_EXPORT size_t qHash(const QJsonValue &value, size_t seed = 0); |
301 | |
302 | #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) |
303 | Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); |
304 | #endif |
305 | |
306 | #ifndef QT_NO_DATASTREAM |
307 | Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &); |
308 | Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonValue &); |
309 | #endif |
310 | |
311 | QT_END_NAMESPACE |
312 | |
313 | #endif // QJSONVALUE_H |
314 | |