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
qdbusmetatype.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 <string.h>
10
11#include <qbytearray.h>
12#include <qglobal.h>
13#include <qlist.h>
14#include <qreadwritelock.h>
15#include <qdatetime.h>
16#include <qrect.h>
17#include <qsize.h>
18#include <qpoint.h>
19#include <qline.h>
20
22#include "qdbusutil_p.h"
24#ifndef QT_BOOTSTRAPPED
25#include "qdbusmessage.h"
26#endif
27
28#ifndef QT_NO_DBUS
29
31# define DBUS_TYPE_UNIX_FD int('h')
32# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
33#endif
34
36
38{
39public:
41 { }
42
43 // Suggestion:
44 // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
48};
49
51{
52 Q_CONSTINIT static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false);
53
54 // reentrancy is not a problem since everything else is locked on their own
55 // set the guard variable at the end
56 if (!initialized.loadRelaxed()) {
57 // register our types with Qt Core
58 message().registerType();
59 argument().registerType();
60 variant().registerType();
61 objectpath().registerType();
62 signature().registerType();
63 error().registerType();
64 unixfd().registerType();
65
66#ifndef QDBUS_NO_SPECIALTYPES
67 // and register Qt Core's with us
68 qDBusRegisterMetaType<QDate>();
69 qDBusRegisterMetaType<QTime>();
70 qDBusRegisterMetaType<QDateTime>();
71 qDBusRegisterMetaType<QRect>();
72 qDBusRegisterMetaType<QRectF>();
73 qDBusRegisterMetaType<QSize>();
74 qDBusRegisterMetaType<QSizeF>();
75 qDBusRegisterMetaType<QPoint>();
76 qDBusRegisterMetaType<QPointF>();
77 qDBusRegisterMetaType<QLine>();
78 qDBusRegisterMetaType<QLineF>();
79 qDBusRegisterMetaType<QVariantList>();
80 qDBusRegisterMetaType<QVariantMap>();
81 qDBusRegisterMetaType<QVariantHash>();
82
83 qDBusRegisterMetaType<QList<bool> >();
84 qDBusRegisterMetaType<QList<short> >();
85 qDBusRegisterMetaType<QList<ushort> >();
86 qDBusRegisterMetaType<QList<int> >();
87 qDBusRegisterMetaType<QList<uint> >();
88 qDBusRegisterMetaType<QList<qlonglong> >();
89 qDBusRegisterMetaType<QList<qulonglong> >();
90 qDBusRegisterMetaType<QList<double> >();
91 qDBusRegisterMetaType<QMap<QString, QVariantMap>>();
92
93 // plus lists of our own types
94 qDBusRegisterMetaType<QList<QDBusVariant> >();
95 qDBusRegisterMetaType<QList<QDBusObjectPath> >();
96 qDBusRegisterMetaType<QList<QDBusSignature> >();
97 qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
98#endif
99
100 initialized.storeRelaxed(true);
101 }
102}
103
109
110Q_GLOBAL_STATIC(QDBusCustomTypes, customTypes)
111
112/*!
113 \class QDBusMetaType
114 \inmodule QtDBus
115 \brief Meta-type registration system for the Qt D-Bus module.
116 \internal
117
118 The QDBusMetaType class allows you to register class types for
119 marshalling and demarshalling over D-Bus. D-Bus supports a very
120 limited set of primitive types, but allows one to extend the type
121 system by creating compound types, such as arrays (lists) and
122 structs. In order to use them with Qt D-Bus, those types must be
123 registered.
124
125 See \l {qdbustypesystem.html}{Qt D-Bus Type System} for more
126 information on the type system and how to register additional
127 types.
128
129 \sa {qdbustypesystem.html}{Qt D-Bus Type System},
130 qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
131*/
132
133/*!
134 \fn template<typename T> QMetaType qDBusRegisterMetaType()
135 \relates QDBusArgument
136 \threadsafe
137 \since 4.2
138
139 Registers \c{T} with the
140 \l {qdbustypesystem.html}{Qt D-Bus Type System} and the Qt \l
141 {QMetaType}{meta-type system}, if it's not already registered.
142
143 To register a type, it must be declared as a meta-type with the
144 Q_DECLARE_METATYPE() macro, and then registered as in the
145 following example:
146
147 \snippet code/src_qdbus_qdbusmetatype.cpp 0-0
148 \codeline
149 \snippet code/src_qdbus_qdbusmetatype.cpp 0-1
150
151 If \c{T} isn't one of
152 Qt's \l{container classes}, the \c{operator<<} and
153 \c{operator>>} streaming operators between \c{T} and QDBusArgument
154 must be already declared. See the \l {qdbustypesystem.html}{Qt D-Bus
155 Type System} page for more information on how to declare such
156 types.
157
158 This function returns the Qt meta type id for the type (the same
159 value that is returned from qRegisterMetaType()).
160
161 \note The feature that a \c{T} inheriting a streamable type (including
162 the containers QList, QHash or QMap) can be streamed without providing
163 custom \c{operator<<} and \c{operator>>} is deprecated as of Qt 5.7,
164 because it ignores everything in \c{T} except the base class. There is
165 no diagnostic. You should always provide these operators for all types
166 you wish to stream and not rely on Qt-provided stream operators for
167 base classes.
168
169 \sa {qdbustypesystem.html}{Qt D-Bus Type System}, qRegisterMetaType(), QMetaType
170*/
171
172/*!
173 \typedef QDBusMetaType::MarshallFunction
174 \internal
175*/
176
177/*!
178 \typedef QDBusMetaType::DemarshallFunction
179 \internal
180*/
181
182/*!
183 \internal
184 Registers the marshalling and demarshalling functions for meta
185 type \a metaType.
186*/
187void QDBusMetaType::registerMarshallOperators(QMetaType metaType, MarshallFunction mf,
188 DemarshallFunction df)
189{
190 int id = metaType.id();
191 if (id < 0 || !mf || !df)
192 return; // error!
193
194 auto *ct = customTypes();
195 if (!ct)
196 return;
197
198 QWriteLocker locker(&ct->lock);
199 QDBusCustomTypeInfo &info = ct->hash[id];
200 info.marshall = mf;
201 info.demarshall = df;
202}
203
204/*!
205 \internal
206 Executes the marshalling of type \a metaType (whose data is contained in
207 \a data) to the D-Bus marshalling argument \a arg. Returns \c true if
208 the marshalling succeeded, or false if an error occurred.
209*/
210bool QDBusMetaType::marshall(QDBusArgument &arg, QMetaType metaType, const void *data)
211{
212 auto *ct = customTypes();
213 if (!ct)
214 return false;
215
216 int id = metaType.id();
217 QDBusMetaTypeId::init();
218
219 MarshallFunction mf;
220 {
221 QReadLocker locker(&ct->lock);
222
223 auto it = ct->hash.constFind(id);
224 if (it == ct->hash.cend())
225 return false; // non-existent
226
227 const QDBusCustomTypeInfo &info = *it;
228 if (!info.marshall) {
229 mf = nullptr; // make gcc happy
230 return false;
231 } else
232 mf = info.marshall;
233 }
234
235 mf(arg, data);
236 return true;
237}
238
239/*!
240 \internal
241 Executes the demarshalling of type \a metaType (whose data will be placed in
242 \a data) from the D-Bus marshalling argument \a arg. Returns \c true if
243 the demarshalling succeeded, or false if an error occurred.
244*/
245bool QDBusMetaType::demarshall(const QDBusArgument &arg, QMetaType metaType, void *data)
246{
247 auto *ct = customTypes();
248 if (!ct)
249 return false;
250
251 int id = metaType.id();
252 QDBusMetaTypeId::init();
253
254 DemarshallFunction df;
255 {
256 QReadLocker locker(&ct->lock);
257
258 auto it = ct->hash.constFind(id);
259 if (it == ct->hash.cend())
260 return false; // non-existent
261
262 const QDBusCustomTypeInfo &info = *it;
263 if (!info.demarshall) {
264 df = nullptr; // make gcc happy
265 return false;
266 } else
267 df = info.demarshall;
268 }
269#ifndef QT_BOOTSTRAPPED
270 QDBusArgument copy = arg;
271 df(copy, data);
272#else
273 Q_UNUSED(arg);
274 Q_UNUSED(data);
275 Q_UNUSED(df);
276#endif
277 return true;
278}
279
280/*!
281 \fn QDBusMetaType::signatureToType(const char *signature)
282 \internal
283
284 Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
285 by \a signature.
286
287 Note: this function only handles the basic D-Bus types.
288
289 \sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
290 QVariant::metaType()
291*/
292QMetaType QDBusMetaType::signatureToMetaType(const char *signature)
293{
294 if (!signature)
295 return QMetaType(QMetaType::UnknownType);
296
297 QDBusMetaTypeId::init();
298 switch (signature[0])
299 {
301 return QMetaType(QMetaType::Bool);
302
303 case DBUS_TYPE_BYTE:
304 return QMetaType(QMetaType::UChar);
305
306 case DBUS_TYPE_INT16:
307 return QMetaType(QMetaType::Short);
308
309 case DBUS_TYPE_UINT16:
310 return QMetaType(QMetaType::UShort);
311
312 case DBUS_TYPE_INT32:
313 return QMetaType(QMetaType::Int);
314
315 case DBUS_TYPE_UINT32:
316 return QMetaType(QMetaType::UInt);
317
318 case DBUS_TYPE_INT64:
319 return QMetaType(QMetaType::LongLong);
320
321 case DBUS_TYPE_UINT64:
322 return QMetaType(QMetaType::ULongLong);
323
324 case DBUS_TYPE_DOUBLE:
325 return QMetaType(QMetaType::Double);
326
327 case DBUS_TYPE_STRING:
328 return QMetaType(QMetaType::QString);
329
331 return QDBusMetaTypeId::objectpath();
332
334 return QDBusMetaTypeId::signature();
335
337 return QDBusMetaTypeId::unixfd();
338
340 return QDBusMetaTypeId::variant();
341
342 case DBUS_TYPE_ARRAY: // special case
343 switch (signature[1]) {
344 case DBUS_TYPE_BYTE:
345 return QMetaType(QMetaType::QByteArray);
346
347 case DBUS_TYPE_STRING:
348 return QMetaType(QMetaType::QStringList);
349
351 return QMetaType(QMetaType::QVariantList);
352
354 return QMetaType::fromType<QList<QDBusObjectPath> >();
355
357 return QMetaType::fromType<QList<QDBusSignature> >();
358
359 }
360 Q_FALLTHROUGH();
361 default:
362 return QMetaType(QMetaType::UnknownType);
363 }
364}
365
366/*!
367 \fn QDBusMetaType::registerCustomType(QMetaType type, const QByteArray &signature)
368 \internal
369
370 Registers the meta type \a type to be represeneted by the given D-Bus \a signature.
371
372 This is used in qdbuscpp2xml for custom types which aren't known to the C++ type system.
373*/
374void QDBusMetaType::registerCustomType(QMetaType type, const QByteArray &signature)
375{
376 auto *ct = customTypes();
377 if (!ct)
378 return;
379
380 QWriteLocker locker(&ct->lock);
381 auto &info = ct->hash[type.id()];
382 info.signature = signature;
383 // note how marshall/demarshall are not set, the type is never used at runtime
384}
385
386/*!
387 \fn QDBusMetaType::typeToSignature(int type)
388 \internal
389
390 Returns the D-Bus signature equivalent to the supplied meta type id \a type.
391
392 More types can be registered with the qDBusRegisterMetaType() function.
393
394 \sa QDBusUtil::isValidSingleSignature(), signatureToType(),
395 QVariant::metaType()
396*/
397const char *QDBusMetaType::typeToSignature(QMetaType type)
398{
399 // check if it's a static type
400 switch (type.id())
401 {
402 case QMetaType::UChar:
404
405 case QMetaType::Bool:
407
408 case QMetaType::Short:
410
411 case QMetaType::UShort:
413
414 case QMetaType::Int:
416
417 case QMetaType::UInt:
419
420 case QMetaType::LongLong:
422
423 case QMetaType::ULongLong:
425
426 case QMetaType::Double:
428
429 case QMetaType::QString:
431
432 case QMetaType::QStringList:
435
436 case QMetaType::QByteArray:
439 }
440
441 QDBusMetaTypeId::init();
442 if (type == QDBusMetaTypeId::variant())
444 else if (type == QDBusMetaTypeId::objectpath())
446 else if (type == QDBusMetaTypeId::signature())
448 else if (type == QDBusMetaTypeId::unixfd())
450
451 // try the database
452 auto *ct = customTypes();
453 if (!ct)
454 return nullptr;
455
456 {
457 QReadLocker locker(&ct->lock);
458 auto it = ct->hash.constFind(type.id());
459 if (it == ct->hash.end())
460 return nullptr;
461
462 const QDBusCustomTypeInfo &info = *it;
463
464 if (!info.signature.isNull())
465 return info.signature;
466
467 if (!info.marshall)
468 return nullptr; // type not registered with us
469 }
470
471 // call to user code to construct the signature type
472 QDBusCustomTypeInfo *info;
473 {
474 // createSignature will never return a null QByteArray
475 // if there was an error, it'll return ""
476 QByteArray signature = QDBusArgumentPrivate::createSignature(type);
477
478 // re-acquire lock
479 QWriteLocker locker(&ct->lock);
480 info = &ct->hash[type.id()];
481 info->signature = signature;
482 }
483 return info->signature;
484}
485
486QT_END_NAMESPACE
487
488#endif // QT_NO_DBUS
\inmodule QtCore \reentrant
Definition qdatetime.h:29
Definition qlist.h:80
\inmodule QtCore\reentrant
Definition qpoint.h:231
\inmodule QtCore\reentrant
Definition qpoint.h:29
\inmodule QtCore
Definition qsize.h:26
\inmodule QtCore \reentrant
Definition qdatetime.h:250
#define DBUS_TYPE_UINT64_AS_STRING
#define DBUS_TYPE_UNIX_FD_AS_STRING
#define DBUS_TYPE_BOOLEAN_AS_STRING
#define DBUS_TYPE_INT16_AS_STRING
#define DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_BYTE_AS_STRING
#define DBUS_TYPE_OBJECT_PATH
#define DBUS_TYPE_BYTE
#define DBUS_TYPE_INT64_AS_STRING
#define DBUS_TYPE_DOUBLE_AS_STRING
#define DBUS_TYPE_INT16
#define DBUS_TYPE_VARIANT
#define DBUS_TYPE_INT32
#define DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_INT32_AS_STRING
#define DBUS_TYPE_BOOLEAN
#define DBUS_TYPE_SIGNATURE_AS_STRING
#define DBUS_TYPE_STRING
#define DBUS_TYPE_OBJECT_PATH_AS_STRING
#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_UINT16
#define DBUS_TYPE_UINT32_AS_STRING
#define DBUS_TYPE_UINT32
#define DBUS_TYPE_UINT16_AS_STRING
Q_DBUS_EXPORT void init()
QMetaType unixfd()
QMetaType variant()
QMetaType error()
QMetaType argument()
QMetaType objectpath()
QMetaType message()
QMetaType signature()
QReadWriteLock lock
QHash< int, QDBusCustomTypeInfo > hash