Encapsulate and protect all accesses to the vtable of Heap objects
[platform/upstream/qtdeclarative.git] / src / qml / jsruntime / qv4string_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33 #ifndef QV4STRING_H
34 #define QV4STRING_H
35
36 #include <QtCore/qstring.h>
37 #include "qv4managed_p.h"
38
39 QT_BEGIN_NAMESPACE
40
41 namespace QV4 {
42
43 struct ExecutionEngine;
44 struct Identifier;
45
46 namespace Heap {
47
48 #ifndef V4_BOOTSTRAP
49 struct Q_QML_PRIVATE_EXPORT String : Base {
50     enum StringType {
51         StringType_Unknown,
52         StringType_Regular,
53         StringType_ArrayIndex
54     };
55
56     String(const QString &text);
57     String(String *l, String *n);
58     ~String() {
59         if (!largestSubLength && !text->ref.deref())
60             QStringData::deallocate(text);
61     }
62     void simplifyString() const;
63     int length() const {
64         Q_ASSERT((largestSubLength &&
65                   (len == left->len + right->len)) ||
66                  len == (uint)text->size);
67         return len;
68     }
69     void createHashValue() const;
70     inline unsigned hashValue() const {
71         if (subtype == StringType_Unknown)
72             createHashValue();
73         Q_ASSERT(!largestSubLength);
74
75         return stringHash;
76     }
77     inline QString toQString() const {
78         if (largestSubLength)
79             simplifyString();
80         QStringDataPtr ptr = { text };
81         text->ref.ref();
82         return QString(ptr);
83     }
84     inline bool isEqualTo(const String *other) const {
85         if (this == other)
86             return true;
87         if (hashValue() != other->hashValue())
88             return false;
89         Q_ASSERT(!largestSubLength);
90         if (identifier && identifier == other->identifier)
91             return true;
92         if (subtype == Heap::String::StringType_ArrayIndex && other->subtype == Heap::String::StringType_ArrayIndex)
93             return true;
94
95         return toQString() == other->toQString();
96     }
97
98     union {
99         mutable QStringData *text;
100         mutable String *left;
101     };
102     union {
103         mutable Identifier *identifier;
104         mutable String *right;
105     };
106     mutable uint subtype;
107     mutable uint stringHash;
108     mutable uint largestSubLength;
109     uint len;
110 private:
111     static void append(const String *data, QChar *ch);
112 };
113 #endif
114
115 }
116
117 struct Q_QML_PRIVATE_EXPORT String : public Managed {
118 #ifndef V4_BOOTSTRAP
119     V4_MANAGED(String, Managed)
120     Q_MANAGED_TYPE(String)
121     V4_NEEDS_DESTROY
122     enum {
123         IsString = true
124     };
125
126     uchar subtype() const { return d()->subtype; }
127     void setSubtype(uchar subtype) const { d()->subtype = subtype; }
128
129     bool equals(String *other) const {
130         return d()->isEqualTo(other->d());
131     }
132     inline bool isEqualTo(const String *other) const {
133         return d()->isEqualTo(other->d());
134     }
135
136     inline bool compare(const String *other) {
137         return toQString() < other->toQString();
138     }
139
140     inline QString toQString() const {
141         return d()->toQString();
142     }
143
144     inline unsigned hashValue() const {
145         return d()->hashValue();
146     }
147     uint asArrayIndex() const {
148         if (subtype() == Heap::String::StringType_Unknown)
149             d()->createHashValue();
150         Q_ASSERT(!d()->largestSubLength);
151         if (subtype() == Heap::String::StringType_ArrayIndex)
152             return d()->stringHash;
153         return UINT_MAX;
154     }
155     uint toUInt(bool *ok) const;
156
157     void makeIdentifier(ExecutionEngine *e) const {
158         if (d()->identifier)
159             return;
160         makeIdentifierImpl(e);
161     }
162
163     void makeIdentifierImpl(ExecutionEngine *e) const;
164
165     static uint createHashValue(const QChar *ch, int length);
166     static uint createHashValue(const char *ch, int length);
167
168     bool startsWithUpper() const {
169         const String::Data *l = d();
170         while (l->largestSubLength)
171             l = l->left;
172         return l->text->size && QChar::isUpper(l->text->data()[0]);
173     }
174
175     Identifier *identifier() const { return d()->identifier; }
176
177 protected:
178     static void markObjects(Heap::Base *that, ExecutionEngine *e);
179     static bool isEqualTo(Managed *that, Managed *o);
180     static uint getLength(const Managed *m);
181 #endif
182
183 public:
184     static uint toArrayIndex(const QString &str);
185 };
186
187 template<>
188 inline const String *Value::as() const {
189     return isManaged() && m() && m()->vtable()->isString ? static_cast<const String *>(this) : 0;
190 }
191
192 #ifndef V4_BOOTSTRAP
193 template<>
194 inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
195 {
196     return v.toString(e)->asReturnedValue();
197 }
198 #endif
199
200
201 }
202
203 QT_END_NAMESPACE
204
205 #endif