QMetaMethod: clean up offset handling
Centralize the offset handling in one place and avoid lots of magic numbers in various places. Expose the number of ints per method in QMetaObjectPrivate as a constant, so that code in other places can access it via private API. Change-Id: I59790287a17ea47e6160ec65d9c8d0aaee748947 Reviewed-by: Simon Hausmann <hausmann@gmail.com> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
58a7e4f0bc
commit
ee709e3236
@ -884,20 +884,19 @@ int QMetaObjectPrivate::signalIndex(const QMetaMethod &m)
|
|||||||
*/
|
*/
|
||||||
QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index)
|
QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index)
|
||||||
{
|
{
|
||||||
QMetaMethod result;
|
|
||||||
if (signal_index < 0)
|
if (signal_index < 0)
|
||||||
return result;
|
return QMetaMethod();
|
||||||
|
|
||||||
Q_ASSERT(m != nullptr);
|
Q_ASSERT(m != nullptr);
|
||||||
int i = signal_index;
|
int i = signal_index;
|
||||||
i -= signalOffset(m);
|
i -= signalOffset(m);
|
||||||
if (i < 0 && m->d.superdata)
|
if (i < 0 && m->d.superdata)
|
||||||
return signal(m->d.superdata, signal_index);
|
return signal(m->d.superdata, signal_index);
|
||||||
|
|
||||||
if (i >= 0 && i < priv(m->d.data)->signalCount) {
|
|
||||||
result.mobj = m;
|
if (i >= 0 && i < priv(m->d.data)->signalCount)
|
||||||
result.handle = priv(m->d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i;
|
return QMetaMethod::fromRelativeMethodIndex(m, i);
|
||||||
}
|
return QMetaMethod();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1074,13 +1073,9 @@ int QMetaObject::indexOfClassInfo(const char *name) const
|
|||||||
QMetaMethod QMetaObject::constructor(int index) const
|
QMetaMethod QMetaObject::constructor(int index) const
|
||||||
{
|
{
|
||||||
int i = index;
|
int i = index;
|
||||||
QMetaMethod result;
|
if (i >= 0 && i < priv(d.data)->constructorCount)
|
||||||
Q_ASSERT(priv(d.data)->revision >= 2);
|
return QMetaMethod::fromRelativeConstructorIndex(this, i);
|
||||||
if (i >= 0 && i < priv(d.data)->constructorCount) {
|
return QMetaMethod();
|
||||||
result.mobj = this;
|
|
||||||
result.handle = priv(d.data)->constructorData + QMetaObjectPrivate::IntsPerMethod*i;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1095,12 +1090,9 @@ QMetaMethod QMetaObject::method(int index) const
|
|||||||
if (i < 0 && d.superdata)
|
if (i < 0 && d.superdata)
|
||||||
return d.superdata->method(index);
|
return d.superdata->method(index);
|
||||||
|
|
||||||
QMetaMethod result;
|
if (i >= 0 && i < priv(d.data)->methodCount)
|
||||||
if (i >= 0 && i < priv(d.data)->methodCount) {
|
return QMetaMethod::fromRelativeMethodIndex(this, i);
|
||||||
result.mobj = this;
|
return QMetaMethod();
|
||||||
result.handle = priv(d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1724,6 +1716,27 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
|
|||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QMetaMethod QMetaMethod::fromRelativeMethodIndex(const QMetaObject *mobj, int index)
|
||||||
|
{
|
||||||
|
Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->methodCount);
|
||||||
|
QMetaMethod m;
|
||||||
|
m.mobj = mobj;
|
||||||
|
m.data = { mobj->d.data + priv(mobj->d.data)->methodData + index * Data::Size };
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMetaMethod QMetaMethod::fromRelativeConstructorIndex(const QMetaObject *mobj, int index)
|
||||||
|
{
|
||||||
|
Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->constructorCount);
|
||||||
|
QMetaMethod m;
|
||||||
|
m.mobj = mobj;
|
||||||
|
m.data = { mobj->d.data + priv(mobj->d.data)->constructorData + index * Data::Size };
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\macro Q_METAMETHOD_INVOKE_MAX_ARGS
|
\macro Q_METAMETHOD_INVOKE_MAX_ARGS
|
||||||
\relates QMetaMethod
|
\relates QMetaMethod
|
||||||
@ -1752,13 +1765,13 @@ QByteArray QMetaMethodPrivate::signature() const
|
|||||||
QByteArray QMetaMethodPrivate::name() const
|
QByteArray QMetaMethodPrivate::name() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
||||||
return stringData(mobj, mobj->d.data[handle]);
|
return stringData(mobj, data.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
int QMetaMethodPrivate::typesDataIndex() const
|
int QMetaMethodPrivate::typesDataIndex() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
||||||
return mobj->d.data[handle + 2];
|
return data.parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *QMetaMethodPrivate::rawReturnTypeName() const
|
const char *QMetaMethodPrivate::rawReturnTypeName() const
|
||||||
@ -1779,7 +1792,7 @@ int QMetaMethodPrivate::returnType() const
|
|||||||
int QMetaMethodPrivate::parameterCount() const
|
int QMetaMethodPrivate::parameterCount() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
||||||
return mobj->d.data[handle + 1];
|
return data.argc();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QMetaMethodPrivate::parametersDataIndex() const
|
int QMetaMethodPrivate::parametersDataIndex() const
|
||||||
@ -1838,13 +1851,13 @@ QList<QByteArray> QMetaMethodPrivate::parameterNames() const
|
|||||||
QByteArray QMetaMethodPrivate::tag() const
|
QByteArray QMetaMethodPrivate::tag() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
Q_ASSERT(priv(mobj->d.data)->revision >= 7);
|
||||||
return stringData(mobj, mobj->d.data[handle + 3]);
|
return stringData(mobj, data.tag());
|
||||||
}
|
}
|
||||||
|
|
||||||
int QMetaMethodPrivate::ownMethodIndex() const
|
int QMetaMethodPrivate::ownMethodIndex() const
|
||||||
{
|
{
|
||||||
// recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
|
// recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
|
||||||
return (handle - priv(mobj->d.data)->methodData) / QMetaObjectPrivate::IntsPerMethod;
|
return ( data.d - mobj->d.data - priv(mobj->d.data)->methodData)/Data::Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1903,7 +1916,7 @@ QMetaType QMetaMethod::returnMetaType() const
|
|||||||
{
|
{
|
||||||
if (!mobj || methodType() == QMetaMethod::Constructor)
|
if (!mobj || methodType() == QMetaMethod::Constructor)
|
||||||
return QMetaType{};
|
return QMetaType{};
|
||||||
auto mt = QMetaType(mobj->d.metaTypes[mobj->d.data[handle + 5]]);
|
auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset()]);
|
||||||
if (mt.id() == QMetaType::UnknownType)
|
if (mt.id() == QMetaType::UnknownType)
|
||||||
return QMetaType(QMetaMethodPrivate::get(this)->returnType());
|
return QMetaType(QMetaMethodPrivate::get(this)->returnType());
|
||||||
else
|
else
|
||||||
@ -1958,7 +1971,7 @@ QMetaType QMetaMethod::parameterMetaType(int index) const
|
|||||||
return {};
|
return {};
|
||||||
// + 1 if there exists a return type
|
// + 1 if there exists a return type
|
||||||
auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
|
auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
|
||||||
auto mt = QMetaType(mobj->d.metaTypes[mobj->d.data[handle + 5] + parameterOffset]);
|
auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset() + parameterOffset]);
|
||||||
if (mt.id() == QMetaType::UnknownType)
|
if (mt.id() == QMetaType::UnknownType)
|
||||||
return QMetaType(QMetaMethodPrivate::get(this)->parameterType(index));
|
return QMetaType(QMetaMethodPrivate::get(this)->parameterType(index));
|
||||||
else
|
else
|
||||||
@ -2058,7 +2071,7 @@ int QMetaMethod::attributes() const
|
|||||||
{
|
{
|
||||||
if (!mobj)
|
if (!mobj)
|
||||||
return false;
|
return false;
|
||||||
return ((mobj->d.data[handle + 4])>>4);
|
return data.flags() >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2073,6 +2086,18 @@ int QMetaMethod::methodIndex() const
|
|||||||
return QMetaMethodPrivate::get(this)->ownMethodIndex() + mobj->methodOffset();
|
return QMetaMethodPrivate::get(this)->ownMethodIndex() + mobj->methodOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 6.0
|
||||||
|
|
||||||
|
Returns this method's local index inside.
|
||||||
|
*/
|
||||||
|
int QMetaMethod::relativeMethodIndex() const
|
||||||
|
{
|
||||||
|
if (!mobj)
|
||||||
|
return -1;
|
||||||
|
return QMetaMethodPrivate::get(this)->ownMethodIndex();
|
||||||
|
}
|
||||||
|
|
||||||
// This method has been around for a while, but the documentation was marked \internal until 5.1
|
// This method has been around for a while, but the documentation was marked \internal until 5.1
|
||||||
/*!
|
/*!
|
||||||
\since 5.1
|
\since 5.1
|
||||||
@ -2083,9 +2108,9 @@ int QMetaMethod::revision() const
|
|||||||
{
|
{
|
||||||
if (!mobj)
|
if (!mobj)
|
||||||
return 0;
|
return 0;
|
||||||
if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) {
|
if (data.flags() & MethodRevisioned) {
|
||||||
int offset = priv(mobj->d.data)->methodData
|
int offset = priv(mobj->d.data)->methodData
|
||||||
+ priv(mobj->d.data)->methodCount * QMetaObjectPrivate::IntsPerMethod
|
+ priv(mobj->d.data)->methodCount * Data::Size
|
||||||
+ QMetaMethodPrivate::get(this)->ownMethodIndex();
|
+ QMetaMethodPrivate::get(this)->ownMethodIndex();
|
||||||
return mobj->d.data[offset];
|
return mobj->d.data[offset];
|
||||||
}
|
}
|
||||||
@ -2106,7 +2131,7 @@ QMetaMethod::Access QMetaMethod::access() const
|
|||||||
{
|
{
|
||||||
if (!mobj)
|
if (!mobj)
|
||||||
return Private;
|
return Private;
|
||||||
return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
|
return (QMetaMethod::Access)(data.flags() & AccessMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2118,7 +2143,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const
|
|||||||
{
|
{
|
||||||
if (!mobj)
|
if (!mobj)
|
||||||
return QMetaMethod::Method;
|
return QMetaMethod::Method;
|
||||||
return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
|
return (QMetaMethod::MethodType)((data.flags() & MethodTypeMask)>>2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2145,16 +2170,12 @@ QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **si
|
|||||||
{
|
{
|
||||||
int i = -1;
|
int i = -1;
|
||||||
void *args[] = { &i, signal };
|
void *args[] = { &i, signal };
|
||||||
QMetaMethod result;
|
|
||||||
for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
|
for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
|
||||||
m->static_metacall(QMetaObject::IndexOfMethod, 0, args);
|
m->static_metacall(QMetaObject::IndexOfMethod, 0, args);
|
||||||
if (i >= 0) {
|
if (i >= 0)
|
||||||
result.mobj = m;
|
return QMetaMethod::fromRelativeMethodIndex(m, i);
|
||||||
result.handle = priv(m->d.data)->methodData + QMetaObjectPrivate::IntsPerMethod*i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return QMetaMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class Q_CORE_EXPORT QMetaMethod
|
class Q_CORE_EXPORT QMetaMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Q_DECL_CONSTEXPR inline QMetaMethod() : mobj(nullptr), handle(0) {}
|
Q_DECL_CONSTEXPR inline QMetaMethod() : mobj(nullptr), data({ nullptr }) {}
|
||||||
|
|
||||||
QByteArray methodSignature() const;
|
QByteArray methodSignature() const;
|
||||||
QByteArray name() const;
|
QByteArray name() const;
|
||||||
@ -72,6 +72,7 @@ public:
|
|||||||
enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
|
enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
|
||||||
int attributes() const;
|
int attributes() const;
|
||||||
int methodIndex() const;
|
int methodIndex() const;
|
||||||
|
int relativeMethodIndex() const;
|
||||||
int revision() const;
|
int revision() const;
|
||||||
|
|
||||||
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
|
inline const QMetaObject *enclosingMetaObject() const { return mobj; }
|
||||||
@ -184,9 +185,25 @@ private:
|
|||||||
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete;
|
char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete;
|
||||||
#endif
|
#endif
|
||||||
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
|
static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
|
||||||
|
static QMetaMethod fromRelativeMethodIndex(const QMetaObject *mobj, int index);
|
||||||
|
static QMetaMethod fromRelativeConstructorIndex(const QMetaObject *mobj, int index);
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
enum { Size = 6 };
|
||||||
|
|
||||||
|
uint name() const { return d[0]; }
|
||||||
|
uint argc() const { return d[1]; }
|
||||||
|
uint parameters() const { return d[2]; }
|
||||||
|
uint tag() const { return d[3]; }
|
||||||
|
uint flags() const { return d[4]; }
|
||||||
|
uint metaTypeOffset() const { return d[5]; }
|
||||||
|
bool operator==(const Data &other) const { return d == other.d; }
|
||||||
|
|
||||||
|
const uint *d;
|
||||||
|
};
|
||||||
|
|
||||||
const QMetaObject *mobj;
|
const QMetaObject *mobj;
|
||||||
uint handle;
|
Data data;
|
||||||
friend class QMetaMethodPrivate;
|
friend class QMetaMethodPrivate;
|
||||||
friend struct QMetaObject;
|
friend struct QMetaObject;
|
||||||
friend struct QMetaObjectPrivate;
|
friend struct QMetaObjectPrivate;
|
||||||
@ -197,7 +214,7 @@ private:
|
|||||||
Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
inline bool operator==(const QMetaMethod &m1, const QMetaMethod &m2)
|
inline bool operator==(const QMetaMethod &m1, const QMetaMethod &m2)
|
||||||
{ return m1.mobj == m2.mobj && m1.handle == m2.handle; }
|
{ return m1.data == m2.data; }
|
||||||
inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
|
inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2)
|
||||||
{ return !(m1 == m2); }
|
{ return !(m1 == m2); }
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
#include <QtCore/qglobal.h>
|
#include <QtCore/qglobal.h>
|
||||||
#include <QtCore/qobjectdefs.h>
|
#include <QtCore/qobjectdefs.h>
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
|
#include <QtCore/qmetaobject.h>
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
#include <private/qobject_p.h> // For QObjectPrivate::Connection
|
#include <private/qobject_p.h> // For QObjectPrivate::Connection
|
||||||
#endif
|
#endif
|
||||||
@ -178,7 +179,7 @@ struct QMetaObjectPrivate
|
|||||||
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
|
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
|
||||||
// revision 9 is Qt 6.0: It adds the metatype of properties and methods
|
// revision 9 is Qt 6.0: It adds the metatype of properties and methods
|
||||||
enum { OutputRevision = 9 }; // Used by moc, qmetaobjectbuilder and qdbus
|
enum { OutputRevision = 9 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||||
enum { IntsPerMethod = 6};
|
enum { IntsPerMethod = QMetaMethod::Data::Size};
|
||||||
|
|
||||||
int revision;
|
int revision;
|
||||||
int className;
|
int className;
|
||||||
|
@ -2562,9 +2562,9 @@ bool QObject::isSignalConnected(const QMetaMethod &signal) const
|
|||||||
|
|
||||||
Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
|
Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
|
||||||
"QObject::isSignalConnected" , "the parameter must be a signal member of the object");
|
"QObject::isSignalConnected" , "the parameter must be a signal member of the object");
|
||||||
uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/QMetaObjectPrivate::IntsPerMethod;
|
uint signalIndex = signal.relativeMethodIndex();
|
||||||
|
|
||||||
if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
|
if (signal.data.flags() & MethodCloned)
|
||||||
signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
|
signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
|
||||||
|
|
||||||
signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
|
signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
|
||||||
@ -2610,7 +2610,7 @@ void QMetaObjectPrivate::memberIndexes(const QObject *obj,
|
|||||||
m = m->d.superdata;
|
m = m->d.superdata;
|
||||||
if (!m)
|
if (!m)
|
||||||
return;
|
return;
|
||||||
*signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/QMetaObjectPrivate::IntsPerMethod;
|
*signalIndex = *methodIndex = member.relativeMethodIndex();
|
||||||
|
|
||||||
int signalOffset;
|
int signalOffset;
|
||||||
int methodOffset;
|
int methodOffset;
|
||||||
|
@ -427,7 +427,7 @@ struct Q_CORE_EXPORT QMetaObject
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct { // private data
|
struct Data { // private data
|
||||||
SuperData superdata;
|
SuperData superdata;
|
||||||
const uint *stringdata;
|
const uint *stringdata;
|
||||||
const uint *data;
|
const uint *data;
|
||||||
|
Loading…
Reference in New Issue
Block a user