Flutter Engine
dart_byte_data.cc
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 
6 
7 #include <cstring>
8 
10 
11 namespace tonic {
12 
13 namespace {
14 
15 // For large objects it is more efficient to use an external typed data object
16 // with a buffer allocated outside the Dart heap.
17 const int kExternalSizeThreshold = 1000;
18 
19 void FreeFinalizer(void* isolate_callback_data,
20  Dart_WeakPersistentHandle handle,
21  void* peer) {
22  free(peer);
23 }
24 
25 } // anonymous namespace
26 
27 Dart_Handle DartByteData::Create(const void* data, size_t length) {
28  if (length < kExternalSizeThreshold) {
29  auto handle = DartByteData{data, length}.dart_handle();
30  // The destructor should release the typed data.
31  return handle;
32  } else {
33  void* buf = ::malloc(length);
34  TONIC_DCHECK(buf);
35  ::memcpy(buf, data, length);
36  return Dart_NewExternalTypedDataWithFinalizer(
37  Dart_TypedData_kByteData, buf, length, buf, length, FreeFinalizer);
38  }
39 }
40 
42  : data_(nullptr), length_in_bytes_(0), dart_handle_(nullptr) {}
43 
44 DartByteData::DartByteData(const void* data, size_t length)
45  : data_(nullptr),
46  length_in_bytes_(0),
47  dart_handle_(Dart_NewTypedData(Dart_TypedData_kByteData, length)) {
48  if (!Dart_IsError(dart_handle_)) {
49  Dart_TypedData_Type type;
50  auto acquire_result = Dart_TypedDataAcquireData(dart_handle_, &type, &data_,
51  &length_in_bytes_);
52 
53  if (!Dart_IsError(acquire_result)) {
54  ::memcpy(data_, data, length_in_bytes_);
55  }
56  }
57 }
58 
59 DartByteData::DartByteData(Dart_Handle list)
60  : data_(nullptr), length_in_bytes_(0), dart_handle_(list) {
61  if (Dart_IsNull(list))
62  return;
63 
64  Dart_TypedData_Type type;
65  Dart_TypedDataAcquireData(list, &type, &data_, &length_in_bytes_);
66  TONIC_DCHECK(!LogIfError(list));
67  if (type != Dart_TypedData_kByteData)
68  Dart_ThrowException(ToDart("Non-genuine ByteData passed to engine."));
69 }
70 
72  : data_(other.data_),
73  length_in_bytes_(other.length_in_bytes_),
74  dart_handle_(other.dart_handle_) {
75  other.data_ = nullptr;
76  other.dart_handle_ = nullptr;
77 }
78 
80  Release();
81 }
82 
83 std::vector<char> DartByteData::Copy() const {
84  const char* ptr = static_cast<const char*>(data_);
85  return std::vector<char>(ptr, ptr + length_in_bytes_);
86 }
87 
88 void DartByteData::Release() const {
89  if (data_) {
90  Dart_TypedDataReleaseData(dart_handle_);
91  data_ = nullptr;
92  }
93 }
94 
96  Dart_NativeArguments args,
97  int index,
98  Dart_Handle& exception) {
99  Dart_Handle data = Dart_GetNativeArgument(args, index);
100  TONIC_DCHECK(!LogIfError(data));
101  return DartByteData(data);
102 }
103 
105  DartByteData val) {
106  Dart_SetReturnValue(args, val.dart_handle());
107 }
108 
109 } // namespace tonic
G_BEGIN_DECLS FlValue * args
const void * data() const
#define TONIC_DCHECK
Definition: macros.h:32
std::vector< char > Copy() const
size_t length
Dart_Handle dart_handle() const
static Dart_Handle Create(const void *data, size_t length)
Dart_Handle ToDart(const T &object)
bool LogIfError(Dart_Handle handle)
Definition: dart_error.cc:15
void Release() const