1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtDBus module of the Qt Toolkit.
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 Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
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 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#include "qdbusmetatype.h"
43
#include "qdbusmetatype_p.h"
46
#include "qdbus_symbols_p.h"
48
#include <qbytearray.h>
50
#include <qreadwritelock.h>
53
#include "qdbusargument_p.h"
54
#include "qdbusutil_p.h"
55
#include "qdbusunixfiledescriptor.h"
56
#ifndef QT_BOOTSTRAPPED
57
#include "qdbusmessage.h"
62
#ifndef DBUS_TYPE_UNIX_FD
63
# define DBUS_TYPE_UNIX_FD int('h')
64
# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
69
class QDBusCustomTypeInfo
72
QDBusCustomTypeInfo() : signature(), marshall(0), demarshall(0)
76
// change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
78
QDBusMetaType::MarshallFunction marshall;
79
QDBusMetaType::DemarshallFunction demarshall;
83
inline static void registerHelper(T * = 0)
85
void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>;
86
void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>;
87
QDBusMetaType::registerMarshallOperators(qMetaTypeId<T>(),
88
reinterpret_cast<QDBusMetaType::MarshallFunction>(mf),
89
reinterpret_cast<QDBusMetaType::DemarshallFunction>(df));
92
void QDBusMetaTypeId::init()
94
static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false);
96
// reentrancy is not a problem since everything else is locked on their own
97
// set the guard variable at the end
98
if (!initialized.load()) {
99
// register our types with QtCore (calling qMetaTypeId<T>() does this implicitly)
108
#ifndef QDBUS_NO_SPECIALTYPES
109
// and register QtCore's with us
110
registerHelper<QDate>();
111
registerHelper<QTime>();
112
registerHelper<QDateTime>();
113
registerHelper<QRect>();
114
registerHelper<QRectF>();
115
registerHelper<QSize>();
116
registerHelper<QSizeF>();
117
registerHelper<QPoint>();
118
registerHelper<QPointF>();
119
registerHelper<QLine>();
120
registerHelper<QLineF>();
121
registerHelper<QVariantList>();
122
registerHelper<QVariantMap>();
123
registerHelper<QVariantHash>();
125
qDBusRegisterMetaType<QList<bool> >();
126
qDBusRegisterMetaType<QList<short> >();
127
qDBusRegisterMetaType<QList<ushort> >();
128
qDBusRegisterMetaType<QList<int> >();
129
qDBusRegisterMetaType<QList<uint> >();
130
qDBusRegisterMetaType<QList<qlonglong> >();
131
qDBusRegisterMetaType<QList<qulonglong> >();
132
qDBusRegisterMetaType<QList<double> >();
133
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
134
qDBusRegisterMetaType<QList<QDBusSignature> >();
135
qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
138
initialized.store(true);
142
Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes)
143
Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
148
\brief Meta-type registration system for the QtDBus module.
151
The QDBusMetaType class allows you to register class types for
152
marshalling and demarshalling over D-Bus. D-Bus supports a very
153
limited set of primitive types, but allows one to extend the type
154
system by creating compound types, such as arrays (lists) and
155
structs. In order to use them with QtDBus, those types must be
158
See \l {qdbustypesystem.html}{QtDBus type system} for more
159
information on the type system and how to register additional
162
\sa {qdbustypesystem.html}{QtDBus type system},
163
qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
167
\fn int qDBusRegisterMetaType()
168
\relates QDBusArgument
172
Registers \c{T} with the
173
\l {qdbustypesystem.html}{QtDBus type system} and the Qt \l
174
{QMetaType}{meta-type system}, if it's not already registered.
176
To register a type, it must be declared as a meta-type with the
177
Q_DECLARE_METATYPE() macro, and then registered as in the
180
\snippet code/src_qdbus_qdbusmetatype.cpp 0
182
If \c{T} isn't a type derived from one of
183
Qt's \l{container classes}, the \c{operator<<} and
184
\c{operator>>} streaming operators between \c{T} and QDBusArgument
185
must be already declared. See the \l {qdbustypesystem.html}{QtDBus
186
type system} page for more information on how to declare such
189
This function returns the Qt meta type id for the type (the same
190
value that is returned from qRegisterMetaType()).
192
\sa {qdbustypesystem.html}{QtDBus type system}, qRegisterMetaType(), QMetaType
196
\typedef QDBusMetaType::MarshallFunction
201
\typedef QDBusMetaType::DemarshallFunction
207
Registers the marshalling and demarshalling functions for meta
210
void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
211
DemarshallFunction df)
214
QVector<QDBusCustomTypeInfo> *ct = customTypes();
215
if (id < 0 || !mf || !df || !ct)
218
QWriteLocker locker(customTypesLock());
219
if (id >= ct->size())
221
QDBusCustomTypeInfo &info = (*ct)[id];
223
info.demarshall = df;
228
Executes the marshalling of type \a id (whose data is contained in
229
\a data) to the D-Bus marshalling argument \a arg. Returns true if
230
the marshalling succeeded, or false if an error occurred.
232
bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
234
QDBusMetaTypeId::init();
238
QReadLocker locker(customTypesLock());
239
QVector<QDBusCustomTypeInfo> *ct = customTypes();
240
if (id >= ct->size())
241
return false; // non-existent
243
const QDBusCustomTypeInfo &info = (*ct).at(id);
244
if (!info.marshall) {
245
mf = 0; // make gcc happy
257
Executes the demarshalling of type \a id (whose data will be placed in
258
\a data) from the D-Bus marshalling argument \a arg. Returns true if
259
the demarshalling succeeded, or false if an error occurred.
261
bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
263
QDBusMetaTypeId::init();
265
DemarshallFunction df;
267
QReadLocker locker(customTypesLock());
268
QVector<QDBusCustomTypeInfo> *ct = customTypes();
269
if (id >= ct->size())
270
return false; // non-existent
272
const QDBusCustomTypeInfo &info = (*ct).at(id);
273
if (!info.demarshall) {
274
df = 0; // make gcc happy
277
df = info.demarshall;
279
#ifndef QT_BOOTSTRAPPED
280
QDBusArgument copy = arg;
291
\fn QDBusMetaType::signatureToType(const char *signature)
294
Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
297
Note: this function only handles the basic D-Bus types.
299
\sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
300
QVariant::type(), QVariant::userType()
302
int QDBusMetaType::signatureToType(const char *signature)
305
return QMetaType::UnknownType;
307
QDBusMetaTypeId::init();
308
switch (signature[0])
310
case DBUS_TYPE_BOOLEAN:
311
return QVariant::Bool;
314
return QMetaType::UChar;
316
case DBUS_TYPE_INT16:
317
return QMetaType::Short;
319
case DBUS_TYPE_UINT16:
320
return QMetaType::UShort;
322
case DBUS_TYPE_INT32:
323
return QVariant::Int;
325
case DBUS_TYPE_UINT32:
326
return QVariant::UInt;
328
case DBUS_TYPE_INT64:
329
return QVariant::LongLong;
331
case DBUS_TYPE_UINT64:
332
return QVariant::ULongLong;
334
case DBUS_TYPE_DOUBLE:
335
return QVariant::Double;
337
case DBUS_TYPE_STRING:
338
return QVariant::String;
340
case DBUS_TYPE_OBJECT_PATH:
341
return QDBusMetaTypeId::objectpath();
343
case DBUS_TYPE_SIGNATURE:
344
return QDBusMetaTypeId::signature();
346
case DBUS_TYPE_UNIX_FD:
347
return QDBusMetaTypeId::unixfd();
349
case DBUS_TYPE_VARIANT:
350
return QDBusMetaTypeId::variant();
352
case DBUS_TYPE_ARRAY: // special case
353
switch (signature[1]) {
355
return QVariant::ByteArray;
357
case DBUS_TYPE_STRING:
358
return QVariant::StringList;
360
case DBUS_TYPE_VARIANT:
361
return QVariant::List;
363
case DBUS_TYPE_OBJECT_PATH:
364
return qMetaTypeId<QList<QDBusObjectPath> >();
366
case DBUS_TYPE_SIGNATURE:
367
return qMetaTypeId<QList<QDBusSignature> >();
372
return QMetaType::UnknownType;
377
\fn QDBusMetaType::typeToSignature(int type)
380
Returns the D-Bus signature equivalent to the supplied meta type id \a type.
382
More types can be registered with the qDBusRegisterMetaType() function.
384
\sa QDBusUtil::isValidSingleSignature(), signatureToType(),
385
QVariant::type(), QVariant::userType()
387
const char *QDBusMetaType::typeToSignature(int type)
389
// check if it's a static type
392
case QMetaType::UChar:
393
return DBUS_TYPE_BYTE_AS_STRING;
396
return DBUS_TYPE_BOOLEAN_AS_STRING;
398
case QMetaType::Short:
399
return DBUS_TYPE_INT16_AS_STRING;
401
case QMetaType::UShort:
402
return DBUS_TYPE_UINT16_AS_STRING;
405
return DBUS_TYPE_INT32_AS_STRING;
408
return DBUS_TYPE_UINT32_AS_STRING;
410
case QVariant::LongLong:
411
return DBUS_TYPE_INT64_AS_STRING;
413
case QVariant::ULongLong:
414
return DBUS_TYPE_UINT64_AS_STRING;
416
case QVariant::Double:
417
return DBUS_TYPE_DOUBLE_AS_STRING;
419
case QVariant::String:
420
return DBUS_TYPE_STRING_AS_STRING;
422
case QVariant::StringList:
423
return DBUS_TYPE_ARRAY_AS_STRING
424
DBUS_TYPE_STRING_AS_STRING; // as
426
case QVariant::ByteArray:
427
return DBUS_TYPE_ARRAY_AS_STRING
428
DBUS_TYPE_BYTE_AS_STRING; // ay
431
QDBusMetaTypeId::init();
432
if (type == QDBusMetaTypeId::variant())
433
return DBUS_TYPE_VARIANT_AS_STRING;
434
else if (type == QDBusMetaTypeId::objectpath())
435
return DBUS_TYPE_OBJECT_PATH_AS_STRING;
436
else if (type == QDBusMetaTypeId::signature())
437
return DBUS_TYPE_SIGNATURE_AS_STRING;
438
else if (type == QDBusMetaTypeId::unixfd())
439
return DBUS_TYPE_UNIX_FD_AS_STRING;
442
QVector<QDBusCustomTypeInfo> *ct = customTypes();
444
QReadLocker locker(customTypesLock());
445
if (type >= ct->size())
446
return 0; // type not registered with us
448
const QDBusCustomTypeInfo &info = (*ct).at(type);
450
if (!info.signature.isNull())
451
return info.signature;
454
return 0; // type not registered with us
457
// call to user code to construct the signature type
458
QDBusCustomTypeInfo *info;
460
// createSignature will never return a null QByteArray
461
// if there was an error, it'll return ""
462
QByteArray signature = QDBusArgumentPrivate::createSignature(type);
465
QWriteLocker locker(customTypesLock());
467
info->signature = signature;
469
return info->signature;