Flutter Engine
The Flutter Engine
growable_array.h
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4// Defines growable array classes, that differ where they are allocated:
5// - GrowableArray: allocated on stack.
6// - ZoneGrowableArray: allocated in the zone.
7// - MallocGrowableArray: allocates using malloc/realloc; free is only called
8// at destruction.
9
10#ifndef RUNTIME_PLATFORM_GROWABLE_ARRAY_H_
11#define RUNTIME_PLATFORM_GROWABLE_ARRAY_H_
12
13#include "platform/allocation.h"
14#include "platform/utils.h"
15
16namespace dart {
17
18template <typename T, typename B, typename Allocator>
19class BaseGrowableArray : public B {
20 public:
21 explicit BaseGrowableArray(Allocator* allocator)
22 : length_(0), capacity_(0), data_(nullptr), allocator_(allocator) {}
23
24 BaseGrowableArray(intptr_t initial_capacity, Allocator* allocator)
25 : length_(0), capacity_(0), data_(nullptr), allocator_(allocator) {
26 if (initial_capacity > 0) {
27 capacity_ = Utils::RoundUpToPowerOfTwo(initial_capacity);
28 data_ = allocator_->template Alloc<T>(capacity_);
29 }
30 }
31
33 : length_(other.length_),
34 capacity_(other.capacity_),
35 data_(other.data_),
36 allocator_(other.allocator_) {
37 other.length_ = 0;
38 other.capacity_ = 0;
39 other.data_ = nullptr;
40 }
41
42 ~BaseGrowableArray() { allocator_->template Free<T>(data_, capacity_); }
43
45 intptr_t temp = other.length_;
46 other.length_ = length_;
47 length_ = temp;
48 temp = other.capacity_;
49 other.capacity_ = capacity_;
50 capacity_ = temp;
51 T* temp_data = other.data_;
52 other.data_ = data_;
53 data_ = temp_data;
54 Allocator* temp_allocator = other.allocator_;
55 other.allocator_ = allocator_;
56 allocator_ = temp_allocator;
57 return *this;
58 }
59
60 intptr_t length() const { return length_; }
61 T* data() const { return data_; }
62 bool is_empty() const { return length_ == 0; }
63
64 void TruncateTo(intptr_t length) {
65 ASSERT(length_ >= length);
66 length_ = length;
67 }
68
69 inline bool Contains(const T& other,
70 bool isEqual(const T&, const T&) = nullptr) const {
71 for (const auto& value : *this) {
72 if (value == other) {
73 // Value identity should imply isEqual.
74 ASSERT(isEqual == nullptr || isEqual(value, other));
75 return true;
76 }
77 if (isEqual != nullptr && isEqual(value, other)) {
78 return true;
79 }
80 }
81 return false;
82 }
83
84 void Add(const T& value) {
85 Resize(length() + 1);
86 Last() = value;
87 }
88
90 ASSERT(length_ > 0);
91 T& result = operator[](length_ - 1);
92 length_--;
93 return result;
94 }
95
96 T& operator[](intptr_t index) const {
97 ASSERT(0 <= index);
98 ASSERT(index < length_);
99 ASSERT(length_ <= capacity_);
100 return data_[index];
101 }
102
103 void FillWith(const T& value, intptr_t start, intptr_t length) {
104 ASSERT(start >= 0);
105 ASSERT(length >= 0);
106 ASSERT(start <= length_);
107
109 for (intptr_t i = 0; i < length; ++i) {
110 data_[start + i] = value;
111 }
112 }
113
114 void EnsureLength(intptr_t new_length, const T& default_value) {
115 const intptr_t old_length = length_;
116 if (old_length < new_length) {
117 Resize(new_length);
118 for (intptr_t i = old_length; i < new_length; ++i) {
119 (*this)[i] = default_value;
120 }
121 }
122 }
123
124 const T& At(intptr_t index) const { return operator[](index); }
125
126 T& Last() const {
127 ASSERT(length_ > 0);
128 return operator[](length_ - 1);
129 }
130
132 for (intptr_t i = 0; i < src.length(); i++) {
133 Add(src[i]);
134 }
135 }
136
137 void Clear() { length_ = 0; }
138
139 void InsertAt(intptr_t idx, const T& value) {
140 Resize(length() + 1);
141 for (intptr_t i = length_ - 2; i >= idx; i--) {
142 data_[i + 1] = data_[i];
143 }
144 data_[idx] = value;
145 }
146
147 void Reverse() {
148 for (intptr_t i = 0; i < length_ / 2; i++) {
149 const intptr_t j = length_ - 1 - i;
150 T temp = data_[i];
151 data_[i] = data_[j];
152 data_[j] = temp;
153 }
154 }
155
156 // Swap entries |i| and |j|.
157 void Swap(intptr_t i, intptr_t j) {
158 ASSERT(i >= 0);
159 ASSERT(j >= 0);
160 ASSERT(i < length_);
161 ASSERT(j < length_);
162 T temp = data_[i];
163 data_[i] = data_[j];
164 data_[j] = temp;
165 }
166
167 // NOTE: Does not preserve array order.
168 void RemoveAt(intptr_t i) {
169 ASSERT(i >= 0);
170 ASSERT(i < length_);
171 intptr_t last = length_ - 1;
172 if (i < last) {
173 Swap(i, last);
174 }
175 RemoveLast();
176 }
177
178 // Preserves array order.
179 void EraseAt(intptr_t idx) {
180 ASSERT(idx >= 0);
181 ASSERT(idx < length_);
182 for (intptr_t i = idx; i < length_ - 1; i++) {
183 data_[i] = data_[i + 1];
184 }
185 RemoveLast();
186 }
187
188 // The content is uninitialized after calling it.
189 void SetLength(intptr_t new_length);
190
191 // The content (if expanded) is uninitialized after calling it.
192 // The backing store (if expanded) will grow with by a power-of-2.
193 void Resize(intptr_t new_length);
194
195 // Sort the array in place.
196 inline void Sort(int compare(const T*, const T*));
197
198 void StealBuffer(T** buffer, intptr_t* length) {
199 *buffer = data_;
200 *length = length_;
201 data_ = nullptr;
202 length_ = 0;
203 capacity_ = 0;
204 }
205
206 T* begin() { return &data_[0]; }
207 const T* begin() const { return &data_[0]; }
208
209 T* end() { return &data_[length_]; }
210 const T* end() const { return &data_[length_]; }
211
212 private:
213 intptr_t length_;
214 intptr_t capacity_;
215 T* data_;
216 Allocator* allocator_; // Used to (re)allocate the array.
217
218 DISALLOW_COPY_AND_ASSIGN(BaseGrowableArray);
219};
220
221template <typename T, typename B, typename Allocator>
223 const T*)) {
224 // Avoid calling qsort with a null array.
225 if (length_ == 0) return;
226
227 typedef int (*CompareFunction)(const void*, const void*);
228 qsort(data_, length_, sizeof(T), reinterpret_cast<CompareFunction>(compare));
229}
230
231template <typename T, typename B, typename Allocator>
233 if (new_length > capacity_) {
234 intptr_t new_capacity = Utils::RoundUpToPowerOfTwo(new_length);
235 T* new_data =
236 allocator_->template Realloc<T>(data_, capacity_, new_capacity);
237 ASSERT(new_data != nullptr);
238 data_ = new_data;
239 capacity_ = new_capacity;
240 }
241 length_ = new_length;
242}
243
244template <typename T, typename B, typename Allocator>
246 if (new_length > capacity_) {
247 T* new_data = allocator_->template Alloc<T>(new_length);
248 ASSERT(new_data != nullptr);
249 data_ = new_data;
250 capacity_ = new_length;
251 }
252 length_ = new_length;
253}
254
255class Malloc : public AllStatic {
256 public:
257 template <class T>
258 static inline T* Alloc(intptr_t len) {
259 return reinterpret_cast<T*>(dart::malloc(len * sizeof(T)));
260 }
261
262 template <class T>
263 static inline T* Realloc(T* old_array, intptr_t old_len, intptr_t new_len) {
264 return reinterpret_cast<T*>(dart::realloc(old_array, new_len * sizeof(T)));
265 }
266
267 template <class T>
268 static inline void Free(T* old_array, intptr_t old_len) {
269 free(old_array);
270 }
271};
272
273template <typename T>
275 : public BaseGrowableArray<T, MallocAllocated, Malloc> {
276 public:
277 explicit MallocGrowableArray(intptr_t initial_capacity)
278 : BaseGrowableArray<T, MallocAllocated, Malloc>(initial_capacity,
279 nullptr) {}
282};
283
284} // namespace dart
285
286#endif // RUNTIME_PLATFORM_GROWABLE_ARRAY_H_
bool Contains(const T &other, bool isEqual(const T &, const T &)=nullptr) const
void Swap(intptr_t i, intptr_t j)
void TruncateTo(intptr_t length)
void EraseAt(intptr_t idx)
const T * begin() const
void FillWith(const T &value, intptr_t start, intptr_t length)
void AddArray(const BaseGrowableArray< T, B, Allocator > &src)
T & operator[](intptr_t index) const
void InsertAt(intptr_t idx, const T &value)
void Add(const T &value)
void Resize(intptr_t new_length)
void StealBuffer(T **buffer, intptr_t *length)
BaseGrowableArray & operator=(BaseGrowableArray &&other)
const T & At(intptr_t index) const
void SetLength(intptr_t new_length)
const T * end() const
void EnsureLength(intptr_t new_length, const T &default_value)
void RemoveAt(intptr_t i)
BaseGrowableArray(intptr_t initial_capacity, Allocator *allocator)
BaseGrowableArray(BaseGrowableArray &&other)
void Sort(int compare(const T *, const T *))
BaseGrowableArray(Allocator *allocator)
intptr_t length() const
MallocGrowableArray(intptr_t initial_capacity)
static void Free(T *old_array, intptr_t old_len)
static T * Realloc(T *old_array, intptr_t old_len, intptr_t new_len)
static T * Alloc(intptr_t len)
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
Definition: utils.h:135
#define ASSERT(E)
uint8_t value
GAsyncResult * result
Definition: dart_vm.cc:33
void * malloc(size_t size)
Definition: allocation.cc:19
void * realloc(void *ptr, size_t size)
Definition: allocation.cc:27
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
CompareFunction
Definition: formats.h:546
#define T
Definition: precompiler.cc:65
int compare(const void *untyped_lhs, const void *untyped_rhs)
Definition: skdiff.h:161