bemenu/lib/list.c
2014-10-22 22:46:51 +03:00

145 lines
3.0 KiB
C

#include "internal.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void
list_free_list(struct list *list)
{
assert(list);
free(list->items);
list->allocated = list->count = 0;
list->items = NULL;
}
void
list_free_items(struct list *list, list_free_fun destructor)
{
assert(list);
for (uint32_t i = 0; i < list->count; ++i)
destructor(list->items[i]);
list_free_list(list);
}
void*
list_get_items(const struct list *list, uint32_t *out_nmemb)
{
assert(list);
if (out_nmemb)
*out_nmemb = list->count;
return list->items;
}
/** !!! Frees the old list, not items !!! */
bool
list_set_items_no_copy(struct list *list, void *items, uint32_t nmemb)
{
assert(list);
list_free_list(list);
if (!items || nmemb == 0) {
items = NULL;
nmemb = 0;
}
list->items = items;
list->allocated = list->count = nmemb;
return true;
}
/** !!! Frees the old items and list !!! */
bool
list_set_items(struct list *list, const void *items, uint32_t nmemb, list_free_fun destructor)
{
assert(list);
if (!items || nmemb == 0) {
list_free_items(list, destructor);
return true;
}
void *new_items;
if (!(new_items = calloc(sizeof(void*), nmemb)))
return false;
memcpy(new_items, items, sizeof(void*) * nmemb);
return list_set_items_no_copy(list, new_items, nmemb);
}
bool
list_grow(struct list *list, uint32_t step)
{
assert(list);
void *tmp;
uint32_t nsize = sizeof(struct bm_item*) * (list->allocated + step);
if (!list->items || !(tmp = realloc(list->items, nsize))) {
if (!(tmp = malloc(nsize)))
return false;
if (list->items) {
memcpy(tmp, list->items, sizeof(struct bm_item*) * list->allocated);
free(list->items);
}
}
list->items = tmp;
list->allocated += step;
memset(&list->items[list->count], 0, sizeof(struct bm_item*) * (list->allocated - list->count));
return true;
}
bool
list_add_item_at(struct list *list, void *item, uint32_t index)
{
assert(list && item);
if ((!list->items || list->allocated <= list->count) && !list_grow(list, 32))
return false;
if (index + 1 != list->count) {
uint32_t i = index;
memmove(&list->items[i + 1], &list->items[i], sizeof(struct bm_item*) * (list->count - i));
}
list->items[index] = item;
list->count++;
return true;
}
bool
list_add_item(struct list *list, void *item)
{
assert(list);
return list_add_item_at(list, item, list->count);
}
bool
list_remove_item_at(struct list *list, uint32_t index)
{
assert(list);
uint32_t i = index;
if (!list->items || list->count <= i)
return false;
memmove(&list->items[i], &list->items[i], sizeof(void*) * (list->count - i));
return true;
}
bool
list_remove_item(struct list *list, const void *item)
{
uint32_t i;
for (i = 0; i < list->count && list->items[i] != item; ++i);
return list_remove_item_at(list, i);
}
/* vim: set ts=8 sw=4 tw=0 :*/