CVector 4.3.0
A C++ style vector library in strict ANSI C (C89)
Loading...
Searching...
No Matches
cvector_macro.h
Go to the documentation of this file.
1/*
2
3CVector 4.2.1 MIT Licensed vector (dynamic array) library in strict C89
4http://www.robertwinkler.com/projects/cvector.html
5http://www.robertwinkler.com/projects/cvector/
6
7Besides the docs and all the Doxygen comments, see cvector_tests.c for
8examples of how to use it or look at any of these other projects for
9more practical examples:
10
11https://github.com/rswinkle/C_Interpreter
12https://github.com/rswinkle/CPIM2
13https://github.com/rswinkle/spelling_game
14https://github.com/rswinkle/c_bigint
15http://portablegl.com/
16
17The MIT License (MIT)
18
19Copyright (c) 2011-2025 Robert Winkler
20
21Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
22documentation files (the "Software"), to deal in the Software without restriction, including without limitation
23the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
24to permit persons to whom the Software is furnished to do so, subject to the following conditions:
25
26The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
27
28THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
29TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
31CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
32IN THE SOFTWARE.
33*/
34
35#ifndef CVECTOR_MACRO_H
36#define CVECTOR_MACRO_H
37
38#if defined(CVEC_MALLOC) && defined(CVEC_FREE) && defined(CVEC_REALLOC)
39/* ok */
40#elif !defined(CVEC_MALLOC) && !defined(CVEC_FREE) && !defined(CVEC_REALLOC)
41/* ok */
42#else
43#error "Must define all or none of CVEC_MALLOC, CVEC_FREE, and CVEC_REALLOC."
44#endif
45
46#ifndef CVEC_MALLOC
47#include <stdlib.h>
48#define CVEC_MALLOC(sz) malloc(sz)
49#define CVEC_REALLOC(p, sz) realloc(p, sz)
50#define CVEC_FREE(p) free(p)
51#endif
52
53#ifndef CVEC_MEMMOVE
54#include <string.h>
55#define CVEC_MEMMOVE(dst, src, sz) memmove(dst, src, sz)
56#endif
57
58#ifndef CVEC_ASSERT
59#include <assert.h>
60#define CVEC_ASSERT(x) assert(x)
61#endif
62
63#ifndef CVEC_SIZE_TYPE
64#include <stdlib.h>
65#define CVEC_SIZE_TYPE size_t
66#endif
67
68#ifndef CVEC_SZ
69#define CVEC_SZ
71#endif
72
73
74/*
75 User can optionally wrap CVEC_NEW_DECLS(2) with extern "C"
76 since it's not part of the macro
77*/
78
79#define CVEC_NEW_DECLS(TYPE) \
80 typedef struct cvector_##TYPE { \
81 TYPE* a; \
82 cvec_sz size; \
83 cvec_sz capacity; \
84 } cvector_##TYPE; \
85 \
86 extern cvec_sz CVEC_##TYPE##_SZ; \
87 \
88 int cvec_##TYPE(cvector_##TYPE* vec, cvec_sz size, cvec_sz capacity); \
89 int cvec_init_##TYPE(cvector_##TYPE* vec, TYPE* vals, cvec_sz num); \
90 \
91 cvector_##TYPE* cvec_##TYPE##_heap(cvec_sz size, cvec_sz capacity); \
92 cvector_##TYPE* cvec_init_##TYPE##_heap(TYPE* vals, cvec_sz num); \
93 \
94 int cvec_copyc_##TYPE(void* dest, void* src); \
95 int cvec_copy_##TYPE(cvector_##TYPE* dest, cvector_##TYPE* src); \
96 \
97 int cvec_push_##TYPE(cvector_##TYPE* vec, TYPE a); \
98 TYPE cvec_pop_##TYPE(cvector_##TYPE* vec); \
99 \
100 int cvec_extend_##TYPE(cvector_##TYPE* vec, cvec_sz num); \
101 int cvec_insert_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE a); \
102 int cvec_insert_array_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num); \
103 TYPE cvec_replace_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE a); \
104 void cvec_erase_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end); \
105 int cvec_reserve_##TYPE(cvector_##TYPE* vec, cvec_sz size); \
106 int cvec_set_cap_##TYPE(cvector_##TYPE* vec, cvec_sz size); \
107 void cvec_set_val_sz_##TYPE(cvector_##TYPE* vec, TYPE val); \
108 void cvec_set_val_cap_##TYPE(cvector_##TYPE* vec, TYPE val); \
109 \
110 TYPE* cvec_back_##TYPE(cvector_##TYPE* vec); \
111 \
112 void cvec_clear_##TYPE(cvector_##TYPE* vec); \
113 void cvec_free_##TYPE##_heap(void* vec); \
114 void cvec_free_##TYPE(void* vec);
115
116#define CVEC_NEW_DEFS(TYPE, RESIZE_MACRO) \
117 cvec_sz CVEC_##TYPE##_SZ = 50; \
118 \
119 cvector_##TYPE* cvec_##TYPE##_heap(cvec_sz size, cvec_sz capacity) \
120 { \
121 cvector_##TYPE* vec; \
122 if (!(vec = (cvector_##TYPE*)CVEC_MALLOC(sizeof(cvector_##TYPE)))) { \
123 CVEC_ASSERT(vec != NULL); \
124 return NULL; \
125 } \
126 \
127 vec->size = size; \
128 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) \
129 ? capacity \
130 : vec->size + CVEC_##TYPE##_SZ; \
131 \
132 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
133 CVEC_ASSERT(vec->a != NULL); \
134 CVEC_FREE(vec); \
135 return NULL; \
136 } \
137 \
138 return vec; \
139 } \
140 \
141 cvector_##TYPE* cvec_init_##TYPE##_heap(TYPE* vals, cvec_sz num) \
142 { \
143 cvector_##TYPE* vec; \
144 \
145 if (!(vec = (cvector_##TYPE*)CVEC_MALLOC(sizeof(cvector_##TYPE)))) { \
146 CVEC_ASSERT(vec != NULL); \
147 return NULL; \
148 } \
149 \
150 vec->capacity = num + CVEC_##TYPE##_SZ; \
151 vec->size = num; \
152 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
153 CVEC_ASSERT(vec->a != NULL); \
154 CVEC_FREE(vec); \
155 return NULL; \
156 } \
157 \
158 CVEC_MEMMOVE(vec->a, vals, sizeof(TYPE) * num); \
159 \
160 return vec; \
161 } \
162 \
163 int cvec_##TYPE(cvector_##TYPE* vec, cvec_sz size, cvec_sz capacity) \
164 { \
165 vec->size = size; \
166 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) \
167 ? capacity \
168 : vec->size + CVEC_##TYPE##_SZ; \
169 \
170 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
171 CVEC_ASSERT(vec->a != NULL); \
172 vec->size = vec->capacity = 0; \
173 return 0; \
174 } \
175 \
176 return 1; \
177 } \
178 \
179 int cvec_init_##TYPE(cvector_##TYPE* vec, TYPE* vals, cvec_sz num) \
180 { \
181 vec->capacity = num + CVEC_##TYPE##_SZ; \
182 vec->size = num; \
183 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
184 CVEC_ASSERT(vec->a != NULL); \
185 vec->size = vec->capacity = 0; \
186 return 0; \
187 } \
188 \
189 CVEC_MEMMOVE(vec->a, vals, sizeof(TYPE) * num); \
190 \
191 return 1; \
192 } \
193 \
194 int cvec_copyc_##TYPE(void* dest, void* src) \
195 { \
196 cvector_##TYPE* vec1 = (cvector_##TYPE*)dest; \
197 cvector_##TYPE* vec2 = (cvector_##TYPE*)src; \
198 \
199 vec1->a = NULL; \
200 vec1->size = 0; \
201 vec1->capacity = 0; \
202 \
203 return cvec_copy_##TYPE(vec1, vec2); \
204 } \
205 \
206 int cvec_copy_##TYPE(cvector_##TYPE* dest, cvector_##TYPE* src) \
207 { \
208 TYPE* tmp = NULL; \
209 if (!(tmp = (TYPE*)CVEC_REALLOC(dest->a, src->capacity*sizeof(TYPE)))) { \
210 CVEC_ASSERT(tmp != NULL); \
211 return 0; \
212 } \
213 dest->a = tmp; \
214 \
215 CVEC_MEMMOVE(dest->a, src->a, src->size*sizeof(TYPE)); \
216 dest->size = src->size; \
217 dest->capacity = src->capacity; \
218 return 1; \
219 } \
220 \
221 int cvec_push_##TYPE(cvector_##TYPE* vec, TYPE a) \
222 { \
223 TYPE* tmp; \
224 cvec_sz tmp_sz; \
225 if (vec->capacity > vec->size) { \
226 vec->a[vec->size++] = a; \
227 } else { \
228 tmp_sz = RESIZE_MACRO(vec->capacity); \
229 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
230 CVEC_ASSERT(tmp != NULL); \
231 return 0; \
232 } \
233 vec->a = tmp; \
234 vec->a[vec->size++] = a; \
235 vec->capacity = tmp_sz; \
236 } \
237 return 1; \
238 } \
239 \
240 TYPE cvec_pop_##TYPE(cvector_##TYPE* vec) { return vec->a[--vec->size]; } \
241 \
242 TYPE* cvec_back_##TYPE(cvector_##TYPE* vec) { return &vec->a[vec->size - 1]; } \
243 \
244 int cvec_extend_##TYPE(cvector_##TYPE* vec, cvec_sz num) \
245 { \
246 TYPE* tmp; \
247 cvec_sz tmp_sz; \
248 if (vec->capacity < vec->size + num) { \
249 tmp_sz = vec->capacity + num + CVEC_##TYPE##_SZ; \
250 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
251 CVEC_ASSERT(tmp != NULL); \
252 return 0; \
253 } \
254 vec->a = tmp; \
255 vec->capacity = tmp_sz; \
256 } \
257 \
258 vec->size += num; \
259 return 1; \
260 } \
261 \
262 int cvec_insert_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE a) \
263 { \
264 TYPE* tmp; \
265 cvec_sz tmp_sz; \
266 if (vec->capacity > vec->size) { \
267 CVEC_MEMMOVE(&vec->a[i + 1], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
268 vec->a[i] = a; \
269 } else { \
270 tmp_sz = RESIZE_MACRO(vec->capacity); \
271 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
272 CVEC_ASSERT(tmp != NULL); \
273 return 0; \
274 } \
275 vec->a = tmp; \
276 CVEC_MEMMOVE(&vec->a[i + 1], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
277 vec->a[i] = a; \
278 vec->capacity = tmp_sz; \
279 } \
280 \
281 vec->size++; \
282 return 1; \
283 } \
284 \
285 int cvec_insert_array_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num) \
286 { \
287 TYPE* tmp; \
288 cvec_sz tmp_sz; \
289 if (vec->capacity < vec->size + num) { \
290 tmp_sz = vec->capacity + num + CVEC_##TYPE##_SZ; \
291 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
292 CVEC_ASSERT(tmp != NULL); \
293 return 0; \
294 } \
295 vec->a = tmp; \
296 vec->capacity = tmp_sz; \
297 } \
298 \
299 CVEC_MEMMOVE(&vec->a[i + num], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
300 CVEC_MEMMOVE(&vec->a[i], a, num * sizeof(TYPE)); \
301 vec->size += num; \
302 return 1; \
303 } \
304 \
305 TYPE cvec_replace_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE a) \
306 { \
307 TYPE tmp = vec->a[i]; \
308 vec->a[i] = a; \
309 return tmp; \
310 } \
311 \
312 void cvec_erase_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end) \
313 { \
314 cvec_sz d = end - start + 1; \
315 CVEC_MEMMOVE(&vec->a[start], &vec->a[end + 1], (vec->size - 1 - end) * sizeof(TYPE)); \
316 vec->size -= d; \
317 } \
318 \
319 int cvec_reserve_##TYPE(cvector_##TYPE* vec, cvec_sz size) \
320 { \
321 TYPE* tmp; \
322 if (vec->capacity < size) { \
323 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * (size + CVEC_##TYPE##_SZ)))) { \
324 CVEC_ASSERT(tmp != NULL); \
325 return 0; \
326 } \
327 vec->a = tmp; \
328 vec->capacity = size + CVEC_##TYPE##_SZ; \
329 } \
330 return 1; \
331 } \
332 \
333 int cvec_set_cap_##TYPE(cvector_##TYPE* vec, cvec_sz size) \
334 { \
335 TYPE* tmp; \
336 if (size < vec->size) { \
337 vec->size = size; \
338 } \
339 \
340 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * size))) { \
341 CVEC_ASSERT(tmp != NULL); \
342 return 0; \
343 } \
344 vec->a = tmp; \
345 vec->capacity = size; \
346 return 1; \
347 } \
348 \
349 void cvec_set_val_sz_##TYPE(cvector_##TYPE* vec, TYPE val) \
350 { \
351 cvec_sz i; \
352 for (i = 0; i < vec->size; i++) { \
353 vec->a[i] = val; \
354 } \
355 } \
356 \
357 void cvec_set_val_cap_##TYPE(cvector_##TYPE* vec, TYPE val) \
358 { \
359 cvec_sz i; \
360 for (i = 0; i < vec->capacity; i++) { \
361 vec->a[i] = val; \
362 } \
363 } \
364 \
365 void cvec_clear_##TYPE(cvector_##TYPE* vec) { vec->size = 0; } \
366 \
367 void cvec_free_##TYPE##_heap(void* vec) \
368 { \
369 cvector_##TYPE* tmp = (cvector_##TYPE*)vec; \
370 if (!tmp) return; \
371 CVEC_FREE(tmp->a); \
372 CVEC_FREE(tmp); \
373 } \
374 \
375 void cvec_free_##TYPE(void* vec) \
376 { \
377 cvector_##TYPE* tmp = (cvector_##TYPE*)vec; \
378 CVEC_FREE(tmp->a); \
379 tmp->a = NULL; \
380 tmp->size = 0; \
381 tmp->capacity = 0; \
382 }
383
384#define CVEC_NEW_DECLS2(TYPE) \
385 typedef struct cvector_##TYPE { \
386 TYPE* a; \
387 cvec_sz size; \
388 cvec_sz capacity; \
389 void (*elem_free)(void*); \
390 int (*elem_init)(void*, void*); \
391 } cvector_##TYPE; \
392 \
393 extern cvec_sz CVEC_##TYPE##_SZ; \
394 \
395 int cvec_##TYPE(cvector_##TYPE* vec, cvec_sz size, cvec_sz capacity, void (*elem_free)(void*), \
396 int (*elem_init)(void*, void*)); \
397 int cvec_init_##TYPE(cvector_##TYPE* vec, TYPE* vals, cvec_sz num, void (*elem_free)(void*), \
398 int (*elem_init)(void*, void*)); \
399 \
400 cvector_##TYPE* cvec_##TYPE##_heap(cvec_sz size, cvec_sz capacity, void (*elem_free)(void*), \
401 int (*elem_init)(void*, void*)); \
402 cvector_##TYPE* cvec_init_##TYPE##_heap(TYPE* vals, cvec_sz num, void (*elem_free)(void*), \
403 int (*elem_init)(void*, void*)); \
404 \
405 int cvec_copyc_##TYPE(void* dest, void* src); \
406 int cvec_copy_##TYPE(cvector_##TYPE* dest, cvector_##TYPE* src); \
407 \
408 int cvec_push_##TYPE(cvector_##TYPE* vec, TYPE* val); \
409 void cvec_pop_##TYPE(cvector_##TYPE* vec, TYPE* ret); \
410 \
411 int cvec_pushm_##TYPE(cvector_##TYPE* vec, TYPE* a); \
412 void cvec_popm_##TYPE(cvector_##TYPE* vec, TYPE* ret); \
413 int cvec_insertm_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a); \
414 int cvec_insert_arraym_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num); \
415 void cvec_replacem_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, TYPE* ret); \
416 \
417 int cvec_extend_##TYPE(cvector_##TYPE* vec, cvec_sz num); \
418 int cvec_insert_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a); \
419 int cvec_insert_array_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num); \
420 int cvec_replace_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, TYPE* ret); \
421 void cvec_erase_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end); \
422 void cvec_remove_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end); \
423 int cvec_reserve_##TYPE(cvector_##TYPE* vec, cvec_sz size); \
424 int cvec_set_cap_##TYPE(cvector_##TYPE* vec, cvec_sz size); \
425 int cvec_set_val_sz_##TYPE(cvector_##TYPE* vec, TYPE* val); \
426 int cvec_set_val_cap_##TYPE(cvector_##TYPE* vec, TYPE* val); \
427 \
428 TYPE* cvec_back_##TYPE(cvector_##TYPE* vec); \
429 \
430 void cvec_clear_##TYPE(cvector_##TYPE* vec); \
431 void cvec_free_##TYPE##_heap(void* vec); \
432 void cvec_free_##TYPE(void* vec);
433
434#define CVEC_NEW_DEFS2(TYPE, RESIZE_MACRO) \
435 cvec_sz CVEC_##TYPE##_SZ = 20; \
436 \
437 cvector_##TYPE* cvec_##TYPE##_heap(cvec_sz size, cvec_sz capacity, void (*elem_free)(void*), \
438 int (*elem_init)(void*, void*)) \
439 { \
440 cvector_##TYPE* vec; \
441 if (!(vec = (cvector_##TYPE*)CVEC_MALLOC(sizeof(cvector_##TYPE)))) { \
442 CVEC_ASSERT(vec != NULL); \
443 return NULL; \
444 } \
445 \
446 vec->size = size; \
447 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) \
448 ? capacity \
449 : vec->size + CVEC_##TYPE##_SZ; \
450 \
451 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
452 CVEC_ASSERT(vec->a != NULL); \
453 CVEC_FREE(vec); \
454 return NULL; \
455 } \
456 \
457 vec->elem_free = elem_free; \
458 vec->elem_init = elem_init; \
459 \
460 return vec; \
461 } \
462 \
463 cvector_##TYPE* cvec_init_##TYPE##_heap(TYPE* vals, cvec_sz num, void (*elem_free)(void*), \
464 int (*elem_init)(void*, void*)) \
465 { \
466 cvector_##TYPE* vec; \
467 cvec_sz i; \
468 \
469 if (!(vec = (cvector_##TYPE*)CVEC_MALLOC(sizeof(cvector_##TYPE)))) { \
470 CVEC_ASSERT(vec != NULL); \
471 return NULL; \
472 } \
473 \
474 vec->capacity = num + CVEC_##TYPE##_SZ; \
475 vec->size = num; \
476 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
477 CVEC_ASSERT(vec->a != NULL); \
478 CVEC_FREE(vec); \
479 return NULL; \
480 } \
481 \
482 if (elem_init) { \
483 for (i = 0; i < num; ++i) { \
484 if (!elem_init(&vec->a[i], &vals[i])) { \
485 CVEC_ASSERT(0); \
486 CVEC_FREE(vec->a); \
487 CVEC_FREE(vec); \
488 return NULL; \
489 } \
490 } \
491 } else { \
492 CVEC_MEMMOVE(vec->a, vals, sizeof(TYPE) * num); \
493 } \
494 \
495 vec->elem_free = elem_free; \
496 vec->elem_init = elem_init; \
497 \
498 return vec; \
499 } \
500 \
501 int cvec_##TYPE(cvector_##TYPE* vec, cvec_sz size, cvec_sz capacity, void (*elem_free)(void*), \
502 int (*elem_init)(void*, void*)) \
503 { \
504 vec->size = size; \
505 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) \
506 ? capacity \
507 : vec->size + CVEC_##TYPE##_SZ; \
508 \
509 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
510 CVEC_ASSERT(vec->a != NULL); \
511 vec->size = vec->capacity = 0; \
512 return 0; \
513 } \
514 \
515 vec->elem_free = elem_free; \
516 vec->elem_init = elem_init; \
517 \
518 return 1; \
519 } \
520 \
521 int cvec_init_##TYPE(cvector_##TYPE* vec, TYPE* vals, cvec_sz num, void (*elem_free)(void*), \
522 int (*elem_init)(void*, void*)) \
523 { \
524 cvec_sz i; \
525 \
526 vec->capacity = num + CVEC_##TYPE##_SZ; \
527 vec->size = num; \
528 if (!(vec->a = (TYPE*)CVEC_MALLOC(vec->capacity * sizeof(TYPE)))) { \
529 CVEC_ASSERT(vec->a != NULL); \
530 vec->size = vec->capacity = 0; \
531 return 0; \
532 } \
533 \
534 if (elem_init) { \
535 for (i = 0; i < num; ++i) { \
536 if (!elem_init(&vec->a[i], &vals[i])) { \
537 CVEC_ASSERT(0); \
538 return 0; \
539 } \
540 } \
541 } else { \
542 CVEC_MEMMOVE(vec->a, vals, sizeof(TYPE) * num); \
543 } \
544 \
545 vec->elem_free = elem_free; \
546 vec->elem_init = elem_init; \
547 \
548 return 1; \
549 } \
550 \
551 int cvec_copyc_##TYPE(void* dest, void* src) \
552 { \
553 cvector_##TYPE* vec1 = (cvector_##TYPE*)dest; \
554 cvector_##TYPE* vec2 = (cvector_##TYPE*)src; \
555 \
556 vec1->a = NULL; \
557 vec1->size = 0; \
558 vec1->capacity = 0; \
559 \
560 return cvec_copy_##TYPE(vec1, vec2); \
561 } \
562 \
563 int cvec_copy_##TYPE(cvector_##TYPE* dest, cvector_##TYPE* src) \
564 { \
565 int i; \
566 TYPE* tmp = NULL; \
567 if (!(tmp = (TYPE*)CVEC_REALLOC(dest->a, src->capacity*sizeof(TYPE)))) { \
568 CVEC_ASSERT(tmp != NULL); \
569 return 0; \
570 } \
571 dest->a = tmp; \
572 \
573 if (src->elem_init) { \
574 for (i=0; i<src->size; ++i) { \
575 if (!src->elem_init(&dest->a[i], &src->a[i])) { \
576 CVEC_ASSERT(0); \
577 return 0; \
578 } \
579 } \
580 } else { \
581 CVEC_MEMMOVE(dest->a, src->a, src->size*sizeof(TYPE)); \
582 } \
583 \
584 dest->size = src->size; \
585 dest->capacity = src->capacity; \
586 dest->elem_free = src->elem_free; \
587 dest->elem_init = src->elem_init; \
588 return 1; \
589 } \
590 \
591 int cvec_push_##TYPE(cvector_##TYPE* vec, TYPE* a) \
592 { \
593 TYPE* tmp; \
594 cvec_sz tmp_sz; \
595 if (vec->capacity == vec->size) { \
596 tmp_sz = RESIZE_MACRO(vec->capacity); \
597 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
598 CVEC_ASSERT(tmp != NULL); \
599 return 0; \
600 } \
601 vec->a = tmp; \
602 vec->capacity = tmp_sz; \
603 } \
604 if (vec->elem_init) { \
605 if (!vec->elem_init(&vec->a[vec->size], a)) { \
606 CVEC_ASSERT(0); \
607 return 0; \
608 } \
609 } else { \
610 CVEC_MEMMOVE(&vec->a[vec->size], a, sizeof(TYPE)); \
611 } \
612 \
613 vec->size++; \
614 return 1; \
615 } \
616 \
617 int cvec_pushm_##TYPE(cvector_##TYPE* vec, TYPE* a) \
618 { \
619 TYPE* tmp; \
620 cvec_sz tmp_sz; \
621 if (vec->capacity == vec->size) { \
622 tmp_sz = RESIZE_MACRO(vec->capacity); \
623 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
624 CVEC_ASSERT(tmp != NULL); \
625 return 0; \
626 } \
627 vec->a = tmp; \
628 vec->capacity = tmp_sz; \
629 } \
630 CVEC_MEMMOVE(&vec->a[vec->size], a, sizeof(TYPE)); \
631 \
632 vec->size++; \
633 return 1; \
634 } \
635 \
636 void cvec_pop_##TYPE(cvector_##TYPE* vec, TYPE* ret) \
637 { \
638 if (ret) { \
639 CVEC_MEMMOVE(ret, &vec->a[--vec->size], sizeof(TYPE)); \
640 } else { \
641 vec->size--; \
642 } \
643 \
644 if (vec->elem_free) { \
645 vec->elem_free(&vec->a[vec->size]); \
646 } \
647 } \
648 \
649 void cvec_popm_##TYPE(cvector_##TYPE* vec, TYPE* ret) \
650 { \
651 vec->size--; \
652 if (ret) { \
653 CVEC_MEMMOVE(ret, &vec->a[vec->size], sizeof(TYPE)); \
654 } \
655 } \
656 \
657 TYPE* cvec_back_##TYPE(cvector_##TYPE* vec) { return &vec->a[vec->size - 1]; } \
658 \
659 int cvec_extend_##TYPE(cvector_##TYPE* vec, cvec_sz num) \
660 { \
661 TYPE* tmp; \
662 cvec_sz tmp_sz; \
663 if (vec->capacity < vec->size + num) { \
664 tmp_sz = vec->capacity + num + CVEC_##TYPE##_SZ; \
665 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
666 CVEC_ASSERT(tmp != NULL); \
667 return 0; \
668 } \
669 vec->a = tmp; \
670 vec->capacity = tmp_sz; \
671 } \
672 \
673 vec->size += num; \
674 return 1; \
675 } \
676 \
677 int cvec_insert_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a) \
678 { \
679 TYPE* tmp; \
680 cvec_sz tmp_sz; \
681 if (vec->capacity == vec->size) { \
682 tmp_sz = RESIZE_MACRO(vec->capacity); \
683 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
684 CVEC_ASSERT(tmp != NULL); \
685 return 0; \
686 } \
687 \
688 vec->a = tmp; \
689 vec->capacity = tmp_sz; \
690 } \
691 CVEC_MEMMOVE(&vec->a[i + 1], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
692 \
693 if (vec->elem_init) { \
694 if (!vec->elem_init(&vec->a[i], a)) { \
695 CVEC_ASSERT(0); \
696 return 0; \
697 } \
698 } else { \
699 CVEC_MEMMOVE(&vec->a[i], a, sizeof(TYPE)); \
700 } \
701 \
702 vec->size++; \
703 return 1; \
704 } \
705 \
706 int cvec_insertm_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a) \
707 { \
708 TYPE* tmp; \
709 cvec_sz tmp_sz; \
710 if (vec->capacity == vec->size) { \
711 tmp_sz = RESIZE_MACRO(vec->capacity); \
712 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
713 CVEC_ASSERT(tmp != NULL); \
714 return 0; \
715 } \
716 \
717 vec->a = tmp; \
718 vec->capacity = tmp_sz; \
719 } \
720 CVEC_MEMMOVE(&vec->a[i + 1], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
721 \
722 CVEC_MEMMOVE(&vec->a[i], a, sizeof(TYPE)); \
723 \
724 vec->size++; \
725 return 1; \
726 } \
727 \
728 int cvec_insert_array_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num) \
729 { \
730 TYPE* tmp; \
731 cvec_sz tmp_sz, j; \
732 if (vec->capacity < vec->size + num) { \
733 tmp_sz = vec->capacity + num + CVEC_##TYPE##_SZ; \
734 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
735 CVEC_ASSERT(tmp != NULL); \
736 return 0; \
737 } \
738 vec->a = tmp; \
739 vec->capacity = tmp_sz; \
740 } \
741 \
742 CVEC_MEMMOVE(&vec->a[i + num], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
743 if (vec->elem_init) { \
744 for (j = 0; j < num; ++j) { \
745 if (!vec->elem_init(&vec->a[j + i], &a[j])) { \
746 CVEC_ASSERT(0); \
747 return 0; \
748 } \
749 } \
750 } else { \
751 CVEC_MEMMOVE(&vec->a[i], a, num * sizeof(TYPE)); \
752 } \
753 vec->size += num; \
754 return 1; \
755 } \
756 \
757 int cvec_insert_arraym_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, cvec_sz num) \
758 { \
759 TYPE* tmp; \
760 cvec_sz tmp_sz; \
761 if (vec->capacity < vec->size + num) { \
762 tmp_sz = vec->capacity + num + CVEC_##TYPE##_SZ; \
763 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * tmp_sz))) { \
764 CVEC_ASSERT(tmp != NULL); \
765 return 0; \
766 } \
767 vec->a = tmp; \
768 vec->capacity = tmp_sz; \
769 } \
770 \
771 CVEC_MEMMOVE(&vec->a[i + num], &vec->a[i], (vec->size - i) * sizeof(TYPE)); \
772 \
773 CVEC_MEMMOVE(&vec->a[i], a, num * sizeof(TYPE)); \
774 vec->size += num; \
775 return 1; \
776 } \
777 \
778 int cvec_replace_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, TYPE* ret) \
779 { \
780 if (ret) { \
781 CVEC_MEMMOVE(ret, &vec->a[i], sizeof(TYPE)); \
782 } else if (vec->elem_free) { \
783 vec->elem_free(&vec->a[i]); \
784 } \
785 \
786 if (vec->elem_init) { \
787 if (!vec->elem_init(&vec->a[i], a)) { \
788 CVEC_ASSERT(0); \
789 return 0; \
790 } \
791 } else { \
792 CVEC_MEMMOVE(&vec->a[i], a, sizeof(TYPE)); \
793 } \
794 return 1; \
795 } \
796 \
797 void cvec_replacem_##TYPE(cvector_##TYPE* vec, cvec_sz i, TYPE* a, TYPE* ret) \
798 { \
799 if (ret) { \
800 CVEC_MEMMOVE(ret, &vec->a[i], sizeof(TYPE)); \
801 } \
802 \
803 CVEC_MEMMOVE(&vec->a[i], a, sizeof(TYPE)); \
804 } \
805 \
806 void cvec_erase_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end) \
807 { \
808 cvec_sz i; \
809 cvec_sz d = end - start + 1; \
810 if (vec->elem_free) { \
811 for (i = start; i <= end; i++) { \
812 vec->elem_free(&vec->a[i]); \
813 } \
814 } \
815 CVEC_MEMMOVE(&vec->a[start], &vec->a[end + 1], (vec->size - 1 - end) * sizeof(TYPE)); \
816 vec->size -= d; \
817 } \
818 \
819 void cvec_remove_##TYPE(cvector_##TYPE* vec, cvec_sz start, cvec_sz end) \
820 { \
821 cvec_sz d = end - start + 1; \
822 CVEC_MEMMOVE(&vec->a[start], &vec->a[end + 1], (vec->size - 1 - end) * sizeof(TYPE)); \
823 vec->size -= d; \
824 } \
825 \
826 int cvec_reserve_##TYPE(cvector_##TYPE* vec, cvec_sz size) \
827 { \
828 TYPE* tmp; \
829 if (vec->capacity < size) { \
830 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * (size + CVEC_##TYPE##_SZ)))) { \
831 CVEC_ASSERT(tmp != NULL); \
832 return 0; \
833 } \
834 vec->a = tmp; \
835 vec->capacity = size + CVEC_##TYPE##_SZ; \
836 } \
837 return 1; \
838 } \
839 \
840 int cvec_set_cap_##TYPE(cvector_##TYPE* vec, cvec_sz size) \
841 { \
842 cvec_sz i; \
843 TYPE* tmp; \
844 if (size < vec->size) { \
845 if (vec->elem_free) { \
846 for (i = vec->size - 1; i >= size; i--) { \
847 vec->elem_free(&vec->a[i]); \
848 } \
849 } \
850 vec->size = size; \
851 } \
852 \
853 vec->capacity = size; \
854 \
855 if (!(tmp = (TYPE*)CVEC_REALLOC(vec->a, sizeof(TYPE) * size))) { \
856 CVEC_ASSERT(tmp != NULL); \
857 return 0; \
858 } \
859 vec->a = tmp; \
860 return 1; \
861 } \
862 \
863 int cvec_set_val_sz_##TYPE(cvector_##TYPE* vec, TYPE* val) \
864 { \
865 cvec_sz i; \
866 \
867 if (vec->elem_free) { \
868 for (i = 0; i < vec->size; i++) { \
869 vec->elem_free(&vec->a[i]); \
870 } \
871 } \
872 \
873 if (vec->elem_init) { \
874 for (i = 0; i < vec->size; i++) { \
875 if (!vec->elem_init(&vec->a[i], val)) { \
876 CVEC_ASSERT(0); \
877 return 0; \
878 } \
879 } \
880 } else { \
881 for (i = 0; i < vec->size; i++) { \
882 CVEC_MEMMOVE(&vec->a[i], val, sizeof(TYPE)); \
883 } \
884 } \
885 return 1; \
886 } \
887 \
888 int cvec_set_val_cap_##TYPE(cvector_##TYPE* vec, TYPE* val) \
889 { \
890 cvec_sz i; \
891 if (vec->elem_free) { \
892 for (i = 0; i < vec->size; i++) { \
893 vec->elem_free(&vec->a[i]); \
894 } \
895 vec->size = vec->capacity; \
896 } \
897 \
898 if (vec->elem_init) { \
899 for (i = 0; i < vec->capacity; i++) { \
900 if (!vec->elem_init(&vec->a[i], val)) { \
901 CVEC_ASSERT(0); \
902 return 0; \
903 } \
904 } \
905 } else { \
906 for (i = 0; i < vec->capacity; i++) { \
907 CVEC_MEMMOVE(&vec->a[i], val, sizeof(TYPE)); \
908 } \
909 } \
910 return 1; \
911 } \
912 \
913 void cvec_clear_##TYPE(cvector_##TYPE* vec) \
914 { \
915 cvec_sz i; \
916 if (vec->elem_free) { \
917 for (i = 0; i < vec->size; ++i) { \
918 vec->elem_free(&vec->a[i]); \
919 } \
920 } \
921 vec->size = 0; \
922 } \
923 \
924 void cvec_free_##TYPE##_heap(void* vec) \
925 { \
926 cvec_sz i; \
927 cvector_##TYPE* tmp = (cvector_##TYPE*)vec; \
928 if (!tmp) return; \
929 if (tmp->elem_free) { \
930 for (i = 0; i < tmp->size; i++) { \
931 tmp->elem_free(&tmp->a[i]); \
932 } \
933 } \
934 CVEC_FREE(tmp->a); \
935 CVEC_FREE(tmp); \
936 } \
937 \
938 void cvec_free_##TYPE(void* vec) \
939 { \
940 cvec_sz i; \
941 cvector_##TYPE* tmp = (cvector_##TYPE*)vec; \
942 if (tmp->elem_free) { \
943 for (i = 0; i < tmp->size; i++) { \
944 tmp->elem_free(&tmp->a[i]); \
945 } \
946 } \
947 \
948 CVEC_FREE(tmp->a); \
949 tmp->a = NULL; \
950 tmp->size = 0; \
951 tmp->capacity = 0; \
952 }
953
954#endif
#define CVEC_SIZE_TYPE
CVEC_SIZE_TYPE cvec_sz