always pass vectors by reference
[cvector.git] / vec_def.h
blobbaa68a28c690dc03e02ec1bcab190ac108f144c6
1 #ifndef VEC_DEF_H_
2 #define VEC_DEF_H_
4 #include "vec_decl.h"
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <assert.h>
11 #ifdef NDEBUG
12 #define DEBUG(...)
13 #else
14 #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
15 #endif
17 #define DEFINE_VECTOR(_typename_, _ctype_) \
18 void _typename_##_realloc(_typename_* const vec) { \
19 if (vec->data == NULL) { \
20 if (0 == vec->capacity) { \
21 DEBUG("REALLOC NULL\n"); \
22 } else { \
23 DEBUG("REALLOC NULL -> %zu (%zub)", vec->capacity, (vec->capacity * sizeof(_ctype_))); \
24 if ((vec->data = malloc(vec->capacity * sizeof(_ctype_))) == NULL) { \
25 DEBUG("\nMemory reallocation failure\n"); \
26 exit(EXIT_FAILURE); \
27 } \
28 DEBUG(" [%p]\n", (void*) vec->data); \
29 assert(vec->data != NULL); \
30 } \
31 } else { \
32 if (0 == vec->capacity) { \
33 DEBUG("REALLOC [%p] -> NULL\n", (void*) vec->data); \
34 free(vec->data); \
35 vec->data = NULL; \
36 } else { \
37 DEBUG("REALLOC [%p] -> %zu (%zub)", (void*) vec->data, vec->capacity, (vec->capacity * sizeof(_ctype_))); \
38 if ((vec->data = realloc(vec->data, vec->capacity * sizeof(_ctype_))) == NULL) { \
39 DEBUG("\nMemory reallocation failure\n"); \
40 exit(EXIT_FAILURE); \
41 } \
42 DEBUG(" [%p]\n", (void*) vec->data); \
43 assert(vec->data != NULL); \
44 } \
45 } \
46 } \
48 void _typename_##_malloc(_typename_* const vec) { \
49 assert(vec->data == NULL); \
50 if (0 == vec->capacity) { \
51 DEBUG("MALLOC NULL\n"); \
52 vec->data = NULL; \
53 } else { \
54 DEBUG("MALLOC %zu (%zub)", vec->capacity, (vec->capacity * sizeof(_ctype_))); \
55 if ((vec->data = malloc(vec->capacity * sizeof(_ctype_))) == NULL) { \
56 DEBUG("\nMemory allocation failure\n"); \
57 exit(EXIT_FAILURE); \
58 } \
59 DEBUG(" [%p]\n", (void*) vec->data); \
60 assert(vec->data != NULL); \
61 } \
62 } \
64 VECTOR_CREATE_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
65 _typename_ vec = { 0, size, NULL }; \
66 _typename_##_malloc(&vec); \
67 return vec; \
68 } \
70 VECTOR_FREE_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
71 if (vec->data == NULL) { \
72 DEBUG("FREE NULL\n"); \
73 } else { \
74 DEBUG("FREE [%p]\n", (void*) vec->data); \
75 free(vec->data); \
76 vec->data = NULL; \
77 } \
78 } \
80 VECTOR_GETV_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
81 assert(index < vec->size); \
82 return vec->data[index]; \
83 } \
85 VECTOR_GETP_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
86 assert(index < vec->size); \
87 return &vec->data[index]; \
88 } \
90 VECTOR_SET_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
91 assert(index < vec->size); \
92 vec->data[index] = val; \
93 } \
95 VECTOR_PUSH_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
96 vec->size++; \
97 if (vec->size > vec->capacity) { \
98 vec->capacity = vec->capacity * 2 + 1; \
99 _typename_##_realloc(vec); \
101 vec->data[vec->size - 1] = val; \
104 VECTOR_PRINT_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
105 char const* const sep = ((separator == NULL) ? ", " : separator); \
106 printf("{ "); \
107 for (size_t i=0; i<vec->size; i++) { \
108 printf(element_format, vec->data[i]); \
109 if (i != (vec->size - 1)) { \
110 printf("%s", sep); \
113 printf(" }"); \
116 VECTOR_FRONT_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
117 assert(vec->size > 0); \
118 return vec->data[0]; \
121 VECTOR_BACK_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
122 assert(vec->size > 0); \
123 return vec->data[vec->size - 1]; \
126 VECTOR_DATA_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
127 return vec->data; \
130 VECTOR_EMPTY_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
131 return (vec->size == 0) ? true : false; \
134 VECTOR_SHRINK_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
135 if (vec->size != vec->capacity) { \
136 vec->capacity = vec->size; \
137 _typename_##_realloc(vec); \
141 VECTOR_CLEAR_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
142 vec->size = 0; \
145 VECTOR_INSERT_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
146 assert(pos < vec->size); \
147 assert(vec->size > 0); \
148 assert(vec->data != NULL); \
149 size_t i = vec->size; \
150 vec->size++; \
151 if (vec->size > vec->capacity) { \
152 vec->capacity = vec->capacity * 2 + 1; \
153 _typename_##_realloc(vec); \
155 for (; i>pos; i--) { \
156 vec->data[i] = vec->data[i-1]; \
158 vec->data[pos] = elem; \
161 VECTOR_ERASE_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
162 assert(pos < vec->size); \
163 assert(vec->size > 0); \
164 assert(vec->data != NULL); \
165 vec->size--; \
166 for (size_t i=pos; i<vec->size; i++) { \
167 vec->data[i] = vec->data[i+1]; \
171 VECTOR_POP_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
172 assert(vec->size > 0); \
173 assert(vec->data != NULL); \
174 return vec->data[--vec->size]; \
177 VECTOR_SWAP_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
178 _typename_ tmp = *vec1; \
179 *vec1 = *vec2; \
180 *vec2 = tmp; \
183 VECTOR_INSERT_VECTOR_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
184 assert(pos < vec->size); \
185 assert(vec->size > 0); \
186 assert(vec->data != NULL); \
187 assert(((ins_vec->capacity > 0) && (ins_vec->data != NULL) \
188 && (((vec->data + vec->capacity - 1) < ins_vec->data) \
189 || (vec->data > (ins_vec->data + ins_vec->capacity - 1)))) \
190 || ((ins_vec->capacity == 0) && (ins_vec->data != NULL))); \
191 _typename_##_insert_array(vec, pos, ins_vec->data, ins_vec->size); \
194 VECTOR_INSERT_ARRAY_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
195 assert(pos < vec->size); \
196 assert(vec->size > 0); \
197 assert(vec->data != NULL); \
198 assert(((array_size > 0) && (array != NULL) \
199 && (((vec->data + vec->capacity - 1) < array) \
200 || (vec->data > (array + array_size - 1)))) \
201 || ((array_size == 0) && (array != NULL))); \
202 vec->size += array_size; \
203 if (vec->size > vec->capacity) { \
204 vec->capacity = vec->size * 2; \
205 _typename_##_realloc(vec); \
207 for (size_t i=0; i<array_size; i++) { \
208 vec->data[(array_size-1)+pos+i] = vec->data[pos+i]; \
209 vec->data[pos+i] = array[i]; \
213 VECTOR_PUSH_ARRAY_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
214 assert(((array_size == 0) && (array == NULL)) \
215 || ((array_size > 0) && (array != NULL))); \
216 size_t pos = vec->size; \
217 vec->size += array_size; \
218 if (vec->size > vec->capacity) { \
219 vec->capacity = vec->size * 2; \
220 _typename_##_realloc(vec); \
222 for (size_t i=0; i<array_size; i++) { \
223 vec->data[i+pos] = array[i]; \
227 VECTOR_PUSH_VECTOR_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
228 assert(push_vec->data != NULL); \
229 assert(vec->data != NULL); \
230 _typename_##_push_array(vec, push_vec->data, push_vec->size); \
233 VECTOR_COPY_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
234 assert(vec->data != NULL); \
235 _typename_ res; \
236 res.size = vec->size; \
237 res.capacity = vec->capacity; \
238 res.data = NULL; \
239 _typename_##_malloc(&res); \
240 memcpy(res.data, vec->data, (vec->size * sizeof(_ctype_))); \
241 return res; \
244 VECTOR_EQV_FUNCTION_PROTOTYPE(_typename_, _ctype_) { \
245 assert((vec1->data != NULL) && (vec2->data != NULL)); \
246 if (vec1->size != vec2->size) { \
247 return false; \
249 for(size_t i=0; i<vec1->size; i++) { \
250 if (!eqv(vec1->data[i], vec2->data[i])) { \
251 return false; \
254 return true; \
257 #endif // VEC_DEF_H_