1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtDBus module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "qdbusmetaobject_p.h"
42
43 #include <QtCore/qbytearray.h>
44 #include <QtCore/qhash.h>
45 #include <QtCore/qstring.h>
46 #include <QtCore/qvarlengtharray.h>
47
48 #include "qdbusutil_p.h"
49 #include "qdbuserror.h"
50 #include "qdbusmetatype.h"
51 #include "qdbusargument.h"
52 #include "qdbusintrospection_p.h"
53 #include "qdbusabstractinterface_p.h"
54
55 #include <private/qmetaobject_p.h>
56 #include <private/qmetaobjectbuilder_p.h>
57
58 #ifndef QT_NO_DBUS
59
60 QT_BEGIN_NAMESPACE
61
62 class QDBusMetaObjectGenerator
63 {
64 public:
65 QDBusMetaObjectGenerator(const QString &interface,
66 const QDBusIntrospection::Interface *parsedData);
67 void write(QDBusMetaObject *obj);
68 void writeWithoutXml(QDBusMetaObject *obj);
69
70 private:
71 struct Method {
72 QList<QByteArray> parameterNames;
73 QByteArray tag;
74 QByteArray name;
75 QVarLengthArray<int, 4> inputTypes;
76 QVarLengthArray<int, 4> outputTypes;
77 QByteArray rawReturnType;
78 int flags;
79 };
80
81 struct Property {
82 QByteArray typeName;
83 QByteArray signature;
84 int type;
85 int flags;
86 };
87 struct Type {
88 int id;
89 QByteArray name;
90 };
91
92 QMap<QByteArray, Method> signals_;
93 QMap<QByteArray, Method> methods;
94 QMap<QByteArray, Property> properties;
95
96 const QDBusIntrospection::Interface *data;
97 QString interface;
98
99 Type findType(const QByteArray &signature,
100 const QDBusIntrospection::Annotations &annotations,
101 const char *direction = "Out", int id = -1);
102
103 void parseMethods();
104 void parseSignals();
105 void parseProperties();
106
107 static int aggregateParameterCount(const QMap<QByteArray, Method> &map);
108 };
109
110 static const int intsPerProperty = 2;
111 static const int intsPerMethod = 2;
112
113 struct QDBusMetaObjectPrivate : public QMetaObjectPrivate
114 {
115 int propertyDBusData;
116 int methodDBusData;
117 };
118
QDBusMetaObjectGenerator(const QString & interfaceName,const QDBusIntrospection::Interface * parsedData)119 QDBusMetaObjectGenerator::QDBusMetaObjectGenerator(const QString &interfaceName,
120 const QDBusIntrospection::Interface *parsedData)
121 : data(parsedData), interface(interfaceName)
122 {
123 if (data) {
124 parseProperties();
125 parseSignals(); // call parseSignals first so that slots override signals
126 parseMethods();
127 }
128 }
129
registerComplexDBusType(const char * typeName)130 static int registerComplexDBusType(const char *typeName)
131 {
132 struct QDBusRawTypeHandler {
133 static void destruct(void *)
134 {
135 qFatal("Cannot destruct placeholder type QDBusRawType");
136 }
137
138 static void *construct(void *, const void *)
139 {
140 qFatal("Cannot construct placeholder type QDBusRawType");
141 return nullptr;
142 }
143 };
144
145 return QMetaType::registerNormalizedType(typeName,
146 QDBusRawTypeHandler::destruct,
147 QDBusRawTypeHandler::construct,
148 sizeof(void *),
149 QMetaType::MovableType,
150 nullptr);
151 }
152
153 Q_DBUS_EXPORT bool qt_dbus_metaobject_skip_annotations = false;
154
155 QDBusMetaObjectGenerator::Type
findType(const QByteArray & signature,const QDBusIntrospection::Annotations & annotations,const char * direction,int id)156 QDBusMetaObjectGenerator::findType(const QByteArray &signature,
157 const QDBusIntrospection::Annotations &annotations,
158 const char *direction, int id)
159 {
160 Type result;
161 result.id = QMetaType::UnknownType;
162
163 int type = QDBusMetaType::signatureToType(signature);
164 if (type == QMetaType::UnknownType && !qt_dbus_metaobject_skip_annotations) {
165 // it's not a type normally handled by our meta type system
166 // it must contain an annotation
167 QString annotationName = QString::fromLatin1("org.qtproject.QtDBus.QtTypeName");
168 if (id >= 0)
169 annotationName += QString::fromLatin1(".%1%2")
170 .arg(QLatin1String(direction))
171 .arg(id);
172
173 // extract from annotations:
174 QByteArray typeName = annotations.value(annotationName).toLatin1();
175
176 // verify that it's a valid one
177 if (typeName.isEmpty()) {
178 // try the old annotation from Qt 4
179 annotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName");
180 if (id >= 0)
181 annotationName += QString::fromLatin1(".%1%2")
182 .arg(QLatin1String(direction))
183 .arg(id);
184 typeName = annotations.value(annotationName).toLatin1();
185 }
186
187 if (!typeName.isEmpty()) {
188 // type name found
189 type = QMetaType::type(typeName);
190 }
191
192 if (type == QMetaType::UnknownType || signature != QDBusMetaType::typeToSignature(type)) {
193 // type is still unknown or doesn't match back to the signature that it
194 // was expected to, so synthesize a fake type
195 typeName = "QDBusRawType<0x" + signature.toHex() + ">*";
196 type = registerComplexDBusType(typeName);
197 }
198
199 result.name = typeName;
200 } else if (type == QMetaType::UnknownType) {
201 // this case is used only by the qdbus command-line tool
202 // invalid, let's create an impossible type that contains the signature
203
204 if (signature == "av") {
205 result.name = "QVariantList";
206 type = QMetaType::QVariantList;
207 } else if (signature == "a{sv}") {
208 result.name = "QVariantMap";
209 type = QMetaType::QVariantMap;
210 } else if (signature == "a{ss}") {
211 result.name = "QMap<QString,QString>";
212 type = qMetaTypeId<QMap<QString, QString> >();
213 } else if (signature == "aay") {
214 result.name = "QByteArrayList";
215 type = qMetaTypeId<QByteArrayList>();
216 } else {
217 result.name = "{D-Bus type \"" + signature + "\"}";
218 type = registerComplexDBusType(result.name);
219 }
220 } else {
221 result.name = QMetaType::typeName(type);
222 }
223
224 result.id = type;
225 return result; // success
226 }
227
parseMethods()228 void QDBusMetaObjectGenerator::parseMethods()
229 {
230 //
231 // TODO:
232 // Add cloned methods when the remote object has return types
233 //
234
235 QDBusIntrospection::Methods::ConstIterator method_it = data->methods.constBegin();
236 QDBusIntrospection::Methods::ConstIterator method_end = data->methods.constEnd();
237 for ( ; method_it != method_end; ++method_it) {
238 const QDBusIntrospection::Method &m = *method_it;
239 Method mm;
240
241 mm.name = m.name.toLatin1();
242 QByteArray prototype = mm.name;
243 prototype += '(';
244
245 bool ok = true;
246
247 // build the input argument list
248 for (int i = 0; i < m.inputArgs.count(); ++i) {
249 const QDBusIntrospection::Argument &arg = m.inputArgs.at(i);
250
251 Type type = findType(arg.type.toLatin1(), m.annotations, "In", i);
252 if (type.id == QMetaType::UnknownType) {
253 ok = false;
254 break;
255 }
256
257 mm.inputTypes.append(type.id);
258
259 mm.parameterNames.append(arg.name.toLatin1());
260
261 prototype.append(type.name);
262 prototype.append(',');
263 }
264 if (!ok) continue;
265
266 // build the output argument list:
267 for (int i = 0; i < m.outputArgs.count(); ++i) {
268 const QDBusIntrospection::Argument &arg = m.outputArgs.at(i);
269
270 Type type = findType(arg.type.toLatin1(), m.annotations, "Out", i);
271 if (type.id == QMetaType::UnknownType) {
272 ok = false;
273 break;
274 }
275
276 mm.outputTypes.append(type.id);
277
278 if (i == 0 && type.id == -1) {
279 mm.rawReturnType = type.name;
280 }
281 if (i != 0) {
282 // non-const ref parameter
283 mm.parameterNames.append(arg.name.toLatin1());
284
285 prototype.append(type.name);
286 prototype.append("&,");
287 }
288 }
289 if (!ok) continue;
290
291 // convert the last commas:
292 if (!mm.parameterNames.isEmpty())
293 prototype[prototype.length() - 1] = ')';
294 else
295 prototype.append(')');
296
297 // check the async tag
298 if (m.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"))
299 mm.tag = "Q_NOREPLY";
300
301 // meta method flags
302 mm.flags = AccessPublic | MethodSlot | MethodScriptable;
303
304 // add
305 methods.insert(QMetaObject::normalizedSignature(prototype), mm);
306 }
307 }
308
parseSignals()309 void QDBusMetaObjectGenerator::parseSignals()
310 {
311 QDBusIntrospection::Signals::ConstIterator signal_it = data->signals_.constBegin();
312 QDBusIntrospection::Signals::ConstIterator signal_end = data->signals_.constEnd();
313 for ( ; signal_it != signal_end; ++signal_it) {
314 const QDBusIntrospection::Signal &s = *signal_it;
315 Method mm;
316
317 mm.name = s.name.toLatin1();
318 QByteArray prototype = mm.name;
319 prototype += '(';
320
321 bool ok = true;
322
323 // build the output argument list
324 for (int i = 0; i < s.outputArgs.count(); ++i) {
325 const QDBusIntrospection::Argument &arg = s.outputArgs.at(i);
326
327 Type type = findType(arg.type.toLatin1(), s.annotations, "Out", i);
328 if (type.id == QMetaType::UnknownType) {
329 ok = false;
330 break;
331 }
332
333 mm.inputTypes.append(type.id);
334
335 mm.parameterNames.append(arg.name.toLatin1());
336
337 prototype.append(type.name);
338 prototype.append(',');
339 }
340 if (!ok) continue;
341
342 // convert the last commas:
343 if (!mm.parameterNames.isEmpty())
344 prototype[prototype.length() - 1] = ')';
345 else
346 prototype.append(')');
347
348 // meta method flags
349 mm.flags = AccessPublic | MethodSignal | MethodScriptable;
350
351 // add
352 signals_.insert(QMetaObject::normalizedSignature(prototype), mm);
353 }
354 }
355
parseProperties()356 void QDBusMetaObjectGenerator::parseProperties()
357 {
358 QDBusIntrospection::Properties::ConstIterator prop_it = data->properties.constBegin();
359 QDBusIntrospection::Properties::ConstIterator prop_end = data->properties.constEnd();
360 for ( ; prop_it != prop_end; ++prop_it) {
361 const QDBusIntrospection::Property &p = *prop_it;
362 Property mp;
363 Type type = findType(p.type.toLatin1(), p.annotations);
364 if (type.id == QMetaType::UnknownType)
365 continue;
366
367 QByteArray name = p.name.toLatin1();
368 mp.signature = p.type.toLatin1();
369 mp.type = type.id;
370 mp.typeName = type.name;
371
372 // build the flags:
373 mp.flags = StdCppSet | Scriptable | Stored | Designable;
374 if (p.access != QDBusIntrospection::Property::Write)
375 mp.flags |= Readable;
376 if (p.access != QDBusIntrospection::Property::Read)
377 mp.flags |= Writable;
378
379 // add the property:
380 properties.insert(name, mp);
381 }
382 }
383
384 // Returns the sum of all parameters (including return type) for the given
385 // \a map of methods. This is needed for calculating the size of the methods'
386 // parameter type/name meta-data.
aggregateParameterCount(const QMap<QByteArray,Method> & map)387 int QDBusMetaObjectGenerator::aggregateParameterCount(const QMap<QByteArray, Method> &map)
388 {
389 int sum = 0;
390 QMap<QByteArray, Method>::const_iterator it;
391 for (it = map.constBegin(); it != map.constEnd(); ++it) {
392 const Method &m = it.value();
393 sum += m.inputTypes.size() + qMax(1, m.outputTypes.size());
394 }
395 return sum;
396 }
397
write(QDBusMetaObject * obj)398 void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
399 {
400 // this code here is mostly copied from qaxbase.cpp
401 // with a few modifications to make it cleaner
402
403 QString className = interface;
404 className.replace(QLatin1Char('.'), QLatin1String("::"));
405 if (className.isEmpty())
406 className = QLatin1String("QDBusInterface");
407
408 QVarLengthArray<int> idata;
409 idata.resize(sizeof(QDBusMetaObjectPrivate) / sizeof(int));
410
411 int methodParametersDataSize =
412 ((aggregateParameterCount(signals_)
413 + aggregateParameterCount(methods)) * 2) // types and parameter names
414 - signals_.count() // return "parameters" don't have names
415 - methods.count(); // ditto
416
417 QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
418 Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QtDBus meta-object generator should generate the same version as moc");
419 header->revision = QMetaObjectPrivate::OutputRevision;
420 header->className = 0;
421 header->classInfoCount = 0;
422 header->classInfoData = 0;
423 header->methodCount = signals_.count() + methods.count();
424 header->methodData = idata.size();
425 header->propertyCount = properties.count();
426 header->propertyData = header->methodData + header->methodCount * 5 + methodParametersDataSize;
427 header->enumeratorCount = 0;
428 header->enumeratorData = 0;
429 header->constructorCount = 0;
430 header->constructorData = 0;
431 header->flags = RequiresVariantMetaObject;
432 header->signalCount = signals_.count();
433 // These are specific to QDBusMetaObject:
434 header->propertyDBusData = header->propertyData + header->propertyCount * 3;
435 header->methodDBusData = header->propertyDBusData + header->propertyCount * intsPerProperty;
436
437 int data_size = idata.size() +
438 (header->methodCount * (5+intsPerMethod)) + methodParametersDataSize +
439 (header->propertyCount * (3+intsPerProperty));
440 for (const Method &mm : qAsConst(signals_))
441 data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
442 for (const Method &mm : qAsConst(methods))
443 data_size += 2 + mm.inputTypes.count() + mm.outputTypes.count();
444 idata.resize(data_size + 1);
445
446 QMetaStringTable strings(className.toLatin1());
447
448 int offset = header->methodData;
449 int parametersOffset = offset + header->methodCount * 5;
450 int signatureOffset = header->methodDBusData;
451 int typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
452 idata[typeidOffset++] = 0; // eod
453
454 // add each method:
455 for (int x = 0; x < 2; ++x) {
456 // Signals must be added before other methods, to match moc.
457 QMap<QByteArray, Method> &map = (x == 0) ? signals_ : methods;
458 for (QMap<QByteArray, Method>::ConstIterator it = map.constBegin();
459 it != map.constEnd(); ++it) {
460 const Method &mm = it.value();
461
462 int argc = mm.inputTypes.size() + qMax(0, mm.outputTypes.size() - 1);
463
464 idata[offset++] = strings.enter(mm.name);
465 idata[offset++] = argc;
466 idata[offset++] = parametersOffset;
467 idata[offset++] = strings.enter(mm.tag);
468 idata[offset++] = mm.flags;
469
470 // Parameter types
471 for (int i = -1; i < argc; ++i) {
472 int type;
473 QByteArray typeName;
474 if (i < 0) { // Return type
475 if (!mm.outputTypes.isEmpty()) {
476 type = mm.outputTypes.first();
477 if (type == -1) {
478 type = IsUnresolvedType | strings.enter(mm.rawReturnType);
479 }
480 } else {
481 type = QMetaType::Void;
482 }
483 } else if (i < mm.inputTypes.size()) {
484 type = mm.inputTypes.at(i);
485 } else {
486 Q_ASSERT(mm.outputTypes.size() > 1);
487 type = mm.outputTypes.at(i - mm.inputTypes.size() + 1);
488 // Output parameters are references; type id not available
489 typeName = QMetaType::typeName(type);
490 typeName.append('&');
491 }
492 Q_ASSERT(type != QMetaType::UnknownType);
493 int typeInfo;
494 if (!typeName.isEmpty())
495 typeInfo = IsUnresolvedType | strings.enter(typeName);
496 else
497 typeInfo = type;
498 idata[parametersOffset++] = typeInfo;
499 }
500 // Parameter names
501 for (int i = 0; i < argc; ++i)
502 idata[parametersOffset++] = strings.enter(mm.parameterNames.at(i));
503
504 idata[signatureOffset++] = typeidOffset;
505 idata[typeidOffset++] = mm.inputTypes.count();
506 memcpy(idata.data() + typeidOffset, mm.inputTypes.data(), mm.inputTypes.count() * sizeof(int));
507 typeidOffset += mm.inputTypes.count();
508
509 idata[signatureOffset++] = typeidOffset;
510 idata[typeidOffset++] = mm.outputTypes.count();
511 memcpy(idata.data() + typeidOffset, mm.outputTypes.data(), mm.outputTypes.count() * sizeof(int));
512 typeidOffset += mm.outputTypes.count();
513 }
514 }
515
516 Q_ASSERT(offset == header->methodData + header->methodCount * 5);
517 Q_ASSERT(parametersOffset == header->propertyData);
518 Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
519 Q_ASSERT(typeidOffset == idata.size());
520 offset += methodParametersDataSize;
521 Q_ASSERT(offset == header->propertyData);
522
523 // add each property
524 signatureOffset = header->propertyDBusData;
525 for (QMap<QByteArray, Property>::ConstIterator it = properties.constBegin();
526 it != properties.constEnd(); ++it) {
527 const Property &mp = it.value();
528
529 // form is name, typeinfo, flags
530 idata[offset++] = strings.enter(it.key()); // name
531 Q_ASSERT(mp.type != QMetaType::UnknownType);
532 idata[offset++] = mp.type;
533 idata[offset++] = mp.flags;
534
535 idata[signatureOffset++] = strings.enter(mp.signature);
536 idata[signatureOffset++] = mp.type;
537 }
538
539 Q_ASSERT(offset == header->propertyDBusData);
540 Q_ASSERT(signatureOffset == header->methodDBusData);
541
542 char *string_data = new char[strings.blobSize()];
543 strings.writeBlob(string_data);
544
545 uint *uint_data = new uint[idata.size()];
546 memcpy(uint_data, idata.data(), idata.size() * sizeof(int));
547
548 // put the metaobject together
549 obj->d.data = uint_data;
550 obj->d.relatedMetaObjects = nullptr;
551 obj->d.static_metacall = nullptr;
552 obj->d.extradata = nullptr;
553 obj->d.stringdata = reinterpret_cast<const QByteArrayData *>(string_data);
554 obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
555 }
556
557 #if 0
558 void QDBusMetaObjectGenerator::writeWithoutXml(const QString &interface)
559 {
560 // no XML definition
561 QString tmp(interface);
562 tmp.replace(QLatin1Char('.'), QLatin1String("::"));
563 QByteArray name(tmp.toLatin1());
564
565 QDBusMetaObjectPrivate *header = new QDBusMetaObjectPrivate;
566 memset(header, 0, sizeof *header);
567 header->revision = 1;
568 // leave the rest with 0
569
570 char *stringdata = new char[name.length() + 1];
571 stringdata[name.length()] = '\0';
572
573 d.data = reinterpret_cast<uint*>(header);
574 d.relatedMetaObjects = 0;
575 d.static_metacall = 0;
576 d.extradata = 0;
577 d.stringdata = stringdata;
578 d.superdata = &QDBusAbstractInterface::staticMetaObject;
579 cached = false;
580 }
581 #endif
582
583 /////////
584 // class QDBusMetaObject
585
createMetaObject(const QString & interface,const QString & xml,QHash<QString,QDBusMetaObject * > & cache,QDBusError & error)586 QDBusMetaObject *QDBusMetaObject::createMetaObject(const QString &interface, const QString &xml,
587 QHash<QString, QDBusMetaObject *> &cache,
588 QDBusError &error)
589 {
590 error = QDBusError();
591 QDBusIntrospection::Interfaces parsed = QDBusIntrospection::parseInterfaces(xml);
592
593 QDBusMetaObject *we = nullptr;
594 QDBusIntrospection::Interfaces::ConstIterator it = parsed.constBegin();
595 QDBusIntrospection::Interfaces::ConstIterator end = parsed.constEnd();
596 for ( ; it != end; ++it) {
597 // check if it's in the cache
598 bool us = it.key() == interface;
599
600 QDBusMetaObject *obj = cache.value(it.key(), 0);
601 if ( !obj && ( us || !interface.startsWith( QLatin1String("local.") ) ) ) {
602 // not in cache; create
603 obj = new QDBusMetaObject;
604 QDBusMetaObjectGenerator generator(it.key(), it.value().constData());
605 generator.write(obj);
606
607 if ( (obj->cached = !it.key().startsWith( QLatin1String("local.") )) )
608 // cache it
609 cache.insert(it.key(), obj);
610 else if (!us)
611 delete obj;
612
613 }
614
615 if (us)
616 // it's us
617 we = obj;
618 }
619
620 if (we)
621 return we;
622 // still nothing?
623
624 if (parsed.isEmpty()) {
625 // object didn't return introspection
626 we = new QDBusMetaObject;
627 QDBusMetaObjectGenerator generator(interface, nullptr);
628 generator.write(we);
629 we->cached = false;
630 return we;
631 } else if (interface.isEmpty()) {
632 // merge all interfaces
633 it = parsed.constBegin();
634 QDBusIntrospection::Interface merged = *it.value().constData();
635
636 for (++it; it != end; ++it) {
637 merged.annotations.insert(it.value()->annotations);
638 merged.methods.unite(it.value()->methods);
639 merged.signals_.unite(it.value()->signals_);
640 merged.properties.insert(it.value()->properties);
641 }
642
643 merged.name = QLatin1String("local.Merged");
644 merged.introspection.clear();
645
646 we = new QDBusMetaObject;
647 QDBusMetaObjectGenerator generator(merged.name, &merged);
648 generator.write(we);
649 we->cached = false;
650 return we;
651 }
652
653 // mark as an error
654 error = QDBusError(QDBusError::UnknownInterface,
655 QLatin1String("Interface '%1' was not found")
656 .arg(interface));
657 return nullptr;
658 }
659
QDBusMetaObject()660 QDBusMetaObject::QDBusMetaObject()
661 {
662 }
663
priv(const uint * data)664 static inline const QDBusMetaObjectPrivate *priv(const uint* data)
665 {
666 return reinterpret_cast<const QDBusMetaObjectPrivate *>(data);
667 }
668
inputTypesForMethod(int id) const669 const int *QDBusMetaObject::inputTypesForMethod(int id) const
670 {
671 //id -= methodOffset();
672 if (id >= 0 && id < priv(d.data)->methodCount) {
673 int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
674 return reinterpret_cast<const int*>(d.data + d.data[handle]);
675 }
676 return nullptr;
677 }
678
outputTypesForMethod(int id) const679 const int *QDBusMetaObject::outputTypesForMethod(int id) const
680 {
681 //id -= methodOffset();
682 if (id >= 0 && id < priv(d.data)->methodCount) {
683 int handle = priv(d.data)->methodDBusData + id*intsPerMethod;
684 return reinterpret_cast<const int*>(d.data + d.data[handle + 1]);
685 }
686 return nullptr;
687 }
688
propertyMetaType(int id) const689 int QDBusMetaObject::propertyMetaType(int id) const
690 {
691 //id -= propertyOffset();
692 if (id >= 0 && id < priv(d.data)->propertyCount) {
693 int handle = priv(d.data)->propertyDBusData + id*intsPerProperty;
694 return d.data[handle + 1];
695 }
696 return 0;
697 }
698
699 QT_END_NAMESPACE
700
701 #endif // QT_NO_DBUS
702