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

kjs

  • 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 "value.h"
25 #include "object.h"
26 #include "types.h"
27 #include "interpreter.h"
28 
29 #include <assert.h>
30 #include <math.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
34 
35 #include "internal.h"
36 #include "collector.h"
37 #include "operations.h"
38 #include "error_object.h"
39 #include "nodes.h"
40 #include "simple_number.h"
41 
42 using namespace KJS;
43 
44 // ----------------------------- ValueImp -------------------------------------
45 
46 ValueImp::ValueImp() :
47  refcount(0),
48  // Tell the garbage collector that this memory block corresponds to a real object now
49  _flags(VI_CREATED)
50 {
51  //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
52 }
53 
54 ValueImp::~ValueImp()
55 {
56  //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
57  _flags |= VI_DESTRUCTED;
58 }
59 
60 void ValueImp::mark()
61 {
62  //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
63  _flags |= VI_MARKED;
64 }
65 
66 bool ValueImp::marked() const
67 {
68  // Simple numbers are always considered marked.
69  return SimpleNumber::is(this) || (_flags & VI_MARKED);
70 }
71 
72 void ValueImp::setGcAllowed()
73 {
74  //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
75  // simple numbers are never seen by the collector so setting this
76  // flag is irrelevant
77  if (!SimpleNumber::is(this))
78  _flags |= VI_GCALLOWED;
79 }
80 
81 void* ValueImp::operator new(size_t s)
82 {
83  return Collector::allocate(s);
84 }
85 
86 void ValueImp::operator delete(void*)
87 {
88  // Do nothing. So far.
89 }
90 
91 bool ValueImp::toUInt32(unsigned&) const
92 {
93  return false;
94 }
95 
96 // ECMA 9.4
97 int ValueImp::toInteger(ExecState *exec) const
98 {
99  unsigned i;
100  if (dispatchToUInt32(i))
101  return static_cast<int>(i);
102  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
103  if (isInf(d))
104  return INT_MAX;
105  return static_cast<int>(d);
106 }
107 
108 int ValueImp::toInt32(ExecState *exec) const
109 {
110  unsigned i;
111  if (dispatchToUInt32(i))
112  return (int)i;
113 
114  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
115  if (isNaN(d) || isInf(d) || d == 0.0)
116  return 0;
117  double d32 = fmod(d, D32);
118 
119  //Make sure we use the positive remainder. This matters since this may be
120  //less than MIN_INT (but still < 2^32), and we don't want the cast to clamp.
121  if (d32 < 0)
122  d32 += D32;
123 
124  if (d32 >= D32 / 2.0)
125  d32 -= D32;
126 
127  return static_cast<int>(d32);
128 }
129 
130 unsigned int ValueImp::toUInt32(ExecState *exec) const
131 {
132  unsigned i;
133  if (dispatchToUInt32(i))
134  return i;
135 
136  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
137  if (isNaN(d) || isInf(d) || d == 0.0)
138  return 0;
139  double d32 = fmod(d, D32);
140 
141  if (d32 < 0)
142  d32 += D32;
143 
144  //6.3.1.4 Real floating and integer
145  // 50) The remaindering operation performed when a value of integer type is
146  // converted to unsigned type need not be performed when a value of real
147  // floating type is converted to unsigned type. Thus, the range of
148  // portable real floating values is (-1, Utype_MAX+1).
149  return static_cast<unsigned int>(d32);
150 }
151 
152 unsigned short ValueImp::toUInt16(ExecState *exec) const
153 {
154  unsigned i;
155  if (dispatchToUInt32(i))
156  return (unsigned short)i;
157 
158  double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
159  double d16 = fmod(d, D16);
160 
161  // look at toUInt32 to see why this is necesary
162  int t_int = static_cast<int>(d16);
163  return static_cast<unsigned short>(t_int);
164 }
165 
166 // Dispatchers for virtual functions, to special-case simple numbers which
167 // won't be real pointers.
168 
169 Type ValueImp::dispatchType() const
170 {
171  if (SimpleNumber::is(this))
172  return NumberType;
173  return type();
174 }
175 
176 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
177 {
178  if (SimpleNumber::is(this))
179  return Value(const_cast<ValueImp *>(this));
180  return toPrimitive(exec, preferredType);
181 }
182 
183 bool ValueImp::dispatchToBoolean(ExecState *exec) const
184 {
185  if (SimpleNumber::is(this))
186  return SimpleNumber::value(this);
187  return toBoolean(exec);
188 }
189 
190 double ValueImp::dispatchToNumber(ExecState *exec) const
191 {
192  if (SimpleNumber::is(this))
193  return SimpleNumber::value(this);
194  return toNumber(exec);
195 }
196 
197 UString ValueImp::dispatchToString(ExecState *exec) const
198 {
199  if (SimpleNumber::is(this))
200  return UString::from(SimpleNumber::value(this));
201  return toString(exec);
202 }
203 
204 Object ValueImp::dispatchToObject(ExecState *exec) const
205 {
206  if (SimpleNumber::is(this))
207  return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
208  return toObject(exec);
209 }
210 
211 bool ValueImp::dispatchToUInt32(unsigned& result) const
212 {
213  if (SimpleNumber::is(this)) {
214  long i = SimpleNumber::value(this);
215  if (i < 0)
216  return false;
217  result = (unsigned)i;
218  return true;
219  }
220  return toUInt32(result);
221 }
222 
223 // ------------------------------ Value ----------------------------------------
224 
225 Value::Value(ValueImp *v)
226 {
227  rep = v;
228 #ifdef DEBUG_COLLECTOR
229  assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
230  assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
231 #endif
232  if (v)
233  {
234  v->ref();
235  //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
236  v->setGcAllowed();
237  }
238 }
239 
240 Value::Value(const Value &v)
241 {
242  rep = v.imp();
243 #ifdef DEBUG_COLLECTOR
244  assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
245  assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
246 #endif
247  if (rep)
248  {
249  rep->ref();
250  //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
251  }
252 }
253 
254 Value::~Value()
255 {
256  if (rep)
257  {
258  rep->deref();
259  //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
260  }
261 }
262 
263 Value& Value::operator=(const Value &v)
264 {
265  ValueImp *tmpRep = v.imp();
266 
267  //Avoid the destruction of the object underneath us by
268  //incrementing the reference on it first
269  if (tmpRep) {
270  tmpRep->ref();
271  //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, tmpRep, tmpRep->refcount);
272  }
273 
274  if (rep) {
275  rep->deref();
276  //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
277  }
278  rep = tmpRep;
279 
280  return *this;
281 }
282 
283 // ------------------------------ Undefined ------------------------------------
284 
285 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
286 {
287 }
288 
289 Undefined Undefined::dynamicCast(const Value &v)
290 {
291  if (!v.isValid() || v.type() != UndefinedType)
292  return Undefined(0);
293 
294  return Undefined();
295 }
296 
297 // ------------------------------ Null -----------------------------------------
298 
299 Null::Null() : Value(NullImp::staticNull)
300 {
301 }
302 
303 Null Null::dynamicCast(const Value &v)
304 {
305  if (!v.isValid() || v.type() != NullType)
306  return Null(0);
307 
308  return Null();
309 }
310 
311 // ------------------------------ Boolean --------------------------------------
312 
313 Boolean::Boolean(bool b)
314  : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
315 {
316 }
317 
318 bool Boolean::value() const
319 {
320  assert(rep);
321  return ((BooleanImp*)rep)->value();
322 }
323 
324 Boolean Boolean::dynamicCast(const Value &v)
325 {
326  if (!v.isValid() || v.type() != BooleanType)
327  return static_cast<BooleanImp*>(0);
328 
329  return static_cast<BooleanImp*>(v.imp());
330 }
331 
332 // ------------------------------ String ---------------------------------------
333 
334 String::String(const UString &s) : Value(new StringImp(s))
335 {
336 #ifndef NDEBUG
337  if (s.isNull())
338  fprintf(stderr, "WARNING: KJS::String constructed from null string\n");
339 #endif
340 }
341 
342 UString String::value() const
343 {
344  assert(rep);
345  return ((StringImp*)rep)->value();
346 }
347 
348 String String::dynamicCast(const Value &v)
349 {
350  if (!v.isValid() || v.type() != StringType)
351  return String(0);
352 
353  return String(static_cast<StringImp*>(v.imp()));
354 }
355 
356 // ------------------------------ Number ---------------------------------------
357 
358 Number::Number(int i)
359  : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
360 
361 Number::Number(unsigned int u)
362  : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
363 
364 // check for NaN first if we werent't compiled with -mieee on Alpha
365 #if defined(__alpha) && !defined(_IEEE_FP)
366 Number::Number(double d)
367  : Value(KJS::isNaN(d) ? NumberImp::staticNaN : (SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : new NumberImp(d))) { }
368 #else
369 Number::Number(double d)
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::Value
Value objects are act as wrappers ("smart pointers") around ValueImp objects and their descendents...
Definition: value.h:167
KJS::Value::type
Type type() const
Returns the type of value.
Definition: value.h:195
KJS::UString::from
static UString from(int i)
Constructs a string from an int.
Definition: ustring.cpp:340
KJS::Undefined::dynamicCast
static Undefined dynamicCast(const Value &v)
Converts a Value into an Undefined.
Definition: value.cpp:289
KJS::Number
Represents an primitive Number value.
Definition: value.h:367
KJS::Null
Represents an primitive Null value.
Definition: value.h:294
KJS::Object
Represents an Object.
Definition: object.h:81
KJS::Undefined
Represents an primitive Undefined value.
Definition: value.h:269
KJS::Null::dynamicCast
static Null dynamicCast(const Value &v)
Converts a Value into an Null.
Definition: value.cpp:303
KJS::UString
Unicode string class.
Definition: ustring.h:189
KJS::String
Represents an primitive String value.
Definition: value.h:340
KJS::UString::isNull
bool isNull() const
Definition: ustring.h:343
KJS
Definition: array_instance.h:27
KJS::ValueImp
ValueImp is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects i...
Definition: value.h:78
KJS::Boolean::dynamicCast
static Boolean dynamicCast(const Value &v)
Converts a Value into an Boolean.
Definition: value.cpp:324
KJS::Boolean
Represents an primitive Boolean value.
Definition: value.h:316
KJS::Number::dynamicCast
static Number dynamicCast(const Value &v)
Converts a Value into an Number.
Definition: value.cpp:379
KJS::Collector::allocate
static void * allocate(size_t s)
Register an object with the collector.
Definition: collector.cpp:79
KJS::String::dynamicCast
static String dynamicCast(const Value &v)
Converts a Value into an String.
Definition: value.cpp:348
KJS::Value::isValid
bool isValid() const
Returns whether or not this is a valid value.
Definition: value.h:181
KJS::ExecState
Represents the current state of script execution.
Definition: interpreter.h:438

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
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kjs by doxygen 1.8.8
This website is maintained by Timothy Pearson.