~ubuntu-branches/ubuntu/maverick/webkit/maverick

« back to all changes in this revision

Viewing changes to JavaScriptCore/kjs/operations.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2007-08-19 15:54:12 UTC
  • Revision ID: james.westby@ubuntu.com-20070819155412-uxxg1h9plpghmtbi
Tags: upstream-0~svn25144
ImportĀ upstreamĀ versionĀ 0~svn25144

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- c-basic-offset: 2 -*-
 
2
/*
 
3
 *  This file is part of the KDE libraries
 
4
 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 
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 Street, Fifth Floor,
 
19
 *  Boston, MA 02110-1301, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
#include "operations.h"
 
25
 
 
26
#include "object.h"
 
27
#include <math.h>
 
28
#include <stdio.h>
 
29
#include <wtf/MathExtras.h>
 
30
 
 
31
#if HAVE(FUNC_ISINF) && HAVE(IEEEFP_H)
 
32
#include <ieeefp.h>
 
33
#endif
 
34
 
 
35
#if HAVE(FLOAT_H)
 
36
#include <float.h>
 
37
#endif
 
38
 
 
39
namespace KJS {
 
40
    
 
41
#if !PLATFORM(DARWIN)
 
42
 
 
43
// FIXME: Should probably be inlined on non-Darwin platforms too, and controlled exclusively
 
44
// by HAVE macros rather than PLATFORM.
 
45
 
 
46
// FIXME: Merge with isnan in MathExtras.h and remove this one entirely.
 
47
bool isNaN(double d)
 
48
{
 
49
#if HAVE(FUNC_ISNAN)
 
50
    return isnan(d);
 
51
#elif HAVE(FLOAT_H)
 
52
    return _isnan(d) != 0;
 
53
#else
 
54
    return !(d == d);
 
55
#endif
 
56
}
 
57
 
 
58
// FIXME: Merge with isinf in MathExtras.h and remove this one entirely.
 
59
bool isInf(double d)
 
60
{
 
61
    // FIXME: should be HAVE(_FPCLASS)
 
62
#if PLATFORM(WIN_OS)
 
63
    int fpClass = _fpclass(d);
 
64
    return _FPCLASS_PINF == fpClass || _FPCLASS_NINF == fpClass;
 
65
#elif HAVE(FUNC_ISINF)
 
66
    return isinf(d);
 
67
#elif HAVE(FUNC_FINITE)
 
68
    return finite(d) == 0 && d == d;
 
69
#elif HAVE(FUNC__FINITE)
 
70
    return _finite(d) == 0 && d == d;
 
71
#else
 
72
    return false;
 
73
#endif
 
74
}
 
75
 
 
76
bool isPosInf(double d)
 
77
{
 
78
    // FIXME: should be HAVE(_FPCLASS)
 
79
#if PLATFORM(WIN_OS)
 
80
    return _FPCLASS_PINF == _fpclass(d);
 
81
#elif HAVE(FUNC_ISINF)
 
82
    return (isinf(d) == 1);
 
83
#elif HAVE(FUNC_FINITE)
 
84
    return !finite(d) && d == d; // ### can we distinguish between + and - ?
 
85
#elif HAVE(FUNC__FINITE)
 
86
    return !_finite(d) && d == d; // ###
 
87
#else
 
88
    return false;
 
89
#endif
 
90
}
 
91
 
 
92
bool isNegInf(double d)
 
93
{
 
94
    // FIXME: should be HAVE(_FPCLASS)
 
95
#if PLATFORM(WIN_OS)
 
96
    return _FPCLASS_NINF == _fpclass(d);
 
97
#elif HAVE(FUNC_ISINF)
 
98
    return (isinf(d) == -1);
 
99
#elif HAVE(FUNC_FINITE)
 
100
    return finite(d) == 0 && d == d; // ###
 
101
#elif HAVE(FUNC__FINITE)
 
102
    return _finite(d) == 0 && d == d; // ###
 
103
#else
 
104
    return false;
 
105
#endif
 
106
}
 
107
 
 
108
#endif
 
109
 
 
110
// ECMA 11.9.3
 
111
bool equal(ExecState *exec, JSValue *v1, JSValue *v2)
 
112
{
 
113
    JSType t1 = v1->type();
 
114
    JSType t2 = v2->type();
 
115
    
 
116
    if (t1 != t2) {
 
117
        if (t1 == UndefinedType)
 
118
            t1 = NullType;
 
119
        if (t2 == UndefinedType)
 
120
            t2 = NullType;
 
121
        
 
122
        if (t1 == BooleanType)
 
123
            t1 = NumberType;
 
124
        if (t2 == BooleanType)
 
125
            t2 = NumberType;
 
126
        
 
127
        if (t1 == NumberType && t2 == StringType) {
 
128
            // use toNumber
 
129
        } else if (t1 == StringType && t2 == NumberType)
 
130
            t1 = NumberType;
 
131
            // use toNumber
 
132
        else {
 
133
            if ((t1 == StringType || t1 == NumberType) && t2 >= ObjectType)
 
134
                return equal(exec, v1, v2->toPrimitive(exec));
 
135
            if (t1 == NullType && t2 == ObjectType)
 
136
                return static_cast<JSObject *>(v2)->masqueradeAsUndefined();
 
137
            if (t1 >= ObjectType && (t2 == StringType || t2 == NumberType))
 
138
                return equal(exec, v1->toPrimitive(exec), v2);
 
139
            if (t1 == ObjectType && t2 == NullType)
 
140
                return static_cast<JSObject *>(v1)->masqueradeAsUndefined();
 
141
            if (t1 != t2)
 
142
                return false;
 
143
        }
 
144
    }
 
145
    
 
146
    if (t1 == UndefinedType || t1 == NullType)
 
147
        return true;
 
148
    
 
149
    if (t1 == NumberType) {
 
150
        double d1 = v1->toNumber(exec);
 
151
        double d2 = v2->toNumber(exec);
 
152
        return d1 == d2;
 
153
    }
 
154
    
 
155
    if (t1 == StringType)
 
156
        return v1->toString(exec) == v2->toString(exec);
 
157
    
 
158
    if (t1 == BooleanType)
 
159
        return v1->toBoolean(exec) == v2->toBoolean(exec);
 
160
    
 
161
    // types are Object
 
162
    return v1 == v2;
 
163
}
 
164
 
 
165
bool strictEqual(ExecState *exec, JSValue *v1, JSValue *v2)
 
166
{
 
167
    JSType t1 = v1->type();
 
168
    JSType t2 = v2->type();
 
169
    
 
170
    if (t1 != t2)
 
171
        return false;
 
172
    if (t1 == UndefinedType || t1 == NullType)
 
173
        return true;
 
174
    if (t1 == NumberType) {
 
175
        double n1 = v1->toNumber(exec);
 
176
        double n2 = v2->toNumber(exec);
 
177
        if (n1 == n2)
 
178
            return true;
 
179
        return false;
 
180
    } else if (t1 == StringType)
 
181
        return v1->toString(exec) == v2->toString(exec);
 
182
    else if (t2 == BooleanType)
 
183
        return v1->toBoolean(exec) == v2->toBoolean(exec);
 
184
    
 
185
    if (v1 == v2)
 
186
        return true;
 
187
    /* TODO: joined objects */
 
