shithub: sce

Download patch

ref: bdd642b56f958a862fc12a784e6af0b3fdbb7790
parent: 710b64171c4f486abbe52bcd03e225dc6761abc4
author: qwx <qwx@sciops.net>
date: Sun Dec 19 19:58:55 EST 2021

util: fix and sanitize vectors

--- a/dat.h
+++ b/dat.h
@@ -40,7 +40,9 @@
 struct Vector{
 	void *p;
 	ulong n;
+	ulong elsz;
 	ulong bufsz;
+	ulong totsz;
 	int firstempty;
 };
 
--- a/drw.c
+++ b/drw.c
@@ -142,13 +142,13 @@
 static void
 clearvis(void)
 {
-	clearvec(&vis, sizeof(Mobj*));
+	clearvec(&vis);
 }
 
 static int
 addvis(Mobj *mo)
 {
-	pushvec(&vis, &mo, sizeof mo);
+	pushvec(&vis, &mo);
 	return vis.n - 1;
 }
 
@@ -328,8 +328,8 @@
 	Drawlist *dl;
 
 	for(dl=drawlist; dl<drawlist+DLend; dl++){
-		clearvec(&dl->mobj, sizeof(Mobj*));
-		clearvec(&dl->pics, sizeof(Pic*));
+		clearvec(&dl->mobj);
+		clearvec(&dl->pics);
 	}
 }
 
@@ -340,8 +340,8 @@
 
 	if((p = frm(mo, type)) == nil)
 		return;
-	pushvec(&dl->mobj, &mo, sizeof mo);
-	pushvec(&dl->pics, &p, sizeof p);
+	pushvec(&dl->mobj, &mo);
+	pushvec(&dl->pics, &p);
 }
 
 static void
@@ -403,7 +403,30 @@
 	*rp = r;
 }
 
-void
+static void
+flushdrw(void)
+{
+	uchar *p;
+	Rectangle r, r2;
+
+	r = selr;
+	p = (uchar *)fb;
+	if(scale == 1){
+		loadimage(fbi, fbi->r, p, fbsz);
+		draw(screen, r, fbi, nil, ZP);
+	}else{
+		r2 = r;
+		while(r.min.y < r2.max.y){
+			r.max.y = r.min.y + scale;
+			p += loadimage(fbi, fbi->r, p, fbsz / fbh);
+			draw(screen, r, fbi, nil, ZP);
+			r.min.y = r.max.y;
+		}
+	}
+	flushimage(display, 1);
+}
+
+static void
 redraw(void)
 {
 	Point p;
@@ -428,16 +451,16 @@
 }
 
 void
-updatefb(void)
+updatedrw(void)
 {
 	qlock(&drawlock);
 	redraw();
 	qunlock(&drawlock);
-	drawfb();
+	flushdrw();
 }
 
 void
-resetfb(void)
+resetdrw(void)
 {
 	fbws = min(mapwidth * Nodesz * scale, Dx(screen->r));
 	fbh = min(mapheight * Nodesz * scale, Dy(screen->r));
@@ -467,24 +490,15 @@
 }
 
 void
