1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
5 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
6 * Copyright (C) 2003 Apple Computer, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 #define USE_CONSERVATIVE_GC 1
29 #define TEST_CONSERVATIVE_GC 0
31 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
33 // Uncomment this to enable very verbose output from KJS
35 // Uncomment this to debug memory allocation and garbage collection
36 //#define KJS_DEBUG_MEM
40 #include <stdlib.h> // Needed for size_t
44 #include "simple_number.h"
46 // Primitive data types
52 class ValueImpPrivate;
86 * ValueImp is the base type for all primitives (Undefined, Null, Boolean,
87 * String, Number) and objects in ECMAScript.
89 * Note: you should never inherit from ValueImp as it is for primitive types
90 * only (all of which are provided internally by KJS). Instead, inherit from
94 friend class Collector;
96 friend class ContextImp;
98 #if USE_CONSERVATIVE_GC
99 ValueImp() : _marked(0) {}
100 virtual ~ValueImp() {}
106 #if !USE_CONSERVATIVE_GC
107 ValueImp* ref() { if (!SimpleNumber::is(this)) refcount++; return this; }
108 bool deref() { if (SimpleNumber::is(this)) return false; else return (!--refcount); }
113 void* operator new(size_t);
114 void operator delete(void*);
116 #if !USE_CONSERVATIVE_GC
120 * set by Object() so that the collector is allowed to delete us
124 // Will crash if called on a simple number.
125 void setGcAllowedFast() { _flags |= VI_GCALLOWED; }
128 double toInteger(ExecState *exec) const;
129 int32_t toInt32(ExecState *exec) const;
130 uint32_t toUInt32(ExecState *exec) const;
131 uint16_t toUInt16(ExecState *exec) const;
133 // Dispatch wrappers that handle the special small number case
135 Type dispatchType() const;
136 Value dispatchToPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) const;
137 bool dispatchToBoolean(ExecState *exec) const;
138 double dispatchToNumber(ExecState *exec) const;
139 UString dispatchToString(ExecState *exec) const;
140 bool dispatchToUInt32(uint32_t&) const;
141 Object dispatchToObject(ExecState *exec) const;
143 #if !USE_CONSERVATIVE_GC
144 unsigned short int refcount;
148 virtual Type type() const = 0;
150 // The conversion operations
152 virtual Value toPrimitive(ExecState *exec, Type preferredType = UnspecifiedType) 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 Object toObject(ExecState *exec) const = 0;
157 virtual bool toUInt32(unsigned&) const;
159 #if USE_CONSERVATIVE_GC
162 unsigned short int _flags;
168 #if TEST_CONSERVATIVE_GC
169 , VI_CONSERVATIVE_MARKED = 8
170 #endif // TEST_CONSERVATIVE_GC
171 }; // VI means VALUEIMPL
172 #endif // USE_CONSERVATIVE_GC
174 // Give a compile time error if we try to copy one of these.
175 ValueImp(const ValueImp&);
176 ValueImp& operator=(const ValueImp&);
178 #if TEST_CONSERVATIVE_GC
179 static void useConservativeMark(bool);
184 * Value objects are act as wrappers ("smart pointers") around ValueImp
185 * objects and their descendents. Instead of using ValueImps
186 * (and derivatives) during normal program execution, you should use a
187 * Value-derived class.
189 * Value maintains a pointer to a ValueImp object and uses a reference
190 * counting scheme to ensure that the ValueImp object is not deleted or
193 * Note: The conversion operations all return values of various types -
194 * if an error occurs during conversion, an error object will instead
195 * be returned (where possible), and the execution state's exception
196 * will be set appropriately.
201 #if USE_CONSERVATIVE_GC
202 explicit Value(ValueImp *v) : rep(v) {}
203 Value(const Value &v) : rep (v.rep) {}
205 Value& operator=(const Value &v) { rep = v.rep; return *this; }
207 explicit Value(ValueImp *v);
208 Value(const Value &v);
210 Value& operator=(const Value &v);
213 bool isNull() const { return rep == 0; }
214 ValueImp *imp() const { return rep; }
217 * Returns the type of value. This is one of UndefinedType, NullType,
218 * BooleanType, StringType, NumberType, or ObjectType.
220 * @return The type of value
222 Type type() const { return rep->dispatchType(); }
225 * Checks whether or not the value is of a particular tpye
227 * @param The type to compare with
228 * @return true if the value is of the specified type, otherwise false
230 bool isA(Type t) const { return rep->dispatchType() == t; }
233 * Performs the ToPrimitive type conversion operation on this value
236 Value toPrimitive(ExecState *exec,
237 Type preferredType = UnspecifiedType) const
238 { return rep->dispatchToPrimitive(exec, preferredType); }
241 * Performs the ToBoolean type conversion operation on this value (ECMA 9.2)
243 bool toBoolean(ExecState *exec) const { return rep->dispatchToBoolean(exec); }
246 * Performs the ToNumber type conversion operation on this value (ECMA 9.3)
248 double toNumber(ExecState *exec) const { return rep->dispatchToNumber(exec); }
251 * Performs the ToInteger type conversion operation on this value (ECMA 9.4)
253 double toInteger(ExecState *exec) const { return rep->toInteger(exec); }
256 * Performs the ToInt32 type conversion operation on this value (ECMA 9.5)
258 int32_t toInt32(ExecState *exec) const { return rep->toInt32(exec); }
261 * Performs the ToUint32 type conversion operation on this value (ECMA 9.6)
263 uint32_t toUInt32(ExecState *exec) const { return rep->toUInt32(exec); }
266 * Performs the ToUint16 type conversion operation on this value (ECMA 9.7)
268 uint16_t toUInt16(ExecState *exec) const { return rep->toUInt16(exec); }
271 * Performs the ToString type conversion operation on this value (ECMA 9.8)
273 UString toString(ExecState *exec) const { return rep->dispatchToString(exec); }
276 * Performs the ToObject type conversion operation on this value (ECMA 9.9)
278 Object toObject(ExecState *exec) const;
281 * Checks if we can do a lossless conversion to UInt32.
283 bool toUInt32(uint32_t& i) const { return rep->dispatchToUInt32(i); }
292 * Represents an primitive Undefined value. All instances of this class
293 * share the same implementation object, so == will always return true
294 * for any comparison between two Undefined objects.
296 class Undefined : public Value {
301 * Converts a Value into an Undefined. If the value's type is not
302 * UndefinedType, a null object will be returned (i.e. one with it's
303 * internal pointer set to 0). If you do not know for sure whether the
304 * value is of type UndefinedType, you should check the @ref isNull()
305 * methods afterwards before calling any methods on the returned value.
307 * @return The value converted to an Undefined
309 static Undefined dynamicCast(const Value &v);
311 friend class UndefinedImp;
312 explicit Undefined(UndefinedImp *v);
317 * Represents an primitive Null value. All instances of this class
318 * share the same implementation object, so == will always return true
319 * for any comparison between two Null objects.
321 class Null : public Value {
326 * Converts a Value into an Null. If the value's type is not NullType,
327 * a null object will be returned (i.e. one with it's internal pointer set
328 * to 0). If you do not know for sure whether the value is of type
329 * NullType, you should check the @ref isNull() methods afterwards before
330 * calling any methods on the returned value.
332 * @return The value converted to a Null
334 static Null dynamicCast(const Value &v);
336 friend class NullImp;
337 explicit Null(NullImp *v);
341 * Represents an primitive Null value
343 class Boolean : public Value {
345 Boolean(bool b = false);
348 * Converts a Value into an Boolean. If the value's type is not BooleanType,
349 * a null object will be returned (i.e. one with it's internal pointer set
350 * to 0). If you do not know for sure whether the value is of type
351 * BooleanType, you should check the @ref isNull() methods afterwards before
352 * calling any methods on the returned value.
354 * @return The value converted to a Boolean
356 static Boolean dynamicCast(const Value &v);
360 friend class BooleanImp;
361 explicit Boolean(BooleanImp *v);
365 * Represents an primitive Null value
367 class String : public Value {
369 String(const UString &s = "");
372 * Converts a Value into an String. If the value's type is not StringType,
373 * a null object will be returned (i.e. one with it's internal pointer set
374 * to 0). If you do not know for sure whether the value is of type
375 * StringType, you should check the @ref isNull() methods afterwards before
376 * calling any methods on the returned value.
378 * @return The value converted to a String
380 static String dynamicCast(const Value &v);
382 UString value() const;
384 friend class StringImp;
385 explicit String(StringImp *v);
388 extern const double NaN;
389 extern const double Inf;
392 * Represents an primitive Number value
394 class Number : public Value {
395 friend class ValueImp;
398 Number(unsigned int u);
399 Number(double d = 0.0);
401 Number(long unsigned int l);
403 double value() const;
404 int intValue() const;
410 * Converts a Value into an Number. If the value's type is not NumberType,
411 * a null object will be returned (i.e. one with it's internal pointer set
412 * to 0). If you do not know for sure whether the value is of type
413 * NumberType, you should check the @ref isNull() methods afterwards before
414 * calling any methods on the returned value.
416 * @return The value converted to a Number
418 static Number dynamicCast(const Value &v);
420 friend class NumberImp;
421 explicit Number(NumberImp *v);
426 #endif // _KJS_VALUE_H_