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 | #include "tonic/typed_data/typed_list.h" |
6 | |
7 | #include <cstring> |
8 | |
9 | #include "tonic/logging/dart_error.h" |
10 | |
11 | namespace tonic { |
12 | |
13 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
14 | TypedList<kTypeName, ElemType>::TypedList() |
15 | : data_(nullptr), num_elements_(0), dart_handle_(nullptr) {} |
16 | |
17 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
18 | TypedList<kTypeName, ElemType>::TypedList(Dart_Handle list) |
19 | : data_(nullptr), num_elements_(0), dart_handle_(list) { |
20 | if (Dart_IsNull(list)) |
21 | return; |
22 | |
23 | Dart_TypedData_Type type; |
24 | Dart_TypedDataAcquireData(list, &type, reinterpret_cast<void**>(&data_), |
25 | &num_elements_); |
26 | TONIC_DCHECK(!LogIfError(list)); |
27 | if (type != kTypeName) |
28 | Dart_ThrowException(ToDart("Non-genuine TypedData passed to engine." )); |
29 | } |
30 | |
31 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
32 | TypedList<kTypeName, ElemType>::TypedList( |
33 | TypedList<kTypeName, ElemType>&& other) |
34 | : data_(other.data_), |
35 | num_elements_(other.num_elements_), |
36 | dart_handle_(other.dart_handle_) { |
37 | other.data_ = nullptr; |
38 | other.num_elements_ = 0; |
39 | other.dart_handle_ = nullptr; |
40 | } |
41 | |
42 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
43 | TypedList<kTypeName, ElemType>::~TypedList() { |
44 | Release(); |
45 | } |
46 | |
47 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
48 | void TypedList<kTypeName, ElemType>::Release() { |
49 | if (data_) { |
50 | Dart_TypedDataReleaseData(dart_handle_); |
51 | data_ = nullptr; |
52 | num_elements_ = 0; |
53 | dart_handle_ = nullptr; |
54 | } |
55 | } |
56 | |
57 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
58 | TypedList<kTypeName, ElemType> |
59 | DartConverter<TypedList<kTypeName, ElemType>>::FromArguments( |
60 | Dart_NativeArguments args, |
61 | int index, |
62 | Dart_Handle& exception) { |
63 | Dart_Handle list = Dart_GetNativeArgument(args, index); |
64 | TONIC_DCHECK(!LogIfError(list)); |
65 | return TypedList<kTypeName, ElemType>(list); |
66 | } |
67 | |
68 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
69 | void DartConverter<TypedList<kTypeName, ElemType>>::SetReturnValue( |
70 | Dart_NativeArguments args, |
71 | TypedList<kTypeName, ElemType> val) { |
72 | Dart_Handle result = val.dart_handle(); |
73 | val.Release(); // Must release acquired typed data before calling Dart API. |
74 | Dart_SetReturnValue(args, result); |
75 | } |
76 | |
77 | template <Dart_TypedData_Type kTypeName, typename ElemType> |
78 | Dart_Handle DartConverter<TypedList<kTypeName, ElemType>>::ToDart( |
79 | const ElemType* buffer, |
80 | unsigned int length) { |
81 | const intptr_t buffer_length = static_cast<intptr_t>(length); |
82 | Dart_Handle array = Dart_NewTypedData(kTypeName, buffer_length); |
83 | TONIC_DCHECK(!LogIfError(array)); |
84 | { |
85 | Dart_TypedData_Type type; |
86 | void* data = nullptr; |
87 | intptr_t data_length = 0; |
88 | Dart_TypedDataAcquireData(array, &type, &data, &data_length); |
89 | TONIC_CHECK(type == kTypeName); |
90 | TONIC_CHECK(data); |
91 | TONIC_CHECK(data_length == buffer_length); |
92 | std::memmove(data, buffer, data_length * sizeof(ElemType)); |
93 | Dart_TypedDataReleaseData(array); |
94 | } |
95 | return array; |
96 | } |
97 | |
98 | #define TONIC_TYPED_DATA_DEFINE(name, type) \ |
99 | template class TypedList<Dart_TypedData_k##name, type>; \ |
100 | template struct DartConverter<name##List>; |
101 | |
102 | TONIC_TYPED_DATA_FOREACH(TONIC_TYPED_DATA_DEFINE) |
103 | |
104 | #undef TONIC_TYPED_DATA_DEFINE |
105 | |
106 | } // namespace tonic |
107 | |