bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller) { int code = q_dbus_message_iter_get_arg_type(&demarshaller->iterator); if (QDBusUtil::isValidBasicType(code)) { // easy: just append // do exactly like the D-BUS docs suggest // (see apidocs for q_dbus_message_iter_get_basic) qlonglong value; q_dbus_message_iter_get_basic(&demarshaller->iterator, &value); q_dbus_message_iter_next(&demarshaller->iterator); q_dbus_message_iter_append_basic(&iterator, code, &value); return true; } if (code == DBUS_TYPE_ARRAY) { int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator); if (QDBusUtil::isValidFixedType(element) && element != DBUS_TYPE_UNIX_FD) { // another optimization: fixed size arrays // code is exactly like QDBusDemarshaller::toByteArray DBusMessageIter sub; q_dbus_message_iter_recurse(&demarshaller->iterator, &sub); q_dbus_message_iter_next(&demarshaller->iterator); int len; void* data; q_dbus_message_iter_get_fixed_array(&sub,&data,&len); char signature[2] = { char(element), 0 }; q_dbus_message_iter_open_container(&iterator, DBUS_TYPE_ARRAY, signature, &sub); q_dbus_message_iter_append_fixed_array(&sub, element, &data, len); q_dbus_message_iter_close_container(&iterator, &sub); return true; } } // We have to recurse QDBusDemarshaller *drecursed = demarshaller->beginCommon(); QDBusMarshaller mrecursed(capabilities); // create on the stack makes it autoclose QByteArray subSignature; const char *sig = 0; if (code == DBUS_TYPE_VARIANT || code == DBUS_TYPE_ARRAY) { subSignature = drecursed->currentSignature().toLatin1(); if (!subSignature.isEmpty()) sig = subSignature.constData(); } open(mrecursed, code, sig); while (!drecursed->atEnd()) { if (!mrecursed.appendCrossMarshalling(drecursed)) { delete drecursed; return false; } } delete drecursed; return true; }
static inline T qIterGet(DBusMessageIter *it) { T t; q_dbus_message_iter_get_basic(it, &t); q_dbus_message_iter_next(it); return t; }
static inline T qIterGet(DBusMessageIter *it) { // Use a union of expected and largest type q_dbus_message_iter_get_basic // will return to ensure reading the wrong basic type does not result in // stack overwrite union { // The value to be extracted T t; // Largest type that q_dbus_message_iter_get_basic will return // according to dbus_message_iter_get_basic API documentation dbus_uint64_t maxValue; // A pointer to ensure no stack overwrite in case there is a platform // where sizeof(void*) > sizeof(dbus_uint64_t) void* ptr; } value; // Initialize the value in case a narrower type is extracted to it. // Note that the result of extracting a narrower type in place of a wider // one and vice-versa will be platform-dependent. value.t = T(); q_dbus_message_iter_get_basic(it, &value); q_dbus_message_iter_next(it); return value.t; }
QDBusArgument QDBusDemarshaller::duplicate() { QDBusDemarshaller *d = new QDBusDemarshaller; d->iterator = iterator; d->message = q_dbus_message_ref(message); q_dbus_message_iter_next(&iterator); return QDBusArgumentPrivate::create(d); }
inline QDBusVariant QDBusDemarshaller::toVariant() { QDBusDemarshaller sub; sub.message = q_dbus_message_ref(message); q_dbus_message_iter_recurse(&iterator, &sub.iterator); q_dbus_message_iter_next(&iterator); return QDBusVariant( sub.toVariantInternal() ); }
QByteArray QDBusDemarshaller::toByteArray() { DBusMessageIter sub; q_dbus_message_iter_recurse(&iterator, &sub); q_dbus_message_iter_next(&iterator); int len; char* data; q_dbus_message_iter_get_fixed_array(&sub,&data,&len); return QByteArray(data,len); }
QDBusDemarshaller *QDBusDemarshaller::beginCommon() { QDBusDemarshaller *d = new QDBusDemarshaller; d->parent = this; d->message = q_dbus_message_ref(message); // recurse q_dbus_message_iter_recurse(&iterator, &d->iterator); q_dbus_message_iter_next(&iterator); return d; }
QStringList QDBusDemarshaller::toStringList() { QStringList list; QDBusDemarshaller sub; q_dbus_message_iter_recurse(&iterator, &sub.iterator); q_dbus_message_iter_next(&iterator); while (!sub.atEnd()) list.append(sub.toString()); return list; }
QVariant QDBusDemarshaller::toVariantInternal() { switch (q_dbus_message_iter_get_arg_type(&iterator)) { case DBUS_TYPE_BYTE: return QVariant::fromValue(toByte()); case DBUS_TYPE_INT16: return QVariant::fromValue(toShort()); case DBUS_TYPE_UINT16: return QVariant::fromValue(toUShort()); case DBUS_TYPE_INT32: return toInt(); case DBUS_TYPE_UINT32: return toUInt(); case DBUS_TYPE_DOUBLE: return toDouble(); case DBUS_TYPE_BOOLEAN: return toBool(); case DBUS_TYPE_INT64: return toLongLong(); case DBUS_TYPE_UINT64: return toULongLong(); case DBUS_TYPE_STRING: return toStringUnchecked(); case DBUS_TYPE_OBJECT_PATH: return QVariant::fromValue(toObjectPathUnchecked()); case DBUS_TYPE_SIGNATURE: return QVariant::fromValue(toSignatureUnchecked()); case DBUS_TYPE_VARIANT: return QVariant::fromValue(toVariant()); case DBUS_TYPE_ARRAY: switch (q_dbus_message_iter_get_element_type(&iterator)) { case DBUS_TYPE_BYTE: // QByteArray return toByteArrayUnchecked(); case DBUS_TYPE_STRING: return toStringListUnchecked(); case DBUS_TYPE_DICT_ENTRY: return QVariant::fromValue(duplicate()); default: return QVariant::fromValue(duplicate()); } case DBUS_TYPE_STRUCT: return QVariant::fromValue(duplicate()); case DBUS_TYPE_UNIX_FD: if (capabilities & QDBusConnection::UnixFileDescriptorPassing) return QVariant::fromValue(toUnixFileDescriptor()); // fall through default: // qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", // q_dbus_message_iter_get_arg_type(&iterator), // q_dbus_message_iter_get_arg_type(&iterator)); char *ptr = 0; ptr += q_dbus_message_iter_get_arg_type(&iterator); q_dbus_message_iter_next(&iterator); // I hope you never dereference this pointer! return QVariant::fromValue<void *>(ptr); }; }