1 /****************************************************************************
3 ** Copyright (C) 2012 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"
45 #include <QtCore/qmetaobject.h>
49 struct QFastMetaBuilderHeader
54 struct QMetaObjectPrivate
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
68 DynamicMetaObject = 0x01
73 Readable = 0x00000001,
74 Writable = 0x00000002,
75 Resettable = 0x00000004,
76 EnumOrFlag = 0x00000008,
77 StdCppSet = 0x00000100,
78 // Override = 0x00000200,
79 Constant = 0x00000400,
81 Designable = 0x00001000,
82 ResolveDesignable = 0x00002000,
83 Scriptable = 0x00004000,
84 ResolveScriptable = 0x00008000,
86 ResolveStored = 0x00020000,
87 Editable = 0x00040000,
88 ResolveEditable = 0x00080000,
90 ResolveUser = 0x00200000,
92 Revisioned = 0x00800000
97 AccessProtected = 0x01,
99 AccessMask = 0x03, //mask
104 MethodConstructor = 0x0c,
105 MethodTypeMask = 0x0c,
107 MethodCompatibility = 0x10,
109 MethodScriptable = 0x40,
110 MethodRevisioned = 0x80
113 #define FMBHEADER_FIELD_COUNT 1
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
121 static inline uint *fieldPointer(QByteArray &data)
122 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
124 static inline const uint *fieldPointer(const QByteArray &data)
125 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
127 static inline QMetaObjectPrivate *priv(QByteArray &data)
128 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
130 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
131 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
133 static inline QFastMetaBuilderHeader *header(QByteArray &data)
134 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
136 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
137 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
139 QFastMetaBuilder::QFastMetaBuilder()
140 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
144 QFastMetaBuilder::~QFastMetaBuilder()
148 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
149 int propertyCount, int methodCount,
150 int signalCount, int classInfoCount)
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);
159 int fieldCount = FMBHEADER_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;
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;
173 header(m_data)->fieldCount = fieldCount;
175 QMetaObjectPrivate *p = priv(m_data);
177 int dataIndex = HEADER_FIELD_COUNT;
183 p->classInfoCount = classInfoCount;
184 if (p->classInfoCount) {
185 p->classInfoData = dataIndex;
186 dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
188 p->classInfoData = 0;
192 p->methodCount = methodCount + signalCount;
193 if (p->methodCount) {
194 p->methodData = dataIndex;
195 dataIndex += p->methodCount * METHOD_FIELD_COUNT;
199 p->signalCount = signalCount;
202 p->propertyCount = propertyCount;
203 if (p->propertyCount) {
204 p->propertyData = dataIndex;
205 dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
211 p->flags = DynamicMetaObject; // Always dynamic
213 // Enums and constructors not supported
214 p->enumeratorCount = 0;
215 p->enumeratorData = 0;
216 p->constructorCount = 0;
217 p->constructorData = 0;
222 className._l = classNameLength;
226 // Allocate a string of \a length. \a length should *not* include the null terminator.
227 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
229 Q_ASSERT(length > 0);
233 sr._o = m_stringDataLength;
236 m_stringDataLength += length + 1 /* for null terminator */;
241 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
243 Q_ASSERT(!m_data.isEmpty());
244 Q_ASSERT(!key.isEmpty() && !value.isEmpty());
246 QMetaObjectPrivate *p = priv(m_data);
247 Q_ASSERT(index < p->classInfoCount);
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();
254 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
255 QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
257 Q_ASSERT(!m_data.isEmpty());
258 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
260 QMetaObjectPrivate *p = priv(m_data);
261 Q_ASSERT(index < p->propertyCount);
264 if ((int)qtType == qMetaTypeId<QVariant>())
265 qtType = 0xFF; // Special handling for QVariant
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;
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;
282 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
283 QFastMetaBuilder::PropertyFlag flags, int notifySignal)
285 Q_ASSERT(!m_data.isEmpty());
286 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
288 QMetaObjectPrivate *p = priv(m_data);
289 Q_ASSERT(index < p->propertyCount);
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;
299 ptr[2] = flags | Scriptable | Readable | Notify;
300 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
304 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
305 const StringRef ¶meterNames,
306 const StringRef &type)
308 Q_ASSERT(!m_data.isEmpty());
309 Q_ASSERT(!signature.isEmpty());
311 QMetaObjectPrivate *p = priv(m_data);
312 int mindex = metaObjectIndexForSignal(index);
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();
320 ptr[4] = AccessProtected | MethodSignal;
323 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
324 const StringRef ¶meterNames,
325 const StringRef &type)
327 Q_ASSERT(!m_data.isEmpty());
328 Q_ASSERT(!signature.isEmpty());
330 QMetaObjectPrivate *p = priv(m_data);
331 int mindex = metaObjectIndexForMethod(index);
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();
339 ptr[4] = AccessProtected | MethodSlot;
342 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
344 Q_ASSERT(!m_data.isEmpty());
345 Q_ASSERT(index < priv(m_data)->signalCount);
349 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
351 Q_ASSERT(!m_data.isEmpty());
353 const QMetaObjectPrivate *p = priv(m_data);
354 Q_ASSERT(index < (p->methodCount - p->signalCount));
355 return index + p->signalCount;
358 void QFastMetaBuilder::allocateStringData()
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);
367 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
369 output->d.superdata = parent;
370 output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
371 output->d.data = fieldPointer(data);