#ifndef KJS_VALUE_H
#define KJS_VALUE_H
#include "JSImmediate.h"
#include "ustring.h"
#include <stddef.h> // for size_t
#ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
#endif
namespace KJS {
class ClassInfo;
class ExecState;
class JSObject;
class JSCell;
class JSValue {
friend class JSCell; friend class Collector;
private:
JSValue();
virtual ~JSValue();
public:
JSType type() const;
bool isUndefined() const;
bool isNull() const;
bool isUndefinedOrNull() const;
bool isBoolean() const;
bool isNumber() const;
bool isString() const;
bool isObject() const;
bool isObject(const ClassInfo *) const;
bool getBoolean(bool&) const;
bool getBoolean() const; bool getNumber(double&) const;
double getNumber() const; bool getString(UString&) const;
UString getString() const; JSObject *getObject(); const JSObject *getObject() const;
bool getUInt32(uint32_t&) const;
JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
bool toBoolean(ExecState *exec) const;
double toNumber(ExecState *exec) const;
UString toString(ExecState *exec) const;
JSObject *toObject(ExecState *exec) const;
double toInteger(ExecState *exec) const;
int32_t toInt32(ExecState*) const;
int32_t toInt32(ExecState*, bool& ok) const;
uint32_t toUInt32(ExecState *exec) const;
uint16_t toUInt16(ExecState *exec) const;
void mark();
bool marked() const;
private:
JSCell *downcast();
const JSCell *downcast() const;
inline int32_t toInt32Inline(ExecState*, bool& ok) const;
JSValue(const JSValue&);
JSValue& operator=(const JSValue&);
};
class JSCell : public JSValue {
friend class Collector;
friend class NumberImp;
friend class StringImp;
friend class JSObject;
friend class GetterSetterImp;
private:
explicit JSCell(bool destructorIsThreadSafe = true);
virtual ~JSCell();
public:
virtual JSType type() const = 0;
bool isNumber() const;
bool isString() const;
bool isObject() const;
bool isObject(const ClassInfo *) const;
bool getNumber(double&) const;
double getNumber() const; bool getString(UString&) const;
UString getString() const; JSObject *getObject(); const JSObject *getObject() const;
virtual bool getUInt32(uint32_t&) const;
virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const = 0;
virtual bool toBoolean(ExecState *exec) const = 0;
virtual double toNumber(ExecState *exec) const = 0;
virtual UString toString(ExecState *exec) const = 0;
virtual JSObject *toObject(ExecState *exec) const = 0;
void *operator new(size_t);
virtual void mark();
bool marked() const;
private:
bool m_destructorIsThreadSafe : 1;
bool m_marked : 1;
};
JSValue *jsNumberCell(double);
JSCell *jsString(const UString &); JSCell *jsString(const char * = "");
extern const double NaN;
extern const double Inf;
inline JSValue *jsUndefined()
{
return JSImmediate::undefinedImmediate();
}
inline JSValue *jsNull()
{
return JSImmediate::nullImmediate();
}
inline JSValue *jsNaN()
{
return JSImmediate::NaNImmediate();
}
inline JSValue *jsBoolean(bool b)
{
return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
}
inline JSValue *jsNumber(double d)
{
JSValue *v = JSImmediate::fromDouble(d);
return v ? v : jsNumberCell(d);
}
inline JSValue::JSValue()
{
}
inline JSValue::~JSValue()
{
}
inline JSCell::JSCell(bool destructorIsThreadSafe)
: m_destructorIsThreadSafe(destructorIsThreadSafe)
, m_marked(false)
{
}
inline JSCell::~JSCell()
{
}
inline bool JSCell::isNumber() const
{
return type() == NumberType;
}
inline bool JSCell::isString() const
{
return type() == StringType;
}
inline bool JSCell::isObject() const
{
return type() == ObjectType;
}
inline bool JSCell::marked() const
{
return m_marked;
}
inline void JSCell::mark()
{
m_marked = true;
}
inline JSCell *JSValue::downcast()
{
ASSERT(!JSImmediate::isImmediate(this));
return static_cast<JSCell *>(this);
}
inline const JSCell *JSValue::downcast() const
{
ASSERT(!JSImmediate::isImmediate(this));
return static_cast<const JSCell *>(this);
}
inline bool JSValue::isUndefined() const
{
return this == jsUndefined();
}
inline bool JSValue::isNull() const
{
return this == jsNull();
}
inline bool JSValue::isUndefinedOrNull() const
{
return JSImmediate::isUndefinedOrNull(this);
}
inline bool JSValue::isBoolean() const
{
return JSImmediate::isBoolean(this);
}
inline bool JSValue::isNumber() const
{
return JSImmediate::isNumber(this) || !JSImmediate::isImmediate(this) && downcast()->isNumber();
}
inline bool JSValue::isString() const
{
return !JSImmediate::isImmediate(this) && downcast()->isString();
}
inline bool JSValue::isObject() const
{
return !JSImmediate::isImmediate(this) && downcast()->isObject();
}
inline bool JSValue::getBoolean(bool& v) const
{
if (JSImmediate::isBoolean(this)) {
v = JSImmediate::toBoolean(this);
return true;
}
return false;
}
inline bool JSValue::getBoolean() const
{
return JSImmediate::isBoolean(this) ? JSImmediate::toBoolean(this) : false;
}
inline bool JSValue::getNumber(double& v) const
{
if (JSImmediate::isImmediate(this)) {
v = JSImmediate::toDouble(this);
return true;
}
return downcast()->getNumber(v);
}
inline double JSValue::getNumber() const
{
return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->getNumber();
}
inline bool JSValue::getString(UString& s) const
{
return !JSImmediate::isImmediate(this) && downcast()->getString(s);
}
inline UString JSValue::getString() const
{
return JSImmediate::isImmediate(this) ? UString() : downcast()->getString();
}
inline JSObject *JSValue::getObject()
{
return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
}
inline const JSObject *JSValue::getObject() const
{
return JSImmediate::isImmediate(this) ? 0 : downcast()->getObject();
}
inline bool JSValue::getUInt32(uint32_t& v) const
{
if (JSImmediate::isImmediate(this)) {
double d = JSImmediate::toDouble(this);
if (!(d >= 0) || d > 0xFFFFFFFFUL) return false;
v = static_cast<uint32_t>(d);
return JSImmediate::isNumber(this);
}
return downcast()->getUInt32(v);
}
inline void JSValue::mark()
{
ASSERT(!JSImmediate::isImmediate(this)); downcast()->mark();
}
inline bool JSValue::marked() const
{
return JSImmediate::isImmediate(this) || downcast()->marked();
}
inline JSType JSValue::type() const
{
return JSImmediate::isImmediate(this) ? JSImmediate::type(this) : downcast()->type();
}
inline JSValue *JSValue::toPrimitive(ExecState *exec, JSType preferredType) const
{
return JSImmediate::isImmediate(this) ? const_cast<JSValue *>(this) : downcast()->toPrimitive(exec, preferredType);
}
inline bool JSValue::toBoolean(ExecState *exec) const
{
return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : downcast()->toBoolean(exec);
}
inline double JSValue::toNumber(ExecState *exec) const
{
return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->toNumber(exec);
}
inline UString JSValue::toString(ExecState *exec) const
{
return JSImmediate::isImmediate(this) ? JSImmediate::toString(this) : downcast()->toString(exec);
}
inline JSObject* JSValue::toObject(ExecState* exec) const
{
return JSImmediate::isImmediate(this) ? JSImmediate::toObject(this, exec) : downcast()->toObject(exec);
}
}
#endif // KJS_VALUE_H