kjs Library: operations.cpp Source File (kjs Library)

| # kjs Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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 Library 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  *  Library General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU Library 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 }

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:07 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003