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