| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef SKY_ENGINE_TONIC_DART_CONVERTER_H_ |
| 6 #define SKY_ENGINE_TONIC_DART_CONVERTER_H_ |
| 7 |
| 8 #include <string> |
| 9 #include "sky/engine/tonic/dart_state.h" |
| 10 #include "sky/engine/tonic/dart_string.h" |
| 11 #include "sky/engine/tonic/dart_string_cache.h" |
| 12 #include "sky/engine/tonic/dart_value.h" |
| 13 #include "sky/engine/wtf/text/StringUTF8Adaptor.h" |
| 14 #include "sky/engine/wtf/text/WTFString.h" |
| 15 |
| 16 namespace blink { |
| 17 |
| 18 // DartConvert converts types back and forth from Sky to Dart. The template |
| 19 // parameter |T| determines what kind of type conversion to perform. |
| 20 template <typename T, typename Enable = void> |
| 21 struct DartConverter {}; |
| 22 |
| 23 //////////////////////////////////////////////////////////////////////////////// |
| 24 // Boolean |
| 25 |
| 26 template <> |
| 27 struct DartConverter<bool> { |
| 28 static Dart_Handle ToDart(bool val) { return Dart_NewBoolean(val); } |
| 29 |
| 30 static void SetReturnValue(Dart_NativeArguments args, bool val) { |
| 31 Dart_SetBooleanReturnValue(args, val); |
| 32 } |
| 33 |
| 34 static bool FromDart(Dart_Handle handle) { |
| 35 bool result = 0; |
| 36 Dart_BooleanValue(handle, &result); |
| 37 return result; |
| 38 } |
| 39 |
| 40 static bool FromArguments(Dart_NativeArguments args, |
| 41 int index, |
| 42 Dart_Handle& exception) { |
| 43 bool result = false; |
| 44 Dart_GetNativeBooleanArgument(args, index, &result); |
| 45 return result; |
| 46 } |
| 47 }; |
| 48 |
| 49 //////////////////////////////////////////////////////////////////////////////// |
| 50 // Numbers |
| 51 |
| 52 template <typename T> |
| 53 struct DartConverterInteger { |
| 54 static Dart_Handle ToDart(T val) { return Dart_NewInteger(val); } |
| 55 |
| 56 static void SetReturnValue(Dart_NativeArguments args, T val) { |
| 57 Dart_SetIntegerReturnValue(args, val); |
| 58 } |
| 59 |
| 60 static T FromDart(Dart_Handle handle) { |
| 61 int64_t result = 0; |
| 62 Dart_IntegerToInt64(handle, &result); |
| 63 return result; |
| 64 } |
| 65 |
| 66 static T FromArguments(Dart_NativeArguments args, |
| 67 int index, |
| 68 Dart_Handle& exception) { |
| 69 int64_t result = 0; |
| 70 Dart_GetNativeIntegerArgument(args, index, &result); |
| 71 return result; |
| 72 } |
| 73 }; |
| 74 |
| 75 template <> |
| 76 struct DartConverter<int> : public DartConverterInteger<int> {}; |
| 77 |
| 78 template <> |
| 79 struct DartConverter<unsigned> : public DartConverterInteger<unsigned> {}; |
| 80 |
| 81 template <> |
| 82 struct DartConverter<long long> : public DartConverterInteger<long long> {}; |
| 83 |
| 84 template <> |
| 85 struct DartConverter<unsigned long long> { |
| 86 static Dart_Handle ToDart(unsigned long long val) { |
| 87 // FIXME: WebIDL unsigned long long is guaranteed to fit into 64-bit |
| 88 // unsigned, |
| 89 // so we need a dart API for constructing an integer from uint64_t. |
| 90 DCHECK(val <= 0x7fffffffffffffffLL); |
| 91 return Dart_NewInteger(static_cast<int64_t>(val)); |
| 92 } |
| 93 |
| 94 static void SetReturnValue(Dart_NativeArguments args, |
| 95 unsigned long long val) { |
| 96 DCHECK(val <= 0x7fffffffffffffffLL); |
| 97 Dart_SetIntegerReturnValue(args, val); |
| 98 } |
| 99 |
| 100 static unsigned long long FromDart(Dart_Handle handle) { |
| 101 int64_t result = 0; |
| 102 Dart_IntegerToInt64(handle, &result); |
| 103 return result; |
| 104 } |
| 105 |
| 106 static unsigned long long FromArguments(Dart_NativeArguments args, |
| 107 int index, |
| 108 Dart_Handle& exception) { |
| 109 int64_t result = 0; |
| 110 Dart_GetNativeIntegerArgument(args, index, &result); |
| 111 return result; |
| 112 } |
| 113 }; |
| 114 |
| 115 template <typename T> |
| 116 struct DartConverterFloatingPoint { |
| 117 static Dart_Handle ToDart(T val) { return Dart_NewDouble(val); } |
| 118 |
| 119 static void SetReturnValue(Dart_NativeArguments args, T val) { |
| 120 Dart_SetDoubleReturnValue(args, val); |
| 121 } |
| 122 |
| 123 static T FromDart(Dart_Handle handle) { |
| 124 double result = 0; |
| 125 Dart_DoubleValue(handle, &result); |
| 126 return result; |
| 127 } |
| 128 |
| 129 static T FromArguments(Dart_NativeArguments args, |
| 130 int index, |
| 131 Dart_Handle& exception) { |
| 132 double result = 0; |
| 133 Dart_GetNativeDoubleArgument(args, index, &result); |
| 134 return result; |
| 135 } |
| 136 }; |
| 137 |
| 138 template <> |
| 139 struct DartConverter<float> : public DartConverterFloatingPoint<float> {}; |
| 140 |
| 141 template <> |
| 142 struct DartConverter<double> : public DartConverterFloatingPoint<double> {}; |
| 143 |
| 144 //////////////////////////////////////////////////////////////////////////////// |
| 145 // Strings |
| 146 |
| 147 template <> |
| 148 struct DartConverter<String> { |
| 149 static Dart_Handle ToDart(DartState* state, const String& val) { |
| 150 if (val.isEmpty()) |
| 151 return Dart_EmptyString(); |
| 152 return Dart_HandleFromWeakPersistent(state->string_cache().Get(val.impl())); |
| 153 } |
| 154 |
| 155 static void SetReturnValue(Dart_NativeArguments args, |
| 156 const String& val, |
| 157 bool auto_scope = true) { |
| 158 // TODO(abarth): What should we do with auto_scope? |
| 159 if (val.isEmpty()) { |
| 160 Dart_SetReturnValue(args, Dart_EmptyString()); |
| 161 return; |
| 162 } |
| 163 DartState* state = DartState::Current(); |
| 164 Dart_SetWeakHandleReturnValue(args, state->string_cache().Get(val.impl())); |
| 165 } |
| 166 |
| 167 static void SetReturnValueWithNullCheck(Dart_NativeArguments args, |
| 168 const String& val, |
| 169 bool auto_scope = true) { |
| 170 if (val.isNull()) |
| 171 Dart_SetReturnValue(args, Dart_Null()); |
| 172 else |
| 173 SetReturnValue(args, val, auto_scope); |
| 174 } |
| 175 |
| 176 static String FromDart(Dart_Handle handle) { |
| 177 intptr_t char_size = 0; |
| 178 intptr_t length = 0; |
| 179 void* peer = nullptr; |
| 180 Dart_Handle result = |
| 181 Dart_StringGetProperties(handle, &char_size, &length, &peer); |
| 182 if (peer) |
| 183 return String(static_cast<StringImpl*>(peer)); |
| 184 if (Dart_IsError(result)) |
| 185 return String(); |
| 186 return ExternalizeDartString(handle); |
| 187 } |
| 188 |
| 189 static String FromArguments(Dart_NativeArguments args, |
| 190 int index, |
| 191 Dart_Handle& exception, |
| 192 bool auto_scope = true) { |
| 193 // TODO(abarth): What should we do with auto_scope? |
| 194 void* peer = nullptr; |
| 195 Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer); |
| 196 if (peer) |
| 197 return reinterpret_cast<StringImpl*>(peer); |
| 198 if (Dart_IsError(handle)) |
| 199 return String(); |
| 200 return ExternalizeDartString(handle); |
| 201 } |
| 202 |
| 203 static String FromArgumentsWithNullCheck(Dart_NativeArguments args, |
| 204 int index, |
| 205 Dart_Handle& exception, |
| 206 bool auto_scope = true) { |
| 207 // TODO(abarth): What should we do with auto_scope? |
| 208 void* peer = nullptr; |
| 209 Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer); |
| 210 if (peer) |
| 211 return reinterpret_cast<StringImpl*>(peer); |
| 212 if (Dart_IsError(handle) || Dart_IsNull(handle)) |
| 213 return String(); |
| 214 return ExternalizeDartString(handle); |
| 215 } |
| 216 }; |
| 217 |
| 218 template <> |
| 219 struct DartConverter<AtomicString> { |
| 220 static Dart_Handle ToDart(DartState* state, const AtomicString& val) { |
| 221 return DartConverter<String>::ToDart(state, val.string()); |
| 222 } |
| 223 }; |
| 224 |
| 225 //////////////////////////////////////////////////////////////////////////////// |
| 226 // Collections |
| 227 |
| 228 template <typename T> |
| 229 struct DartConverter<Vector<T>> { |
| 230 static Dart_Handle ToDart(const Vector<T>& val) { |
| 231 Dart_Handle list = Dart_NewList(val.size()); |
| 232 if (Dart_IsError(list)) |
| 233 return list; |
| 234 for (size_t i = 0; i < val.size(); i++) { |
| 235 Dart_Handle result = |
| 236 Dart_ListSetAt(list, i, DartConverter<T>::ToDart(val[i])); |
| 237 if (Dart_IsError(result)) |
| 238 return result; |
| 239 } |
| 240 return list; |
| 241 } |
| 242 |
| 243 static Vector<T> FromDart(Dart_Handle handle) { |
| 244 Vector<T> result; |
| 245 if (!Dart_IsList(handle)) |
| 246 return result; |
| 247 intptr_t length = 0; |
| 248 Dart_ListLength(handle, &length); |
| 249 result.reserveCapacity(length); |
| 250 for (intptr_t i = 0; i < length; ++i) { |
| 251 Dart_Handle element = Dart_ListGetAt(handle, i); |
| 252 DCHECK(!Dart_IsError(element)); |
| 253 result.append(DartConverter<T>::FromDart(element)); |
| 254 } |
| 255 return result; |
| 256 } |
| 257 |
| 258 static Vector<T> FromArguments(Dart_NativeArguments args, |
| 259 int index, |
| 260 Dart_Handle& exception, |
| 261 bool auto_scope = true) { |
| 262 // TODO(abarth): What should we do with auto_scope? |
| 263 return FromDart(Dart_GetNativeArgument(args, index)); |
| 264 } |
| 265 }; |
| 266 |
| 267 //////////////////////////////////////////////////////////////////////////////// |
| 268 // DartValue |
| 269 |
| 270 template <> |
| 271 struct DartConverter<DartValue> { |
| 272 static Dart_Handle ToDart(DartState* state, DartValue* val) { |
| 273 return val->dart_value(); |
| 274 } |
| 275 |
| 276 static void SetReturnValue(Dart_NativeArguments args, DartValue* val) { |
| 277 Dart_SetReturnValue(args, val->dart_value()); |
| 278 } |
| 279 }; |
| 280 |
| 281 //////////////////////////////////////////////////////////////////////////////// |
| 282 // Convience wrappers for commonly used conversions |
| 283 |
| 284 inline Dart_Handle StringToDart(DartState* state, const String& val) { |
| 285 return DartConverter<String>::ToDart(state, val); |
| 286 } |
| 287 |
| 288 inline Dart_Handle StringToDart(DartState* state, const AtomicString& val) { |
| 289 return DartConverter<AtomicString>::ToDart(state, val); |
| 290 } |
| 291 |
| 292 inline String StringFromDart(Dart_Handle handle) { |
| 293 return DartConverter<String>::FromDart(handle); |
| 294 } |
| 295 |
| 296 //////////////////////////////////////////////////////////////////////////////// |
| 297 // Convience wrappers using type inference for ease of code generation |
| 298 |
| 299 template <typename T> |
| 300 inline Dart_Handle VectorToDart(const Vector<T>& val) { |
| 301 return DartConverter<Vector<T>>::ToDart(val); |
| 302 } |
| 303 |
| 304 template<typename T> |
| 305 Dart_Handle ToDart(const T& object) { |
| 306 return DartConverter<T>::ToDart(object); |
| 307 } |
| 308 |
| 309 //////////////////////////////////////////////////////////////////////////////// |
| 310 // std::string support (slower, but more convienent for some clients) |
| 311 |
| 312 inline Dart_Handle StdStringToDart(const std::string& val) { |
| 313 return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()), |
| 314 val.length()); |
| 315 } |
| 316 |
| 317 inline std::string StdStringFromDart(Dart_Handle handle) { |
| 318 String string = StringFromDart(handle); |
| 319 StringUTF8Adaptor utf8(string); |
| 320 return std::string(utf8.data(), utf8.length()); |
| 321 } |
| 322 |
| 323 } // namespace blink |
| 324 |
| 325 #endif // SKY_ENGINE_TONIC_DART_CONVERTER_H_ |
| OLD | NEW |