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