1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qfastmetabuilder_p.h"
44 #include <QtCore/qmetaobject.h>
48 struct QFastMetaBuilderHeader
53 struct QMetaObjectPrivate
57 int classInfoCount, classInfoData;
58 int methodCount, methodData;
59 int propertyCount, propertyData;
60 int enumeratorCount, enumeratorData;
61 int constructorCount, constructorData; //since revision 2
62 int flags; //since revision 3
63 int signalCount; //since revision 4
67 DynamicMetaObject = 0x01
72 Readable = 0x00000001,
73 Writable = 0x00000002,
74 Resettable = 0x00000004,
75 EnumOrFlag = 0x00000008,
76 StdCppSet = 0x00000100,
77 // Override = 0x00000200,
78 Constant = 0x00000400,
80 Designable = 0x00001000,
81 ResolveDesignable = 0x00002000,
82 Scriptable = 0x00004000,
83 ResolveScriptable = 0x00008000,
85 ResolveStored = 0x00020000,
86 Editable = 0x00040000,
87 ResolveEditable = 0x00080000,
89 ResolveUser = 0x00200000,
91 Revisioned = 0x00800000
96 AccessProtected = 0x01,
98 AccessMask = 0x03, //mask
103 MethodConstructor = 0x0c,
104 MethodTypeMask = 0x0c,
106 MethodCompatibility = 0x10,
108 MethodScriptable = 0x40,
109 MethodRevisioned = 0x80
112 #define FMBHEADER_FIELD_COUNT 1
114 #define HEADER_FIELD_COUNT 14
115 #define CLASSINFO_FIELD_COUNT 2
116 #define METHOD_FIELD_COUNT 5
117 #define PROPERTY_FIELD_COUNT 3
118 #define PROPERTY_NOTIFY_FIELD_COUNT 1
120 static inline uint *fieldPointer(QByteArray &data)
121 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
123 static inline const uint *fieldPointer(const QByteArray &data)
124 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
126 static inline QMetaObjectPrivate *priv(QByteArray &data)
127 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
129 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
130 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
132 static inline QFastMetaBuilderHeader *header(QByteArray &data)
133 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
135 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
136 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
138 QFastMetaBuilder::QFastMetaBuilder()
139 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
143 QFastMetaBuilder::~QFastMetaBuilder()
147 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
148 int propertyCount, int methodCount,
149 int signalCount, int classInfoCount)
151 Q_ASSERT(m_data.isEmpty());
152 Q_ASSERT(classNameLength > 0);
153 Q_ASSERT(propertyCount >= 0);
154 Q_ASSERT(methodCount >= 0);
155 Q_ASSERT(signalCount >= 0);
156 Q_ASSERT(classInfoCount >= 0);
158 int fieldCount = FMBHEADER_FIELD_COUNT +
160 propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT) +
161 methodCount * (METHOD_FIELD_COUNT) +
162 signalCount * (METHOD_FIELD_COUNT) +
163 classInfoCount * CLASSINFO_FIELD_COUNT;
165 m_data.resize(fieldCount * sizeof(uint) + classNameLength + 1);
166 m_stringData = m_data.data() + m_data.size() - classNameLength - 1;
167 m_stringDataLength = classNameLength + 1;
168 m_stringDataAllocated = classNameLength + 1;
169 m_stringData[classNameLength] = 0;
170 m_zeroPtr = classNameLength;
172 header(m_data)->fieldCount = fieldCount;
174 QMetaObjectPrivate *p = priv(m_data);
176 int dataIndex = HEADER_FIELD_COUNT;
182 p->classInfoCount = classInfoCount;
183 if (p->classInfoCount) {
184 p->classInfoData = dataIndex;
185 dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
187 p->classInfoData = 0;
191 p->methodCount = methodCount + signalCount;
192 if (p->methodCount) {
193 p->methodData = dataIndex;
194 dataIndex += p->methodCount * METHOD_FIELD_COUNT;
198 p->signalCount = signalCount;
201 p->propertyCount = propertyCount;
202 if (p->propertyCount) {
203 p->propertyData = dataIndex;
204 dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
210 p->flags = DynamicMetaObject; // Always dynamic
212 // Enums and constructors not supported
213 p->enumeratorCount = 0;
214 p->enumeratorData = 0;
215 p->constructorCount = 0;
216 p->constructorData = 0;
221 className._l = classNameLength;
225 // Allocate a string of \a length. \a length should *not* include the null terminator.
226 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
228 Q_ASSERT(length > 0);
232 sr._o = m_stringDataLength;
235 m_stringDataLength += length + 1 /* for null terminator */;
240 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
242 Q_ASSERT(!m_data.isEmpty());
243 Q_ASSERT(!key.isEmpty() && !value.isEmpty());
245 QMetaObjectPrivate *p = priv(m_data);
246 Q_ASSERT(index < p->classInfoCount);
248 uint *ptr = fieldPointer(m_data) + p->classInfoData + index * CLASSINFO_FIELD_COUNT;
249 // classinfo: key, value
250 ptr[0] = key.offset(); ptr[1] = value.offset();
253 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
254 QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
256 Q_ASSERT(!m_data.isEmpty());
257 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
259 QMetaObjectPrivate *p = priv(m_data);
260 Q_ASSERT(index < p->propertyCount);
262 uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
263 // properties: name, type, flags
264 ptr[0] = name.offset();
265 ptr[1] = type.offset();
266 if (notifySignal == -1) {
267 ptr[2] = mtype << 24;
268 ptr[2] |= flags | Scriptable | Readable;
269 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
271 ptr[2] = mtype << 24;
272 ptr[2] |= flags | Scriptable | Readable | Notify;
273 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
277 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
278 QFastMetaBuilder::PropertyFlag flags, int notifySignal)
280 Q_ASSERT(!m_data.isEmpty());
281 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
283 QMetaObjectPrivate *p = priv(m_data);
284 Q_ASSERT(index < p->propertyCount);
286 uint *ptr = fieldPointer(m_data) + p->propertyData + index * PROPERTY_FIELD_COUNT;
287 // properties: name, type, flags
288 ptr[0] = name.offset();
289 ptr[1] = type.offset();
290 if (notifySignal == -1) {
291 ptr[2] = flags | Scriptable | Readable;
292 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = 0;
294 ptr[2] = flags | Scriptable | Readable | Notify;
295 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
299 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
300 const StringRef ¶meterNames,
301 const StringRef &type)
303 Q_ASSERT(!m_data.isEmpty());
304 Q_ASSERT(!signature.isEmpty());
306 QMetaObjectPrivate *p = priv(m_data);
307 int mindex = metaObjectIndexForSignal(index);
309 uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
310 // methods: signature, parameters, type, tag, flags
311 ptr[0] = signature.offset();
312 ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
313 ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
315 ptr[4] = AccessProtected | MethodSignal;
318 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
319 const StringRef ¶meterNames,
320 const StringRef &type)
322 Q_ASSERT(!m_data.isEmpty());
323 Q_ASSERT(!signature.isEmpty());
325 QMetaObjectPrivate *p = priv(m_data);
326 int mindex = metaObjectIndexForMethod(index);
328 uint *ptr = fieldPointer(m_data) + p->methodData + mindex * METHOD_FIELD_COUNT;
329 // methods: signature, parameters, type, tag, flags
330 ptr[0] = signature.offset();
331 ptr[1] = parameterNames.isEmpty()?m_zeroPtr:parameterNames.offset();
332 ptr[2] = type.isEmpty()?m_zeroPtr:type.offset();
334 ptr[4] = AccessProtected | MethodSlot;
337 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
339 Q_ASSERT(!m_data.isEmpty());
340 Q_ASSERT(index < priv(m_data)->signalCount);
344 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
346 Q_ASSERT(!m_data.isEmpty());
348 const QMetaObjectPrivate *p = priv(m_data);
349 Q_ASSERT(index < (p->methodCount - p->signalCount));
350 return index + p->signalCount;
353 void QFastMetaBuilder::allocateStringData()
355 if (m_stringDataAllocated < m_stringDataLength) {
356 m_data.resize(m_data.size() + m_stringDataLength - m_stringDataAllocated);
357 m_stringDataAllocated = m_stringDataLength;
358 m_stringData = m_data.data() + header(m_data)->fieldCount * sizeof(uint);
362 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
364 output->d.superdata = parent;
365 output->d.stringdata = data.constData() + header(data)->fieldCount * sizeof(uint);
366 output->d.data = fieldPointer(data);