diff --git a/include/list.h b/include/list.h index ce9f201be..2edf38dfb 100644 --- a/include/list.h +++ b/include/list.h @@ -18,8 +18,7 @@ /** Static list initialization */ #define LIST_INIT(dtor) { \ - .start = NULL, \ - .end = NULL, \ + .array = NULL, \ .length = 0, \ .capacity = 0, \ .lock = PTHREAD_MUTEX_INITIALIZER, \ @@ -27,12 +26,12 @@ } #define list_length(list) ((list)->length) -#define list_at(list, index) ((list)->length > index ? (list)->start[index] : NULL) +#define list_at(list, index) ((list)->length > index ? (list)->array[index] : NULL) #define list_first(list) list_at(list, 0) #define list_last(list) list_at(list, (list)->length-1) #define list_foreach(ptr, list) for (int _i = 0, _p; _p = 1, _i < (list)->length; _i++) \ - for (ptr = (list)->start[_i]; _p--; ) + for (ptr = (list)->array[_i]; _p--; ) /** Callback to destroy list elements. * @@ -44,10 +43,9 @@ typedef void (*dtor_cb_t)(void *); typedef int (*cmp_cb_t)(const void *, const void *); struct list { - void **start; /**< Array of pointers to list elements */ - void **end; /**< Array of pointers to list elements */ - size_t capacity; /**< Size of list::start in elements */ - size_t length; /**< Number of elements of list::start which are in use */ + void **array; /**< Array of pointers to list elements */ + size_t capacity; /**< Size of list::array in elements */ + size_t length; /**< Number of elements of list::array which are in use */ dtor_cb_t destructor; /**< A destructor which gets called for every list elements during list_destroy() */ pthread_mutex_t lock; /**< A mutex to allow thread-safe accesses */ }; @@ -61,6 +59,9 @@ void list_destroy(struct list *l); /** Append an element to the end of the list */ void list_push(struct list *l, void *p); +/** Remove all occurences of a list item */ +void list_remove(struct list *l, void *p); + /** Search the list for an element whose first element is a character array which matches name. * * @see Only possible because of ยง1424 of http://c0x.coding-guidelines.com/6.7.2.1.html diff --git a/lib/list.c b/lib/list.c index d42674481..89f37589a 100644 --- a/lib/list.c +++ b/lib/list.c @@ -21,8 +21,7 @@ void list_init(struct list *l, dtor_cb_t dtor) l->length = 0; l->capacity = 0; - l->start = NULL; - l->end = NULL; + l->array = NULL; } void list_destroy(struct list *l) @@ -34,10 +33,9 @@ void list_destroy(struct list *l) l->destructor(p); } - free(l->start); + free(l->array); - l->start = - l->end = NULL; + l->array = NULL; l->length = l->capacity = 0; @@ -51,36 +49,51 @@ void list_push(struct list *l, void *p) pthread_mutex_lock(&l->lock); /* Resize array if out of capacity */ - if (l->end == l->start + l->capacity) { + if (l->length >= l->capacity) { l->capacity += LIST_CHUNKSIZE; - l->start = realloc(l->start, l->capacity * sizeof(void *)); + l->array = realloc(l->array, l->capacity * sizeof(void *)); } - l->start[l->length] = p; + l->array[l->length] = p; l->length++; - l->end = &l->start[l->length]; pthread_mutex_unlock(&l->lock); } -void * list_lookup(struct list *l, const char *needle) +void list_remove(struct list *l, void *p) { - int cmp(const void *elm, const void *needle) { - char *name = * (char **) elm; /* Ugly hack: the lookup key (name) must be the first element in the list element struct */ - - return strcmp(name, needle); + int removed = 0; + + pthread_mutex_lock(&l->lock); + + for (int i = 0; i < l->length; i++) { + if (l->array[i] == p) + removed++; + else + l->array[i - removed] = l->array[i]; + } + + l->length -= removed; + + pthread_mutex_unlock(&l->lock); +} + +void * list_lookup(struct list *l, const char *name) +{ + int cmp_helper(const void *a, const void *b) { + return strcmp(* (char **) a, b); } - return list_search(l, cmp, (void *) needle); + return list_search(l, cmp_helper, (void *) name); } int list_contains(struct list *l, void *p) { - int cmp(const void *a, const void *b) { + int cmp_helper(const void *a, const void *b) { return a == b; } - return list_count(l, cmp, p); + return list_count(l, cmp_helper, p); } int list_count(struct list *l, cmp_cb_t cmp, void *ctx) @@ -123,6 +136,8 @@ void list_sort(struct list *l, cmp_cb_t cmp) } pthread_mutex_lock(&l->lock); - qsort(l->start, l->length, sizeof(void *), cmp_helper); + + qsort(l->array, l->length, sizeof(void *), cmp_helper); + pthread_mutex_unlock(&l->lock); } \ No newline at end of file