1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtCore module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#ifndef QMETAOBJECT_P_H
43
#define QMETAOBJECT_P_H
44
45
//
46
//  W A R N I N G
47
//  -------------
48
//
49
// This file is not part of the Qt API.  It exists for the convenience
50
// of moc.  This header file may change from version to version without notice,
51
// or even be removed.
52
//
53
// We mean it.
54
//
55
56
#include <QtCore/qglobal.h>
57
#include <QtCore/qobjectdefs.h>
58
59
QT_BEGIN_NAMESPACE
60
61
enum PropertyFlags  {
62
    Invalid = 0x00000000,
63
    Readable = 0x00000001,
64
    Writable = 0x00000002,
65
    Resettable = 0x00000004,
66
    EnumOrFlag = 0x00000008,
67
    StdCppSet = 0x00000100,
68
//     Override = 0x00000200,
69
    Constant = 0x00000400,
70
    Final = 0x00000800,
71
    Designable = 0x00001000,
72
    ResolveDesignable = 0x00002000,
73
    Scriptable = 0x00004000,
74
    ResolveScriptable = 0x00008000,
75
    Stored = 0x00010000,
76
    ResolveStored = 0x00020000,
77
    Editable = 0x00040000,
78
    ResolveEditable = 0x00080000,
79
    User = 0x00100000,
80
    ResolveUser = 0x00200000,
81
    Notify = 0x00400000,
82
    Revisioned = 0x00800000
83
};
84
85
enum MethodFlags  {
86
    AccessPrivate = 0x00,
87
    AccessProtected = 0x01,
88
    AccessPublic = 0x02,
89
    AccessMask = 0x03, //mask
90
91
    MethodMethod = 0x00,
92
    MethodSignal = 0x04,
93
    MethodSlot = 0x08,
94
    MethodConstructor = 0x0c,
95
    MethodTypeMask = 0x0c,
96
97
    MethodCompatibility = 0x10,
98
    MethodCloned = 0x20,
99
    MethodScriptable = 0x40,
100
    MethodRevisioned = 0x80
101
};
102
103
enum MetaObjectFlags {
104
    DynamicMetaObject = 0x01
105
};
106
107
class QMutex;
108
109
struct QMetaObjectPrivate
110
{
111
    int revision;
112
    int className;
113
    int classInfoCount, classInfoData;
114
    int methodCount, methodData;
115
    int propertyCount, propertyData;
116
    int enumeratorCount, enumeratorData;
117
    int constructorCount, constructorData; //since revision 2
118
    int flags; //since revision 3
119
    int signalCount; //since revision 4
120
    // revision 5 introduces changes in normalized signatures, no new members
121
    // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
122
123
    static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
124
    { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
125
126
    static int indexOfSignalRelative(const QMetaObject **baseObject,
127
                                     const char* name,
128
                                     bool normalizeStringData);
129
    static int indexOfSlotRelative(const QMetaObject **m,
130
                           const char *slot,
131
                           bool normalizeStringData);
132
    static int originalClone(const QMetaObject *obj, int local_method_index);
133
134
#ifndef QT_NO_QOBJECT
135
    //defined in qobject.cpp
136
    enum DisconnectType { DisconnectAll, DisconnectOne };
137
    static void memberIndexes(const QObject *obj, const QMetaMethod &member,
138
                              int *signalIndex, int *methodIndex);
139
    static bool connect(const QObject *sender, int signal_index,
140
                        const QObject *receiver, int method_index_relative,
141
                        const QMetaObject *rmeta = 0,
142
                        int type = 0, int *types = 0);
143
    static bool disconnect(const QObject *sender, int signal_index,
144
                           const QObject *receiver, int method_index,
145
                           DisconnectType = DisconnectAll);
146
    static inline bool disconnectHelper(QObjectPrivate::Connection *c,
147
                                        const QObject *receiver, int method_index,
148
                                        QMutex *senderMutex, DisconnectType);
149
#endif
150
};
151
152
#ifndef UTILS_H
153
// mirrored in moc's utils.h
154
static inline bool is_ident_char(char s)
155
{
156
    return ((s >= 'a' && s <= 'z')
157
            || (s >= 'A' && s <= 'Z')
158
            || (s >= '0' && s <= '9')
159
            || s == '_'
160
       );
161
}
162
163
static inline bool is_space(char s)
164
{
165
    return (s == ' ' || s == '\t');
166
}
167
#endif
168
169
// This code is shared with moc.cpp
170
static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
171
{
172
    int len = e - t;
173
    /*
174
      Convert 'char const *' into 'const char *'. Start at index 1,
175
      not 0, because 'const char *' is already OK.
176
    */
177
    QByteArray constbuf;
178
    for (int i = 1; i < len; i++) {
179
        if ( t[i] == 'c'
180
             && strncmp(t + i + 1, "onst", 4) == 0
181
             && (i + 5 >= len || !is_ident_char(t[i + 5]))
182
             && !is_ident_char(t[i-1])
183
             ) {
184
            constbuf = QByteArray(t, len);
185
            if (is_space(t[i-1]))
186
                constbuf.remove(i-1, 6);
187
            else
188
                constbuf.remove(i, 5);
189
            constbuf.prepend("const ");
190
            t = constbuf.data();
191
            e = constbuf.data() + constbuf.length();
192
            break;
193
        }
194
        /*
195
          We musn't convert 'char * const *' into 'const char **'
196
          and we must beware of 'Bar<const Bla>'.
197
        */
198
        if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
199
            break;
200
    }
201
    if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) {
202
        if (*(e-1) == '&') { // treat const reference as value
203
            t += 6;
204
            --e;
205
        } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value
206
            t += 6;
207
        }
208
    }
