richterm

"terminal emulator" with support for text fonts and images for plan9
git clone git://nsmpr.xyz/richterm.git
Log | Files | Refs | README

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 }