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 }