From 02b61c0156ac82c9cf1f0ed8db011fdc6b9ae743 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sun, 19 May 2019 14:37:32 -0400 Subject: [PATCH] Changed uiEvent.handlers into a uiprivArray; also fixed the buggy implementations of InsertAt and Delete. --- common/alloc.c | 18 +++++++------- common/events.c | 62 +++++++++++++++++-------------------------------- common/uipriv.h | 10 ++++---- 3 files changed, 36 insertions(+), 54 deletions(-) diff --git a/common/alloc.c b/common/alloc.c index 17106e46..30ca06b8 100644 --- a/common/alloc.c +++ b/common/alloc.c @@ -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); } diff --git a/common/events.c b/common/events.c index 638193d7..309c1c4e 100644 --- a/common/events.c +++ b/common/events.c @@ -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++; diff --git a/common/uipriv.h b/common/uipriv.h index 9ffdf57c..ceee8d6a 100644 --- a/common/uipriv.h +++ b/common/uipriv.h @@ -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