~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/dbus/qdbusmetatype.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtDBus module of the Qt Toolkit.
 
7
**
 
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.
 
16
**
 
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.
 
24
**
 
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.
 
28
**
 
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.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qdbusmetatype.h"
 
43
#include "qdbusmetatype_p.h"
 
44
 
 
45
#include <string.h>
 
46
#include "qdbus_symbols_p.h"
 
47
 
 
48
#include <qbytearray.h>
 
49
#include <qglobal.h>
 
50
#include <qreadwritelock.h>
 
51
#include <qvector.h>
 
52
 
 
53
#include "qdbusargument_p.h"
 
54
#include "qdbusutil_p.h"
 
55
#include "qdbusunixfiledescriptor.h"
 
56
#ifndef QT_BOOTSTRAPPED
 
57
#include "qdbusmessage.h"
 
58
#endif
 
59
 
 
60
#ifndef QT_NO_DBUS
 
61
 
 
62
#ifndef DBUS_TYPE_UNIX_FD
 
63
# define DBUS_TYPE_UNIX_FD int('h')
 
64
# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
 
65
#endif
 
66
 
 
67
QT_BEGIN_NAMESPACE
 
68
 
 
69
class QDBusCustomTypeInfo
 
70
{
 
71
public:
 
72
    QDBusCustomTypeInfo() : signature(), marshall(0), demarshall(0)
 
73
    { }
 
74
 
 
75
    // Suggestion:
 
76
    // change 'signature' to char* and make QDBusCustomTypeInfo a Movable type
 
77
    QByteArray signature;
 
78
    QDBusMetaType::MarshallFunction marshall;
 
79
    QDBusMetaType::DemarshallFunction demarshall;
 
80
};
 
81
 
 
82
template<typename T>
 
83
inline static void registerHelper(T * = 0)
 
84
{
 
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));
 
90
}
 
91
 
 
92
void QDBusMetaTypeId::init()
 
93
{
 
94
    static QBasicAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(false);
 
95
 
 
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)
 
100
        (void)message();
 
101
        (void)argument();
 
102
        (void)variant();
 
103
        (void)objectpath();
 
104
        (void)signature();
 
105
        (void)error();
 
106
        (void)unixfd();
 
107
 
 
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>();
 
124
 
 
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> >();
 
136
#endif
 
137
 
 
138
        initialized.store(true);
 
139
    }
 
140
}
 
141
 
 
142
Q_GLOBAL_STATIC(QVector<QDBusCustomTypeInfo>, customTypes)
 
143
Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
 
144
 
 
145
/*!
 
146
    \class QDBusMetaType
 
147
    \inmodule QtDBus
 
148
    \brief Meta-type registration system for the QtDBus module.
 
149
    \internal
 
150
 
 
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
 
156
    registered.
 
157
 
 
158
    See \l {qdbustypesystem.html}{QtDBus type system} for more
 
159
    information on the type system and how to register additional
 
160
    types.
 
161
 
 
162
    \sa {qdbustypesystem.html}{QtDBus type system},
 
163
    qDBusRegisterMetaType(), QMetaType, QVariant, QDBusArgument
 
164
*/
 
165
 
 
166
/*!
 
167
    \fn int qDBusRegisterMetaType()
 
168
    \relates QDBusArgument
 
169
    \threadsafe
 
170
    \since 4.2
 
171
 
 
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.
 
175
 
 
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
 
178
    following example:
 
179
 
 
180
    \snippet code/src_qdbus_qdbusmetatype.cpp 0
 
181
 
 
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
 
187
    types.
 
188
 
 
189
    This function returns the Qt meta type id for the type (the same
 
190
    value that is returned from qRegisterMetaType()).
 
191
 
 
192
    \sa {qdbustypesystem.html}{QtDBus type system}, qRegisterMetaType(), QMetaType
 
193
*/
 
194
 
 
195
/*!
 
196
    \typedef QDBusMetaType::MarshallFunction
 
197
    \internal
 
198
*/
 
199
 
 
200
/*!
 
201
    \typedef QDBusMetaType::DemarshallFunction
 
202
    \internal
 
203
*/
 
204
 
 
205
/*!
 
206
    \internal
 
207
    Registers the marshalling and demarshalling functions for meta
 
208
    type \a id.
 
209
*/
 
210
void QDBusMetaType::registerMarshallOperators(int id, MarshallFunction mf,
 
211
                                              DemarshallFunction df)
 
