From 1b8fbbd843ddeb5fc81c9303db9c590a436d499b Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 9 Jul 2018 12:10:32 -0700 Subject: progress --- ccan/take/take.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 ccan/take/take.c (limited to 'ccan/take/take.c') diff --git a/ccan/take/take.c b/ccan/take/take.c new file mode 100644 index 0000000..c628aac --- /dev/null +++ b/ccan/take/take.c @@ -0,0 +1,115 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include +#include +#include +#include +#include + +static const void **takenarr; +static const char **labelarr; +static size_t max_taken, num_taken; +static size_t allocfail; +static void (*allocfailfn)(const void *p); + +void *take_(const void *p, const char *label) +{ + /* Overallocate: it's better than risking calloc returning NULL! */ + if (unlikely(label && !labelarr)) + labelarr = calloc(max_taken+1, sizeof(*labelarr)); + + if (unlikely(num_taken == max_taken)) { + const void **new; + + new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1)); + if (unlikely(!new)) { + if (allocfailfn) { + allocfail++; + allocfailfn(p); + return NULL; + } + /* Otherwise we leak p. */ + return (void *)p; + } + takenarr = new; + /* Once labelarr is set, we maintain it. */ + if (labelarr) + labelarr = realloc(labelarr, + sizeof(*labelarr) * (max_taken+1)); + max_taken++; + } + if (unlikely(labelarr)) + labelarr[num_taken] = label; + takenarr[num_taken++] = p; + + return (void *)p; +} + +static size_t find_taken(const void *p) +{ + size_t i; + + for (i = 0; i < num_taken; i++) { + if (takenarr[i] == p) + return i+1; + } + return 0; +} + +bool taken(const void *p) +{ + size_t i; + + if (!p && unlikely(allocfail)) { + allocfail--; + return true; + } + + i = find_taken(p); + if (!i) + return false; + + memmove(&takenarr[i-1], &takenarr[i], + (--num_taken - (i - 1))*sizeof(takenarr[0])); + return true; +} + +bool is_taken(const void *p) +{ + if (!p && unlikely(allocfail)) + return true; + + return find_taken(p) > 0; +} + +const char *taken_any(void) +{ + static char pointer_buf[32]; + + if (num_taken == 0) + return NULL; + + /* We're *allowed* to have some with labels, some without. */ + if (labelarr) { + size_t i; + for (i = 0; i < num_taken; i++) + if (labelarr[i]) + return labelarr[i]; + } + + sprintf(pointer_buf, "%p", takenarr[0]); + return pointer_buf; +} + +void take_cleanup(void) +{ + max_taken = num_taken = 0; + free(takenarr); + takenarr = NULL; + free(labelarr); + labelarr = NULL; +} + +void take_allocfail(void (*fn)(const void *p)) +{ + allocfailfn = fn; +} -- cgit v1.2.3