1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDBus module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** 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 "qdbusmessage.h"
53 #include "qdbusunixfiledescriptor.h"
54 #include "qdbusutil_p.h"
55 #include "qdbusmetatype_p.h"
56 #include "qdbusargument_p.h"
60 #ifndef DBUS_TYPE_UNIX_FD
61 # define DBUS_TYPE_UNIX_FD int('h')
62 # define DBUS_TYPE_UNIX_FD_AS_STRING "h"
65 Q_DECLARE_METATYPE(QList<bool>)
66 Q_DECLARE_METATYPE(QList<short>)
67 Q_DECLARE_METATYPE(QList<ushort>)
68 Q_DECLARE_METATYPE(QList<int>)
69 Q_DECLARE_METATYPE(QList<uint>)
70 Q_DECLARE_METATYPE(QList<qlonglong>)
71 Q_DECLARE_METATYPE(QList<qulonglong>)
72 Q_DECLARE_METATYPE(QList<double>)
76 class QDBusCustomTypeInfo
79 QDBusCustomTypeInfo() : signature(0, '\0'), marshall(0), demarshall(0)
83 // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
85 QDBusMetaType::MarshallFunction marshall;
86 QDBusMetaType::DemarshallFunction demarshall;
90 inline static void registerHelper(T * = 0)
92 void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>;
93 void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>;
94 QDBusMetaType::registerMarshallOperators(qMetaTypeId<T>(),
95 reinterpret_cast<QDBusMetaType::MarshallFunction>(mf),
96 reinterpret_cast<QDBusMetaType::DemarshallFunction>(df));
99 int QDBusMetaTypeId::message;
100 int QDBusMetaTypeId::argument;
101 int QDBusMetaTypeId::variant;
102 int QDBusMetaTypeId::objectpath;
103 int QDBusMetaTypeId::signature;
104 int QDBusMetaTypeId::error;
105 int QDBusMetaTypeId::unixfd;
107 void QDBusMetaTypeId::init()
109 static volatile bool initialized = false;
111 // reentrancy is not a problem since everything else is locked on their own
112 // set the guard variable at the end
114 // register our types with QtCore
115 message = qRegisterMetaType<QDBusMessage>("QDBusMessage");
116 argument = qRegisterMetaType<QDBusArgument>("QDBusArgument");
117 variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
118 objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
119 signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
120 error = qRegisterMetaType<QDBusError>("QDBusError");
121 unixfd = qRegisterMetaType<QDBusUnixFileDescriptor>("QDBusUnixFileDescriptor");
123 #ifndef QDBUS_NO_SPECIALTYPES
124 // and register QtCore's with us
125 registerHelper<QDate>();
126 registerHelper<QTime>();
127 registerHelper<QDateTime>();
128 registerHelper<QRect>();
129 registerHelper<QRectF>();
130 registerHelper<QSize>();
131 registerHelper<QSizeF>();
132 registerHelper<QPoint>();
133 registerHelper<QPointF>();
134 registerHelper<QLine>();
135 registerHelper<QLineF>();
136 registerHelper<QVariantList>();
137 registerHelper<QVariantMap>();
138 registerHelper<QVariantHash>();
140 qDBusRegisterMetaType<QList<bool> >();
141 qDBusRegisterMetaType<QList<short> >();
142 qDBusRegisterMetaType<QList<ushort> >();
143 qDBusRegisterMetaType<QList<int> >();
144 qDBusRegisterMetaType<QList<uint> >();
145 qDBusRegisterMetaType<QList<qlonglong> >();
146 qDBusRegisterMetaType<QList<qulonglong> >();
147 qDBusRegisterMetaType<QList<double> >();
148 qDBusRegisterMetaType<QList<QDBusObjectPath> >();
149 qDBusRegisterMetaType<QList<QDBusSignature> >();
150 qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
157 Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes)
158 Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
162 \brief Meta-type registration system for the QtDBus module.
165 The QDBusMetaType class allows you to register class types for
166 marshalling and demarshalling over D-Bus. D-Bus supports a very
167 limited set of primitive types, but allows one to extend the type
168 system by creating compound types, such as arrays (lists) and
169 structs. In order to use them with QtDBus, those types must be
172 See \l {qdbustypesystem.html}{QtDBus type system} for more
173 information on the type system and how to register additional
176 \sa {qdbustypesystem.html}{QtDBus type system},
177 qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
181 \fn int qDBusRegisterMetaType()
182 \relates QDBusArgument
186 Registers \c{T} with the
187 \l {qdbustypesystem.html}{QtDBus type system} and the Qt \l
188 {QMetaType}{meta-type system}, if it's not already registered.
190 To register a type, it must be declared as a meta-type with the
191 Q_DECLARE_METATYPE() macro, and then registered as in the
194 \snippet doc/src/snippets/code/src_qdbus_qdbusmetatype.cpp 0
196 If \c{T} isn't a type derived from one of
197 Qt's \l{container classes}, the \c{operator<<} and
198 \c{operator>>} streaming operators between \c{T} and QDBusArgument
199 must be already declared. See the \l {qdbustypesystem.html}{QtDBus
200 type system} page for more information on how to declare such
203 This function returns the Qt meta type id for the type (the same
204 value that is returned from qRegisterMetaType()).
206 \sa {qdbustypesystem.html}{QtDBus type system}, qRegisterMetaType(), QMetaType
210 \typedef QDBusMetaType::MarshallFunction
215 \typedef QDBusMetaType::DemarshallFunction
221 Registers the marshalling and demarshalling functions for meta
224 void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
225 DemarshallFunction df)
228 QVector<QDBusCustomTypeInfo> *ct = customTypes();
229 if (id < 0 || !mf || !df || !ct)
232 QWriteLocker locker(customTypesLock());
233 if (id >= ct->size())
235 QDBusCustomTypeInfo &info = (*ct)[id];
237 info.demarshall = df;
242 Executes the marshalling of type \a id (whose data is contained in
243 \a data) to the D-Bus marshalling argument \a arg. Returns true if
244 the marshalling succeeded, or false if an error occurred.
246 bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
248 QDBusMetaTypeId::init();
252 QReadLocker locker(customTypesLock());
253 QVector<QDBusCustomTypeInfo> *ct = customTypes();
254 if (id >= ct->size())
255 return false; // non-existent
257 const QDBusCustomTypeInfo &info = (*ct).at(id);
258 if (!info.marshall) {
259 mf = 0; // make gcc happy
271 Executes the demarshalling of type \a id (whose data will be placed in
272 \a data) from the D-Bus marshalling argument \a arg. Returns true if
273 the demarshalling succeeded, or false if an error occurred.
275 bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
277 QDBusMetaTypeId::init();
279 DemarshallFunction df;
281 QReadLocker locker(customTypesLock());
282 QVector<QDBusCustomTypeInfo> *ct = customTypes();
283 if (id >= ct->size())
284 return false; // non-existent
286 const QDBusCustomTypeInfo &info = (*ct).at(id);
287 if (!info.demarshall) {
288 df = 0; // make gcc happy
291 df = info.demarshall;
294 QDBusArgument copy = arg;
300 \fn QDBusMetaType::signatureToType(const char *signature)
303 Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
306 Note: this function only handles the basic D-Bus types.
308 \sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
309 QVariant::type(), QVariant::userType()
311 int QDBusMetaType::signatureToType(const char *signature)
314 return QVariant::Invalid;
316 QDBusMetaTypeId::init();
317 switch (signature[0])
319 case DBUS_TYPE_BOOLEAN:
320 return QVariant::Bool;
323 return QMetaType::UChar;
325 case DBUS_TYPE_INT16:
326 return QMetaType::Short;
328 case DBUS_TYPE_UINT16:
329 return QMetaType::UShort;
331 case DBUS_TYPE_INT32:
332 return QVariant::Int;
334 case DBUS_TYPE_UINT32:
335 return QVariant::UInt;
337 case DBUS_TYPE_INT64:
338 return QVariant::LongLong;
340 case DBUS_TYPE_UINT64:
341 return QVariant::ULongLong;
343 case DBUS_TYPE_DOUBLE:
344 return QVariant::Double;
346 case DBUS_TYPE_STRING:
347 return QVariant::String;
349 case DBUS_TYPE_OBJECT_PATH:
350 return QDBusMetaTypeId::objectpath;
352 case DBUS_TYPE_SIGNATURE:
353 return QDBusMetaTypeId::signature;
355 case DBUS_TYPE_UNIX_FD:
356 return QDBusMetaTypeId::unixfd;
358 case DBUS_TYPE_VARIANT:
359 return QDBusMetaTypeId::variant;
361 case DBUS_TYPE_ARRAY: // special case
362 switch (signature[1]) {
364 return QVariant::ByteArray;
366 case DBUS_TYPE_STRING:
367 return QVariant::StringList;
369 case DBUS_TYPE_VARIANT:
370 return QVariant::List;
372 case DBUS_TYPE_OBJECT_PATH:
373 return qMetaTypeId<QList<QDBusObjectPath> >();
375 case DBUS_TYPE_SIGNATURE:
376 return qMetaTypeId<QList<QDBusSignature> >();
381 return QVariant::Invalid;
386 \fn QDBusMetaType::typeToSignature(int type)
389 Returns the D-Bus signature equivalent to the supplied meta type id \a type.
391 More types can be registered with the qDBusRegisterMetaType() function.
393 \sa QDBusUtil::isValidSingleSignature(), signatureToType(),
394 QVariant::type(), QVariant::userType()
396 const char *QDBusMetaType::typeToSignature(int type)
398 // check if it's a static type
401 case QMetaType::UChar:
402 return DBUS_TYPE_BYTE_AS_STRING;
405 return DBUS_TYPE_BOOLEAN_AS_STRING;
407 case QMetaType::Short:
408 return DBUS_TYPE_INT16_AS_STRING;
410 case QMetaType::UShort:
411 return DBUS_TYPE_UINT16_AS_STRING;
414 return DBUS_TYPE_INT32_AS_STRING;
417 return DBUS_TYPE_UINT32_AS_STRING;
419 case QVariant::LongLong:
420 return DBUS_TYPE_INT64_AS_STRING;
422 case QVariant::ULongLong:
423 return DBUS_TYPE_UINT64_AS_STRING;
425 case QVariant::Double:
426 return DBUS_TYPE_DOUBLE_AS_STRING;
428 case QVariant::String:
429 return DBUS_TYPE_STRING_AS_STRING;
431 case QVariant::StringList:
432 return DBUS_TYPE_ARRAY_AS_STRING
433 DBUS_TYPE_STRING_AS_STRING; // as
435 case QVariant::ByteArray:
436 return DBUS_TYPE_ARRAY_AS_STRING
437 DBUS_TYPE_BYTE_AS_STRING; // ay
440 QDBusMetaTypeId::init();
441 if (type == QDBusMetaTypeId::variant)
442 return DBUS_TYPE_VARIANT_AS_STRING;
443 else if (type == QDBusMetaTypeId::objectpath)
444 return DBUS_TYPE_OBJECT_PATH_AS_STRING;
445 else if (type == QDBusMetaTypeId::signature)
446 return DBUS_TYPE_SIGNATURE_AS_STRING;
447 else if (type == QDBusMetaTypeId::unixfd)
448 return DBUS_TYPE_UNIX_FD_AS_STRING;
451 QVector<QDBusCustomTypeInfo> *ct = customTypes();
453 QReadLocker locker(customTypesLock());
454 if (type >= ct->size())
455 return 0; // type not registered with us
457 const QDBusCustomTypeInfo &info = (*ct).at(type);
459 if (!info.signature.isNull())
460 return info.signature;
463 return 0; // type not registered with us
466 // call to user code to construct the signature type
467 QDBusCustomTypeInfo *info;
469 // createSignature will never return a null QByteArray
470 // if there was an error, it'll return ""
471 QByteArray signature = QDBusArgumentPrivate::createSignature(type);
474 QWriteLocker locker(customTypesLock());
476 info->signature = signature;
478 return info->signature;