source: webkit/trunk/JavaScriptCore/kjs/value.cpp@ 3367

Last change on this file since 3367 was 3367, checked in by darin, 22 years ago
  • correct our copyrights to 2003; copyright is based on year of publication, not year worked on
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003 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#include "value.h"
26#include "object.h"
27#include "types.h"
28#include "interpreter.h"
29
30#include <assert.h>
31#include <math.h>
32#include <stdio.h>
33#include <string.h>
34
35#include "internal.h"
36#include "collector.h"
37#include "operations.h"
38#include "error_object.h"
39#include "nodes.h"
40#include "simple_number.h"
41
42using namespace KJS;
43
44// ----------------------------- ValueImp -------------------------------------
45
46ValueImp::ValueImp() :
47 refcount(0),
48 // Tell the garbage collector that this memory block corresponds to a real object now
49 _flags(VI_CREATED)
50{
51 //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
52}
53
54ValueImp::~ValueImp()
55{
56 //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
57}
58
59void ValueImp::mark()
60{
61 //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
62 _flags |= VI_MARKED;
63}
64
65bool ValueImp::marked() const
66{
67 // Simple numbers are always considered marked.
68 return SimpleNumber::is(this) || (_flags & VI_MARKED);
69}
70
71void ValueImp::setGcAllowed()
72{
73 //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
74 // simple numbers are never seen by the collector so setting this
75 // flag is irrelevant
76 if (!SimpleNumber::is(this))
77 _flags |= VI_GCALLOWED;
78}
79
80void* ValueImp::operator new(size_t s)
81{
82 return Collector::allocate(s);
83}
84
85void ValueImp::operator delete(void*)
86{
87 // Do nothing. So far.
88}
89
90bool ValueImp::toUInt32(unsigned&) const
91{
92 return false;
93}
94
95// ECMA 9.4
96int ValueImp::toInteger(ExecState *exec) const
97{
98 unsigned i;
99 if (dispatchToUInt32(i))
100 return (int)i;
101 return int(roundValue(exec, Value(const_cast<ValueImp*>(this))));
102}
103
104int ValueImp::toInt32(ExecState *exec) const
105{
106 unsigned i;
107 if (dispatchToUInt32(i))
108 return (int)i;
109
110 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
111 double d32 = fmod(d, D32);
112
113 if (d32 >= D32 / 2.0)
114 d32 -= D32;
115
116 return static_cast<int>(d32);
117}
118
119unsigned int ValueImp::toUInt32(ExecState *exec) const
120{
121 unsigned i;
122 if (dispatchToUInt32(i))
123 return i;
124
125 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
126 double d32 = fmod(d, D32);
127
128 return static_cast<unsigned int>(d32);
129}
130
131unsigned short ValueImp::toUInt16(ExecState *exec) const
132{
133 unsigned i;
134 if (dispatchToUInt32(i))
135 return (unsigned short)i;
136
137 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
138 double d16 = fmod(d, D16);
139
140 return static_cast<unsigned short>(d16);
141}
142
143// Dispatchers for virtual functions, to special-case simple numbers which
144// won't be real pointers.
145
146Type ValueImp::dispatchType() const
147{
148 if (SimpleNumber::is(this))
149 return NumberType;
150 return type();
151}
152
153Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
154{
155 if (SimpleNumber::is(this))
156 return Value(const_cast<ValueImp *>(this));
157 return toPrimitive(exec, preferredType);
158}
159
160bool ValueImp::dispatchToBoolean(ExecState *exec) const
161{
162 if (SimpleNumber::is(this))
163 return SimpleNumber::value(this);
164 return toBoolean(exec);
165}
166
167double ValueImp::dispatchToNumber(ExecState *exec) const
168{
169 if (SimpleNumber::is(this))
170 return SimpleNumber::value(this);
171 return toNumber(exec);
172}
173
174UString ValueImp::dispatchToString(ExecState *exec) const
175{
176 if (SimpleNumber::is(this))
177 return UString::from(SimpleNumber::value(this));
178 return toString(exec);
179}
180
181Object ValueImp::dispatchToObject(ExecState *exec) const
182{
183 if (SimpleNumber::is(this))
184 return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
185 return toObject(exec);
186}
187
188bool ValueImp::dispatchToUInt32(unsigned& result) const
189{
190 if (SimpleNumber::is(this)) {
191 long i = SimpleNumber::value(this);
192 if (i < 0)
193 return false;
194 result = (unsigned)i;
195 return true;
196 }
197 return toUInt32(result);
198}
199
200// ------------------------------ Value ----------------------------------------
201
202Value::Value(ValueImp *v)
203{
204 rep = v;
205#if DEBUG_COLLECTOR
206 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
207 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
208#endif
209 if (v)
210 {
211 v->ref();
212 //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
213 v->setGcAllowed();
214 }
215}
216
217Value::Value(const Value &v)
218{
219 rep = v.imp();
220#if DEBUG_COLLECTOR
221 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
222 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
223#endif
224 if (rep)
225 {
226 rep->ref();
227 //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
228 }
229}
230
231Value::~Value()
232{
233 if (rep)
234 {
235 rep->deref();
236 //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
237 }
238}
239
240Value& Value::operator=(const Value &v)
241{
242 if (rep) {
243 rep->deref();
244 //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
245 }
246 rep = v.imp();
247 if (rep)
248 {
249 rep->ref();
250 //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
251 }
252 return *this;
253}
254
255// ------------------------------ Undefined ------------------------------------
256
257Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
258{
259}
260
261Undefined Undefined::dynamicCast(const Value &v)
262{
263 if (v.isNull() || v.type() != UndefinedType)
264 return Undefined(0);
265
266 return Undefined();
267}
268
269// ------------------------------ Null -----------------------------------------
270
271Null::Null() : Value(NullImp::staticNull)
272{
273}
274
275Null Null::dynamicCast(const Value &v)
276{
277 if (v.isNull() || v.type() != NullType)
278 return Null(0);
279
280 return Null();
281}
282
283// ------------------------------ Boolean --------------------------------------
284
285Boolean::Boolean(bool b)
286 : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
287{
288}
289
290bool Boolean::value() const
291{
292 assert(rep);
293 return ((BooleanImp*)rep)->value();
294}
295
296Boolean Boolean::dynamicCast(const Value &v)
297{
298 if (v.isNull() || v.type() != BooleanType)
299 return static_cast<BooleanImp*>(0);
300
301 return static_cast<BooleanImp*>(v.imp());
302}
303
304// ------------------------------ String ---------------------------------------
305
306String::String(const UString &s) : Value(new StringImp(s))
307{
308}
309
310UString String::value() const
311{
312 assert(rep);
313 return ((StringImp*)rep)->value();
314}
315
316String String::dynamicCast(const Value &v)
317{
318 if (v.isNull() || v.type() != StringType)
319 return String(0);
320
321 return String(static_cast<StringImp*>(v.imp()));
322}
323
324// ------------------------------ Number ---------------------------------------
325
326Number::Number(int i)
327 : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
328
329Number::Number(unsigned int u)
330 : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
331
332Number::Number(double d)
333 : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
334
335Number::Number(long int l)
336 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
337
338Number::Number(long unsigned int l)
339 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
340
341Number Number::dynamicCast(const Value &v)
342{
343 if (v.isNull() || v.type() != NumberType)
344 return Number((NumberImp*)0);
345
346 return Number(static_cast<NumberImp*>(v.imp()));
347}
348
349double Number::value() const
350{
351 if (SimpleNumber::is(rep))
352 return (double)SimpleNumber::value(rep);
353 assert(rep);
354 return ((NumberImp*)rep)->value();
355}
356
357int Number::intValue() const
358{
359 if (SimpleNumber::is(rep))
360 return SimpleNumber::value(rep);
361 return (int)((NumberImp*)rep)->value();
362}
363
364bool Number::isNaN() const
365{
366 return rep == NumberImp::staticNaN;
367}
368
369bool Number::isInf() const
370{
371 if (SimpleNumber::is(rep))
372 return false;
373 return KJS::isInf(((NumberImp*)rep)->value());
374}
Note: See TracBrowser for help on using the repository browser.