├── vector.c └── vector.h /vector.c: -------------------------------------------------------------------------------- 1 | #include "vector.h" 2 | 3 | #include 4 | #include 5 | 6 | #define ELEM(i) ((char *) (v->elem) + (i) * (v->size)) 7 | 8 | struct vector { 9 | size_t plen; 10 | size_t llen; 11 | size_t size; 12 | void (*free)(void *); 13 | void *elem; 14 | }; 15 | 16 | static bool brim(vector v); 17 | static bool grow(vector v); 18 | 19 | vector vector_new(size_t hint, size_t size, void (*freefn)(void *)) { 20 | vector v = malloc(sizeof *v); 21 | if (!v) return NULL; 22 | v->plen = hint ? hint : 16; 23 | v->llen = 0; 24 | v->size = size ? size : 1; 25 | v->free = freefn; 26 | v->elem = malloc(v->plen * v->size); 27 | if (!v->elem) { free(v); return NULL; } 28 | return v; 29 | } 30 | 31 | void vector_free(vector v) { 32 | if (v->free) 33 | for (size_t i = 0; i < v->llen; i++) 34 | v->free(*(void **)(ELEM(i))); 35 | free(v->elem); 36 | free(v); 37 | } 38 | 39 | size_t vector_size(vector v) { 40 | if (!v) return 0; 41 | return v->llen; 42 | } 43 | 44 | bool vector_empty(vector v) { 45 | if (!v) return true; 46 | return v->llen ? false : true; 47 | } 48 | 49 | bool vector_clear(vector v) { 50 | if (!v) return false; 51 | if (v->free) 52 | for (size_t i = 0; i < v->llen; v++) 53 | v->free(*(void **)(ELEM(i))); 54 | v->llen = 0; 55 | return true; 56 | } 57 | 58 | bool vector_get(vector v, size_t i, void *elem) { 59 | if (!v || i >= v->llen || !elem) return false; 60 | memcpy(elem, ELEM(i), v->size); 61 | return true; 62 | } 63 | 64 | bool vector_remove(vector v, size_t i, void *elem) { 65 | if (!v || i >= v->llen) return false; 66 | if (elem) memcpy(elem, ELEM(i), v->size); 67 | else if (v->free) v->free(*(void **)(ELEM(i))); 68 | memmove(ELEM(i), ELEM(i+1), (v->llen-- - i + v->size)); 69 | return true; 70 | } 71 | 72 | bool vector_add(vector v, void *elem) { 73 | if (!v) return false; 74 | if (brim(v) && !grow(v)) return false; 75 | memcpy(ELEM(v->llen++), elem, v->size); 76 | return true; 77 | } 78 | 79 | bool vector_insert(vector v, size_t i, void *elem) { 80 | if (!v || i >= v->llen) return false; 81 | if (brim(v) && !grow(v)) return false; 82 | memmove(ELEM(i+1), ELEM(i), (v->llen++ - i + v->size)); 83 | memcpy(ELEM(i), elem, v->size); 84 | return true; 85 | } 86 | 87 | static bool brim(vector v) { return v->llen == v->plen ? true : false; } 88 | 89 | static bool grow(vector v) { 90 | size_t more = v->plen * 2; 91 | void *temp = realloc(v->elem, more * v->size); 92 | if (!temp) return false; 93 | v->plen = more; 94 | v->elem = temp; 95 | return true; 96 | } 97 | -------------------------------------------------------------------------------- /vector.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_H 2 | #define VECTOR_H 3 | 4 | #include 5 | #include 6 | 7 | /* An opaque pointer to a vector abstract data type. */ 8 | typedef struct vector *vector; 9 | 10 | /* Allocate, initialize, and return a new vector that stores elements of size 11 | * `size`. If `freefn` is not NULL, it is used to free individual elements 12 | * upon removal. Note that `freefn` will be called on already free'd memory 13 | * if elements point to the same memory location. */ 14 | vector vector_new(size_t hint, size_t size, void (*freefn)(void *)); 15 | 16 | /* Free memory allocated by `vector_new`. If `v` has a non-NULL `free` 17 | * function, the remaining elements of `v` are passed to this function. */ 18 | void vector_free(vector v); 19 | 20 | /* Get the logical size of `v`. */ 21 | size_t vector_size(vector v); 22 | 23 | /* Add `elem` to the end of `v`. */ 24 | bool vector_add(vector v, void *elem); 25 | 26 | /* Store the element at index `i` in `elem`. */ 27 | bool vector_get(vector v, size_t i, void *elem); 28 | 29 | /* Remove the element at index `i`. If `elem` is not NULL, the object removed 30 | * is stored in `elem`. If `elem` is NULL and `v` has a non-NULL `free` 31 | * function, the element at index `i` is passed to this function. */ 32 | bool vector_remove(vector v, size_t i, void *elem); 33 | 34 | /* Insert the element `elem` at index `i`. The indices of elements after the 35 | * insertion point increment by one. */ 36 | bool vector_insert(vector v, size_t i, void *elem); 37 | 38 | /* Return `true` if `v` is empty; otherwise, return `false`. */ 39 | bool vector_empty(vector v); 40 | 41 | /* Remove all elements from `v`. If `v` has a non-NULL `free` function, the 42 | * each element of `v` is passed to this function. */ 43 | bool vector_clear(vector v); 44 | 45 | 46 | #endif 47 | --------------------------------------------------------------------------------