Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qv4string.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant
4
5
#
include
"qv4string_p.h"
6
#
include
"qv4value_p.h"
7
#
include
"qv4identifiertable_p.h"
8
#
include
"qv4runtime_p.h"
9
#
include
<
QtQml
/
private
/
qv4mm_p
.
h
>
10
#
include
<
QtCore
/
QHash
>
11
#
include
<
QtCore
/
private
/
qnumeric_p
.
h
>
12
13
using
namespace
QV4;
14
15
void
Heap::StringOrSymbol::markObjects(Heap::Base *that, MarkStack *markStack)
16
{
17
StringOrSymbol *s =
static_cast
<StringOrSymbol *>(that);
18
Heap::StringOrSymbol *id = s->identifier.asStringOrSymbol();
19
if
(id)
20
id->mark(markStack);
21
}
22
23
void
Heap::String::markObjects(Heap::Base *that, MarkStack *markStack)
24
{
25
StringOrSymbol::markObjects(that, markStack);
26
String *s =
static_cast
<String *>(that);
27
if
(s->subtype < StringType_Complex)
28
return
;
29
30
ComplexString *cs =
static_cast
<ComplexString *>(s);
31
if
(cs->subtype == StringType_AddedString) {
32
cs->left->mark(markStack);
33
cs->right->mark(markStack);
34
}
else
{
35
Q_ASSERT(cs->subtype == StringType_SubString);
36
cs->left->mark(markStack);
37
}
38
}
39
40
DEFINE_MANAGED_VTABLE
(
StringOrSymbol
);
41
DEFINE_MANAGED_VTABLE
(
String
);
42
43
44
bool
String::virtualIsEqualTo(Managed *t, Managed *o)
45
{
46
if
(t == o)
47
return
true
;
48
49
if
(!o->vtable()->isString)
50
return
false
;
51
52
return
static_cast
<String *>(t)->isEqualTo(
static_cast
<String *>(o));
53
}
54
55
56
void
Heap::String::init(
const
QString &t)
57
{
58
QString mutableText(t);
59
StringOrSymbol::init(mutableText.data_ptr());
60
subtype = String::StringType_Unknown;
61
}
62
63
void
Heap::ComplexString::init(String *l, String *r)
64
{
65
StringOrSymbol::init();
66
subtype = String::StringType_AddedString;
67
68
left = l;
69
right = r;
70
len = left->length() + right->length();
71
if
(left->subtype >= StringType_Complex)
72
largestSubLength =
static_cast
<ComplexString *>(left)->largestSubLength;
73
else
74
largestSubLength = left->length();
75
if
(right->subtype >= StringType_Complex)
76
largestSubLength = qMax(largestSubLength,
static_cast
<ComplexString *>(right)->largestSubLength);
77
else
78
largestSubLength = qMax(largestSubLength, right->length());
79
80
// make sure we don't get excessive depth in our strings
81
if
(len > 256 && len >= 2*largestSubLength)
82
simplifyString();
83
}
84
85
void
Heap::ComplexString::init(Heap::String *ref,
int
from,
int
len)
86
{
87
Q_ASSERT(ref->length() >= from + len);
88
StringOrSymbol::init();
89
90
subtype = String::StringType_SubString;
91
92
left = ref;
93
this
->from = from;
94
this
->len = len;
95
}
96
97
void
Heap::StringOrSymbol::destroy()
98
{
99
if
(subtype < Heap::String::StringType_AddedString) {
100
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
101
qptrdiff(-text().size) * qptrdiff(
sizeof
(QChar)));
102
}
103
text().~QStringPrivate();
104
Base::destroy();
105
}
106
107
uint String::toUInt(
bool
*ok)
const
108
{
109
*ok =
true
;
110
111
if
(subtype() >= Heap::String::StringType_Unknown)
112
d()->createHashValue();
113
if
(subtype() == Heap::String::StringType_ArrayIndex)
114
return
d()->stringHash;
115
116
// required for UINT_MAX or numbers starting with a leading 0
117
double
d = RuntimeHelpers::stringToNumber(toQString());
118
uint l = (uint)d;
119
if
(d == l)
120
return
l;
121
*ok =
false
;
122
return
UINT_MAX;
123
}
124
125
void
String::createPropertyKeyImpl()
const
126
{
127
if
(d()->subtype >= Heap::String::StringType_AddedString)
128
d()->simplifyString();
129
Q_ASSERT(d()->subtype < Heap::String::StringType_AddedString);
130
engine()->identifierTable->asPropertyKey(
this
);
131
}
132
133
void
Heap::String::simplifyString()
const
134
{
135
Q_ASSERT(subtype >= StringType_AddedString);
136
137
int
l = length();
138
QString result(l, Qt::Uninitialized);
139
QChar *ch =
const_cast
<QChar *>(result.constData());
140
append(
this
, ch);
141
text() = result.data_ptr();
142
const
ComplexString *cs =
static_cast
<
const
ComplexString *>(
this
);
143
identifier = PropertyKey::invalid();
144
cs->left = cs->right =
nullptr
;
145
146
internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
147
qptrdiff(text().size) * qptrdiff(
sizeof
(QChar)));
148
subtype = StringType_Unknown;
149
}
150
151
bool
Heap::String::startsWithUpper()
const
152
{
153
if
(subtype == StringType_AddedString)
154
return
static_cast
<
const
Heap::ComplexString *>(
this
)->left->startsWithUpper();
155
156
const
Heap::String *str =
this
;
157
int
offset = 0;
158
if
(subtype == StringType_SubString) {
159
const
ComplexString *cs =
static_cast
<
const
Heap::ComplexString *>(
this
);
160
if
(!cs->len)
161
return
false
;
162
// simplification here is not ideal, but hopefully not a common case.
163
if
(cs->left->subtype >= Heap::String::StringType_Complex)
164
cs->left->simplifyString();
165
str = cs->left;
166
offset = cs->from;
167
}
168
Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
169
return
str->text().size > offset && QChar::isUpper(str->text().data()[offset]);
170
}
171
172
void
Heap::String::append(
const
String *data, QChar *ch)
173
{
174
// in-order visitation with explicit stack
175
// where leaf nodes are "real" strings that get appended to ch
176
177
enum
StatusTag :
bool
{ NotVisited, Visited };
178
using
Pointer = QTaggedPointer<
const
String, StatusTag>;
179
180
std::vector<Pointer> worklist;
181
worklist.reserve(32);
182
worklist.push_back(Pointer(data));
183
184
while
(!worklist.empty()) {
185
Pointer item = worklist.back();
186
if
(item.tag() == Visited) {
187
Q_ASSERT(item->subtype == StringType_AddedString);
188
const
ComplexString *cs =
static_cast
<
const
ComplexString *>(item.data());
189
worklist.pop_back();
190
worklist.push_back(Pointer(cs->right));
191
continue
;
192
}
193
194
if
(item->subtype == StringType_AddedString) {
195
// we need to keep the node in the worklist, as we still need to handle "right"
196
worklist.back().setTag(Visited);
197
const
ComplexString *cs =
static_cast
<
const
ComplexString *>(item.data());
198
worklist.push_back(Pointer(cs->left));
199
}
else
if
(item->subtype == StringType_SubString) {
200
worklist.pop_back();
201
const
ComplexString *cs =
static_cast
<
const
ComplexString *>(item.data());
202
memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*
sizeof
(QChar));
203
ch += cs->len;
204
}
else
{
205
worklist.pop_back();
206
memcpy(
static_cast
<
void
*>(ch), item->text().data(), item->text().size *
sizeof
(QChar));
207
ch += item->text().size;
208
}
209
}
210
}
211
212
void
Heap::StringOrSymbol::createHashValue()
const
213
{
214
if
(subtype >= StringType_AddedString) {
215
Q_ASSERT(internalClass->vtable->isString);
216
static_cast
<
const
Heap::String *>(
this
)->simplifyString();
217
}
218
Q_ASSERT(subtype < StringType_AddedString);
219
const
QChar *ch =
reinterpret_cast
<
const
QChar *>(text().data());
220
const
QChar *end = ch + text().size;
221
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
222
}
223
224
qint64 String::virtualGetLength(
const
Managed *m)
225
{
226
return
static_cast
<
const
String *>(m)->d()->length();
227
}
DEFINE_MANAGED_VTABLE
DEFINE_MANAGED_VTABLE(String)
DEFINE_MANAGED_VTABLE
DEFINE_MANAGED_VTABLE(StringOrSymbol)
qtdeclarative
src
qml
jsruntime
qv4string.cpp
Generated on
for Qt by
1.18.0