• 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
42using namespace KJS;
43
44// ----------------------------- ValueImp -------------------------------------
45
46ValueImp::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
54ValueImp::~ValueImp()
55{
56 //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
57 _flags |= VI_DESTRUCTED;
58}
59
60void ValueImp::mark()
61{
62 //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
63 _flags |= VI_MARKED;
64}
65
66bool ValueImp::marked() const
67{
68 // Simple numbers are always considered marked.
69 return SimpleNumber::is(this) || (_flags & VI_MARKED);
70}
71
72void 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
81void* ValueImp::operator new(size_t s)
82{
83 return Collector::allocate(s);
84}
85
86void ValueImp::operator delete(void*)
87{
88 // Do nothing. So far.
89}
90
91bool ValueImp::toUInt32(unsigned&) const
92{
93 return false;
94}
95
96// ECMA 9.4
97int 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
108int 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
130unsigned 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
152unsigned 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
169Type ValueImp::dispatchType() const
170{
171 if (SimpleNumber::is(this))
172 return NumberType;
173 return type();
174}
175
176Value 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
183bool ValueImp::dispatchToBoolean(ExecState *exec) const
184{
185 if (SimpleNumber::is(this))
186 return SimpleNumber::value(this);
187 return toBoolean(exec);
188}
189
190double ValueImp::dispatchToNumber(ExecState *exec) const
191{
192 if (SimpleNumber::is(this))
193 return SimpleNumber::value(this);
194 return toNumber(exec);
195}
196
197UString ValueImp::dispatchToString(ExecState *exec) const
198{
199 if (SimpleNumber::is(this))
200 return UString::from(SimpleNumber::value(this));
201 return toString(exec);
202}
203
204Object 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
211bool 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
225Value::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
240Value::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
254Value::~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
263Value& 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
285Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
286{
287}
288
289Undefined 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
299Null::Null() : Value(NullImp::staticNull)
300{
301}
302
303Null 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
313Boolean::Boolean(bool b)
314 : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
315{
316}
317
318bool Boolean::value() const
319{
320 assert(rep);
321 return ((BooleanImp*)rep)->value();
322}
323
324Boolean 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
334String::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
342UString String::value() const
343{
344 assert(rep);
345 return ((StringImp*)rep)->value();
346}
347
348String 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
358Number::Number(int i)
359 : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
360
361Number::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)
366Number::Number(double d)
367 : Value(KJS::isNaN(d) ? NumberImp::staticNaN : (SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : new NumberImp(d))) { }
368#else
369Number::Number(double d)
370 : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
371#endif
372
373Number::Number(long int l)
374 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
375
376Number::Number(long unsigned int l)
377 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
378
379Number 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
387double 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
395int Number::intValue() const
396{
397 if (SimpleNumber::is(rep))
398 return SimpleNumber::value(rep);
399 return (int)((NumberImp*)rep)->value();
400}
401
402bool Number::isNaN() const
403{
404 return rep == NumberImp::staticNaN;
405}
406
407bool Number::isInf() const
408{
409 if (SimpleNumber::is(rep))
410 return false;
411 return KJS::isInf(((NumberImp*)rep)->value());
412}
KJS::Boolean
Represents an primitive Boolean value.
Definition: value.h:316
KJS::Boolean::dynamicCast
static Boolean dynamicCast(const Value &v)
Converts a Value into an Boolean.
Definition: value.cpp:324
KJS::Collector::allocate
static void * allocate(size_t s)
Register an object with the collector.
Definition: collector.cpp:79
KJS::ExecState
Represents the current state of script execution.
Definition: interpreter.h:438
KJS::Null
Represents an primitive Null value.
Definition: value.h:294
KJS::Null::dynamicCast
static Null dynamicCast(const Value &v)
Converts a Value into an Null.
Definition: value.cpp:303
KJS::Number
Represents an primitive Number value.
Definition: value.h:367
KJS::Number::dynamicCast
static Number dynamicCast(const Value &v)
Converts a Value into an Number.
Definition: value.cpp:379
KJS::Object
Represents an Object.
Definition: object.h:81
KJS::String
Represents an primitive String value.
Definition: value.h:340
KJS::String::dynamicCast
static String dynamicCast(const Value &v)
Converts a Value into an String.
Definition: value.cpp:348
KJS::UString
Unicode string class.
Definition: ustring.h:189
KJS::UString::isNull
bool isNull() const
Definition: ustring.h:343
KJS::UString::from
static UString from(int i)
Constructs a string from an int.
Definition: ustring.cpp:340
KJS::Undefined
Represents an primitive Undefined value.
Definition: value.h:269
KJS::ValueImp
ValueImp is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects i...
Definition: value.h:78
KJS::Value
Value objects are act as wrappers ("smart pointers") around ValueImp objects and their descendents.
Definition: value.h:167
KJS::Value::isValid
bool isValid() const
Returns whether or not this is a valid value.
Definition: value.h:181
KJS::Value::type
Type type() const
Returns the type of value.
Definition: value.h:195

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