2012-11-17 21:10:52 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2015-01-28 11:55:39 +00:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
** Contact: http://www.qt.io/licensing/
|
2012-11-17 21:10:52 +00:00
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2012-11-17 21:10:52 +00:00
|
|
|
**
|
2014-08-22 06:13:59 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL21$
|
2012-11-17 21:10:52 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
2012-11-17 21:10:52 +00:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-08-22 06:13:59 +00:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-11-17 21:10:52 +00:00
|
|
|
**
|
2015-01-28 11:55:39 +00:00
|
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2012-11-17 21:10:52 +00:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
2014-01-24 14:07:34 +00:00
|
|
|
#ifndef QV4VALUE_P_H
|
|
|
|
#define QV4VALUE_P_H
|
2013-04-19 19:24:46 +00:00
|
|
|
|
2014-01-25 20:41:31 +00:00
|
|
|
#include <limits.h>
|
|
|
|
|
2012-11-17 21:10:52 +00:00
|
|
|
#include <QtCore/QString>
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4global_p.h"
|
2013-06-25 12:23:35 +00:00
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2013-04-19 11:03:42 +00:00
|
|
|
namespace QV4 {
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
typedef uint Bool;
|
2013-09-15 13:46:36 +00:00
|
|
|
|
2014-11-01 22:04:20 +00:00
|
|
|
namespace Heap {
|
|
|
|
|
|
|
|
struct Q_QML_EXPORT Base {
|
2015-01-09 21:02:40 +00:00
|
|
|
union {
|
2015-01-10 16:55:29 +00:00
|
|
|
const ManagedVTable *vtable;
|
2015-01-09 21:02:40 +00:00
|
|
|
quintptr mm_data;
|
|
|
|
};
|
2014-11-01 19:56:47 +00:00
|
|
|
|
|
|
|
inline ReturnedValue asReturnedValue() const;
|
|
|
|
inline void mark(QV4::ExecutionEngine *engine);
|
|
|
|
|
2015-01-09 18:48:56 +00:00
|
|
|
enum {
|
2015-01-09 21:02:40 +00:00
|
|
|
MarkBit = 0x1,
|
2015-01-09 18:48:56 +00:00
|
|
|
NotInUse = 0x2,
|
|
|
|
PointerMask = ~0x3
|
|
|
|
};
|
2015-01-09 21:02:40 +00:00
|
|
|
|
2015-01-10 16:55:29 +00:00
|
|
|
ManagedVTable *gcGetVtable() const {
|
|
|
|
return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
|
2015-01-09 21:02:40 +00:00
|
|
|
}
|
|
|
|
inline bool isMarked() const {
|
|
|
|
return mm_data & MarkBit;
|
|
|
|
}
|
|
|
|
inline void setMarkBit() {
|
|
|
|
mm_data |= MarkBit;
|
|
|
|
}
|
|
|
|
inline void clearMarkBit() {
|
|
|
|
mm_data &= ~MarkBit;
|
|
|
|
}
|
|
|
|
|
2015-01-09 18:48:56 +00:00
|
|
|
inline bool inUse() const {
|
2015-01-09 21:02:40 +00:00
|
|
|
return !(mm_data & NotInUse);
|
2015-01-09 18:48:56 +00:00
|
|
|
}
|
|
|
|
|
2014-11-13 20:53:27 +00:00
|
|
|
Base *nextFree() {
|
2015-01-09 21:02:40 +00:00
|
|
|
return reinterpret_cast<Base *>(mm_data & PointerMask);
|
2014-11-13 20:53:27 +00:00
|
|
|
}
|
|
|
|
void setNextFree(Base *m) {
|
2015-01-09 21:02:40 +00:00
|
|
|
mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
|
2014-11-13 20:53:27 +00:00
|
|
|
}
|
|
|
|
|
2014-11-01 19:56:47 +00:00
|
|
|
void *operator new(size_t, Managed *m) { return m; }
|
2014-11-01 22:04:20 +00:00
|
|
|
void *operator new(size_t, Heap::Base *m) { return m; }
|
|
|
|
void operator delete(void *, Heap::Base *) {}
|
2014-11-01 19:56:47 +00:00
|
|
|
};
|
2014-07-23 11:56:43 +00:00
|
|
|
|
2014-11-01 22:04:20 +00:00
|
|
|
}
|
|
|
|
|
2014-03-12 15:55:06 +00:00
|
|
|
struct Q_QML_PRIVATE_EXPORT Value
|
2013-11-02 15:30:26 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
/*
|
|
|
|
We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
|
2013-01-28 15:46:09 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN)
|
|
|
|
is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the
|
|
|
|
processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
|
|
|
|
and encode the other types using the free space given to use by the unused bits for NaN values. This also
|
|
|
|
works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
|
|
|
|
will make the number a NaN. The Masks below are used for encoding the other types.
|
|
|
|
|
|
|
|
On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded
|
|
|
|
with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
|
|
|
|
can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
|
|
|
|
|
|
|
|
If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer.
|
|
|
|
This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set).
|
|
|
|
|
|
|
|
Bit 15-17 is then used to encode other immediates.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
union {
|
|
|
|
quint64 val;
|
2013-02-21 11:07:17 +00:00
|
|
|
#if QT_POINTER_SIZE == 8
|
2014-11-01 22:04:20 +00:00
|
|
|
Heap::Base *m;
|
2012-11-17 21:10:52 +00:00
|
|
|
#else
|
2014-01-24 14:07:34 +00:00
|
|
|
double dbl;
|
|
|
|
#endif
|
|
|
|
struct {
|
|
|
|
#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
|
|
|
|
uint tag;
|
|
|
|
#endif
|
|
|
|
union {
|
|
|
|
uint uint_32;
|
|
|
|
int int_32;
|
|
|
|
#if QT_POINTER_SIZE == 4
|
2014-11-01 22:04:20 +00:00
|
|
|
Heap::Base *m;
|
2014-01-24 14:07:34 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
|
|
|
uint tag;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
#if QT_POINTER_SIZE == 4
|
|
|
|
enum Masks {
|
2014-04-15 22:42:40 +00:00
|
|
|
SilentNaNBit = 0x00040000,
|
|
|
|
NaN_Mask = 0x7ff80000,
|
|
|
|
NotDouble_Mask = 0x7ffa0000,
|
|
|
|
Type_Mask = 0xffffc000,
|
|
|
|
Immediate_Mask = NotDouble_Mask | 0x00004000 | SilentNaNBit,
|
|
|
|
IsNullOrUndefined_Mask = Immediate_Mask | 0x08000,
|
2014-01-24 14:07:34 +00:00
|
|
|
Tag_Shift = 32
|
|
|
|
};
|
|
|
|
enum ValueType {
|
|
|
|
Undefined_Type = Immediate_Mask | 0x00000,
|
2014-04-15 22:42:40 +00:00
|
|
|
Null_Type = Immediate_Mask | 0x10000,
|
|
|
|
Boolean_Type = Immediate_Mask | 0x08000,
|
|
|
|
Integer_Type = Immediate_Mask | 0x18000,
|
|
|
|
Managed_Type = NotDouble_Mask | 0x00000 | SilentNaNBit,
|
|
|
|
Empty_Type = NotDouble_Mask | 0x18000 | SilentNaNBit
|
2014-01-24 14:07:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum ImmediateFlags {
|
|
|
|
ConvertibleToInt = Immediate_Mask | 0x1
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ValueTypeInternal {
|
|
|
|
_Null_Type = Null_Type | ConvertibleToInt,
|
|
|
|
_Boolean_Type = Boolean_Type | ConvertibleToInt,
|
|
|
|
_Integer_Type = Integer_Type | ConvertibleToInt,
|
|
|
|
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
static const quint64 NaNEncodeMask = 0xffff800000000000ll;
|
|
|
|
static const quint64 IsInt32Mask = 0x0002000000000000ll;
|
|
|
|
static const quint64 IsDoubleMask = 0xfffc000000000000ll;
|
|
|
|
static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask;
|
|
|
|
static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll;
|
|
|
|
static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll;
|
|
|
|
static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask;
|
|
|
|
|
|
|
|
enum Masks {
|
|
|
|
NaN_Mask = 0x7ff80000,
|
|
|
|
Type_Mask = 0xffff8000,
|
|
|
|
IsDouble_Mask = 0xfffc0000,
|
|
|
|
Immediate_Mask = 0x00018000,
|
|
|
|
IsNullOrUndefined_Mask = 0x00008000,
|
|
|
|
IsNullOrBoolean_Mask = 0x00010000,
|
|
|
|
Tag_Shift = 32
|
|
|
|
};
|
|
|
|
enum ValueType {
|
|
|
|
Undefined_Type = IsNullOrUndefined_Mask,
|
|
|
|
Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask,
|
|
|
|
Boolean_Type = IsNullOrBoolean_Mask,
|
|
|
|
Integer_Type = 0x20000|IsNullOrBoolean_Mask,
|
|
|
|
Managed_Type = 0,
|
|
|
|
Empty_Type = Undefined_Type | 0x4000
|
|
|
|
};
|
|
|
|
enum {
|
|
|
|
IsDouble_Shift = 64-14,
|
|
|
|
IsNumber_Shift = 64-15,
|
|
|
|
IsConvertibleToInt_Shift = 64-16,
|
|
|
|
IsManaged_Shift = 64-17
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum ValueTypeInternal {
|
|
|
|
_Null_Type = Null_Type,
|
|
|
|
_Boolean_Type = Boolean_Type,
|
|
|
|
_Integer_Type = Integer_Type
|
|
|
|
};
|
2012-11-17 21:10:52 +00:00
|
|
|
#endif
|
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline unsigned type() const {
|
|
|
|
return tag & Type_Mask;
|
|
|
|
}
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
// used internally in property
|
|
|
|
inline bool isEmpty() const { return tag == Empty_Type; }
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline bool isUndefined() const { return tag == Undefined_Type; }
|
|
|
|
inline bool isNull() const { return tag == _Null_Type; }
|
|
|
|
inline bool isBoolean() const { return tag == _Boolean_Type; }
|
|
|
|
#if QT_POINTER_SIZE == 8
|
|
|
|
inline bool isInteger() const { return (val >> IsNumber_Shift) == 1; }
|
|
|
|
inline bool isDouble() const { return (val >> IsDouble_Shift); }
|
|
|
|
inline bool isNumber() const { return (val >> IsNumber_Shift); }
|
|
|
|
inline bool isManaged() const { return !(val >> IsManaged_Shift); }
|
|
|
|
inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
|
|
|
|
inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
|
|
|
|
static inline bool integerCompatible(Value a, Value b) {
|
|
|
|
return a.integerCompatible() && b.integerCompatible();
|
2013-01-11 13:33:10 +00:00
|
|
|
}
|
2014-01-24 14:07:34 +00:00
|
|
|
static inline bool bothDouble(Value a, Value b) {
|
|
|
|
return a.isDouble() && b.isDouble();
|
|
|
|
}
|
|
|
|
double doubleValue() const {
|
|
|
|
Q_ASSERT(isDouble());
|
|
|
|
union {
|
|
|
|
quint64 i;
|
|
|
|
double d;
|
|
|
|
} v;
|
|
|
|
v.i = val ^ NaNEncodeMask;
|
|
|
|
return v.d;
|
|
|
|
}
|
|
|
|
void setDouble(double d) {
|
|
|
|
union {
|
|
|
|
quint64 i;
|
|
|
|
double d;
|
|
|
|
} v;
|
|
|
|
v.d = d;
|
|
|
|
val = v.i ^ NaNEncodeMask;
|
|
|
|
Q_ASSERT(isDouble());
|
|
|
|
}
|
2014-12-30 22:11:59 +00:00
|
|
|
inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
|
2014-01-24 14:07:34 +00:00
|
|
|
#else
|
|
|
|
inline bool isInteger() const { return tag == _Integer_Type; }
|
|
|
|
inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
|
|
|
|
inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
|
|
|
|
inline bool isManaged() const { return tag == Managed_Type; }
|
|
|
|
inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
|
|
|
|
inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
|
|
|
|
static inline bool integerCompatible(Value a, Value b) {
|
|
|
|
return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
|
|
|
|
}
|
|
|
|
static inline bool bothDouble(Value a, Value b) {
|
|
|
|
return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
|
|
|
|
}
|
2014-04-29 10:13:08 +00:00
|
|
|
double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
|
|
|
|
void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
|
2014-12-30 22:11:59 +00:00
|
|
|
inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
|
2014-01-24 14:07:34 +00:00
|
|
|
#endif
|
|
|
|
inline bool isString() const;
|
|
|
|
inline bool isObject() const;
|
|
|
|
inline bool isInt32() {
|
|
|
|
if (tag == _Integer_Type)
|
|
|
|
return true;
|
|
|
|
if (isDouble()) {
|
|
|
|
double d = doubleValue();
|
|
|
|
int i = (int)d;
|
|
|
|
if (i == d) {
|
|
|
|
int_32 = i;
|
|
|
|
tag = _Integer_Type;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
double asDouble() const {
|
|
|
|
if (tag == _Integer_Type)
|
|
|
|
return int_32;
|
2013-09-15 13:46:36 +00:00
|
|
|
return doubleValue();
|
2014-01-24 14:07:34 +00:00
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
bool booleanValue() const {
|
|
|
|
return int_32;
|
|
|
|
}
|
|
|
|
int integerValue() const {
|
2013-09-14 13:08:11 +00:00
|
|
|
return int_32;
|
2014-01-24 14:07:34 +00:00
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
String *stringValue() const {
|
2014-11-18 20:22:44 +00:00
|
|
|
return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
|
2014-01-24 14:07:34 +00:00
|
|
|
}
|
|
|
|
Object *objectValue() const {
|
2014-11-18 20:22:44 +00:00
|
|
|
return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
|
2014-01-24 14:07:34 +00:00
|
|
|
}
|
|
|
|
Managed *managed() const {
|
2014-11-18 20:22:44 +00:00
|
|
|
return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
|
2014-07-23 11:56:43 +00:00
|
|
|
}
|
2014-11-01 22:04:20 +00:00
|
|
|
Heap::Base *heapObject() const {
|
2014-01-24 14:07:34 +00:00
|
|
|
return m;
|
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
quint64 rawValue() const {
|
|
|
|
return val;
|
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-11-01 22:04:20 +00:00
|
|
|
static inline Value fromHeapObject(Heap::Base *m)
|
2014-07-23 11:56:43 +00:00
|
|
|
{
|
|
|
|
Value v;
|
|
|
|
v.m = m;
|
|
|
|
#if QT_POINTER_SIZE == 4
|
|
|
|
v.tag = Managed_Type;
|
|
|
|
#endif
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2014-07-23 10:37:17 +00:00
|
|
|
static inline Value fromManaged(Managed *m);
|
2014-01-24 14:07:34 +00:00
|
|
|
|
|
|
|
int toUInt16() const;
|
|
|
|
inline int toInt32() const;
|
|
|
|
inline unsigned int toUInt32() const;
|
|
|
|
|
|
|
|
inline bool toBoolean() const;
|
|
|
|
double toInteger() const;
|
|
|
|
inline double toNumber() const;
|
|
|
|
double toNumberImpl() const;
|
|
|
|
QString toQStringNoThrow() const;
|
|
|
|
QString toQString() const;
|
2014-11-11 14:08:30 +00:00
|
|
|
Heap::String *toString(ExecutionEngine *e) const;
|
2014-11-11 12:34:18 +00:00
|
|
|
Heap::Object *toObject(ExecutionEngine *e) const;
|
2014-01-24 14:07:34 +00:00
|
|
|
|
|
|
|
inline bool isPrimitive() const;
|
|
|
|
inline bool tryIntegerConversion() {
|
|
|
|
bool b = integerCompatible();
|
|
|
|
if (b)
|
|
|
|
tag = _Integer_Type;
|
|
|
|
return b;
|
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline String *asString() const;
|
|
|
|
inline Managed *asManaged() const;
|
|
|
|
inline Object *asObject() const;
|
|
|
|
inline FunctionObject *asFunctionObject() const;
|
|
|
|
inline NumberObject *asNumberObject() const;
|
|
|
|
inline StringObject *asStringObject() const;
|
|
|
|
inline DateObject *asDateObject() const;
|
|
|
|
inline ArrayObject *asArrayObject() const;
|
|
|
|
inline ErrorObject *asErrorObject() const;
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
template<typename T> inline T *as() const;
|
2014-07-24 09:53:59 +00:00
|
|
|
template<typename T> inline T *cast() {
|
|
|
|
return static_cast<T *>(managed());
|
|
|
|
}
|
|
|
|
template<typename T> inline const T *cast() const {
|
|
|
|
return static_cast<const T *>(managed());
|
|
|
|
}
|
2013-09-14 13:08:11 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline uint asArrayIndex() const;
|
|
|
|
inline uint asArrayLength(bool *ok) const;
|
2013-02-14 22:16:50 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
ReturnedValue asReturnedValue() const { return val; }
|
|
|
|
static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
|
2013-01-11 13:33:10 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
// Section 9.12
|
|
|
|
bool sameValue(Value other) const;
|
2013-01-11 09:13:02 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline void mark(ExecutionEngine *e) const;
|
2014-01-24 21:55:39 +00:00
|
|
|
|
|
|
|
Value &operator =(const ScopedValue &v);
|
|
|
|
Value &operator=(ReturnedValue v) { val = v; return *this; }
|
2014-11-12 15:07:56 +00:00
|
|
|
Value &operator=(Managed *m) {
|
|
|
|
val = Value::fromManaged(m).val;
|
2014-01-24 21:55:39 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2014-11-01 22:04:20 +00:00
|
|
|
Value &operator=(Heap::Base *o) {
|
2014-07-23 11:56:43 +00:00
|
|
|
m = o;
|
2014-11-12 15:07:56 +00:00
|
|
|
#if QT_POINTER_SIZE == 4
|
|
|
|
tag = Managed_Type;
|
|
|
|
#endif
|
2014-05-09 09:35:47 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2014-01-24 21:55:39 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
Value &operator=(const Scoped<T> &t);
|
|
|
|
Value &operator=(const Value &v) {
|
|
|
|
val = v.val;
|
|
|
|
return *this;
|
|
|
|
}
|
2014-01-24 14:07:34 +00:00
|
|
|
};
|
2013-01-25 12:23:58 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline Managed *Value::asManaged() const
|
2013-01-25 12:23:58 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
if (isManaged())
|
|
|
|
return managed();
|
|
|
|
return 0;
|
2013-01-25 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2014-03-12 15:55:06 +00:00
|
|
|
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
|
2013-01-25 12:23:58 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
inline static Primitive emptyValue();
|
|
|
|
static inline Primitive fromBoolean(bool b);
|
|
|
|
static inline Primitive fromInt32(int i);
|
|
|
|
inline static Primitive undefinedValue();
|
|
|
|
static inline Primitive nullValue();
|
|
|
|
static inline Primitive fromDouble(double d);
|
|
|
|
static inline Primitive fromUInt32(uint i);
|
|
|
|
|
|
|
|
static double toInteger(double fromNumber);
|
|
|
|
static int toInt32(double value);
|
|
|
|
static unsigned int toUInt32(double value);
|
|
|
|
};
|
2013-01-25 12:23:58 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline Primitive Primitive::undefinedValue()
|
2013-01-25 12:23:58 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
Primitive v;
|
|
|
|
#if QT_POINTER_SIZE == 8
|
|
|
|
v.val = quint64(Undefined_Type) << Tag_Shift;
|
|
|
|
#else
|
|
|
|
v.tag = Undefined_Type;
|
|
|
|
v.int_32 = 0;
|
|
|
|
#endif
|
|
|
|
return v;
|
2013-01-25 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
inline Primitive Primitive::emptyValue()
|
2013-01-25 12:23:58 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
Primitive v;
|
|
|
|
v.tag = Value::Empty_Type;
|
|
|
|
v.uint_32 = 0;
|
|
|
|
return v;
|
2013-01-25 12:23:58 +00:00
|
|
|
}
|
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
template <typename T>
|
2014-01-24 21:55:39 +00:00
|
|
|
struct TypedValue : public Value
|
2014-01-24 14:07:34 +00:00
|
|
|
{
|
|
|
|
template<typename X>
|
2014-01-24 21:55:39 +00:00
|
|
|
TypedValue &operator =(X *x) {
|
2014-06-13 13:11:14 +00:00
|
|
|
m = x;
|
|
|
|
#if QT_POINTER_SIZE == 4
|
|
|
|
tag = Managed_Type;
|
|
|
|
#endif
|
2014-11-11 14:08:30 +00:00
|
|
|
return *this;
|
2013-05-07 11:17:57 +00:00
|
|
|
}
|
2014-01-24 21:55:39 +00:00
|
|
|
TypedValue &operator =(T *t);
|
|
|
|
TypedValue &operator =(const Scoped<T> &v);
|
2014-01-27 13:58:52 +00:00
|
|
|
// TypedValue &operator =(const ManagedRef<T> &v);
|
2013-03-06 19:04:43 +00:00
|
|
|
|
2014-01-24 21:55:39 +00:00
|
|
|
TypedValue &operator =(const TypedValue<T> &t);
|
2013-05-06 09:37:53 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
bool operator!() const { return !managed(); }
|
|
|
|
|
2014-05-07 11:33:24 +00:00
|
|
|
operator T *() { return static_cast<T *>(managed()); }
|
2014-01-24 14:07:34 +00:00
|
|
|
T *operator->() { return static_cast<T *>(managed()); }
|
|
|
|
const T *operator->() const { return static_cast<T *>(managed()); }
|
|
|
|
T *getPointer() const { return static_cast<T *>(managed()); }
|
2013-03-06 19:04:43 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
|
2013-03-06 19:04:43 +00:00
|
|
|
};
|
2014-01-24 21:55:39 +00:00
|
|
|
typedef TypedValue<String> StringValue;
|
2013-03-06 19:04:43 +00:00
|
|
|
|
2014-01-25 20:41:31 +00:00
|
|
|
|
|
|
|
struct Encode {
|
|
|
|
static ReturnedValue undefined() {
|
|
|
|
return quint64(Value::Undefined_Type) << Value::Tag_Shift;
|
|
|
|
}
|
|
|
|
static ReturnedValue null() {
|
|
|
|
return quint64(Value::_Null_Type) << Value::Tag_Shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
Encode(bool b) {
|
|
|
|
val = (quint64(Value::_Boolean_Type) << Value::Tag_Shift) | (uint)b;
|
|
|
|
}
|
|
|
|
Encode(double d) {
|
|
|
|
Value v;
|
|
|
|
v.setDouble(d);
|
|
|
|
val = v.val;
|
|
|
|
}
|
|
|
|
Encode(int i) {
|
|
|
|
val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | (uint)i;
|
|
|
|
}
|
|
|
|
Encode(uint i) {
|
|
|
|
if (i <= INT_MAX) {
|
|
|
|
val = (quint64(Value::_Integer_Type) << Value::Tag_Shift) | i;
|
|
|
|
} else {
|
|
|
|
Value v;
|
|
|
|
v.setDouble(i);
|
|
|
|
val = v.val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Encode(ReturnedValue v) {
|
|
|
|
val = v;
|
|
|
|
}
|
|
|
|
|
2014-11-11 12:34:18 +00:00
|
|
|
Encode(Heap::Base *o) {
|
|
|
|
Q_ASSERT(o);
|
|
|
|
val = Value::fromHeapObject(o).asReturnedValue();
|
|
|
|
}
|
|
|
|
|
2014-01-25 20:41:31 +00:00
|
|
|
operator ReturnedValue() const {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
quint64 val;
|
|
|
|
private:
|
|
|
|
Encode(void *);
|
|
|
|
};
|
|
|
|
|
2014-11-01 19:56:47 +00:00
|
|
|
inline
|
2014-11-01 22:04:20 +00:00
|
|
|
ReturnedValue Heap::Base::asReturnedValue() const
|
2014-11-01 19:56:47 +00:00
|
|
|
{
|
2014-11-01 22:04:20 +00:00
|
|
|
return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
|
2014-11-01 19:56:47 +00:00
|
|
|
}
|
|
|
|
|
2014-01-25 20:41:31 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
template<typename T>
|
|
|
|
T *value_cast(const Value &v)
|
2013-05-23 20:13:42 +00:00
|
|
|
{
|
2014-01-24 14:07:34 +00:00
|
|
|
return v.as<T>();
|
|
|
|
}
|
2013-05-23 20:13:42 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
template<typename T>
|
2014-01-25 20:59:15 +00:00
|
|
|
ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
|
2013-05-23 20:13:42 +00:00
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
}
|
2012-11-17 21:10:52 +00:00
|
|
|
|
2013-01-31 09:00:06 +00:00
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
2014-01-24 14:07:34 +00:00
|
|
|
#endif // QV4VALUE_DEF_P_H
|