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 *