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