Cache QObject method arguments
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativepropertycache_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 #ifndef QDECLARATIVEPROPERTYCACHE_P_H
43 #define QDECLARATIVEPROPERTYCACHE_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include <private/qdeclarativerefcount_p.h>
57 #include "qdeclarativecleanup_p.h"
58 #include "qdeclarativenotifier_p.h"
59
60 #include <private/qhashedstring_p.h>
61 #include <QtCore/qvarlengtharray.h>
62 #include <QtCore/qvector.h>
63
64 QT_BEGIN_NAMESPACE
65
66 class QDeclarativeEngine;
67 class QMetaProperty;
68 class QV8Engine;
69 class QV8QObjectWrapper;
70 class QDeclarativePropertyCacheMethodArguments;
71
72 class Q_DECLARATIVE_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup
73 {
74 public:
75     QDeclarativePropertyCache(QDeclarativeEngine *);
76     QDeclarativePropertyCache(QDeclarativeEngine *, const QMetaObject *);
77     virtual ~QDeclarativePropertyCache();
78
79     // We have this somewhat aweful split between RawData and Data so that RawData can be
80     // used in unions.  In normal code, you should always use Data which initializes RawData
81     // to an invalid state on construction.
82     struct Data;
83     struct RawData {
84         enum Flag { 
85                     NoFlags           = 0x00000000,
86                     ValueTypeFlagMask = 0x0000FFFF, // Flags in valueTypeFlags must fit in this mask
87
88                     // Can apply to all properties, except IsFunction
89                     IsConstant         = 0x00000001, // Has CONST flag
90                     IsWritable         = 0x00000002, // Has WRITE function
91                     IsResettable       = 0x00000004, // Has RESET function
92                     IsAlias            = 0x00000008, // Is a QML alias to another property
93                     IsFinal            = 0x00000010, // Has FINAL flag
94                     IsDirect           = 0x00000020, // Exists on a C++ QMetaObject
95
96                     // These are mutualy exclusive
97                     IsFunction         = 0x00000040, // Is an invokable
98                     IsQObjectDerived   = 0x00000080, // Property type is a QObject* derived type
99                     IsEnumType         = 0x00000100, // Property type is an enum
100                     IsQList            = 0x00000200, // Property type is a QML list
101                     IsQmlBinding       = 0x00000400, // Property type is a QDeclarativeBinding*
102                     IsQJSValue         = 0x00000800, // Property type is a QScriptValue
103                     IsV8Handle         = 0x00001000, // Property type is a QDeclarativeV8Handle
104                     IsVMEProperty      = 0x00002000, // Property type is a "var" property of VMEMO
105                     IsValueTypeVirtual = 0x00004000, // Property is a value type "virtual" property
106
107                     // Apply only to IsFunctions
108                     IsVMEFunction      = 0x00008000, // Function was added by QML
109                     HasArguments       = 0x00010000, // Function takes arguments
110                     IsSignal           = 0x00020000, // Function is a signal
111                     IsVMESignal        = 0x00040000, // Signal was added by QML
112                     IsV8Function       = 0x00080000, // Function takes QDeclarativeV8Function* args
113                     IsSignalHandler    = 0x00100000, // Function is a signal handler
114                     IsOverload         = 0x00200000, // Function is an overload of another function
115
116                     // Internal QDeclarativePropertyCache flags
117                     NotFullyResolved   = 0x00400000  // True if the type data is to be lazily resolved
118         };
119         Q_DECLARE_FLAGS(Flags, Flag)
120
121         Flags getFlags() const { return Flag(flags); }
122         void setFlags(Flags f) { flags = f; }
123
124         bool isValid() const { return coreIndex != -1; } 
125
126         bool isConstant() const { return flags & IsConstant; }
127         bool isWritable() const { return flags & IsWritable; }
128         bool isResettable() const { return flags & IsResettable; }
129         bool isAlias() const { return flags & IsAlias; }
130         bool isFinal() const { return flags & IsFinal; }
131         bool isDirect() const { return flags & IsDirect; }
132         bool isFunction() const { return flags & IsFunction; }
133         bool isQObject() const { return flags & IsQObjectDerived; }
134         bool isEnum() const { return flags & IsEnumType; }
135         bool isQList() const { return flags & IsQList; }
136         bool isQmlBinding() const { return flags & IsQmlBinding; }
137         bool isQJSValue() const { return flags & IsQJSValue; }
138         bool isV8Handle() const { return flags & IsV8Handle; }
139         bool isVMEProperty() const { return flags & IsVMEProperty; }
140         bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
141         bool isVMEFunction() const { return flags & IsVMEFunction; }
142         bool hasArguments() const { return flags & HasArguments; }
143         bool isSignal() const { return flags & IsSignal; }
144         bool isVMESignal() const { return flags & IsVMESignal; }
145         bool isV8Function() const { return flags & IsV8Function; }
146         bool isSignalHandler() const { return flags & IsSignalHandler; }
147         bool isOverload() const { return flags & IsOverload; }
148
149         union {
150             int propType;             // When !NotFullyResolved
151             const char *propTypeName; // When NotFullyResolved
152         };
153         int coreIndex;
154         union {
155             int notifyIndex;  // When !IsFunction
156             void *arguments;  // When IsFunction && HasArguments
157         };
158         union {
159             struct { // When !IsValueTypeVirtual
160                 uint overrideIndexIsProperty : 1;
161                 signed int overrideIndex : 31;
162             };
163             struct { // When IsValueTypeVirtual
164                 quint16 valueTypeFlags; // flags of the access property on the value type proxy object
165                 quint8 valueTypePropType; // The QVariant::Type of access property on the value type 
166                                           // proxy object
167                 quint8 valueTypeCoreIndex; // The prop index of the access property on the value type 
168                                            //proxy object
169             };
170         };
171         int revision; 
172         int metaObjectOffset;
173
174     private:
175         friend struct Data;
176         friend class QDeclarativePropertyCache;
177         quint32 flags;
178     };
179
180     struct Data : public RawData {
181         inline Data(); 
182         inline Data(const RawData &); 
183
184         inline bool operator==(const RawData &);
185
186         static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0);
187         void load(const QMetaProperty &, QDeclarativeEngine *engine = 0);
188         void load(const QMetaMethod &);
189         QString name(QObject *);
190         QString name(const QMetaObject *);
191
192         // Returns -1 if not a value type virtual property
193         inline int getValueTypeCoreIndex() const;
194
195     private:
196         friend class QDeclarativePropertyCache;
197         void lazyLoad(const QMetaProperty &, QDeclarativeEngine *engine = 0);
198         void lazyLoad(const QMetaMethod &);
199         bool notFullyResolved() const { return flags & NotFullyResolved; }
200     };
201
202     void update(QDeclarativeEngine *, const QMetaObject *);
203
204     QDeclarativePropertyCache *copy(int reserve = 0);
205     void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags,
206                 Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags);
207     void append(QDeclarativeEngine *, const QMetaObject *, int revision, Data::Flag propertyFlags = Data::NoFlags,
208                 Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags);
209
210     static Data create(const QMetaObject *, const QString &);
211
212     inline Data *property(const QHashedV8String &) const;
213     Data *property(const QHashedStringRef &) const;
214     Data *property(const QHashedCStringRef &) const;
215     Data *property(const QString &) const;
216     Data *property(int) const;
217     Data *method(int) const;
218     QStringList propertyNames() const;
219
220     inline Data *overrideData(Data *) const;
221     inline bool isAllowedInRevision(Data *) const;
222
223     inline QDeclarativeEngine *qmlEngine() const;
224     static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &);
225     static Data *property(QDeclarativeEngine *, QObject *, const QHashedV8String &, Data &);
226     static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
227                                      QByteArray *unknownTypeError);
228
229     static bool isDynamicMetaObject(const QMetaObject *);
230 protected:
231     virtual void destroy();
232     virtual void clear();
233
234 private:
235     friend class QDeclarativeEnginePrivate;
236     friend class QV8QObjectWrapper;
237
238     // Implemented in v8/qv8qobjectwrapper.cpp
239     v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
240
241     typedef QVector<Data> IndexCache;
242     typedef QStringHash<Data *> StringCache;
243     typedef QVector<int> AllowedRevisionCache;
244
245     void resolve(Data *) const;
246     void updateRecur(QDeclarativeEngine *, const QMetaObject *);
247
248     QDeclarativeEngine *engine;
249     
250     QDeclarativePropertyCache *parent;
251     int propertyIndexCacheStart;
252     int methodIndexCacheStart;
253
254     IndexCache propertyIndexCache;
255     IndexCache methodIndexCache;
256     IndexCache signalHandlerIndexCache;
257     StringCache stringCache;
258     AllowedRevisionCache allowedRevisionCache;
259     v8::Persistent<v8::Function> constructor;
260
261     const QMetaObject *metaObject;
262     QDeclarativePropertyCacheMethodArguments *argumentsCache;
263 };
264 Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags);
265   
266 QDeclarativePropertyCache::Data::Data()
267 {
268     propType = 0;
269     coreIndex = -1;
270     notifyIndex = -1;
271     overrideIndexIsProperty = false;
272     overrideIndex = -1;
273     revision = 0;
274     metaObjectOffset = -1; 
275     flags = 0;
276 }
277
278 QDeclarativePropertyCache::Data::Data(const QDeclarativePropertyCache::RawData &d)
279 {
280     *(static_cast<RawData *>(this)) = d;
281 }
282
283 bool QDeclarativePropertyCache::Data::operator==(const QDeclarativePropertyCache::RawData &other)
284 {
285     return flags == other.flags &&
286            propType == other.propType &&
287            coreIndex == other.coreIndex &&
288            notifyIndex == other.notifyIndex &&
289            revision == other.revision &&
290            (!isValueTypeVirtual() || 
291             (valueTypeCoreIndex == other.valueTypeCoreIndex && 
292              valueTypePropType == other.valueTypePropType));
293 }
294
295 int QDeclarativePropertyCache::Data::getValueTypeCoreIndex() const
296 {
297     return isValueTypeVirtual()?valueTypeCoreIndex:-1;
298 }
299
300 QDeclarativePropertyCache::Data *
301 QDeclarativePropertyCache::overrideData(Data *data) const
302 {
303     if (data->overrideIndex < 0)
304         return 0;
305
306     if (data->overrideIndexIsProperty)
307         return property(data->overrideIndex);
308     else
309         return method(data->overrideIndex);
310 }
311
312 bool QDeclarativePropertyCache::isAllowedInRevision(Data *data) const
313 {
314     return (data->metaObjectOffset == -1 && data->revision == 0) ||
315            (allowedRevisionCache[data->metaObjectOffset] >= data->revision);
316 }
317
318 QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const
319 {
320     return engine;
321 }
322
323 QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(const QHashedV8String &str) const
324 {
325     QDeclarativePropertyCache::Data **rv = stringCache.value(str);
326     if (rv && (*rv)->notFullyResolved()) resolve(*rv);
327     return rv?*rv:0;
328 }
329
330 QT_END_NAMESPACE
331
332 #endif // QDECLARATIVEPROPERTYCACHE_P_H