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 "qdbusmetatype.h"
45 #include "qdbus_symbols_p.h"
47 #include <qbytearray.h>
49 #include <qreadwritelock.h>
52 #include "qdbusmetatype_p.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"
67 Q_DECLARE_METATYPE(QList<bool>)
68 Q_DECLARE_METATYPE(QList<short>)
69 Q_DECLARE_METATYPE(QList<ushort>)
70 Q_DECLARE_METATYPE(QList<int>)
71 Q_DECLARE_METATYPE(QList<uint>)
72 Q_DECLARE_METATYPE(QList<qlonglong>)
73 Q_DECLARE_METATYPE(QList<qulonglong>)
74 Q_DECLARE_METATYPE(QList<double>)
78 class QDBusCustomTypeInfo
81 QDBusCustomTypeInfo() : signature(0, '\0'), marshall(0), demarshall(0)
85 // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
87 QDBusMetaType::MarshallFunction marshall;
88 QDBusMetaType::DemarshallFunction demarshall;
92 inline static void registerHelper(T * = 0)
94 void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>;
95 void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>;
96 QDBusMetaType::registerMarshallOperators(qMetaTypeId<T>(),
97 reinterpret_cast<QDBusMetaType::MarshallFunction>(mf),
98 reinterpret_cast<QDBusMetaType::DemarshallFunction>(df));
101 int QDBusMetaTypeId::message;
102 int QDBusMetaTypeId::argument;
103 int QDBusMetaTypeId::variant;
104 int QDBusMetaTypeId::objectpath;
105 int QDBusMetaTypeId::signature;
106 int QDBusMetaTypeId::error;
107 int QDBusMetaTypeId::unixfd;
109 void QDBusMetaTypeId::init()
111 static volatile bool initialized = false;
113 // reentrancy is not a problem since everything else is locked on their own
114 // set the guard variable at the end
116 #ifndef QT_BOOTSTRAPPED
117 // register our types with QtCore
118 message = qRegisterMetaType<QDBusMessage>("QDBusMessage");
119 error = qRegisterMetaType<QDBusError>("QDBusError");
121 argument = qRegisterMetaType<QDBusArgument>("QDBusArgument");
122 variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
123 objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
124 signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
125 unixfd = qRegisterMetaType<QDBusUnixFileDescriptor>("QDBusUnixFileDescriptor");
127 #ifndef QDBUS_NO_SPECIALTYPES
128 // and register QtCore's with us
129 registerHelper<QDate>();
130 registerHelper<QTime>();
131 registerHelper<QDateTime>();
132 registerHelper<QRect>();
133 registerHelper<QRectF>();
134 registerHelper<QSize>();
135 registerHelper<QSizeF>();
136 registerHelper<QPoint>();
137 registerHelper<QPointF>();
138 registerHelper<QLine>();
139 registerHelper<QLineF>();
140 registerHelper<QVariantList>();
141 registerHelper<QVariantMap>();
142 registerHelper<QVariantHash>();
144 qDBusRegisterMetaType<QList<bool> >();
145 qDBusRegisterMetaType<QList<short> >();
146 qDBusRegisterMetaType<QList<ushort> >();
147 qDBusRegisterMetaType<QList<int> >();
148 qDBusRegisterMetaType<QList<uint> >();
149 qDBusRegisterMetaType<QList<qlonglong> >();
150 qDBusRegisterMetaType<QList<qulonglong> >();
151 qDBusRegisterMetaType<QList<double> >();
152 qDBusRegisterMetaType<QList<QDBusObjectPath> >();
153 qDBusRegisterMetaType<QList<QDBusSignature> >();
154 qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
158 const int lastId = qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
159 message = lastId + 1;
166 Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes)
167 Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
171 \brief Meta-type registration system for the QtDBus module.
174 The QDBusMetaType class allows you to register class types for
175 marshalling and demarshalling over D-Bus. D-Bus supports a very
176 limited set of primitive types, but allows one to extend the type
177 system by creating compound types, such as arrays (lists) and
178 structs. In order to use them with QtDBus, those types must be
181 See \l {qdbustypesystem.html}{QtDBus type system} for more
182 information on the type system and how to register additional
185 \sa {qdbustypesystem.html}{QtDBus type system},
186 qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
190 \fn int qDBusRegisterMetaType()
191 \relates QDBusArgument
195 Registers \c{T} with the
196 \l {qdbustypesystem.html}{QtDBus type system} and the Qt \l
197 {QMetaType}{meta-type system}, if it's not already registered.
199 To register a type, it must be declared as a meta-type with the
200 Q_DECLARE_METATYPE() macro, and then registered as in the
203 \snippet doc/src/snippets/code/src_qdbus_qdbusmetatype.cpp 0
205 If \c{T} isn't a type derived from one of
206 Qt's \l{container classes}, the \c{operator<<} and
207 \c{operator>>} streaming operators between \c{T} and QDBusArgument
208 must be already declared. See the \l {qdbustypesystem.html}{QtDBus
209 type system} page for more information on how to declare such
212 This function returns the Qt meta type id for the type (the same
213 value that is returned from qRegisterMetaType()).
215 \sa {qdbustypesystem.html}{QtDBus type system}, qRegisterMetaType(), QMetaType
219 \typedef QDBusMetaType::MarshallFunction
224 \typedef QDBusMetaType::DemarshallFunction
230 Registers the marshalling and demarshalling functions for meta
233 void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
234 DemarshallFunction df)
237 QVector<QDBusCustomTypeInfo> *ct = customTypes();
238 if (id < 0 || !mf || !df || !ct)
241 QWriteLocker locker(customTypesLock());
242 if (id >= ct->size())
244 QDBusCustomTypeInfo &info = (*ct)[id];
246 info.demarshall = df;
251 Executes the marshalling of type \a id (whose data is contained in
252 \a data) to the D-Bus marshalling argument \a arg. Returns true if
253 the marshalling succeeded, or false if an error occurred.
255 bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
257 QDBusMetaTypeId::init();
261 QReadLocker locker(customTypesLock());
262 QVector<QDBusCustomTypeInfo> *ct = customTypes();
263 if (id >= ct->size())
264 return false; // non-existent
266 const QDBusCustomTypeInfo &info = (*ct).at(id);
267 if (!info.marshall) {
268 mf = 0; // make gcc happy
280 Executes the demarshalling of type \a id (whose data will be placed in
281 \a data) from the D-Bus marshalling argument \a arg. Returns true if
282 the demarshalling succeeded, or false if an error occurred.
284 bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
286 QDBusMetaTypeId::init();
288 DemarshallFunction df;
290 QReadLocker locker(customTypesLock());
291 QVector<QDBusCustomTypeInfo> *ct = customTypes();
292 if (id >= ct->size())
293 return false; // non-existent
295 const QDBusCustomTypeInfo &info = (*ct).at(id);
296 if (!info.demarshall) {
297 df = 0; // make gcc happy
300 df = info.demarshall;
302 #ifndef QT_BOOTSTRAPPED
303 QDBusArgument copy = arg;
314 \fn QDBusMetaType::signatureToType(const char *signature)
317 Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
320 Note: this function only handles the basic D-Bus types.
322 \sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
323 QVariant::type(), QVariant::userType()
325 int QDBusMetaType::signatureToType(const char *signature)
328 return QMetaType::UnknownType;
330 QDBusMetaTypeId::init();
331 switch (signature[0])
333 case DBUS_TYPE_BOOLEAN:
334 return QVariant::Bool;
337 return QMetaType::UChar;
339 case DBUS_TYPE_INT16:
340 return QMetaType::Short;
342 case DBUS_TYPE_UINT16:
343 return QMetaType::UShort;
345 case DBUS_TYPE_INT32:
346 return QVariant::Int;
348 case DBUS_TYPE_UINT32:
349 return QVariant::UInt;
351 case DBUS_TYPE_INT64:
352 return QVariant::LongLong;
354 case DBUS_TYPE_UINT64:
355 return QVariant::ULongLong;
357 case DBUS_TYPE_DOUBLE:
358 return QVariant::Double;
360 case DBUS_TYPE_STRING:
361 return QVariant::String;
363 case DBUS_TYPE_OBJECT_PATH:
364 return QDBusMetaTypeId::objectpath;
366 case DBUS_TYPE_SIGNATURE:
367 return QDBusMetaTypeId::signature;
369 case DBUS_TYPE_UNIX_FD:
370 return QDBusMetaTypeId::unixfd;
372 case DBUS_TYPE_VARIANT:
373 return QDBusMetaTypeId::variant;
375 case DBUS_TYPE_ARRAY: // special case
376 switch (signature[1]) {
378 return QVariant::ByteArray;
380 case DBUS_TYPE_STRING:
381 return QVariant::StringList;
383 case DBUS_TYPE_VARIANT:
384 return QVariant::List;
386 case DBUS_TYPE_OBJECT_PATH:
387 return qMetaTypeId<QList<QDBusObjectPath> >();
389 case DBUS_TYPE_SIGNATURE:
390 return qMetaTypeId<QList<QDBusSignature> >();
395 return QMetaType::UnknownType;
400 \fn QDBusMetaType::typeToSignature(int type)
403 Returns the D-Bus signature equivalent to the supplied meta type id \a type.
405 More types can be registered with the qDBusRegisterMetaType() function.
407 \sa QDBusUtil::isValidSingleSignature(), signatureToType(),
408 QVariant::type(), QVariant::userType()
410 const char *QDBusMetaType::typeToSignature(int type)
412 // check if it's a static type
415 case QMetaType::UChar:
416 return DBUS_TYPE_BYTE_AS_STRING;
419 return DBUS_TYPE_BOOLEAN_AS_STRING;
421 case QMetaType::Short:
422 return DBUS_TYPE_INT16_AS_STRING;
424 case QMetaType::UShort:
425 return DBUS_TYPE_UINT16_AS_STRING;
428 return DBUS_TYPE_INT32_AS_STRING;
431 return DBUS_TYPE_UINT32_AS_STRING;
433 case QVariant::LongLong:
434 return DBUS_TYPE_INT64_AS_STRING;
436 case QVariant::ULongLong:
437 return DBUS_TYPE_UINT64_AS_STRING;
439 case QVariant::Double:
440 return DBUS_TYPE_DOUBLE_AS_STRING;
442 case QVariant::String:
443 return DBUS_TYPE_STRING_AS_STRING;
445 case QVariant::StringList:
446 return DBUS_TYPE_ARRAY_AS_STRING
447 DBUS_TYPE_STRING_AS_STRING; // as
449 case QVariant::ByteArray:
450 return DBUS_TYPE_ARRAY_AS_STRING
451 DBUS_TYPE_BYTE_AS_STRING; // ay
454 QDBusMetaTypeId::init();
455 if (type == QDBusMetaTypeId::variant)
456 return DBUS_TYPE_VARIANT_AS_STRING;
457 else if (type == QDBusMetaTypeId::objectpath)
458 return DBUS_TYPE_OBJECT_PATH_AS_STRING;
459 else if (type == QDBusMetaTypeId::signature)
460 return DBUS_TYPE_SIGNATURE_AS_STRING;
461 else if (type == QDBusMetaTypeId::unixfd)
462 return DBUS_TYPE_UNIX_FD_AS_STRING;
465 QVector<QDBusCustomTypeInfo> *ct = customTypes();
467 QReadLocker locker(customTypesLock());
468 if (type >= ct->size())
469 return 0; // type not registered with us
471 const QDBusCustomTypeInfo &info = (*ct).at(type);
473 if (!info.signature.isNull())
474 return info.signature;
477 return 0; // type not registered with us
480 // call to user code to construct the signature type
481 QDBusCustomTypeInfo *info;
483 // createSignature will never return a null QByteArray
484 // if there was an error, it'll return ""
485 QByteArray signature = QDBusArgumentPrivate::createSignature(type);
488 QWriteLocker locker(customTypesLock());
490 info->signature = signature;
492 return info->signature;