InspectorTypeBuilder.h [plain text]
#ifndef InspectorTypeBuilder_h
#define InspectorTypeBuilder_h
#if ENABLE(INSPECTOR)
#include "InspectorValues.h"
#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h>
namespace Inspector {
namespace TypeBuilder {
template<typename T>
class OptOutput {
public:
OptOutput() : m_assigned(false) { }
void operator=(T value)
{
m_value = value;
m_assigned = true;
}
bool isAssigned() const { return m_assigned; }
T getValue()
{
ASSERT(isAssigned());
return m_value;
}
private:
T m_value;
bool m_assigned;
WTF_MAKE_NONCOPYABLE(OptOutput);
};
class ExactlyInt {
public:
template<typename T>
ExactlyInt(T t) : m_value(cast_to_int<T>(t)) { }
ExactlyInt() { }
operator int() { return m_value; }
private:
int m_value;
template<typename T>
static int cast_to_int(T) { return T::default_case_cast_is_not_supported(); }
};
template<>
inline int ExactlyInt::cast_to_int<int>(int i) { return i; }
template<>
inline int ExactlyInt::cast_to_int<unsigned int>(unsigned int i) { return i; }
#if !ASSERT_DISABLED
class RuntimeCastHelper {
public:
template<InspectorValue::Type TYPE>
static void assertType(InspectorValue* value)
{
ASSERT(value->type() == TYPE);
}
static void assertAny(InspectorValue*)
{
}
static void assertInt(InspectorValue* value)
{
double v;
bool castRes = value->asNumber(&v);
ASSERT_UNUSED(castRes, castRes);
ASSERT(static_cast<double>(static_cast<int>(v)) == v);
}
};
#endif
template<typename T>
struct ArrayItemHelper {
typedef typename T::ItemTraits Traits;
};
template<typename T>
class Array : public InspectorArrayBase {
private:
Array() { }
InspectorArray* openAccessors()
{
COMPILE_ASSERT(sizeof(InspectorArray) == sizeof(Array<T>), cannot_cast);
return static_cast<InspectorArray*>(static_cast<InspectorArrayBase*>(this));
}
public:
void addItem(PassRefPtr<T> value)
{
ArrayItemHelper<T>::Traits::pushRefPtr(this->openAccessors(), value);
}
void addItem(T value)
{
ArrayItemHelper<T>::Traits::pushRaw(this->openAccessors(), value);
}
static PassRefPtr<Array<T>> create()
{
return adoptRef(new Array<T>());
}
static PassRefPtr<Array<T>> runtimeCast(PassRefPtr<InspectorValue> value)
{
RefPtr<InspectorArray> array;
bool castRes = value->asArray(&array);
ASSERT_UNUSED(castRes, castRes);
#if !ASSERT_DISABLED
assertCorrectValue(array.get());
#endif // !ASSERT_DISABLED
COMPILE_ASSERT(sizeof(Array<T>) == sizeof(InspectorArray), type_cast_problem);
return static_cast<Array<T>*>(static_cast<InspectorArrayBase*>(array.get()));
}
#if !ASSERT_DISABLED
static void assertCorrectValue(InspectorValue* value)
{
RefPtr<InspectorArray> array;
bool castRes = value->asArray(&array);
ASSERT_UNUSED(castRes, castRes);
for (unsigned i = 0; i < array->length(); i++)
ArrayItemHelper<T>::Traits::template assertCorrectValue<T>(array->get(i).get());
}
#endif // !ASSERT_DISABLED
};
struct StructItemTraits {
static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
{
array->pushValue(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
T::assertCorrectValue(value);
}
#endif // !ASSERT_DISABLED
};
template<>
struct ArrayItemHelper<String> {
struct Traits {
static void pushRaw(InspectorArray* array, const String& value)
{
array->pushString(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertType<InspectorValue::TypeString>(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<int> {
struct Traits {
static void pushRaw(InspectorArray* array, int value)
{
array->pushInt(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertInt(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<double> {
struct Traits {
static void pushRaw(InspectorArray* array, double value)
{
array->pushNumber(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertType<InspectorValue::TypeNumber>(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<bool> {
struct Traits {
static void pushRaw(InspectorArray* array, bool value)
{
array->pushBoolean(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertType<InspectorValue::TypeBoolean>(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<InspectorValue> {
struct Traits {
static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
{
array->pushValue(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertAny(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<InspectorObject> {
struct Traits {
static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value)
{
array->pushValue(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertType<InspectorValue::TypeObject>(value);
}
#endif // !ASSERT_DISABLED
};
};
template<>
struct ArrayItemHelper<InspectorArray> {
struct Traits {
static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorArray> value)
{
array->pushArray(value);
}
#if !ASSERT_DISABLED
template<typename T>
static void assertCorrectValue(InspectorValue* value)
{
RuntimeCastHelper::assertType<InspectorValue::TypeArray>(value);
}
#endif // !ASSERT_DISABLED
};
};
template<typename T>
struct ArrayItemHelper<TypeBuilder::Array<T>> {
struct Traits {
static void pushRefPtr(InspectorArray* array, PassRefPtr<TypeBuilder::Array<T>> value)
{
array->pushValue(value);
}
#if !ASSERT_DISABLED
template<typename S>
static void assertCorrectValue(InspectorValue* value)
{
S::assertCorrectValue(value);
}
#endif // !ASSERT_DISABLED
};
};
}
}
#endif // ENABLE(INSPECTOR)
#endif // !defined(InspectorTypeBuilder_h)