vector.c (1834B)
1 /* Vector implementation using a hashed-array tree */ 2 #include <stdlib.h> 3 4 struct leaf { 5 void *data; 6 }; 7 8 struct vector { 9 struct leaf **l; 10 size_t sz; 11 size_t ne; 12 }; 13 14 static int 15 grow(struct vector *v) 16 { 17 struct leaf **tmp, *l; 18 size_t i, j, ne = 0; 19 20 tmp = calloc(v->sz * 2, sizeof(*tmp)); 21 if (!tmp) 22 return -1; 23 for (i = 0; i < v->sz / 2; i++) { 24 tmp[i] = calloc(v->sz * 2, sizeof(**tmp)); 25 if (!tmp[i]) { 26 while (i-- > 0) 27 free(tmp[i]); 28 free(tmp); 29 return -1; 30 } 31 } 32 for (i = 0; i < v->sz; i++) { 33 l = tmp[ne / (v->sz * 2)]; 34 for (j = 0; j < v->sz; j++) { 35 l[ne % (v->sz * 2)].data = v->l[i][j].data; 36 ne++; 37 } 38 free(v->l[i]); 39 } 40 free(v->l); 41 v->l = tmp; 42 v->sz *= 2; 43 return 0; 44 } 45 46 struct vector * 47 vector_init(void) 48 { 49 struct vector *v; 50 51 v = calloc(1, sizeof(*v)); 52 if (!v) 53 return NULL; 54 v->sz = 2; 55 v->l = calloc(v->sz, sizeof(*v->l)); 56 if (!v->l) { 57 free(v); 58 return NULL; 59 } 60 return v; 61 } 62 63 void 64 vector_free(struct vector *v) 65 { 66 size_t i; 67 68 for (i = 0; i < v->sz; i++) 69 free(v->l[i]); 70 free(v->l); 71 } 72 73 size_t 74 vector_add(struct vector *v, void *data) 75 { 76 size_t index, offset; 77 struct leaf *l; 78 79 if (v->ne == v->sz * v->sz) 80 if (grow(v) < 0) 81 return -1; 82 index = v->ne / v->sz; 83 offset = v->ne % v->sz; 84 if (!v->l[index]) { 85 v->l[index] = calloc(v->sz, sizeof(**v->l)); 86 if (!v->l[index]) 87 return -1; 88 } 89 l = v->l[index]; 90 l[offset].data = data; 91 return v->ne++; 92 } 93 94 void * 95 vector_get(struct vector *v, size_t i) 96 { 97 size_t index, offset; 98 struct leaf *l; 99 100 index = i / v->sz; 101 offset = i % v->sz; 102 if (v->l[index]) { 103 l = v->l[index]; 104 return l[offset].data; 105 } 106 return NULL; 107 } 108 109 size_t 110 vector_size(struct vector *v) 111 { 112 return v->ne; 113 } 114 115 void 116 vector_walk(struct vector *v, void (*cb)(struct vector *, void *)) 117 { 118 size_t i; 119 120 for (i = 0; i < v->ne; i++) 121 cb(v, v->l[i / v->sz][i % v->sz].data); 122 }