Adapt to Qt5 meta-object changes
[profile/ivi/qtdeclarative.git] / src / qml / qml / ftw / qfastmetabuilder.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qfastmetabuilder_p.h"
43
44 #include <QtCore/qmetaobject.h>
45 #include <private/qobject_p.h>
46 #include <private/qmetaobject_p.h>
47
48 QT_BEGIN_NAMESPACE
49
50 struct QFastMetaBuilderHeader
51 {
52     int fieldCount;
53 };
54
55 #define FMBHEADER_FIELD_COUNT 1
56
57 #define HEADER_FIELD_COUNT 14
58 #define CLASSINFO_FIELD_COUNT 2
59 #define METHOD_FIELD_COUNT 5
60 #define PROPERTY_FIELD_COUNT 3
61 #define PROPERTY_NOTIFY_FIELD_COUNT 1
62
63 static inline uint *fieldPointer(QByteArray &data)
64 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
65
66 static inline const uint *fieldPointer(const QByteArray &data)
67 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
68
69 static inline QMetaObjectPrivate *priv(QByteArray &data)
70 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
71
72 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
73 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
74
75 static inline QFastMetaBuilderHeader *header(QByteArray &data)
76 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
77
78 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
79 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
80
81 QFastMetaBuilder::QFastMetaBuilder()
82 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
83 {
84 }
85
86 QFastMetaBuilder::~QFastMetaBuilder()
87 {
88 }
89
90 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
91                                                    int propertyCount, int methodCount, 
92                                                    int signalCount, int classInfoCount)
93 {
94     Q_ASSERT(m_data.isEmpty());
95     Q_ASSERT(classNameLength > 0);
96     Q_ASSERT(propertyCount >= 0);
97     Q_ASSERT(methodCount >= 0);
98     Q_ASSERT(signalCount >= 0);
99     Q_ASSERT(classInfoCount >= 0);
100
101     int fieldCount = FMBHEADER_FIELD_COUNT +
102                      HEADER_FIELD_COUNT + 
103                      propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
104                      methodCount * (METHOD_FIELD_COUNT) +
105                      signalCount * (METHOD_FIELD_COUNT) +
106                      classInfoCount * CLASSINFO_FIELD_COUNT;
107
108     m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
109     m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
110     m_stringDataLength = classNameLength + 1;
111     m_stringDataAllocated = classNameLength + 1;
112     m_stringData[classNameLength] = 0;
113     m_zeroPtr = classNameLength;
114
115     header(m_data)->fieldCount = fieldCount;
116
117     QMetaObjectPrivate *p = priv(m_data);
118
119     int dataIndex = HEADER_FIELD_COUNT;
120
121     p->revision = 6;
122     p->className = 0;
123
124     // Class infos
125     p->classInfoCount = classInfoCount;
126     if (p->classInfoCount) { 
127         p->classInfoData = dataIndex;
128         dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
129     } else {
130         p->classInfoData = 0;
131     }
132
133     // Methods
134     p->methodCount = methodCount + signalCount;
135     if (p->methodCount) {
136         p->methodData = dataIndex;
137         dataIndex += p->methodCount * METHOD_FIELD_COUNT;
138     } else {
139         p->methodData = 0;
140     }
141     p->signalCount = signalCount;
142
143     // Properties
144     p->propertyCount = propertyCount;
145     if (p->propertyCount) {
146         p->propertyData = dataIndex;
147         dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
148     } else {
149         p->propertyData = 0;
150     }
151
152     // Flags
153     p->flags = DynamicMetaObject; // Always dynamic
154
155     // Enums and constructors not supported
156     p->enumeratorCount = 0;
157     p->enumeratorData = 0;
158     p->constructorCount = 0;
159     p->constructorData = 0;
160
161     StringRef className;
162     className._b = this;
163     className._o = 0;
164     className._l = classNameLength;
165     return className;
166 }
167
168 // Allocate a string of \a length.  \a length should *not* include the null terminator.
169 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
170 {
171     Q_ASSERT(length > 0);
172
173     StringRef sr;
174     sr._b = this;
175     sr._o = m_stringDataLength;
176     sr._l = length;
177
178     m_stringDataLength += length + 1 /* for null terminator */;
179
180     return sr;
181 }
182
183 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
184 {
185     Q_ASSERT(!m_data.isEmpty());
186     Q_ASSERT(!key.isEmpty() && !value.isEmpty());
187
188     QMetaObjectPrivate *p = priv(m_data);
189     Q_ASSERT(index < p->classInfoCount);
190
191     uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
192     // classinfo: key, value
193     ptr[0] = key.offset(); ptr[1] = value.offset();
194 }
195
196 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
197                                    QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
198 {
199     Q_ASSERT(!m_data.isEmpty());
200     Q_ASSERT(!name.isEmpty());
201     Q_ASSERT(!type.isEmpty());
202
203     QMetaObjectPrivate *p = priv(m_data);
204     Q_ASSERT(index < p->propertyCount);
205
206     uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
207     // properties: name, type, flags
208     ptr[0] = name.offset();
209     ptr[1] = type.offset();
210     if (notifySignal == -1) {
211         ptr[2] = mtype << 24;
212         ptr[2] |= flags | Scriptable | Readable;
213         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
214     } else {
215         ptr[2] = mtype << 24;
216         ptr[2] |= flags | Scriptable | Readable | Notify;
217         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
218     }
219 }
220
221 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
222                                    QFastMetaBuilder::PropertyFlag flags, int notifySignal)
223 {
224     Q_ASSERT(!m_data.isEmpty());
225     Q_ASSERT(!name.isEmpty() && !type.isEmpty());
226
227     QMetaObjectPrivate *p = priv(m_data);
228     Q_ASSERT(index < p->propertyCount);
229
230     uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
231     // properties: name, type, flags
232     ptr[0] = name.offset();
233     ptr[1] = type.offset();
234     if (notifySignal == -1) {
235         ptr[2] = flags | Scriptable | Readable;
236         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
237     } else {
238         ptr[2] = flags | Scriptable | Readable | Notify;
239         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
240     }
241 }
242
243 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
244                                  const StringRef &parameterNames,
245                                  const StringRef &type)
246 {
247     Q_ASSERT(!m_data.isEmpty());
248     Q_ASSERT(!signature.isEmpty());
249
250     QMetaObjectPrivate *p = priv(m_data);
251     int mindex = metaObjectIndexForSignal(index);
252
253     uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
254     // methods: signature, parameters, type, tag, flags
255     ptr[0] = signature.offset();
256     ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
257     ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
258     ptr[3] = m_zeroPtr;
259     ptr[4] = AccessProtected | MethodSignal;
260 }
261
262 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
263                                  const StringRef &parameterNames,
264                                  const StringRef &type)
265 {
266     Q_ASSERT(!m_data.isEmpty());
267     Q_ASSERT(!signature.isEmpty());
268
269     QMetaObjectPrivate *p = priv(m_data);
270     int mindex = metaObjectIndexForMethod(index);
271
272     uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
273     // methods: signature, parameters, type, tag, flags
274     ptr[0] = signature.offset();
275     ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
276     ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
277     ptr[3] = m_zeroPtr;
278     ptr[4] = AccessProtected | MethodSlot;
279 }
280
281 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
282 {
283     Q_ASSERT(!m_data.isEmpty());
284     Q_ASSERT(index < priv(m_data)->signalCount);
285     return index;
286 }
287
288 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
289 {
290     Q_ASSERT(!m_data.isEmpty());
291
292     const QMetaObjectPrivate *p = priv(m_data);
293     Q_ASSERT(index < (p->methodCount - p->signalCount));
294     return index + p->signalCount;
295 }
296
297 void QFastMetaBuilder::allocateStringData()
298 {
299     if (m_stringDataAllocated < m_stringDataLength) {
300         m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
301         m_stringDataAllocated = m_stringDataLength;
302         m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
303     }
304 }
305
306 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
307 {
308     output->d.superdata = parent;
309     output->d.stringdata = reinterpret_cast<const QByteArrayData *>(data.constData() + header(data)->fieldCount * sizeof(uint));
310     output->d.data = fieldPointer(data);
311     output->d.extradata = 0;
312 }
313
314 QT_END_NAMESPACE