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 QDBUSARGUMENT_H
5#define QDBUSARGUMENT_H
6
7#include <QtDBus/qtdbusglobal.h>
8#include <QtCore/qbytearray.h>
9#include <QtCore/qhash.h>
10#include <QtCore/qglobal.h>
11#include <QtCore/qlist.h>
12#include <QtCore/qmap.h>
13#include <QtCore/qstring.h>
14#include <QtCore/qstringlist.h>
15#include <QtCore/qvariant.h>
16#include <QtDBus/qdbusextratypes.h>
17
18#ifndef QT_NO_DBUS
19
20QT_BEGIN_NAMESPACE
21
22
23class QDBusUnixFileDescriptor;
24
25class QDBusArgumentPrivate;
26class QDBusDemarshaller;
27class QDBusMarshaller;
28class Q_DBUS_EXPORT QDBusArgument
29{
30public:
31 enum ElementType {
32 BasicType,
33 VariantType,
34 ArrayType,
35 StructureType,
36 MapType,
37 MapEntryType,
38 UnknownType = -1
39 };
40
41 QDBusArgument();
42 QDBusArgument(const QDBusArgument &other);
43 QDBusArgument(QDBusArgument &&other) noexcept : d(other.d) { other.d = nullptr; }
44 QDBusArgument &operator=(QDBusArgument &&other) noexcept { swap(other); return *this; }
45 QDBusArgument &operator=(const QDBusArgument &other);
46 ~QDBusArgument();
47
48 void swap(QDBusArgument &other) noexcept { qt_ptr_swap(lhs&: d, rhs&: other.d); }
49
50 // used for marshalling (Qt -> D-BUS)
51 QDBusArgument &operator<<(uchar arg);
52 QDBusArgument &operator<<(bool arg);
53 QDBusArgument &operator<<(short arg);
54 QDBusArgument &operator<<(ushort arg);
55 QDBusArgument &operator<<(int arg);
56 QDBusArgument &operator<<(uint arg);
57 QDBusArgument &operator<<(qlonglong arg);
58 QDBusArgument &operator<<(qulonglong arg);
59 QDBusArgument &operator<<(double arg);
60 QDBusArgument &operator<<(const QString &arg);
61 QDBusArgument &operator<<(const QDBusVariant &arg);
62 QDBusArgument &operator<<(const QDBusObjectPath &arg);
63 QDBusArgument &operator<<(const QDBusSignature &arg);
64 QDBusArgument &operator<<(const QDBusUnixFileDescriptor &arg);
65 QDBusArgument &operator<<(const QStringList &arg);
66 QDBusArgument &operator<<(const QByteArray &arg);
67
68 void beginStructure();
69 void endStructure();
70 void beginArray(int elementMetaTypeId)
71 { beginArray(elementMetaType: QMetaType(elementMetaTypeId)); }
72 void beginArray(QMetaType elementMetaType);
73 void endArray();
74 void beginMap(int keyMetaTypeId, int valueMetaTypeId)
75 { beginMap(keyMetaType: QMetaType(keyMetaTypeId), valueMetaType: QMetaType(valueMetaTypeId)); }
76 void beginMap(QMetaType keyMetaType, QMetaType valueMetaType);
77 void endMap();
78 void beginMapEntry();
79 void endMapEntry();
80
81 void appendVariant(const QVariant &v);
82
83 // used for de-marshalling (D-BUS -> Qt)
84 QString currentSignature() const;
85 ElementType currentType() const;
86
87 const QDBusArgument &operator>>(uchar &arg) const;
88 const QDBusArgument &operator>>(bool &arg) const;
89 const QDBusArgument &operator>>(short &arg) const;
90 const QDBusArgument &operator>>(ushort &arg) const;
91 const QDBusArgument &operator>>(int &arg) const;
92 const QDBusArgument &operator>>(uint &arg) const;
93 const QDBusArgument &operator>>(qlonglong &arg) const;
94 const QDBusArgument &operator>>(qulonglong &arg) const;
95 const QDBusArgument &operator>>(double &arg) const;
96 const QDBusArgument &operator>>(QString &arg) const;
97 const QDBusArgument &operator>>(QDBusVariant &arg) const;
98 const QDBusArgument &operator>>(QDBusObjectPath &arg) const;
99 const QDBusArgument &operator>>(QDBusSignature &arg) const;
100 const QDBusArgument &operator>>(QDBusUnixFileDescriptor &arg) const;
101 const QDBusArgument &operator>>(QStringList &arg) const;
102 const QDBusArgument &operator>>(QByteArray &arg) const;
103
104 void beginStructure() const;
105 void endStructure() const;
106 void beginArray() const;
107 void endArray() const;
108 void beginMap() const;
109 void endMap() const;
110 void beginMapEntry() const;
111 void endMapEntry() const;
112 bool atEnd() const;
113
114 QVariant asVariant() const;
115
116protected:
117 QDBusArgument(QDBusArgumentPrivate *d);
118 friend class QDBusArgumentPrivate;
119 mutable QDBusArgumentPrivate *d;
120};
121Q_DECLARE_SHARED(QDBusArgument)
122
123QT_END_NAMESPACE
124QT_DECL_METATYPE_EXTERN(QDBusArgument, Q_DBUS_EXPORT)
125QT_BEGIN_NAMESPACE
126
127template<typename T> inline T qdbus_cast(const QDBusArgument &arg)
128{
129 T item;
130 arg >> item;
131 return item;
132}
133
134template<typename T> inline T qdbus_cast(const QVariant &v)
135{
136 if (v.metaType() == QMetaType::fromType<QDBusArgument>())
137 return qdbus_cast<T>(qvariant_cast<QDBusArgument>(v));
138 else
139 return qvariant_cast<T>(v);
140}
141
142// specialize for QVariant, allowing it to be used in place of QDBusVariant
143template<> inline QVariant qdbus_cast<QVariant>(const QDBusArgument &arg)
144{
145 QDBusVariant item;
146 arg >> item;
147 return item.variant();
148}
149template<> inline QVariant qdbus_cast<QVariant>(const QVariant &v)
150{
151 return qdbus_cast<QDBusVariant>(v).variant();
152}
153
154Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v);
155
156// QVariant types
157#ifndef QDBUS_NO_SPECIALTYPES
158
159Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date);
160Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QDate &date);
161
162Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time);
163Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QTime &time);
164
165Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt);
166Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt);
167
168Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect);
169Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect);
170
171Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect);
172Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect);
173
174Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size);
175Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QSize &size);
176
177Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size);
178Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size);
179
180Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt);
181Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt);
182
183Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt);
184Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt);
185
186Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line);
187Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QLine &line);
188
189Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line);
190Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line);
191#endif
192
193template<template <typename> class Container, typename T,
194 typename = typename Container<T>::iterator>
195inline QDBusArgument &operator<<(QDBusArgument &arg, const Container<T> &list)
196{
197 arg.beginArray(QMetaType::fromType<T>());
198 typename Container<T>::const_iterator it = list.begin();
199 typename Container<T>::const_iterator end = list.end();
200 for ( ; it != end; ++it)
201 arg << *it;
202 arg.endArray();
203 return arg;
204}
205
206template<template <typename> class Container, typename T,
207 typename = typename Container<T>::iterator>
208inline const QDBusArgument &operator>>(const QDBusArgument &arg, Container<T> &list)
209{
210 arg.beginArray();
211 list.clear();
212 while (!arg.atEnd()) {
213 T item;
214 arg >> item;
215 list.push_back(item);
216 }
217
218 arg.endArray();
219 return arg;
220}
221
222inline QDBusArgument &operator<<(QDBusArgument &arg, const QVariantList &list)
223{
224 arg.beginArray(elementMetaType: QMetaType::fromType<QDBusVariant>());
225 for (const QVariant &value : list)
226 arg << QDBusVariant(value);
227 arg.endArray();
228 return arg;
229}
230
231// Specializations for associative containers
232template <template <typename, typename> class Container, typename Key, typename T,
233 QtPrivate::IfAssociativeIteratorHasKeyAndValue<typename Container<Key, T>::iterator> = true>
234inline QDBusArgument &operator<<(QDBusArgument &arg, const Container<Key, T> &map)
235{
236 arg.beginMap(QMetaType::fromType<Key>(), QMetaType::fromType<T>());
237 auto it = map.begin();
238 auto end = map.end();
239 for ( ; it != end; ++it) {
240 arg.beginMapEntry();
241 arg << it.key() << it.value();
242 arg.endMapEntry();
243 }
244 arg.endMap();
245 return arg;
246}
247
248template <template <typename, typename> class Container, typename Key, typename T,
249 QtPrivate::IfAssociativeIteratorHasFirstAndSecond<typename Container<Key, T>::iterator> = true>
250inline QDBusArgument &operator<<(QDBusArgument &arg, const Container<Key, T> &map)
251{
252 arg.beginMap(QMetaType::fromType<Key>(), QMetaType::fromType<T>());
253 auto it = map.begin();
254 auto end = map.end();
255 for ( ; it != end; ++it) {
256 arg.beginMapEntry();
257 arg << it->first << it->second;
258 arg.endMapEntry();
259 }
260 arg.endMap();
261 return arg;
262}
263
264template <template <typename, typename> class Container, typename Key, typename T,
265 QtPrivate::IfAssociativeIteratorHasKeyAndValue<typename Container<Key, T>::iterator> = true>
266inline const QDBusArgument &operator>>(const QDBusArgument &arg, Container<Key, T> &map)
267{
268 arg.beginMap();
269 map.clear();
270 while (!arg.atEnd()) {
271 Key key;
272 T value;
273 arg.beginMapEntry();
274 arg >> key >> value;
275 map.insert(key, value);
276 arg.endMapEntry();
277 }
278 arg.endMap();
279 return arg;
280}
281
282inline QDBusArgument &operator<<(QDBusArgument &arg, const QVariantMap &map)
283{
284 arg.beginMap(keyMetaType: QMetaType::fromType<QString>(), valueMetaType: QMetaType::fromType<QDBusVariant>());
285 for (const auto &[key, value] : map.asKeyValueRange()) {
286 arg.beginMapEntry();
287 arg << key << QDBusVariant(value);
288 arg.endMapEntry();
289 }
290 arg.endMap();
291 return arg;
292}
293
294inline QDBusArgument &operator<<(QDBusArgument &arg, const QVariantHash &map)
295{
296 arg.beginMap(keyMetaType: QMetaType::fromType<QString>(), valueMetaType: QMetaType::fromType<QDBusVariant>());
297 for (const auto &[key, value] : map.asKeyValueRange()) {
298 arg.beginMapEntry();
299 arg << key << QDBusVariant(value);
300 arg.endMapEntry();
301 }
302 arg.endMap();
303 return arg;
304}
305
306template <typename T1, typename T2>
307inline QDBusArgument &operator<<(QDBusArgument &arg, const QPair<T1, T2> &pair)
308{
309 arg.beginStructure();
310 arg << pair.first << pair.second;
311 arg.endStructure();
312 return arg;
313}
314
315template <typename T1, typename T2>
316inline const QDBusArgument &operator>>(const QDBusArgument &arg, QPair<T1, T2> &pair)
317{
318 arg.beginStructure();
319 arg >> pair.first >> pair.second;
320 arg.endStructure();
321 return arg;
322}
323
324QT_END_NAMESPACE
325
326#endif // QT_NO_DBUS
327#endif
328

source code of qtbase/src/dbus/qdbusargument.h