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#include "qdbusargument.h"
41#include "qdbusargument_p.h"
42
43#include <qatomic.h>
44#include <qbytearray.h>
45#include <qlist.h>
46#include <qmap.h>
47#include <qstring.h>
48#include <qstringlist.h>
49#include <qvariant.h>
50#include <qdatetime.h>
51#include <qrect.h>
52#include <qline.h>
53
54#include "qdbusmetatype_p.h"
55#include "qdbusutil_p.h"
56
57#ifndef QT_NO_DBUS
58
59QT_BEGIN_NAMESPACE
60
61QDBusArgumentPrivate::~QDBusArgumentPrivate()
62{
63 if (message)
64 q_dbus_message_unref(message);
65}
66
67QByteArray QDBusArgumentPrivate::createSignature(int id)
68{
69 if (!qdbus_loadLibDBus())
70 return "";
71
72 QByteArray signature;
73 QDBusMarshaller *marshaller = new QDBusMarshaller(0);
74 marshaller->ba = &signature;
75
76 // run it
77 void *null = nullptr;
78 QVariant v(id, null);
79 QDBusArgument arg(marshaller);
80 QDBusMetaType::marshall(arg, id: v.userType(), data: v.constData());
81 arg.d = nullptr;
82
83 // delete it
84 bool ok = marshaller->ok;
85 delete marshaller;
86
87 if (signature.isEmpty() || !ok || !QDBusUtil::isValidSingleSignature(signature: QString::fromLatin1(str: signature))) {
88 qWarning(msg: "QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' "
89 "(Did you forget to call beginStructure() ?)",
90 QMetaType::typeName(type: id),
91 signature.isEmpty() ? "<empty>" : signature.constData());
92 return "";
93 } else if ((signature.at(i: 0) != DBUS_TYPE_ARRAY && signature.at(i: 0) != DBUS_STRUCT_BEGIN_CHAR) ||
94 (signature.at(i: 0) == DBUS_TYPE_ARRAY && (signature.at(i: 1) == DBUS_TYPE_BYTE ||
95 signature.at(i: 1) == DBUS_TYPE_STRING))) {
96 qWarning(msg: "QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) "
97 "(Did you forget to call beginStructure() ?)",
98 QMetaType::typeName(type: id),
99 signature.constData(),
100 QMetaType::typeName(type: QDBusMetaType::signatureToType(signature)));
101 return "";
102 }
103 return signature;
104}
105
106bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d)
107{
108 if (!d)
109 return false;
110 if (d->direction == Marshalling) {
111 if (!d->marshaller()->ok)
112 return false;
113
114 if (d->message && d->ref.loadRelaxed() != 1) {
115 QDBusMarshaller *dd = new QDBusMarshaller(d->capabilities);
116 dd->message = q_dbus_message_copy(message: d->message);
117 q_dbus_message_iter_init_append(message: dd->message, iter: &dd->iterator);
118
119 if (!d->ref.deref())
120 delete d;
121 d = dd;
122 }
123 return true;
124 }
125
126#ifdef QT_DEBUG
127 qFatal("QDBusArgument: write from a read-only object");
128#else
129 qWarning(msg: "QDBusArgument: write from a read-only object");
130#endif
131 return false;
132}
133
134bool QDBusArgumentPrivate::checkRead(QDBusArgumentPrivate *d)
135{
136 if (!d)
137 return false;
138 if (d->direction == Demarshalling)
139 return true;
140
141#ifdef QT_DEBUG
142 qFatal("QDBusArgument: read from a write-only object");
143#else
144 qWarning(msg: "QDBusArgument: read from a write-only object");
145#endif
146
147 return false;
148}
149
150bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d)
151{
152 if (!checkRead(d))
153 return false; // don't bother
154
155 if (d->ref.loadRelaxed() == 1)
156 return true; // no need to detach
157
158 QDBusDemarshaller *dd = new QDBusDemarshaller(d->capabilities);
159 dd->message = q_dbus_message_ref(message: d->message);
160 dd->iterator = static_cast<QDBusDemarshaller*>(d)->iterator;
161
162 if (!d->ref.deref())
163 delete d;
164 d = dd;
165 return true;
166}
167
168/*!
169 \class QDBusArgument
170 \inmodule QtDBus
171 \since 4.2
172
173 \brief The QDBusArgument class is used to marshall and demarshall D-Bus arguments.
174
175 The class is used to send arguments over D-Bus to remote
176 applications and to receive them back. D-Bus offers an extensible
177 type system, based on a few primitive types and associations of
178 them. See the \l {qdbustypesystem.html}{Qt D-Bus Type System} page
179 for more information on the type system.
180
181 QDBusArgument is the central class in the Qt D-Bus type system,
182 providing functions to marshall and demarshall the primitive
183 types. The compound types are then created by association of one
184 or more of the primitive types in arrays, dictionaries or
185 structures.
186
187 The following example illustrates how a structure containing an
188 integer and a string can be constructed using the \l
189 {qdbustypesystem.html}{Qt D-Bus type system}:
190
191 \snippet code/src_qdbus_qdbusargument.cpp 0
192
193 The type has to be registered with qDBusRegisterMetaType() before
194 it can be used with QDBusArgument. Therefore, somewhere in your
195 program, you should add the following code:
196
197 \snippet code/src_qdbus_qdbusargument.cpp 1
198
199 Once registered, a type can be used in outgoing method calls
200 (placed with QDBusAbstractInterface::call()), signal emissions
201 from registered objects or in incoming calls from remote
202 applications.
203
204 It is important to note that the \c{operator<<} and \c{operator>>}
205 streaming functions must always produce the same number of entries
206 in case of structures, both in reading and in writing (marshalling
207 and demarshalling), otherwise calls and signals may start to
208 silently fail.
209
210 The following example illustrates this wrong usage
211 in context of a class that may contain invalid data:
212
213 \code
214 //bad code
215 // Wrongly marshall the MyTime data into a D-Bus argument
216 QDBusArgument &operator<<(QDBusArgument &argument, const MyTime &mytime)
217 {
218 argument.beginStructure();
219 if (mytime.isValid)
220 argument << true << mytime.hour
221 << mytime.minute << mytime.second;
222 else
223 argument << false;
224 argument.endStructure();
225 return argument;
226 }
227 \endcode
228
229 In this example, both the \c{operator<<} and the \c{operator>>}
230 functions may produce a different number of reads/writes. This can
231 confuse the Qt D-Bus type system and should be avoided.
232
233 \sa QDBusAbstractInterface, {qdbustypesystem.html}{The Qt D-Bus type
234 system}, {usingadaptors.html}{Using Adaptors}, qdbus_cast()
235*/
236
237/*!
238 \enum QDBusArgument::ElementType
239 \since 4.5
240
241 This enum describes the type of element held by the argument.
242
243 \value BasicType A basic element, which is understood by
244 QVariant. The following types are considered basic: bool,
245 byte, short, ushort, int, uint, qint64, quint64, double,
246 QString, QByteArray, QDBusObjectPath, QDBusSignature
247
248 \value VariantType The variant element (QDBusVariant)
249
250 \value ArrayType An array element, usually represented by QList<T>
251 or QVector<T>. Note: QByteArray and associative maps are not
252 considered arrays, even if the D-Bus protocol transports them as such.
253
254 \value StructureType A custom type represented by a structure,
255 like QDateTime, QPoint, etc.
256
257 \value MapType An associative container, like QMap<Key, Value> or
258 QHash<Key, Value>
259
260 \value MapEntryType One entry in an associative container: both
261 the key and the value form one map-entry type.
262
263 \value UnknownType The type is unknown or we have reached the end
264 of the list.
265
266 \sa currentType()
267*/
268
269/*!
270 \fn template<typename T> T qdbus_cast(const QDBusArgument &arg, T*)
271 \relates QDBusArgument
272 \since 4.2
273
274 Attempts to demarshall the contents of \a arg into the type
275 \c{T}. For example:
276
277 \snippet code/src_qdbus_qdbusargument.cpp 2
278
279 Note that it is equivalent to the following:
280
281 \snippet code/src_qdbus_qdbusargument.cpp 3
282*/
283
284/*!
285 Constructs an empty QDBusArgument argument.
286
287 An empty QDBusArgument object does not allow either reading or
288 writing to be performed.
289*/
290QDBusArgument::QDBusArgument()
291{
292 if (!qdbus_loadLibDBus()) {
293 d = nullptr;
294 return;
295 }
296
297 QDBusMarshaller *dd = new QDBusMarshaller(0);
298 d = dd;
299
300 // create a new message with any type, we won't sent it anyways
301 dd->message = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
302 q_dbus_message_iter_init_append(message: dd->message, iter: &dd->iterator);
303}
304
305/*!
306 Constructs a copy of the \a other QDBusArgument object.
307
308 Both objects will therefore contain the same state from this point
309 forward. QDBusArguments are explicitly shared and, therefore, any
310 modification to either copy will affect the other one too.
311*/
312QDBusArgument::QDBusArgument(const QDBusArgument &other)
313 : d(other.d)
314{
315 if (d)
316 d->ref.ref();
317}
318
319/*!
320 \internal
321*/
322QDBusArgument::QDBusArgument(QDBusArgumentPrivate *dd)
323 : d(dd)
324{
325}
326
327/*!
328 Copies the \a other QDBusArgument object into this one.
329
330 Both objects will therefore contain the same state from this point
331 forward. QDBusArguments are explicitly shared and, therefore, any
332 modification to either copy will affect the other one too.
333*/
334QDBusArgument &QDBusArgument::operator=(const QDBusArgument &other)
335{
336 qAtomicAssign(d, x: other.d);
337 return *this;
338}
339
340/*!
341 Disposes of the resources associated with this QDBusArgument
342 object.
343*/
344QDBusArgument::~QDBusArgument()
345{
346 if (d && !d->ref.deref())
347 delete d;
348}
349
350/*!
351 Appends the primitive value \a arg of type \c{BYTE} to the D-Bus stream.
352*/
353QDBusArgument &QDBusArgument::operator<<(uchar arg)
354{
355 if (QDBusArgumentPrivate::checkWrite(d))
356 d->marshaller()->append(arg);
357 return *this;
358}
359
360/*!
361 \overload
362 Appends the primitive value \a arg of type \c{BOOLEAN} to the D-Bus stream.
363*/
364QDBusArgument &QDBusArgument::operator<<(bool arg)
365{
366 if (QDBusArgumentPrivate::checkWrite(d))
367 d->marshaller()->append(arg);
368 return *this;
369}
370
371/*!
372 \overload
373 Appends the primitive value \a arg of type \c{INT16} to the D-Bus stream.
374*/
375QDBusArgument &QDBusArgument::operator<<(short arg)
376{
377 if (QDBusArgumentPrivate::checkWrite(d))
378 d->marshaller()->append(arg);
379 return *this;
380}
381
382/*!
383 \overload
384 Appends the primitive value \a arg of type \c{UINT16} to the D-Bus stream.
385*/
386QDBusArgument &QDBusArgument::operator<<(ushort arg)
387{
388 if (QDBusArgumentPrivate::checkWrite(d))
389 d->marshaller()->append(arg);
390 return *this;
391}
392
393/*!
394 \overload
395 Appends the primitive value \a arg of type \c{INT32} to the D-Bus stream.
396*/
397QDBusArgument &QDBusArgument::operator<<(int arg)
398{
399 if (QDBusArgumentPrivate::checkWrite(d))
400 d->marshaller()->append(arg);
401 return *this;
402}
403
404/*!
405 \overload
406 Appends the primitive value \a arg of type \c{UINT32} to the D-Bus stream.
407*/
408QDBusArgument &QDBusArgument::operator<<(uint arg)
409{
410 if (QDBusArgumentPrivate::checkWrite(d))
411 d->marshaller()->append(arg);
412 return *this;
413}
414
415/*!
416 \overload
417 Appends the primitive value \a arg of type \c{INT64} to the D-Bus stream.
418*/
419QDBusArgument &QDBusArgument::operator<<(qlonglong arg)
420{
421 if (QDBusArgumentPrivate::checkWrite(d))
422 d->marshaller()->append(arg);
423 return *this;
424}
425
426/*!
427 \overload
428 Appends the primitive value \a arg of type \c{UINT64} to the D-Bus stream.
429*/
430QDBusArgument &QDBusArgument::operator<<(qulonglong arg)
431{
432 if (QDBusArgumentPrivate::checkWrite(d))
433 d->marshaller()->append(arg);
434 return *this;
435}
436
437/*!
438 \overload
439 Appends the primitive value \a arg of type \c{DOUBLE} (double-precision
440 floating-point) to the D-Bus stream.
441*/
442QDBusArgument &QDBusArgument::operator<<(double arg)
443{
444 if (QDBusArgumentPrivate::checkWrite(d))
445 d->marshaller()->append(arg);
446 return *this;
447}
448
449/*!
450 \overload
451 Appends the primitive value \a arg of type \c{STRING} (Unicode character
452 string) to the D-Bus stream.
453*/
454QDBusArgument &QDBusArgument::operator<<(const QString &arg)
455{
456 if (QDBusArgumentPrivate::checkWrite(d))
457 d->marshaller()->append(arg);
458 return *this;
459}
460
461/*!
462 \overload
463 \internal
464 Appends the primitive value \a arg of type \c{OBJECT_PATH} (path to a D-Bus
465 object) to the D-Bus stream.
466*/
467QDBusArgument &QDBusArgument::operator<<(const QDBusObjectPath &arg)
468{
469 if (QDBusArgumentPrivate::checkWrite(d))
470 d->marshaller()->append(arg);
471 return *this;
472}
473
474/*!
475 \overload
476 \internal
477 Appends the primitive value \a arg of type \c{SIGNATURE} (D-Bus type
478 signature) to the D-Bus stream.
479*/
480QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg)
481{
482 if (QDBusArgumentPrivate::checkWrite(d))
483 d->marshaller()->append(arg);
484 return *this;
485}
486
487/*!
488 \overload
489 \since 4.8
490 \internal
491 Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix
492 File Descriptor) to the D-Bus stream.
493*/
494QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg)
495{
496 if (QDBusArgumentPrivate::checkWrite(d))
497 d->marshaller()->append(arg);
498 return *this;
499}
500
501/*!
502 \overload
503 Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
504
505 A D-Bus variant type can contain any type, including other
506 variants. It is similar to the Qt QVariant type.
507*/
508QDBusArgument &QDBusArgument::operator<<(const QDBusVariant &arg)
509{
510 if (QDBusArgumentPrivate::checkWrite(d))
511 d->marshaller()->append(arg);
512 return *this;
513}
514
515/*!
516 \overload
517 Appends the QStringList given by \a arg as \c{ARRAY of STRING}
518 to the D-Bus stream.
519
520 QStringList and QByteArray are the only two non-primitive types
521 that are supported directly by QDBusArgument because of their
522 widespread usage in Qt applications.
523
524 Other arrays are supported through compound types in Qt D-Bus.
525*/
526QDBusArgument &QDBusArgument::operator<<(const QStringList &arg)
527{
528 if (QDBusArgumentPrivate::checkWrite(d))
529 d->marshaller()->append(arg);
530 return *this;
531}
532
533/*!
534 \overload
535 Appends the QByteArray given by \a arg as \c{ARRAY of BYTE}
536 to the D-Bus stream.
537
538 QStringList and QByteArray are the only two non-primitive types
539 that are supported directly by QDBusArgument because of their
540 widespread usage in Qt applications.
541
542 Other arrays are supported through compound types in Qt D-Bus.
543*/
544QDBusArgument &QDBusArgument::operator<<(const QByteArray &arg)
545{
546 if (QDBusArgumentPrivate::checkWrite(d))
547 d->marshaller()->append(arg);
548 return *this;
549}
550
551/*!
552 \internal
553 \since 4.5
554
555 Appends the variant \a v.
556
557 \sa asVariant()
558*/
559void QDBusArgument::appendVariant(const QVariant &v)
560{
561 if (QDBusArgumentPrivate::checkWrite(d))
562 d->marshaller()->appendVariantInternal(arg: v);
563}
564
565/*!
566 \internal
567 Returns the type signature of the D-Bus type this QDBusArgument
568 object is currently pointing to.
569*/
570QString QDBusArgument::currentSignature() const
571{
572 if (!d)
573 return QString();
574 if (d->direction == QDBusArgumentPrivate::Demarshalling)
575 return d->demarshaller()->currentSignature();
576 else
577 return d->marshaller()->currentSignature();
578}
579
580/*!
581 \since 4.5
582 Returns the classification of the current element type. If an
583 error decoding the type occurs or if we're at the end of the
584 argument, this function returns QDBusArgument::UnknownType.
585
586 This function only makes sense when demarshalling arguments. If it
587 is used while marshalling, it will always return UnknownType.
588*/
589QDBusArgument::ElementType QDBusArgument::currentType() const
590{
591 if (!d)
592 return UnknownType;
593 if (d->direction == QDBusArgumentPrivate::Demarshalling)
594 return d->demarshaller()->currentType();
595 return UnknownType;
596}
597
598/*!
599 Extracts one D-BUS primitive argument of type \c{BYTE} from the
600 D-BUS stream and puts it into \a arg.
601*/
602const QDBusArgument &QDBusArgument::operator>>(uchar &arg) const
603{
604 if (QDBusArgumentPrivate::checkReadAndDetach(d))
605 arg = d->demarshaller()->toByte();
606 else
607 arg = 0;
608 return *this;
609}
610
611/*!
612 \overload
613 Extracts one D-Bus primitive argument of type \c{BOOLEAN} from the
614 D-Bus stream.
615*/
616const QDBusArgument &QDBusArgument::operator>>(bool &arg) const
617{
618 if (QDBusArgumentPrivate::checkReadAndDetach(d))
619 arg = d->demarshaller()->toBool();
620 else
621 arg = false;
622 return *this;
623}
624
625/*!
626 \overload
627 Extracts one D-Bus primitive argument of type \c{UINT16} from the
628 D-Bus stream.
629*/
630const QDBusArgument &QDBusArgument::operator>>(ushort &arg) const
631{
632 if (QDBusArgumentPrivate::checkReadAndDetach(d))
633 arg = d->demarshaller()->toUShort();
634 else
635 arg = 0;
636 return *this;
637}
638
639/*!
640 \overload
641 Extracts one D-Bus primitive argument of type \c{INT16} from the
642 D-Bus stream.
643*/
644const QDBusArgument &QDBusArgument::operator>>(short &arg) const
645{
646 if (QDBusArgumentPrivate::checkReadAndDetach(d))
647 arg = d->demarshaller()->toShort();
648 else
649 arg = 0;
650 return *this;
651}
652
653/*!
654 \overload
655 Extracts one D-Bus primitive argument of type \c{INT32} from the
656 D-Bus stream.
657*/
658const QDBusArgument &QDBusArgument::operator>>(int &arg) const
659{
660 if (QDBusArgumentPrivate::checkReadAndDetach(d))
661 arg = d->demarshaller()->toInt();
662 else
663 arg = 0;
664 return *this;
665}
666
667/*!
668 \overload
669 Extracts one D-Bus primitive argument of type \c{UINT32} from the
670 D-Bus stream.
671*/
672const QDBusArgument &QDBusArgument::operator>>(uint &arg) const
673{
674 if (QDBusArgumentPrivate::checkReadAndDetach(d))
675 arg = d->demarshaller()->toUInt();
676 else
677 arg = 0;
678 return *this;
679}
680
681/*!
682 \overload
683 Extracts one D-Bus primitive argument of type \c{INT64} from the
684 D-Bus stream.
685*/
686const QDBusArgument &QDBusArgument::operator>>(qlonglong &arg) const
687{
688 if (QDBusArgumentPrivate::checkReadAndDetach(d))
689 arg = d->demarshaller()->toLongLong();
690 else
691 arg = 0;
692 return *this;
693}
694
695/*!
696 \overload
697 Extracts one D-Bus primitive argument of type \c{UINT64} from the
698 D-Bus stream.
699*/
700const QDBusArgument &QDBusArgument::operator>>(qulonglong &arg) const
701{
702 if (QDBusArgumentPrivate::checkReadAndDetach(d))
703 arg = d->demarshaller()->toULongLong();
704 else
705 arg = 0;
706 return *this;
707}
708
709/*!
710 \overload
711 Extracts one D-Bus primitive argument of type \c{DOUBLE}
712 (double-precision floating pount) from the D-Bus stream.
713*/
714const QDBusArgument &QDBusArgument::operator>>(double &arg) const
715{
716 if (QDBusArgumentPrivate::checkReadAndDetach(d))
717 arg = d->demarshaller()->toDouble();
718 else
719 arg = 0;
720 return *this;
721}
722
723/*!
724 \overload
725 Extracts one D-Bus primitive argument of type \c{STRING} (Unicode
726 character string) from the D-Bus stream.
727*/
728const QDBusArgument &QDBusArgument::operator>>(QString &arg) const
729{
730 if (QDBusArgumentPrivate::checkReadAndDetach(d))
731 arg = d->demarshaller()->toString();
732 return *this;
733}
734
735/*!
736 \overload
737 \internal
738 Extracts one D-Bus primitive argument of type \c{OBJECT_PATH}
739 (D-Bus path to an object) from the D-Bus stream.
740*/
741const QDBusArgument &QDBusArgument::operator>>(QDBusObjectPath &arg) const
742{
743 if (QDBusArgumentPrivate::checkReadAndDetach(d))
744 arg = d->demarshaller()->toObjectPath();
745 return *this;
746}
747
748/*!
749 \overload
750 \internal
751 Extracts one D-Bus primitive argument of type \c{SIGNATURE} (D-Bus
752 type signature) from the D-Bus stream.
753*/
754const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
755{
756 if (QDBusArgumentPrivate::checkReadAndDetach(d))
757 arg = d->demarshaller()->toSignature();
758 return *this;
759}
760
761/*!
762 \overload
763 \since 4.8
764 \internal
765 Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR}
766 (Unix file descriptor) from the D-Bus stream.
767*/
768const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const
769{
770 if (QDBusArgumentPrivate::checkReadAndDetach(d))
771 arg = d->demarshaller()->toUnixFileDescriptor();
772 return *this;
773}
774
775/*!
776 \overload
777 Extracts one D-Bus primitive argument of type \c{VARIANT} from the
778 D-Bus stream.
779
780 A D-Bus variant type can contain any type, including other
781 variants. It is similar to the Qt QVariant type.
782
783 In case the variant contains a type not directly supported by
784 QDBusArgument, the value of the returned QDBusVariant will contain
785 another QDBusArgument. It is your responsibility to further
786 demarshall it into another type.
787*/
788const QDBusArgument &QDBusArgument::operator>>(QDBusVariant &arg) const
789{
790 if (QDBusArgumentPrivate::checkReadAndDetach(d))
791 arg = d->demarshaller()->toVariant();
792 return *this;
793}
794
795/*!
796 \overload
797 Extracts an array of strings from the D-Bus stream and return it
798 as a QStringList.
799
800 QStringList and QByteArray are the only two non-primitive types
801 that are supported directly by QDBusArgument because of their
802 widespread usage in Qt applications.
803
804 Other arrays are supported through compound types in Qt D-Bus.
805*/
806const QDBusArgument &QDBusArgument::operator>>(QStringList &arg) const
807{
808 if (QDBusArgumentPrivate::checkReadAndDetach(d))
809 arg = d->demarshaller()->toStringList();
810 return *this;
811}
812
813/*!
814 \overload
815 Extracts an array of bytes from the D-Bus stream and return it
816 as a QByteArray.
817
818 QStringList and QByteArray are the only two non-primitive types
819 that are supported directly by QDBusArgument because of their
820 widespread usage in Qt applications.
821
822 Other arrays are supported through compound types in Qt D-Bus.
823*/
824const QDBusArgument &QDBusArgument::operator>>(QByteArray &arg) const
825{
826 if (QDBusArgumentPrivate::checkReadAndDetach(d))
827 arg = d->demarshaller()->toByteArray();
828 return *this;
829}
830
831/*!
832 Opens a new D-Bus structure suitable for appending new arguments.
833
834 This function is used usually in \c{operator<<} streaming
835 operators, as in the following example:
836
837 \snippet code/src_qdbus_qdbusargument.cpp 4
838
839 Structures can contain other structures, so the following code is
840 also valid:
841
842 \snippet code/src_qdbus_qdbusargument.cpp 5
843
844 \sa endStructure(), beginArray(), beginMap()
845*/
846void QDBusArgument::beginStructure()
847{
848 if (QDBusArgumentPrivate::checkWrite(d))
849 d = d->marshaller()->beginStructure();
850}
851
852/*!
853 Closes a D-Bus structure opened with beginStructure(). This function must be called
854 same number of times that beginStructure() is called.
855
856 \sa beginStructure(), endArray(), endMap()
857*/
858void QDBusArgument::endStructure()
859{
860 if (QDBusArgumentPrivate::checkWrite(d))
861 d = d->marshaller()->endStructure();
862}
863
864/*!
865 Opens a new D-Bus array suitable for appending elements of meta-type \a id.
866
867 This function is used usually in \c{operator<<} streaming
868 operators, as in the following example:
869
870 \snippet code/src_qdbus_qdbusargument.cpp 6
871
872 If the type you want to marshall is a QList, QVector or any of the
873 Qt's \l {Container Classes} that take one template parameter,
874 you need not declare an \c{operator<<} function for it, since
875 Qt D-Bus provides generic templates to do the job of marshalling
876 the data. The same applies for STL's sequence containers, such
877 as \c {std::list}, \c {std::vector}, etc.
878
879 \sa endArray(), beginStructure(), beginMap()
880*/
881void QDBusArgument::beginArray(int id)
882{
883 if (QDBusArgumentPrivate::checkWrite(d))
884 d = d->marshaller()->beginArray(id);
885}
886
887/*!
888 Closes a D-Bus array opened with beginArray(). This function must be called
889 same number of times that beginArray() is called.
890
891 \sa beginArray(), endStructure(), endMap()
892*/
893void QDBusArgument::endArray()
894{
895 if (QDBusArgumentPrivate::checkWrite(d))
896 d = d->marshaller()->endArray();
897}
898
899/*!
900 Opens a new D-Bus map suitable for
901 appending elements. Maps are containers that associate one entry
902 (the key) to another (the value), such as Qt's QMap or QHash. The
903 ids of the map's key and value meta types must be passed in \a kid
904 and \a vid respectively.
905
906 This function is used usually in \c{operator<<} streaming
907 operators, as in the following example:
908
909 \snippet code/src_qdbus_qdbusargument.cpp 7
910
911 If the type you want to marshall is a QMap or QHash, you need not
912 declare an \c{operator<<} function for it, since Qt D-Bus provides
913 generic templates to do the job of marshalling the data.
914
915 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
916*/
917void QDBusArgument::beginMap(int kid, int vid)
918{
919 if (QDBusArgumentPrivate::checkWrite(d))
920 d = d->marshaller()->beginMap(kid, vid);
921}
922
923/*!
924 Closes a D-Bus map opened with beginMap(). This function must be called
925 same number of times that beginMap() is called.
926
927 \sa beginMap(), endStructure(), endArray()
928*/
929void QDBusArgument::endMap()
930{
931 if (QDBusArgumentPrivate::checkWrite(d))
932 d = d->marshaller()->endMap();
933}
934
935/*!
936 Opens a D-Bus map entry suitable for
937 appending the key and value entries. This function is only valid
938 when a map has been opened with beginMap().
939
940 See beginMap() for an example of usage of this function.
941
942 \sa endMapEntry(), beginMap()
943*/
944void QDBusArgument::beginMapEntry()
945{
946 if (QDBusArgumentPrivate::checkWrite(d))
947 d = d->marshaller()->beginMapEntry();
948}
949
950/*!
951 Closes a D-Bus map entry opened with beginMapEntry(). This function must be called
952 same number of times that beginMapEntry() is called.
953
954 \sa beginMapEntry()
955*/
956void QDBusArgument::endMapEntry()
957{
958 if (QDBusArgumentPrivate::checkWrite(d))
959 d = d->marshaller()->endMapEntry();
960}
961
962/*!
963 Opens a D-Bus structure suitable for extracting elements.
964
965 This function is used usually in \c{operator>>} streaming
966 operators, as in the following example:
967
968 \snippet code/src_qdbus_qdbusargument.cpp 8
969
970 \sa endStructure(), beginArray(), beginMap()
971*/
972void QDBusArgument::beginStructure() const
973{
974 if (QDBusArgumentPrivate::checkReadAndDetach(d))
975 d = d->demarshaller()->beginStructure();
976}
977
978/*!
979 Closes the D-Bus structure and allow extracting of the next element
980 after the structure.
981
982 \sa beginStructure()
983*/
984void QDBusArgument::endStructure() const
985{
986 if (QDBusArgumentPrivate::checkReadAndDetach(d))
987 d = d->demarshaller()->endStructure();
988}
989
990/*!
991 Recurses into the D-Bus array to allow extraction of
992 the array elements.
993
994 This function is used usually in \c{operator>>} streaming
995 operators, as in the following example:
996
997 \snippet code/src_qdbus_qdbusargument.cpp 9
998
999 If the type you want to demarshall is a QList, QVector or any of the
1000 Qt's \l {Container Classes} that take one template parameter, you
1001 need not declare an \c{operator>>} function for it, since Qt D-Bus
1002 provides generic templates to do the job of demarshalling the data.
1003 The same applies for STL's sequence containers, such as \c {std::list},
1004 \c {std::vector}, etc.
1005
1006 \sa atEnd(), beginStructure(), beginMap()
1007*/
1008void QDBusArgument::beginArray() const
1009{
1010 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1011 d = d->demarshaller()->beginArray();
1012}
1013
1014/*!
1015 Closes the D-Bus array and allow extracting of the next element
1016 after the array.
1017
1018 \sa beginArray()
1019*/
1020void QDBusArgument::endArray() const
1021{
1022 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1023 d = d->demarshaller()->endArray();
1024}
1025
1026/*!
1027 Recurses into the D-Bus map to allow extraction of
1028 the map's elements.
1029
1030 This function is used usually in \c{operator>>} streaming
1031 operators, as in the following example:
1032
1033 \snippet code/src_qdbus_qdbusargument.cpp 10
1034
1035 If the type you want to demarshall is a QMap or QHash, you need not
1036 declare an \c{operator>>} function for it, since Qt D-Bus provides
1037 generic templates to do the job of demarshalling the data.
1038
1039 \sa endMap(), beginStructure(), beginArray(), beginMapEntry()
1040*/
1041void QDBusArgument::beginMap() const
1042{
1043 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1044 d = d->demarshaller()->beginMap();
1045}
1046
1047/*!
1048 Closes the D-Bus map and allow extracting of the next element
1049 after the map.
1050
1051 \sa beginMap()
1052*/
1053void QDBusArgument::endMap() const
1054{
1055 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1056 d = d->demarshaller()->endMap();
1057}
1058
1059/*!
1060 Recurses into the D-Bus map entry to allow extraction
1061 of the key and value pair.
1062
1063 See beginMap() for an example of how this function is usually used.
1064
1065 \sa endMapEntry(), beginMap()
1066*/
1067void QDBusArgument::beginMapEntry() const
1068{
1069 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1070 d = d->demarshaller()->beginMapEntry();
1071}
1072
1073/*!
1074 Closes the D-Bus map entry and allow extracting of the next element
1075 on the map.
1076
1077 \sa beginMapEntry()
1078*/
1079void QDBusArgument::endMapEntry() const
1080{
1081 if (QDBusArgumentPrivate::checkReadAndDetach(d))
1082 d = d->demarshaller()->endMapEntry();
1083}
1084
1085/*!
1086 Returns \c true if there are no more elements to be extracted from
1087 this QDBusArgument. This function is usually used in QDBusArgument
1088 objects returned from beginMap() and beginArray().
1089*/
1090bool QDBusArgument::atEnd() const
1091{
1092 if (QDBusArgumentPrivate::checkRead(d))
1093 return d->demarshaller()->atEnd();
1094
1095 return true; // at least, stop reading
1096}
1097
1098/*!
1099 \since 4.5
1100
1101 Returns the current argument in the form of a QVariant. Basic
1102 types will be decoded and returned in the QVariant, but for
1103 complex types, this function will return a QDBusArgument object in
1104 the QVariant. It is the caller's responsibility to decode the
1105 argument (for example, by calling asVariant() in it).
1106
1107 For example, if the current argument is an INT32, this function
1108 will return a QVariant with an argument of type QVariant::Int. For
1109 an array of INT32, it will return a QVariant containing a
1110 QDBusArgument.
1111
1112 If an error occurs or if there are no more arguments to decode
1113 (i.e., we are at the end of the argument list), this function will
1114 return an invalid QVariant.
1115
1116 \sa atEnd()
1117*/
1118QVariant QDBusArgument::asVariant() const
1119{
1120 if (QDBusArgumentPrivate::checkRead(d))
1121 return d->demarshaller()->toVariantInternal();
1122
1123 return QVariant();
1124}
1125
1126QT_END_NAMESPACE
1127
1128// for optimization purposes, we include the marshallers here
1129#include "qdbusmarshaller.cpp"
1130#include "qdbusdemarshaller.cpp"
1131
1132QT_BEGIN_NAMESPACE
1133
1134// QDBusArgument operators
1135
1136const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v)
1137{
1138 QDBusVariant dbv;
1139 a >> dbv;
1140 v = dbv.variant();
1141 return a;
1142}
1143
1144// QVariant types
1145#ifndef QDBUS_NO_SPECIALTYPES
1146const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date)
1147{
1148 int y, m, d;
1149 a.beginStructure();
1150 a >> y >> m >> d;
1151 a.endStructure();
1152
1153 if (y != 0 && m != 0 && d != 0)
1154 date.setDate(year: y, month: m, day: d);
1155 else
1156 date = QDate();
1157 return a;
1158}
1159
1160QDBusArgument &operator<<(QDBusArgument &a, const QDate &date)
1161{
1162 a.beginStructure();
1163 if (date.isValid())
1164 a << date.year() << date.month() << date.day();
1165 else
1166 a << 0 << 0 << 0;
1167 a.endStructure();
1168 return a;
1169}
1170
1171const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time)
1172{
1173 int h, m, s, ms;
1174 a.beginStructure();
1175 a >> h >> m >> s >> ms;
1176 a.endStructure();
1177
1178 if (h < 0)
1179 time = QTime();
1180 else
1181 time.setHMS(h, m, s, ms);
1182 return a;
1183}
1184
1185QDBusArgument &operator<<(QDBusArgument &a, const QTime &time)
1186{
1187 a.beginStructure();
1188 if (time.isValid())
1189 a << time.hour() << time.minute() << time.second() << time.msec();
1190 else
1191 a << -1 << -1 << -1 << -1;
1192 a.endStructure();
1193 return a;
1194}
1195
1196const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt)
1197{
1198 QDate date;
1199 QTime time;
1200 int timespec;
1201
1202 a.beginStructure();
1203 a >> date >> time >> timespec;
1204 a.endStructure();
1205
1206 dt = QDateTime(date, time, Qt::TimeSpec(timespec));
1207 return a;
1208}
1209
1210QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt)
1211{
1212 a.beginStructure();
1213 a << dt.date() << dt.time() << int(dt.timeSpec());
1214 a.endStructure();
1215 return a;
1216}
1217
1218const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect)
1219{
1220 int x, y, width, height;
1221 a.beginStructure();
1222 a >> x >> y >> width >> height;
1223 a.endStructure();
1224
1225 rect.setRect(ax: x, ay: y, aw: width, ah: height);
1226 return a;
1227}
1228
1229QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect)
1230{
1231 a.beginStructure();
1232 a << rect.x() << rect.y() << rect.width() << rect.height();
1233 a.endStructure();
1234
1235 return a;
1236}
1237
1238const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect)
1239{
1240 double x, y, width, height;
1241 a.beginStructure();
1242 a >> x >> y >> width >> height;
1243 a.endStructure();
1244
1245 rect.setRect(ax: qreal(x), ay: qreal(y), aaw: qreal(width), aah: qreal(height));
1246 return a;
1247}
1248
1249QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect)
1250{
1251 a.beginStructure();
1252 a << double(rect.x()) << double(rect.y()) << double(rect.width()) << double(rect.height());
1253 a.endStructure();
1254
1255 return a;
1256}
1257
1258const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size)
1259{
1260 a.beginStructure();
1261 a >> size.rwidth() >> size.rheight();
1262 a.endStructure();
1263
1264 return a;
1265}
1266
1267QDBusArgument &operator<<(QDBusArgument &a, const QSize &size)
1268{
1269 a.beginStructure();
1270 a << size.width() << size.height();
1271 a.endStructure();
1272
1273 return a;
1274}
1275
1276const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size)
1277{
1278 double width, height;
1279 a.beginStructure();
1280 a >> width >> height;
1281 a.endStructure();
1282
1283 size.setWidth(qreal(width));
1284 size.setHeight(qreal(height));
1285 return a;
1286}
1287
1288QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size)
1289{
1290 a.beginStructure();
1291 a << double(size.width()) << double(size.height());
1292 a.endStructure();
1293
1294 return a;
1295}
1296
1297const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt)
1298{
1299 a.beginStructure();
1300 a >> pt.rx() >> pt.ry();
1301 a.endStructure();
1302
1303 return a;
1304}
1305
1306QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt)
1307{
1308 a.beginStructure();
1309 a << pt.x() << pt.y();
1310 a.endStructure();
1311
1312 return a;
1313}
1314
1315const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt)
1316{
1317 double x, y;
1318 a.beginStructure();
1319 a >> x >> y;
1320 a.endStructure();
1321
1322 pt.setX(qreal(x));
1323 pt.setY(qreal(y));
1324 return a;
1325}
1326
1327QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt)
1328{
1329 a.beginStructure();
1330 a << double(pt.x()) << double(pt.y());
1331 a.endStructure();
1332
1333 return a;
1334}
1335
1336const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line)
1337{
1338 QPoint p1, p2;
1339 a.beginStructure();
1340 a >> p1 >> p2;
1341 a.endStructure();
1342
1343 line = QLine(p1, p2);
1344 return a;
1345}
1346
1347QDBusArgument &operator<<(QDBusArgument &a, const QLine &line)
1348{
1349 a.beginStructure();
1350 a << line.p1() << line.p2();
1351 a.endStructure();
1352
1353 return a;
1354}
1355
1356const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line)
1357{
1358 QPointF p1, p2;
1359 a.beginStructure();
1360 a >> p1 >> p2;
1361 a.endStructure();
1362
1363 line = QLineF(p1, p2);
1364 return a;
1365}
1366
1367QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line)
1368{
1369 a.beginStructure();
1370 a << line.p1() << line.p2();
1371 a.endStructure();
1372
1373 return a;
1374}
1375#endif
1376
1377/*!
1378 \fn void QDBusArgument::swap(QDBusArgument &other)
1379
1380 Swaps this QDBusArgument instance with \a other.
1381*/
1382
1383QT_END_NAMESPACE
1384
1385#endif // QT_NO_DBUS
1386

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