1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qfastmetabuilder_p.h"
46 struct QFastMetaBuilderHeader
51 struct QMetaObjectPrivate
55 int classInfoCount, classInfoData;
56 int methodCount, methodData;
57 int propertyCount, propertyData;
58 int enumeratorCount, enumeratorData;
59 int constructorCount, constructorData; //since revision 2
60 int flags; //since revision 3
61 int signalCount; //since revision 4
65 DynamicMetaObject = 0x01
70 Readable = 0x00000001,
71 Writable = 0x00000002,
72 Resettable = 0x00000004,
73 EnumOrFlag = 0x00000008,
74 StdCppSet = 0x00000100,
75 // Override = 0x00000200,
76 Constant = 0x00000400,
78 Designable = 0x00001000,
79 ResolveDesignable = 0x00002000,
80 Scriptable = 0x00004000,
81 ResolveScriptable = 0x00008000,
83 ResolveStored = 0x00020000,
84 Editable = 0x00040000,
85 ResolveEditable = 0x00080000,
87 ResolveUser = 0x00200000,
89 Revisioned = 0x00800000
94 AccessProtected = 0x01,
96 AccessMask = 0x03, //mask
101 MethodConstructor = 0x0c,
102 MethodTypeMask = 0x0c,
104 MethodCompatibility = 0x10,
106 MethodScriptable = 0x40,
107 MethodRevisioned = 0x80
110 #define FMBHEADER_FIELD_COUNT 1
112 #define HEADER_FIELD_COUNT 14
113 #define CLASSINFO_FIELD_COUNT 2
114 #define METHOD_FIELD_COUNT 5
115 #define PROPERTY_FIELD_COUNT 3
116 #define PROPERTY_NOTIFY_FIELD_COUNT 1
118 static inline uint *fieldPointer(QByteArray &data)
119 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
121 static inline const uint *fieldPointer(const QByteArray &data)
122 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
124 static inline QMetaObjectPrivate *priv(QByteArray &data)
125 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
127 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
128 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
130 static inline QFastMetaBuilderHeader *header(QByteArray &data)
131 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
133 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
134 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
136 QFastMetaBuilder::QFastMetaBuilder()
137 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
141 QFastMetaBuilder::~QFastMetaBuilder()
145 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
146 int propertyCount, int methodCount,
147 int signalCount, int classInfoCount)
149 Q_ASSERT(m_data.isEmpty());
150 Q_ASSERT(classNameLength > 0);
151 Q_ASSERT(propertyCount >= 0);
152 Q_ASSERT(methodCount >= 0);
153 Q_ASSERT(signalCount >= 0);
154 Q_ASSERT(classInfoCount >= 0);
156 int fieldCount = FMBHEADER_FIELD_COUNT +
158 propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
159 methodCount * (METHOD_FIELD_COUNT) +
160 signalCount * (METHOD_FIELD_COUNT) +
161 classInfoCount * CLASSINFO_FIELD_COUNT;
163 m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
164 m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
165 m_stringDataLength = classNameLength + 1;
166 m_stringDataAllocated = classNameLength + 1;
167 m_stringData[classNameLength] = 0;
168 m_zeroPtr = classNameLength;
170 header(m_data)->fieldCount = fieldCount;
172 QMetaObjectPrivate *p = priv(m_data);
174 int dataIndex = HEADER_FIELD_COUNT;
180 p->classInfoCount = classInfoCount;
181 if (p->classInfoCount) {
182 p->classInfoData = dataIndex;
183 dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
185 p->classInfoData = 0;
189 p->methodCount = methodCount + signalCount;
190 if (p->methodCount) {
191 p->methodData = dataIndex;
192 dataIndex += p->methodCount * METHOD_FIELD_COUNT;
196 p->signalCount = signalCount;
199 p->propertyCount = propertyCount;
200 if (p->propertyCount) {
201 p->propertyData = dataIndex;
202 dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
208 p->flags = DynamicMetaObject; // Always dynamic
210 // Enums and constructors not supported
211 p->enumeratorCount = 0;
212 p->enumeratorData = 0;
213 p->constructorCount = 0;
214 p->constructorData = 0;
219 className._l = classNameLength;
223 // Allocate a string of \a length. \a length should *not* include the null terminator.
224 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
226 Q_ASSERT(length > 0);
230 sr._o = m_stringDataLength;
233 m_stringDataLength += length + 1 /* for null terminator */;
238 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
240 Q_ASSERT(!m_data.isEmpty());
241 Q_ASSERT(!key.isEmpty() && !value.isEmpty());
243 QMetaObjectPrivate *p = priv(m_data);
244 Q_ASSERT(index < p->classInfoCount);
246 uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
247 // classinfo: key, value
248 ptr[0] = key.offset(); ptr[1] = value.offset();
251 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
252 QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
254 Q_ASSERT(!m_data.isEmpty());
255 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
257 QMetaObjectPrivate *p = priv(m_data);
258 Q_ASSERT(index < p->propertyCount);
261 if ((int)qtType == qMetaTypeId<QVariant>())
262 qtType = 0xFF; // Special handling for QVariant
264 uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
265 // properties: name, type, flags
266 ptr[0] = name.offset();
267 ptr[1] = type.offset();
268 if (notifySignal == -1) {
269 ptr[2] = qtType << 24;
270 ptr[2] |= flags | Scriptable | Readable;
271 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
273 ptr[2] = qtType << 24;
274 ptr[2] |= flags | Scriptable | Readable | Notify;
275 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
279 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
280 QFastMetaBuilder::PropertyFlag flags, int notifySignal)
282 Q_ASSERT(!m_data.isEmpty());
283 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
285 QMetaObjectPrivate *p = priv(m_data);
286 Q_ASSERT(index < p->propertyCount);
288 uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
289 // properties: name, type, flags
290 ptr[0] = name.offset();
291 ptr[1] = type.offset();
292 if (notifySignal == -1) {
293 ptr[2] = flags | Scriptable | Readable;
294 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
296 ptr[2] = flags | Scriptable | Readable | Notify;
297 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
301 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
302 const StringRef ¶meterNames,
303 const StringRef &type)
305 Q_ASSERT(!m_data.isEmpty());
306 Q_ASSERT(!signature.isEmpty());
308 QMetaObjectPrivate *p = priv(m_data);
309 int mindex = metaObjectIndexForSignal(index);
311 uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
312 // methods: signature, parameters, type, tag, flags
313 ptr[0] = signature.offset();
314 ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
315 ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
317 ptr[4] = AccessProtected | MethodSignal;
320 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
321 const StringRef ¶meterNames,
322 const StringRef &type)
324 Q_ASSERT(!m_data.isEmpty());
325 Q_ASSERT(!signature.isEmpty());
327 QMetaObjectPrivate *p = priv(m_data);
328 int mindex = metaObjectIndexForMethod(index);
330 uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
331 // methods: signature, parameters, type, tag, flags
332 ptr[0] = signature.offset();
333 ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
334 ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
336 ptr[4] = AccessProtected | MethodSlot;
339 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
341 Q_ASSERT(!m_data.isEmpty());
342 Q_ASSERT(index < priv(m_data)->signalCount);
346 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
348 Q_ASSERT(!m_data.isEmpty());
350 const QMetaObjectPrivate *p = priv(m_data);
351 Q_ASSERT(index < (p->methodCount - p->signalCount));
352 return index + p->signalCount;
355 void QFastMetaBuilder::allocateStringData()
357 if (m_stringDataAllocated < m_stringDataLength) {
358 m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
359 m_stringDataAllocated = m_stringDataLength;
360 m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
364 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
366 output->d.superdata = parent;
367 output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
368 output->d.data = fieldPointer(data);