7d3e2efdf9c99d5c47d3780b29372d02dea6993c
[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 #include <wtf/AlwaysInline.h>
31
32 namespace KJS {
33
34 class ExecState;
35 class JSObject;
36 class JSCell;
37
38 struct ClassInfo;
39
40 /**
41  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
42  * String, Number) and objects in ECMAScript.
43  *
44  * Note: you should never inherit from JSValue as it is for primitive types
45  * only (all of which are provided internally by KJS). Instead, inherit from
46  * JSObject.
47  */
48 class JSValue : Noncopyable {
49     friend class JSCell; // so it can derive from this class
50     friend class Collector; // so it can call asCell()
51
52 private:
53     JSValue();
54     virtual ~JSValue();
55
56 public:
57     // Querying the type.
58     JSType type() const;
59     bool isUndefined() const;
60     bool isNull() const;
61     bool isUndefinedOrNull() const;
62     bool isBoolean() const;
63     bool isNumber() const;
64     bool isString() const;
65     bool isObject() const;
66     bool isObject(const ClassInfo *) const;
67
68     // Extracting the value.
69     bool getBoolean(bool&) const;
70     bool getBoolean() const; // false if not a boolean
71     bool getNumber(double&) const;
72     double getNumber() const; // NaN if not a number
73     bool getString(UString&) const;
74     UString getString() const; // null string if not a string
75     JSObject *getObject(); // NULL if not an object
76     const JSObject *getObject() const; // NULL if not an object
77
78     // Extracting integer values.
79     bool getUInt32(uint32_t&) const;
80     bool getTruncatedInt32(int32_t&) const;
81     bool getTruncatedUInt32(uint32_t&) const;
82
83     // Basic conversions.
84     JSValue* toPrimitive(ExecState* exec, JSType preferredType = UnspecifiedType) const;
85     bool getPrimitiveNumber(ExecState* exec, double& number) const;
86
87     bool toBoolean(ExecState *exec) const;
88     double toNumber(ExecState *exec) const;
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     return JSImmediate::NaNImmediate();
190 }
191
192 inline JSValue *jsBoolean(bool b)
193 {
194     return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
195 }
196
197 ALWAYS_INLINE JSValue* jsNumber(double d)
198 {
199     JSValue *v = JSImmediate::fromDouble(d);
200     return v ? v : jsNumberCell(d);
201 }
202
203 inline JSValue::JSValue()
204 {
205 }
206
207 inline JSValue::~JSValue()
208 {
209 }
210
211 inline JSCell::JSCell()
212 {
213 }
214
215 inline JSCell::~JSCell()
216 {
217 }
218
219 inline bool JSCell::isNumber() const
220 {
221     return type() == NumberType;
222 }
223
224 inline bool JSCell::isString() const
225 {
226     return type() == StringType;
227 }
228
229 inline bool JSCell::isObject() const
230 {
231     return type() == ObjectType;
232 }
233
234 inline bool JSCell::marked() const
235 {
236     return Collector::isCellMarked(this);
237 }
238
239 inline void JSCell::mark()
240 {
241     return Collector::markCell(this);
242 }
243
244 inline JSCell *JSValue::asCell()
245 {
246     ASSERT(!JSImmediate::isImmediate(this));
247     return static_cast<JSCell *>(this);
248 }
249
250 inline const JSCell *JSValue::asCell() const
251 {
252     ASSERT(!JSImmediate::isImmediate(this));
253     return static_cast<const JSCell *>(this);
254 }
255
256 inline bool JSValue::isUndefined() const
257 {
258     return this == jsUndefined();
259 }
260
261 inline bool JSValue::isNull() const
262 {
263     return this == jsNull();
264 }
265
266 inline bool JSValue::isUndefinedOrNull() const
267 {
268     return JSImmediate::isUndefinedOrNull(this);
269 }
270
271 inline bool JSValue::isBoolean() const
272 {
273     return JSImmediate::isBoolean(this);
274 }
275
276 inline bool JSValue::isNumber() const
277 {
278     return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && asCell()->isNumber();
279 }
280
281 inline bool JSValue::isString() const
282 {
283     return !JSImmediate::isImmediate(this) && asCell()->isString();
284 }
285
286 inline bool JSValue::isObject() const
287 {
288     return !JSImmediate::isImmediate(this) && asCell()->isObject();
289 }
290
291 inline bool JSValue::getBoolean(bool& v) const
292 {
293     if (JSImmediate::isBoolean(this)) {
294         v = JSImmediate::toBoolean(this);
295         return true;
296     }
297     
298     return false;
299 }
300
301 inline bool JSValue::getBoolean() const
302 {
303     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
304 }
305
306 inline bool JSValue::getNumber(double& v) const
307 {
308     if (JSImmediate::isImmediate(this)) {
309         v = JSImmediate::toDouble(this);
310         return true;
311     }
312     return asCell()->getNumber(v);
313 }
314
315 inline double JSValue::getNumber() const
316 {
317     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
318 }
319
320 inline bool JSValue::getString(UString& s) const
321 {
322     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
323 }
324
325 inline UString JSValue::getString() const
326 {
327     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
328 }
329
330 inline JSObject *JSValue::getObject()
331 {
332     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
333 }
334
335 inline const JSObject *JSValue::getObject() const
336 {
337     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
338 }
339
340 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
341 {
342     return JSImmediate::isImmediate(this) ? JSImmediate::getUInt32(this, v) : asCell()->getUInt32(v);
343 }
344
345 ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
346 {
347     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedInt32(this, v) : asCell()->getTruncatedInt32(v);
348 }
349
350 inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
351 {
352     return JSImmediate::isImmediate(this) ? JSImmediate::getTruncatedUInt32(this, v) : asCell()->getTruncatedUInt32(v);
353 }
354
355 inline void JSValue::mark()
356 {
357     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
358     asCell()->mark();
359 }
360
361 inline bool JSValue::marked() const
362 {
363     return JSImmediate::isImmediate(this) || asCell()->marked();
364 }
365
366 inline JSType JSValue::type() const
367 {
368     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
369 }
370
371 inline JSValue* JSValue::toPrimitive(ExecState* exec, JSType preferredType) const
372 {
373     return JSImmediate::isImmediate(this) ? const_cast<JSValue*>(this) : asCell()->toPrimitive(exec, preferredType);
374 }
375
376 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number) const
377 {
378     if (JSImmediate::isImmediate(this)) {
379         number = JSImmediate::toDouble(this);
380         return true;
381     }
382     return asCell()->getPrimitiveNumber(exec, number);
383 }
384
385 inline bool JSValue::toBoolean(ExecState *exec) const
386 {
387     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
388 }
389
390 ALWAYS_INLINE double JSValue::toNumber(ExecState *exec) const
391 {
392     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
393 }
394
395 inline UString JSValue::toString(ExecState *exec) const
396 {
397     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
398 }
399
400 inline JSObject* JSValue::toObject(ExecState* exec) const
401 {
402     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
403 }
404
405 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
406 {
407     int32_t i;
408     if (getTruncatedInt32(i))
409         return i;
410     bool ok;
411     return toInt32SlowCase(exec, ok);
412 }
413
414 inline uint32_t JSValue::toUInt32(ExecState* exec) const
415 {
416     uint32_t i;
417     if (getTruncatedUInt32(i))
418         return i;
419     bool ok;
420     return toUInt32SlowCase(exec, ok);
421 }
422
423 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
424 {
425     int32_t i;
426     if (getTruncatedInt32(i)) {
427         ok = true;
428         return i;
429     }
430     return toInt32SlowCase(exec, ok);
431 }
432
433 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
434 {
435     uint32_t i;
436     if (getTruncatedUInt32(i)) {
437         ok = true;
438         return i;
439     }
440     return toUInt32SlowCase(exec, ok);
441 }
442
443 } // namespace
444
445 #endif // KJS_VALUE_H