|
73 | 73 | (*(ptr_to_ary))->meta.size++; \ |
74 | 74 | } while (0) |
75 | 75 |
|
76 | | -/* Removes the element at idx and replaces it with the last element. |
77 | | - * ptr_to_ary and idx is evaluated multiple times. |
78 | | - * Warning: not bounds checked. |
79 | | - * |
80 | | - * void rb_darray_swap_remove(rb_darray(T) *ptr_to_ary, size_t idx); |
81 | | - */ |
82 | | -#define rb_darray_swap_remove(ptr_to_ary, idx) do { \ |
83 | | - size_t _darray_size = rb_darray_size(*(ptr_to_ary)); \ |
84 | | - if ((idx) != _darray_size - 1) { \ |
85 | | - (*(ptr_to_ary))->data[idx] = (*(ptr_to_ary))->data[_darray_size - 1]; \ |
86 | | - } \ |
87 | | - (*(ptr_to_ary))->meta.size--; \ |
88 | | -} while (0) |
89 | | - |
90 | 76 | // Iterate over items of the array in a for loop |
91 | 77 | // |
92 | 78 | #define rb_darray_foreach(ary, idx_name, elem_ptr_var) \ |
@@ -175,6 +161,18 @@ rb_darray_free(void *ary) |
175 | 161 | xfree(ary); |
176 | 162 | } |
177 | 163 |
|
| 164 | +void ruby_sized_xfree(void *x, size_t size); |
| 165 | + |
| 166 | +static inline void |
| 167 | +rb_darray_free_sized0(void *ary, size_t element_size) |
| 168 | +{ |
| 169 | + const rb_darray_meta_t *meta = ary; |
| 170 | + if (meta) { |
| 171 | + ruby_sized_xfree(ary, sizeof(*meta) + (element_size * meta->capa)); |
| 172 | + } |
| 173 | +} |
| 174 | +#define rb_darray_free_sized(ary, T) rb_darray_free_sized0((ary), sizeof(T)) |
| 175 | + |
178 | 176 | static inline void |
179 | 177 | rb_darray_free_without_gc(void *ary) |
180 | 178 | { |
@@ -205,13 +203,16 @@ rb_darray_calloc_mul_add_without_gc(size_t x, size_t y, size_t z) |
205 | 203 | return ptr; |
206 | 204 | } |
207 | 205 |
|
| 206 | +void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size); |
| 207 | + |
208 | 208 | /* Internal function. Like rb_xrealloc_mul_add. */ |
209 | 209 | static inline void * |
210 | | -rb_darray_realloc_mul_add(void *orig_ptr, size_t x, size_t y, size_t z) |
| 210 | +rb_darray_realloc_mul_add(void *orig_ptr, size_t capa, size_t element_size, size_t header_size) |
211 | 211 | { |
212 | | - size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z); |
| 212 | + size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(capa, element_size), header_size); |
| 213 | + size_t old_size = (rb_darray_capa(orig_ptr) * element_size) + header_size; // We know it won't overflow |
213 | 214 |
|
214 | | - void *ptr = xrealloc(orig_ptr, size); |
| 215 | + void *ptr = ruby_sized_xrealloc(orig_ptr, size, old_size); |
215 | 216 | RUBY_ASSERT(ptr != NULL); |
216 | 217 |
|
217 | 218 | return ptr; |
|
0 commit comments