Reviewed by Maciej.
[WebKit-https.git] / JavaScriptCore / kjs / value.cpp
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2003 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "value.h"
26
27 #include <math.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "operations.h"
32 #include "error_object.h"
33 #include "nodes.h"
34
35 namespace KJS {
36
37 static const double D16 = 65536.0;
38 static const double D32 = 4294967296.0;
39
40 void *JSCell::operator new(size_t size)
41 {
42     return Collector::allocate(size);
43 }
44
45 bool JSCell::getUInt32(unsigned&) const
46 {
47     return false;
48 }
49
50 // ECMA 9.4
51 double JSValue::toInteger(ExecState *exec) const
52 {
53     uint32_t i;
54     if (getUInt32(i))
55         return i;
56     return roundValue(exec, const_cast<JSValue*>(this));
57 }
58
59 int32_t JSValue::toInt32(ExecState *exec) const
60 {
61     uint32_t i;
62     if (getUInt32(i))
63         return i;
64
65     double d = roundValue(exec, const_cast<JSValue*>(this));
66     if (isNaN(d) || isInf(d))
67         return 0;
68     double d32 = fmod(d, D32);
69
70     if (d32 >= D32 / 2)
71         d32 -= D32;
72     else if (d32 < -D32 / 2)
73         d32 += D32;
74
75     return static_cast<int32_t>(d32);
76 }
77
78 uint32_t JSValue::toUInt32(ExecState *exec) const
79 {
80     uint32_t i;
81     if (getUInt32(i))
82         return i;
83
84     double d = roundValue(exec, const_cast<JSValue*>(this));
85     if (isNaN(d) || isInf(d))
86         return 0;
87     double d32 = fmod(d, D32);
88
89     if (d32 < 0)
90         d32 += D32;
91
92     return static_cast<uint32_t>(d32);
93 }
94
95 uint16_t JSValue::toUInt16(ExecState *exec) const
96 {
97     uint32_t i;
98     if (getUInt32(i))
99         return i;
100
101     double d = roundValue(exec, const_cast<JSValue*>(this));
102     if (isNaN(d) || isInf(d))
103         return 0;
104     double d16 = fmod(d, D16);
105
106     if (d16 < 0)
107         d16 += D16;
108
109     return static_cast<uint16_t>(d16);
110 }
111
112 bool JSCell::getNumber(double &numericValue) const
113 {
114     if (!isNumber())
115         return false;
116     numericValue = static_cast<const NumberImp *>(this)->value();
117     return true;
118 }
119
120 double JSCell::getNumber() const
121 {
122     return isNumber() ? static_cast<const NumberImp *>(this)->value() : NaN;
123 }
124
125 bool JSCell::getString(UString &stringValue) const
126 {
127     if (!isString())
128         return false;
129     stringValue = static_cast<const StringImp *>(this)->value();
130     return true;
131 }
132
133 UString JSCell::getString() const
134 {
135     return isString() ? static_cast<const StringImp *>(this)->value() : UString();
136 }
137
138 JSObject *JSCell::getObject()
139 {
140     return isObject() ? static_cast<JSObject *>(this) : 0;
141 }
142
143 const JSObject *JSCell::getObject() const
144 {
145     return isObject() ? static_cast<const JSObject *>(this) : 0;
146 }
147
148 JSCell *jsString(const char *s)
149 {
150     return new StringImp(s ? s : "");
151 }
152
153 JSCell *jsString(const UString &s)
154 {
155     return s.isNull() ? new StringImp("") : new StringImp(s);
156 }
157
158 // This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
159 // it in a separate function to keep the normal case speedy.
160 JSValue *jsNumberCell(double d)
161 {
162     return new NumberImp(d);
163 }
164
165 } // namespace KJS