Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpropertycache_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLPROPERTYCACHE_P_H
6#define QQMLPROPERTYCACHE_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qlinkedstringhash_p.h>
20#include <private/qqmlenumdata_p.h>
21#include <private/qqmlenumvalue_p.h>
22#include <private/qqmlpropertydata_p.h>
23#include <private/qqmlrefcount_p.h>
24#include <private/qexpected_p.h>
25
26#include <QtCore/qvarlengtharray.h>
27#include <QtCore/qvector.h>
28#include <QtCore/qversionnumber.h>
29#include <QtCore/qxpfunctional.h>
30#include <QtCore/qloggingcategory.h>
31
32#include <limits>
33
34class tst_qqmlpropertycache;
35
36QT_BEGIN_NAMESPACE
37
38class QCryptographicHash;
39class QJSEngine;
40class QMetaObjectBuilder;
41class QQmlContextData;
42class QQmlPropertyCache;
44class QQmlVMEMetaObject;
45
47{
48public:
50
56
58 {
59 const auto dd = d.loadAcquire();
60 if (dd & Shared)
61 reinterpret_cast<SharedHolder *>(dd ^ Shared)->release();
62 }
63
64private:
65 friend class QQmlPropertyCache;
67 : d(other.d.loadRelaxed())
68 {
69 // other has to survive until this ctor is done. So d cannot disappear before.
70 const auto od = other.d.loadRelaxed();
71 if (od & Shared)
72 reinterpret_cast<SharedHolder *>(od ^ Shared)->addref();
73 }
74
75 QQmlMetaObjectPointer(QQmlMetaObjectPointer &&other) = delete;
76 QQmlMetaObjectPointer &operator=(QQmlMetaObjectPointer &&other) = delete;
77 QQmlMetaObjectPointer &operator=(const QQmlMetaObjectPointer &other) = delete;
78
79public:
80 void setSharedOnce(QMetaObject *shared) const
81 {
82 SharedHolder *holder = new SharedHolder(shared);
83 if (!d.testAndSetRelease(0, quintptr(holder) | Shared))
84 holder->release();
85 }
86
87 const QMetaObject *metaObject() const
88 {
89 const auto dd = d.loadAcquire();
90 if (dd & Shared)
91 return reinterpret_cast<SharedHolder *>(dd ^ Shared)->metaObject;
92 return reinterpret_cast<const QMetaObject *>(dd);
93 }
94
95 bool isShared() const
96 {
97 // This works because static metaobjects need to be set in the ctor and once a shared
98 // metaobject has been set, it cannot be removed anymore.
99 const auto dd = d.loadRelaxed();
100 return !dd || (dd & Shared);
101 }
102
103 bool isNull() const
104 {
105 return d.loadRelaxed() == 0;
106 }
107
108private:
109 enum Tag {
110 Static = 0,
111 Shared = 1
112 };
113
114 struct SharedHolder final : public QQmlRefCounted<SharedHolder>
115 {
116 Q_DISABLE_COPY_MOVE(SharedHolder)
117 SharedHolder(QMetaObject *shared) : metaObject(shared) {}
118 ~SharedHolder() { free(metaObject); }
119 QMetaObject *metaObject;
120 };
121
122 mutable QBasicAtomicInteger<quintptr> d = 0;
123};
124
125// TODO should be moved somewhere else?
126namespace OverrideSemantics {
127enum class Status : uint8_t {
128 Valid = 0,
129 NoOverride, // Derived { (virtual|final) property var a;} Base {}
130
131 MissingBase, // Derived { override property var a;} Base {}
132 OverridingFinal, // Derived { * property var a;} Base {final property var a;}
133 OverridingNonVirtual, // Derived { (virtual|final) property var a;} Base {property var a;}
134 OverridingNonVirtualError, // Derived { override property var a;} Base {property var a;}
135 MissingOverrideOrFinalSpecifier, // Derived { (virtual) property var a;} Base { virtual property var a;}
136
137 InvokabilityMismatch, // property overrides method(function, slot, invokable) or vice-versa
138
140};
141
142inline bool isValidOverride(Status res)
143{
144 return res == Status::NoOverride
145 || res == Status::Valid
146 // MissingOverrideOrFinalSpecifier, OverridingNonVirtual and InvokabilityMismatch
147 // are currently considered valid to preserve backwards compatibility.
148 // It will become invalid in Qt7
151}
152
153enum class CheckMode : uint8_t {
154 Minimal = 0, // pre virtual and override keywords
156};
157
158[[nodiscard]] Q_AUTOTEST_EXPORT Status handleOverride(QQmlPropertyData &overridingProperty,
161
164
165} // namespace OverrideSemantics
166
167Q_DECLARE_LOGGING_CATEGORY(qqmlPropertyCacheAppend)
168
169/*
170 * QQmlPropertyCache has the following structure:
171 *
172 * It maintains a non-owning map (StringCache) that associates each property name
173 * with a pointer to a QQmlPropertyData object. Each pointer refers to an element
174 * stored in one of the owning containers — for example, PropertyIndexCache or
175 * MethodsIndexCache.
176 *
177 * As a result, if an owning container such as PropertyIndexCache is resized,
178 * the entries in StringCache become invalid.
179 *
180 * To protect users of this class from such undefined behavior, most modifying
181 * methods are kept private. A few trusted classes, such as QQmlPropertyCacheCreator,
182 * are declared as friends. As the name suggests, QQmlPropertyCacheCreator is responsible
183 * for constructing and populating a QQmlPropertyCache instance in one controlled place,
184 * ensuring that all indices and data remain coherent.
185 *
186 * Because the internal logic of this class is non-trivial, the unit test
187 * (tst_qqmlpropertycache) is also declared as a friend to support proper testing
188 * and maintainability.
189 */
190class Q_QML_EXPORT QQmlPropertyCache final : public QQmlRefCounted<QQmlPropertyCache>
191{
192public:
193 using Ptr = QQmlRefPointer<QQmlPropertyCache>;
194
195 struct ConstPtr : public QQmlRefPointer<const QQmlPropertyCache>
196 {
197 using QQmlRefPointer<const QQmlPropertyCache>::QQmlRefPointer;
198
199 ConstPtr(const Ptr &ptr) : ConstPtr(ptr.data(), AddRef) {}
200 ConstPtr(Ptr &&ptr) : ConstPtr(ptr.take(), Adopt) {}
201 ConstPtr &operator=(const Ptr &ptr) { return operator=(ConstPtr(ptr)); }
202 ConstPtr &operator=(Ptr &&ptr) { return operator=(ConstPtr(std::move(ptr))); }
203 };
204
205 static Ptr createStandalone(
206 const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero());
207
208 QQmlPropertyCache(
209 OverrideSemantics::HandlerRef handleOverride = OverrideSemantics::handleOverride)
210 : _handleOverride(handleOverride) { };
211 ~QQmlPropertyCache();
212
213 void update(const QMetaObject *);
214 void invalidate(const QMetaObject *);
215
216 QQmlPropertyCache::Ptr copy() const;
217
218 QQmlPropertyCache::Ptr copyAndAppend(
219 const QMetaObject *, QTypeRevision typeVersion,
220 QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
221 QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
222 QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()) const;
223
224 QQmlPropertyCache::Ptr copyAndReserve(
225 int propertyCount, int methodCount, int signalCount, int enumCount) const;
226
227 const QMetaObject *metaObject() const;
228 const QMetaObject *createMetaObject() const;
229 const QMetaObject *firstCppMetaObject() const;
230
231 template<typename K>
232 const QQmlPropertyData *property(const K &key, QObject *object,
233 const QQmlRefPointer<QQmlContextData> &context) const
234 {
235 return findProperty(stringCache.find(key), object, context);
236 }
237
238 const QQmlPropertyData *property(int) const;
239 const QQmlPropertyData *maybeUnresolvedProperty(int) const;
240 const QQmlPropertyData *method(int) const;
241 const QQmlPropertyData *signal(int index) const;
242 QQmlEnumData *qmlEnum(int) const;
243 int methodIndexToSignalIndex(int) const;
244
245 QString defaultPropertyName() const;
246 const QQmlPropertyData *defaultProperty() const;
247
248 // Return a reference here so that we don't have to addref/release all the time
249 inline const QQmlPropertyCache::ConstPtr &parent() const;
250
251 // is used by the Qml Designer
252 void setParent(QQmlPropertyCache::ConstPtr newParent);
253
254 inline const QQmlPropertyData *overrideData(const QQmlPropertyData *) const;
255 inline bool isAllowedInRevision(const QQmlPropertyData *) const;
256
257 static const QQmlPropertyData *property(
258 QObject *, QStringView, const QQmlRefPointer<QQmlContextData> &,
259 QQmlPropertyData *);
260 static const QQmlPropertyData *property(QObject *, const QLatin1String &, const QQmlRefPointer<QQmlContextData> &,
261 QQmlPropertyData *);
262 static const QQmlPropertyData *property(QObject *, const QV4::String *, const QQmlRefPointer<QQmlContextData> &,
263 QQmlPropertyData *);
264
265 //see QMetaObjectPrivate::originalClone
266 int originalClone(int index) const;
267 static int originalClone(const QObject *, int index);
268
269 QList<QByteArray> signalParameterNames(int index) const;
270 static QString signalParameterStringForJS(
271 const QList<QByteArray> &parameterNameList, QString *errorString = nullptr);
272
273 const char *className() const;
274
275 inline int propertyCount() const;
276 inline int ownPropertyCount() const { return int(propertyIndexCache.count()); }
277 inline int propertyOffset() const;
278 inline int methodCount() const;
279 inline int ownMethodCount() const { return int(methodIndexCache.count()); }
280 inline int methodOffset() const;
281 inline int signalCount() const;
282 inline int ownSignalCount() const { return int(signalHandlerIndexCache.count()); }
283 inline int signalOffset() const;
284 inline int qmlEnumCount() const;
285
286 void toMetaObjectBuilder(QMetaObjectBuilder &) const;
287
288 inline bool callJSFactoryMethod(QObject *object, void **args) const;
289
290 static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
291 static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
292
293 QByteArray checksum(QHash<quintptr, QByteArray> *checksums, bool *ok) const;
294
295 QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; }
296 void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; }
297
298private:
299 friend class QQmlEnginePrivate;
300 friend class QQmlCompiler;
301 template <typename T> friend class QQmlPropertyCacheCreator;
302 template <typename T> friend class QQmlPropertyCacheAliasCreator;
303 template <typename T> friend class QQmlComponentAndAliasResolver;
304 friend class QQmlMetaObject;
305 friend class ::tst_qqmlpropertycache;
306
307 QQmlPropertyCache(
308 const QQmlMetaObjectPointer &metaObject,
309 OverrideSemantics::HandlerRef handleOverride = OverrideSemantics::handleOverride)
310 : _handleOverride(handleOverride), _metaObject(metaObject)
311 {
312 }
313
314 inline QQmlPropertyCache::Ptr copy(const QQmlMetaObjectPointer &mo, int reserve) const;
315
316 void append(const QMetaObject *, QTypeRevision typeVersion,
317 QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
318 QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
319 QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
320
321 // TODO incorporate warning from maybeLog
322 using Error = OverrideSemantics::Status;
323 using AppendResult = q23::expected<void, Error>;
324
325 // TODO QTBUG-141728
326 // Always adds a property to the propertyIndex even if override semantics are invalid, not
327 // accessible by name though
328 AppendResult appendPropertyAttr(const QString &name, QQmlPropertyData &&data);
329 AppendResult appendAlias(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
330 QMetaType propType, QTypeRevision version, int notifyIndex,
331 int encodedTargetIndex, int targetObjectId);
332 void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
333 const QMetaType *types = nullptr,
334 const QList<QByteArray> &names = QList<QByteArray>());
335 void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
336 QMetaType returnType, const QList<QByteArray> &names,
337 const QList<QMetaType> &parameterTypes);
338 void appendEnum(const QString &, const QList<QQmlEnumValue> &);
339
340 QQmlPropertyCacheMethodArguments *createArgumentsObject(int count,
341 const QList<QByteArray> &names);
342
343 typedef QList<QQmlPropertyData> IndexCache;
344 typedef QLinkedStringMultiHash<std::pair<int, QQmlPropertyData *> > StringCache;
345 typedef QList<QTypeRevision> AllowedRevisionCache;
346
347 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *,
348 const QQmlRefPointer<QQmlContextData> &) const;
349 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *,
350 const QQmlRefPointer<QQmlContextData> &) const;
351
352 template<typename K>
353 QQmlPropertyData *findNamedProperty(const K &key) const
354 {
355 StringCache::mapped_type *it = stringCache.value(key);
356 return it ? it->second : 0;
357 }
358
359 template<typename K>
360 void setNamedProperty(const K &key, int index, QQmlPropertyData *data)
361 {
362 stringCache.insert(key, std::make_pair(index, data));
363 }
364
365 // Conditionally logs diagnostics for override semantics.
366 //
367 // Important: "Valid" override semantics do not imply "no warning".
368 // Some override situations are allowed by the language rules but are still
369 // diagnosed to help users avoid surprising or unintended behavior.
370 //
371 // Does not construct diagnostic messages when no logging is required
372 // to compute qPrintable(name) and className() only when needed.
373 template <typename String>
374 void maybeLog(OverrideSemantics::Status status, const String &name) const
375 {
376 switch (status) {
377 case OverrideSemantics::Status::OverridingFinal: {
378 qCWarning(qqmlPropertyCacheAppend).noquote()
379 << QStringLiteral("Final member %1 is overridden in class %2. The "
380 "override won't be used.")
381 .arg(qPrintable(name), className());
382 return;
383 }
384 case OverrideSemantics::Status::MissingBase: {
385 qCWarning(qqmlPropertyCacheAppend).noquote()
386 << QStringLiteral("Member %1 of the object %2 does not override anything."
387 " Consider removing \"override\". ")
388 .arg(qPrintable(name), className());
389 return;
390 }
391 case OverrideSemantics::Status::OverridingNonVirtual: {
392 // TODO: Make this a warning as soon as we can
393 qCDebug(qqmlPropertyCacheAppend).noquote()
394 << QStringLiteral("Member %1 of the object %2 overrides a non-virtual member. "
395 "Consider renaming it or mark it virtual in the base object")
396 .arg(qPrintable(name), className());
397 return;
398 }
399 case OverrideSemantics::Status::OverridingNonVirtualError: {
400 qCWarning(qqmlPropertyCacheAppend).noquote()
401 << QStringLiteral("Member %1 of the object %2 overrides a non-virtual member. "
402 "Consider renaming it or mark it virtual in the base object")
403 .arg(qPrintable(name), className());
404 return;
405 }
406 case OverrideSemantics::Status::MissingOverrideOrFinalSpecifier: {
407 qCWarning(qqmlPropertyCacheAppend).noquote()
408 << QStringLiteral(
409 "Member %1 of the object %2 overrides a member of the base object. "
410 "Consider renaming it or adding final or override specifier")
411 .arg(qPrintable(name), className());
412 return;
413 }
414 // TODO QTBUG-98320, when override is cleaned up for methods, we need a warning for InvokabilityMismatch
415 default:
416 return;
417 }
418 }
419
420private:
421 OverrideSemantics::HandlerRef _handleOverride;
422
423 int propertyIndexCacheStart = 0; // placed here to avoid gap between QQmlRefCount and _parent
424 QQmlPropertyCache::ConstPtr _parent;
425
426 IndexCache propertyIndexCache;
427 IndexCache methodIndexCache;
428 IndexCache signalHandlerIndexCache;
429 StringCache stringCache;
430 AllowedRevisionCache allowedRevisionCache;
431 QList<QQmlEnumData> enumCache;
432
433 QQmlMetaObjectPointer _metaObject;
434 QByteArray _dynamicClassName;
435 QByteArray _dynamicStringData;
436 QByteArray _listPropertyAssignBehavior;
437 QString _defaultPropertyName;
438 QQmlPropertyCacheMethodArguments *argumentsCache = nullptr;
439 int methodIndexCacheStart = 0;
440 int signalHandlerIndexCacheStart = 0;
441 int _jsFactoryMethodIndex = -1;
442};
443
444// Returns this property cache's metaObject. May be null if it hasn't been created yet.
445inline const QMetaObject *QQmlPropertyCache::metaObject() const
446{
447 return _metaObject.metaObject();
448}
449
450// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
451// QML
452inline const QMetaObject *QQmlPropertyCache::firstCppMetaObject() const
453{
454 const QQmlPropertyCache *p = this;
455 while (p->_metaObject.isShared())
456 p = p->parent().data();
457 return p->_metaObject.metaObject();
458}
459
460inline const QQmlPropertyData *QQmlPropertyCache::property(int index) const
461{
462 if (index < 0 || index >= propertyCount())
463 return nullptr;
464
465 if (index < propertyIndexCacheStart)
466 return _parent->property(index);
467
468 return &propertyIndexCache.at(index - propertyIndexCacheStart);
469}
470
471inline const QQmlPropertyData *QQmlPropertyCache::method(int index) const
472{
473 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
474 return nullptr;
475
476 if (index < methodIndexCacheStart)
477 return _parent->method(index);
478
479 return const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
480}
481
482/*! \internal
483 \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
484 This is different from QMetaMethod::methodIndex().
485*/
486inline const QQmlPropertyData *QQmlPropertyCache::signal(int index) const
487{
488 if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.size()))
489 return nullptr;
490
491 if (index < signalHandlerIndexCacheStart)
492 return _parent->signal(index);
493
494 const QQmlPropertyData *rv = const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
495 Q_ASSERT(rv->isSignal() || rv->coreIndex() == -1);
496 return rv;
497}
498
499inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const
500{
501 if (index < 0 || index >= enumCache.size())
502 return nullptr;
503
504 return const_cast<QQmlEnumData *>(&enumCache.at(index));
505}
506
507inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
508{
509 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
510 return index;
511
512 if (index < methodIndexCacheStart)
513 return _parent->methodIndexToSignalIndex(index);
514
515 return index - methodIndexCacheStart + signalHandlerIndexCacheStart;
516}
517
518// Returns the name of the default property for this cache
519inline QString QQmlPropertyCache::defaultPropertyName() const
520{
521 return _defaultPropertyName;
522}
523
524inline const QQmlPropertyCache::ConstPtr &QQmlPropertyCache::parent() const
525{
526 return _parent;
527}
528
529const QQmlPropertyData *
530QQmlPropertyCache::overrideData(const QQmlPropertyData *data) const
531{
532 if (!data->hasOverride())
533 return nullptr;
534
535 if (data->overrideIndexIsProperty())
536 return property(data->overrideIndex());
537 else
538 return method(data->overrideIndex());
539}
540
541bool QQmlPropertyCache::isAllowedInRevision(const QQmlPropertyData *data) const
542{
543 // Aliases can't be revisioned.
544 if (data->isAlias())
545 return true;
546
547 const QTypeRevision requested = data->revision();
548 const int offset = data->metaObjectOffset();
549 if (offset == -1 && requested == QTypeRevision::zero())
550 return true;
551
552 Q_ASSERT(offset >= 0);
553 Q_ASSERT(offset < allowedRevisionCache.size());
554 const QTypeRevision allowed = allowedRevisionCache[offset];
555
556 if (requested.hasMajorVersion()) {
557 if (requested.majorVersion() > allowed.majorVersion())
558 return false;
559 if (requested.majorVersion() < allowed.majorVersion())
560 return true;
561 }
562
563 return !requested.hasMinorVersion() || requested.minorVersion() <= allowed.minorVersion();
564}
565
566int QQmlPropertyCache::propertyCount() const
567{
568 return propertyIndexCacheStart + int(propertyIndexCache.size());
569}
570
571int QQmlPropertyCache::propertyOffset() const
572{
573 return propertyIndexCacheStart;
574}
575
576int QQmlPropertyCache::methodCount() const
577{
578 return methodIndexCacheStart + int(methodIndexCache.size());
579}
580
581int QQmlPropertyCache::methodOffset() const
582{
583 return methodIndexCacheStart;
584}
585
586int QQmlPropertyCache::signalCount() const
587{
588 return signalHandlerIndexCacheStart + int(signalHandlerIndexCache.size());
589}
590
591int QQmlPropertyCache::signalOffset() const
592{
593 return signalHandlerIndexCacheStart;
594}
595
596int QQmlPropertyCache::qmlEnumCount() const
597{
598 return int(enumCache.size());
599}
600
601bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
602{
603 if (_jsFactoryMethodIndex != -1) {
604 if (const QMetaObject *mo = _metaObject.metaObject()) {
605 mo->d.static_metacall(object, QMetaObject::InvokeMetaMethod,
606 _jsFactoryMethodIndex, args);
607 return true;
608 }
609 return false;
610 }
611 if (_parent)
612 return _parent->callJSFactoryMethod(object, args);
613 return false;
614}
615
616QT_END_NAMESPACE
617
618#endif // QQMLPROPERTYCACHE_P_H
friend class QJSEngine
const QMetaObject * metaObject() const
void setSharedOnce(QMetaObject *shared) const
static Status checkMinimal(const QQmlPropertyData *const existingProperty)
static Status check(const QQmlPropertyData &overridingProperty, const QQmlPropertyData *const existingProperty, CheckMode mode)
static bool hasInvalidModifierCombintation(const QQmlPropertyData &overridingProperty)
static Status checkFull(const QQmlPropertyData &overridingProperty, const QQmlPropertyData *const existingProperty)
Status handleOverride(QQmlPropertyData &overridingProperty, QQmlPropertyData *existingProperty, CheckMode mode)
bool isValidOverride(Status res)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
const QQmlPropertyData * qQmlPropertyCacheProperty(QObject *obj, T name, const QQmlRefPointer< QQmlContextData > &context, QQmlPropertyData *local)
static const QByteArray stringData(const QMetaObject *mo, int index)
static QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const T &propertyName)
#define Q_INT16_MAX
static const char * qQmlPropertyCacheToString(QLatin1String string)
static QByteArray qQmlPropertyCacheToString(const QV4::String *string)
static std::pair< bool, int > deriveEncodingAndLength(const char *str)
static QHashedString signalNameToHandlerName(const QHashedString &methodName)
static int metaObjectSignalCount(const QMetaObject *metaObject)