KJS

value.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 1999-2001 Harri Porten ([email protected])
4  * Copyright (C) 2001 Peter Kelly ([email protected])
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 "value.h"
25 
26 #include "error_object.h"
27 #include "nodes.h"
28 #include "operations.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <wtf/MathExtras.h>
32 
33 namespace KJS
34 {
35 
36 static const double D16 = 65536.0;
37 static const double D32 = 4294967296.0;
38 
39 void *JSCell::operator new(size_t size)
40 {
41  return Collector::allocate(size);
42 }
43 
44 bool JSCell::getUInt32(uint32_t &) const
45 {
46  return false;
47 }
48 
49 bool JSCell::getTruncatedInt32(int32_t &) const
50 {
51  return false;
52 }
53 
54 bool JSCell::getTruncatedUInt32(uint32_t &) const
55 {
56  return false;
57 }
58 
59 // ECMA 9.4
60 double JSValue::toInteger(ExecState *exec) const
61 {
62  return toInteger(this, exec);
63 }
64 
65 double JSValue::toInteger(const JSValue *value, ExecState *exec)
66 {
67  int32_t i;
68  if (getTruncatedInt32(value, i)) {
69  return i;
70  }
71  double d = toNumber(value, exec);
72  return isNaN(d) ? 0.0 : trunc(d);
73 }
74 
75 double JSValue::toIntegerPreserveNaN(ExecState *exec) const
76 {
77  return toIntegerPreserveNaN(this, exec);
78 }
79 
80 double JSValue::toIntegerPreserveNaN(const JSValue *value, ExecState *exec)
81 {
82  int32_t i;
83  if (getTruncatedInt32(value, i)) {
84  return i;
85  }
86  return trunc(toNumber(value, exec));
87 }
88 
89 int32_t JSValue::toInt32SlowCase(double d, bool &ok)
90 {
91  ok = true;
92 
93  if (d >= -D32 / 2 && d < D32 / 2) {
94  return static_cast<int32_t>(d);
95  }
96 
97  if (isNaN(d) || isInf(d)) {
98  ok = false;
99  return 0;
100  }
101 
102  double d32 = fmod(trunc(d), D32);
103  if (d32 >= D32 / 2) {
104  d32 -= D32;
105  } else if (d32 < -D32 / 2) {
106  d32 += D32;
107  }
108  return static_cast<int32_t>(d32);
109 }
110 
111 int32_t JSValue::toInt32SlowCase(const JSValue *value, ExecState *exec, bool &ok)
112 {
113  return JSValue::toInt32SlowCase(toNumber(value, exec), ok);
114 }
115 
116 uint32_t JSValue::toUInt32SlowCase(double d, bool &ok)
117 {
118  ok = true;
119 
120  if (d >= 0.0 && d < D32) {
121  return static_cast<uint32_t>(d);
122  }
123 
124  if (isNaN(d) || isInf(d)) {
125  ok = false;
126  return 0;
127  }
128 
129  double d32 = fmod(trunc(d), D32);
130  if (d32 < 0) {
131  d32 += D32;
132  }
133  return static_cast<uint32_t>(d32);
134 }
135 
136 uint32_t JSValue::toUInt32SlowCase(const JSValue *value, ExecState *exec, bool &ok)
137 {
138  return JSValue::toUInt32SlowCase(toNumber(value, exec), ok);
139 }
140 
141 uint16_t JSValue::toUInt16(ExecState *exec) const
142 {
143  return toUInt16(this, exec);
144 }
145 
146 uint16_t JSValue::toUInt16(const JSValue *value, ExecState *exec)
147 {
148  uint32_t i;
149  if (getUInt32(value, i)) {
150  return static_cast<uint16_t>(i);
151  }
152 
153  return KJS::toUInt16(const_cast<JSValue *>(value)->toNumber(value, exec));
154 }
155 
156 float JSValue::toFloat(ExecState *exec) const
157 {
158  return toFloat(this, exec);
159 }
160 
161 float JSValue::toFloat(const JSValue *value, ExecState *exec)
162 {
163  return static_cast<float>(toNumber(value, exec));
164 }
165 
166 bool JSCell::getNumber(double &numericValue) const
167 {
168  if (!isNumber()) {
169  return false;
170  }
171  numericValue = static_cast<const NumberImp *>(this)->value();
172  return true;
173 }
174 
175 double JSCell::getNumber() const
176 {
177  return isNumber() ? static_cast<const NumberImp *>(this)->value() : NaN;
178 }
179 
180 bool JSCell::getString(UString &stringValue) const
181 {
182  if (!isString()) {
183  return false;
184  }
185  stringValue = static_cast<const StringImp *>(this)->value();
186  return true;
187 }
188 
189 UString JSCell::getString() const
190 {
191  return isString() ? static_cast<const StringImp *>(this)->value() : UString();
192 }
193 
194 JSObject *JSCell::getObject()
195 {
196  return isObject() ? static_cast<JSObject *>(this) : nullptr;
197 }
198 
199 const JSObject *JSCell::getObject() const
200 {
201  return isObject() ? static_cast<const JSObject *>(this) : nullptr;
202 }
203 
204 bool JSCell::implementsCall() const
205 {
206  return false;
207 }
208 
209 JSCell *jsString()
210 {
211  return new StringImp();
212 }
213 
214 JSCell *jsString(const char *s)
215 {
216  return new StringImp(s, s ? strlen(s) : 0);
217 }
218 
219 JSCell *jsString(const char *s, int len)
220 {
221  return new StringImp(s, len);
222 }
223 
224 JSCell *jsString(const UString &s)
225 {
226  return s.isNull() ? new StringImp() : new StringImp(s);
227 }
228 
229 JSCell *jsOwnedString(const UString &s)
230 {
231  return s.isNull() ? new StringImp(UString::empty, StringImp::HasOtherOwner) : new StringImp(s, StringImp::HasOtherOwner);
232 }
233 
234 JSCell *jsString(ExecState *exec, const JSValue *value)
235 {
236  if (JSValue::isString(value)) {
237  return jsString(static_cast<const StringImp *>(value)->value());
238  }
239  return jsString(JSValue::toString(value, exec));
240 }
241 
242 // This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
243 // it in a separate function to keep the normal case speedy.
244 JSValue *jsNumberCell(double d)
245 {
246  return new NumberImp(d);
247 }
248 
249 JSValue *JSValue::getByIndex(ExecState *exec, unsigned propertyName) const
250 {
251  return getByIndex(this, exec, propertyName);
252 }
253 
254 JSValue *JSValue::getByIndex(const JSValue *value, ExecState *exec, unsigned propertyName)
255 {
256  switch (type(value)) {
257  case StringType: {
258  UString s = static_cast<const StringImp *>(value->asCell())->value();
259  if (propertyName < static_cast<unsigned>(s.size())) {
260  return jsString(s.substr(propertyName, 1));
261  }
262  // fall through
263  }
264  default: {
265  JSObject *obj = toObject(value, exec);
266  PropertySlot slot;
267  if (obj->getPropertySlot(exec, propertyName, slot)) {
268  return slot.getValue(exec, obj, propertyName);
269  }
270 
271  return jsUndefined();
272  }
273  }
274 }
275 
276 } // namespace KJS
static void * allocate(size_t s)
Register an object with the collector.
Definition: collector.cpp:331
bool isNaN(double x)
bool isInf(double x)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Jun 28 2022 03:50:52 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.