1/****************************************************************************
2**
3** Copyright (C) 2018 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QCBORMAP_H
41#define QCBORMAP_H
42
43#include <QtCore/qcborvalue.h>
44#include <QtCore/qpair.h>
45
46#include <initializer_list>
47
48QT_BEGIN_NAMESPACE
49
50template <class Key, class T> class QMap;
51typedef QMap<QString, QVariant> QVariantMap;
52template <class Key, class T> class QHash;
53typedef QHash<QString, QVariant> QVariantHash;
54class QJsonObject;
55class QDataStream;
56
57class QCborContainerPrivate;
58class Q_CORE_EXPORT QCborMap
59{
60public:
61 typedef QPair<QCborValue, QCborValue> value_type;
62 typedef QCborValue key_type;
63 typedef QCborValue mapped_type;
64 typedef qsizetype size_type;
65
66 class ConstIterator;
67 class Iterator {
68 mutable QCborValueRef item; // points to the value
69 friend class ConstIterator;
70 friend class QCborMap;
71 Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
72 public:
73 typedef std::random_access_iterator_tag iterator_category;
74 typedef qsizetype difference_type;
75 typedef QPair<const QCborValueRef, QCborValueRef> value_type;
76 typedef QPair<const QCborValueRef, QCborValueRef> reference;
77 typedef QPair<const QCborValueRef, QCborValueRef> pointer;
78
79 Q_DECL_CONSTEXPR Iterator() = default;
80 Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
81 Iterator &operator=(const Iterator &other)
82 {
83 // rebind the reference
84 item.d = other.item.d;
85 item.i = other.item.i;
86 return *this;
87 }
88
89 value_type operator*() const { return { {item.d, item.i - 1}, item }; }
90 QCborValueRef *operator->() const { return &item; }
91 QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
92 QCborValueRef value() const { return item; }
93
94 bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
95 bool operator!=(const Iterator &o) const { return !(*this == o); }
96 bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
97 bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
98 bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
99 bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
100 bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
101 bool operator!=(const ConstIterator &o) const { return !(*this == o); }
102 bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
103 bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
104 bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
105 bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
106 Iterator &operator++() { item.i += 2; return *this; }
107 Iterator operator++(int) { Iterator n = *this; item.i += 2; return n; }
108 Iterator &operator--() { item.i -= 2; return *this; }
109 Iterator operator--(int) { Iterator n = *this; item.i -= 2; return n; }
110 Iterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
111 Iterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
112 Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + 2 * j }); }
113 Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - 2 * j }); }
114 qsizetype operator-(Iterator j) const { return (item.i - j.item.i) / 2; }
115 };
116
117 class ConstIterator {
118 QCborValueRef item; // points to the value
119 friend class Iterator;
120 friend class QCborMap;
121 friend class QCborValue;
122 friend class QCborValueRef;
123 ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
124 public:
125 typedef std::random_access_iterator_tag iterator_category;
126 typedef qsizetype difference_type;
127 typedef QPair<const QCborValueRef, const QCborValueRef> value_type;
128 typedef QPair<const QCborValueRef, const QCborValueRef> reference;
129 typedef QPair<const QCborValueRef, const QCborValueRef> pointer;
130
131 Q_DECL_CONSTEXPR ConstIterator() = default;
132 Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
133 ConstIterator &operator=(const ConstIterator &other)
134 {
135 // rebind the reference
136 item.d = other.item.d;
137 item.i = other.item.i;
138 return *this;
139 }
140
141 value_type operator*() const { return { {item.d, item.i - 1}, item }; }
142 const QCborValueRef *operator->() const { return &item; }
143 QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
144 QCborValueRef value() const { return item; }
145
146 bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
147 bool operator!=(const Iterator &o) const { return !(*this == o); }
148 bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
149 bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
150 bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
151 bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
152 bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
153 bool operator!=(const ConstIterator &o) const { return !(*this == o); }
154 bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
155 bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
156 bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
157 bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
158 ConstIterator &operator++() { item.i += 2; return *this; }
159 ConstIterator operator++(int) { ConstIterator n = *this; item.i += 2; return n; }
160 ConstIterator &operator--() { item.i -= 2; return *this; }
161 ConstIterator operator--(int) { ConstIterator n = *this; item.i -= 2; return n; }
162 ConstIterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
163 ConstIterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
164 ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + 2 * j }); }
165 ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - 2 * j }); }
166 qsizetype operator-(ConstIterator j) const { return (item.i - j.item.i) / 2; }
167 };
168
169 QCborMap() noexcept;
170 QCborMap(const QCborMap &other) noexcept;
171 QCborMap &operator=(const QCborMap &other) noexcept;
172 QCborMap(std::initializer_list<value_type> args)
173 : QCborMap()
174 {
175 detach(args.size());
176 for (const auto &pair : args)
177 insert(pair.first, pair.second);
178 }
179 ~QCborMap();
180
181 void swap(QCborMap &other) noexcept
182 {
183 qSwap(d, other.d);
184 }
185
186 QCborValue toCborValue() const { return *this; }
187
188 qsizetype size() const noexcept Q_DECL_PURE_FUNCTION;
189 bool isEmpty() const { return size() == 0; }
190 void clear();
191 QVector<QCborValue> keys() const;
192
193 QCborValue value(qint64 key) const
194 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
195 QCborValue value(QLatin1String key) const
196 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
197 QCborValue value(const QString & key) const
198 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
199 QCborValue value(const QCborValue &key) const
200 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
201#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
202 template<size_t N> QT_ASCII_CAST_WARN const QCborValue value(const char (&key)[N]) const
203 { return value(QString::fromUtf8(key, N - 1)); }
204#endif
205 const QCborValue operator[](qint64 key) const
206 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
207 const QCborValue operator[](QLatin1String key) const
208 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
209 const QCborValue operator[](const QString & key) const
210 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
211 const QCborValue operator[](const QCborValue &key) const
212 { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
213#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
214 template<size_t N> QT_ASCII_CAST_WARN const QCborValue operator[](const char (&key)[N]) const
215 { return operator[](QString::fromUtf8(key, N - 1)); }
216#endif
217 QCborValueRef operator[](qint64 key);
218 QCborValueRef operator[](QLatin1String key);
219 QCborValueRef operator[](const QString & key);
220 QCborValueRef operator[](const QCborValue &key);
221
222 QCborValue take(qint64 key)
223 { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
224 QCborValue take(QLatin1String key)
225 { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
226 QCborValue take(const QString &key)
227 { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
228 QCborValue take(const QCborValue &key)
229 { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
230 void remove(qint64 key)
231 { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
232 void remove(QLatin1String key)
233 { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
234 void remove(const QString & key)
235 { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
236 void remove(const QCborValue &key)
237 { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
238 bool contains(qint64 key) const
239 { const_iterator it = find(key); return it != end(); }
240 bool contains(QLatin1String key) const
241 { const_iterator it = find(key); return it != end(); }
242 bool contains(const QString & key) const
243 { const_iterator it = find(key); return it != end(); }
244 bool contains(const QCborValue &key) const
245 { const_iterator it = find(key); return it != end(); }
246
247 int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
248#if 0 && QT_HAS_INCLUDE(<compare>)
249 std::strong_ordering operator<=>(const QCborMap &other) const
250 {
251 int c = compare(other);
252 if (c > 0) return std::strong_ordering::greater;
253 if (c == 0) return std::strong_ordering::equivalent;
254 return std::strong_ordering::less;
255 }
256#else
257 bool operator==(const QCborMap &other) const noexcept
258 { return compare(other) == 0; }
259 bool operator!=(const QCborMap &other) const noexcept
260 { return !(*this == other); }
261 bool operator<(const QCborMap &other) const
262 { return compare(other) < 0; }
263#endif
264
265 typedef Iterator iterator;
266 typedef ConstIterator const_iterator;
267 iterator begin() { detach(); return iterator{d.data(), 1}; }
268 const_iterator constBegin() const { return const_iterator{d.data(), 1}; }
269 const_iterator begin() const { return constBegin(); }
270 const_iterator cbegin() const { return constBegin(); }
271 iterator end() { detach(); return iterator{d.data(), 2 * size() + 1}; }
272 const_iterator constEnd() const { return const_iterator{d.data(), 2 * size() + 1}; }
273 const_iterator end() const { return constEnd(); }
274 const_iterator cend() const { return constEnd(); }
275 iterator erase(iterator it);
276 iterator erase(const_iterator it) { return erase(iterator{ it.item.d, it.item.i }); }
277 QCborValue extract(iterator it);
278 QCborValue extract(const_iterator it) { return extract(iterator{ it.item.d, it.item.i }); }
279 bool empty() const { return isEmpty(); }
280
281 iterator find(qint64 key);
282 iterator find(QLatin1String key);
283 iterator find(const QString & key);
284 iterator find(const QCborValue &key);
285 const_iterator constFind(qint64 key) const;
286 const_iterator constFind(QLatin1String key) const;
287 const_iterator constFind(const QString & key) const;
288 const_iterator constFind(const QCborValue &key) const;
289 const_iterator find(qint64 key) const { return constFind(key); }
290 const_iterator find(QLatin1String key) const { return constFind(key); }
291 const_iterator find(const QString & key) const { return constFind(key); }
292 const_iterator find(const QCborValue &key) const { return constFind(key); }
293
294 iterator insert(qint64 key, const QCborValue &value_)
295 {
296 QCborValueRef v = operator[](key); // detaches
297 v = value_;
298 return { d.data(), v.i };
299 }
300 iterator insert(QLatin1String key, const QCborValue &value_)
301 {
302 QCborValueRef v = operator[](key); // detaches
303 v = value_;
304 return { d.data(), v.i };
305 }
306 iterator insert(const QString &key, const QCborValue &value_)
307 {
308 QCborValueRef v = operator[](key); // detaches
309 v = value_;
310 return { d.data(), v.i };
311 }
312 iterator insert(const QCborValue &key, const QCborValue &value_)
313 {
314 QCborValueRef v = operator[](key); // detaches
315 v = value_;
316 return { d.data(), v.i };
317 }
318 iterator insert(value_type v) { return insert(v.first, v.second); }
319
320 static QCborMap fromVariantMap(const QVariantMap &map);
321 static QCborMap fromVariantHash(const QVariantHash &hash);
322 static QCborMap fromJsonObject(const QJsonObject &o);
323 QVariantMap toVariantMap() const;
324 QVariantHash toVariantHash() const;
325 QJsonObject toJsonObject() const;
326
327private:
328 friend class QCborValue;
329 friend class QCborValueRef;
330 void detach(qsizetype reserve = 0);
331
332 explicit QCborMap(QCborContainerPrivate &dd) noexcept;
333 QExplicitlySharedDataPointer<QCborContainerPrivate> d;
334};
335
336Q_DECLARE_SHARED(QCborMap)
337
338inline QCborValue::QCborValue(QCborMap &&m)
339 : n(-1), container(m.d.take()), t(Map)
340{
341}
342
343inline QCborMap QCborValueRef::toMap() const
344{
345 return concrete().toMap();
346}
347
348inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
349{
350 return concrete().toMap(m);
351}
352
353Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
354
355#if !defined(QT_NO_DEBUG_STREAM)
356Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
357#endif
358
359#ifndef QT_NO_DATASTREAM
360Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborMap &);
361Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborMap &);
362#endif
363
364
365QT_END_NAMESPACE
366
367#endif // QCBORMAP_H
368