8b1d4160efc3cef1f919901cd6e910c74f436bcd
[WebKit-https.git] / JavaScriptCore / kjs / value.h
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2003-2005 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #ifndef KJS_VALUE_H
25 #define KJS_VALUE_H
26
27 #include "JSImmediate.h"
28 #include "ustring.h"
29 #include <stddef.h> // for size_t
30
31 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
32
33 // Uncomment this to enable very verbose output from KJS
34 //#define KJS_VERBOSE
35 // Uncomment this to debug memory allocation and garbage collection
36 //#define KJS_DEBUG_MEM
37
38 #endif
39
40 namespace KJS {
41
42 class ExecState;
43 class JSObject;
44 class JSCell;
45
46 struct ClassInfo;
47
48 /**
49  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
50  * String, Number) and objects in ECMAScript.
51  *
52  * Note: you should never inherit from JSValue as it is for primitive types
53  * only (all of which are provided internally by KJS). Instead, inherit from
54  * JSObject.
55  */
56 class JSValue {
57     friend class JSCell; // so it can derive from this class
58     friend class Collector; // so it can call downcast()
59
60 private:
61     JSValue();
62     virtual ~JSValue();
63
64 public:
65     // Querying the type.
66     JSType type() const;
67     bool isUndefined() const;
68     bool isNull() const;
69     bool isUndefinedOrNull() const;
70     bool isBoolean() const;
71     bool isNumber() const;
72     bool isString() const;
73     bool isObject() const;
74     bool isObject(const ClassInfo *) const;
75
76     // Extracting the value.
77     bool getBoolean(bool&) const;
78     bool getBoolean() const; // false if not a boolean
79     bool getNumber(double&) const;
80     double getNumber() const; // NaN if not a number
81     bool getString(UString&) const;
82     UString getString() const; // null string if not a string
83     JSObject *getObject(); // NULL if not an object
84     const JSObject *getObject() const; // NULL if not an object
85
86     // Extracting integer values.
87     bool getUInt32(uint32_t&) const;
88
89     // Basic conversions.
90     JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
91     bool toBoolean(ExecState *exec) const;
92     double toNumber(ExecState *exec) const;
93     UString toString(ExecState *exec) const;
94     JSObject *toObject(ExecState *exec) const;
95
96     // Integer conversions.
97     double toInteger(ExecState*) const;
98     int32_t toInt32(ExecState*) const;
99     int32_t toInt32(ExecState*, bool& ok) const;
100     uint32_t toUInt32(ExecState*) const;
101     uint32_t toUInt32(ExecState*, bool& ok) const;
102     uint16_t toUInt16(ExecState*) const;
103
104     // Garbage collection.
105     void mark();
106     bool marked() const;
107
108 private:
109     // Implementation details.
110     JSCell *downcast();
111     const JSCell *downcast() const;
112
113     // Give a compile time error if we try to copy one of these.
114     JSValue(const JSValue&);
115     JSValue& operator=(const JSValue&);
116 };
117
118 class JSCell : public JSValue {
119     friend class Collector;
120     friend class NumberImp;
121     friend class StringImp;
122     friend class JSObject;
123     friend class GetterSetterImp;
124 private:
125     JSCell();
126     virtual ~JSCell();
127 public:
128     // Querying the type.
129     virtual JSType type() const = 0;
130     bool isNumber() const;
131     bool isString() const;
132     bool isObject() const;
133     bool isObject(const ClassInfo *) const;
134
135     // Extracting the value.
136     bool getNumber(double&) const;
137     double getNumber() const; // NaN if not a number
138     bool getString(UString&) const;
139     UString getString() const; // null string if not a string
140     JSObject *getObject(); // NULL if not an object
141     const JSObject *getObject() const; // NULL if not an object
142
143     // Extracting integer values.
144     virtual bool getUInt32(uint32_t&) const;
145
146     // Basic conversions.
147     virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
148     virtual bool toBoolean(ExecState *exec) const = 0;
149     virtual double toNumber(ExecState *exec) const = 0;
150     virtual UString toString(ExecState *exec) const = 0;
151     virtual JSObject *toObject(ExecState *exec) const = 0;
152
153     // Garbage collection.
154     void *operator new(size_t);
155     virtual void mark();
156     bool marked() const;
157
158 private:
159     bool m_collectOnMainThreadOnly : 1;
160     bool m_marked : 1;
161 };
162
163 JSValue *jsNumberCell(double);
164
165 JSCell *jsString(const UString &); // returns empty string if passed null string
166 JSCell *jsString(const char * = ""); // returns empty string if passed 0
167
168 extern const double NaN;
169 extern const double Inf;
170
171
172 inline JSValue *jsUndefined()
173 {
174     return JSImmediate::undefinedImmediate();
175 }
176
177 inline JSValue *jsNull()
178 {
179     return JSImmediate::nullImmediate();
180 }
181
182 inline JSValue *jsNaN()
183 {
184     return JSImmediate::NaNImmediate();
185 }
186
187 inline JSValue *jsBoolean(bool b)
188 {
189     return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
190 }
191
192 inline JSValue *jsNumber(double d)
193 {
194     JSValue *v = JSImmediate::fromDouble(d);
195     return v ? v : jsNumberCell(d);
196 }
197
198 inline JSValue::JSValue()
199 {
200 }
201
202 inline JSValue::~JSValue()
203 {
204 }
205
206 inline JSCell::JSCell()
207     : m_collectOnMainThreadOnly(false)
208     , m_marked(false)
209 {
210 }
211
212 inline JSCell::~JSCell()
213 {
214 }
215
216 inline bool JSCell::isNumber() const
217 {
218     return type() == NumberType;
219 }
220
221 inline bool JSCell::isString() const
222 {
223     return type() == StringType;
224 }
225
226 inline bool JSCell::isObject() const
227 {
228     return type() == ObjectType;
229 }
230
231 inline bool JSCell::marked() const
232 {
233     return m_marked;
234 }
235
236 inline void JSCell::mark()
237 {
238     m_marked = true;
239 }
240
241 inline JSCell *JSValue::downcast()
242 {
243     ASSERT(!JSImmediate::isImmediate(this));
244     return static_cast<JSCell *>(this);
245 }
246
247 inline const JSCell *JSValue::downcast() const
248 {
249     ASSERT(!JSImmediate::isImmediate(this));
250     return static_cast<const JSCell *>(this);
251 }
252
253 inline bool JSValue::isUndefined() const
254 {
255     return this == jsUndefined();
256 }
257
258 inline bool JSValue::isNull() const
259 {
260     return this == jsNull();
261 }
262
263 inline bool JSValue::isUndefinedOrNull() const
264 {
265     return JSImmediate::isUndefinedOrNull(this);
266 }
267
268 inline bool JSValue::isBoolean() const
269 {
270     return JSImmediate::isBoolean(this);
271 }
272
273 inline bool JSValue::isNumber() const
274 {
275     return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && downcast()->isNumber();
276 }
277
278 inline bool JSValue::isString() const
279 {
280     return !JSImmediate::isImmediate(this) && downcast()->isString();
281 }
282
283 inline bool JSValue::isObject() const
284 {
285     return !JSImmediate::isImmediate(this) && downcast()->isObject();
286 }
287
288 inline bool JSValue::getBoolean(bool& v) const
289 {
290     if (JSImmediate::isBoolean(this)) {
291         v = JSImmediate::toBoolean(this);
292         return true;
293     }
294     
295     return false;
296 }
297
298 inline bool JSValue::getBoolean() const
299 {
300     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
301 }
302
303 inline bool JSValue::getNumber(double& v) const
304 {
305     if (JSImmediate::isImmediate(this)) {
306         v = JSImmediate::toDouble(this);
307         return true;
308     }
309     return downcast()->getNumber(v);
310 }
311
312 inline double JSValue::getNumber() const
313 {
314     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->getNumber();
315 }
316
317 inline bool JSValue::getString(UString& s) const
318 {
319     return !JSImmediate::isImmediate(this) && downcast()->getString(s);
320 }
321
322 inline UString JSValue::getString() const
323 {
324     return JSImmediate::isImmediate(this) ? UString() : downcast()->getString();
325 }
326
327 inline JSObject *JSValue::getObject()
328 {
329     return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
330 }
331
332 inline const JSObject *JSValue::getObject() const
333 {
334     return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
335 }
336
337 inline bool JSValue::getUInt32(uint32_t& v) const
338 {
339     if (JSImmediate::isImmediate(this)) {
340         double d = JSImmediate::toDouble(this);
341         if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN
342             return false;
343         v = static_cast<uint32_t>(d);
344         return JSImmediate::isNumber(this);
345     }
346     return downcast()->getUInt32(v);
347 }
348
349 inline void JSValue::mark()
350 {
351     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
352     downcast()->mark();
353 }
354
355 inline bool JSValue::marked() const
356 {
357     return JSImmediate::isImmediate(this) || downcast()->marked();
358 }
359
360 inline JSType JSValue::type() const
361 {
362     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : downcast()->type();
363 }
364
365 inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
366 {
367     return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
368 }
369
370 inline bool JSValue::toBoolean(ExecState *exec) const
371 {
372     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : downcast()->toBoolean(exec);
373 }
374
375 inline double JSValue::toNumber(ExecState *exec) const
376 {
377     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->toNumber(exec);
378 }
379
380 inline UString JSValue::toString(ExecState *exec) const
381 {
382     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : downcast()->toString(exec);
383 }
384
385 inline JSObject* JSValue::toObject(ExecState* exec) const
386 {
387     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : downcast()->toObject(exec);
388 }
389
390 } // namespace
391
392 #endif // KJS_VALUE_H