|
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 "collector.h" |
|
29 #include "ustring.h" |
|
30 #include <stddef.h> // for size_t |
|
31 |
|
32 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on |
|
33 |
|
34 // Uncomment this to enable very verbose output from KJS |
|
35 //#define KJS_VERBOSE |
|
36 // Uncomment this to debug memory allocation and garbage collection |
|
37 //#define KJS_DEBUG_MEM |
|
38 |
|
39 #endif |
|
40 |
|
41 namespace KJS { |
|
42 |
|
43 class ExecState; |
|
44 class JSObject; |
|
45 class JSCell; |
|
46 |
|
47 struct ClassInfo; |
|
48 |
|
49 /** |
|
50 * JSValue is the base type for all primitives (Undefined, Null, Boolean, |
|
51 * String, Number) and objects in ECMAScript. |
|
52 * |
|
53 * Note: you should never inherit from JSValue as it is for primitive types |
|
54 * only (all of which are provided internally by KJS). Instead, inherit from |
|
55 * JSObject. |
|
56 */ |
|
57 class JSValue : Noncopyable { |
|
58 friend class JSCell; // so it can derive from this class |
|
59 friend class Collector; // so it can call asCell() |
|
60 |
|
61 private: |
|
62 JSValue(); |
|
63 virtual ~JSValue(); |
|
64 |
|
65 public: |
|
66 // Querying the type. |
|
67 JSType type() const; |
|
68 bool isUndefined() const; |
|
69 bool isNull() const; |
|
70 bool isUndefinedOrNull() const; |
|
71 bool isBoolean() const; |
|
72 bool isNumber() const; |
|
73 bool isString() const; |
|
74 bool isObject() const; |
|
75 bool isObject(const ClassInfo *) const; |
|
76 |
|
77 // Extracting the value. |
|
78 bool getBoolean(bool&) const; |
|
79 bool getBoolean() const; // false if not a boolean |
|
80 IMPORT bool getNumber(double&) const; |
|
81 double getNumber() const; // NaN if not a number |
|
82 bool getString(UString&) const; |
|
83 UString getString() const; // null string if not a string |
|
84 JSObject *getObject(); // NULL if not an object |
|
85 const JSObject *getObject() const; // NULL if not an object |
|
86 |
|
87 // Extracting integer values. |
|
88 bool getUInt32(uint32_t&) const; |
|
89 |
|
90 // Basic conversions. |
|
91 JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const; |
|
92 bool toBoolean(ExecState *exec) const; |
|
93 double toNumber(ExecState *exec) const; |
|
94 UString toString(ExecState *exec) const; |
|
95 JSObject *toObject(ExecState *exec) const; |
|
96 |
|
97 // Integer conversions. |
|
98 double toInteger(ExecState*) const; |
|
99 IMPORT int32_t toInt32(ExecState*) const; |
|
100 IMPORT int32_t toInt32(ExecState*, bool& ok) const; |
|
101 IMPORT uint32_t toUInt32(ExecState*) const; |
|
102 uint32_t toUInt32(ExecState*, bool& ok) const; |
|
103 uint16_t toUInt16(ExecState*) const; |
|
104 |
|
105 // Floating point conversions. |
|
106 IMPORT float toFloat(ExecState*) const; |
|
107 |
|
108 // Garbage collection. |
|
109 void mark(); |
|
110 bool marked() const; |
|
111 |
|
112 private: |
|
113 // Implementation details. |
|
114 JSCell *asCell(); |
|
115 const JSCell *asCell() const; |
|
116 |
|
117 // Give a compile time error if we try to copy one of these. |
|
118 JSValue(const JSValue&); |
|
119 JSValue& operator=(const JSValue&); |
|
120 }; |
|
121 |
|
122 class JSCell : public JSValue { |
|
123 friend class Collector; |
|
124 friend class NumberImp; |
|
125 friend class StringImp; |
|
126 friend class JSObject; |
|
127 friend class GetterSetterImp; |
|
128 private: |
|
129 JSCell(); |
|
130 virtual ~JSCell(); |
|
131 public: |
|
132 // Querying the type. |
|
133 virtual JSType type() const = 0; |
|
134 bool isNumber() const; |
|
135 bool isString() const; |
|
136 bool isObject() const; |
|
137 bool isObject(const ClassInfo *) const; |
|
138 |
|
139 // Extracting the value. |
|
140 IMPORT bool getNumber(double&) const; |
|
141 IMPORT double getNumber() const; // NaN if not a number |
|
142 IMPORT bool getString(UString&) const; |
|
143 UString getString() const; // null string if not a string |
|
144 IMPORT JSObject *getObject(); // NULL if not an object |
|
145 const JSObject *getObject() const; // NULL if not an object |
|
146 |
|
147 // Extracting integer values. |
|
148 IMPORT virtual bool getUInt32(uint32_t&) const; |
|
149 |
|
150 // Basic conversions. |
|
151 virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0; |
|
152 virtual bool toBoolean(ExecState *exec) const = 0; |
|
153 virtual double toNumber(ExecState *exec) const = 0; |
|
154 virtual UString toString(ExecState *exec) const = 0; |
|
155 virtual JSObject *toObject(ExecState *exec) const = 0; |
|
156 |
|
157 // Garbage collection. |
|
158 IMPORT void *operator new(size_t); |
|
159 virtual void mark(); |
|
160 bool marked() const; |
|
161 }; |
|
162 |
|
163 IMPORT JSValue *jsNumberCell(double); |
|
164 |
|
165 IMPORT JSCell *jsString(const UString&); // returns empty string if passed null string |
|
166 IMPORT JSCell *jsString(const char* = ""); // returns empty string if passed 0 |
|
167 |
|
168 // should be used for strings that are owned by an object that will |
|
169 // likely outlive the JSValue this makes, such as the parse tree or a |
|
170 // DOM object that contains a UString |
|
171 IMPORT JSCell *jsOwnedString(const UString&); |
|
172 |
|
173 extern const double NaN; |
|
174 extern const double Inf; |
|
175 |
|
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 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 inline bool JSValue::getUInt32(uint32_t& v) const |
|
341 { |
|
342 if (JSImmediate::isImmediate(this)) { |
|
343 double d = JSImmediate::toDouble(this); |
|
344 if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN |
|
345 return false; |
|
346 v = static_cast<uint32_t>(d); |
|
347 return JSImmediate::isNumber(this); |
|
348 } |
|
349 return asCell()->getUInt32(v); |
|
350 } |
|
351 |
|
352 inline void JSValue::mark() |
|
353 { |
|
354 ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark() |
|
355 asCell()->mark(); |
|
356 } |
|
357 |
|
358 inline bool JSValue::marked() const |
|
359 { |
|
360 return JSImmediate::isImmediate(this) || asCell()->marked(); |
|
361 } |
|
362 |
|
363 inline JSType JSValue::type() const |
|
364 { |
|
365 return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type(); |
|
366 } |
|
367 |
|
368 inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const |
|
369 { |
|
370 return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : asCell()->toPrimitive(exec, preferredType); |
|
371 } |
|
372 |
|
373 inline bool JSValue::toBoolean(ExecState *exec) const |
|
374 { |
|
375 return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec); |
|
376 } |
|
377 |
|
378 inline double JSValue::toNumber(ExecState *exec) const |
|
379 { |
|
380 return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec); |
|
381 } |
|
382 |
|
383 inline UString JSValue::toString(ExecState *exec) const |
|
384 { |
|
385 return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec); |
|
386 } |
|
387 |
|
388 inline JSObject* JSValue::toObject(ExecState* exec) const |
|
389 { |
|
390 return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec); |
|
391 } |
|
392 |
|
393 } // namespace |
|
394 |
|
395 #endif // KJS_VALUE_H |