kjs Library API Documentation

value.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
00006  *  Copyright (C) 2003 Apple Computer, Inc.
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public License
00019  *  along with this library; see the file COPYING.LIB.  If not, write to
00020  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021  *  Boston, MA 02111-1307, USA.
00022  *
00023  */
00024 
00025 #include "value.h"
00026 #include "object.h"
00027 #include "types.h"
00028 #include "interpreter.h"
00029 
00030 #include <assert.h>
00031 #include <math.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <limits.h>
00035 
00036 #include "internal.h"
00037 #include "collector.h"
00038 #include "operations.h"
00039 #include "error_object.h"
00040 #include "nodes.h"
00041 #include "simple_number.h"
00042 
00043 using namespace KJS;
00044 
00045 // ----------------------------- ValueImp -------------------------------------
00046 
00047 ValueImp::ValueImp() :
00048   refcount(0),
00049   // Tell the garbage collector that this memory block corresponds to a real object now
00050   _flags(VI_CREATED)
00051 {
00052   //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
00053 }
00054 
00055 ValueImp::~ValueImp()
00056 {
00057   //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
00058   _flags |= VI_DESTRUCTED;
00059 }
00060 
00061 void ValueImp::mark()
00062 {
00063   //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
00064   _flags |= VI_MARKED;
00065 }
00066 
00067 bool ValueImp::marked() const
00068 {
00069   // Simple numbers are always considered marked.
00070   return SimpleNumber::is(this) || (_flags & VI_MARKED);
00071 }
00072 
00073 void ValueImp::setGcAllowed()
00074 {
00075   //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
00076   // simple numbers are never seen by the collector so setting this
00077   // flag is irrelevant
00078   if (!SimpleNumber::is(this))
00079     _flags |= VI_GCALLOWED;
00080 }
00081 
00082 void* ValueImp::operator new(size_t s)
00083 {
00084   return Collector::allocate(s);
00085 }
00086 
00087 void ValueImp::operator delete(void*)
00088 {
00089   // Do nothing. So far.
00090 }
00091 
00092 bool ValueImp::toUInt32(unsigned&) const
00093 {
00094   return false;
00095 }
00096 
00097 // ECMA 9.4
00098 int ValueImp::toInteger(ExecState *exec) const
00099 {
00100   unsigned i;
00101   if (dispatchToUInt32(i))
00102     return static_cast<int>(i);
00103   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
00104   if (isInf(d))
00105     return INT_MAX;
00106   return static_cast<int>(d);
00107 }
00108 
00109 int ValueImp::toInt32(ExecState *exec) const
00110 {
00111   unsigned i;
00112   if (dispatchToUInt32(i))
00113     return (int)i;
00114 
00115   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
00116   if (isNaN(d) || isInf(d) || d == 0.0)
00117     return 0;
00118   double d32 = fmod(d, D32);
00119 
00120   //Make sure we use the positive remainder. This matters since this may be
00121   //less than MIN_INT (but still < 2^32), and we don't want the cast to clamp.
00122   if (d32 < 0)
00123     d32 += D32;
00124 
00125   if (d32 >= D32 / 2.0)
00126     d32 -= D32;
00127 
00128   return static_cast<int>(d32);
00129 }
00130 
00131 unsigned int ValueImp::toUInt32(ExecState *exec) const
00132 {
00133   unsigned i;
00134   if (dispatchToUInt32(i))
00135     return i;
00136 
00137   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
00138   if (isNaN(d) || isInf(d) || d == 0.0)
00139     return 0;
00140   double d32 = fmod(d, D32);
00141 
00142   //6.3.1.4 Real floating and integer
00143   // 50) The remaindering operation performed when a value of integer type is
00144   //   converted to unsigned type need not be performed when a value of real
00145   //   floating type is converted to unsigned type. Thus, the range of
00146   //   portable real floating values is (-1, Utype_MAX+1). 
00147   int t_int = static_cast<int>(d32);
00148   return static_cast<unsigned int>(t_int);
00149 }
00150 
00151 unsigned short ValueImp::toUInt16(ExecState *exec) const
00152 {
00153   unsigned i;
00154   if (dispatchToUInt32(i))
00155     return (unsigned short)i;
00156 
00157   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
00158   double d16 = fmod(d, D16);
00159 
00160   // look at toUInt32 to see why this is necesary
00161   int t_int = static_cast<int>(d16);
00162   return static_cast<unsigned short>(t_int);
00163 }
00164 
00165 // Dispatchers for virtual functions, to special-case simple numbers which
00166 // won't be real pointers.
00167 
00168 Type ValueImp::dispatchType() const
00169 {
00170   if (SimpleNumber::is(this))
00171     return NumberType;
00172   return type();
00173 }
00174 
00175 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
00176 {
00177   if (SimpleNumber::is(this))
00178     return Value(const_cast<ValueImp *>(this));
00179   return toPrimitive(exec, preferredType);
00180 }
00181 
00182 bool ValueImp::dispatchToBoolean(ExecState *exec) const
00183 {
00184   if (SimpleNumber::is(this))
00185     return SimpleNumber::value(this);
00186   return toBoolean(exec);
00187 }
00188 
00189 double ValueImp::dispatchToNumber(ExecState *exec) const
00190 {
00191   if (SimpleNumber::is(this))
00192     return SimpleNumber::value(this);
00193   return toNumber(exec);
00194 }
00195 
00196 UString ValueImp::dispatchToString(ExecState *exec) const
00197 {
00198   if (SimpleNumber::is(this))
00199     return UString::from(SimpleNumber::value(this));
00200   return toString(exec);
00201 }
00202 
00203 Object ValueImp::dispatchToObject(ExecState *exec) const
00204 {
00205   if (SimpleNumber::is(this))
00206     return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
00207   return toObject(exec);
00208 }
00209 
00210 bool ValueImp::dispatchToUInt32(unsigned& result) const
00211 {
00212   if (SimpleNumber::is(this)) {
00213     long i = SimpleNumber::value(this);
00214     if (i < 0)
00215       return false;
00216     result = (unsigned)i;
00217     return true;
00218   }
00219   return toUInt32(result);
00220 }
00221 
00222 // ------------------------------ Value ----------------------------------------
00223 
00224 Value::Value(ValueImp *v)
00225 {
00226   rep = v;
00227 #ifdef DEBUG_COLLECTOR
00228   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
00229   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
00230 #endif
00231   if (v)
00232   {
00233     v->ref();
00234     //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
00235     v->setGcAllowed();
00236   }
00237 }
00238 
00239 Value::Value(const Value &v)
00240 {
00241   rep = v.imp();
00242 #ifdef DEBUG_COLLECTOR
00243   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
00244   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
00245 #endif
00246   if (rep)
00247   {
00248     rep->ref();
00249     //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
00250   }
00251 }
00252 
00253 Value::~Value()
00254 {
00255   if (rep)
00256   {
00257     rep->deref();
00258     //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
00259   }
00260 }
00261 
00262 Value& Value::operator=(const Value &v)
00263 {
00264   ValueImp *tmpRep = v.imp();
00265 
00266   //Avoid the destruction of the object underneath us by
00267   //incrementing the reference on it first
00268   if (tmpRep) {
00269     tmpRep->ref();
00270     //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, tmpRep, tmpRep->refcount);
00271   }
00272 
00273   if (rep) {
00274     rep->deref();
00275     //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
00276   }
00277   rep = tmpRep;
00278 
00279   return *this;
00280 }
00281 
00282 // ------------------------------ Undefined ------------------------------------
00283 
00284 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
00285 {
00286 }
00287 
00288 Undefined Undefined::dynamicCast(const Value &v)
00289 {
00290   if (!v.isValid() || v.type() != UndefinedType)
00291     return Undefined(0);
00292 
00293   return Undefined();
00294 }
00295 
00296 // ------------------------------ Null -----------------------------------------
00297 
00298 Null::Null() : Value(NullImp::staticNull)
00299 {
00300 }
00301 
00302 Null Null::dynamicCast(const Value &v)
00303 {
00304   if (!v.isValid() || v.type() != NullType)
00305     return Null(0);
00306 
00307   return Null();
00308 }
00309 
00310 // ------------------------------ Boolean --------------------------------------
00311 
00312 Boolean::Boolean(bool b)
00313   : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
00314 {
00315 }
00316 
00317 bool Boolean::value() const
00318 {
00319   assert(rep);
00320   return ((BooleanImp*)rep)->value();
00321 }
00322 
00323 Boolean Boolean::dynamicCast(const Value &v)
00324 {
00325   if (!v.isValid() || v.type() != BooleanType)
00326     return static_cast<BooleanImp*>(0);
00327 
00328   return static_cast<BooleanImp*>(v.imp());
00329 }
00330 
00331 // ------------------------------ String ---------------------------------------
00332 
00333 String::String(const UString &s) : Value(new StringImp(UString(s)))
00334 {
00335 }
00336 
00337 UString String::value() const
00338 {
00339   assert(rep);
00340   return ((StringImp*)rep)->value();
00341 }
00342 
00343 String String::dynamicCast(const Value &v)
00344 {
00345   if (!v.isValid() || v.type() != StringType)
00346     return String(0);
00347 
00348   return String(static_cast<StringImp*>(v.imp()));
00349 }
00350 
00351 // ------------------------------ Number ---------------------------------------
00352 
00353 Number::Number(int i)
00354   : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
00355 
00356 Number::Number(unsigned int u)
00357   : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
00358 
00359 Number::Number(double d)
00360 #if defined(__alpha) && !defined(_IEEE_FP)
00361   // check for NaN first if we werent't compiled with -mieee on Alpha
00362  : Value(KJS::isNaN(d) ? NumberImp::staticNaN : (SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : new NumberImp(d))) { }
00363 #else
00364  : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
00365 #endif
00366 
00367 Number::Number(long int l)
00368   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
00369 
00370 Number::Number(long unsigned int l)
00371   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
00372 
00373 Number Number::dynamicCast(const Value &v)
00374 {
00375   if (v.isNull() || v.type() != NumberType)
00376     return Number((NumberImp*)0);
00377 
00378   return Number(static_cast<NumberImp*>(v.imp()));
00379 }
00380 
00381 double Number::value() const
00382 {
00383   if (SimpleNumber::is(rep))
00384     return (double)SimpleNumber::value(rep);
00385   assert(rep);
00386   return ((NumberImp*)rep)->value();
00387 }
00388 
00389 int Number::intValue() const
00390 {
00391   if (SimpleNumber::is(rep))
00392     return SimpleNumber::value(rep);
00393   return (int)((NumberImp*)rep)->value();
00394 }
00395 
00396 bool Number::isNaN() const
00397 {
00398   return rep == NumberImp::staticNaN;
00399 }
00400 
00401 bool Number::isInf() const
00402 {
00403   if (SimpleNumber::is(rep))
00404     return false;
00405   return KJS::isInf(((NumberImp*)rep)->value());
00406 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 22 14:23:48 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003