webengine/osswebengine/JavaScriptCore/kjs/value.h
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     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-2005 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 #ifndef KJS_VALUE_H
       
    25 #define KJS_VALUE_H
       
    26 
       
    27 #include "JSImmediate.h"
       
    28 #include "collector.h"
       
    29 #include "ustring.h"
       
    30 #include <stddef.h> // for size_t
       
    31 
       
    32 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
       
    33 
       
    34 // Uncomment this to enable very verbose output from KJS
       
    35 //#define KJS_VERBOSE
       
    36 // Uncomment this to debug memory allocation and garbage collection
       
    37 //#define KJS_DEBUG_MEM
       
    38 
       
    39 #endif
       
    40 
       
    41 namespace KJS {
       
    42 
       
    43 class ExecState;
       
    44 class JSObject;
       
    45 class JSCell;
       
    46 
       
    47 struct ClassInfo;
       
    48 
       
    49 /**
       
    50  * JSValue is the base type for all primitives (Undefined, Null, Boolean,
       
    51  * String, Number) and objects in ECMAScript.
       
    52  *
       
    53  * Note: you should never inherit from JSValue as it is for primitive types
       
    54  * only (all of which are provided internally by KJS). Instead, inherit from
       
    55  * JSObject.
       
    56  */
       
    57 class JSValue : Noncopyable {
       
    58     friend class JSCell; // so it can derive from this class
       
    59     friend class Collector; // so it can call asCell()
       
    60 
       
    61 private:
       
    62     JSValue();
       
    63     virtual ~JSValue();
       
    64 
       
    65 public:
       
    66     // Querying the type.
       
    67     JSType type() const;
       
    68     bool isUndefined() const;
       
    69     bool isNull() const;
       
    70     bool isUndefinedOrNull() const;
       
    71     bool isBoolean() const;
       
    72     bool isNumber() const;
       
    73     bool isString() const;
       
    74     bool isObject() const;
       
    75     bool isObject(const ClassInfo *) const;
       
    76 
       
    77     // Extracting the value.
       
    78     bool getBoolean(bool&) const;
       
    79     bool getBoolean() const; // false if not a boolean
       
    80     IMPORT bool getNumber(double&) const;
       
    81     double getNumber() const; // NaN if not a number
       
    82     bool getString(UString&) const;
       
    83     UString getString() const; // null string if not a string
       
    84     JSObject *getObject(); // NULL if not an object
       
    85     const JSObject *getObject() const; // NULL if not an object
       
    86 
       
    87     // Extracting integer values.
       
    88     bool getUInt32(uint32_t&) const;
       
    89 
       
    90     // Basic conversions.
       
    91     JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
       
    92     bool toBoolean(ExecState *exec) const;
       
    93     double toNumber(ExecState *exec) const;
       
    94     UString toString(ExecState *exec) const;
       
    95     JSObject *toObject(ExecState *exec) const;
       
    96 
       
    97     // Integer conversions.
       
    98     double toInteger(ExecState*) const;
       
    99     IMPORT int32_t toInt32(ExecState*) const;
       
   100     IMPORT int32_t toInt32(ExecState*, bool& ok) const;
       
   101     IMPORT uint32_t toUInt32(ExecState*) const;
       
   102     uint32_t toUInt32(ExecState*, bool& ok) const;
       
   103     uint16_t toUInt16(ExecState*) const;
       
   104 
       
   105     // Floating point conversions.
       
   106     IMPORT float toFloat(ExecState*) const;
       
   107 
       
   108     // Garbage collection.
       
   109     void mark();
       
   110     bool marked() const;
       
   111 
       
   112 private:
       
   113     // Implementation details.
       
   114     JSCell *asCell();
       
   115     const JSCell *asCell() const;
       
   116 
       
   117     // Give a compile time error if we try to copy one of these.
       
   118     JSValue(const JSValue&);
       
   119     JSValue& operator=(const JSValue&);
       
   120 };
       
   121 
       
   122 class JSCell : public JSValue {
       
   123     friend class Collector;
       
   124     friend class NumberImp;
       
   125     friend class StringImp;
       
   126     friend class JSObject;
       
   127     friend class GetterSetterImp;
       
   128 private:
       
   129     JSCell();
       
   130     virtual ~JSCell();
       
   131 public:
       
   132     // Querying the type.
       
   133     virtual JSType type() const = 0;
       
   134     bool isNumber() const;
       
   135     bool isString() const;
       
   136     bool isObject() const;
       
   137     bool isObject(const ClassInfo *) const;
       
   138 
       
   139     // Extracting the value.
       
   140     IMPORT bool getNumber(double&) const;
       
   141     IMPORT double getNumber() const; // NaN if not a number
       
   142     IMPORT bool getString(UString&) const;
       
   143     UString getString() const; // null string if not a string
       
   144     IMPORT JSObject *getObject(); // NULL if not an object
       
   145     const JSObject *getObject() const; // NULL if not an object
       
   146 
       
   147     // Extracting integer values.
       
   148     IMPORT virtual bool getUInt32(uint32_t&) const;
       
   149 
       
   150     // Basic conversions.
       
   151     virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
       
   152     virtual bool toBoolean(ExecState *exec) const = 0;
       
   153     virtual double toNumber(ExecState *exec) const = 0;
       
   154     virtual UString toString(ExecState *exec) const = 0;
       
   155     virtual JSObject *toObject(ExecState *exec) const = 0;
       
   156 
       
   157     // Garbage collection.
       
   158     IMPORT void *operator new(size_t);
       
   159     virtual void mark();
       
   160     bool marked() const;
       
   161 };
       
   162 
       
   163 IMPORT JSValue *jsNumberCell(double);
       
   164 
       
   165 IMPORT JSCell *jsString(const UString&); // returns empty string if passed null string
       
   166 IMPORT JSCell *jsString(const char* = ""); // returns empty string if passed 0
       
   167 
       
   168 // should be used for strings that are owned by an object that will
       
   169 // likely outlive the JSValue this makes, such as the parse tree or a
       
   170 // DOM object that contains a UString
       
   171 IMPORT JSCell *jsOwnedString(const UString&); 
       
   172 
       
   173 extern const double NaN;
       
   174 extern const double Inf;
       
   175 
       
   176 
       
   177 inline JSValue *jsUndefined()
       
   178 {
       
   179     return JSImmediate::undefinedImmediate();
       
   180 }
       
   181 
       
   182 inline JSValue *jsNull()
       
   183 {
       
   184     return JSImmediate::nullImmediate();
       
   185 }
       
   186 
       
   187 inline JSValue *jsNaN()
       
   188 {
       
   189     return JSImmediate::NaNImmediate();
       
   190 }
       
   191 
       
   192 inline JSValue *jsBoolean(bool b)
       
   193 {
       
   194     return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
       
   195 }
       
   196 
       
   197 inline JSValue *jsNumber(double d)
       
   198 {
       
   199     JSValue *v = JSImmediate::fromDouble(d);
       
   200     return v ? v : jsNumberCell(d);
       
   201 }
       
   202 
       
   203 inline JSValue::JSValue()
       
   204 {
       
   205 }
       
   206 
       
   207 inline JSValue::~JSValue()
       
   208 {
       
   209 }
       
   210 
       
   211 inline JSCell::JSCell()
       
   212 {
       
   213 }
       
   214 
       
   215 inline JSCell::~JSCell()
       
   216 {
       
   217 }
       
   218 
       
   219 inline bool JSCell::isNumber() const
       
   220 {
       
   221     return type() == NumberType;
       
   222 }
       
   223 
       
   224 inline bool JSCell::isString() const
       
   225 {
       
   226     return type() == StringType;
       
   227 }
       
   228 
       
   229 inline bool JSCell::isObject() const
       
   230 {
       
   231     return type() == ObjectType;
       
   232 }
       
   233 
       
   234 inline bool JSCell::marked() const
       
   235 {
       
   236     return Collector::isCellMarked(this);
       
   237 }
       
   238 
       
   239 inline void JSCell::mark()
       
   240 {
       
   241     return Collector::markCell(this);
       
   242 }
       
   243 
       
   244 inline JSCell *JSValue::asCell()
       
   245 {
       
   246     ASSERT(!JSImmediate::isImmediate(this));
       
   247     return static_cast<JSCell *>(this);
       
   248 }
       
   249 
       
   250 inline const JSCell *JSValue::asCell() const
       
   251 {
       
   252     ASSERT(!JSImmediate::isImmediate(this));
       
   253     return static_cast<const JSCell *>(this);
       
   254 }
       
   255 
       
   256 inline bool JSValue::isUndefined() const
       
   257 {
       
   258     return this == jsUndefined();
       
   259 }
       
   260 
       
   261 inline bool JSValue::isNull() const
       
   262 {
       
   263     return this == jsNull();
       
   264 }
       
   265 
       
   266 inline bool JSValue::isUndefinedOrNull() const
       
   267 {
       
   268     return JSImmediate::isUndefinedOrNull(this);
       
   269 }
       
   270 
       
   271 inline bool JSValue::isBoolean() const
       
   272 {
       
   273     return JSImmediate::isBoolean(this);
       
   274 }
       
   275 
       
   276 inline bool JSValue::isNumber() const
       
   277 {
       
   278     return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && asCell()->isNumber();
       
   279 }
       
   280 
       
   281 inline bool JSValue::isString() const
       
   282 {
       
   283     return !JSImmediate::isImmediate(this) && asCell()->isString();
       
   284 }
       
   285 
       
   286 inline bool JSValue::isObject() const
       
   287 {
       
   288     return !JSImmediate::isImmediate(this) && asCell()->isObject();
       
   289 }
       
   290 
       
   291 inline bool JSValue::getBoolean(bool& v) const
       
   292 {
       
   293     if (JSImmediate::isBoolean(this)) {
       
   294         v = JSImmediate::toBoolean(this);
       
   295         return true;
       
   296     }
       
   297     
       
   298     return false;
       
   299 }
       
   300 
       
   301 inline bool JSValue::getBoolean() const
       
   302 {
       
   303     return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
       
   304 }
       
   305 
       
   306 inline bool JSValue::getNumber(double& v) const
       
   307 {
       
   308     if (JSImmediate::isImmediate(this)) {
       
   309         v = JSImmediate::toDouble(this);
       
   310         return true;
       
   311     }
       
   312     return asCell()->getNumber(v);
       
   313 }
       
   314 
       
   315 inline double JSValue::getNumber() const
       
   316 {
       
   317     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->getNumber();
       
   318 }
       
   319 
       
   320 inline bool JSValue::getString(UString& s) const
       
   321 {
       
   322     return !JSImmediate::isImmediate(this) && asCell()->getString(s);
       
   323 }
       
   324 
       
   325 inline UString JSValue::getString() const
       
   326 {
       
   327     return JSImmediate::isImmediate(this) ? UString() : asCell()->getString();
       
   328 }
       
   329 
       
   330 inline JSObject *JSValue::getObject()
       
   331 {
       
   332     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
       
   333 }
       
   334 
       
   335 inline const JSObject *JSValue::getObject() const
       
   336 {
       
   337     return JSImmediate::isImmediate(this) ? 0 : asCell()->getObject();
       
   338 }
       
   339 
       
   340 inline bool JSValue::getUInt32(uint32_t& v) const
       
   341 {
       
   342     if (JSImmediate::isImmediate(this)) {
       
   343         double d = JSImmediate::toDouble(this);
       
   344         if (!(d >= 0) || d > 0xFFFFFFFFUL) // true for NaN
       
   345             return false;
       
   346         v = static_cast<uint32_t>(d);
       
   347         return JSImmediate::isNumber(this);
       
   348     }
       
   349     return asCell()->getUInt32(v);
       
   350 }
       
   351 
       
   352 inline void JSValue::mark()
       
   353 {
       
   354     ASSERT(!JSImmediate::isImmediate(this)); // callers should check !marked() before calling mark()
       
   355     asCell()->mark();
       
   356 }
       
   357 
       
   358 inline bool JSValue::marked() const
       
   359 {
       
   360     return JSImmediate::isImmediate(this) || asCell()->marked();
       
   361 }
       
   362 
       
   363 inline JSType JSValue::type() const
       
   364 {
       
   365     return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : asCell()->type();
       
   366 }
       
   367 
       
   368 inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
       
   369 {
       
   370     return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : asCell()->toPrimitive(exec, preferredType);
       
   371 }
       
   372 
       
   373 inline bool JSValue::toBoolean(ExecState *exec) const
       
   374 {
       
   375     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
       
   376 }
       
   377 
       
   378 inline double JSValue::toNumber(ExecState *exec) const
       
   379 {
       
   380     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : asCell()->toNumber(exec);
       
   381 }
       
   382 
       
   383 inline UString JSValue::toString(ExecState *exec) const
       
   384 {
       
   385     return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : asCell()->toString(exec);
       
   386 }
       
   387 
       
   388 inline JSObject* JSValue::toObject(ExecState* exec) const
       
   389 {
       
   390     return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : asCell()->toObject(exec);
       
   391 }
       
   392 
       
   393 } // namespace
       
   394 
       
   395 #endif // KJS_VALUE_H