212
{
 
213
    QByteArray var;
 
214
    QVector<QDBusCustomTypeInfo> *ct = customTypes();
 
215
    if (id < 0 || !mf || !df || !ct)
 
216
        return;                 // error!
 
217
 
 
218
    QWriteLocker locker(customTypesLock());
 
219
    if (id >= ct->size())
 
220
        ct->resize(id + 1);
 
221
    QDBusCustomTypeInfo &info = (*ct)[id];
 
222
    info.marshall = mf;
 
223
    info.demarshall = df;
 
224
}
 
225
 
 
226
/*!
 
227
    \internal
 
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.
 
231
*/
 
232
bool QDBusMetaType::marshall(QDBusArgument &arg, int id, const void *data)
 
233
{
 
234
    QDBusMetaTypeId::init();
 
235
 
 
236
    MarshallFunction mf;
 
237
    {
 
238
        QReadLocker locker(customTypesLock());
 
239
        QVector<QDBusCustomTypeInfo> *ct = customTypes();
 
240
        if (id >= ct->size())
 
241
            return false;       // non-existent
 
242
 
 
243
        const QDBusCustomTypeInfo &info = (*ct).at(id);
 
244
        if (!info.marshall) {
 
245
            mf = 0;             // make gcc happy
 
246
            return false;
 
247
        } else
 
248
            mf = info.marshall;
 
249
    }
 
250
 
 
251
    mf(arg, data);
 
252
    return true;
 
253
}
 
254
 
 
255
/*!
 
256
    \internal
 
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.
 
260
*/
 
261
bool QDBusMetaType::demarshall(const QDBusArgument &arg, int id, void *data)
 
262
{
 
263
    QDBusMetaTypeId::init();
 
264
 
 
265
    DemarshallFunction df;
 
266
    {
 
267
        QReadLocker locker(customTypesLock());
 
268
        QVector<QDBusCustomTypeInfo> *ct = customTypes();
 
269
        if (id >= ct->size())
 
270
            return false;       // non-existent
 
271
 
 
272
        const QDBusCustomTypeInfo &info = (*ct).at(id);
 
273
        if (!info.demarshall) {
 
274
            df = 0;             // make gcc happy
 
275
            return false;
 
276
        } else
 
277
            df = info.demarshall;
 
278
    }
 
279
#ifndef QT_BOOTSTRAPPED
 
280
    QDBusArgument copy = arg;
 
281
    df(copy, data);
 
282
#else
 
283
    Q_UNUSED(arg);
 
284
    Q_UNUSED(data);
 
285
    Q_UNUSED(df);
 
286
#endif
 
287
    return true;
 
288
}
 
289
 
 
290
/*!
 
291
    \fn QDBusMetaType::signatureToType(const char *signature)
 
292
    \internal
 
293
 
 
294
    Returns the Qt meta type id for the given D-Bus signature for exactly one full type, given
 
295
    by \a signature.
 
296
 
 
297
    Note: this function only handles the basic D-Bus types.
 
298
 
 
299
    \sa QDBusUtil::isValidSingleSignature(), typeToSignature(),
 
300
        QVariant::type(), QVariant::userType()
 
301
*/
 
302
int QDBusMetaType::signatureToType(const char *signature)
 
303
{
 
304
    if (!signature)
 
305
        return QMetaType::UnknownType;
 
306
 
 
307
    QDBusMetaTypeId::init();
 
308
    switch (signature[0])
 
309
    {
 
310
    case DBUS_TYPE_BOOLEAN:
 
311
        return QVariant::Bool;
 
312
 
 
313
    case DBUS_TYPE_BYTE:
 
314
        return QMetaType::UChar;
 
315
 
 
316
    case DBUS_TYPE_INT16:
 
317
        return QMetaType::Short;
 
318
 
 
319
    case DBUS_TYPE_UINT16:
 
320
        return QMetaType::UShort;
 
321
        
 
322
    case DBUS_TYPE_INT32:
 
323
        return QVariant::Int;
 
324
        
 
325
    case DBUS_TYPE_UINT32:
 
326
        return QVariant::UInt;
 
327
 
 
328
    case DBUS_TYPE_INT64:
 
329
        return QVariant::LongLong;
 
330
 
 
331
    case DBUS_TYPE_UINT64:
 
332
        return QVariant::ULongLong;
 
333
 
 
334
    case DBUS_TYPE_DOUBLE:
 
335
        return QVariant::Double;
 
336
 
 
337
    case DBUS_TYPE_STRING:
 
338
        return QVariant::String;
 
339
 
 
340
    case DBUS_TYPE_OBJECT_PATH:
 
341
        return QDBusMetaTypeId::objectpath();
 
342
 
 
343
    case DBUS_TYPE_SIGNATURE:
 
344
        return QDBusMetaTypeId::signature();
 
345
 
 
346
    case DBUS_TYPE_UNIX_FD:
 
347
        return QDBusMetaTypeId::unixfd();
 
348
 
 
349
    case DBUS_TYPE_VARIANT:
 
350
        return QDBusMetaTypeId::variant();
 
351
 
 
352
    case DBUS_TYPE_ARRAY:       // special case
 
353
        switch (signature[1]) {
 
354
        case DBUS_TYPE_BYTE:
 
355
            return QVariant::ByteArray;
 
356
 
 
357
        case DBUS_TYPE_STRING:
 
358
            return QVariant::StringList;
 
359
 
 
360
        case DBUS_TYPE_VARIANT:
 
361
            return QVariant::List;
 
362
 
 
363
        case DBUS_TYPE_OBJECT_PATH:
 
364
            return qMetaTypeId<QList<QDBusObjectPath> >();
 
365
 
 
366
        case DBUS_TYPE_SIGNATURE:
 
367
            return qMetaTypeId<QList<QDBusSignature> >();
 
368
 
 
369
        }
 
370
        // fall through
 
371
    default:
 
372
        return QMetaType::UnknownType;
 
373
    }
 
374
}
 
