kjs Library API Documentation

operations.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser General Public License
00017  *  along with this library; see the file COPYING.LIB.  If not, write to
00018  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  *  Boston, MA 02111-1307, USA.
00020  *
00021  */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 #ifndef HAVE_FLOAT_H   /* just for !Windows */
00027 #define HAVE_FLOAT_H 0
00028 #define HAVE_FUNC__FINITE 0
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <assert.h>
00033 #include <math.h>
00034 #include <stdlib.h>
00035 
00036 // For declaration of isinf on Sun C++
00037 #ifdef __SUNPRO_CC
00038 #include <sunmath.h>
00039 #endif
00040 
00041 #ifndef HAVE_FUNC_ISINF
00042 #ifdef HAVE_IEEEFP_H
00043 #include <ieeefp.h>
00044 #endif
00045 #endif /* HAVE_FUNC_ISINF */
00046 
00047 #if HAVE_FLOAT_H
00048 #include <float.h>
00049 #endif
00050 
00051 #include "operations.h"
00052 #include "object.h"
00053 
00054 using namespace KJS;
00055 
00056 bool KJS::isNaN(double d)
00057 {
00058 #ifdef HAVE_FUNC_ISNAN
00059   return isnan(d);
00060 #elif defined HAVE_FLOAT_H
00061   return _isnan(d) != 0;
00062 #else
00063   return !(d == d);
00064 #endif
00065 }
00066 
00067 bool KJS::isInf(double d)
00068 {
00069 #if defined(HAVE_FUNC_ISINF)
00070   return isinf(d);
00071 #elif HAVE_FUNC_FINITE
00072   return finite(d) == 0 && d == d;
00073 #elif HAVE_FUNC__FINITE
00074   return _finite(d) == 0 && d == d;
00075 #else
00076   return false;
00077 #endif
00078 }
00079 
00080 bool KJS::isPosInf(double d)
00081 {
00082 #if defined(HAVE_FUNC_ISINF)
00083   return (isinf(d) == 1);
00084 #elif HAVE_FUNC_FINITE
00085   return finite(d) == 0 && d == d; // ### can we distinguish between + and - ?
00086 #elif HAVE_FUNC__FINITE
00087   return _finite(d) == 0 && d == d; // ###
00088 #else
00089   return false;
00090 #endif
00091 }
00092 
00093 bool KJS::isNegInf(double d)
00094 {
00095 #if defined(HAVE_FUNC_ISINF)
00096   return (isinf(d) == -1);
00097 #elif HAVE_FUNC_FINITE
00098   return finite(d) == 0 && d == d; // ###
00099 #elif HAVE_FUNC__FINITE
00100   return _finite(d) == 0 && d == d; // ###
00101 #else
00102   return false;
00103 #endif
00104 }
00105 
00106 // ECMA 11.9.3
00107 bool KJS::equal(ExecState *exec, const Value& v1, const Value& v2)
00108 {
00109   Type t1 = v1.type();
00110   Type t2 = v2.type();
00111 
00112   if (t1 == t2) {
00113     if (t1 == UndefinedType || t1 == NullType)
00114       return true;
00115     if (t1 == NumberType)
00116     {
00117       double d1 = v1.toNumber(exec);
00118       double d2 = v2.toNumber(exec);
00119       if ( isNaN( d1 ) || isNaN( d2 ) )
00120         return false;
00121       return ( d1 == d2 ); /* TODO: +0, -0 ? */
00122     }
00123     if (t1 == StringType)
00124       return (v1.toString(exec) == v2.toString(exec));
00125     if (t1 == BooleanType)
00126       return (v1.toBoolean(exec) == v2.toBoolean(exec));
00127 
00128     // types are Object
00129     return (v1.imp() == v2.imp());
00130   }
00131 
00132   // different types
00133   if ((t1 == NullType && t2 == UndefinedType) || (t1 == UndefinedType && t2 == NullType))
00134     return true;
00135   if (t1 == NumberType && t2 == StringType) {
00136     Number n2 = v2.toNumber(exec);
00137     return equal(exec,v1, n2);
00138   }
00139   if ((t1 == StringType && t2 == NumberType) || t1 == BooleanType) {
00140     Number n1 = v1.toNumber(exec);
00141     return equal(exec,n1, v2);
00142   }
00143   if (t2 == BooleanType) {
00144     Number n2 = v2.toNumber(exec);
00145     return equal(exec,v1, n2);
00146   }
00147   if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType) {
00148     Value p2 = v2.toPrimitive(exec);
00149     return equal(exec,v1, p2);
00150   }
00151   if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType)) {
00152     Value p1 = v1.toPrimitive(exec);
00153     return equal(exec,p1, v2);
00154   }
00155 
00156   return false;
00157 }
00158 
00159 bool KJS::strictEqual(ExecState *exec, const Value &v1, const Value &v2)
00160 {
00161   Type t1 = v1.type();
00162   Type t2 = v2.type();
00163 
00164   if (t1 != t2)
00165     return false;
00166   if (t1 == UndefinedType || t1 == NullType)
00167     return true;
00168   if (t1 == NumberType) {
00169     double n1 = v1.toNumber(exec);
00170     double n2 = v2.toNumber(exec);
00171     if (isNaN(n1) || isNaN(n2))
00172       return false;
00173     if (n1 == n2)
00174       return true;
00175     /* TODO: +0 and -0 */
00176     return false;
00177   } else if (t1 == StringType) {
00178     return v1.toString(exec) == v2.toString(exec);
00179   } else if (t2 == BooleanType) {
00180     return v1.toBoolean(exec) == v2.toBoolean(exec);
00181   }
00182   if (v1.imp() == v2.imp())
00183     return true;
00184   /* TODO: joined objects */
00185 
00186   return false;
00187 }
00188 
00189 int KJS::relation(ExecState *exec, const Value& v1, const Value& v2)
00190 {
00191   Value p1 = v1.toPrimitive(exec,NumberType);
00192   Value p2 = v2.toPrimitive(exec,NumberType);
00193 
00194   if (p1.type() == StringType && p2.type() == StringType)
00195     return p1.toString(exec) < p2.toString(exec) ? 1 : 0;
00196 
00197   double n1 = p1.toNumber(exec);
00198   double n2 = p2.toNumber(exec);
00199   if ( isNaN( n1 ) || isNaN( n2 ) )
00200     return -1; // means undefined
00201   if (n1 == n2)
00202     return 0;
00203   /* TODO: +0, -0 */
00204   if ( isPosInf( n1 ) )
00205     return 0;
00206   if ( isPosInf( n2 ) )
00207     return 1;
00208   if ( isNegInf( n2 ) )
00209     return 0;
00210   if ( isNegInf( n1 ) )
00211     return 1;
00212   return (n1 < n2) ? 1 : 0;
00213 }
00214 
00215 int KJS::maxInt(int d1, int d2)
00216 {
00217   return (d1 > d2) ? d1 : d2;
00218 }
00219 
00220 int KJS::minInt(int d1, int d2)
00221 {
00222   return (d1 < d2) ? d1 : d2;
00223 }
00224 
00225 // ECMA 11.6
00226 Value KJS::add(ExecState *exec, const Value &v1, const Value &v2, char oper)
00227 {
00228   // exception for the Date exception in defaultValue()
00229   Type preferred = oper == '+' ? UnspecifiedType : NumberType;
00230   Value p1 = v1.toPrimitive(exec, preferred);
00231   Value p2 = v2.toPrimitive(exec, preferred);
00232 
00233   if ((p1.type() == StringType || p2.type() == StringType) && oper == '+') {
00234     UString s1 = p1.toString(exec);
00235     UString s2 = p2.toString(exec);
00236 
00237     return String(s1 + s2);
00238   }
00239 
00240   double n1 = p1.toNumber(exec);
00241   double n2 = p2.toNumber(exec);
00242 
00243   if (oper == '+')
00244     return Number(n1 + n2);
00245   else
00246     return Number(n1 - n2);
00247 }
00248 
00249 // ECMA 11.5
00250 Value KJS::mult(ExecState *exec, const Value &v1, const Value &v2, char oper)
00251 {
00252   double n1 = v1.toNumber(exec);
00253   double n2 = v2.toNumber(exec);
00254 
00255   double result;
00256 
00257   if (oper == '*')
00258     result = n1 * n2;
00259   else if (oper == '/')
00260     result = n1 / n2;
00261   else
00262     result = fmod(n1, n2);
00263 
00264   return Number(result);
00265 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:15 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001