• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kjs
 

kjs

  • kjs
value.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  * This file is part of the KDE libraries
4  * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
5  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
6  * Copyright (C) 2003 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB. If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "value.h"
26 #include "object.h"
27 #include "types.h"
28 #include "interpreter.h"
29 
30 #include <assert.h>
31 #include <math.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
35 
36 #include "internal.h"
37 #include "collector.h"
38 #include "operations.h"
39 #include "error_object.h"
40 #include "nodes.h"
41 #include "simple_number.h"
42 
43 using namespace KJS;
44 
45 // ----------------------------- ValueImp -------------------------------------
46 
47 ValueImp::ValueImp() :
48  refcount(0),
49  // Tell the garbage collector that this memory block corresponds to a real object now
50  _flags(VI_CREATED)
51 {
52  //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
53 }
54 
55 ValueImp::~ValueImp()
56 {
57  //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
58  _flags |= VI_DESTRUCTED;
59 }
60 
61 void ValueImp::mark()
62 {
63  //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
64  _flags |= VI_MARKED;
65 }
66 
67 bool ValueImp::marked() const
68 {
69  // Simple numbers are always considered marked.
70  return SimpleNumber::is(this) || (_flags & VI_MARKED);
71 }
72 
73 void ValueImp::setGcAllowed()
74 {
75  //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
76  // simple numbers are never seen by the collector so setting this
77  // flag is irrelevant
78  if (!SimpleNumber::is(this))
79  _flags |= VI_GCALLOWED;
80 }
81 
82 void* ValueImp::operator new(size_t s)
83 {
84  return Collector::allocate(s);
85 }
86 
87 void ValueImp::operator delete(void*)
88 {
89  // Do nothing. So far.
90 }
91 
92 bool ValueImp::toUInt32(unsigned&) const
93 {
94  return false;
95 }
96 
97 // ECMA 9.4
98 int ValueImp::toInteger(ExecState *exec) const
99 {
100  unsigned i;
101  if (dispatchToUInt32(i))
102  return static_cast<int>(i);
103  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
104  if (isInf(d))
105  return INT_MAX;
106  return static_cast<int>(d);
107 }
108 
109 int ValueImp::toInt32(ExecState *exec) const
110 {
111  unsigned i;
112  if (dispatchToUInt32(i))
113  return (int)i;
114 
115  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
116  if (isNaN(d) || isInf(d) || d == 0.0)
117  return 0;
118  double d32 = fmod(d, D32);
119 
120  //Make sure we use the positive remainder. This matters since this may be
121  //less than MIN_INT (but still < 2^32), and we don't want the cast to clamp.
122  if (d32 < 0)
123  d32 += D32;
124 
125  if (d32 >= D32 / 2.0)
126  d32 -= D32;
127 
128  return static_cast<int>(d32);
129 }
130 
131 unsigned int ValueImp::toUInt32(ExecState *exec) const
132 {
133  unsigned i;
134  if (dispatchToUInt32(i))
135  return i;
136 
137  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
138  if (isNaN(d) || isInf(d) || d == 0.0)
139  return 0;
140  double d32 = fmod(d, D32);
141 
142  if (d32 < 0)
143  d32 += D32;
144 
145  //6.3.1.4 Real floating and integer
146  // 50) The remaindering operation performed when a value of integer type is
147  // converted to unsigned type need not be performed when a value of real
148  // floating type is converted to unsigned type. Thus, the range of
149  // portable real floating values is (-1, Utype_MAX+1).
150  return static_cast<unsigned int>(d32);
151 }
152 
153 unsigned short ValueImp::toUInt16(ExecState *exec) const
154 {
155  unsigned i;
156  if (dispatchToUInt32(i))
157  return (unsigned short)i;
158 
159  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
160  double d16 = fmod(d, D16);
161 
162  // look at toUInt32 to see why this is necesary
163  int t_int = static_cast<int>(d16);
164  return static_cast<unsigned short>(t_int);
165 }
166 
167 // Dispatchers for virtual functions, to special-case simple numbers which
168 // won't be real pointers.
169 
170 Type ValueImp::dispatchType() const
171 {
172  if (SimpleNumber::is(this))
173  return NumberType;
174  return type();
175 }
176 
177 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
178 {
179  if (SimpleNumber::is(this))
180  return Value(const_cast<ValueImp *>(this));
181  return toPrimitive(exec, preferredType);
182 }
183 
184 bool ValueImp::dispatchToBoolean(ExecState *exec) const
185 {
186  if (SimpleNumber::is(this))
187  return SimpleNumber::value(this);
188  return toBoolean(exec);
189 }
190 
191 double ValueImp::dispatchToNumber(ExecState *exec) const
192 {
193  if (SimpleNumber::is(this))
194  return SimpleNumber::value(this);
195  return toNumber(exec);
196 }
197 
198 UString ValueImp::dispatchToString(ExecState *exec) const
199 {
200  if (SimpleNumber::is(this))
201  return UString::from(SimpleNumber::value(this));
202  return toString(exec);
203 }
204 
205 Object ValueImp::dispatchToObject(ExecState *exec) const
206 {
207  if (SimpleNumber::is(this))
208  return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
209  return toObject(exec);
210 }
211 
212 bool ValueImp::dispatchToUInt32(unsigned& result) const
213 {
214  if (SimpleNumber::is(this)) {
215  long i = SimpleNumber::value(this);
216  if (i < 0)
217  return false;
218  result = (unsigned)i;
219  return true;
220  }
221  return toUInt32(result);
222 }
223 
224 // ------------------------------ Value ----------------------------------------
225 
226 Value::Value(ValueImp *v)
227 {
228  rep = v;
229 #ifdef DEBUG_COLLECTOR
230  assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
231  assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
232 #endif
233  if (v)
234  {
235  v->ref();
236  //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
237  v->setGcAllowed();
238  }
239 }
240 
241 Value::Value(const Value &v)
242 {
243  rep = v.imp();
244 #ifdef DEBUG_COLLECTOR
245  assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
246  assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
247 #endif
248  if (rep)
249  {
250  rep->ref();
251  //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
252  }
253 }
254 
255 Value::~Value()
256 {
257  if (rep)
258  {
259  rep->deref();
260  //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
261  }
262 }
263 
264 Value& Value::operator=(const Value &v)
265 {
266  ValueImp *tmpRep = v.imp();
267 
268  //Avoid the destruction of the object underneath us by
269  //incrementing the reference on it first
270  if (tmpRep) {
271  tmpRep->ref();
272  //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, tmpRep, tmpRep->refcount);
273  }
274 
275  if (rep) {
276  rep->deref();
277  //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
278  }
279  rep = tmpRep;
280 
281  return *this;
282 }
283 
284 // ------------------------------ Undefined ------------------------------------
285 
286 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
287 {
288 }
289 
290 Undefined Undefined::dynamicCast(const Value &v)
291 {
292  if (!v.isValid() || v.type() != UndefinedType)
293  return Undefined(0);
294 
295  return Undefined();
296 }
297 
298 // ------------------------------ Null -----------------------------------------
299 
300 Null::Null() : Value(NullImp::staticNull)
301 {
302 }
303 
304 Null Null::dynamicCast(const Value &v)
305 {
306  if (!v.isValid() || v.type() != NullType)
307  return Null(0);
308 
309  return Null();
310 }
311 
312 // ------------------------------ Boolean --------------------------------------
313 
314 Boolean::Boolean(bool b)
315  : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
316 {
317 }
318 
319 bool Boolean::value() const
320 {
321  assert(rep);
322  return ((BooleanImp*)rep)->value();
323 }
324 
325 Boolean Boolean::dynamicCast(const Value &v)
326 {
327  if (!v.isValid() || v.type() != BooleanType)
328  return static_cast<BooleanImp*>(0);
329 
330  return static_cast<BooleanImp*>(v.imp());
331 }
332 
333 // ------------------------------ String ---------------------------------------
334 
335 String::String(const UString &s) : Value(new StringImp(s))
336 {
337 #ifndef NDEBUG
338  if (s.isNull())
339  fprintf(stderr, "WARNING: KJS::String constructed from null string\n");
340 #endif
341 }
342 
343 UString String::value() const
344 {
345  assert(rep);
346  return ((StringImp*)rep)->value();
347 }
348 
349 String String::dynamicCast(const Value &v)
350 {
351  if (!v.isValid() || v.type() != StringType)
352  return String(0);
353 
354  return String(static_cast<StringImp*>(v.imp()));
355 }
356 
357 // ------------------------------ Number ---------------------------------------
358 
359 Number::Number(int i)
360  : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
361 
362 Number::Number(unsigned int u)
363  : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
364 
365 Number::Number(double d)
366 #if defined(__alpha) && !defined(_IEEE_FP)
367  // check for NaN first if we werent't compiled with -mieee on Alpha
368  : Value(KJS::isNaN(d) ? NumberImp::staticNaN : (SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : new NumberImp(d))) { }
369 #else
370  : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
371 #endif
372 
373 Number::Number(long int l)
374  : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
375 
376 Number::Number(long unsigned int l)
377  : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
378 
379 Number Number::dynamicCast(const Value &v)
380 {
381  if (!v.isValid() || v.type() != NumberType)
382  return Number((NumberImp*)0);
383 
384  return Number(static_cast<NumberImp*>(v.imp()));
385 }
386 
387 double Number::value() const
388 {
389  if (SimpleNumber::is(rep))
390  return (double)SimpleNumber::value(rep);
391  assert(rep);
392  return ((NumberImp*)rep)->value();
393 }
394 
395 int Number::intValue() const
396 {
397  if (SimpleNumber::is(rep))
398  return SimpleNumber::value(rep);
399  return (int)((NumberImp*)rep)->value();
400 }
401 
402 bool Number::isNaN() const
403 {
404  return rep == NumberImp::staticNaN;
405 }
406 
407 bool Number::isInf() const
408 {
409  if (SimpleNumber::is(rep))
410  return false;
411  return KJS::isInf(((NumberImp*)rep)->value());
412 }

kjs

Skip menu "kjs"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kjs

Skip menu "kjs"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kjs by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |