1/* 2 * Copyright (C) 2013 Apple Inc. All Rights Reserved. 3 * Copyright (C) 2011 The Chromium Authors. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#ifndef InspectorTypeBuilder_h 28#define InspectorTypeBuilder_h 29 30#if ENABLE(INSPECTOR) 31 32#include "InspectorValues.h" 33#include <wtf/Assertions.h> 34#include <wtf/PassRefPtr.h> 35 36namespace Inspector { 37 38namespace TypeBuilder { 39 40template<typename T> 41class OptOutput { 42public: 43 OptOutput() : m_assigned(false) { } 44 45 void operator=(T value) 46 { 47 m_value = value; 48 m_assigned = true; 49 } 50 51 bool isAssigned() const { return m_assigned; } 52 53 T getValue() 54 { 55 ASSERT(isAssigned()); 56 return m_value; 57 } 58 59private: 60 T m_value; 61 bool m_assigned; 62 63 WTF_MAKE_NONCOPYABLE(OptOutput); 64}; 65 66 67// A small transient wrapper around int type, that can be used as a funciton parameter type 68// cleverly disallowing C++ implicit casts from float or double. 69class ExactlyInt { 70public: 71 template<typename T> 72 ExactlyInt(T t) : m_value(cast_to_int<T>(t)) { } 73 ExactlyInt() { } 74 75 operator int() { return m_value; } 76 77private: 78 int m_value; 79 80 template<typename T> 81 static int cast_to_int(T) { return T::default_case_cast_is_not_supported(); } 82}; 83 84template<> 85inline int ExactlyInt::cast_to_int<int>(int i) { return i; } 86 87template<> 88inline int ExactlyInt::cast_to_int<unsigned int>(unsigned int i) { return i; } 89 90#if !ASSERT_DISABLED 91class RuntimeCastHelper { 92public: 93 template<InspectorValue::Type TYPE> 94 static void assertType(InspectorValue* value) 95 { 96 ASSERT(value->type() == TYPE); 97 } 98 99 static void assertAny(InspectorValue*) 100 { 101 } 102 103 static void assertInt(InspectorValue* value) 104 { 105 double v; 106 bool castRes = value->asNumber(&v); 107 ASSERT_UNUSED(castRes, castRes); 108 ASSERT(static_cast<double>(static_cast<int>(v)) == v); 109 } 110}; 111#endif 112 113 114// This class provides "Traits" type for the input type T. It is programmed using C++ template specialization 115// technique. By default it simply takes "ItemTraits" type from T, but it doesn't work with the base types. 116template<typename T> 117struct ArrayItemHelper { 118 typedef typename T::ItemTraits Traits; 119}; 120 121template<typename T> 122class Array : public InspectorArrayBase { 123private: 124 Array() { } 125 126 InspectorArray* openAccessors() 127 { 128 COMPILE_ASSERT(sizeof(InspectorArray) == sizeof(Array<T>), cannot_cast); 129 return static_cast<InspectorArray*>(static_cast<InspectorArrayBase*>(this)); 130 } 131 132public: 133 void addItem(PassRefPtr<T> value) 134 { 135 ArrayItemHelper<T>::Traits::pushRefPtr(this->openAccessors(), value); 136 } 137 138 void addItem(T value) 139 { 140 ArrayItemHelper<T>::Traits::pushRaw(this->openAccessors(), value); 141 } 142 143 static PassRefPtr<Array<T>> create() 144 { 145 return adoptRef(new Array<T>()); 146 } 147 148 static PassRefPtr<Array<T>> runtimeCast(PassRefPtr<InspectorValue> value) 149 { 150 RefPtr<InspectorArray> array; 151 bool castRes = value->asArray(&array); 152 ASSERT_UNUSED(castRes, castRes); 153#if !ASSERT_DISABLED 154 assertCorrectValue(array.get()); 155#endif // !ASSERT_DISABLED 156 COMPILE_ASSERT(sizeof(Array<T>) == sizeof(InspectorArray), type_cast_problem); 157 return static_cast<Array<T>*>(static_cast<InspectorArrayBase*>(array.get())); 158 } 159 160#if !ASSERT_DISABLED 161 static void assertCorrectValue(InspectorValue* value) 162 { 163 RefPtr<InspectorArray> array; 164 bool castRes = value->asArray(&array); 165 ASSERT_UNUSED(castRes, castRes); 166 for (unsigned i = 0; i < array->length(); i++) 167 ArrayItemHelper<T>::Traits::template assertCorrectValue<T>(array->get(i).get()); 168 } 169#endif // !ASSERT_DISABLED 170}; 171 172struct StructItemTraits { 173 static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value) 174 { 175 array->pushValue(value); 176 } 177 178#if !ASSERT_DISABLED 179 template<typename T> 180 static void assertCorrectValue(InspectorValue* value) 181 { 182 T::assertCorrectValue(value); 183 } 184#endif // !ASSERT_DISABLED 185}; 186 187template<> 188struct ArrayItemHelper<String> { 189 struct Traits { 190 static void pushRaw(InspectorArray* array, const String& value) 191 { 192 array->pushString(value); 193 } 194 195#if !ASSERT_DISABLED 196 template<typename T> 197 static void assertCorrectValue(InspectorValue* value) 198 { 199 RuntimeCastHelper::assertType<InspectorValue::TypeString>(value); 200 } 201#endif // !ASSERT_DISABLED 202 }; 203}; 204 205template<> 206struct ArrayItemHelper<int> { 207 struct Traits { 208 static void pushRaw(InspectorArray* array, int value) 209 { 210 array->pushInt(value); 211 } 212 213#if !ASSERT_DISABLED 214 template<typename T> 215 static void assertCorrectValue(InspectorValue* value) 216 { 217 RuntimeCastHelper::assertInt(value); 218 } 219#endif // !ASSERT_DISABLED 220 }; 221}; 222 223template<> 224struct ArrayItemHelper<double> { 225 struct Traits { 226 static void pushRaw(InspectorArray* array, double value) 227 { 228 array->pushNumber(value); 229 } 230 231#if !ASSERT_DISABLED 232 template<typename T> 233 static void assertCorrectValue(InspectorValue* value) 234 { 235 RuntimeCastHelper::assertType<InspectorValue::TypeNumber>(value); 236 } 237#endif // !ASSERT_DISABLED 238 }; 239}; 240 241template<> 242struct ArrayItemHelper<bool> { 243 struct Traits { 244 static void pushRaw(InspectorArray* array, bool value) 245 { 246 array->pushBoolean(value); 247 } 248 249#if !ASSERT_DISABLED 250 template<typename T> 251 static void assertCorrectValue(InspectorValue* value) 252 { 253 RuntimeCastHelper::assertType<InspectorValue::TypeBoolean>(value); 254 } 255#endif // !ASSERT_DISABLED 256 }; 257}; 258 259template<> 260struct ArrayItemHelper<InspectorValue> { 261 struct Traits { 262 static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value) 263 { 264 array->pushValue(value); 265 } 266 267#if !ASSERT_DISABLED 268 template<typename T> 269 static void assertCorrectValue(InspectorValue* value) 270 { 271 RuntimeCastHelper::assertAny(value); 272 } 273#endif // !ASSERT_DISABLED 274 }; 275}; 276 277template<> 278struct ArrayItemHelper<InspectorObject> { 279 struct Traits { 280 static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorValue> value) 281 { 282 array->pushValue(value); 283 } 284 285#if !ASSERT_DISABLED 286 template<typename T> 287 static void assertCorrectValue(InspectorValue* value) 288 { 289 RuntimeCastHelper::assertType<InspectorValue::TypeObject>(value); 290 } 291#endif // !ASSERT_DISABLED 292 }; 293}; 294 295template<> 296struct ArrayItemHelper<InspectorArray> { 297 struct Traits { 298 static void pushRefPtr(InspectorArray* array, PassRefPtr<InspectorArray> value) 299 { 300 array->pushArray(value); 301 } 302 303#if !ASSERT_DISABLED 304 template<typename T> 305 static void assertCorrectValue(InspectorValue* value) 306 { 307 RuntimeCastHelper::assertType<InspectorValue::TypeArray>(value); 308 } 309#endif // !ASSERT_DISABLED 310 }; 311}; 312 313template<typename T> 314struct ArrayItemHelper<TypeBuilder::Array<T>> { 315 struct Traits { 316 static void pushRefPtr(InspectorArray* array, PassRefPtr<TypeBuilder::Array<T>> value) 317 { 318 array->pushValue(value); 319 } 320 321#if !ASSERT_DISABLED 322 template<typename S> 323 static void assertCorrectValue(InspectorValue* value) 324 { 325 S::assertCorrectValue(value); 326 } 327#endif // !ASSERT_DISABLED 328 }; 329}; 330 331} // namespace TypeBuilder 332 333} // namespace Inspector 334 335#endif // ENABLE(INSPECTOR) 336 337#endif // !defined(InspectorTypeBuilder_h) 338