1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00
VILLASnode/lib/list.c

234 lines
4.4 KiB
C
Raw Permalink Normal View History

/** A generic linked list
*
* Linked lists a used for several data structures in the code.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
2017-04-27 12:56:43 +02:00
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* 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 3 of the License, or
* any later version.
*
2017-04-27 12:56:43 +02:00
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
2017-04-27 12:56:43 +02:00
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2015-06-02 21:53:04 +02:00
*********************************************************************************/
#include <stdlib.h>
#include <string.h>
2017-12-09 02:19:28 +08:00
#include <villas/list.h>
#include <villas/utils.h>
/* Compare functions */
static int cmp_lookup(const void *a, const void *b) {
const struct {
char *name;
} *obj = a;
return strcmp(obj->name, b);
}
2016-03-29 08:59:26 +02:00
static int cmp_contains(const void *a, const void *b) {
return a == b ? 0 : 1;
}
2016-03-29 08:59:26 +02:00
static int cmp_sort(const void *a, const void *b, void *thunk) {
cmp_cb_t cmp = (cmp_cb_t) thunk;
return cmp(*(void **) a, *(void **) b);
}
int list_init(struct list *l)
{
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_DESTROYED);
pthread_mutex_init(&l->lock, NULL);
2015-08-07 01:11:43 +02:00
2015-05-06 11:40:44 +02:00
l->length = 0;
l->capacity = 0;
l->array = NULL;
2017-03-12 17:04:43 -03:00
l->state = STATE_INITIALIZED;
2017-10-18 15:39:53 +02:00
return 0;
}
int list_destroy(struct list *l, dtor_cb_t destructor, bool release)
{
pthread_mutex_lock(&l->lock);
2015-08-07 01:11:43 +02:00
2017-03-12 17:04:43 -03:00
assert(l->state != STATE_DESTROYED);
for (size_t i = 0; i < list_length(l); i++) {
2018-03-26 12:51:43 +02:00
void *e = list_at(l, i);
if (destructor)
2018-03-26 12:51:43 +02:00
destructor(e);
if (release)
2018-03-26 12:51:43 +02:00
free(e);
}
free(l->array);
l->length = -1;
l->capacity = 0;
2018-03-26 12:51:43 +02:00
l->array = NULL;
l->state = STATE_DESTROYED;
2015-08-07 01:11:43 +02:00
2015-03-21 15:20:22 +01:00
pthread_mutex_unlock(&l->lock);
pthread_mutex_destroy(&l->lock);
return 0;
}
2015-03-18 15:47:49 +01:00
void list_push(struct list *l, void *p)
{
pthread_mutex_lock(&l->lock);
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_INITIALIZED);
/* Resize array if out of capacity */
if (l->length >= l->capacity) {
l->capacity += LIST_CHUNKSIZE;
l->array = realloc(l->array, l->capacity * sizeof(void *));
}
l->array[l->length] = p;
2015-05-06 11:40:44 +02:00
l->length++;
2015-03-18 15:47:49 +01:00
pthread_mutex_unlock(&l->lock);
}
void list_remove(struct list *l, void *p)
{
int removed = 0;
pthread_mutex_lock(&l->lock);
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_INITIALIZED);
for (size_t i = 0; i < list_length(l); i++) {
2018-03-26 12:51:43 +02:00
if (list_at(l, i) == p)
removed++;
else
2018-03-26 12:51:43 +02:00
l->array[i - removed] = list_at(l, i);
}
l->length -= removed;
pthread_mutex_unlock(&l->lock);
}
void * list_lookup(struct list *l, const char *name)
{
return list_search(l, cmp_lookup, (void *) name);
2015-12-04 01:54:33 +01:00
}
ssize_t list_lookup_index(struct list *l, const char *name)
{
void *ptr = list_lookup(l, name);
if (!ptr)
return -1;
return list_index(l, ptr);
}
2015-12-04 01:54:33 +01:00
int list_contains(struct list *l, void *p)
{
return list_count(l, cmp_contains, p);
}
int list_count(struct list *l, cmp_cb_t cmp, void *ctx)
{
int c = 0;
2018-03-26 12:51:43 +02:00
void *e;
pthread_mutex_lock(&l->lock);
2015-12-04 01:54:33 +01:00
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_INITIALIZED);
for (size_t i = 0; i < list_length(l); i++) {
2018-03-26 12:51:43 +02:00
e = list_at(l, i);
if (cmp(e, ctx) == 0)
c++;
}
pthread_mutex_unlock(&l->lock);
return c;
}
void * list_search(struct list *l, cmp_cb_t cmp, void *ctx)
{
void *e;
pthread_mutex_lock(&l->lock);
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_INITIALIZED);
for (size_t i = 0; i < list_length(l); i++) {
e = list_at(l, i);
if (cmp(e, ctx) == 0)
goto out;
}
e = NULL; /* not found */
out: pthread_mutex_unlock(&l->lock);
return e;
}
void list_sort(struct list *l, cmp_cb_t cmp)
2015-08-07 01:11:43 +02:00
{
pthread_mutex_lock(&l->lock);
2017-03-12 17:04:43 -03:00
assert(l->state == STATE_INITIALIZED);
qsort_r(l->array, l->length, sizeof(void *), cmp_sort, (void *) cmp);
pthread_mutex_unlock(&l->lock);
2017-05-23 09:56:47 +02:00
}
int list_set(struct list *l, int index, void *value)
{
if (index >= l->length)
return -1;
l->array[index] = value;
2017-07-24 19:33:35 +02:00
2017-05-23 09:56:47 +02:00
return 0;
2017-07-24 19:33:35 +02:00
}
2018-03-26 12:52:04 +02:00
ssize_t list_index(struct list *l, void *p)
{
void *e;
ssize_t f;
pthread_mutex_lock(&l->lock);
assert(l->state == STATE_INITIALIZED);
for (size_t i = 0; i < list_length(l); i++) {
e = list_at(l, i);
if (e == p) {
f = i;
goto found;
}
}
f = -1;
found: pthread_mutex_unlock(&l->lock);
return f;
}