209
    QByteArray result;
210
    result.reserve(len);
211
212
#if 1
213
    // consume initial 'const '
214
    if (strncmp("const ", t, 6) == 0) {
215
        t+= 6;
216
        result += "const ";
217
    }
218
#endif
219
220
    // some type substitutions for 'unsigned x'
221
    if (strncmp("unsigned", t, 8) == 0) {
222
        // make sure "unsigned" is an isolated word before making substitutions
223
        if (!t[8] || !is_ident_char(t[8])) {
224
            if (strncmp(" int", t+8, 4) == 0) {
225
                t += 8+4;
226
                result += "uint";
227
            } else if (strncmp(" long", t+8, 5) == 0) {
228
                if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int'
229
                    && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long'
230
                   ) {
231
                    t += 8+5;
232
                    result += "ulong";
233
                }
234
            } else if (strncmp(" short", t+8, 6) != 0  // preserve unsigned short
235
                && strncmp(" char", t+8, 5) != 0) {    // preserve unsigned char
236
                //  treat rest (unsigned) as uint
237
                t += 8;
238
                result += "uint";
239
            }
240
        }
241
    } else {
242
        // discard 'struct', 'class', and 'enum'; they are optional
243
        // and we don't want them in the normalized signature
244
        struct {
245
            const char *keyword;
246
            int len;
247
        } optional[] = {
248
            { "struct ", 7 },
249
            { "class ", 6 },
250
            { "enum ", 5 },
251
            { 0, 0 }
252
        };
253
        int i = 0;
254
        do {
255
            if (strncmp(optional[i].keyword, t, optional[i].len) == 0) {
256
                t += optional[i].len;
257
                break;
258
            }
259
        } while (optional[++i].keyword != 0);
260
    }
261
262
    bool star = false;
263
    while (t != e) {
264
        char c = *t++;
265
        if (fixScope && c == ':' && *t == ':' ) {
266
            ++t;
267
            c = *t++;
268
            int i = result.size() - 1;
269
            while (i >= 0 && is_ident_char(result.at(i)))
270
                --i;
271
            result.resize(i + 1);
272
        }
273
        star = star || c == '*';
274
        result += c;
275
        if (c == '<') {
276
            //template recursion
277
            const char* tt = t;
278
            int templdepth = 1;
279
            while (t != e) {
280
                c = *t++;
281
                if (c == '<')
282
                    ++templdepth;
283
                if (c == '>')
284
                    --templdepth;
285
                if (templdepth == 0 || (templdepth == 1 && c == ',')) {
286
                    result += normalizeTypeInternal(tt, t-1, fixScope, false);
287
                    result += c;
288
                    if (templdepth == 0) {
289
                        if (*t == '>')
290
                            result += ' '; // avoid >>
291
                        break;
292
                    }
293
                    tt = t;
294
                }
295
            }
296
        }
297
298
        // cv qualifers can appear after the type as well
299
        if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)
300
            && (e - t == 5 || !is_ident_char(t[5]))) {
301
            t += 5;
302
            while (t != e && is_space(*t))
303
                ++t;
304
            if (adjustConst && t != e && *t == '&') {
305
                // treat const ref as value
306
                ++t;
307
            } else if (adjustConst && !star) {
308
                // treat const as value
309
            } else if (!star) {
310
                // move const to the front (but not if const comes after a *)
311
                result.prepend("const ");
312
            } else {
313
                // keep const after a *
314
                result += "const";
315
            }
316
        }
317
    }
318
319
    return result;
320
}
321
322
323
QT_END_NAMESPACE
324
325
#endif