1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDBus module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdbusargument_p.h"
43 #include "qdbusconnection.h"
49 static inline T qIterGet(DBusMessageIter *it)
51 // Use a union of expected and largest type q_dbus_message_iter_get_basic
52 // will return to ensure reading the wrong basic type does not result in
55 // The value to be extracted
57 // Largest type that q_dbus_message_iter_get_basic will return
58 // according to dbus_message_iter_get_basic API documentation
59 dbus_uint64_t maxValue;
60 // A pointer to ensure no stack overwrite in case there is a platform
61 // where sizeof(void*) > sizeof(dbus_uint64_t)
65 // Initialize the value in case a narrower type is extracted to it.
66 // Note that the result of extracting a narrower type in place of a wider
67 // one and vice-versa will be platform-dependent.
70 q_dbus_message_iter_get_basic(it, &value);
71 q_dbus_message_iter_next(it);
75 QDBusDemarshaller::~QDBusDemarshaller()
79 inline QString QDBusDemarshaller::currentSignature()
81 char *sig = q_dbus_message_iter_get_signature(&iterator);
82 QString retval = QString::fromUtf8(sig);
88 inline uchar QDBusDemarshaller::toByte()
90 return qIterGet<uchar>(&iterator);
93 inline bool QDBusDemarshaller::toBool()
95 return bool(qIterGet<dbus_bool_t>(&iterator));
98 inline ushort QDBusDemarshaller::toUShort()
100 return qIterGet<dbus_uint16_t>(&iterator);
103 inline short QDBusDemarshaller::toShort()
105 return qIterGet<dbus_int16_t>(&iterator);
108 inline int QDBusDemarshaller::toInt()
110 return qIterGet<dbus_int32_t>(&iterator);
113 inline uint QDBusDemarshaller::toUInt()
115 return qIterGet<dbus_uint32_t>(&iterator);
118 inline qlonglong QDBusDemarshaller::toLongLong()
120 return qIterGet<qlonglong>(&iterator);
123 inline qulonglong QDBusDemarshaller::toULongLong()
125 return qIterGet<qulonglong>(&iterator);
128 inline double QDBusDemarshaller::toDouble()
130 return qIterGet<double>(&iterator);
133 inline QString QDBusDemarshaller::toStringUnchecked()
135 return QString::fromUtf8(qIterGet<char *>(&iterator));
138 inline QString QDBusDemarshaller::toString()
140 if (isCurrentTypeStringLike())
141 return toStringUnchecked();
146 inline QDBusObjectPath QDBusDemarshaller::toObjectPathUnchecked()
148 return QDBusObjectPath(QString::fromUtf8(qIterGet<char *>(&iterator)));
151 inline QDBusObjectPath QDBusDemarshaller::toObjectPath()
153 if (isCurrentTypeStringLike())
154 return toObjectPathUnchecked();
156 return QDBusObjectPath();
159 inline QDBusSignature QDBusDemarshaller::toSignatureUnchecked()
161 return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator)));
164 inline QDBusSignature QDBusDemarshaller::toSignature()
166 if (isCurrentTypeStringLike())
167 return toSignatureUnchecked();
169 return QDBusSignature();
172 inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor()
174 QDBusUnixFileDescriptor fd;
175 fd.giveFileDescriptor(qIterGet<dbus_int32_t>(&iterator));
179 inline QDBusVariant QDBusDemarshaller::toVariant()
181 QDBusDemarshaller sub(capabilities);
182 sub.message = q_dbus_message_ref(message);
183 q_dbus_message_iter_recurse(&iterator, &sub.iterator);
184 q_dbus_message_iter_next(&iterator);
186 return QDBusVariant( sub.toVariantInternal() );
189 QDBusArgument::ElementType QDBusDemarshaller::currentType()
191 switch (q_dbus_message_iter_get_arg_type(&iterator)) {
193 case DBUS_TYPE_INT16:
194 case DBUS_TYPE_UINT16:
195 case DBUS_TYPE_INT32:
196 case DBUS_TYPE_UINT32:
197 case DBUS_TYPE_INT64:
198 case DBUS_TYPE_UINT64:
199 case DBUS_TYPE_BOOLEAN:
200 case DBUS_TYPE_DOUBLE:
201 case DBUS_TYPE_STRING:
202 case DBUS_TYPE_OBJECT_PATH:
203 case DBUS_TYPE_SIGNATURE:
204 return QDBusArgument::BasicType;
206 case DBUS_TYPE_VARIANT:
207 return QDBusArgument::VariantType;
209 case DBUS_TYPE_ARRAY:
210 switch (q_dbus_message_iter_get_element_type(&iterator)) {
212 case DBUS_TYPE_STRING:
213 // QByteArray and QStringList
214 return QDBusArgument::BasicType;
215 case DBUS_TYPE_DICT_ENTRY:
216 return QDBusArgument::MapType;
218 return QDBusArgument::ArrayType;
221 case DBUS_TYPE_STRUCT:
222 return QDBusArgument::StructureType;
223 case DBUS_TYPE_DICT_ENTRY:
224 return QDBusArgument::MapEntryType;
226 case DBUS_TYPE_UNIX_FD:
227 return capabilities & QDBusConnection::UnixFileDescriptorPassing ?
228 QDBusArgument::BasicType : QDBusArgument::UnknownType;
230 case DBUS_TYPE_INVALID:
231 return QDBusArgument::UnknownType;
234 // qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
235 // q_dbus_message_iter_get_arg_type(&iterator),
236 // q_dbus_message_iter_get_arg_type(&iterator));
238 return QDBusArgument::UnknownType;
241 QVariant QDBusDemarshaller::toVariantInternal()
243 switch (q_dbus_message_iter_get_arg_type(&iterator)) {
245 return QVariant::fromValue(toByte());
246 case DBUS_TYPE_INT16:
247 return QVariant::fromValue(toShort());
248 case DBUS_TYPE_UINT16:
249 return QVariant::fromValue(toUShort());
250 case DBUS_TYPE_INT32:
252 case DBUS_TYPE_UINT32:
254 case DBUS_TYPE_DOUBLE:
256 case DBUS_TYPE_BOOLEAN:
258 case DBUS_TYPE_INT64:
260 case DBUS_TYPE_UINT64:
261 return toULongLong();
262 case DBUS_TYPE_STRING:
263 return toStringUnchecked();
264 case DBUS_TYPE_OBJECT_PATH:
265 return QVariant::fromValue(toObjectPathUnchecked());
266 case DBUS_TYPE_SIGNATURE:
267 return QVariant::fromValue(toSignatureUnchecked());
268 case DBUS_TYPE_VARIANT:
269 return QVariant::fromValue(toVariant());
271 case DBUS_TYPE_ARRAY:
272 switch (q_dbus_message_iter_get_element_type(&iterator)) {
275 return toByteArrayUnchecked();
276 case DBUS_TYPE_STRING:
277 return toStringListUnchecked();
278 case DBUS_TYPE_DICT_ENTRY:
279 return QVariant::fromValue(duplicate());
282 return QVariant::fromValue(duplicate());
285 case DBUS_TYPE_STRUCT:
286 return QVariant::fromValue(duplicate());
288 case DBUS_TYPE_UNIX_FD:
289 if (capabilities & QDBusConnection::UnixFileDescriptorPassing)
290 return QVariant::fromValue(toUnixFileDescriptor());
294 // qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
295 // q_dbus_message_iter_get_arg_type(&iterator),
296 // q_dbus_message_iter_get_arg_type(&iterator));
298 ptr += q_dbus_message_iter_get_arg_type(&iterator);
299 q_dbus_message_iter_next(&iterator);
301 // I hope you never dereference this pointer!
302 return QVariant::fromValue<void *>(ptr);
307 bool QDBusDemarshaller::isCurrentTypeStringLike()
309 const int type = q_dbus_message_iter_get_arg_type(&iterator);
311 case DBUS_TYPE_STRING: //FALLTHROUGH
312 case DBUS_TYPE_OBJECT_PATH: //FALLTHROUGH
313 case DBUS_TYPE_SIGNATURE:
320 QStringList QDBusDemarshaller::toStringListUnchecked()
324 QDBusDemarshaller sub(capabilities);
325 q_dbus_message_iter_recurse(&iterator, &sub.iterator);
326 q_dbus_message_iter_next(&iterator);
328 list.append(sub.toStringUnchecked());
333 QStringList QDBusDemarshaller::toStringList()
335 if (q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_ARRAY
336 && q_dbus_message_iter_get_element_type(&iterator) == DBUS_TYPE_STRING)
337 return toStringListUnchecked();
339 return QStringList();
342 QByteArray QDBusDemarshaller::toByteArrayUnchecked()
345 q_dbus_message_iter_recurse(&iterator, &sub);
346 q_dbus_message_iter_next(&iterator);
349 q_dbus_message_iter_get_fixed_array(&sub,&data,&len);
350 return QByteArray(data,len);
353 QByteArray QDBusDemarshaller::toByteArray()
355 if (q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_ARRAY
356 && q_dbus_message_iter_get_element_type(&iterator) == DBUS_TYPE_BYTE) {
357 return toByteArrayUnchecked();
362 bool QDBusDemarshaller::atEnd()
364 // dbus_message_iter_has_next is broken if the list has one single element
365 return q_dbus_message_iter_get_arg_type(&iterator) == DBUS_TYPE_INVALID;
368 inline QDBusDemarshaller *QDBusDemarshaller::beginStructure()
370 return beginCommon();
373 inline QDBusDemarshaller *QDBusDemarshaller::beginArray()
375 return beginCommon();
378 inline QDBusDemarshaller *QDBusDemarshaller::beginMap()
380 return beginCommon();
383 inline QDBusDemarshaller *QDBusDemarshaller::beginMapEntry()
385 return beginCommon();
388 QDBusDemarshaller *QDBusDemarshaller::beginCommon()
390 QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
392 d->message = q_dbus_message_ref(message);
395 q_dbus_message_iter_recurse(&iterator, &d->iterator);
396 q_dbus_message_iter_next(&iterator);
400 inline QDBusDemarshaller *QDBusDemarshaller::endStructure()
405 inline QDBusDemarshaller *QDBusDemarshaller::endArray()
410 inline QDBusDemarshaller *QDBusDemarshaller::endMap()
415 inline QDBusDemarshaller *QDBusDemarshaller::endMapEntry()
420 QDBusDemarshaller *QDBusDemarshaller::endCommon()
422 QDBusDemarshaller *retval = parent;
427 QDBusArgument QDBusDemarshaller::duplicate()
429 QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
430 d->iterator = iterator;
431 d->message = q_dbus_message_ref(message);
433 q_dbus_message_iter_next(&iterator);
434 return QDBusArgumentPrivate::create(d);