Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4value.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
4#include <qv4runtime_p.h>
5#include <qv4propertykey_p.h>
6#include <qv4string_p.h>
7#include <qv4symbol_p.h>
8#include <qv4object_p.h>
9#include <qv4objectproto_p.h>
10#include <private/qv4mm_p.h>
11
12#include <wtf/MathExtras.h>
13
14using namespace QV4;
15
16int Value::toUInt16() const
17{
19 return (ushort)(uint)integerValue();
20
21 double number = toNumber();
22
23 double D16 = 65536.0;
24 if ((number >= 0 && number < D16))
25 return static_cast<ushort>(number);
26
27 if (!std::isfinite(number))
28 return +0;
29
30 double d = ::floor(::fabs(number));
31 if (std::signbit(number))
32 d = -d;
33
34 number = ::fmod(d , D16);
35
36 if (number < 0)
37 number += D16;
38
39 return (unsigned short)number;
40}
41
43{
44 if (val.isManagedOrUndefined()) {
45 Heap::Base *b = val.m();
46 if (!b)
47 return false;
48 if (b->internalClass->vtable->isString)
49 return static_cast<Heap::String *>(b)->length() > 0;
50 return true;
51 }
52
53 // double
54 double d = val.doubleValue();
55 return d && !std::isnan(d);
56}
57
59{
60 switch (val.type()) {
62 return std::numeric_limits<double>::quiet_NaN();
64 if (String *s = val.stringValue())
65 return RuntimeHelpers::stringToNumber(s->toQString());
66 if (val.isSymbol()) {
67 Managed &m = static_cast<Managed &>(val);
69 return 0;
70 }
71 {
72 Q_ASSERT(val.isObject());
73 Scope scope(val.objectValue()->engine());
74 ScopedValue protectThis(scope, val);
76 if (scope.hasException())
77 return 0;
78 return prim->toNumber();
79 }
83 return val.int_32();
84 default: // double
85 Q_UNREACHABLE();
86 }
87}
88
90{
91 switch (value->type()) {
93 Q_ASSERT(!"empty Value encountered");
94 Q_UNREACHABLE_RETURN(QString());
96 return QStringLiteral("undefined");
98 return QStringLiteral("null");
100 if (value->booleanValue())
101 return QStringLiteral("true");
102 else
103 return QStringLiteral("false");
105 Q_UNREACHABLE_RETURN(QString());
106 case Value::Integer_Type: {
107 QString str;
108 RuntimeHelpers::numberToString(&str, (double)value->int_32(), 10);
109 return str;
110 }
111 case Value::Double_Type: {
112 QString str;
113 RuntimeHelpers::numberToString(&str, value->doubleValue(), 10);
114 return str;
115 }
116 } // switch
117
118 Q_UNREACHABLE_RETURN(QString());
119}
120
121
123{
124 if (isManaged()) {
125 if (String *s = stringValue())
126 return s->toQString();
127 if (Symbol *s = symbolValue())
128 return s->descriptiveString();
129
131 Scope scope(objectValue()->engine());
132 ScopedValue ex(scope);
133 bool caughtException = false;
135 if (scope.hasException()) {
136 ex = scope.engine->catchException();
137 caughtException = true;
138 } else if (prim->isPrimitive()) {
139 return prim->toQStringNoThrow();
140 }
141
142 // Can't nest try/catch due to CXX ABI limitations for foreign exception nesting.
143 if (caughtException) {
145 if (scope.hasException()) {
146 ex = scope.engine->catchException();
147 } else if (prim->isPrimitive()) {
148 return prim->toQStringNoThrow();
149 }
150 }
151
152 return QString();
153 }
154
155 return primitiveToQString(this);
156}
157
159{
160 if (isManaged()) {
161 if (String *s = stringValue())
162 return s->toQString();
163
164 if (isSymbol()) {
165 static_cast<const Managed *>(this)->engine()->throwTypeError();
166 return QString();
167 }
168
170 Scope scope(objectValue()->engine());
172 return prim->toQString();
173 }
174
175 return primitiveToQString(this);
176}
177
179{
180 if (isManaged()) {
181 if (String *s = stringValue()) {
182 *ok = true;
183 return s->toQString();
184 }
185
186 if (isSymbol()) {
187 static_cast<const Managed *>(this)->engine()->throwTypeError();
188 *ok = false;
189 return QString();
190 }
191
193 Scope scope(objectValue()->engine());
195
196 if (scope.hasException()) {
197 *ok = false;
198 return QString();
199 }
200
201 return prim->toQString(ok);
202 }
203
204 return primitiveToQString(this);
205}
206
208{
209 if (isInteger() && int_32() >= 0)
210 return PropertyKey::fromArrayIndex(static_cast<uint>(int_32()));
211 if (isStringOrSymbol()) {
212 Scope scope(e);
213 ScopedStringOrSymbol s(scope, this);
214 return s->toPropertyKey();
215 }
216 Scope scope(e);
218 if (!v->isStringOrSymbol())
219 v = v->toString(e);
220 if (e->hasException)
221 return PropertyKey::invalid();
222 ScopedStringOrSymbol s(scope, v);
223 return s->toPropertyKey();
224}
225
227 if (_val == other._val)
228 return true;
229 String *s = stringValue();
230 String *os = other.stringValue();
231 if (s && os)
232 return s->isEqualTo(os);
233 if (isInteger() && other.isDouble())
234 return int_32() ? (double(int_32()) == other.doubleValue())
235 : (other.doubleValue() == 0 && !std::signbit(other.doubleValue()));
236 if (isDouble() && other.isInteger())
237 return other.int_32() ? (doubleValue() == double(other.int_32()))
238 : (doubleValue() == 0 && !std::signbit(doubleValue()));
239 if (isManaged())
240 return other.isManaged() && cast<Managed>()->isEqualTo(other.cast<Managed>());
241 return false;
242}
243
245 if (_val == other._val)
246 return true;
247 String *s = stringValue();
248 String *os = other.stringValue();
249 if (s && os)
250 return s->isEqualTo(os);
251 if (isInteger() && other.isDouble())
252 return double(int_32()) == other.doubleValue();
253 if (isDouble() && other.isInteger())
254 return other.int_32() == doubleValue();
255 if (isDouble() && other.isDouble()) {
256 if (doubleValue() == 0 && other.doubleValue() == 0) {
257 return true;
258 }
259 }
260 if (isManaged())
261 return other.isManaged() && cast<Managed>()->isEqualTo(other.cast<Managed>());
262 return false;
263}
264
269
271{
272 return RuntimeHelpers::convertToObject(e, val);
273}
274
276{
277 *ok = true;
278 if (isInteger()) {
279 if (int_32() >= 0) {
280 return (uint)int_32();
281 } else {
282 *ok = false;
283 return UINT_MAX;
284 }
285 }
286 if (isNumber()) {
287 double d = doubleValue();
288 uint idx = (uint)d;
289 if (idx != d) {
290 *ok = false;
291 return UINT_MAX;
292 }
293 return idx;
294 }
295 if (String *s = stringValue())
296 return s->toUInt(ok);
297
298 uint idx = toUInt32();
299 double d = toNumber();
300 if (d != idx) {
301 *ok = false;
302 return UINT_MAX;
303 }
304 return idx;
305}
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString str
[2]
@ STRING_HINT
@ NUMBER_HINT
Scoped< StringOrSymbol > ScopedStringOrSymbol
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLenum GLuint GLenum GLsizei length
GLdouble s
[6]
Definition qopenglext.h:235
GLuint GLfloat * val
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
unsigned int uint
Definition qtypes.h:34
unsigned short ushort
Definition qtypes.h:33
static QString primitiveToQString(const Value *value)
Definition qv4value.cpp:89
QSharedPointer< T > other(t)
[5]
QJSEngine engine
[0]
ReturnedValue catchException(StackTrace *trace=nullptr)
ReturnedValue throwTypeError()
ExecutionEngine * engine() const
static PropertyKey invalid()
static PropertyKey fromArrayIndex(uint idx)
static Heap::Object * convertToObject(ExecutionEngine *engine, const Value &value)
static void numberToString(QString *result, double num, int radix=10)
static ReturnedValue toPrimitive(const Value &value, TypeHint typeHint)
static Heap::String * convertToString(ExecutionEngine *engine, Value value, TypeHint=STRING_HINT)
static double stringToNumber(const QString &s)
bool hasException() const
ExecutionEngine * engine
bool isNumber() const
bool isInteger() const
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const
bool isManaged() const
bool integerCompatible() const
int integerValue() const
bool isDouble() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
bool isStringOrSymbol() const
Definition qv4value_p.h:290
static bool toBooleanImpl(Value val)
Definition qv4value.cpp:42
int toUInt16() const
Definition qv4value.cpp:16
Heap::String * toString(ExecutionEngine *e) const
Definition qv4value_p.h:114
QV4::PropertyKey toPropertyKey(ExecutionEngine *e) const
Definition qv4value.cpp:207
unsigned int toUInt32() const
Definition qv4value_p.h:364
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
Definition qv4value_p.h:55
bool sameValueZero(Value other) const
Definition qv4value.cpp:244
double toNumber() const
Definition qv4value_p.h:323
uint asArrayLength(bool *ok) const
Definition qv4value.cpp:275
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
Definition qv4value_p.h:70
QString toQString() const
Definition qv4value.cpp:158
double toNumberImpl() const
Definition qv4value_p.h:108
bool sameValue(Value other) const
Definition qv4value.cpp:226
QML_NEARLY_ALWAYS_INLINE Symbol * symbolValue() const
Definition qv4value_p.h:65
QString toQStringNoThrow() const
Definition qv4value.cpp:122
bool isSymbol() const
Definition qv4value_p.h:296
Heap::Object * toObject(ExecutionEngine *e) const
Definition qv4value_p.h:122
bool isObject() const
Definition qv4value_p.h:302