188
    
 
189
    return false;
 
190
}
 
191
 
 
192
int relation(ExecState *exec, JSValue *v1, JSValue *v2)
 
193
{
 
194
    JSValue *p1 = v1->toPrimitive(exec,NumberType);
 
195
    JSValue *p2 = v2->toPrimitive(exec,NumberType);
 
196
    
 
197
    if (p1->isString() && p2->isString())
 
198
        return p1->toString(exec) < p2->toString(exec) ? 1 : 0;
 
199
    
 
200
    double n1 = p1->toNumber(exec);
 
201
    double n2 = p2->toNumber(exec);
 
202
    if (n1 < n2)
 
203
        return 1;
 
204
    if (n1 >= n2)
 
205
        return 0;
 
206
    return -1; // must be NaN, so undefined
 
207
}
 
208
 
 
209
int maxInt(int d1, int d2)
 
210
{
 
211
    return (d1 > d2) ? d1 : d2;
 
212
}
 
213
 
 
214
int minInt(int d1, int d2)
 
215
{
 
216
    return (d1 < d2) ? d1 : d2;
 
217
}
 
218
 
 
219
// ECMA 11.6
 
220
JSValue *add(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
 
221
{
 
222
    // exception for the Date exception in defaultValue()
 
223
    JSType preferred = oper == '+' ? UnspecifiedType : NumberType;
 
224
    JSValue *p1 = v1->toPrimitive(exec, preferred);
 
225
    JSValue *p2 = v2->toPrimitive(exec, preferred);
 
226
    
 
227
    if ((p1->isString() || p2->isString()) && oper == '+') {
 
228
        UString value = p1->toString(exec) + p2->toString(exec);
 
229
        if (value.isNull()) {
 
230
            JSObject *error = Error::create(exec, GeneralError, "Out of memory");
 
231
            exec->setException(error);
 
232
            return error;
 
233
        } else
 
234
            return jsString(value);
 
235
    }
 
236
    
 
237
    if (oper == '+')
 
238
        return jsNumber(p1->toNumber(exec) + p2->toNumber(exec));
 
239
    else
 
240
        return jsNumber(p1->toNumber(exec) - p2->toNumber(exec));
 
241
}
 
242
 
 
243
// ECMA 11.5
 
244
JSValue *mult(ExecState *exec, JSValue *v1, JSValue *v2, char oper)
 
245
{
 
246
    double n1 = v1->toNumber(exec);
 
247
    double n2 = v2->toNumber(exec);
 
248
    
 
249
    double result;
 
250
    
 
251
    if (oper == '*')
 
252
        result = n1 * n2;
 
253
    else if (oper == '/')
 
254
        result = n1 / n2;
 
255
    else
 
256
        result = fmod(n1, n2);
 
257
    
 
258
    return jsNumber(result);
 
259
}
 
260
 
 
261
}