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

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