375
 
 
376
/*!
 
377
    \fn QDBusMetaType::typeToSignature(int type)
 
378
    \internal 
 
379
 
 
380
    Returns the D-Bus signature equivalent to the supplied meta type id \a type.
 
381
 
 
382
    More types can be registered with the qDBusRegisterMetaType() function.
 
383
 
 
384
    \sa QDBusUtil::isValidSingleSignature(), signatureToType(),
 
385
        QVariant::type(), QVariant::userType()
 
386
*/
 
387
const char *QDBusMetaType::typeToSignature(int type)
 
388
{
 
389
    // check if it's a static type
 
390
    switch (type)
 
391
    {
 
392
    case QMetaType::UChar:
 
393
        return DBUS_TYPE_BYTE_AS_STRING;
 
394
 
 
395
    case QVariant::Bool:
 
396
        return DBUS_TYPE_BOOLEAN_AS_STRING;
 
397
 
 
398
    case QMetaType::Short:
 
399
        return DBUS_TYPE_INT16_AS_STRING;
 
400
 
 
401
    case QMetaType::UShort:
 
402
        return DBUS_TYPE_UINT16_AS_STRING;
 
403
 
 
404
    case QVariant::Int:
 
405
        return DBUS_TYPE_INT32_AS_STRING;
 
406
 
 
407
    case QVariant::UInt:
 
408
        return DBUS_TYPE_UINT32_AS_STRING;
 
409
 
 
410
    case QVariant::LongLong:
 
411
        return DBUS_TYPE_INT64_AS_STRING;
 
412
 
 
413
    case QVariant::ULongLong:
 
414
        return DBUS_TYPE_UINT64_AS_STRING;
 
415
 
 
416
    case QVariant::Double:
 
417
        return DBUS_TYPE_DOUBLE_AS_STRING;
 
418
 
 
419
    case QVariant::String:
 
420
        return DBUS_TYPE_STRING_AS_STRING;
 
421
 
 
422
    case QVariant::StringList:
 
423
        return DBUS_TYPE_ARRAY_AS_STRING
 
424
            DBUS_TYPE_STRING_AS_STRING; // as
 
425
 
 
426
    case QVariant::ByteArray:
 
427
        return DBUS_TYPE_ARRAY_AS_STRING
 
428
            DBUS_TYPE_BYTE_AS_STRING; // ay
 
429
    }
 
430
 
 
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;
 
440
 
 
441
    // try the database
 
442
    QVector<QDBusCustomTypeInfo> *ct = customTypes();
 
443
    {
 
444
        QReadLocker locker(customTypesLock());
 
445
        if (type >= ct->size())
 
446
            return 0;           // type not registered with us
 
447
 
 
448
        const QDBusCustomTypeInfo &info = (*ct).at(type);
 
449
 
 
450
        if (!info.signature.isNull())
 
451
            return info.signature;
 
452
 
 
453
        if (!info.marshall)
 
454
            return 0;           // type not registered with us
 
455
    }
 
456
 
 
457
    // call to user code to construct the signature type
 
458
    QDBusCustomTypeInfo *info;
 
459
    {
 
460
        // createSignature will never return a null QByteArray
 
461
        // if there was an error, it'll return ""
 
462
        QByteArray signature = QDBusArgumentPrivate::createSignature(type);
 
463
 
 
464
        // re-acquire lock
 
465
        QWriteLocker locker(customTypesLock());
 
466
        info = &(*ct)[type];
 
467
        info->signature = signature;
 
468
    }
 
469
    return info->signature;
 
470
}
 
471
 
 
472
QT_END_NAMESPACE
 
473
 
 
474
#endif // QT_NO_DBUS