Changed uiEvent.handlers into a uiprivArray; also fixed the buggy implementations of InsertAt and Delete.

This commit is contained in:
Pietro Gagliardi 2019-05-19 14:37:32 -04:00
parent 745440b1e7
commit 02b61c0156
3 changed files with 36 additions and 54 deletions

View File

@ -38,7 +38,7 @@ void *uiprivArrayAppend(uiprivArray *arr, size_t n)
void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t n) void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t n)
{ {
uint8_t *old, *new; uint8_t *old, *new;
size_t nBytes; size_t nBytesAdded, nBytesRemaining;
if ((arr->len + n) >= arr->cap) { if ((arr->len + n) >= arr->cap) {
size_t nGrow; size_t nGrow;
@ -53,11 +53,12 @@ void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t n)
} }
arr->len += n; arr->len += n;
nBytes = n * arr->elemsize; nBytesRemaining = (arr->len - pos) * arr->elemsize;
nBytesAdded = n * arr->elemsize;
new = ((uint8_t *) (arr->buf)) + (pos * arr->elemsize); new = ((uint8_t *) (arr->buf)) + (pos * arr->elemsize);
old = new + nBytes; old = new + nBytesAdded;
memmove(old, new, nBytes); memmove(old, new, nBytesRemaining);
memset(new, 0, nBytes); memset(new, 0, nBytesAdded);
return new; return new;
} }
@ -70,8 +71,9 @@ void uiprivArrayDelete(uiprivArray *arr, size_t pos, size_t n)
nBytesRemaining = (arr->len - pos - n) * arr->elemsize; nBytesRemaining = (arr->len - pos - n) * arr->elemsize;
dest = ((uint8_t *) (arr->buf)) + (pos * arr->elemsize); dest = ((uint8_t *) (arr->buf)) + (pos * arr->elemsize);
src = dest + nBytesDeleted; src = dest + nBytesDeleted;
memmove(dest, src, nBytesDeleted); memmove(dest, src, nBytesRemaining);
memset(src, 0, nBytesRemaining); src = dest + nBytesRemaining;
memset(src, 0, nBytesDeleted);
arr->len -= n; arr->len -= n;
} }
@ -85,7 +87,7 @@ void uiprivArrayDeleteItem(uiprivArray *arr, void *p, size_t n)
uiprivArrayDelete(arr, (p8 - buf8) / arr->elemsize, n); uiprivArrayDelete(arr, (p8 - buf8) / arr->elemsize, n);
} }
void *uiprivArrayBsearch(uiprivArray *arr, const void *key, int (*compare)(const void *, const void *)) void *uiprivArrayBsearch(const uiprivArray *arr, const void *key, int (*compare)(const void *, const void *))
{ {
return bsearch(key, arr->buf, arr->len, arr->elemsize, compare); return bsearch(key, arr->buf, arr->len, arr->elemsize, compare);
} }

View File

