1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QMETAOBJECT_P_H
6#define QMETAOBJECT_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 for the convenience
13// of moc. This header file may change from version to version without notice,
14// or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qglobal.h>
20#include <QtCore/qobjectdefs.h>
21#include <QtCore/qmutex.h>
22#include <QtCore/qmetaobject.h>
23#ifndef QT_NO_QOBJECT
24#include <private/qobject_p.h> // For QObjectPrivate::Connection
25#endif
26#include <private/qtools_p.h>
27#include <QtCore/qvarlengtharray.h>
28
29QT_BEGIN_NAMESPACE
30// ### TODO - QTBUG-87869: wrap in a proper Q_NAMESPACE and use scoped enums, to avoid name clashes
31
32using namespace QtMiscUtils;
33
34enum PropertyFlags {
35 Invalid = 0x00000000,
36 Readable = 0x00000001,
37 Writable = 0x00000002,
38 Resettable = 0x00000004,
39 EnumOrFlag = 0x00000008,
40 Alias = 0x00000010,
41 // Reserved for future usage = 0x00000020,
42 StdCppSet = 0x00000100,
43 Constant = 0x00000400,
44 Final = 0x00000800,
45 Designable = 0x00001000,
46 Scriptable = 0x00004000,
47 Stored = 0x00010000,
48 User = 0x00100000,
49 Required = 0x01000000,
50 Bindable = 0x02000000
51};
52
53enum MethodFlags {
54 AccessPrivate = 0x00,
55 AccessProtected = 0x01,
56 AccessPublic = 0x02,
57 AccessMask = 0x03, // mask
58
59 MethodMethod = 0x00,
60 MethodSignal = 0x04,
61 MethodSlot = 0x08,
62 MethodConstructor = 0x0c,
63 MethodTypeMask = 0x0c,
64
65 MethodCompatibility = 0x10,
66 MethodCloned = 0x20,
67 MethodScriptable = 0x40,
68 MethodRevisioned = 0x80,
69
70 MethodIsConst = 0x100, // no use case for volatile so far
71};
72
73enum MetaObjectFlag {
74 DynamicMetaObject = 0x01,
75 RequiresVariantMetaObject = 0x02,
76 PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
77};
78Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
79Q_DECLARE_OPERATORS_FOR_FLAGS(MetaObjectFlags)
80
81enum MetaDataFlags {
82 IsUnresolvedType = 0x80000000,
83 TypeNameIndexMask = 0x7FFFFFFF,
84 IsUnresolvedSignal = 0x70000000
85};
86
87enum EnumFlags {
88 EnumIsFlag = 0x1,
89 EnumIsScoped = 0x2
90};
91
92Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *);
93
94class QArgumentType
95{
96public:
97 QArgumentType(int type)
98 : _type(type)
99 {}
100 QArgumentType(const QByteArray &name)
101 : _type(qMetaTypeTypeInternal(name.constData())), _name(name)
102 {}
103 QArgumentType()
104 : _type(0)
105 {}
106 int type() const
107 { return _type; }
108 QByteArray name() const
109 {
110 if (_type && _name.isEmpty())
111 const_cast<QArgumentType *>(this)->_name = QMetaType(_type).name();
112 return _name;
113 }
114 bool operator==(const QArgumentType &other) const
115 {
116 if (_type && other._type)
117 return _type == other._type;
118 else
119 return name() == other.name();
120 }
121 bool operator!=(const QArgumentType &other) const
122 {
123 if (_type && other._type)
124 return _type != other._type;
125 else
126 return name() != other.name();
127 }
128
129private:
130 int _type;
131 QByteArray _name;
132};
133Q_DECLARE_TYPEINFO(QArgumentType, Q_RELOCATABLE_TYPE);
134
135typedef QVarLengthArray<QArgumentType, 10> QArgumentTypeArray;
136
137namespace { class QMetaMethodPrivate; }
138class QMetaMethodInvoker : public QMetaMethod
139{
140 QMetaMethodInvoker() = delete;
141
142public:
143 enum class InvokeFailReason : int {
144 // negative values mean a match was found but the invocation failed
145 // (and a warning has been printed)
146 ReturnTypeMismatch = -1,
147 DeadLockDetected = -2,
148 CallViaVirtualFailed = -3, // no warning
149 ConstructorCallOnObject = -4,
150 ConstructorCallWithoutResult = -5,
151 ConstructorCallFailed = -6, // no warning
152
153 CouldNotQueueParameter = -0x1000,
154
155 // zero is success
156 None = 0,
157
158 // positive values mean the parameters did not match
159 TooFewArguments,
160 FormalParameterMismatch = 0x1000,
161 };
162
163 // shadows the public function
164 static InvokeFailReason Q_CORE_EXPORT
165 invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount,
166 const void *const *parameters, const char *const *typeNames,
167 const QtPrivate::QMetaTypeInterface *const *metaTypes);
168};
169
170struct QMetaObjectPrivate
171{
172 // revision 7 is Qt 5.0 everything lower is not supported
173 // revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
174 // revision 9 is Qt 6.0: It adds the metatype of properties and methods
175 // revision 10 is Qt 6.2: The metatype of the metaobject is stored in the metatypes array
176 // and metamethods store a flag stating whether they are const
177 // revision 11 is Qt 6.5: The metatype for void is stored in the metatypes array
178 // revision 12 is Qt 6.6: It adds the metatype for enums
179 enum { OutputRevision = 12 }; // Used by moc, qmetaobjectbuilder and qdbus
180 enum { IntsPerMethod = QMetaMethod::Data::Size };
181 enum { IntsPerEnum = QMetaEnum::Data::Size };
182 enum { IntsPerProperty = QMetaProperty::Data::Size };
183
184 int revision;
185 int className;
186 int classInfoCount, classInfoData;
187 int methodCount, methodData;
188 int propertyCount, propertyData;
189 int enumeratorCount, enumeratorData;
190 int constructorCount, constructorData;
191 int flags;
192 int signalCount;
193
194 static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
195 { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
196
197 static int originalClone(const QMetaObject *obj, int local_method_index);
198
199 static QByteArray decodeMethodSignature(const char *signature,
200 QArgumentTypeArray &types);
201 static int indexOfSignalRelative(const QMetaObject **baseObject,
202 const QByteArray &name, int argc,
203 const QArgumentType *types);
204 static int indexOfSlotRelative(const QMetaObject **m,
205 const QByteArray &name, int argc,
206 const QArgumentType *types);
207 static int indexOfSignal(const QMetaObject *m, const QByteArray &name,
208 int argc, const QArgumentType *types);
209 static int indexOfSlot(const QMetaObject *m, const QByteArray &name,
210 int argc, const QArgumentType *types);
211 static int indexOfMethod(const QMetaObject *m, const QByteArray &name,
212 int argc, const QArgumentType *types);
213 static int indexOfConstructor(const QMetaObject *m, const QByteArray &name,
214 int argc, const QArgumentType *types);
215 Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index);
216 static inline int signalOffset(const QMetaObject *m)
217 {
218 Q_ASSERT(m != nullptr);
219 int offset = 0;
220 for (m = m->d.superdata; m; m = m->d.superdata)
221 offset += reinterpret_cast<const QMetaObjectPrivate *>(m->d.data)->signalCount;
222 return offset;
223 }
224 Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m);
225 Q_CORE_EXPORT static int signalIndex(const QMetaMethod &m);
226 static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
227 int methodArgc, const QArgumentType *methodTypes);
228 static bool checkConnectArgs(const QMetaMethodPrivate *signal,
229 const QMetaMethodPrivate *method);
230
231 static QList<QByteArray> parameterTypeNamesFromSignature(const char *signature);
232
233#ifndef QT_NO_QOBJECT
234 // defined in qobject.cpp
235 enum DisconnectType { DisconnectAll, DisconnectOne };
236 static void memberIndexes(const QObject *obj, const QMetaMethod &member,
237 int *signalIndex, int *methodIndex);
238 static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index,
239 const QMetaObject *smeta,
240 const QObject *receiver, int method_index_relative,
241 const QMetaObject *rmeta = nullptr,
242 int type = 0, int *types = nullptr);
243 static bool disconnect(const QObject *sender, int signal_index,
244 const QMetaObject *smeta,
245 const QObject *receiver, int method_index, void **slot,
246 DisconnectType = DisconnectAll);
247 static inline bool disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
248 const QObject *receiver, int method_index, void **slot,
249 QBasicMutex *senderMutex, DisconnectType = DisconnectAll);
250#endif
251
252 template<int MethodType>
253 static inline int indexOfMethodRelative(const QMetaObject **baseObject,
254 const QByteArray &name, int argc,
255 const QArgumentType *types);
256
257 static bool methodMatch(const QMetaObject *m, const QMetaMethod &method,
258 const QByteArray &name, int argc,
259 const QArgumentType *types);
260 Q_CORE_EXPORT static QMetaMethod firstMethod(const QMetaObject *baseObject, QByteArrayView name);
261
262};
263
264// For meta-object generators
265
266enum { MetaObjectPrivateFieldCount = sizeof(QMetaObjectPrivate) / sizeof(int) };
267
268#ifndef UTILS_H
269// mirrored in moc's utils.h
270static inline bool is_ident_char(char s)
271{
272 return isAsciiLetterOrNumber(c: s) || s == '_';
273}
274
275static inline bool is_space(char s)
276{
277 return (s == ' ' || s == '\t');
278}
279#endif
280
281/*
282 This function is shared with moc.cpp. The implementation lives in qmetaobject_moc_p.h, which
283 should be included where needed. The declaration here is not used to avoid warnings from
284 the compiler about unused functions.
285
286static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true);
287*/
288
289QT_END_NAMESPACE
290
291#endif
292
293

source code of qtbase/src/corelib/kernel/qmetaobject_p.h