Flutter Engine
dart_converter.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 LIB_CONVERTER_TONIC_DART_CONVERTER_H_
6 #define LIB_CONVERTER_TONIC_DART_CONVERTER_H_
7 
8 #include <string>
9 #include <type_traits>
10 #include <vector>
11 
12 #include "third_party/dart/runtime/include/dart_api.h"
13 #include "tonic/common/macros.h"
15 
16 namespace tonic {
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 // This is to work around the fact that typedefs do not create new types. If you
24 // have a typedef, and want it to use a different converter, specialize this
25 // template and override the types here.
26 // Ex:
27 // typedef int ColorType; // Want to use a different converter.
28 // class ColorConverterType {}; // Dummy type.
29 // template<> struct DartConvertType<ColorConverterType> {
30 // using ConverterType = ColorConverterType;
31 // using ValueType = ColorType;
32 // };
33 template <typename T>
35  using ConverterType = T;
36  using ValueType = T;
37 };
38 
39 ////////////////////////////////////////////////////////////////////////////////
40 // Boolean
41 
42 template <>
43 struct DartConverter<bool> {
44  static Dart_Handle ToDart(bool val) { return Dart_NewBoolean(val); }
45 
46  static void SetReturnValue(Dart_NativeArguments args, bool val) {
47  Dart_SetBooleanReturnValue(args, val);
48  }
49 
50  static bool FromDart(Dart_Handle handle) {
51  bool result = 0;
52  Dart_BooleanValue(handle, &result);
53  return result;
54  }
55 
56  static bool FromArguments(Dart_NativeArguments args,
57  int index,
58  Dart_Handle& exception) {
59  bool result = false;
60  Dart_GetNativeBooleanArgument(args, index, &result);
61  return result;
62  }
63 };
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 // Numbers
67 
68 template <typename T>
70  static Dart_Handle ToDart(T val) { return Dart_NewInteger(val); }
71 
72  static void SetReturnValue(Dart_NativeArguments args, T val) {
73  Dart_SetIntegerReturnValue(args, val);
74  }
75 
76  static T FromDart(Dart_Handle handle) {
77  int64_t result = 0;
78  Dart_IntegerToInt64(handle, &result);
79  return static_cast<T>(result);
80  }
81 
82  static T FromArguments(Dart_NativeArguments args,
83  int index,
84  Dart_Handle& exception) {
85  int64_t result = 0;
86  Dart_GetNativeIntegerArgument(args, index, &result);
87  return static_cast<T>(result);
88  }
89 };
90 
91 template <>
92 struct DartConverter<int> : public DartConverterInteger<int> {};
93 
94 template <>
95 struct DartConverter<long int> : public DartConverterInteger<long int> {};
96 
97 template <>
98 struct DartConverter<unsigned> : public DartConverterInteger<unsigned> {};
99 
100 template <>
101 struct DartConverter<long long> : public DartConverterInteger<long long> {};
102 
103 template <>
104 struct DartConverter<unsigned long>
105  : public DartConverterInteger<unsigned long> {};
106 
107 template <>
108 struct DartConverter<unsigned long long> {
109  // TODO(abarth): The Dart VM API doesn't yet have an entry-point for
110  // an unsigned 64-bit type. We will need to add a Dart API for
111  // constructing an integer from uint64_t.
112  //
113  // (In the meantime, we have asserts below to check that we're never
114  // converting values that have the 64th bit set.)
115 
116  static Dart_Handle ToDart(unsigned long long val) {
117  TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
118  return Dart_NewInteger(static_cast<int64_t>(val));
119  }
120 
121  static void SetReturnValue(Dart_NativeArguments args,
122  unsigned long long val) {
123  TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
124  Dart_SetIntegerReturnValue(args, val);
125  }
126 
127  static unsigned long long FromDart(Dart_Handle handle) {
128  int64_t result = 0;
129  Dart_IntegerToInt64(handle, &result);
130  return result;
131  }
132 
133  static unsigned long long FromArguments(Dart_NativeArguments args,
134  int index,
135  Dart_Handle& exception) {
136  int64_t result = 0;
137  Dart_GetNativeIntegerArgument(args, index, &result);
138  return result;
139  }
140 };
141 
142 template <typename T>
144  static Dart_Handle ToDart(T val) { return Dart_NewDouble(val); }
145 
146  static void SetReturnValue(Dart_NativeArguments args, T val) {
147  Dart_SetDoubleReturnValue(args, val);
148  }
149 
150  static T FromDart(Dart_Handle handle) {
151  double result = 0;
152  Dart_DoubleValue(handle, &result);
153  return result;
154  }
155 
156  static T FromArguments(Dart_NativeArguments args,
157  int index,
158  Dart_Handle& exception) {
159  double result = 0;
160  Dart_GetNativeDoubleArgument(args, index, &result);
161  return result;
162  }
163 };
164 
165 template <>
166 struct DartConverter<float> : public DartConverterFloatingPoint<float> {};
167 
168 template <>
169 struct DartConverter<double> : public DartConverterFloatingPoint<double> {};
170 
171 ////////////////////////////////////////////////////////////////////////////////
172 // Enum Classes
173 
174 template <typename T>
175 struct DartConverter<T, typename std::enable_if<std::is_enum<T>::value>::type> {
176  static Dart_Handle ToDart(T val) {
177  return Dart_NewInteger(
178  static_cast<typename std::underlying_type<T>::type>(val));
179  }
180 
181  static void SetReturnValue(Dart_NativeArguments args, T val) {
182  Dart_SetIntegerReturnValue(
183  args, static_cast<typename std::underlying_type<T>::type>(val));
184  }
185 
186  static T FromDart(Dart_Handle handle) {
187  int64_t result = 0;
188  Dart_IntegerToInt64(handle, &result);
189  return static_cast<T>(result);
190  }
191 
192  static T FromArguments(Dart_NativeArguments args,
193  int index,
194  Dart_Handle& exception) {
195  int64_t result = 0;
196  Dart_GetNativeIntegerArgument(args, index, &result);
197  return static_cast<T>(result);
198  }
199 };
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 // Strings
203 
204 template <>
205 struct DartConverter<std::string> {
206  static Dart_Handle ToDart(const std::string& val) {
207  return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(val.data()),
208  val.length());
209  }
210 
211  static void SetReturnValue(Dart_NativeArguments args,
212  const std::string& val) {
213  Dart_SetReturnValue(args, ToDart(val));
214  }
215 
216  static std::string FromDart(Dart_Handle handle) {
217  uint8_t* data = nullptr;
218  intptr_t length = 0;
219  if (Dart_IsError(Dart_StringToUTF8(handle, &data, &length)))
220  return std::string();
221  return std::string(reinterpret_cast<char*>(data), length);
222  }
223 
224  static std::string FromArguments(Dart_NativeArguments args,
225  int index,
226  Dart_Handle& exception) {
227  return FromDart(Dart_GetNativeArgument(args, index));
228  }
229 };
230 
231 template <>
232 struct DartConverter<std::u16string> {
233  static Dart_Handle ToDart(const std::u16string& val) {
234  return Dart_NewStringFromUTF16(
235  reinterpret_cast<const uint16_t*>(val.data()), val.length());
236  }
237 
238  static void SetReturnValue(Dart_NativeArguments args,
239  const std::u16string& val) {
240  Dart_SetReturnValue(args, ToDart(val));
241  }
242 
243  static std::u16string FromDart(Dart_Handle handle) {
244  intptr_t length = 0;
245  Dart_StringLength(handle, &length);
246  std::vector<uint16_t> data(length);
247  Dart_StringToUTF16(handle, data.data(), &length);
248  return std::u16string(reinterpret_cast<char16_t*>(data.data()), length);
249  }
250 
251  static std::u16string FromArguments(Dart_NativeArguments args,
252  int index,
253  Dart_Handle& exception) {
254  return FromDart(Dart_GetNativeArgument(args, index));
255  }
256 };
257 
258 template <>
259 struct DartConverter<const char*> {
260  static Dart_Handle ToDart(const char* val) {
261  return Dart_NewStringFromCString(val);
262  }
263 
264  static void SetReturnValue(Dart_NativeArguments args, const char* val) {
265  Dart_SetReturnValue(args, ToDart(val));
266  }
267 
268  static const char* FromDart(Dart_Handle handle) {
269  const char* result = nullptr;
270  Dart_StringToCString(handle, &result);
271  return result;
272  }
273 
274  static const char* FromArguments(Dart_NativeArguments args,
275  int index,
276  Dart_Handle& exception) {
277  return FromDart(Dart_GetNativeArgument(args, index));
278  }
279 };
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 // Collections
283 
284 inline Dart_Handle LookupNonNullableType(const std::string& library_name,
285  const std::string& type_name) {
286  auto library =
287  Dart_LookupLibrary(DartConverter<std::string>::ToDart(library_name));
288  if (LogIfError(library)) {
289  return library;
290  }
291  auto type_string = DartConverter<std::string>::ToDart(type_name);
292  if (LogIfError(type_string)) {
293  return type_string;
294  }
295  auto type = Dart_GetNonNullableType(library, type_string, 0, nullptr);
296  if (LogIfError(type)) {
297  return type;
298  }
299  return type;
300 }
301 
302 template <typename T,
304 Dart_Handle ToDartTypeHandle() {
305  return LookupNonNullableType("dart:core", "String");
306 }
307 
309 Dart_Handle ToDartTypeHandle() {
310  return LookupNonNullableType("dart:core", "int");
311 }
312 
313 template <typename T,
315 Dart_Handle ToDartTypeHandle() {
316  return LookupNonNullableType("dart:core", "double");
317 }
318 
319 template <typename T>
321  Dart_Handle type_handle_or_null = ::Dart_Null()) {
322  if constexpr (std::is_same<std::string, T>::value) {
323  return ::Dart_EmptyString();
324  } else if constexpr (std::is_integral<T>::value) {
325  return ::Dart_NewIntegerFromUint64(0u);
326  } else if constexpr (std::is_floating_point<T>::value) {
327  return ::Dart_NewDouble(0.0);
328  } else {
329  auto object = ::Dart_New(type_handle_or_null, ::Dart_Null(), 0, nullptr);
330  LogIfError(object);
331  return object;
332  }
333  return ::Dart_Null();
334 }
335 
336 template <typename T, typename Enable = void>
338  static Dart_Handle NewList(Dart_Handle type_handle, intptr_t length) {
339  bool is_nullable = false;
340  auto is_nullable_handle = ::Dart_IsNullableType(type_handle, &is_nullable);
341  if (LogIfError(is_nullable_handle)) {
342  return is_nullable_handle;
343  }
344  if (is_nullable) {
345  auto list = ::Dart_NewListOfType(type_handle, length);
346  LogIfError(list);
347  return list;
348  } else {
349  auto sentinel = CreateZeroInitializedDartObject<T>(type_handle);
350  if (LogIfError(sentinel)) {
351  return sentinel;
352  }
353  auto list = ::Dart_NewListOfTypeFilled(type_handle, sentinel, length);
354  LogIfError(list);
355  return list;
356  }
357  return ::Dart_Null();
358  }
359 };
360 
361 template <typename T>
362 struct DartConverter<std::vector<T>> {
365 
366  static Dart_Handle ToDart(const std::vector<ValueType>& val) {
367  Dart_Handle list = DartListFactory<ValueType>::NewList(
368  ToDartTypeHandle<ValueType>(), val.size());
369  if (Dart_IsError(list))
370  return list;
371  for (size_t i = 0; i < val.size(); i++) {
372  Dart_Handle result =
373  Dart_ListSetAt(list, i, DartConverter<ConverterType>::ToDart(val[i]));
374  if (Dart_IsError(result))
375  return result;
376  }
377  return list;
378  }
379 
380  static void SetReturnValue(Dart_NativeArguments args,
381  const std::vector<ValueType>& val) {
382  Dart_SetReturnValue(args, ToDart(val));
383  }
384 
385  static std::vector<ValueType> FromDart(Dart_Handle handle) {
386  std::vector<ValueType> result;
387 
388  if (!Dart_IsList(handle))
389  return result;
390 
391  intptr_t length = 0;
392  Dart_ListLength(handle, &length);
393 
394  if (length == 0)
395  return result;
396 
397  result.reserve(length);
398 
399  std::vector<Dart_Handle> items(length);
400  Dart_Handle items_result =
401  Dart_ListGetRange(handle, 0, length, items.data());
402  TONIC_DCHECK(!Dart_IsError(items_result));
403 
404  for (intptr_t i = 0; i < length; ++i) {
405  TONIC_DCHECK(items[i]);
406  result.push_back(DartConverter<ConverterType>::FromDart(items[i]));
407  }
408  return result;
409  }
410 
411  static std::vector<ValueType> FromArguments(Dart_NativeArguments args,
412  int index,
413  Dart_Handle& exception) {
414  return FromDart(Dart_GetNativeArgument(args, index));
415  }
416 };
417 
418 ////////////////////////////////////////////////////////////////////////////////
419 // Dart_Handle
420 
421 template <>
422 struct DartConverter<Dart_Handle> {
423  static Dart_Handle ToDart(Dart_Handle val) { return val; }
424 
425  static void SetReturnValue(Dart_NativeArguments args, Dart_Handle val) {
426  Dart_SetReturnValue(args, val);
427  }
428 
429  static Dart_Handle FromDart(Dart_Handle handle) { return handle; }
430 
431  static Dart_Handle FromArguments(Dart_NativeArguments args,
432  int index,
433  Dart_Handle& exception) {
434  return Dart_GetNativeArgument(args, index);
435  }
436 };
437 
438 ////////////////////////////////////////////////////////////////////////////////
439 // Convience wrappers using type inference
440 
441 template <typename T>
442 Dart_Handle ToDart(const T& object) {
443  return DartConverter<T>::ToDart(object);
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 // std::string support
448 
449 inline Dart_Handle StdStringToDart(const std::string& val) {
451 }
452 
453 inline std::string StdStringFromDart(Dart_Handle handle) {
455 }
456 
457 // Alias Dart_NewStringFromCString for less typing.
458 inline Dart_Handle ToDart(const char* val) {
459  return Dart_NewStringFromCString(val);
460 }
461 
462 } // namespace tonic
463 
464 #endif // LIB_CONVERTER_TONIC_DART_CONVERTER_H_
static bool FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static unsigned long long FromDart(Dart_Handle handle)
static T FromDart(Dart_Handle handle)
static Dart_Handle NewList(Dart_Handle type_handle, intptr_t length)
#define TONIC_DCHECK
Definition: macros.h:32
static T FromDart(Dart_Handle handle)
Dart_Handle ToDart(const char *val)
static T FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static void SetReturnValue(Dart_NativeArguments args, const char *val)
static unsigned long long FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
Definition: ref_ptr.h:252
static Dart_Handle ToDart(const std::vector< ValueType > &val)
static void SetReturnValue(Dart_NativeArguments args, T val)
static std::vector< ValueType > FromDart(Dart_Handle handle)
static void SetReturnValue(Dart_NativeArguments args, const std::vector< ValueType > &val)
static Dart_Handle ToDart(unsigned long long val)
static Dart_Handle FromDart(Dart_Handle handle)
Dart_Handle LookupNonNullableType(const std::string &library_name, const std::string &type_name)
static const char * FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static std::vector< ValueType > FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static Dart_Handle ToDart(T val)
static T FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static Dart_Handle ToDart(const char *val)
Dart_Handle CreateZeroInitializedDartObject(Dart_Handle type_handle_or_null=::Dart_Null())
uint8_t value
static Dart_Handle FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static Dart_Handle ToDart(Dart_Handle val)
std::string StdStringFromDart(Dart_Handle handle)
static const char * FromDart(Dart_Handle handle)
size_t length
static Dart_Handle ToDart(const std::u16string &val)
static void SetReturnValue(Dart_NativeArguments args, Dart_Handle val)
static std::string FromDart(Dart_Handle handle)
typename DartConverterTypes< T >::ConverterType ConverterType
static std::string FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static void SetReturnValue(Dart_NativeArguments args, const std::string &val)
static void SetReturnValue(Dart_NativeArguments args, T val)
static void SetReturnValue(Dart_NativeArguments args, unsigned long long val)
static T FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static std::u16string FromDart(Dart_Handle handle)
typename DartConverterTypes< T >::ValueType ValueType
static Dart_Handle ToDart(T val)
static Dart_Handle ToDart(bool val)
static bool FromDart(Dart_Handle handle)
Dart_Handle ToDart(const T &object)
bool LogIfError(Dart_Handle handle)
Definition: dart_error.cc:15
Dart_Handle StdStringToDart(const std::string &val)
static Dart_Handle ToDart(const std::string &val)
static std::u16string FromArguments(Dart_NativeArguments args, int index, Dart_Handle &exception)
static void SetReturnValue(Dart_NativeArguments args, const std::u16string &val)
static void SetReturnValue(Dart_NativeArguments args, bool val)
Dart_Handle ToDartTypeHandle()