]>
git.saurik.com Git - apple/javascriptcore.git/blob - kjs/value.h
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2007 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "JSImmediate.h"
27 #include "collector.h"
29 #include <stddef.h> // for size_t
40 * JSValue is the base type for all primitives (Undefined, Null, Boolean,
41 * String, Number) and objects in ECMAScript.
43 * Note: you should never inherit from JSValue as it is for primitive types
44 * only (all of which are provided internally by KJS). Instead, inherit from
47 class JSValue
: Noncopyable
{
48 friend class JSCell
; // so it can derive from this class
49 friend class Collector
; // so it can call asCell()
58 bool isUndefined() const;
60 bool isUndefinedOrNull() const;
61 bool isBoolean() const;
62 bool isNumber() const;
63 bool isString() const;
64 bool isObject() const;
65 bool isObject(const ClassInfo
*) const;
67 // Extracting the value.
68 bool getBoolean(bool&) const;
69 bool getBoolean() const; // false if not a boolean
70 bool getNumber(double&) const;
71 double getNumber() const; // NaN if not a number
72 bool getString(UString
&) const;
73 UString
getString() const; // null string if not a string
74 JSObject
*getObject(); // NULL if not an object
75 const JSObject
*getObject() const; // NULL if not an object
77 // Extracting integer values.
78 bool getUInt32(uint32_t&) const;
79 bool getTruncatedInt32(int32_t&) const;
80 bool getTruncatedUInt32(uint32_t&) const;
83 JSValue
* toPrimitive(ExecState
* exec
, JSType preferredType
= UnspecifiedType
) const;
84 bool getPrimitiveNumber(ExecState
* exec
, double& number
, JSValue
*& value
);
86 bool toBoolean(ExecState
*exec
) const;
87 double toNumber(ExecState
*exec
) const;
88 JSValue
* toJSNumber(ExecState
*) const; // Fast path for when you expect that the value is an immediate number.
89 UString
toString(ExecState
*exec
) const;
90 JSObject
*toObject(ExecState
*exec
) const;
92 // Integer conversions.
93 double toInteger(ExecState
*) const;
94 double toIntegerPreserveNaN(ExecState
*) const;
95 int32_t toInt32(ExecState
*) const;
96 int32_t toInt32(ExecState
*, bool& ok
) const;
97 uint32_t toUInt32(ExecState
*) const;
98 uint32_t toUInt32(ExecState
*, bool& ok
) const;
100 // These are identical logic to above, and faster than jsNumber(number)->toInt32(exec)
101 static int32_t toInt32(double);
102 static int32_t toUInt32(double);
104 // Floating point conversions.
105 float toFloat(ExecState
*) const;
107 // Garbage collection.
111 static int32_t toInt32SlowCase(double, bool& ok
);
112 static uint32_t toUInt32SlowCase(double, bool& ok
);
115 int32_t toInt32SlowCase(ExecState
*, bool& ok
) const;
116 uint32_t toUInt32SlowCase(ExecState
*, bool& ok
) const;
118 // Implementation details.
120 const JSCell
*asCell() const;
122 // Give a compile time error if we try to copy one of these.
123 JSValue(const JSValue
&);
124 JSValue
& operator=(const JSValue
&);
127 class JSCell
: public JSValue
{
128 friend class Collector
;
129 friend class NumberImp
;
130 friend class StringImp
;
131 friend class JSObject
;
132 friend class GetterSetterImp
;
137 // Querying the type.
138 virtual JSType
type() const = 0;
139 bool isNumber() const;
140 bool isString() const;
141 bool isObject() const;
142 bool isObject(const ClassInfo
*) const;
144 // Extracting the value.
145 bool getNumber(double&) const;
146 double getNumber() const; // NaN if not a number
147 bool getString(UString
&) const;
148 UString
getString() const; // null string if not a string
149 JSObject
*getObject(); // NULL if not an object
150 const JSObject
*getObject() const; // NULL if not an object
152 // Extracting integer values.
153 virtual bool getUInt32(uint32_t&) const;
154 virtual bool getTruncatedInt32(int32_t&) const;
155 virtual bool getTruncatedUInt32(uint32_t&) const;
157 // Basic conversions.
158 virtual JSValue
*toPrimitive(ExecState
*exec
, JSType preferredType
= UnspecifiedType
) const = 0;
159 virtual bool getPrimitiveNumber(ExecState
* exec
, double& number
, JSValue
*& value
) = 0;
160 virtual bool toBoolean(ExecState
*exec
) const = 0;
161 virtual double toNumber(ExecState
*exec
) const = 0;
162 virtual UString
toString(ExecState
*exec
) const = 0;
163 virtual JSObject
*toObject(ExecState
*exec
) const = 0;
165 // Garbage collection.
166 void *operator new(size_t);
171 JSValue
*jsNumberCell(double);
173 JSCell
*jsString(const UString
&); // returns empty string if passed null string
174 JSCell
*jsString(const char* = ""); // returns empty string if passed 0
176 // should be used for strings that are owned by an object that will
177 // likely outlive the JSValue this makes, such as the parse tree or a
178 // DOM object that contains a UString
179 JSCell
*jsOwnedString(const UString
&);
181 extern const double NaN
;
182 extern const double Inf
;
184 inline JSValue
*jsUndefined()
186 return JSImmediate::undefinedImmediate();
189 inline JSValue
*jsNull()
191 return JSImmediate::nullImmediate();
194 inline JSValue
*jsNaN()
199 } nan
= { 0x7ff80000ULL
<< 32 };
200 return jsNumberCell(nan
.d
);
203 inline JSValue
*jsBoolean(bool b
)
205 return b
? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
208 ALWAYS_INLINE JSValue
* jsNumber(double d
)
210 JSValue
* v
= JSImmediate::from(d
);
211 return v
? v
: jsNumberCell(d
);
214 ALWAYS_INLINE JSValue
* jsNumber(int i
)
216 JSValue
* v
= JSImmediate::from(i
);
217 return v
? v
: jsNumberCell(i
);
220 ALWAYS_INLINE JSValue
* jsNumber(unsigned i
)
222 JSValue
* v
= JSImmediate::from(i
);
223 return v
? v
: jsNumberCell(i
);
226 ALWAYS_INLINE JSValue
* jsNumber(long i
)
228 JSValue
* v
= JSImmediate::from(i
);
229 return v
? v
: jsNumberCell(i
);
232 ALWAYS_INLINE JSValue
* jsNumber(unsigned long i
)
234 JSValue
* v
= JSImmediate::from(i
);
235 return v
? v
: jsNumberCell(i
);
238 ALWAYS_INLINE JSValue
* jsNumber(long long i
)
240 JSValue
* v
= JSImmediate::from(i
);
241 return v
? v
: jsNumberCell(static_cast<double>(i
));
244 ALWAYS_INLINE JSValue
* jsNumber(unsigned long long i
)
246 JSValue
* v
= JSImmediate::from(i
);
247 return v
? v
: jsNumberCell(static_cast<double>(i
));
250 ALWAYS_INLINE JSValue
* jsNumberFromAnd(ExecState
*exec
, JSValue
* v1
, JSValue
* v2
)
252 if (JSImmediate::areBothImmediateNumbers(v1
, v2
))
253 return JSImmediate::andImmediateNumbers(v1
, v2
);
254 return jsNumber(v1
->toInt32(exec
) & v2
->toInt32(exec
));
257 inline JSValue::JSValue()
261 inline JSValue::~JSValue()
265 inline JSCell::JSCell()
269 inline JSCell::~JSCell()
273 inline bool JSCell::isNumber() const
275 return type() == NumberType
;
278 inline bool JSCell::isString() const
280 return type() == StringType
;
283 inline bool JSCell::isObject() const
285 return type() == ObjectType
;
288 inline bool JSCell::marked() const
290 return Collector::isCellMarked(this);
293 inline void JSCell::mark()
295 return Collector::markCell(this);
298 ALWAYS_INLINE JSCell
* JSValue::asCell()
300 ASSERT(!JSImmediate::isImmediate(this));
301 return static_cast<JSCell
*>(this);
304 ALWAYS_INLINE
const JSCell
* JSValue::asCell() const
306 ASSERT(!JSImmediate::isImmediate(this));
307 return static_cast<const JSCell
*>(this);
310 inline bool JSValue::isUndefined() const
312 return this == jsUndefined();
315 inline bool JSValue::isNull() const
317 return this == jsNull();
320 inline bool JSValue::isUndefinedOrNull() const
322 return JSImmediate::isUndefinedOrNull(this);
325 inline bool JSValue::isBoolean() const
327 return JSImmediate::isBoolean(this);
330 inline bool JSValue::isNumber() const
332 return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
335 inline bool JSValue::isString() const
337 return !JSImmediate::isImmediate(this) && asCell()->isString();
340 inline bool JSValue::isObject() const
342 return !JSImmediate::isImmediate(this) && asCell()->isObject();
345 inline bool JSValue::getBoolean(bool& v
) const
347 if (JSImmediate::isBoolean(this)) {
348 v
= JSImmediate::toBoolean(this);
355 inline bool JSValue::getBoolean() const
357 return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
360 inline bool JSValue::getNumber(double& v
) const
362 if (JSImmediate::isImmediate(this)) {
363 v
= JSImmediate::toDouble(this);
366 return asCell()->getNumber(v
);
369 inline double JSValue::getNumber() const
371 return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
374 inline bool JSValue::getString(UString
& s
) const
376 return !JSImmediate::isImmediate(this) && asCell()->getString(s
);
379 inline UString
JSValue::getString() const
381 return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
384 inline JSObject
*JSValue::getObject()
386 return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
389 inline const JSObject
*JSValue::getObject() const
391 return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
394 ALWAYS_INLINE
bool JSValue::getUInt32(uint32_t& v
) const
396 return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v
) : asCell()->getUInt32(v
);
399 ALWAYS_INLINE
bool JSValue::getTruncatedInt32(int32_t& v
) const
401 return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v
) : asCell()->getTruncatedInt32(v
);
404 inline bool JSValue::getTruncatedUInt32(uint32_t& v
) const
406 return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v
) : asCell()->getTruncatedUInt32(v
);
409 inline void JSValue::mark()
411 ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
415 inline bool JSValue::marked() const
417 return JSImmediate::isImmediate(this) || asCell()->marked();
420 inline JSType
JSValue::type() const
422 return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
425 inline JSValue
* JSValue::toPrimitive(ExecState
* exec
, JSType preferredType
) const
427 return JSImmediate::isImmediate(this) ? const_cast<JSValue
*>(this) : asCell()->toPrimitive(exec
, preferredType
);
430 inline bool JSValue::getPrimitiveNumber(ExecState
* exec
, double& number
, JSValue
*& value
)
432 if (JSImmediate::isImmediate(this)) {
433 number
= JSImmediate::toDouble(this);
437 return asCell()->getPrimitiveNumber(exec
, number
, value
);
440 inline bool JSValue::toBoolean(ExecState
*exec
) const
442 return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec
);
445 ALWAYS_INLINE
double JSValue::toNumber(ExecState
*exec
) const
447 return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec
);
450 ALWAYS_INLINE JSValue
* JSValue::toJSNumber(ExecState
* exec
) const
452 return JSImmediate::isNumber(this) ? const_cast<JSValue
*>(this) : jsNumber(this->toNumber(exec
));
455 inline UString
JSValue::toString(ExecState
*exec
) const
457 return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec
);
460 inline JSObject
* JSValue::toObject(ExecState
* exec
) const
462 return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec
) : asCell()->toObject(exec
);
465 ALWAYS_INLINE
int32_t JSValue::toInt32(ExecState
* exec
) const
468 if (getTruncatedInt32(i
))
471 return toInt32SlowCase(exec
, ok
);
474 inline uint32_t JSValue::toUInt32(ExecState
* exec
) const
477 if (getTruncatedUInt32(i
))
480 return toUInt32SlowCase(exec
, ok
);
483 inline int32_t JSValue::toInt32(double val
)
485 if (!(val
>= -2147483648.0 && val
< 2147483648.0)) {
487 return toInt32SlowCase(val
, ignored
);
489 return static_cast<int32_t>(val
);
492 inline int32_t JSValue::toUInt32(double val
)
494 if (!(val
>= 0.0 && val
< 4294967296.0)) {
496 return toUInt32SlowCase(val
, ignored
);
498 return static_cast<uint32_t>(val
);
501 inline int32_t JSValue::toInt32(ExecState
* exec
, bool& ok
) const
504 if (getTruncatedInt32(i
)) {
508 return toInt32SlowCase(exec
, ok
);
511 inline uint32_t JSValue::toUInt32(ExecState
* exec
, bool& ok
) const
514 if (getTruncatedUInt32(i
)) {
518 return toUInt32SlowCase(exec
, ok
);
523 #endif // KJS_VALUE_H