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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Aug 30 22:54:17 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003