Index: tonic/dart_converter.h |
diff --git a/tonic/dart_converter.h b/tonic/dart_converter.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..47d9f8409d0468fe47ba819950a11769a6dc24a6 |
--- /dev/null |
+++ b/tonic/dart_converter.h |
@@ -0,0 +1,383 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef SKY_ENGINE_TONIC_DART_CONVERTER_H_ |
+#define SKY_ENGINE_TONIC_DART_CONVERTER_H_ |
+ |
+#include <string> |
+#include "tonic/dart_state.h" |
+#include "tonic/dart_string.h" |
+#include "tonic/dart_string_cache.h" |
+#include "tonic/dart_value.h" |
+#include "sky/engine/wtf/text/StringUTF8Adaptor.h" |
+#include "sky/engine/wtf/text/WTFString.h" |
+ |
+namespace blink { |
+ |
+// DartConvert converts types back and forth from Sky to Dart. The template |
+// parameter |T| determines what kind of type conversion to perform. |
+template <typename T, typename Enable = void> |
+struct DartConverter { |
+}; |
+ |
+// This is to work around the fact that typedefs do not create new types. If you |
+// have a typedef, and want it to use a different converter, specialize this |
+// template and override the types here. |
+// Ex: |
+// typedef int ColorType; // Want to use a different converter. |
+// class ColorConverterType {}; // Dummy type. |
+// template<> struct DartConvertType<ColorConverterType> { |
+// using ConverterType = ColorConverterType; |
+// using ValueType = ColorType; |
+// }; |
+template <typename T> |
+struct DartConverterTypes { |
+ using ConverterType = T; |
+ using ValueType = T; |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Boolean |
+ |
+template <> |
+struct DartConverter<bool> { |
+ static Dart_Handle ToDart(bool val) { return Dart_NewBoolean(val); } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, bool val) { |
+ Dart_SetBooleanReturnValue(args, val); |
+ } |
+ |
+ static bool FromDart(Dart_Handle handle) { |
+ bool result = 0; |
+ Dart_BooleanValue(handle, &result); |
+ return result; |
+ } |
+ |
+ static bool FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception) { |
+ bool result = false; |
+ Dart_GetNativeBooleanArgument(args, index, &result); |
+ return result; |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Numbers |
+ |
+template <typename T> |
+struct DartConverterInteger { |
+ static Dart_Handle ToDart(T val) { return Dart_NewInteger(val); } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, T val) { |
+ Dart_SetIntegerReturnValue(args, val); |
+ } |
+ |
+ static T FromDart(Dart_Handle handle) { |
+ int64_t result = 0; |
+ Dart_IntegerToInt64(handle, &result); |
+ return static_cast<T>(result); |
+ } |
+ |
+ static T FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception) { |
+ int64_t result = 0; |
+ Dart_GetNativeIntegerArgument(args, index, &result); |
+ return static_cast<T>(result); |
+ } |
+}; |
+ |
+template <> |
+struct DartConverter<int> : public DartConverterInteger<int> {}; |
+ |
+template <> |
+struct DartConverter<unsigned> : public DartConverterInteger<unsigned> {}; |
+ |
+template <> |
+struct DartConverter<long long> : public DartConverterInteger<long long> {}; |
+ |
+template <> |
+struct DartConverter<unsigned long long> { |
+ static Dart_Handle ToDart(unsigned long long val) { |
+ // FIXME: WebIDL unsigned long long is guaranteed to fit into 64-bit |
+ // unsigned, |
+ // so we need a dart API for constructing an integer from uint64_t. |
+ DCHECK(val <= 0x7fffffffffffffffLL); |
+ return Dart_NewInteger(static_cast<int64_t>(val)); |
+ } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, |
+ unsigned long long val) { |
+ DCHECK(val <= 0x7fffffffffffffffLL); |
+ Dart_SetIntegerReturnValue(args, val); |
+ } |
+ |
+ static unsigned long long FromDart(Dart_Handle handle) { |
+ int64_t result = 0; |
+ Dart_IntegerToInt64(handle, &result); |
+ return result; |
+ } |
+ |
+ static unsigned long long FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception) { |
+ int64_t result = 0; |
+ Dart_GetNativeIntegerArgument(args, index, &result); |
+ return result; |
+ } |
+}; |
+ |
+template <typename T> |
+struct DartConverterFloatingPoint { |
+ static Dart_Handle ToDart(T val) { return Dart_NewDouble(val); } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, T val) { |
+ Dart_SetDoubleReturnValue(args, val); |
+ } |
+ |
+ static T FromDart(Dart_Handle handle) { |
+ double result = 0; |
+ Dart_DoubleValue(handle, &result); |
+ return result; |
+ } |
+ |
+ static T FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception) { |
+ double result = 0; |
+ Dart_GetNativeDoubleArgument(args, index, &result); |
+ return result; |
+ } |
+}; |
+ |
+template <> |
+struct DartConverter<float> : public DartConverterFloatingPoint<float> {}; |
+ |
+template <> |
+struct DartConverter<double> : public DartConverterFloatingPoint<double> {}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Enums |
+ |
+template <typename T> |
+struct DartConverterEnum { |
+ static T FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception) { |
+ Dart_Handle enum_handle = Dart_GetNativeArgument(args, index); |
+ Dart_Handle index_handle = |
+ Dart_GetField(enum_handle, DartState::Current()->index_handle()); |
+ |
+ uint64_t enum_index = 0; |
+ Dart_IntegerToUint64(index_handle, &enum_index); |
+ return static_cast<T>(enum_index); |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Strings |
+ |
+template <> |
+struct DartConverter<String> { |
+ static Dart_Handle ToDart(DartState* state, const String& val) { |
+ if (val.isEmpty()) |
+ return Dart_EmptyString(); |
+ return Dart_HandleFromWeakPersistent(state->string_cache().Get(val.impl())); |
+ } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, |
+ const String& val, |
+ bool auto_scope = true) { |
+ // TODO(abarth): What should we do with auto_scope? |
+ if (val.isEmpty()) { |
+ Dart_SetReturnValue(args, Dart_EmptyString()); |
+ return; |
+ } |
+ DartState* state = DartState::Current(); |
+ Dart_SetWeakHandleReturnValue(args, state->string_cache().Get(val.impl())); |
+ } |
+ |
+ static void SetReturnValueWithNullCheck(Dart_NativeArguments args, |
+ const String& val, |
+ bool auto_scope = true) { |
+ if (val.isNull()) |
+ Dart_SetReturnValue(args, Dart_Null()); |
+ else |
+ SetReturnValue(args, val, auto_scope); |
+ } |
+ |
+ static String FromDart(Dart_Handle handle) { |
+ intptr_t char_size = 0; |
+ intptr_t length = 0; |
+ void* peer = nullptr; |
+ Dart_Handle result = |
+ Dart_StringGetProperties(handle, &char_size, &length, &peer); |
+ if (peer) |
+ return String(static_cast<StringImpl*>(peer)); |
+ if (Dart_IsError(result)) |
+ return String(); |
+ return ExternalizeDartString(handle); |
+ } |
+ |
+ static String FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): What should we do with auto_scope? |
+ void* peer = nullptr; |
+ Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer); |
+ if (peer) |
+ return reinterpret_cast<StringImpl*>(peer); |
+ if (Dart_IsError(handle)) |
+ return String(); |
+ return ExternalizeDartString(handle); |
+ } |
+ |
+ static String FromArgumentsWithNullCheck(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): What should we do with auto_scope? |
+ void* peer = nullptr; |
+ Dart_Handle handle = Dart_GetNativeStringArgument(args, index, &peer); |
+ if (peer) |
+ return reinterpret_cast<StringImpl*>(peer); |
+ if (Dart_IsError(handle) || Dart_IsNull(handle)) |
+ return String(); |
+ return ExternalizeDartString(handle); |
+ } |
+}; |
+ |
+template <> |
+struct DartConverter<AtomicString> { |
+ static Dart_Handle ToDart(DartState* state, const AtomicString& val) { |
+ return DartConverter<String>::ToDart(state, val.string()); |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Collections |
+ |
+template <typename T> |
+struct DartConverter<Vector<T>> { |
+ using ValueType = typename DartConverterTypes<T>::ValueType; |
+ using ConverterType = typename DartConverterTypes<T>::ConverterType; |
+ |
+ static Dart_Handle ToDart(const Vector<ValueType>& val) { |
+ Dart_Handle list = Dart_NewList(val.size()); |
+ if (Dart_IsError(list)) |
+ return list; |
+ for (size_t i = 0; i < val.size(); i++) { |
+ Dart_Handle result = |
+ Dart_ListSetAt(list, i, |
+ DartConverter<ConverterType>::ToDart(val[i])); |
+ if (Dart_IsError(result)) |
+ return result; |
+ } |
+ return list; |
+ } |
+ |
+ static Vector<ValueType> FromDart(Dart_Handle handle) { |
+ Vector<ValueType> result; |
+ if (!Dart_IsList(handle)) |
+ return result; |
+ intptr_t length = 0; |
+ Dart_ListLength(handle, &length); |
+ result.reserveCapacity(length); |
+ for (intptr_t i = 0; i < length; ++i) { |
+ Dart_Handle item = Dart_ListGetAt(handle, i); |
+ DCHECK(!Dart_IsError(item)); |
+ DCHECK(item); |
+ result.append(DartConverter<ConverterType>::FromDart(item)); |
+ } |
+ return result; |
+ } |
+ |
+ static Vector<ValueType> FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): What should we do with auto_scope? |
+ return FromDart(Dart_GetNativeArgument(args, index)); |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// DartValue |
+ |
+template <> |
+struct DartConverter<DartValue*> { |
+ static Dart_Handle ToDart(DartState* state, DartValue* val) { |
+ return val->dart_value(); |
+ } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, DartValue* val) { |
+ Dart_SetReturnValue(args, val->dart_value()); |
+ } |
+ |
+ static PassRefPtr<DartValue> FromDart(Dart_Handle handle) { |
+ return DartValue::Create(DartState::Current(), handle); |
+ } |
+ |
+ static PassRefPtr<DartValue> FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): What should we do with auto_scope? |
+ return FromDart(Dart_GetNativeArgument(args, index)); |
+ } |
+}; |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Convience wrappers for commonly used conversions |
+ |
+inline Dart_Handle StringToDart(DartState* state, const String& val) { |
+ return DartConverter<String>::ToDart(state, val); |
+} |
+ |
+inline Dart_Handle StringToDart(DartState* state, const AtomicString& val) { |
+ return DartConverter<AtomicString>::ToDart(state, val); |
+} |
+ |
+inline String StringFromDart(Dart_Handle handle) { |
+ return DartConverter<String>::FromDart(handle); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Convience wrappers using type inference for ease of code generation |
+ |
+template <typename T> |
+inline Dart_Handle VectorToDart(const Vector<T>& val) { |
+ return DartConverter<Vector<T>>::ToDart(val); |
+} |
+ |
+template<typename T> |
+Dart_Handle ToDart(const T& object) { |
+ return DartConverter<T>::ToDart(object); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// std::string support (slower, but more convienent for some clients) |
+ |
+inline Dart_Handle StdStringToDart(const std::string& val) { |
+ return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()), |
+ val.length()); |
+} |
+ |
+inline std::string StdStringFromDart(Dart_Handle handle) { |
+ String string = StringFromDart(handle); |
+ StringUTF8Adaptor utf8(string); |
+ return std::string(utf8.data(), utf8.length()); |
+} |
+ |
+ |
+// Alias Dart_NewStringFromCString for less typing. |
+inline Dart_Handle ToDart(const char* val) { |
+ return Dart_NewStringFromCString(val); |
+} |
+ |
+} // namespace blink |
+ |
+#endif // SKY_ENGINE_TONIC_DART_CONVERTER_H_ |