array.c (3045B)
1 #include <u.h> 2 #include <libc.h> 3 4 #include "array.h" 5 6 #define MAGIC 0x1234 7 8 int 9 _arraycheck(Array *ap, long n, char *s) 10 { 11 if ((n < 0) || (n >= ap->count)) { 12 werrstr("%s: out of bounds", s); 13 return -1; 14 } 15 return 0; 16 } 17 18 void * 19 _arrayget(Array *ap, long n) 20 { 21 return (void *)(ap->p + ap->size * n); 22 } 23 24 Array * 25 arraycreate(long size, long n, void (*free)(void *)) 26 { 27 Array *ap; 28 ap = mallocz(sizeof(Array), 1); 29 *ap = (Array) { 30 MAGIC, 31 mallocz(sizeof(QLock), 1), 32 size, 33 n, 34 0, 35 mallocz(size * n, 1), 36 free, 37 }; 38 return ap; 39 } 40 41 void 42 arrayfree(Array *ap) 43 { 44 assert(ap->magic == MAGIC); 45 46 long i; 47 qlock(ap->l); 48 if (ap->free != nil) { 49 for (i = 0; i < ap->count; i ++) { 50 void **v; 51 v = _arrayget(ap, i); 52 if (*v != nil) ap->free(*v); 53 } 54 } 55 qunlock(ap->l); 56 free(ap); 57 } 58 59 void * 60 arraygrow(Array *ap, long n, void *v) 61 { 62 assert(ap->magic == MAGIC); 63 64 char *ve; 65 if (n < 0) { 66 werrstr("arraygrow: negative growth size"); 67 return nil; 68 } 69 if (n == 0) { 70 werrstr("arraygrow: zero growth size"); 71 return nil; 72 } 73 qlock(ap->l); 74 75 ap->count += n; 76 if (ap->count >= ap->n) { 77 ap->n = 2 * ap->count; 78 ap->p = realloc(ap->p, ap->size * ap->n); 79 } 80 81 ve = ap->p + ap->size * (ap->count - n); 82 83 memset(ve, 0, n * ap->size); 84 if (v != nil) { 85 memcpy(ve, v, n * ap->size); 86 } 87 qunlock(ap->l); 88 return (void *)ve; 89 } 90 91 int 92 arraydel(Array *ap, long offset, long count) 93 { 94 assert(ap->magic == MAGIC); 95 96 void *v, *ve; 97 long i; 98 if (_arraycheck(ap, offset, "arraydel") != 0) return -1; 99 if (offset + count > ap->count) { 100 werrstr("arraydel: count past array limit"); 101 return -1; 102 }; 103 104 qlock(ap->l); 105 106 if (ap->free != nil) { 107 for (i = offset; i < offset+ count; i++) { 108 v = _arrayget(ap, i); 109 ap->free(v); 110 } 111 } 112 113 v = _arrayget(ap, offset); 114 ve = _arrayget(ap, offset + count); 115 memcpy(v, ve, (ap->count - offset - count) * ap->size); 116 ap->count -= count; 117 qunlock(ap->l); 118 return 0; 119 } 120 121 void * 122 arrayget(Array *ap, long n, void *v) 123 { 124 assert(ap->magic == MAGIC); 125 if (_arraycheck(ap, n, "arrayget") != 0) return nil; 126 qlock(ap->l); 127 if (v != nil) { 128 memcpy(v, ap->p + ap->size * n, ap->size); 129 } 130 qunlock(ap->l); 131 return _arrayget(ap, n); 132 } 133 134 void * 135 arrayend(Array *ap) 136 { 137 assert(ap->magic == MAGIC); 138 139 return _arrayget(ap, ap->count); 140 } 141 142 void * 143 arrayinsert(Array *ap, long n, long m, void *v) 144 { 145 assert(ap->magic == MAGIC); 146 147 void *vs, *vn; 148 if (n == ap->count) { 149 vs = arraygrow(ap, m, v); 150 return vs; 151 } 152 if (_arraycheck(ap, n, "arrayinsert") != 0) return nil; 153 if (arraygrow(ap, m, nil) == nil) { 154 werrstr("arrayinsert: %r"); 155 return nil; 156 } 157 158 qlock(ap->l); 159 160 vs = _arrayget(ap, n); 161 vn = _arrayget(ap, n + m); 162 memcpy(vn, vs, (ap->count - n - m) * ap->size); 163 memset(vs, 0, m * ap->size); 164 if (v != nil) { 165 memcpy(vs, v, m * ap->size); 166 } 167 qunlock(ap->l); 168 return vs; 169 } 170 171 void * 172 arrayset(Array *ap, long n, void *v) 173 { 174 assert(ap->magic == MAGIC); 175 if (_arraycheck(ap, n, "arrayset") != 0) return nil; 176 qlock(ap->l); 177 if (v != nil) { 178 memcpy(ap->p + ap->size * n, v, ap->size); 179 } 180 qunlock(ap->l); 181 return _arrayget(ap, n); 182 }