]> git.saurik.com Git - apple/javascriptcore.git/blame - kjs/value.h
JavaScriptCore-466.1.tar.gz
[apple/javascriptcore.git] / kjs / value.h
CommitLineData
b37bf2e1
A
1/*
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.
5 *
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.
10 *
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.
15 *
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.
20 *
21 */
22
23#ifndef KJS_VALUE_H
24#define KJS_VALUE_H
25
26#include "JSImmediate.h"
27#include "collector.h"
28#include "ustring.h"
29#include <stddef.h> // for size_t
30
31namespace KJS {
32
33class ExecState;
34class JSObject;
35class JSCell;
36
37struct ClassInfo;
38
39/**
40 * JSValue is the base type for all primitives (Undefined, Null, Boolean,
41 * String, Number) and objects in ECMAScript.
42 *
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
45 * JSObject.
46 */
47class JSValue : Noncopyable {
48 friend class JSCell; // so it can derive from this class
49 friend class Collector; // so it can call asCell()
50
51private:
52 JSValue();
53 virtual ~JSValue();
54
55public:
56 // Querying the type.
57 JSType type() const;
58 bool isUndefined() const;
59 bool isNull() 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;
66
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
76
77 // Extracting integer values.
78 bool getUInt32(uint32_t&) const;
79 bool getTruncatedInt32(int32_t&) const;
80 bool getTruncatedUInt32(uint32_t&) const;
81
82 // Basic conversions.
83 JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
84 bool getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value);
85
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;
91
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;
99
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);
103
104 // Floating point conversions.
105 float toFloat(ExecState*) const;
106
107 // Garbage collection.
108 void mark();
109 bool marked() const;
110
111 static int32_t toInt32SlowCase(double, bool& ok);
112 static uint32_t toUInt32SlowCase(double, bool& ok);
113
114private:
115 int32_t toInt32SlowCase(ExecState*, bool& ok) const;
116 uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
117
118 // Implementation details.
119 JSCell *asCell();
120 const JSCell *asCell() const;
121
122 // Give a compile time error if we try to copy one of these.
123 JSValue(const JSValue&);
124 JSValue& operator=(const JSValue&);
125};
126
127class JSCell : public JSValue {
128 friend class Collector;
129 friend class NumberImp;
130 friend class StringImp;
131 friend class JSObject;
132 friend class GetterSetterImp;
133private:
134 JSCell();
135 virtual ~JSCell();
136public:
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;
143
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
151
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;
156
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;
164
165 // Garbage collection.
166 void *operator new(size_t);
167 virtual void mark();
168 bool marked() const;
169};
170
171JSValue *jsNumberCell(double);
172
173JSCell *jsString(const UString&); // returns empty string if passed null string
174JSCell *jsString(const char* = ""); // returns empty string if passed 0
175
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
179JSCell *jsOwnedString(const UString&);
180
181extern const double NaN;
182extern const double Inf;
183
184inline JSValue *jsUndefined()
185{
186 return JSImmediate::undefinedImmediate();
187}
188
189inline JSValue *jsNull()
190{
191 return JSImmediate::nullImmediate();
192}
193
194inline JSValue *jsNaN()
195{
196 static const union {
197 uint64_t bits;
198 double d;
199 } nan = { 0x7ff80000ULL << 32 };
200 return jsNumberCell(nan.d);
201}
202
203inline JSValue *jsBoolean(bool b)
204{
205 return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
206}
207
208ALWAYS_INLINE JSValue* jsNumber(double d)
209{
210 JSValue* v = JSImmediate::from(d);
211 return v ? v : jsNumberCell(d);
212}
213
214ALWAYS_INLINE JSValue* jsNumber(int i)
215{
216 JSValue* v = JSImmediate::from(i);
217 return v ? v : jsNumberCell(i);
218}
219
220ALWAYS_INLINE JSValue* jsNumber(unsigned i)
221{
222 JSValue* v = JSImmediate::from(i);
223 return v ? v : jsNumberCell(i);
224}
225
226ALWAYS_INLINE JSValue* jsNumber(long i)
227{
228 JSValue* v = JSImmediate::from(i);
229 return v ? v : jsNumberCell(i);
230}
231
232ALWAYS_INLINE JSValue* jsNumber(unsigned long i)
233{
234 JSValue* v = JSImmediate::from(i);
235 return v ? v : jsNumberCell(i);
236}
237
238ALWAYS_INLINE JSValue* jsNumber(long long i)
239{
240 JSValue* v = JSImmediate::from(i);
241 return v ? v : jsNumberCell(static_cast<double>(i));
242}
243
244ALWAYS_INLINE JSValue* jsNumber(unsigned long long i)
245{
246 JSValue* v = JSImmediate::from(i);
247 return v ? v : jsNumberCell(static_cast<double>(i));
248}
249
250ALWAYS_INLINE JSValue* jsNumberFromAnd(ExecState *exec, JSValue* v1, JSValue* v2)
251{
252 if (JSImmediate::areBothImmediateNumbers(v1, v2))
253 return JSImmediate::andImmediateNumbers(v1, v2);
254 return jsNumber(v1->toInt32(exec) & v2->toInt32(exec));
255}
256
257inline JSValue::JSValue()
258{
259}
260
261inline JSValue::~JSValue()
262{
263}
264
265inline JSCell::JSCell()
266{
267}
268
269inline JSCell::~JSCell()
270{
271}
272
273inline bool JSCell::isNumber() const
274{
275 return type() == NumberType;
276}
277
278inline bool JSCell::isString() const
279{
280 return type() == StringType;
281}
282
283inline bool JSCell::isObject() const
284{
285 return type() == ObjectType;
286}
287
288inline bool JSCell::marked() const
289{
290 return Collector::isCellMarked(this);
291}
292
293inline void JSCell::mark()
294{
295 return Collector::markCell(this);
296}
297
298ALWAYS_INLINE JSCell* JSValue::asCell()
299{
300 ASSERT(!JSImmediate::isImmediate(this));
301 return static_cast<JSCell*>(this);
302}
303
304ALWAYS_INLINE const JSCell* JSValue::asCell() const
305{
306 ASSERT(!JSImmediate::isImmediate(this));
307 return static_cast<const JSCell*>(this);
308}
309
310inline bool JSValue::isUndefined() const
311{
312 return this == jsUndefined();
313}
314
315inline bool JSValue::isNull() const
316{
317 return this == jsNull();
318}
319
320inline bool JSValue::isUndefinedOrNull() const
321{
322 return JSImmediate::isUndefinedOrNull(this);
323}
324
325inline bool JSValue::isBoolean() const
326{
327 return JSImmediate::isBoolean(this);
328}
329
330inline bool JSValue::isNumber() const
331{
332 return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
333}
334
335inline bool JSValue::isString() const
336{
337 return !JSImmediate::isImmediate(this) && asCell()->isString();
338}
339
340inline bool JSValue::isObject() const
341{
342 return !JSImmediate::isImmediate(this) && asCell()->isObject();
343}
344
345inline bool JSValue::getBoolean(bool& v) const
346{
347 if (JSImmediate::isBoolean(this)) {
348 v = JSImmediate::toBoolean(this);
349 return true;
350 }
351
352 return false;
353}
354
355inline bool JSValue::getBoolean() const
356{
357 return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
358}
359
360inline bool JSValue::getNumber(double& v) const
361{
362 if (JSImmediate::isImmediate(this)) {
363 v = JSImmediate::toDouble(this);
364 return true;
365 }
366 return asCell()->getNumber(v);
367}
368
369inline double JSValue::getNumber() const
370{
371 return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
372}
373
374inline bool JSValue::getString(UString& s) const
375{
376 return !JSImmediate::isImmediate(this) && asCell()->getString(s);
377}
378
379inline UString JSValue::getString() const
380{
381 return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
382}
383
384inline JSObject *JSValue::getObject()
385{
386 return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
387}
388
389inline const JSObject *JSValue::getObject() const
390{
391 return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
392}
393
394ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
395{
396 return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
397}
398
399ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
400{
401 return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
402}
403
404inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
405{
406 return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
407}
408
409inline void JSValue::mark()
410{
411 ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
412 asCell()->mark();
413}
414
415inline bool JSValue::marked() const
416{
417 return JSImmediate::isImmediate(this) || asCell()->marked();
418}
419
420inline JSType JSValue::type() const
421{
422 return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
423}
424
425inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
426{
427 return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
428}
429
430inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
431{
432 if (JSImmediate::isImmediate(this)) {
433 number = JSImmediate::toDouble(this);
434 value = this;
435 return true;
436 }
437 return asCell()->getPrimitiveNumber(exec, number, value);
438}
439
440inline bool JSValue::toBoolean(ExecState *exec) const
441{
442 return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
443}
444
445ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
446{
447 return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
448}
449
450ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
451{
452 return JSImmediate::isNumber(this) ? const_cast<JSValue*>(this) : jsNumber(this->toNumber(exec));
453}
454
455inline UString JSValue::toString(ExecState *exec) const
456{
457 return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
458}
459
460inline JSObject* JSValue::toObject(ExecState* exec) const
461{
462 return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
463}
464
465ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
466{
467 int32_t i;
468 if (getTruncatedInt32(i))
469 return i;
470 bool ok;
471 return toInt32SlowCase(exec, ok);
472}
473
474inline uint32_t JSValue::toUInt32(ExecState* exec) const
475{
476 uint32_t i;
477 if (getTruncatedUInt32(i))
478 return i;
479 bool ok;
480 return toUInt32SlowCase(exec, ok);
481}
482
483inline int32_t JSValue::toInt32(double val)
484{
485 if (!(val >= -2147483648.0 && val < 2147483648.0)) {
486 bool ignored;
487 return toInt32SlowCase(val, ignored);
488 }
489 return static_cast<int32_t>(val);
490}
491
492inline int32_t JSValue::toUInt32(double val)
493{
494 if (!(val >= 0.0 && val < 4294967296.0)) {
495 bool ignored;
496 return toUInt32SlowCase(val, ignored);
497 }
498 return static_cast<uint32_t>(val);
499}
500
501inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
502{
503 int32_t i;
504 if (getTruncatedInt32(i)) {
505 ok = true;
506 return i;
507 }
508 return toInt32SlowCase(exec, ok);
509}
510
511inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
512{
513 uint32_t i;
514 if (getTruncatedUInt32(i)) {
515 ok = true;
516 return i;
517 }
518 return toUInt32SlowCase(exec, ok);
519}
520
521} // namespace
522
523#endif // KJS_VALUE_H