-drawfb(void)
+initdrw(void)
 {
-	uchar *p;
-	Rectangle r, r2;
+	Drawlist *dl;
 
-	r = selr;
-	p = (uchar *)fb;
-	if(scale == 1){
-		loadimage(fbi, fbi->r, p, fbsz);
-		draw(screen, r, fbi, nil, ZP);
-	}else{
-		r2 = r;
-		while(r.min.y < r2.max.y){
-			r.max.y = r.min.y + scale;
-			p += loadimage(fbi, fbi->r, p, fbsz / fbh);
-			draw(screen, r, fbi, nil, ZP);
-			r.min.y = r.max.y;
-		}
+	if(initdraw(nil, nil, "path") < 0)
+		sysfatal("initdraw: %r");
+	newvec(&vis, 32, sizeof(Mobj*));
+	for(dl=drawlist; dl<drawlist+DLend; dl++){
+		newvec(&dl->mobj, 32, sizeof(Mobj*));
+		newvec(&dl->pics, 32, sizeof(Pic*));
 	}
-	flushimage(display, 1);
 }
--- a/fns.h
+++ b/fns.h
@@ -41,10 +41,9 @@
 void	doselect(Point);
 void	doaction(Point, int);
 void	compose(Point, u32int);
-void	redraw(void);
-void	updatefb(void);
-void	resetfb(void);
-void	drawfb(void);
+void	updatedrw(void);
+void	resetdrw(void);
+void	initdrw(void);
 void	initimg(void);
 void	initfs(void);
 double	eucdist(Point, Point);
@@ -76,9 +75,11 @@
 void	dprint(char *, ...);
 int	max(int, int);
 int	min(int, int);
-void	clearvec(Vector*, int);
+void	clearvec(Vector*);
+void	popsparsevec(Vector*, int);
 void*	pushsparsevec(Vector*, void*);
-void*	pushvec(Vector*, void*, int);
+void*	pushvec(Vector*, void*);
+void*	newvec(Vector*, int, int);
 char*	estrdup(char*);
 void*	erealloc(void*, ulong, ulong);
 void*	emalloc(ulong);
--- a/fs.c
+++ b/fs.c
@@ -608,10 +608,15 @@
 initmapobj(void)
 {
 	Objp *op;
-	Tile *t;
+	Tile *tl;
+	Team *t;
 
-	for(t=tilemap; t<tilemap+tilemapwidth*tilemapheight; t++)
-		t->ml.l = t->ml.lp = &t->ml;
+	for(tl=tilemap; tl<tilemap+tilemapwidth*tilemapheight; tl++)
+		tl->ml.l = tl->ml.lp = &tl->ml;
+	for(t=teams; t<=teams+nteam; t++){
+		newvec(&t->mobj, 32, sizeof(Mobj*));
+		newvec(&t->drops, 32, sizeof(Mobj*));
+	}
 	for(op=objp; op<objp+nobjp; op++){
 		if(op->resource){
 			if(spawnresource(op->o, op->Point, op->amount) < 0)
--- a/map.c
+++ b/map.c
@@ -151,6 +151,7 @@
 	mo->uuid = lrand();
 	setpos(mo, p);
 	mo->o = o;
+	newvec(&mo->path.moves, 32, sizeof(Point));
 	updatemap(mo);
 	return mo;
 }
--- a/path.c
+++ b/path.c
@@ -479,8 +479,8 @@
 
 	pp = &mo->path;
 	pp->dist = eucdist(a->Point, g->Point);
-	clearvec(&pp->moves, sizeof g->Point);
-	pushvec(&pp->moves, &g->Point, sizeof g->Point);
+	clearvec(&pp->moves);
+	pushvec(&pp->moves, &g->Point);
 	pp->step = (Point *)pp->moves.p + pp->moves.n - 1;
 }
 
@@ -492,9 +492,9 @@
 	pp = &mo->path;
 	assert(n != a && n->step > 0);
 	pp->dist = n->len;
-	clearvec(&pp->moves, sizeof n->Point);
+	clearvec(&pp->moves);
 	for(; n!=a; n=n->from)
-		pushvec(&pp->moves, &n->Point, sizeof n->Point);
+		pushvec(&pp->moves, &n->Point);
 	pp->step = (Point *)pp->moves.p + pp->moves.n - 1;
 }
 
--- a/sce.c
+++ b/sce.c
@@ -132,11 +132,10 @@
 static void
 initcl(void)
 {
-	if(initdraw(nil, nil, progname) < 0)
-		sysfatal("initdraw: %r");
 	initsnd();
+	initdrw();
 	initimg();
-	resetfb();
+	resetdrw();
 	if((reszc = chancreate(sizeof(int), 2)) == nil
 	|| (kc = chancreate(sizeof(Kev), 20)) == nil
 	|| (mc = chancreate(sizeof(Mev), 20)) == nil
@@ -217,7 +216,7 @@
 		case Aresize:
 			if(getwindow(display, Refnone) < 0)
 				sysfatal("resize failed: %r");
-			resetfb();
+			resetdrw();
 			break;
 		case Amouse:
 			qlock(&drawlock);	/* just for security */
@@ -247,7 +246,7 @@
 			flushcl();
 			break;
 		case Atic:
-			updatefb();
+			updatedrw();
 			break;
 		}
 	}
--- a/sim.c
+++ b/sim.c
@@ -56,7 +56,7 @@
 	n = p - (Mobj **)t->mobj.p;
 	mo->idx = mo->team << Teamshift | n;
 	if(mo->o->f & Fdropoff)
-		pushvec(&t->drops, &mo, sizeof mo);
+		pushvec(&t->drops, &mo);
 }
 
 void
