CVector 4.3.0
A C++ style vector library in strict ANSI C (C89)
Loading...
Searching...
No Matches
cvector_void.c
Go to the documentation of this file.
1#include "cvector_void.h"
2
3
4
5#if defined(CVEC_MALLOC) && defined(CVEC_FREE) && defined(CVEC_REALLOC)
6/* ok */
7#elif !defined(CVEC_MALLOC) && !defined(CVEC_FREE) && !defined(CVEC_REALLOC)
8/* ok */
9#else
10#error "Must define all or none of CVEC_MALLOC, CVEC_FREE, and CVEC_REALLOC."
11#endif
12
13#ifndef CVEC_MALLOC
14#include <stdlib.h>
15#define CVEC_MALLOC(sz) malloc(sz)
16#define CVEC_REALLOC(p, sz) realloc(p, sz)
17#define CVEC_FREE(p) free(p)
18#endif
19
20#ifndef CVEC_MEMMOVE
21#include <string.h>
22#define CVEC_MEMMOVE(dst, src, sz) memmove(dst, src, sz)
23#endif
24
25#ifndef CVEC_ASSERT
26#include <assert.h>
27#define CVEC_ASSERT(x) assert(x)
28#endif
29
31
32#define CVEC_VOID_ALLOCATOR(x) ((x+1) * 2)
33
63cvector_void* cvec_void_heap(cvec_sz size, cvec_sz capacity, cvec_sz elem_sz, void(*elem_free)(void*), int(*elem_init)(void*, void*))
64{
65 cvector_void* vec;
66 if (!(vec = (cvector_void*)CVEC_MALLOC(sizeof(cvector_void)))) {
67 CVEC_ASSERT(vec != NULL);
68 return NULL;
69 }
70
71 vec->size = size;
72 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_VOID_START_SZ;
73
74 vec->elem_size = elem_sz;
75
76 if (!(vec->a = (cvec_u8*)CVEC_MALLOC(vec->capacity*elem_sz))) {
77 CVEC_ASSERT(vec->a != NULL);
78 CVEC_FREE(vec);
79 return NULL;
80 }
81 /* not clearing to 0 here as in cvector_str because elem_free cannot be calling CVEC_FREE directly
82 * since it takes the address of the element not the element itself */
83
84 vec->elem_free = elem_free;
85 vec->elem_init = elem_init;
86
87 return vec;
88}
89
94cvector_void* cvec_init_void_heap(void* vals, cvec_sz num, cvec_sz elem_sz, void(*elem_free)(void*), int(*elem_init)(void*, void*))
95{
96 cvector_void* vec;
97 cvec_sz i;
98
99 if (!(vec = (cvector_void*)CVEC_MALLOC(sizeof(cvector_void)))) {
100 CVEC_ASSERT(vec != NULL);
101 return NULL;
102 }
103
104 vec->elem_size = elem_sz;
105
106 vec->capacity = num + CVEC_VOID_START_SZ;
107 vec->size = num;
108 if (!(vec->a = (cvec_u8*)CVEC_MALLOC(vec->capacity*elem_sz))) {
109 CVEC_ASSERT(vec->a != NULL);
110 CVEC_FREE(vec);
111 return NULL;
112 }
113
114 if (elem_init) {
115 for (i=0; i<num; ++i) {
116 if (!elem_init(&vec->a[i*elem_sz], &((cvec_u8*)vals)[i*elem_sz])) {
117 CVEC_ASSERT(0);
118 CVEC_FREE(vec->a);
119 CVEC_FREE(vec);
120 return NULL;
121 }
122 }
123 } else {
124 CVEC_MEMMOVE(vec->a, vals, elem_sz*num);
125 }
126
127 vec->elem_free = elem_free;
128 vec->elem_init = elem_init;
129
130 return vec;
131}
132
136int cvec_void(cvector_void* vec, cvec_sz size, cvec_sz capacity, cvec_sz elem_sz, void(*elem_free)(void*), int(*elem_init)(void*, void*))
137{
138 vec->size = size;
139 vec->capacity = (capacity > vec->size || (vec->size && capacity == vec->size)) ? capacity : vec->size + CVEC_VOID_START_SZ;
140
141 vec->elem_size = elem_sz;
142
143 if (!(vec->a = (cvec_u8*)CVEC_MALLOC(vec->capacity*elem_sz))) {
144 CVEC_ASSERT(vec->a != NULL);
145 vec->size = vec->capacity = 0;
146 return 0;
147 }
148
149 vec->elem_free = elem_free;
150 vec->elem_init = elem_init;
151
152 return 1;
153}
154
158int cvec_init_void(cvector_void* vec, void* vals, cvec_sz num, cvec_sz elem_sz, void(*elem_free)(void*), int(*elem_init)(void*, void*))
159{
160 cvec_sz i;
161
162 vec->elem_size = elem_sz;
163
164 vec->capacity = num + CVEC_VOID_START_SZ;
165 vec->size = num;
166 if (!(vec->a = (cvec_u8*)CVEC_MALLOC(vec->capacity*elem_sz))) {
167 CVEC_ASSERT(vec->a != NULL);
168 vec->size = vec->capacity = 0;
169 return 0;
170 }
171
172 if (elem_init) {
173 for (i=0; i<num; ++i) {
174 if (!elem_init(&vec->a[i*elem_sz], &((cvec_u8*)vals)[i*elem_sz])) {
175 CVEC_ASSERT(0);
176 return 0;
177 }
178 }
179 } else {
180 CVEC_MEMMOVE(vec->a, vals, elem_sz*num);
181 }
182
183 vec->elem_free = elem_free;
184 vec->elem_init = elem_init;
185
186 return 1;
187}
188
199int cvec_copyc_void(void* dest, void* src)
200{
201 cvector_void* vec1 = (cvector_void*)dest;
202 cvector_void* vec2 = (cvector_void*)src;
203
204 vec1->a = NULL;
205 vec1->size = 0;
206 vec1->capacity = 0;
207
208 return cvec_copy_void(vec1, vec2);
209}
210
221{
222 int i;
223 cvec_u8* tmp = NULL;
224 if (!(tmp = (cvec_u8*)CVEC_REALLOC(dest->a, src->capacity*src->elem_size))) {
225 CVEC_ASSERT(tmp != NULL);
226 return 0;
227 }
228 dest->a = tmp;
229
230 if (src->elem_init) {
231 for (i=0; i<src->size; ++i) {
232 if (!src->elem_init(&dest->a[i*src->elem_size], &src->a[i*src->elem_size])) {
233 CVEC_ASSERT(0);
234 return 0;
235 }
236 }
237 } else {
238 /* could use memcpy here since we know we just allocated dest->a */
239 CVEC_MEMMOVE(dest->a, src->a, src->size*src->elem_size);
240 }
241
242 dest->size = src->size;
243 dest->capacity = src->capacity;
244 dest->elem_size = src->elem_size;
245 dest->elem_free = src->elem_free;
246 dest->elem_init = src->elem_init;
247 return 1;
248}
249
256int cvec_push_void(cvector_void* vec, void* a)
257{
258 cvec_u8* tmp;
259 cvec_sz tmp_sz;
260 if (vec->capacity == vec->size) {
261 tmp_sz = CVEC_VOID_ALLOCATOR(vec->capacity);
262 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
263 CVEC_ASSERT(tmp != NULL);
264 return 0;
265 }
266 vec->a = tmp;
267 vec->capacity = tmp_sz;
268 }
269 if (vec->elem_init) {
270 if (!vec->elem_init(&vec->a[vec->size*vec->elem_size], a)) {
271 CVEC_ASSERT(0);
272 return 0;
273 }
274 } else {
275 CVEC_MEMMOVE(&vec->a[vec->size*vec->elem_size], a, vec->elem_size);
276 }
277
278 vec->size++;
279 return 1;
280}
281
284{
285 cvec_u8* tmp;
286 cvec_sz tmp_sz;
287 if (vec->capacity == vec->size) {
288 tmp_sz = CVEC_VOID_ALLOCATOR(vec->capacity);
289 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
290 CVEC_ASSERT(tmp != NULL);
291 return 0;
292 }
293 vec->a = tmp;
294 vec->capacity = tmp_sz;
295 }
296 CVEC_MEMMOVE(&vec->a[vec->size*vec->elem_size], a, vec->elem_size);
297
298 vec->size++;
299 return 1;
300}
301
302
308void cvec_pop_void(cvector_void* vec, void* ret)
309{
310 vec->size--;
311 if (ret) {
312 CVEC_MEMMOVE(ret, &vec->a[vec->size*vec->elem_size], vec->elem_size);
313 }
314 if (vec->elem_free) {
315 vec->elem_free(&vec->a[vec->size*vec->elem_size]);
316 }
317}
318
320void cvec_popm_void(cvector_void* vec, void* ret)
321{
322 vec->size--;
323 if (ret) {
324 CVEC_MEMMOVE(ret, &vec->a[vec->size*vec->elem_size], vec->elem_size);
325 }
326}
327
330{
331 return &vec->a[(vec->size-1)*vec->elem_size];
332}
333
337{
338 cvec_u8* tmp;
339 cvec_sz tmp_sz;
340 if (vec->capacity < vec->size + num) {
341 tmp_sz = vec->capacity + num + CVEC_VOID_START_SZ;
342 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
343 CVEC_ASSERT(tmp != NULL);
344 return 0;
345 }
346 vec->a = tmp;
347 vec->capacity = tmp_sz;
348 }
349
350 vec->size += num;
351 return 1;
352}
353
360{
361 return &vec->a[i*vec->elem_size];
362}
363
369{
370 cvec_u8* tmp;
371 cvec_sz tmp_sz;
372 if (vec->capacity == vec->size) {
373 tmp_sz = CVEC_VOID_ALLOCATOR(vec->capacity);
374 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
375 CVEC_ASSERT(tmp != NULL);
376 return 0;
377 }
378
379 vec->a = tmp;
380 vec->capacity = tmp_sz;
381 }
382 CVEC_MEMMOVE(&vec->a[(i+1)*vec->elem_size], &vec->a[i*vec->elem_size], (vec->size-i)*vec->elem_size);
383
384 if (vec->elem_init) {
385 if (!vec->elem_init(&vec->a[i*vec->elem_size], a)) {
386 CVEC_ASSERT(0);
387 return 0;
388 }
389 } else {
390 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, vec->elem_size);
391 }
392
393 vec->size++;
394 return 1;
395}
396
399{
400 cvec_u8* tmp;
401 cvec_sz tmp_sz;
402 if (vec->capacity == vec->size) {
403 tmp_sz = CVEC_VOID_ALLOCATOR(vec->capacity);
404 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
405 CVEC_ASSERT(tmp != NULL);
406 return 0;
407 }
408
409 vec->a = tmp;
410 vec->capacity = tmp_sz;
411 }
412 CVEC_MEMMOVE(&vec->a[(i+1)*vec->elem_size], &vec->a[i*vec->elem_size], (vec->size-i)*vec->elem_size);
413
414 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, vec->elem_size);
415
416 vec->size++;
417 return 1;
418}
419
428{
429 cvec_u8* tmp;
430 cvec_sz tmp_sz, j;
431 if (vec->capacity < vec->size + num) {
432 tmp_sz = vec->capacity + num + CVEC_VOID_START_SZ;
433 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
434 CVEC_ASSERT(tmp != NULL);
435 return 0;
436 }
437 vec->a = tmp;
438 vec->capacity = tmp_sz;
439 }
440
441 CVEC_MEMMOVE(&vec->a[(i+num)*vec->elem_size], &vec->a[i*vec->elem_size], (vec->size-i)*vec->elem_size);
442 if (vec->elem_init) {
443 for (j=0; j<num; ++j) {
444 if (!vec->elem_init(&vec->a[(j+i)*vec->elem_size], &((cvec_u8*)a)[j*vec->elem_size])) {
445 CVEC_ASSERT(0);
446 return 0;
447 }
448 }
449 } else {
450 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, num*vec->elem_size);
451 }
452 vec->size += num;
453 return 1;
454}
455
458{
459 cvec_u8* tmp;
460 cvec_sz tmp_sz;
461 if (vec->capacity < vec->size + num) {
462 tmp_sz = vec->capacity + num + CVEC_VOID_START_SZ;
463 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*tmp_sz))) {
464 CVEC_ASSERT(tmp != NULL);
465 return 0;
466 }
467 vec->a = tmp;
468 vec->capacity = tmp_sz;
469 }
470
471 CVEC_MEMMOVE(&vec->a[(i+num)*vec->elem_size], &vec->a[i*vec->elem_size], (vec->size-i)*vec->elem_size);
472
473 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, num*vec->elem_size);
474 vec->size += num;
475 return 1;
476}
477
481int cvec_replace_void(cvector_void* vec, cvec_sz i, void* a, void* ret)
482{
483 if (ret) {
484 CVEC_MEMMOVE(ret, &vec->a[i*vec->elem_size], vec->elem_size);
485 } else if (vec->elem_free) {
486 vec->elem_free(&vec->a[i*vec->elem_size]);
487 }
488
489 if (vec->elem_init) {
490 if (!vec->elem_init(&vec->a[i*vec->elem_size], a)) {
491 CVEC_ASSERT(0);
492 return 0;
493 }
494 } else {
495 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, vec->elem_size);
496 }
497 return 1;
498}
499
505void cvec_replacem_void(cvector_void* vec, cvec_sz i, void* a, void* ret)
506{
507 if (ret) {
508 CVEC_MEMMOVE(ret, &vec->a[i*vec->elem_size], vec->elem_size);
509 }
510
511 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], a, vec->elem_size);
512}
513
520{
521 cvec_sz i;
522 cvec_sz d = end - start + 1;
523 if (vec->elem_free) {
524 for (i=start; i<=end; i++) {
525 vec->elem_free(&vec->a[i*vec->elem_size]);
526 }
527 }
528 CVEC_MEMMOVE(&vec->a[start*vec->elem_size], &vec->a[(end+1)*vec->elem_size], (vec->size-1-end)*vec->elem_size);
529 vec->size -= d;
530}
531
534{
535 cvec_sz d = end - start + 1;
536 CVEC_MEMMOVE(&vec->a[start*vec->elem_size], &vec->a[(end+1)*vec->elem_size], (vec->size-1-end)*vec->elem_size);
537 vec->size -= d;
538}
539
542{
543 cvec_u8* tmp;
544 if (vec->capacity < size) {
545 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*(size+CVEC_VOID_START_SZ)))) {
546 CVEC_ASSERT(tmp != NULL);
547 return 0;
548 }
549 vec->a = tmp;
550 vec->capacity = size + CVEC_VOID_START_SZ;
551 }
552 return 1;
553}
554
560{
561 cvec_sz i;
562 cvec_u8* tmp;
563 if (size < vec->size) {
564 if (vec->elem_free) {
565 for (i=vec->size-1; i>=size; i--) {
566 vec->elem_free(&vec->a[i*vec->elem_size]);
567 }
568 }
569 vec->size = size;
570 }
571
572 vec->capacity = size;
573
574 if (!(tmp = (cvec_u8*)CVEC_REALLOC(vec->a, vec->elem_size*size))) {
575 CVEC_ASSERT(tmp != NULL);
576 return 0;
577 }
578 vec-> a = tmp;
579 return 1;
580}
581
584{
585 cvec_sz i;
586
587 if (vec->elem_free) {
588 for(i=0; i<vec->size; i++) {
589 vec->elem_free(&vec->a[i*vec->elem_size]);
590 }
591 }
592
593 if (vec->elem_init) {
594 for (i=0; i<vec->size; i++) {
595 if (!vec->elem_init(&vec->a[i*vec->elem_size], val)) {
596 CVEC_ASSERT(0);
597 return 0;
598 }
599 }
600 } else {
601 for (i=0; i<vec->size; i++) {
602 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], val, vec->elem_size);
603 }
604 }
605 return 1;
606}
607
614{
615 cvec_sz i;
616 if (vec->elem_free) {
617 for (i=0; i<vec->size; i++) {
618 vec->elem_free(&vec->a[i*vec->elem_size]);
619 }
620 vec->size = vec->capacity;
621 }
622
623 if (vec->elem_init) {
624 for (i=0; i<vec->capacity; i++) {
625 if (!vec->elem_init(&vec->a[i*vec->elem_size], val)) {
626 CVEC_ASSERT(0);
627 return 0;
628 }
629 }
630 } else {
631 for (i=0; i<vec->capacity; i++) {
632 CVEC_MEMMOVE(&vec->a[i*vec->elem_size], val, vec->elem_size);
633 }
634 }
635 return 1;
636}
637
641{
642 cvec_sz i;
643 if (vec->elem_free) {
644 for (i=0; i<vec->size; ++i) {
645 vec->elem_free(&vec->a[i*vec->elem_size]);
646 }
647 }
648 vec->size = 0;
649}
650
654void cvec_free_void_heap(void* vec)
655{
656 cvec_sz i;
657 cvector_void* tmp = (cvector_void*)vec;
658 if (!tmp) return;
659 if (tmp->elem_free) {
660 for (i=0; i<tmp->size; i++) {
661 tmp->elem_free(&tmp->a[i*tmp->elem_size]);
662 }
663 }
664 CVEC_FREE(tmp->a);
665 CVEC_FREE(tmp);
666}
667
670void cvec_free_void(void* vec)
671{
672 cvec_sz i;
673 cvector_void* tmp = (cvector_void*)vec;
674 if (tmp->elem_free) {
675 for (i=0; i<tmp->size; i++) {
676 tmp->elem_free(&tmp->a[i*tmp->elem_size]);
677 }
678 }
679
680 CVEC_FREE(tmp->a);
681 tmp->a = NULL;
682 tmp->size = 0;
683 tmp->capacity = 0;
684}
685
unsigned char cvec_u8
Definition cvector.h:243
CVEC_SIZE_T cvec_sz
Definition cvector.h:88
#define CVEC_FREE(p)
int cvec_set_val_sz_void(cvector_void *vec, void *val)
Set all size elements to val.
int cvec_copyc_void(void *dest, void *src)
Makes dest a copy of src.
#define CVEC_VOID_ALLOCATOR(x)
int cvec_insert_array_void(cvector_void *vec, cvec_sz i, void *a, cvec_sz num)
Insert the first num elements of array a at index i.
int cvec_copy_void(cvector_void *dest, cvector_void *src)
Makes dest a copy of src.
int cvec_reserve_void(cvector_void *vec, cvec_sz size)
Makes sure capacity >= size (the parameter not the member).
cvector_void * cvec_void_heap(cvec_sz size, cvec_sz capacity, cvec_sz elem_sz, void(*elem_free)(void *), int(*elem_init)(void *, void *))
Creates a new vector on the heap.
#define CVEC_REALLOC(p, sz)
int cvec_pushm_void(cvector_void *vec, void *a)
Same as push except no elem_init even if it's set.
int cvec_insert_arraym_void(cvector_void *vec, cvec_sz i, void *a, cvec_sz num)
Same as insert_array but no elem_init even if defined.
int cvec_replace_void(cvector_void *vec, cvec_sz i, void *a, void *ret)
Replace value at i with a, return old value in ret if non-NULL.
void cvec_remove_void(cvector_void *vec, cvec_sz start, cvec_sz end)
Same as erase except it does not call elem_free.
int cvec_init_void(cvector_void *vec, void *vals, cvec_sz num, cvec_sz elem_sz, void(*elem_free)(void *), int(*elem_init)(void *, void *))
Same as init_vec_heap() except the vector passed in was declared on the stack so it isn't allocated i...
cvector_void * cvec_init_void_heap(void *vals, cvec_sz num, cvec_sz elem_sz, void(*elem_free)(void *), int(*elem_init)(void *, void *))
Create (on the heap) and initialize vector with num elements of vals.
#define CVEC_MEMMOVE(dst, src, sz)
void cvec_erase_void(cvector_void *vec, cvec_sz start, cvec_sz end)
Erases elements from start to end inclusive.
void * cvec_get_void(cvector_void *vec, cvec_sz i)
Return a void pointer to the ith element.
int cvec_push_void(cvector_void *vec, void *a)
Append a to end of vector (size increased 1).
int cvec_insertm_void(cvector_void *vec, cvec_sz i, void *a)
Same as insert but no elem_init even if defined.
#define CVEC_MALLOC(sz)
int cvec_void(cvector_void *vec, cvec_sz size, cvec_sz capacity, cvec_sz elem_sz, void(*elem_free)(void *), int(*elem_init)(void *, void *))
Same as cvec_void_heap() except the vector passed in was declared on the stack so it isn't allocated ...
void * cvec_back_void(cvector_void *vec)
Return pointer to last element.
#define CVEC_ASSERT(x)
void cvec_pop_void(cvector_void *vec, void *ret)
Remove the last element (size decreased 1).
int cvec_set_cap_void(cvector_void *vec, cvec_sz size)
Set capacity to size.
void cvec_free_void(void *vec)
Frees the internal array and sets it, size, and capacity to NULL/0 to maintain a consistent state.
void cvec_replacem_void(cvector_void *vec, cvec_sz i, void *a, void *ret)
Same as replace but no elem_free or elem_init even if they're defined.
cvec_sz CVEC_VOID_START_SZ
int cvec_set_val_cap_void(cvector_void *vec, void *val)
Fills entire allocated array (capacity) with val.
void cvec_free_void_heap(void *vec)
Frees everything so don't use vec after calling this.
int cvec_extend_void(cvector_void *vec, cvec_sz num)
Increase the size of the array num items.
void cvec_clear_void(cvector_void *vec)
Sets size to 0 (does not change contents unless elem_free is set then it will elem_free all size elem...
void cvec_popm_void(cvector_void *vec, void *ret)
Same as pop except no elem_free even if it's set.
int cvec_insert_void(cvector_void *vec, cvec_sz i, void *a)
Insert a at index i (0 based).
Data structure for generic type (cast to void) vectors.
Definition cvector.h:247
cvec_sz size
Current size (amount you should use when manipulating array directly).
Definition cvector.h:249
cvec_sz elem_size
Size in bytes of type stored (sizeof(T) where T is type).
Definition cvector.h:251
cvec_sz capacity
Allocated size of array; always >= size.
Definition cvector.h:250
void(* elem_free)(void *)
Definition cvector.h:252
cvec_u8 * a
Array.
Definition cvector.h:248
int(* elem_init)(void *, void *)
Definition cvector.h:253