naev 0.11.5
array.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
4
6#include <limits.h>
7#include <stdio.h>
8#include <stdlib.h>
11#include "array.h"
12
13#include "nstring.h"
14
15void *_array_create_helper(size_t e_size, size_t capacity)
16{
17 if ( capacity <= 0 )
18 capacity = 1;
19
20 _private_container *c = malloc(sizeof(_private_container) + e_size * capacity);
21#if DEBUG_ARRAYS
22 c->_sentinel = ARRAY_SENTINEL;
23#endif
24 c->_reserved = capacity;
25 c->_size = 0;
26 return c->_array;
27}
28
29static void _array_resize_container(_private_container **c_, size_t e_size, size_t new_size)
30{
31 assert( new_size <= (size_t)INT_MAX );
32 _private_container *c = *c_;
33
34 if (new_size > c->_reserved) {
35 /* increases the reserved space */
36 do
37 c->_reserved *= 2;
38 while (new_size > c->_reserved);
39
40 c = realloc(c, sizeof(_private_container) + e_size * c->_reserved);
41 }
42
43 c->_size = new_size;
44 *c_ = c;
45}
46
47void _array_resize_helper(void **a, size_t e_size, size_t new_size)
48{
50 _array_resize_container(&c, e_size, new_size);
51 *a = c->_array;
52}
53
54void *_array_grow_helper(void **a, size_t e_size)
55{
57 if (c->_size == c->_reserved) {
58 /* Array full, doubles the reserved memory */
59 c->_reserved *= 2;
60 c = realloc(c, sizeof(_private_container) + e_size * c->_reserved);
61 *a = c->_array;
62 }
63
64 return c->_array + (c->_size++) * e_size;
65}
66
67void _array_erase_helper(void **a, size_t e_size, void *first, void *last)
68{
69 intptr_t diff = (char *)last - (char *)first;
70
71 if (!diff)
72 return;
73 /* copies the memory */
75 char *end = c->_array + c->_size * e_size;
76 memmove(first, last, end - (char *)last);
77
78 /* resizes the array */
79 assert("Invalid iterators passed to array erase" && (diff % e_size == 0));
80 c->_size -= diff / e_size;
81}
82
83void _array_shrink_helper(void **a, size_t e_size)
84{
86 if (c->_size != 0) {
87 c = realloc(c, sizeof(_private_container) + e_size * c->_size);
88 c->_reserved = c->_size;
89 } else {
90 c = realloc(c, sizeof(_private_container) + e_size);
91 c->_reserved = 1;
92 }
93 *a = c->_array;
94}
95
96void _array_free_helper(void *a)
97{
98 if (a==NULL)
99 return;
101}
102
103void *_array_copy_helper(size_t e_size, void *a)
104{
105 if (a==NULL)
106 return NULL;
108 void *copy = _array_create_helper( e_size, c->_size );
109 _array_resize_helper( &copy, e_size, c->_size );
110 return memcpy( copy, a, e_size * c->_size );
111}
112
113#if 0
114int main() {
115 const int size = 100;
116
117 int i;
118 int *array = array_create(int);
119
120 /* pushes some elements */
121 for (i = 0; i < size; ++i)
122 array_push_back(&array, i);
123 assert(array_size(array) == size);
124 assert(array_size(array) <= array_reserved(array));
125 for (i = 0; i < size; ++i)
126 assert(array[i] == i);
127
128 /* erases second half */
129 array_erase(&array, array + size / 2, array + size);
130 assert(array_size(array) == size / 2);
131 assert(array_size(array) <= array_reserved(array));
132 for (i = 0; i < size / 2; ++i)
133 assert(array[i] == i);
134
135 /* shrinks */
136 array_shrink(&array);
137 assert(array_size(array) == array_reserved(array));
138
139 /* pushes back second half */
140 for (i = size / 2; i < size; ++i)
141 array_push_back(&array, i);
142 assert(array_size(array) == size);
143 assert(array_size(array) <= array_reserved(array));
144 for (i = 0; i < size; ++i)
145 assert(array[i] == i);
146
147 /* erases middle half */
148 array_erase(&array, array + size / 4, array + 3 * size / 4);
149 assert(array_size(array) == size / 2);
150 assert(array_size(array) <= array_reserved(array));
151 for (i = 0; i < size / 4; ++i)
152 assert(array[i] == i);
153 for (; i < size / 2; ++i)
154 assert(array[i] == i + size / 2);
155
156 /* shrinks */
157 array_shrink(&array);
158 assert(array_size(array) == array_reserved(array));
159
160 /* erases one element */
161 array_erase(&array, array, array + 1);
162 assert(array_size(array) == size / 2 - 1);
163 for (i = 1; i < size / 4; ++i)
164 assert(array[i - 1] == i);
165 for (; i < size / 2; ++i)
166 assert(array[i - 1] == i + size / 2);
167
168 /* erases no elements */
169 array_erase(&array, array, array);
170 array_erase(&array, array + array_size(array), array + array_size(array));
171 assert(array_size(array) == size / 2 - 1);
172 for (i = 1; i < size / 4; ++i)
173 assert(array[i - 1] == i);
174 for (; i < size / 2; ++i)
175 assert(array[i - 1] == i + size / 2);
176
177 /* erases all elements */
178 array_erase(&array, array_begin(array), array_end(array));
179 assert(array_size(array) == 0);
180
181 /* shrinks */
182 array_shrink(&array);
183 assert(array_size(array) == 0);
184 assert(array_reserved(array) == 1);
185
186 return 0;
187}
188#endif
Provides macros to work with dynamic arrays.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
Definition array.h:202
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:140
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
static _private_container * _array_private_container(void *a)
Gets the container of an array.
Definition array.h:75
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:149
#define ARRAY_SENTINEL
Definition array.h:47
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
Definition array.h:194
#define array_reserved(array)
Returns number of elements reserved.
Definition array.h:187
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
int main(int argc, char **argv)
The entry point of Naev.
Definition naev.c:170
static const double c[]
Definition rng.c:264
Private container type for the arrays.
Definition array.h:52