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)
{
uint8_t *old, *new;
size_t nBytes;
size_t nBytesAdded, nBytesRemaining;
if ((arr->len + n) >= arr->cap) {
size_t nGrow;
@ -53,11 +53,12 @@ void *uiprivArrayInsertAt(uiprivArray *arr, size_t pos, size_t 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);
old = new + nBytes;
memmove(old, new, nBytes);
memset(new, 0, nBytes);
old = new + nBytesAdded;
memmove(old, new, nBytesRemaining);
memset(new, 0, nBytesAdded);
return new;
}
@ -70,8 +71,9 @@ void uiprivArrayDelete(uiprivArray *arr, size_t pos, size_t n)
nBytesRemaining = (arr->len - pos - n) * arr->elemsize;
dest = ((uint8_t *) (arr->buf)) + (pos * arr->elemsize);
src = dest + nBytesDeleted;
memmove(dest, src, nBytesDeleted);
memset(src, 0, nBytesRemaining);
memmove(dest, src, nBytesRemaining);
src = dest + nBytesRemaining;
memset(src, 0, nBytesDeleted);
arr->len -= n;
}
@ -85,7 +87,7 @@ void uiprivArrayDeleteItem(uiprivArray *arr, void *p, size_t 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);
}

View File

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

View File

@ -23,12 +23,12 @@ struct uiprivArray {
size_t nGrow;
const char *what;
};
#define uiprivInitArray(arr, T, grow) \
memset(&arr, 0, sizeof (uiprivArray)); \
#define uiprivArrayInit(arr, T, grow, whatstr) \
memset(&(arr), 0, sizeof (uiprivArray)); \
arr.elemsize = sizeof (T); \
arr.nGrow = grow; \
arr.what = #T "[]";
#define uiprivFreeArray(arr) \
arr.what = whatstr;
#define uiprivArrayFree(arr) \
uiprivFree(arr.buf); \
memset(&arr, 0, sizeof (uiprivArray);
#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 uiprivArrayDelete(uiprivArray *arr, size_t pos, 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 *));
// errors.c