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 QtQml 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>
45 #include <private/qobject_p.h>
46 #include <private/qmetaobject_p.h>
50 struct QFastMetaBuilderHeader
55 #define FMBHEADER_FIELD_COUNT 1
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
63 static inline uint *fieldPointer(QByteArray &data)
64 { return reinterpret_cast<uint *>(data.data()) + FMBHEADER_FIELD_COUNT; }
66 static inline const uint *fieldPointer(const QByteArray &data)
67 { return reinterpret_cast<const uint *>(data.constData()) + FMBHEADER_FIELD_COUNT; }
69 static inline QMetaObjectPrivate *priv(QByteArray &data)
70 { return reinterpret_cast<QMetaObjectPrivate*>(fieldPointer(data)); }
72 static inline const QMetaObjectPrivate *priv(const QByteArray &data)
73 { return reinterpret_cast<const QMetaObjectPrivate*>(fieldPointer(data)); }
75 static inline QFastMetaBuilderHeader *header(QByteArray &data)
76 { return reinterpret_cast<QFastMetaBuilderHeader*>(data.data()); }
78 static inline const QFastMetaBuilderHeader *header(const QByteArray &data)
79 { return reinterpret_cast<const QFastMetaBuilderHeader*>(data.constData()); }
81 QFastMetaBuilder::QFastMetaBuilder()
82 : m_zeroPtr(0), m_stringData(0), m_stringDataLength(0), m_stringDataAllocated(0)
86 QFastMetaBuilder::~QFastMetaBuilder()
90 QFastMetaBuilder::StringRef QFastMetaBuilder::init(int classNameLength,
91 int propertyCount, int methodCount,
92 int signalCount, int classInfoCount)
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);
101 int fieldCount = FMBHEADER_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;
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;
115 header(m_data)->fieldCount = fieldCount;
117 QMetaObjectPrivate *p = priv(m_data);
119 int dataIndex = HEADER_FIELD_COUNT;
125 p->classInfoCount = classInfoCount;
126 if (p->classInfoCount) {
127 p->classInfoData = dataIndex;
128 dataIndex += p->classInfoCount * CLASSINFO_FIELD_COUNT;
130 p->classInfoData = 0;
134 p->methodCount = methodCount + signalCount;
135 if (p->methodCount) {
136 p->methodData = dataIndex;
137 dataIndex += p->methodCount * METHOD_FIELD_COUNT;
141 p->signalCount = signalCount;
144 p->propertyCount = propertyCount;
145 if (p->propertyCount) {
146 p->propertyData = dataIndex;
147 dataIndex += p->propertyCount * (PROPERTY_FIELD_COUNT + PROPERTY_NOTIFY_FIELD_COUNT);
153 p->flags = DynamicMetaObject; // Always dynamic
155 // Enums and constructors not supported
156 p->enumeratorCount = 0;
157 p->enumeratorData = 0;
158 p->constructorCount = 0;
159 p->constructorData = 0;
164 className._l = classNameLength;
168 // Allocate a string of \a length. \a length should *not* include the null terminator.
169 QFastMetaBuilder::StringRef QFastMetaBuilder::newString(int length)
171 Q_ASSERT(length > 0);
175 sr._o = m_stringDataLength;
178 m_stringDataLength += length + 1 /* for null terminator */;
183 void QFastMetaBuilder::setClassInfo(int index, const StringRef &key, const StringRef &value)
185 Q_ASSERT(!m_data.isEmpty());
186 Q_ASSERT(!key.isEmpty() && !value.isEmpty());
188 QMetaObjectPrivate *p = priv(m_data);
189 Q_ASSERT(index < p->classInfoCount);
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();
196 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
197 QMetaType::Type mtype, PropertyFlag flags, int notifySignal)
199 Q_ASSERT(!m_data.isEmpty());
200 Q_ASSERT(!name.isEmpty());
201 Q_ASSERT(!type.isEmpty());
203 QMetaObjectPrivate *p = priv(m_data);
204 Q_ASSERT(index < p->propertyCount);
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;
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;
221 void QFastMetaBuilder::setProperty(int index, const StringRef &name, const StringRef &type,
222 QFastMetaBuilder::PropertyFlag flags, int notifySignal)
224 Q_ASSERT(!m_data.isEmpty());
225 Q_ASSERT(!name.isEmpty() && !type.isEmpty());
227 QMetaObjectPrivate *p = priv(m_data);
228 Q_ASSERT(index < p->propertyCount);
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;
238 ptr[2] = flags | Scriptable | Readable | Notify;
239 *(fieldPointer(m_data) + p->propertyData + p->propertyCount * PROPERTY_FIELD_COUNT + index) = notifySignal;
243 void QFastMetaBuilder::setSignal(int index, const StringRef &signature,
244 const StringRef ¶meterNames,
245 const StringRef &type)
247 Q_ASSERT(!m_data.isEmpty());
248 Q_ASSERT(!signature.isEmpty());
250 QMetaObjectPrivate *p = priv(m_data);
251 int mindex = metaObjectIndexForSignal(index);
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();
259 ptr[4] = AccessProtected | MethodSignal;
262 void QFastMetaBuilder::setMethod(int index, const StringRef &signature,
263 const StringRef ¶meterNames,
264 const StringRef &type)
266 Q_ASSERT(!m_data.isEmpty());
267 Q_ASSERT(!signature.isEmpty());
269 QMetaObjectPrivate *p = priv(m_data);
270 int mindex = metaObjectIndexForMethod(index);
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();
278 ptr[4] = AccessProtected | MethodSlot;
281 int QFastMetaBuilder::metaObjectIndexForSignal(int index) const
283 Q_ASSERT(!m_data.isEmpty());
284 Q_ASSERT(index < priv(m_data)->signalCount);
288 int QFastMetaBuilder::metaObjectIndexForMethod(int index) const
290 Q_ASSERT(!m_data.isEmpty());
292 const QMetaObjectPrivate *p = priv(m_data);
293 Q_ASSERT(index < (p->methodCount - p->signalCount));
294 return index + p->signalCount;
297 void QFastMetaBuilder::allocateStringData()
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);
306 void QFastMetaBuilder::fromData(QMetaObject *output, const QMetaObject *parent, const QByteArray &data)
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;