2 * Copyright 2016 Xamarin, Inc.
4 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7 // Growable array implementation used by sgen-new-bridge and sgen-tarjan-bridge.
11 int capacity
; /* if negative, data points to another DynArray's data */
17 // IntArray supports an optimization (in sgen-new-bridge.c): If capacity is less than 0 it is a "copy" and does not own its buffer.
22 // PtrArray supports an optimization: If size is equal to 1 it is a "singleton" and data points to the single held item, not to a buffer.
32 dyn_array_init (DynArray
*da
)
40 dyn_array_uninit (DynArray
*da
, int elem_size
)
42 if (da
->capacity
< 0) {
47 if (da
->capacity
== 0)
50 sgen_free_internal_dynamic (da
->data
, elem_size
* da
->capacity
, INTERNAL_MEM_BRIDGE_DATA
);
55 dyn_array_empty (DynArray
*da
)
64 dyn_array_ensure_capacity_internal (DynArray
*da
, int capacity
, int elem_size
)
66 if (da
->capacity
<= 0)
68 while (capacity
> da
->capacity
)
71 return (char *)sgen_alloc_internal_dynamic (elem_size
* da
->capacity
, INTERNAL_MEM_BRIDGE_DATA
, TRUE
);
75 dyn_array_ensure_capacity (DynArray
*da
, int capacity
, int elem_size
)
77 int old_capacity
= da
->capacity
;
80 g_assert (capacity
> 0);
82 if (capacity
<= old_capacity
)
85 new_data
= dyn_array_ensure_capacity_internal (da
, capacity
, elem_size
);
86 memcpy (new_data
, da
->data
, elem_size
* da
->size
);
88 sgen_free_internal_dynamic (da
->data
, elem_size
* old_capacity
, INTERNAL_MEM_BRIDGE_DATA
);
93 dyn_array_is_copy (DynArray
*da
)
95 return da
->capacity
< 0;
99 dyn_array_ensure_independent (DynArray
*da
, int elem_size
)
101 if (!dyn_array_is_copy (da
))
103 dyn_array_ensure_capacity (da
, da
->size
, elem_size
);
104 g_assert (da
->capacity
> 0);
108 dyn_array_add (DynArray
*da
, int elem_size
)
112 dyn_array_ensure_capacity (da
, da
->size
+ 1, elem_size
);
114 p
= da
->data
+ da
->size
* elem_size
;
120 dyn_array_copy (DynArray
*dst
, DynArray
*src
, int elem_size
)
122 dyn_array_uninit (dst
, elem_size
);
127 dst
->size
= src
->size
;
129 dst
->data
= src
->data
;
134 dyn_array_int_init (DynIntArray
*da
)
136 dyn_array_init (&da
->array
);
140 dyn_array_int_uninit (DynIntArray
*da
)
142 dyn_array_uninit (&da
->array
, sizeof (int));
146 dyn_array_int_size (DynIntArray
*da
)
148 return da
->array
.size
;
153 dyn_array_int_empty (DynIntArray
*da
)
155 dyn_array_empty (&da
->array
);
160 dyn_array_int_add (DynIntArray
*da
, int x
)
162 int *p
= (int *)dyn_array_add (&da
->array
, sizeof (int));
167 dyn_array_int_get (DynIntArray
*da
, int x
)
169 return ((int*)da
->array
.data
)[x
];
174 dyn_array_int_set (DynIntArray
*da
, int idx
, int val
)
176 ((int*)da
->array
.data
)[idx
] = val
;
181 dyn_array_int_ensure_independent (DynIntArray
*da
)
183 dyn_array_ensure_independent (&da
->array
, sizeof (int));
187 dyn_array_int_copy (DynIntArray
*dst
, DynIntArray
*src
)
189 dyn_array_copy (&dst
->array
, &src
->array
, sizeof (int));
193 dyn_array_int_is_copy (DynIntArray
*da
)
195 return dyn_array_is_copy (&da
->array
);
201 dyn_array_ptr_init (DynPtrArray
*da
)
203 dyn_array_init (&da
->array
);
207 dyn_array_ptr_uninit (DynPtrArray
*da
)
209 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
210 if (da
->array
.capacity
== 1)
211 dyn_array_ptr_init (da
);
214 dyn_array_uninit (&da
->array
, sizeof (void*));
218 dyn_array_ptr_size (DynPtrArray
*da
)
220 return da
->array
.size
;
224 dyn_array_ptr_empty (DynPtrArray
*da
)
226 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
227 if (da
->array
.capacity
== 1)
228 dyn_array_ptr_init (da
);
231 dyn_array_empty (&da
->array
);
235 dyn_array_ptr_get (DynPtrArray
*da
, int x
)
237 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
238 if (da
->array
.capacity
== 1) {
240 return da
->array
.data
;
243 return ((void**)da
->array
.data
)[x
];
247 dyn_array_ptr_set (DynPtrArray
*da
, int x
, void *ptr
)
249 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
250 if (da
->array
.capacity
== 1) {
252 da
->array
.data
= ptr
;
256 ((void**)da
->array
.data
)[x
] = ptr
;
261 dyn_array_ptr_add (DynPtrArray
*da
, void *ptr
)
265 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
266 if (da
->array
.capacity
== 0) {
267 da
->array
.capacity
= 1;
269 p
= (void**)&da
->array
.data
;
270 } else if (da
->array
.capacity
== 1) {
271 void *ptr0
= da
->array
.data
;
273 dyn_array_init (&da
->array
);
274 p0
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
276 p
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
280 p
= (void **)dyn_array_add (&da
->array
, sizeof (void*));
285 #define dyn_array_ptr_push dyn_array_ptr_add
288 dyn_array_ptr_pop (DynPtrArray
*da
)
290 int size
= da
->array
.size
;
293 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
294 if (da
->array
.capacity
== 1) {
295 p
= dyn_array_ptr_get (da
, 0);
296 dyn_array_init (&da
->array
);
300 g_assert (da
->array
.capacity
> 1);
301 dyn_array_ensure_independent (&da
->array
, sizeof (void*));
302 p
= dyn_array_ptr_get (da
, size
- 1);
309 dyn_array_ptr_ensure_capacity (DynPtrArray
*da
, int capacity
)
311 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
312 if (capacity
== 1 && da
->array
.capacity
< 1) {
313 da
->array
.capacity
= 1;
314 } else if (da
->array
.capacity
== 1) // TODO size==1
318 void *ptr
= dyn_array_ptr_get (da
, 0);
319 da
->array
.data
= dyn_array_ensure_capacity_internal(&da
->array
, capacity
, sizeof (void*));
320 dyn_array_ptr_set (da
, 0, ptr
);
325 dyn_array_ensure_capacity (&da
->array
, capacity
, sizeof (void*));
330 dyn_array_ptr_set_all (DynPtrArray
*dst
, DynPtrArray
*src
)
332 const int copysize
= src
->array
.size
;
334 dyn_array_ptr_ensure_capacity (dst
, copysize
);
336 #ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
338 dyn_array_ptr_set (dst
, 0, dyn_array_ptr_get (src
, 0));
342 memcpy (dst
->array
.data
, src
->array
.data
, copysize
* sizeof (void*));
345 dst
->array
.size
= src
->array
.size
;