rtl_433/src/list.c

86 lines
2.3 KiB
C

/** @file
Generic list.
Copyright (C) 2018 Christian Zuckschwerdt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
#include "list.h"
#include "fatal.h"
#include <stdlib.h>
#include <stdio.h>
void list_ensure_size(list_t *list, size_t min_size)
{
if (!list->elems || list->size < min_size) {
// the input pointer is still valid if reallocation fails
void *elems_realloc = realloc(list->elems, min_size * sizeof(*list->elems));
if (!elems_realloc) {
FATAL_REALLOC("list_ensure_size()");
}
list->elems = elems_realloc;
list->size = min_size;
list->elems[list->len] = NULL; // ensure a terminating NULL
}
}
void list_push(list_t *list, void *p)
{
if (list->len + 1 >= list->size) // account for terminating NULL
list_ensure_size(list, list->size < 8 ? 8 : list->size + list->size / 2);
list->elems[list->len++] = p;
list->elems[list->len] = NULL; // ensure a terminating NULL
}
void list_push_all(list_t *list, void **p)
{
for (void **iter = p; iter && *iter; ++iter)
list_push(list, *iter);
}
void list_remove(list_t *list, size_t idx, list_elem_free_fn elem_free)
{
if (idx >= list->len) {
return; // report error?
}
if (elem_free) {
elem_free(list->elems[idx]);
}
for (size_t i = idx; i < list->len; ++i) { // list might contain NULLs
list->elems[i] = list->elems[i + 1]; // ensures a terminating NULL
}
list->len--;
}
#if defined(__clang__)
// ignore "call to function _free through pointer to incorrect function type"
__attribute__((no_sanitize("undefined")))
#endif
void list_clear(list_t *list, list_elem_free_fn elem_free)
{
if (elem_free) {
for (size_t i = 0; i < list->len; ++i) { // list might contain NULLs
elem_free(list->elems[i]);
}
}
list->len = 0;
if (list->elems) {
list->elems[0] = NULL; // ensure a terminating NULL
}
}
void list_free_elems(list_t *list, list_elem_free_fn elem_free)
{
list_clear(list, elem_free);
free(list->elems);
list->elems = NULL;
list->size = 0;
}