# kjs Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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 }

This file is part of the documentation for kjs Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:08 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003