Reviewed by Ken.
[WebKit-https.git] / JavaScriptCore / kjs / value.h
1 // -*- c-basic-offset: 2 -*-
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.
7  *
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.
12  *
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.
17  *
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.
22  *
23  */
24
25 #ifndef _KJS_VALUE_H_
26 #define _KJS_VALUE_H_
27
28 #define USE_CONSERVATIVE_GC 1
29 #define TEST_CONSERVATIVE_GC 0
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 #include <stdlib.h> // Needed for size_t
41
42 #include "ustring.h"
43
44 #include "simple_number.h"
45
46 // Primitive data types
47
48 namespace KJS {
49
50   class Value;
51   class ValueImp;
52   class ValueImpPrivate;
53   class Undefined;
54   class UndefinedImp;
55   class Null;
56   class NullImp;
57   class Boolean;
58   class BooleanImp;
59   class String;
60   class StringImp;
61   class Number;
62   class NumberImp;
63   class Object;
64   class ObjectImp;
65   class Reference;
66   class ReferenceImp;
67   class List;
68   class ListImp;
69   class Completion;
70   class ExecState;
71
72   /**
73    * Primitive types
74    */
75   enum Type {
76     UnspecifiedType   = 0,
77     UndefinedType     = 1,
78     NullType          = 2,
79     BooleanType       = 3,
80     StringType        = 4,
81     NumberType        = 5,
82     ObjectType        = 6
83   };
84
85   /**
86    * ValueImp is the base type for all primitives (Undefined, Null, Boolean,
87    * String, Number) and objects in ECMAScript.
88    *
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
91    * ObjectImp.
92    */
93   class ValueImp {
94     friend class Collector;
95     friend class Value;
96     friend class ContextImp;
97   public:
98 #if USE_CONSERVATIVE_GC
99     ValueImp() : _marked(0) {}
100     virtual ~ValueImp() {}
101 #else
102     ValueImp();
103     virtual ~ValueImp();
104 #endif
105
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); }
109 #endif
110
111     virtual void mark();
112     bool marked() const;
113     void* operator new(size_t);
114     void operator delete(void*);
115
116 #if !USE_CONSERVATIVE_GC
117     /**
118      * @internal
119      *
120      * set by Object() so that the collector is allowed to delete us
121      */
122     void setGcAllowed();
123     
124     // Will crash if called on a simple number.
125     void setGcAllowedFast() { _flags |= VI_GCALLOWED; }
126 #endif
127
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;
132
133     // Dispatch wrappers that handle the special small number case
134
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;
142
143 #if !USE_CONSERVATIVE_GC
144     unsigned short int refcount;
145 #endif
146
147   private:
148     virtual Type type() const = 0;
149
150     // The conversion operations
151
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;
158
159 #if USE_CONSERVATIVE_GC
160     bool _marked;
161 #else
162     unsigned short int _flags;
163
164     enum {
165       VI_MARKED = 1,
166       VI_GCALLOWED = 2,
167       VI_CREATED = 4
168 #if TEST_CONSERVATIVE_GC
169       , VI_CONSERVATIVE_MARKED = 8
170 #endif // TEST_CONSERVATIVE_GC
171     }; // VI means VALUEIMPL
172 #endif // USE_CONSERVATIVE_GC
173
174     // Give a compile time error if we try to copy one of these.
175     ValueImp(const ValueImp&);
176     ValueImp& operator=(const ValueImp&);
177
178 #if TEST_CONSERVATIVE_GC
179     static void useConservativeMark(bool);
180 #endif
181   };
182
183   /**
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.
188    *
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
191    * garbage collected.
192    *
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.
197    */
198   class Value {
199   public:
200     Value() : rep(0) { }
201 #if USE_CONSERVATIVE_GC
202     explicit Value(ValueImp *v) : rep(v) {}
203     Value(const Value &v) : rep (v.rep) {}
204     ~Value() {}
205     Value& operator=(const Value &v) { rep = v.rep; return *this; } 
206 #else
207     explicit Value(ValueImp *v);
208     Value(const Value &v);
209     ~Value();
210     Value& operator=(const Value &v);
211 #endif
212
213     bool isNull() const { return rep == 0; }
214     ValueImp *imp() const { return rep; }
215
216     /**
217      * Returns the type of value. This is one of UndefinedType, NullType,
218      * BooleanType, StringType, NumberType, or ObjectType.
219      *
220      * @return The type of value
221      */
222     Type type() const { return rep->dispatchType(); }
223
224     /**
225      * Checks whether or not the value is of a particular tpye
226      *
227      * @param The type to compare with
228      * @return true if the value is of the specified type, otherwise false
229      */
230     bool isA(Type t) const { return rep->dispatchType() == t; }
231
232     /**
233      * Performs the ToPrimitive type conversion operation on this value
234      * (ECMA 9.1)
235      */
236     Value toPrimitive(ExecState *exec,
237                       Type preferredType = UnspecifiedType) const
238       { return rep->dispatchToPrimitive(exec, preferredType); }
239
240     /**
241      * Performs the ToBoolean type conversion operation on this value (ECMA 9.2)
242      */
243     bool toBoolean(ExecState *exec) const { return rep->dispatchToBoolean(exec); }
244
245     /**
246      * Performs the ToNumber type conversion operation on this value (ECMA 9.3)
247      */
248     double toNumber(ExecState *exec) const { return rep->dispatchToNumber(exec); }
249
250     /**
251      * Performs the ToInteger type conversion operation on this value (ECMA 9.4)
252      */
253     double toInteger(ExecState *exec) const { return rep->toInteger(exec); }
254
255     /**
256      * Performs the ToInt32 type conversion operation on this value (ECMA 9.5)
257      */
258     int32_t toInt32(ExecState *exec) const { return rep->toInt32(exec); }
259
260     /**
261      * Performs the ToUint32 type conversion operation on this value (ECMA 9.6)
262      */
263     uint32_t toUInt32(ExecState *exec) const { return rep->toUInt32(exec); }
264
265     /**
266      * Performs the ToUint16 type conversion operation on this value (ECMA 9.7)
267      */
268     uint16_t toUInt16(ExecState *exec) const { return rep->toUInt16(exec); }
269
270     /**
271      * Performs the ToString type conversion operation on this value (ECMA 9.8)
272      */
273     UString toString(ExecState *exec) const { return rep->dispatchToString(exec); }
274
275     /**
276      * Performs the ToObject type conversion operation on this value (ECMA 9.9)
277      */
278     Object toObject(ExecState *exec) const;
279
280     /**
281      * Checks if we can do a lossless conversion to UInt32.
282      */
283     bool toUInt32(uint32_t& i) const { return rep->dispatchToUInt32(i); }
284
285   protected:
286     ValueImp *rep;
287   };
288
289   // Primitive types
290
291   /**
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.
295    */
296   class Undefined : public Value {
297   public:
298     Undefined();
299
300     /**
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.
306      *
307      * @return The value converted to an Undefined
308      */
309     static Undefined dynamicCast(const Value &v);
310   private:
311     friend class UndefinedImp;
312     explicit Undefined(UndefinedImp *v);
313
314   };
315
316   /**
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.
320    */
321   class Null : public Value {
322   public:
323     Null();
324
325     /**
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.
331      *
332      * @return The value converted to a Null
333      */
334     static Null dynamicCast(const Value &v);
335   private:
336     friend class NullImp;
337     explicit Null(NullImp *v);
338   };
339
340   /**
341    * Represents an primitive Null value
342    */
343   class Boolean : public Value {
344   public:
345     Boolean(bool b = false);
346
347     /**
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.
353      *
354      * @return The value converted to a Boolean
355      */
356     static Boolean dynamicCast(const Value &v);
357
358     bool value() const;
359   private:
360     friend class BooleanImp;
361     explicit Boolean(BooleanImp *v);
362   };
363
364   /**
365    * Represents an primitive Null value
366    */
367   class String : public Value {
368   public:
369     String(const UString &s = "");
370
371     /**
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.
377      *
378      * @return The value converted to a String
379      */
380     static String dynamicCast(const Value &v);
381
382     UString value() const;
383   private:
384     friend class StringImp;
385     explicit String(StringImp *v);
386   };
387
388   extern const double NaN;
389   extern const double Inf;
390
391   /**
392    * Represents an primitive Number value
393    */
394   class Number : public Value {
395     friend class ValueImp;
396   public:
397     Number(int i);
398     Number(unsigned int u);
399     Number(double d = 0.0);
400     Number(long int l);
401     Number(long unsigned int l);
402
403     double value() const;
404     int intValue() const;
405
406     bool isNaN() const;
407     bool isInf() const;
408
409     /**
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.
415      *
416      * @return The value converted to a Number
417      */
418     static Number dynamicCast(const Value &v);
419   private:
420     friend class NumberImp;
421     explicit Number(NumberImp *v);
422   };
423
424 }; // namespace
425
426 #endif // _KJS_VALUE_H_