f96f76de1d23efe154ceb65f3a272810e6683220
[WebKit-https.git] / JavaScriptCore / kjs / value.h
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
31 namespace KJS {
32
33 class ExecState;
34 class JSObject;
35 class JSCell;
36
37 struct 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  */
47 class JSValue : Noncopyable {
48     friend class JSCell; // so it can derive from this class
49     friend class Collector; // so it can call asCell()
50
51 private:
52     JSValue();
53     virtual ~JSValue();
54
55 public:
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) const;
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     // Floating point conversions.
101     float toFloat(ExecState*) const;
102
103     // Garbage collection.
104     void mark();
105     bool marked() const;
106
107 private:
108     int32_t toInt32SlowCase(ExecState*, bool& ok) const;
109     uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
110
111     // Implementation details.
112     JSCell *asCell();
113     const JSCell *asCell() const;
114
115     // Give a compile time error if we try to copy one of these.
116     JSValue(const JSValue&);
117     JSValue& operator=(const JSValue&);
118 };
119
120 class JSCell : public JSValue {
121     friend class Collector;
122     friend class NumberImp;
123     friend class StringImp;
124     friend class JSObject;
125     friend class GetterSetterImp;
126 private:
127     JSCell();
128     virtual ~JSCell();
129 public:
130     // Querying the type.
131     virtual JSType type() const = 0;
132     bool isNumber() const;
133     bool isString() const;
134     bool isObject() const;
135     bool isObject(const ClassInfo *) const;
136
137     // Extracting the value.
138     bool getNumber(double&) const;
139     double getNumber() const; // NaN if not a number
140     bool getString(UString&) const;
141     UString getString() const; // null string if not a string
142     JSObject *getObject(); // NULL if not an object
143     const JSObject *getObject() const; // NULL if not an object
144
145     // Extracting integer values.
146     virtual bool getUInt32(uint32_t&) const;
147     virtual bool getTruncatedInt32(int32_t&) const;
148     virtual bool getTruncatedUInt32(uint32_t&) const;
149
150     // Basic conversions.
151     virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
152     virtual bool getPrimitiveNumber(ExecState* exec, double& number) const = 0;
153     virtual bool toBoolean(ExecState *exec) const = 0;
154     virtual double toNumber(ExecState *exec) const = 0;
155     virtual UString toString(ExecState *exec) const = 0;
156     virtual JSObject *toObject(ExecState *exec) const = 0;
157
158     // Garbage collection.
159     void *operator new(size_t);
160     virtual void mark();
161     bool marked() const;
162 };
163
164 JSValue *jsNumberCell(double);
165
166 JSCell *jsString(const UString&); // returns empty string if passed null string
167 JSCell *jsString(const char* = ""); // returns empty string if passed 0
168
169 // should be used for strings that are owned by an object that will
170 // likely outlive the JSValue this makes, such as the parse tree or a
171 // DOM object that contains a UString
172 JSCell *jsOwnedString(const UString&); 
173
174 extern const double NaN;
175 extern const double Inf;
176
177 inline JSValue *jsUndefined()
178 {
179     return JSImmediate::undefinedImmediate();
180 }
181
182 inline JSValue *jsNull()
183 {
184     return JSImmediate::nullImmediate();
185 }
186
187 inline JSValue *jsNaN()
188 {
189     static const union {
190         uint64_t bits;
191         double d;
192     } nan = { 0x7ff80000ULL << 32 };
193     return jsNumberCell(nan.d);
194 }
195
196 inline JSValue *jsBoolean(bool b)
197 {
198     return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
199 }
200
201 ALWAYS_INLINE JSValue* jsNumber(double d)
202 {
203     JSValue* v = JSImmediate::from(d);
204     return v ? v : jsNumberCell(d);
205 }
206
207 ALWAYS_INLINE JSValue* jsNumber(int i)
208 {
209     JSValue* v = JSImmediate::from(i);
210     return v ? v : jsNumberCell(i);
211 }
212
213 ALWAYS_INLINE JSValue* jsNumber(unsigned i)
214 {
215     JSValue* v = JSImmediate::from(i);
216     return v ? v : jsNumberCell(i);
217 }
218
219 ALWAYS_INLINE JSValue* jsNumber(long i)
220 {
221     JSValue* v = JSImmediate::from(i);
222     return v ? v : jsNumberCell(i);
223 }
224
225 ALWAYS_INLINE JSValue* jsNumber(unsigned long i)
226 {
227     JSValue* v = JSImmediate::from(i);
228     return v ? v : jsNumberCell(i);
229 }
230
231 ALWAYS_INLINE JSValue* jsNumber(long long i)
232 {
233     JSValue* v = JSImmediate::from(i);
234     return v ? v : jsNumberCell(i);
235 }
236
237 ALWAYS_INLINE JSValue* jsNumber(unsigned long long i)
238 {
239     JSValue* v = JSImmediate::from(i);
240     return v ? v : jsNumberCell(i);
241 }
242
243 ALWAYS_INLINE JSValue* jsNumberFromAnd(ExecState *exec, JSValue* v1, JSValue* v2)
244 {
245     if (JSImmediate::areBothImmediateNumbers(v1, v2))
246         return JSImmediate::andImmediateNumbers(v1, v2);
247     return jsNumber(v1->toInt32(exec) & v2->toInt32(exec));
248 }
249
250 inline JSValue::JSValue()
251 {
252 }
253
254 inline JSValue::~JSValue()
255 {
256 }
257
258 inline JSCell::JSCell()
259 {
260 }
261
262 inline JSCell::~JSCell()
263 {
264 }
265
266 inline bool JSCell::isNumber() const
267 {
268     return type() == NumberType;
269 }
270
271 inline bool JSCell::isString() const
272 {
273     return type() == StringType;
274 }
275
276 inline bool JSCell::isObject() const
277 {
278     return type() == ObjectType;
279 }
280
281 inline bool JSCell::marked() const
282 {
283     return Collector::isCellMarked(this);
284 }
285
286 inline void JSCell::mark()
287 {
288     return Collector::markCell(this);
289 }
290
291 inline JSCell *JSValue::asCell()
292 {
293     ASSERT(!JSImmediate::isImmediate(this));
294     return static_cast<JSCell *>(this);
295 }
296
297 inline const JSCell *JSValue::asCell() const
298 {
299     ASSERT(!JSImmediate::isImmediate(this));
300     return static_cast<const JSCell *>(this);
301 }
302
303 inline bool JSValue::isUndefined() const
304 {
305     return this == jsUndefined();
306 }
307
308 inline bool JSValue::isNull() const
309 {
310     return this == jsNull();
311 }
312
313 inline bool JSValue::isUndefinedOrNull() const
314 {
315     return JSImmediate::isUndefinedOrNull(this);
316 }
317
318 inline bool JSValue::isBoolean() const
319 {
320     return JSImmediate::isBoolean(this);
321 }
322
323 inline bool JSValue::isNumber() const
324 {
325     return JSImmediate::isNumber(this) || (!JSImmediate::isImmediate(this) && asCell()->isNumber());
326 }
327
328 inline bool JSValue::isString() const
329 {
330     return !JSImmediate::isImmediate(this) && asCell()->isString();
331 }
332
333 inline bool JSValue::isObject() const
334 {
335     return !JSImmediate::isImmediate(this) && asCell()->isObject();
336 }
337
338 inline bool JSValue::getBoolean(bool& v) const
339 {
340     if (JSImmediate::isBoolean(this)) {
341         v = JSImmediate::toBoolean(this);
342         return true;
343     }
344     
345     return false;
346 }
347
348 inline bool JSValue::getBoolean() const
349 {
350     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
351 }
352
353 inline bool JSValue::getNumber(double& v) const
354 {
355     if (JSImmediate::isImmediate(this)) {
356         v = JSImmediate::toDouble(this);
357         return true;
358     }
359     return asCell()->getNumber(v);
360 }
361
362 inline double JSValue::getNumber() const
363 {
364     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
365 }
366
367 inline bool JSValue::getString(UString& s) const
368 {
369     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
370 }
371
372 inline UString JSValue::getString() const
373 {
374     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
375 }
376
377 inline JSObject *JSValue::getObject()
378 {
379     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
380 }
381
382 inline const JSObject *JSValue::getObject() const
383 {
384     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
385 }
386
387 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
388 {
389     return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
390 }
391
392 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
393 {
394     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
395 }
396
397 inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
398 {
399     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
400 }
401
402 inline void JSValue::mark()
403 {
404     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
405     asCell()->mark();
406 }
407
408 inline bool JSValue::marked() const
409 {
410     return JSImmediate::isImmediate(this) || asCell()->marked();
411 }
412
413 inline JSType JSValue::type() const
414 {
415     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
416 }
417
418 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
419 {
420     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
421 }
422
423 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number) const
424 {
425     if (JSImmediate::isImmediate(this)) {
426         number = JSImmediate::toDouble(this);
427         return true;
428     }
429     return asCell()->getPrimitiveNumber(exec, number);
430 }
431
432 inline bool JSValue::toBoolean(ExecState *exec) const
433 {
434     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
435 }
436
437 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
438 {
439     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
440 }
441
442 ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
443 {
444     return JSImmediate::isNumber(this) ? const_cast<JSValue*>(this) : jsNumber(this->toNumber(exec));
445 }
446
447 inline UString JSValue::toString(ExecState *exec) const
448 {
449     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
450 }
451
452 inline JSObject* JSValue::toObject(ExecState* exec) const
453 {
454     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
455 }
456
457 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
458 {
459     int32_t i;
460     if (getTruncatedInt32(i))
461         return i;
462     bool ok;
463     return toInt32SlowCase(exec, ok);
464 }
465
466 inline uint32_t JSValue::toUInt32(ExecState* exec) const
467 {
468     uint32_t i;
469     if (getTruncatedUInt32(i))
470         return i;
471     bool ok;
472     return toUInt32SlowCase(exec, ok);
473 }
474
475 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
476 {
477     int32_t i;
478     if (getTruncatedInt32(i)) {
479         ok = true;
480         return i;
481     }
482     return toInt32SlowCase(exec, ok);
483 }
484
485 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
486 {
487     uint32_t i;
488     if (getTruncatedUInt32(i)) {
489         ok = true;
490         return i;
491     }
492     return toUInt32SlowCase(exec, ok);
493 }
494
495 } // namespace
496
497 #endif // KJS_VALUE_H