Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdbusmarshaller.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
4#include "qdbusargument_p.h"
5#include "qdbusconnection.h"
6#include "qdbusmetatype_p.h"
7#include "qdbusutil_p.h"
8
9#ifndef QT_NO_DBUS
10
12
13using namespace Qt::StringLiterals;
14
15static void qIterAppend(DBusMessageIter *it, QByteArray *ba, int type, const void *arg)
16{
17 if (ba)
18 *ba += char(type);
19 else
20 q_dbus_message_iter_append_basic(it, type, arg);
21}
22
27
28void QDBusMarshaller::unregisteredTypeError(QMetaType id)
29{
30 const char *name = id.name();
31 qWarning("QDBusMarshaller: type '%s' (%d) is not registered with D-Bus. "
32 "Use qDBusRegisterMetaType to register it",
33 name ? name : "", id.id());
34 error("Unregistered type %1 passed in arguments"_L1
35 .arg(QLatin1StringView(id.name())));
36}
37
39{
40 if (message)
41 return QString::fromUtf8(q_dbus_message_get_signature(message));
42 return QString();
43}
44
50
52{
53 dbus_bool_t cast = arg;
54 if (!skipSignature)
56}
57
58inline void QDBusMarshaller::append(short arg)
59{
60 if (!skipSignature)
62}
63
69
75
81
87
93
94inline void QDBusMarshaller::append(double arg)
95{
96 if (!skipSignature)
98}
99
101{
102 QByteArray data = arg.toUtf8();
103 const char *cdata = data.constData();
104 if (!skipSignature)
106}
107
109{
110 QByteArray data = arg.path().toUtf8();
111 if (!ba && data.isEmpty()) {
112 error("Invalid object path passed in arguments"_L1);
113 } else {
114 const char *cdata = data.constData();
115 if (!skipSignature)
117 }
118}
119
121{
122 QByteArray data = arg.signature().toUtf8();
123 if (!ba && data.isNull()) {
124 error("Invalid signature passed in arguments"_L1);
125 } else {
126 const char *cdata = data.constData();
127 if (!skipSignature)
129 }
130}
131
133{
134 int fd = arg.fileDescriptor();
135 if (!ba && fd == -1) {
136 error("Invalid file descriptor passed in arguments"_L1);
137 } else {
138 if (!skipSignature)
140 }
141}
142
144{
145 if (ba) {
146 if (!skipSignature)
148 return;
149 }
150
151 const char* cdata = arg.constData();
152 DBusMessageIter subiterator;
153 q_dbus_message_iter_open_container(&iterator, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING,
154 &subiterator);
155 q_dbus_message_iter_append_fixed_array(&subiterator, DBUS_TYPE_BYTE, &cdata, arg.size());
156 q_dbus_message_iter_close_container(&iterator, &subiterator);
157}
158
160{
161 if (ba) {
162 if (!skipSignature)
164 return true;
165 }
166
167 const QVariant &value = arg.variant();
168 QMetaType id = value.metaType();
169 if (!id.isValid()) {
170 qWarning("QDBusMarshaller: cannot add a null QDBusVariant");
171 error("Invalid QVariant passed in arguments"_L1);
172 return false;
173 }
174
175 QByteArray tmpSignature;
176 const char *signature = nullptr;
177 if (id == QDBusMetaTypeId::argument()) {
178 // take the signature from the QDBusArgument object we're marshalling
179 tmpSignature =
180 qvariant_cast<QDBusArgument>(value).currentSignature().toLatin1();
181 signature = tmpSignature.constData();
182 } else {
183 // take the signatuer from the metatype we're marshalling
184 signature = QDBusMetaType::typeToSignature(id);
185 }
186 if (!signature) {
187 unregisteredTypeError(id);
188 return false;
189 }
190
192 open(sub, DBUS_TYPE_VARIANT, signature);
193 bool isOk = sub.appendVariantInternal(value);
194 // don't call sub.close(): it auto-closes
195
196 return isOk;
197}
198
200{
201 if (ba) {
202 if (!skipSignature)
204 return;
205 }
206
209 for (const QString &s : arg)
210 sub.append(s);
211 // don't call sub.close(): it auto-closes
212}
213
218
220{
221 const char *signature = QDBusMetaType::typeToSignature(id);
222 if (!signature) {
223 unregisteredTypeError(id);
224 return this;
225 }
226
227 return beginCommon(DBUS_TYPE_ARRAY, signature);
228}
229
231{
232 const char *ksignature = QDBusMetaType::typeToSignature(kid);
233 if (!ksignature) {
234 unregisteredTypeError(kid);
235 return this;
236 }
237 if (ksignature[1] != 0 || !QDBusUtil::isValidBasicType(*ksignature)) {
239QT_WARNING_DISABLE_GCC("-Wformat-overflow")
240 qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-Bus map.",
241 kid.name(), kid.id());
243 error("Type %1 passed in arguments cannot be used as a key in a map"_L1
244 .arg(QLatin1StringView(kid.name())));
245 return this;
246 }
247
248 const char *vsignature = QDBusMetaType::typeToSignature(vid);
249 if (!vsignature) {
250 unregisteredTypeError(vid);
251 return this;
252 }
253
254 QByteArray signature;
256 signature += ksignature;
257 signature += vsignature;
259 return beginCommon(DBUS_TYPE_ARRAY, signature);
260}
261
266
267void QDBusMarshaller::open(QDBusMarshaller &sub, int code, const char *signature)
268{
269 sub.parent = this;
270 sub.ba = ba;
271 sub.ok = true;
272 sub.capabilities = capabilities;
273 sub.skipSignature = skipSignature;
274
275 if (ba) {
276 if (!skipSignature) {
277 switch (code) {
278 case DBUS_TYPE_ARRAY:
279 *ba += char(code);
280 *ba += signature;
282
284 sub.closeCode = 0;
285 sub.skipSignature = true;
286 break;
287
288 case DBUS_TYPE_STRUCT:
290 sub.closeCode = DBUS_STRUCT_END_CHAR;
291 break;
292 }
293 }
294 } else {
295 q_dbus_message_iter_open_container(&iterator, code, signature, &sub.iterator);
296 }
297}
298
299QDBusMarshaller *QDBusMarshaller::beginCommon(int code, const char *signature)
300{
302 open(*d, code, signature);
303 return d;
304}
305
308
311
314
317
319{
320 QDBusMarshaller *retval = parent;
321 delete this;
322 return retval;
323}
324
326{
327 if (ba) {
328 if (!skipSignature && closeCode)
329 *ba += closeCode;
330 } else if (parent) {
331 q_dbus_message_iter_close_container(&parent->iterator, &iterator);
332 }
333}
334
336{
337 ok = false;
338 if (parent)
339 parent->error(msg);
340 else
341 errorString = msg;
342}
343
345{
346 QMetaType id = arg.metaType();
347 if (!id.isValid()) {
348 qWarning("QDBusMarshaller: cannot add an invalid QVariant");
349 error("Invalid QVariant passed in arguments"_L1);
350 return false;
351 }
352
353 // intercept QDBusArgument parameters here
354 if (id == QDBusMetaTypeId::argument()) {
355 QDBusArgument dbusargument = qvariant_cast<QDBusArgument>(arg);
357 if (!d->message)
358 return false; // can't append this one...
359
361 demarshaller.message = q_dbus_message_ref(d->message);
362
363 if (d->direction == Direction::Demarshalling) {
364 // it's demarshalling; just copy
366 } else {
367 // it's marshalling; start over
368 if (!q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
369 return false; // error!
370 }
371
373 }
374
375 const char *signature = QDBusMetaType::typeToSignature(id);
376 if (!signature) {
377 unregisteredTypeError(id);
378 return false;
379 }
380
381 switch (*signature) {
382#ifdef __OPTIMIZE__
383 case DBUS_TYPE_BYTE:
384 case DBUS_TYPE_INT16:
385 case DBUS_TYPE_UINT16:
386 case DBUS_TYPE_INT32:
387 case DBUS_TYPE_UINT32:
388 case DBUS_TYPE_INT64:
389 case DBUS_TYPE_UINT64:
390 case DBUS_TYPE_DOUBLE:
391 qIterAppend(&iterator, ba, *signature, arg.constData());
392 return true;
394 append( arg.toBool() );
395 return true;
396#else
397 case DBUS_TYPE_BYTE:
398 append( qvariant_cast<uchar>(arg) );
399 return true;
401 append( arg.toBool() );
402 return true;
403 case DBUS_TYPE_INT16:
404 append( qvariant_cast<short>(arg) );
405 return true;
406 case DBUS_TYPE_UINT16:
407 append( qvariant_cast<ushort>(arg) );
408 return true;
409 case DBUS_TYPE_INT32:
410 append( static_cast<dbus_int32_t>(arg.toInt()) );
411 return true;
412 case DBUS_TYPE_UINT32:
413 append( static_cast<dbus_uint32_t>(arg.toUInt()) );
414 return true;
415 case DBUS_TYPE_INT64:
416 append( arg.toLongLong() );
417 return true;
418 case DBUS_TYPE_UINT64:
419 append( arg.toULongLong() );
420 return true;
421 case DBUS_TYPE_DOUBLE:
422 append( arg.toDouble() );
423 return true;
424#endif
425
426 case DBUS_TYPE_STRING:
427 append( arg.toString() );
428 return true;
430 append( qvariant_cast<QDBusObjectPath>(arg) );
431 return true;
433 append( qvariant_cast<QDBusSignature>(arg) );
434 return true;
435
436 // compound types:
438 // nested QVariant
439 return append( qvariant_cast<QDBusVariant>(arg) );
440
441 case DBUS_TYPE_ARRAY:
442 // could be many things
443 // find out what kind of array it is
444 switch (arg.metaType().id()) {
445 case QMetaType::QStringList:
446 append( arg.toStringList() );
447 return true;
448
449 case QMetaType::QByteArray:
450 append( arg.toByteArray() );
451 return true;
452
453 default:
454 ;
455 }
457
458 case DBUS_TYPE_STRUCT:
460 return appendRegisteredType( arg );
461
464 qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!");
465 return false;
466
469 append(qvariant_cast<QDBusUnixFileDescriptor>(arg));
470 return true;
471 }
473
474 default:
475 qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-Bus type '%s'",
476 signature);
477 return false;
478 }
479
480 return true;
481}
482
484{
485 ref.ref(); // reference up
487 return QDBusMetaType::marshall(self, arg.metaType(), arg.constData());
488}
489
491{
492 int code = q_dbus_message_iter_get_arg_type(&demarshaller->iterator);
493 if (QDBusUtil::isValidBasicType(code)) {
494 // easy: just append
495 // do exactly like the D-Bus docs suggest
496 // (see apidocs for q_dbus_message_iter_get_basic)
497
499 q_dbus_message_iter_get_basic(&demarshaller->iterator, &value);
500 q_dbus_message_iter_next(&demarshaller->iterator);
501 q_dbus_message_iter_append_basic(&iterator, code, &value);
502 return true;
503 }
504
505 if (code == DBUS_TYPE_ARRAY) {
506 int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator);
507 if (QDBusUtil::isValidFixedType(element) && element != DBUS_TYPE_UNIX_FD) {
508 // another optimization: fixed size arrays
509 // code is exactly like QDBusDemarshaller::toByteArray
511 q_dbus_message_iter_recurse(&demarshaller->iterator, &sub);
512 q_dbus_message_iter_next(&demarshaller->iterator);
513 int len;
514 void* data;
515 q_dbus_message_iter_get_fixed_array(&sub,&data,&len);
516
517 char signature[2] = { char(element), 0 };
518 q_dbus_message_iter_open_container(&iterator, DBUS_TYPE_ARRAY, signature, &sub);
519 q_dbus_message_iter_append_fixed_array(&sub, element, &data, len);
520 q_dbus_message_iter_close_container(&iterator, &sub);
521
522 return true;
523 }
524 }
525
526 // We have to recurse
528
529 QDBusMarshaller mrecursed(capabilities); // create on the stack makes it autoclose
530 QByteArray subSignature;
531 const char *sig = nullptr;
532 if (code == DBUS_TYPE_VARIANT || code == DBUS_TYPE_ARRAY) {
533 subSignature = drecursed->currentSignature().toLatin1();
534 if (!subSignature.isEmpty())
535 sig = subSignature.constData();
536 }
537 open(mrecursed, code, sig);
538
539 while (!drecursed->atEnd()) {
540 if (!mrecursed.appendCrossMarshalling(drecursed)) {
541 delete drecursed;
542 return false;
543 }
544 }
545
546 delete drecursed;
547 return true;
548}
549
551
552#endif // QT_NO_DBUS
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
bool isNull() const noexcept
Returns true if this byte array is null; otherwise returns false.
static QDBusArgument create(QDBusArgumentPrivate *d)
QDBusDemarshaller * demarshaller()
QDBusConnection::ConnectionCapabilities capabilities
static QDBusArgumentPrivate * d(QDBusArgument &q)
\inmodule QtDBus
QDBusDemarshaller * beginCommon()
DBusMessageIter iterator
void append(uchar arg)
QDBusMarshaller * parent
QDBusMarshaller * endMapEntry()
QDBusMarshaller * endCommon()
QDBusMarshaller * endStructure()
void open(QDBusMarshaller &sub, int code, const char *signature)
QString currentSignature()
bool appendVariantInternal(const QVariant &arg)
QDBusMarshaller * beginMap(QMetaType kid, QMetaType vid)
QDBusMarshaller(QDBusConnection::ConnectionCapabilities flags={})
QDBusMarshaller * endMap()
QDBusMarshaller * beginCommon(int code, const char *signature)
QDBusMarshaller * beginMapEntry()
bool appendRegisteredType(const QVariant &arg)
void error(const QString &message)
QDBusMarshaller * beginStructure()
QDBusMarshaller * beginArray(QMetaType id)
bool appendCrossMarshalling(QDBusDemarshaller *arg)
DBusMessageIter iterator
QDBusMarshaller * endArray()
static bool marshall(QDBusArgument &, QMetaType id, const void *data)
static const char * typeToSignature(QMetaType type)
\inmodule QtDBus
\inmodule QtDBus
\inmodule QtDBus
\inmodule QtCore
Definition qmetatype.h:341
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
\inmodule QtCore
Definition qvariant.h:65
quint32 dbus_uint32_t
#define DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_BYTE_AS_STRING
#define DBUS_TYPE_OBJECT_PATH
#define DBUS_TYPE_BYTE
#define DBUS_TYPE_INT16
#define DBUS_TYPE_VARIANT
#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
#define DBUS_TYPE_INT32
#define DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_BOOLEAN
#define DBUS_STRUCT_BEGIN_CHAR
dbus_uint32_t dbus_bool_t
#define DBUS_TYPE_STRING
qint32 dbus_int32_t
#define DBUS_TYPE_ARRAY
#define DBUS_TYPE_ARRAY_AS_STRING
#define DBUS_TYPE_STRING_AS_STRING
#define DBUS_TYPE_INT64
#define DBUS_TYPE_DOUBLE
#define DBUS_TYPE_UINT64
#define DBUS_TYPE_VARIANT_AS_STRING
#define DBUS_TYPE_DICT_ENTRY
#define DBUS_DICT_ENTRY_BEGIN_CHAR
#define DBUS_TYPE_UINT16
#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING
#define DBUS_TYPE_STRUCT
#define DBUS_STRUCT_END_CHAR
#define DBUS_TYPE_UINT32
QSet< QString >::iterator it
QMetaType argument()
bool isValidBasicType(int c)
Returns true if c is a valid, basic D-Bus type.
bool isValidFixedType(int c)
Returns true if c is a valid, fixed D-Bus type.
Combined button and popup list for selecting options.
#define Q_FALLTHROUGH()
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter * sub
static void qIterAppend(DBusMessageIter *it, QByteArray *ba, int type, const void *arg)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
GLenum GLuint id
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint GLsizei const GLchar * message
GLuint64 GLenum GLint fd
GLint ref
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
GLenum GLsizei len
SSL_CTX int void * arg
unsigned char uchar
Definition qtypes.h:32
quint64 qulonglong
Definition qtypes.h:64
unsigned int uint
Definition qtypes.h:34
unsigned short ushort
Definition qtypes.h:33
qint64 qlonglong
Definition qtypes.h:63
QByteArray ba
[0]