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., 51 Franklin Street, Fifth Floor,
00021  *  Boston, MA 02110-1301, 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   if (d32 < 0)
00143     d32 += D32;
00144 
00145   //6.3.1.4 Real floating and integer
00146   // 50) The remaindering operation performed when a value of integer type is
00147   //   converted to unsigned type need not be performed when a value of real
00148   //   floating type is converted to unsigned type. Thus, the range of
00149   //   portable real floating values is (-1, Utype_MAX+1).
00150   return static_cast<unsigned int>(d32);
00151 }
00152 
00153 unsigned short ValueImp::toUInt16(ExecState *exec) const
00154 {
00155   unsigned i;
00156   if (dispatchToUInt32(i))
00157     return (unsigned short)i;
00158 
00159   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
00160   double d16 = fmod(d, D16);
00161 
00162   // look at toUInt32 to see why this is necesary
00163   int t_int = static_cast<int>(d16);
00164   return static_cast<unsigned short>(t_int);
00165 }
00166 
00167 // Dispatchers for virtual functions, to special-case simple numbers which
00168 // won't be real pointers.
00169 
00170 Type ValueImp::dispatchType() const
00171 {
00172   if (SimpleNumber::is(this))
00173     return NumberType;
00174   return type();
00175 }
00176 
00177 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
00178 {
00179   if (SimpleNumber::is(this))
00180     return Value(const_cast<ValueImp *>(this));
00181   return toPrimitive(exec, preferredType);
00182 }
00183 
00184 bool ValueImp::dispatchToBoolean(ExecState *exec) const
00185 {
00186   if (SimpleNumber::is(this))
00187     return SimpleNumber::value(this);
00188   return toBoolean(exec);
00189 }
00190 
00191 double ValueImp::dispatchToNumber(ExecState *exec) const
00192 {
00193   if (SimpleNumber::is(this))
00194     return SimpleNumber::value(this);
00195   return toNumber(exec);
00196 }
00197 
00198 UString ValueImp::dispatchToString(ExecState *exec) const
00199 {
00200   if (SimpleNumber::is(this))
00201     return UString::from(SimpleNumber::value(this));
00202   return toString(exec);
00203 }
00204 
00205 Object ValueImp::dispatchToObject(ExecState *exec) const
00206 {
00207   if (SimpleNumber::is(this))
00208     return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
00209   return toObject(exec);
00210 }
00211 
00212 bool ValueImp::dispatchToUInt32(unsigned& result) const
00213 {
00214   if (SimpleNumber::is(this)) {
00215     long i = SimpleNumber::value(this);
00216     if (i < 0)
00217       return false;
00218     result = (unsigned)i;
00219     return true;
00220   }
00221   return toUInt32(result);
00222 }
00223 
00224 // ------------------------------ Value ----------------------------------------
00225 
00226 Value::Value(ValueImp *v)
00227 {
00228   rep = v;
00229 #ifdef DEBUG_COLLECTOR
00230   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
00231   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
00232 #endif
00233   if (v)
00234   {
00235     v->ref();
00236     //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
00237     v->setGcAllowed();
00238   }
00239 }
00240 
00241 Value::Value(const Value &v)
00242 {
00243   rep = v.imp();
00244 #ifdef DEBUG_COLLECTOR
00245   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
00246   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
00247 #endif
00248   if (rep)
00249   {
00250     rep->ref();
00251     //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
00252   }
00253 }
00254 
00255 Value::~Value()
00256 {
00257   if (rep)
00258   {
00259     rep->deref();
00260     //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
00261   }
00262 }
00263 
00264 Value& Value::operator=(const Value &v)
00265 {
00266   ValueImp *tmpRep = v.imp();
00267 
00268   //Avoid the destruction of the object underneath us by
00269   //incrementing the reference on it first
00270   if (tmpRep) {
00271     tmpRep->ref();
00272     //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, tmpRep, tmpRep->refcount);
00273   }
00274 
00275   if (rep) {
00276     rep->deref();
00277     //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
00278   }
00279   rep = tmpRep;
00280 
00281   return *this;
00282 }
00283 
00284 // ------------------------------ Undefined ------------------------------------
00285 
00286 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
00287 {
00288 }
00289 
00290 Undefined Undefined::dynamicCast(const Value &v)
00291 {
00292   if (!v.isValid() || v.type() != UndefinedType)
00293     return Undefined(0);
00294 
00295   return Undefined();
00296 }
00297 
00298 // ------------------------------ Null -----------------------------------------
00299 
00300 Null::Null() : Value(NullImp::staticNull)
00301 {
00302 }
00303 
00304 Null Null::dynamicCast(const Value &v)
00305 {
00306   if (!v.isValid() || v.type() != NullType)
00307     return Null(0);
00308 
00309   return Null();
00310 }
00311 
00312 // ------------------------------ Boolean --------------------------------------
00313 
00314 Boolean::Boolean(bool b)
00315   : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
00316 {
00317 }
00318 
00319 bool Boolean::value() const
00320 {
00321   assert(rep);
00322   return ((BooleanImp*)rep)->value();
00323 }
00324 
00325 Boolean Boolean::dynamicCast(const Value &v)
00326 {
00327   if (!v.isValid() || v.type() != BooleanType)
00328     return static_cast<BooleanImp*>(0);
00329 
00330   return static_cast<BooleanImp*>(v.imp());
00331 }
00332 
00333 // ------------------------------ String ---------------------------------------
00334 
00335 String::String(const UString &s) : Value(new StringImp(s))
00336 {
00337 #ifndef NDEBUG
00338   if (s.isNull())
00339     fprintf(stderr, "WARNING: KJS::String constructed from null string\n");
00340 #endif
00341 }
00342 
00343 UString String::value() const
00344 {
00345   assert(rep);
00346   return ((StringImp*)rep)->value();
00347 }
00348 
00349 String String::dynamicCast(const Value &v)
00350 {
00351   if (!v.isValid() || v.type() != StringType)
00352     return String(0);
00353 
00354   return String(static_cast<StringImp*>(v.imp()));
00355 }
00356 
00357 // ------------------------------ Number ---------------------------------------
00358 
00359 Number::Number(int i)
00360   : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
00361 
00362 Number::Number(unsigned int u)
00363   : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
00364 
00365 Number::Number(double d)
00366 #if defined(__alpha) && !defined(_IEEE_FP)
00367   // check for NaN first if we werent't compiled with -mieee on Alpha
00368  : Value(KJS::isNaN(d) ? NumberImp::staticNaN : (SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : new NumberImp(d))) { }
00369 #else
00370  : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
00371 #endif
00372 
00373 Number::Number(long int l)
00374   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
00375 
00376 Number::Number(long unsigned int l)
00377   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
00378 
00379 Number Number::dynamicCast(const Value &v)
00380 {
00381   if (!v.isValid() || v.type() != NumberType)
00382     return Number((NumberImp*)0);
00383 
00384   return Number(static_cast<NumberImp*>(v.imp()));
00385 }
00386 
00387 double Number::value() const
00388 {
00389   if (SimpleNumber::is(rep))
00390     return (double)SimpleNumber::value(rep);
00391   assert(rep);
00392   return ((NumberImp*)rep)->value();
00393 }
00394 
00395 int Number::intValue() const
00396 {
00397   if (SimpleNumber::is(rep))
00398     return SimpleNumber::value(rep);
00399   return (int)((NumberImp*)rep)->value();
00400 }
00401 
00402 bool Number::isNaN() const
00403 {
00404   return rep == NumberImp::staticNaN;
00405 }
00406 
00407 bool Number::isInf() const
00408 {
00409   if (SimpleNumber::is(rep))
00410     return false;
00411   return KJS::isInf(((NumberImp*)rep)->value());
00412 }
KDE Home | KDE Accessibility Home | Description of Access Keys