--- a/sim.move.c
+++ b/sim.move.c
@@ -59,7 +59,7 @@
 	snaptomapgrid(mo);
 	mo->speed = 0.0;
 	mo->path.step = nil;
-	clearvec(&mo->path.moves, sizeof *mo->path.step);
+	clearvec(&mo->path.moves);
 }
 
 static void
--- a/util.c
+++ b/util.c
@@ -48,50 +48,76 @@
 }
 
 void
-clearvec(Vector *v, int sz)
+clearvec(Vector *v)
 {
 	if(v->p == nil)
 		return;
-	memset(v->p, 0, v->bufsz * sz);
+	memset(v->p, 0, v->totsz);
 	v->firstempty = 0;
 	v->n = 0;
 }
 
+static void *
+growvec(Vector *v, int n)
+{
+	if(n < v->bufsz)
+		return (uchar *)v->p + n * v->elsz;
+	v->p = erealloc(v->p, v->totsz + Nvecinc * v->elsz, v->totsz);
+	v->bufsz += Nvecinc;
+	v->totsz += Nvecinc * v->elsz;
+	return (uchar *)v->p + n * v->elsz;
+}
+
+void
+popsparsevec(Vector *v, int n)
+{
+	assert(v != nil && v->elsz > 0 && n >= 0 && n <= v->n);
+	memset((uchar *)v->p + n * v->elsz, 0, v->elsz);
+}
+
+/* assumes that zeroed element means empty; could fill with
+ * magic values instead */
 void *
 pushsparsevec(Vector *v, void *e)
 {
-	int i;
+	int n;
 	uchar *p, *q;
 
-	i = v->firstempty;
-	if(i == v->bufsz){
-		v->p = erealloc(v->p, (v->bufsz + Nvecinc) * sizeof e,
-			v->bufsz * sizeof e);
-		v->bufsz += Nvecinc;
-	}
-	p = (uchar *)v->p + i * sizeof e;
-	memcpy(p, e, sizeof e);
-	for(i++, q=p+1; i<v->n; q++, i++)
-		if(memcmp(p, nil, sizeof p) == 0)
+	assert(v != nil && v->elsz > 0);
+	n = v->firstempty;
+	p = growvec(v, n);
+	for(n++, q=p+v->elsz; n<v->n; n++, q+=v->elsz)
+		if(memcmp(p, q, v->elsz) == 0)
 			break;
-	v->firstempty = i;
+	v->firstempty = n;
+	memcpy(p, e, v->elsz);
 	v->n++;
 	return p;
 }
 
 void *
-pushvec(Vector *v, void *e, int sz)
+pushvec(Vector *v, void *e)
 {
-	void *p;
+	uchar *p;
 
-	if(v->n == v->bufsz){
-		v->p = erealloc(v->p, (v->bufsz + Nvecinc) * sz, v->bufsz * sz);
-		v->bufsz += Nvecinc;
-	}
-	p = (uchar *)v->p + v->n * sz;
-	memcpy(p, e, sz);
+	assert(v != nil && v->elsz > 0);
+	p = growvec(v, v->n);
+	memcpy(p, e, v->elsz);
 	v->n++;
+	v->firstempty = v->n;
 	return p;
+}
+
+void *
+newvec(Vector *v, int nel, int elsz)
+{
+	assert(v != nil && elsz > 0);
+	v->elsz = elsz;
+	nel = nel + Nvecinc-1 & ~(Nvecinc-1);
+	v->bufsz = nel;
+	v->totsz = nel * elsz;
+	v->p = emalloc(v->totsz);
+	return v->p;
 }
 
 char *