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 
59 QT_BEGIN_NAMESPACE
60 
~QDBusArgumentPrivate()61 QDBusArgumentPrivate::~QDBusArgumentPrivate()
62 {
63     if (message)
64         q_dbus_message_unref(message);
65 }
66 
createSignature(int id)67 QByteArray 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, v.userType(), 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(QString::fromLatin1(signature))) {
88         qWarning("QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' "
89                  "(Did you forget to call beginStructure() ?)",
90                  QMetaType::typeName(id),
91                  signature.isEmpty() ? "<empty>" : signature.constData());
92         return "";
93     } else if ((signature.at(0) != DBUS_TYPE_ARRAY && signature.at(0) != DBUS_STRUCT_BEGIN_CHAR) ||
94                (signature.at(0) == DBUS_TYPE_ARRAY && (signature.at(1) == DBUS_TYPE_BYTE ||
95                                                        signature.at(1) == DBUS_TYPE_STRING))) {
96         qWarning("QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) "
97                  "(Did you forget to call beginStructure() ?)",
98                  QMetaType::typeName(id),
99                  signature.constData(),
100                  QMetaType::typeName(QDBusMetaType::signatureToType(signature)));
101         return "";
102     }
103     return signature;
104 }
105 
checkWrite(QDBusArgumentPrivate * & d)106 bool 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(d->message);
117             q_dbus_message_iter_init_append(dd->message, &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("QDBusArgument: write from a read-only object");
130 #endif
131     return false;
132 }
133 
checkRead(QDBusArgumentPrivate * d)134 bool 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("QDBusArgument: read from a write-only object");
145 #endif
146 
147     return false;
148 }
149 
checkReadAndDetach(QDBusArgumentPrivate * & d)150 bool 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(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 */
QDBusArgument()290 QDBusArgument::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(dd->message, &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 */
QDBusArgument(const QDBusArgument & other)312 QDBusArgument::QDBusArgument(const QDBusArgument &other)
313     : d(other.d)
314 {
315     if (d)
316         d->ref.ref();
317 }
318 
319 /*!
320     \internal
321 */
QDBusArgument(QDBusArgumentPrivate * dd)322 QDBusArgument::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 */
operator =(const QDBusArgument & other)334 QDBusArgument &QDBusArgument::operator=(const QDBusArgument &other)
335 {
336     qAtomicAssign(d, other.d);
337     return *this;
338 }
339 
340 /*!
341     Disposes of the resources associated with this QDBusArgument
342     object.
343 */
~QDBusArgument()344 QDBusArgument::~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 */
operator <<(uchar arg)353 QDBusArgument &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 */
operator <<(bool arg)364 QDBusArgument &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 */
operator <<(short arg)375 QDBusArgument &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 */
operator <<(ushort arg)386 QDBusArgument &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 */
operator <<(int arg)397 QDBusArgument &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 */
operator <<(uint arg)408 QDBusArgument &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 */
operator <<(qlonglong arg)419 QDBusArgument &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 */
operator <<(qulonglong arg)430 QDBusArgument &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 */
operator <<(double arg)442 QDBusArgument &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 */
operator <<(const QString & arg)454 QDBusArgument &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 */
operator <<(const QDBusObjectPath & arg)467 QDBusArgument &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 */
operator <<(const QDBusSignature & arg)480 QDBusArgument &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 */
operator <<(const QDBusUnixFileDescriptor & arg)494 QDBusArgument &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 */
operator <<(const QDBusVariant & arg)508 QDBusArgument &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 */
operator <<(const QStringList & arg)526 QDBusArgument &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 */
operator <<(const QByteArray & arg)544 QDBusArgument &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 */
appendVariant(const QVariant & v)559 void QDBusArgument::appendVariant(const QVariant &v)
560 {
561     if (QDBusArgumentPrivate::checkWrite(d))
562         d->marshaller()->appendVariantInternal(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 */
currentSignature() const570 QString 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 */
currentType() const589 QDBusArgument::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 */
operator >>(uchar & arg) const602 const 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 */
operator >>(bool & arg) const616 const 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 */
operator >>(ushort & arg) const630 const 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 */
operator >>(short & arg) const644 const 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 */
operator >>(int & arg) const658 const 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 */
operator >>(uint & arg) const672 const 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 */
operator >>(qlonglong & arg) const686 const 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 */
operator >>(qulonglong & arg) const700 const 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 */
operator >>(double & arg) const714 const 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 */
operator >>(QString & arg) const728 const 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 */
operator >>(QDBusObjectPath & arg) const741 const 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 */
operator >>(QDBusSignature & arg) const754 const 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 */
operator >>(QDBusUnixFileDescriptor & arg) const768 const 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 */
operator >>(QDBusVariant & arg) const788 const 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 */
operator >>(QStringList & arg) const806 const 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 */
operator >>(QByteArray & arg) const824 const 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 */
beginStructure()846 void 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 */
endStructure()858 void 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 */
beginArray(int id)881 void 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 */
endArray()893 void 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 */
beginMap(int kid,int vid)917 void 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 */
endMap()929 void 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 */
beginMapEntry()944 void 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 */
endMapEntry()956 void 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 */
beginStructure() const972 void 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 */
endStructure() const984 void 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 */
beginArray() const1008 void 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 */
endArray() const1020 void 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 */
beginMap() const1041 void 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 */
endMap() const1053 void 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 */
beginMapEntry() const1067 void 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 */
endMapEntry() const1079 void 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 */
atEnd() const1090 bool 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 */
asVariant() const1118 QVariant QDBusArgument::asVariant() const
1119 {
1120     if (QDBusArgumentPrivate::checkRead(d))
1121         return d->demarshaller()->toVariantInternal();
1122 
1123     return QVariant();
1124 }
1125 
1126 QT_END_NAMESPACE
1127 
1128 // for optimization purposes, we include the marshallers here
1129 #include "qdbusmarshaller.cpp"
1130 #include "qdbusdemarshaller.cpp"
1131 
1132 QT_BEGIN_NAMESPACE
1133 
1134 // QDBusArgument operators
1135 
operator >>(const QDBusArgument & a,QVariant & v)1136 const 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
operator >>(const QDBusArgument & a,QDate & date)1146 const 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(y, m, d);
1155     else
1156         date = QDate();
1157     return a;
1158 }
1159 
operator <<(QDBusArgument & a,const QDate & date)1160 QDBusArgument &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 
operator >>(const QDBusArgument & a,QTime & time)1171 const 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 
operator <<(QDBusArgument & a,const QTime & time)1185 QDBusArgument &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 
operator >>(const QDBusArgument & a,QDateTime & dt)1196 const 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 
operator <<(QDBusArgument & a,const QDateTime & dt)1210 QDBusArgument &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 
operator >>(const QDBusArgument & a,QRect & rect)1218 const 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(x, y, width, height);
1226     return a;
1227 }
1228 
operator <<(QDBusArgument & a,const QRect & rect)1229 QDBusArgument &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 
operator >>(const QDBusArgument & a,QRectF & rect)1238 const 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(qreal(x), qreal(y), qreal(width), qreal(height));
1246     return a;
1247 }
1248 
operator <<(QDBusArgument & a,const QRectF & rect)1249 QDBusArgument &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 
operator >>(const QDBusArgument & a,QSize & size)1258 const 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 
operator <<(QDBusArgument & a,const QSize & size)1267 QDBusArgument &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 
operator >>(const QDBusArgument & a,QSizeF & size)1276 const 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 
operator <<(QDBusArgument & a,const QSizeF & size)1288 QDBusArgument &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 
operator >>(const QDBusArgument & a,QPoint & pt)1297 const 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 
operator <<(QDBusArgument & a,const QPoint & pt)1306 QDBusArgument &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 
operator >>(const QDBusArgument & a,QPointF & pt)1315 const 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 
operator <<(QDBusArgument & a,const QPointF & pt)1327 QDBusArgument &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 
operator >>(const QDBusArgument & a,QLine & line)1336 const 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 
operator <<(QDBusArgument & a,const QLine & line)1347 QDBusArgument &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 
operator >>(const QDBusArgument & a,QLineF & line)1356 const 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 
operator <<(QDBusArgument & a,const QLineF & line)1367 QDBusArgument &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 
1383 QT_END_NAMESPACE
1384 
1385 #endif // QT_NO_DBUS
1386