1 /****************************************************************************
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
32 ****************************************************************************/
34 #include "qv4string_p.h"
35 #include "qv4value_p.h"
37 #include "qv4identifiertable_p.h"
38 #include "qv4runtime_p.h"
39 #include "qv4objectproto_p.h"
40 #include "qv4stringobject_p.h"
42 #include <QtCore/QHash>
46 static uint toArrayIndex(const QChar *ch, const QChar *end)
48 uint i = ch->unicode() - '0';
52 // reject "01", "001", ...
53 if (i == 0 && ch != end)
57 uint x = ch->unicode() - '0';
72 static uint toArrayIndex(const char *ch, const char *end)
78 // reject "01", "001", ...
79 if (i == 0 && ch != end)
97 DEFINE_MANAGED_VTABLE(String);
99 void String::markObjects(Heap::Base *that, ExecutionEngine *e)
101 String::Data *s = static_cast<String::Data *>(that);
102 if (s->largestSubLength) {
108 bool String::isEqualTo(Managed *t, Managed *o)
113 if (!o->d()->vtable()->isString)
116 return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
120 Heap::String::String(const QString &t)
122 subtype = String::StringType_Unknown;
124 text = const_cast<QString &>(t).data_ptr();
127 stringHash = UINT_MAX;
128 largestSubLength = 0;
132 Heap::String::String(String *l, String *r)
134 subtype = String::StringType_Unknown;
138 stringHash = UINT_MAX;
139 largestSubLength = qMax(l->largestSubLength, r->largestSubLength);
140 len = l->len + r->len;
142 if (!l->largestSubLength && l->len > largestSubLength)
143 largestSubLength = l->len;
144 if (!r->largestSubLength && r->len > largestSubLength)
145 largestSubLength = r->len;
147 // make sure we don't get excessive depth in our strings
148 if (len > 256 && len >= 2*largestSubLength)
152 uint String::toUInt(bool *ok) const
156 if (subtype() == Heap::String::StringType_Unknown)
157 d()->createHashValue();
158 if (subtype() == Heap::String::StringType_ArrayIndex)
159 return d()->stringHash;
161 // required for UINT_MAX or numbers starting with a leading 0
162 double d = RuntimeHelpers::stringToNumber(toQString());
170 void String::makeIdentifierImpl(ExecutionEngine *e) const
172 if (d()->largestSubLength)
173 d()->simplifyString();
174 Q_ASSERT(!d()->largestSubLength);
175 e->identifierTable->identifier(this);
178 void Heap::String::simplifyString() const
180 Q_ASSERT(largestSubLength);
183 QString result(l, Qt::Uninitialized);
184 QChar *ch = const_cast<QChar *>(result.constData());
186 text = result.data_ptr();
189 largestSubLength = 0;
192 void Heap::String::createHashValue() const
194 if (largestSubLength)
196 Q_ASSERT(!largestSubLength);
197 const QChar *ch = reinterpret_cast<const QChar *>(text->data());
198 const QChar *end = ch + text->size;
200 // array indices get their number as hash value
201 stringHash = ::toArrayIndex(ch, end);
202 if (stringHash != UINT_MAX) {
203 subtype = Heap::String::StringType_ArrayIndex;
209 h = 31 * h + ch->unicode();
214 subtype = Heap::String::StringType_Regular;
217 void Heap::String::append(const String *data, QChar *ch)
219 std::vector<const String *> worklist;
220 worklist.reserve(32);
221 worklist.push_back(data);
223 while (!worklist.empty()) {
224 const String *item = worklist.back();
227 if (item->largestSubLength) {
228 worklist.push_back(item->right);
229 worklist.push_back(item->left);
231 memcpy(ch, item->text->data(), item->text->size * sizeof(QChar));
232 ch += item->text->size;
240 uint String::createHashValue(const QChar *ch, int length)
242 const QChar *end = ch + length;
244 // array indices get their number as hash value
245 uint stringHash = ::toArrayIndex(ch, end);
246 if (stringHash != UINT_MAX)
251 h = 31 * h + ch->unicode();
258 uint String::createHashValue(const char *ch, int length)
260 const char *end = ch + length;
262 // array indices get their number as hash value
263 uint stringHash = ::toArrayIndex(ch, end);
264 if (stringHash != UINT_MAX)
269 if ((uchar)(*ch) >= 0x80)
278 uint String::getLength(const Managed *m)
280 return static_cast<const String *>(m)->d()->length();
283 #endif // V4_BOOTSTRAP
285 uint String::toArrayIndex(const QString &str)
287 return ::toArrayIndex(str.constData(), str.constData() + str.length());