source: trunk/src/dbus/qdbusmetatype.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 13.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtDBus module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdbusmetatype.h"
43
44#include <string.h>
45#include "qdbus_symbols_p.h"
46
47#include <qbytearray.h>
48#include <qglobal.h>
49#include <qreadwritelock.h>
50#include <qvector.h>
51
52#include "qdbusmessage.h"
53#include "qdbusutil_p.h"
54#include "qdbusmetatype_p.h"
55#include "qdbusargument_p.h"
56
57#ifndef QT_NO_DBUS
58
59Q_DECLARE_METATYPE(QList<bool>)
60Q_DECLARE_METATYPE(QList<short>)
61Q_DECLARE_METATYPE(QList<ushort>)
62Q_DECLARE_METATYPE(QList<int>)
63Q_DECLARE_METATYPE(QList<uint>)
64Q_DECLARE_METATYPE(QList<qlonglong>)
65Q_DECLARE_METATYPE(QList<qulonglong>)
66Q_DECLARE_METATYPE(QList<double>)
67
68QT_BEGIN_NAMESPACE
69
70class QDBusCustomTypeInfo
71{
72public:
73 QDBusCustomTypeInfo() : signature(0, '\0'), marshall(0), demarshall(0)
74 { }
75
76 // Suggestion:
77 // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
78 QByteArray signature;
79 QDBusMetaType::MarshallFunction marshall;
80 QDBusMetaType::DemarshallFunction demarshall;
81};
82
83template<typename T>
84inline static void registerHelper(T * = 0)
85{
86 void (*mf)(QDBusArgument &, const T *) = qDBusMarshallHelper<T>;
87 void (*df)(const QDBusArgument &, T *) = qDBusDemarshallHelper<T>;
88 QDBusMetaType::registerMarshallOperators(qMetaTypeId<T>(),
89 reinterpret_cast<QDBusMetaType::MarshallFunction>(mf),
90 reinterpret_cast<QDBusMetaType::DemarshallFunction>(df));
91}
92
93int QDBusMetaTypeId::message;
94int QDBusMetaTypeId::argument;
95int QDBusMetaTypeId::variant;
96int QDBusMetaTypeId::objectpath;
97int QDBusMetaTypeId::signature;
98int QDBusMetaTypeId::error;
99
100void QDBusMetaTypeId::init()
101{
102 static volatile bool initialized = false;
103
104 // reentrancy is not a problem since everything else is locked on their own
105 // set the guard variable at the end
106 if (!initialized) {
107 // register our types with QtCore
108 message = qRegisterMetaType<QDBusMessage>("QDBusMessage");
109 argument = qRegisterMetaType<QDBusArgument>("QDBusArgument");
110 variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
111 objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
112 signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
113 error = qRegisterMetaType<QDBusError>("QDBusError");
114
115#ifndef QDBUS_NO_SPECIALTYPES
116 // and register QtCore's with us
117 registerHelper<QDate>();
118 registerHelper<QTime>();
119 registerHelper<QDateTime>();
120 registerHelper<QRect>();
121 registerHelper<QRectF>();
122 registerHelper<QSize>();
123 registerHelper<QSizeF>();
124 registerHelper<QPoint>();
125 registerHelper<QPointF>();
126 registerHelper<QLine>();
127 registerHelper<QLineF>();
128 registerHelper<QVariantList>();
129 registerHelper<QVariantMap>();
130
131 qDBusRegisterMetaType<QList<bool> >();
132 qDBusRegisterMetaType<QList<short> >();
133 qDBusRegisterMetaType<QList<ushort> >();
134 qDBusRegisterMetaType<QList<int> >();
135 qDBusRegisterMetaType<QList<uint> >();
136 qDBusRegisterMetaType<QList<qlonglong> >();
137 qDBusRegisterMetaType<QList<qulonglong> >();
138 qDBusRegisterMetaType<QList<double> >();
139 qDBusRegisterMetaType<QList<QDBusObjectPath> >();
140 qDBusRegisterMetaType<QList<QDBusSignature> >();
141#endif
142
143 initialized = true;
144 }
145}
146
147Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes)
148Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
149
150/*!
151 \class QDBusMetaType
152 \brief Meta-type registration system for the QtDBus module.
153 \internal
154
155 The QDBusMetaType class allows you to register class types for
156 marshalling and demarshalling over D-Bus. D-Bus supports a very
157 limited set of primitive types, but allows one to extend the type
158 system by creating compound types, such as arrays (lists) and
159 structs. In order to use them with QtDBus, those types must be
160 registered.
161
162 See \l {qdbustypesystem.html}{QtDBus type system} for more
163 information on the type system and how to register additional
164 types.
165
166 \sa {qdbustypesystem.html}{QtDBus type system},
167 qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
168*/
169
170/*!
171 \fn int qDBusRegisterMetaType()
172 \relates QDBusArgument
173 \threadsafe
174 \since 4.2
175
176 Registers \c{T} with the
177 \l {qdbustypesystem.html}{QtDBus type system} and the Qt \l
178 {QMetaType}{meta-type system}, if it's not already registered.
179
180 To register a type, it must be declared as a meta-type with the
181 Q_DECLARE_METATYPE() macro, and then registered as in the
182 following example:
183
184 \snippet doc/src/snippets/code/src_qdbus_qdbusmetatype.cpp 0
185
186 If \c{T} isn't a type derived from one of
187 Qt's \l{container classes}, the \c{operator<<} and
188 \c{operator>>} streaming operators between \c{T} and QDBusArgument
189 must be already declared. See the \l {qdbustypesystem.html}{QtDBus
190 type system} page for more information on how to declare such
191 types.
192
193 This function returns the Qt meta type id for the type (the same
194 value that is returned from qRegisterMetaType()).
195
196 \sa {qdbustypesystem.html}{QtDBus type system}, qRegisterMetaType(), QMetaType
197*/
198
199/*!
200 \typedef QDBusMetaType::MarshallFunction
201 \internal
202*/
203
204/*!
205 \typedef QDBusMetaType::DemarshallFunction
206 \internal
207*/
208
209/*!
210 \internal
211 Registers the marshalling and demarshalling functions for meta
212 type \a id.
213*/
214void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
215 DemarshallFunction df)
216{
217 QByteArray var;
218 QVector<QDBusCustomTypeInfo> *ct = customTypes();
219 if (id < 0 || !mf || !df || !ct)
220 return; // error!
221
222 QWriteLocker locker(customTypesLock());
223 if (id >= ct->size())
224 ct->resize(id + 1);
225 QDBusCustomTypeInfo &info = (*ct)[id];
226 info.marshall = mf;
227 info.demarshall = df;
228}
229
230/*!
231 \internal
232 Executes the marshalling of type \a id (whose data is contained in
233 \a data) to the D-Bus marshalling argument \a arg. Returns true if
234 the marshalling succeeded, or false if an error occurred.
235*/
236bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
237{
238 QDBusMetaTypeId::init();
239
240 MarshallFunction mf;
241 {
242 QReadLocker locker(customTypesLock());
243 QVector<QDBusCustomTypeInfo> *ct = customTypes();
244 if (id >= ct->size())
245 return false; // non-existent
246
247 const QDBusCustomTypeInfo &info = (*ct).at(id);
248 if (!info.marshall) {
249 mf = 0; // make gcc happy
250 return false;
251 } else
252 mf = info.marshall;
253 }
254
255 mf(arg, data);
256 return true;
257}
258
259/*!
260 \internal
261 Executes the demarshalling of type \a id (whose data will be placed in
262 \a data) from the D-Bus marshalling argument \a arg. Returns true if
263 the demarshalling succeeded, or false if an error occurred.
264*/
265bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
266{
267 QDBusMetaTypeId::init();
268
269 DemarshallFunction df;
270 {
271 QReadLocker locker(customTypesLock());
272 QVector<QDBusCustomTypeInfo> *ct = customTypes();
273 if (id >= ct->size())
274 return false; // non-existent
275
276 const QDBusCustomTypeInfo &info = (*ct).at(id);
277 if (!info.demarshall) {
278 df = 0; // make gcc happy
279 return false;
280 } else
281 df = info.demarshall;
282 }
283
284 QDBusArgument copy = arg;
285 df(copy, data);
286 return true;
287}
288
289/*!
290 \fn QDBusMetaType::signatureToType(const char *signature)
291 \internal
292
293 Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
294 by \a signature.
295
296 Note: this function only handles the basic D-Bus types.
297
298 \sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
299 QVariant::type(), QVariant::userType()
300*/
301int QDBusMetaType::signatureToType(const char *signature)
302{
303 if (!signature)
304 return QVariant::Invalid;
305
306 QDBusMetaTypeId::init();
307 switch (signature[0])
308 {
309 case DBUS_TYPE_BOOLEAN:
310 return QVariant::Bool;
311
312 case DBUS_TYPE_BYTE:
313 return QMetaType::UChar;
314
315 case DBUS_TYPE_INT16:
316 return QMetaType::Short;
317
318 case DBUS_TYPE_UINT16:
319 return QMetaType::UShort;
320
321 case DBUS_TYPE_INT32:
322 return QVariant::Int;
323
324 case DBUS_TYPE_UINT32:
325 return QVariant::UInt;
326
327 case DBUS_TYPE_INT64:
328 return QVariant::LongLong;
329
330 case DBUS_TYPE_UINT64:
331 return QVariant::ULongLong;
332
333 case DBUS_TYPE_DOUBLE:
334 return QVariant::Double;
335
336 case DBUS_TYPE_STRING:
337 return QVariant::String;
338
339 case DBUS_TYPE_OBJECT_PATH:
340 return QDBusMetaTypeId::objectpath;
341
342 case DBUS_TYPE_SIGNATURE:
343 return QDBusMetaTypeId::signature;
344
345 case DBUS_TYPE_VARIANT:
346 return QDBusMetaTypeId::variant;
347
348 case DBUS_TYPE_ARRAY: // special case
349 switch (signature[1]) {
350 case DBUS_TYPE_BYTE:
351 return QVariant::ByteArray;
352
353 case DBUS_TYPE_STRING:
354 return QVariant::StringList;
355
356 case DBUS_TYPE_VARIANT:
357 return QVariant::List;
358
359 case DBUS_TYPE_OBJECT_PATH:
360 return qMetaTypeId<QList<QDBusObjectPath> >();
361
362 case DBUS_TYPE_SIGNATURE:
363 return qMetaTypeId<QList<QDBusSignature> >();
364
365 }
366 // fall through
367 default:
368 return QVariant::Invalid;
369 }
370}
371
372/*!
373 \fn QDBusMetaType::typeToSignature(int type)
374 \internal
375
376 Returns the D-Bus signature equivalent to the supplied meta type id \a type.
377
378 More types can be registered with the qDBusRegisterMetaType() function.
379
380 \sa QDBusUtil::isValidSingleSignature(), signatureToType(),
381 QVariant::type(), QVariant::userType()
382*/
383const char *QDBusMetaType::typeToSignature(int type)
384{
385 // check if it's a static type
386 switch (type)
387 {
388 case QMetaType::UChar:
389 return DBUS_TYPE_BYTE_AS_STRING;
390
391 case QVariant::Bool:
392 return DBUS_TYPE_BOOLEAN_AS_STRING;
393
394 case QMetaType::Short:
395 return DBUS_TYPE_INT16_AS_STRING;
396
397 case QMetaType::UShort:
398 return DBUS_TYPE_UINT16_AS_STRING;
399
400 case QVariant::Int:
401 return DBUS_TYPE_INT32_AS_STRING;
402
403 case QVariant::UInt:
404 return DBUS_TYPE_UINT32_AS_STRING;
405
406 case QVariant::LongLong:
407 return DBUS_TYPE_INT64_AS_STRING;
408
409 case QVariant::ULongLong:
410 return DBUS_TYPE_UINT64_AS_STRING;
411
412 case QVariant::Double:
413 return DBUS_TYPE_DOUBLE_AS_STRING;
414
415 case QVariant::String:
416 return DBUS_TYPE_STRING_AS_STRING;
417
418 case QVariant::StringList:
419 return DBUS_TYPE_ARRAY_AS_STRING
420 DBUS_TYPE_STRING_AS_STRING; // as
421
422 case QVariant::ByteArray:
423 return DBUS_TYPE_ARRAY_AS_STRING
424 DBUS_TYPE_BYTE_AS_STRING; // ay
425 }
426
427 QDBusMetaTypeId::init();
428 if (type == QDBusMetaTypeId::variant)
429 return DBUS_TYPE_VARIANT_AS_STRING;
430 else if (type == QDBusMetaTypeId::objectpath)
431 return DBUS_TYPE_OBJECT_PATH_AS_STRING;
432 else if (type == QDBusMetaTypeId::signature)
433 return DBUS_TYPE_SIGNATURE_AS_STRING;
434
435 // try the database
436 QVector<QDBusCustomTypeInfo> *ct = customTypes();
437 {
438 QReadLocker locker(customTypesLock());
439 if (type >= ct->size())
440 return 0; // type not registered with us
441
442 const QDBusCustomTypeInfo &info = (*ct).at(type);
443
444 if (!info.signature.isNull())
445 return info.signature;
446
447 if (!info.marshall)
448 return 0; // type not registered with us
449 }
450
451 // call to user code to construct the signature type
452 QDBusCustomTypeInfo *info;
453 {
454 // createSignature will never return a null QByteArray
455 // if there was an error, it'll return ""
456 QByteArray signature = QDBusArgumentPrivate::createSignature(type);
457
458 // re-acquire lock
459 QWriteLocker locker(customTypesLock());
460 info = &(*ct)[type];
461 info->signature = signature;
462 }
463 return info->signature;
464}
465
466QT_END_NAMESPACE
467
468#endif // QT_NO_DBUS
Note: See TracBrowser for help on using the repository browser.