@ -4,8 +4,6 @@
#include "ui.h" #include "ui.h"
#include "uipriv.h" #include "uipriv.h"
#define nGrow 32
struct handler { struct handler {
int id; int id;
uiEventHandler f; uiEventHandler f;
@ -29,9 +27,7 @@ static int handlerCmp(const void *a, const void *b)
struct uiEvent { struct uiEvent {
uiEventOptions opts; uiEventOptions opts;
struct handler *handlers; uiprivArray handlers;
size_t len;
size_t cap;
int *unusedIDs; int *unusedIDs;
size_t unusedIDsLen; size_t unusedIDsLen;
size_t unusedIDsCap; size_t unusedIDsCap;
@ -52,6 +48,7 @@ uiEvent *uiNewEvent(const uiEventOptions *options)
} }
e = (uiEvent *) uiprivAlloc(sizeof (uiEvent), "uiEvent"); e = (uiEvent *) uiprivAlloc(sizeof (uiEvent), "uiEvent");
e->opts = *options; e->opts = *options;
uiprivArrayInit(e->handlers, struct handler, 32, "uiEvent handlers");
return e; return e;
} }
@ -80,7 +77,7 @@ static bool checkEventSender(const uiEvent *e, void *sender, const char *func)
int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data) int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *data)
{ {
struct handler *h; struct handler *h;
int retID; int id;
checkEventNonnull(e, 0); checkEventNonnull(e, 0);
checkEventNotFiring(e, 0); checkEventNotFiring(e, 0);
@ -91,30 +88,20 @@ int uiEventAddHandler(uiEvent *e, uiEventHandler handler, void *sender, void *da
if (!checkEventSender(e, sender, __func__)) if (!checkEventSender(e, sender, __func__))
return 0; return 0;
if (e->len >= e->cap) { id = 0;
e->handlers = uiprivRealloc(e->handlers,
e->cap * sizeof (struct handler),
(e->cap + nGrow) * sizeof (struct handler),
"uiEvent handlers");
e->cap += nGrow;
}
h = e->handlers + e->len;
h->id = 0;
if (e->unusedIDsLen > 0) { if (e->unusedIDsLen > 0) {
h->id = e->unusedIDs[e->unusedIDsLen - 1]; id = e->unusedIDs[e->unusedIDsLen - 1];
e->unusedIDsLen--; e->unusedIDsLen--;
} else if (e->len != 0) } else if (e->handlers.len != 0)
h->id = e->handlers[e->len - 1].id + 1; id = uiprivArrayAt(e->handlers, struct handler, e->handlers.len - 1)->id + 1;
h = (struct handler *) uiprivArrayAppend(&(e->handlers), 1);
h->id = id;
h->f = handler; h->f = handler;
h->sender = sender; h->sender = sender;
h->data = data; h->data = data;
uiprivArrayQsort(&(e->handlers), handlerCmp);
// after the qsort(), h may no longer be correct, so save the return ID now return id;
retID = h->id;
e->len++;
qsort(e->handlers, e->len, sizeof (struct handler), handlerCmp);
return retID;
} }
static struct handler *findHandler(const uiEvent *e, int id, const char *func) static struct handler *findHandler(const uiEvent *e, int id, const char *func)
@ -122,17 +109,12 @@ static struct handler *findHandler(const uiEvent *e, int id, const char *func)
struct handler key; struct handler key;
struct handler *ret; struct handler *ret;
if (e->len == 0)
goto notFound;
memset(&key, 0, sizeof (struct handler)); memset(&key, 0, sizeof (struct handler));
key.id = id; key.id = id;
ret = (struct handler *) bsearch(&key, e->handlers, e->len, sizeof (struct handler), handlerCmp); ret = (struct handler *) uiprivArrayBsearch(&(e->handlers), &key, handlerCmp);
if (ret != NULL) if (ret == NULL)
return ret; uiprivProgrammerError(uiprivProgrammerErrorIntIDNotFound, "uiEvent handler", id, func);
// otherwise fall through return ret;
notFound:
uiprivProgrammerError(uiprivProgrammerErrorIntIDNotFound, "uiEvent handler", id, func);
return NULL;
} }
void uiEventDeleteHandler(uiEvent *e, int id) void uiEventDeleteHandler(uiEvent *e, int id)
@ -145,16 +127,14 @@ void uiEventDeleteHandler(uiEvent *e, int id)
if (h == NULL) if (h == NULL)
return; return;
e->len--; uiprivArrayDeleteItem(&(e->handlers), h, 1);
// TODO write this in a way that doesn't mix ptrdiff_t and size_t
memmove(h, h + 1, (e->len - (h - e->handlers)) * sizeof (struct handler));
if (e->unusedIDsLen >= e->unusedIDsCap) { if (e->unusedIDsLen >= e->unusedIDsCap) {
e->unusedIDs = (int *) uiprivRealloc(e->unusedIDs, e->unusedIDs = (int *) uiprivRealloc(e->unusedIDs,
e->unusedIDsCap * sizeof (int), e->unusedIDsCap * sizeof (int),
(e->unusedIDsCap + nGrow) * sizeof (int), (e->unusedIDsCap + 32) * sizeof (int),
"uiEvent handler unused IDs"); "uiEvent handler unused IDs");
e->unusedIDsCap += nGrow; e->unusedIDsCap += 32;
} }
e->unusedIDs[e->unusedIDsLen] = id; e->unusedIDs[e->unusedIDsLen] = id;
e->unusedIDsLen++; e->unusedIDsLen++;
@ -174,8 +154,8 @@ void uiEventFire(uiEvent *e, void *sender, void *args)
return; return;
e->firing = true; e->firing = true;
h = e->handlers; h = (struct handler *) (e->handlers.buf);
for (i = 0; i < e->len; i++) { for (i = 0; i < e->handlers.len; i++) {
if (h->sender == sender && !h->blocked) if (h->sender == sender && !h->blocked)
(*(h->f))(sender, args, h->data); (*(h->f))(sender, args, h->data);
h++; h++;

View File

@ -23,12 +23,12 @@ struct uiprivArray {
size_t nGrow; size_t nGrow;
const char *what; const char *what;
}; };
#define uiprivInitArray(arr, T, grow) \ #define uiprivArrayInit(arr, T, grow, whatstr) \
memset(&arr, 0, sizeof (uiprivArray)); \ memset(&(arr), 0, sizeof (uiprivArray)); \
arr.elemsize = sizeof (T); \ arr.elemsize = sizeof (T); \
arr.nGrow = grow; \ arr.nGrow = grow; \
arr.what = #T "[]"; arr.what = whatstr;
#define uiprivFreeArray(arr) \ #define uiprivArrayFree(arr) \
uiprivFree(arr.buf); \ uiprivFree(arr.buf); \
memset(&arr, 0, sizeof (uiprivArray); memset(&arr, 0, sizeof (uiprivArray);
#define uiprivArrayAt(arr, T, n) (((T *) (arr.buf)) + (n)) #define uiprivArrayAt(arr, T, n) (((T *) (arr.buf)) + (n))
@ -36,7 +36,7 @@ extern void *uiprivArrayAppend(uiprivArray *arr, size_t n);
extern void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t n); extern void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t n);
extern void uiprivArrayDelete(uiprivArray *arr, size_t pos, size_t n); extern void uiprivArrayDelete(uiprivArray *arr, size_t pos, size_t n);
extern void uiprivArrayDeleteItem(uiprivArray *arr, void *p, size_t n); extern void uiprivArrayDeleteItem(uiprivArray *arr, void *p, size_t n);
extern void *uiprivArrayBsearch(uiprivArray *arr, const void *key, int (*compare)(const void *, const void *)); extern void *uiprivArrayBsearch(const uiprivArray *arr, const void *key, int (*compare)(const void *, const void *));
extern void uiprivArrayQsort(uiprivArray *arr, int (*compare)(const void *, const void *)); extern void uiprivArrayQsort(uiprivArray *arr, int (*compare)(const void *, const void *));
// errors.c // errors.c