Update copyright year in license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / ftw / qfastmetabuilder.cpp
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 QtDeclarative 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 #include "qfastmetabuilder_p.h"
43 #include "qvariant.h"
44
45 #include <QtCore/qmetaobject.h>
46
47 QT_BEGIN_NAMESPACE
48
49 struct QFastMetaBuilderHeader
50 {
51     int fieldCount;
52 };
53
54 struct QMetaObjectPrivate 
55 {
56     int revision;
57     int className;
58     int classInfoCount, classInfoData;
59     int methodCount, methodData;
60     int propertyCount, propertyData;
61     int enumeratorCount, enumeratorData;
62     int constructorCount, constructorData; //since revision 2
63     int flags; //since revision 3
64     int signalCount; //since revision 4
65 };
66
67 enum MetaObjectFlag {
68     DynamicMetaObject = 0x01
69 };
70
71 enum PropertyFlags  {
72     Invalid = 0x00000000,
73     Readable = 0x00000001,
74     Writable = 0x00000002,
75     Resettable = 0x00000004,
76     EnumOrFlag = 0x00000008,
77     StdCppSet = 0x00000100,
78 //     Override = 0x00000200,
79     Constant = 0x00000400,
80     Final = 0x00000800,
81     Designable = 0x00001000,
82     ResolveDesignable = 0x00002000,
83     Scriptable = 0x00004000,
84     ResolveScriptable = 0x00008000,
85     Stored = 0x00010000,
86     ResolveStored = 0x00020000,
87     Editable = 0x00040000,
88     ResolveEditable = 0x00080000,
89     User = 0x00100000,
90     ResolveUser = 0x00200000,
91     Notify = 0x00400000,
92     Revisioned = 0x00800000
93 };
94
95 enum MethodFlags  {
96     AccessPrivate = 0x00,
97     AccessProtected = 0x01,
98     AccessPublic = 0x02,
99     AccessMask = 0x03, //mask
100
101     MethodMethod = 0x00,
102     MethodSignal = 0x04,
103     MethodSlot = 0x08,
104     MethodConstructor = 0x0c,
105     MethodTypeMask = 0x0c,
106
107     MethodCompatibility = 0x10,
108     MethodCloned = 0x20,
109     MethodScriptable = 0x40,
110     MethodRevisioned = 0x80
111 };
112
113 #define FMBHEADER_FIELD_COUNT 1
114
115 #define HEADER_FIELD_COUNT 14
116 #define CLASSINFO_FIELD_COUNT 2
117 #define METHOD_FIELD_COUNT 5
118 #define PROPERTY_FIELD_COUNT 3
119 #define PROPERTY_NOTIFY_FIELD_COUNT 1
120
121 static inline uint *fieldPointer(QByteArray &data)
122 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
123
124 static inline const uint *fieldPointer(const QByteArray &data)
125 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
126
127 static inline QMetaObjectPrivate *priv(QByteArray &data)
128 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
129
130 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
131 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
132
133 static inline QFastMetaBuilderHeader *header(QByteArray &data)
134 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
135
136 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
137 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
138
139 QFastMetaBuilder::QFastMetaBuilder()
140 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
141 {
142 }
143
144 QFastMetaBuilder::~QFastMetaBuilder()
145 {
146 }
147
148 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
149                                                    int propertyCount, int methodCount, 
150                                                    int signalCount, int classInfoCount)
151 {
152     Q_ASSERT(m_data.isEmpty());
153     Q_ASSERT(classNameLength > 0);
154     Q_ASSERT(propertyCount >= 0);
155     Q_ASSERT(methodCount >= 0);
156     Q_ASSERT(signalCount >= 0);
157     Q_ASSERT(classInfoCount >= 0);
158
159     int fieldCount = FMBHEADER_FIELD_COUNT +
160                      HEADER_FIELD_COUNT + 
161                      propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
162                      methodCount * (METHOD_FIELD_COUNT) +
163                      signalCount * (METHOD_FIELD_COUNT) +
164                      classInfoCount * CLASSINFO_FIELD_COUNT;
165
166     m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
167     m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
168     m_stringDataLength = classNameLength + 1;
169     m_stringDataAllocated = classNameLength + 1;
170     m_stringData[classNameLength] = 0;
171     m_zeroPtr = classNameLength;
172
173     header(m_data)->fieldCount = fieldCount;
174
175     QMetaObjectPrivate *p = priv(m_data);
176
177     int dataIndex = HEADER_FIELD_COUNT;
178
179     p->revision = 4;
180     p->className = 0;
181
182     // Class infos
183     p->classInfoCount = classInfoCount;
184     if (p->classInfoCount) { 
185         p->classInfoData = dataIndex;
186         dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
187     } else {
188         p->classInfoData = 0;
189     }
190
191     // Methods
192     p->methodCount = methodCount + signalCount;
193     if (p->methodCount) {
194         p->methodData = dataIndex;
195         dataIndex += p->methodCount * METHOD_FIELD_COUNT;
196     } else {
197         p->methodData = 0;
198     }
199     p->signalCount = signalCount;
200
201     // Properties
202     p->propertyCount = propertyCount;
203     if (p->propertyCount) {
204         p->propertyData = dataIndex;
205         dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
206     } else {
207         p->propertyData = 0;
208     }
209
210     // Flags
211     p->flags = DynamicMetaObject; // Always dynamic
212
213     // Enums and constructors not supported
214     p->enumeratorCount = 0;
215     p->enumeratorData = 0;
216     p->constructorCount = 0;
217     p->constructorData = 0;
218
219     StringRef className;
220     className._b = this;
221     className._o = 0;
222     className._l = classNameLength;
223     return className;
224 }
225
226 // Allocate a string of \a length.  \a length should *not* include the null terminator.
227 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
228 {
229     Q_ASSERT(length > 0);
230
231     StringRef sr;
232     sr._b = this;
233     sr._o = m_stringDataLength;
234     sr._l = length;
235
236     m_stringDataLength += length + 1 /* for null terminator */;
237
238     return sr;
239 }
240
241 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
242 {
243     Q_ASSERT(!m_data.isEmpty());
244     Q_ASSERT(!key.isEmpty() && !value.isEmpty());
245
246     QMetaObjectPrivate *p = priv(m_data);
247     Q_ASSERT(index < p->classInfoCount);
248
249     uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
250     // classinfo: key, value
251     ptr[0] = key.offset(); ptr[1] = value.offset();
252 }
253
254 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
255                                    QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
256 {
257     Q_ASSERT(!m_data.isEmpty());
258     Q_ASSERT(!name.isEmpty() && !type.isEmpty());
259
260     QMetaObjectPrivate *p = priv(m_data);
261     Q_ASSERT(index < p->propertyCount);
262
263     uint qtType = mtype;
264     if ((int)qtType == qMetaTypeId<QVariant>())
265         qtType = 0xFF; // Special handling for QVariant
266
267     uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
268     // properties: name, type, flags
269     ptr[0] = name.offset();
270     ptr[1] = type.offset();
271     if (notifySignal == -1) {
272         ptr[2] = qtType << 24;
273         ptr[2] |= flags | Scriptable | Readable;
274         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
275     } else {
276         ptr[2] = qtType << 24;
277         ptr[2] |= flags | Scriptable | Readable | Notify;
278         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
279     }
280 }
281
282 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type, 
283                                    QFastMetaBuilder::PropertyFlag flags, int notifySignal)
284 {
285     Q_ASSERT(!m_data.isEmpty());
286     Q_ASSERT(!name.isEmpty() && !type.isEmpty());
287
288     QMetaObjectPrivate *p = priv(m_data);
289     Q_ASSERT(index < p->propertyCount);
290
291     uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
292     // properties: name, type, flags
293     ptr[0] = name.offset();
294     ptr[1] = type.offset();
295     if (notifySignal == -1) {
296         ptr[2] = flags | Scriptable | Readable;
297         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
298     } else {
299         ptr[2] = flags | Scriptable | Readable | Notify;
300         *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
301     }
302 }
303
304 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
305                                  const StringRef &parameterNames,
306                                  const StringRef &type)
307 {
308     Q_ASSERT(!m_data.isEmpty());
309     Q_ASSERT(!signature.isEmpty());
310
311     QMetaObjectPrivate *p = priv(m_data);
312     int mindex = metaObjectIndexForSignal(index);
313
314     uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
315     // methods: signature, parameters, type, tag, flags
316     ptr[0] = signature.offset();
317     ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
318     ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
319     ptr[3] = m_zeroPtr;
320     ptr[4] = AccessProtected | MethodSignal;
321 }
322
323 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
324                                  const StringRef &parameterNames,
325                                  const StringRef &type)
326 {
327     Q_ASSERT(!m_data.isEmpty());
328     Q_ASSERT(!signature.isEmpty());
329
330     QMetaObjectPrivate *p = priv(m_data);
331     int mindex = metaObjectIndexForMethod(index);
332
333     uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
334     // methods: signature, parameters, type, tag, flags
335     ptr[0] = signature.offset();
336     ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
337     ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
338     ptr[3] = m_zeroPtr;
339     ptr[4] = AccessProtected | MethodSlot;
340 }
341
342 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
343 {
344     Q_ASSERT(!m_data.isEmpty());
345     Q_ASSERT(index < priv(m_data)->signalCount);
346     return index;
347 }
348
349 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
350 {
351     Q_ASSERT(!m_data.isEmpty());
352
353     const QMetaObjectPrivate *p = priv(m_data);
354     Q_ASSERT(index < (p->methodCount - p->signalCount));
355     return index + p->signalCount;
356 }
357
358 void QFastMetaBuilder::allocateStringData()
359 {
360     if (m_stringDataAllocated < m_stringDataLength) {
361         m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
362         m_stringDataAllocated = m_stringDataLength;
363         m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
364     }
365 }
366
367 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
368 {
369     output->d.superdata = parent;
370     output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
371     output->d.data = fieldPointer(data);
372 }
373
374 QT_END_NAMESPACE