source: webkit/trunk/JavaScriptCore/kjs/operations.cpp@ 11923

Last change on this file since 11923 was 11923, checked in by andersca, 19 years ago

2006-01-07 Anders Carlsson <[email protected]>

Reviewed by Maciej.

  • kjs/object.h: (KJS::JSObject::isEqualToNull): Add new function which returns true if an object should be treated as null when doing comparisons.
  • kjs/operations.cpp: (KJS::equal): Use isEqualToNull.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.0 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2000 Harri Porten ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "operations.h"
25
26
27#include <stdio.h>
28#include <assert.h>
29#include <math.h>
30#include <stdlib.h>
31
32#ifndef HAVE_FUNC_ISINF
33#ifdef HAVE_IEEEFP_H
34#include <ieeefp.h>
35#endif
36#endif /* HAVE_FUNC_ISINF */
37
38#if HAVE_FLOAT_H
39#include <float.h>
40#endif
41
42#include "object.h"
43
44namespace KJS {
45
46#if !APPLE_CHANGES
47
48bool isNaN(double d)
49{
50#ifdef HAVE_FUNC_ISNAN
51 return isnan(d);
52#elif defined HAVE_FLOAT_H
53 return _isnan(d) != 0;
54#else
55 return !(d == d);
56#endif
57}
58
59bool isInf(double d)
60{
61#if WIN32
62 int fpClass = _fpclass(d);
63 return _FPCLASS_PINF == fpClass || _FPCLASS_NINF == fpClass;
64#elif defined(HAVE_FUNC_ISINF)
65 return isinf(d);
66#elif HAVE_FUNC_FINITE
67 return finite(d) == 0 && d == d;
68#elif HAVE_FUNC__FINITE
69 return _finite(d) == 0 && d == d;
70#else
71 return false;
72#endif
73}
74
75bool isPosInf(double d)
76{
77#if WIN32
78 return _FPCLASS_PINF == _fpclass(d);
79#elif defined(HAVE_FUNC_ISINF)
80 return (isinf(d) == 1);
81#elif HAVE_FUNC_FINITE
82 return finite(d) == 0 && d == d; // ### can we distinguish between + and - ?
83#elif HAVE_FUNC__FINITE
84 return _finite(d) == 0 && d == d; // ###
85#else
86 return false;
87#endif
88}
89
90bool isNegInf(double d)
91{
92#if WIN32
93 return _FPCLASS_PINF == _fpclass(d);
94#elif defined(HAVE_FUNC_ISINF)
95 return (isinf(d) == -1);
96#elif HAVE_FUNC_FINITE
97 return finite(d) == 0 && d == d; // ###
98#elif HAVE_FUNC__FINITE
99 return _finite(d) == 0 && d == d; // ###
100#else
101 return false;
102#endif
103}
104
105#endif
106
107// ECMA 11.9.3
108bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
109{
110 Type t1 = v1->type();
111 Type t2 = v2->type();
112
113 if (t1 != t2) {
114 if (t1 == UndefinedType)
115 t1 = NullType;
116 if (t2 == UndefinedType)
117 t2 = NullType;
118
119 if (t1 == BooleanType)
120 t1 = NumberType;
121 if (t2 == BooleanType)
122 t2 = NumberType;
123
124 if (t1 == NumberType && t2 == StringType) {
125 // use toNumber
126 } else if (t1 == StringType && t2 == NumberType) {
127 t1 = NumberType;
128 // use toNumber
129 } else {
130 if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType)
131 return equal(exec, v1, v2->toPrimitive(exec));
132 if (t1 == NullType && t2 == ObjectType)
133 return static_cast<JSObject *>(v2)->isEqualToNull(exec);
134 if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType))
135 return equal(exec, v1->toPrimitive(exec), v2);
136 if (t1 == ObjectType && t2 == NullType)
137 return static_cast<JSObject *>(v1)->isEqualToNull(exec);
138 if (t1 != t2)
139 return false;
140 }
141 }
142
143 if (t1 == UndefinedType || t1 == NullType)
144 return true;
145
146 if (t1 == NumberType) {
147 double d1 = v1->toNumber(exec);
148 double d2 = v2->toNumber(exec);
149 return d1 == d2;
150 }
151
152 if (t1 == StringType)
153 return v1->toString(exec) == v2->toString(exec);
154
155 if (t1 == BooleanType)
156 return v1->toBoolean(exec) == v2->toBoolean(exec);
157
158 // types are Object
159 return v1 == v2;
160}
161
162bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
163{
164 Type t1 = v1->type();
165 Type t2 = v2->type();
166
167 if (t1 != t2)
168 return false;
169 if (t1 == UndefinedType || t1 == NullType)
170 return true;
171 if (t1 == NumberType) {
172 double n1 = v1->toNumber(exec);
173 double n2 = v2->toNumber(exec);
174 if (n1 == n2)
175 return true;
176 return false;
177 } else if (t1 == StringType) {
178 return v1->toString(exec) == v2->toString(exec);
179 } else if (t2 == BooleanType) {
180 return v1->toBoolean(exec) == v2->toBoolean(exec);
181 }
182 if (v1 == v2)
183 return true;
184 /* TODO: joined objects */
185
186 return false;
187}
188
189int relation(ExecState *exec, JSValue *v1, JSValue *v2)
190{
191 JSValue *p1 = v1->toPrimitive(exec,NumberType);
192 JSValue *p2 = v2->toPrimitive(exec,NumberType);
193
194 if (p1->isString() && p2->isString())
195 return p1->toString(exec) < p2->toString(exec) ? 1 : 0;
196
197 double n1 = p1->toNumber(exec);
198 double n2 = p2->toNumber(exec);
199 if (n1 < n2)
200 return 1;
201 if (n1 >= n2)
202 return 0;
203 return -1; // must be NaN, so undefined
204}
205
206int maxInt(int d1, int d2)
207{
208 return (d1 > d2) ? d1 : d2;
209}
210
211int minInt(int d1, int d2)
212{
213 return (d1 < d2) ? d1 : d2;
214}
215
216// ECMA 11.6
217JSValue *add(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
218{
219 // exception for the Date exception in defaultValue()
220 Type preferred = oper == '+' ? UnspecifiedType : NumberType;
221 JSValue *p1 = v1->toPrimitive(exec, preferred);
222 JSValue *p2 = v2->toPrimitive(exec, preferred);
223
224 if ((p1->isString() || p2->isString()) && oper == '+') {
225 return jsString(p1->toString(exec) + p2->toString(exec));
226 }
227
228 if (oper == '+')
229 return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
230 else
231 return jsNumber(p1->toNumber(exec) - p2->toNumber(exec));
232}
233
234// ECMA 11.5
235JSValue *mult(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
236{
237 double n1 = v1->toNumber(exec);
238 double n2 = v2->toNumber(exec);
239
240 double result;
241
242 if (oper == '*') {
243 result = n1 * n2;
244 } else if (oper == '/') {
245 result = n1 / n2;
246 } else {
247 result = fmod(n1, n2);
248 }
249
250 return jsNumber(result);
251}
252
253}
Note: See TracBrowser for help on using the repository browser.