2015-03-18 00:31:48 +01:00
|
|
|
/** A generic linked list
|
|
|
|
*
|
|
|
|
* Linked lists a used for several data structures in the code.
|
|
|
|
*
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2015-06-02 21:53:04 +02:00
|
|
|
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
|
|
|
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
2015-08-07 01:11:43 +02:00
|
|
|
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
2015-06-02 21:53:04 +02:00
|
|
|
*********************************************************************************/
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
#include <stdlib.h>
|
2015-09-19 15:26:30 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2015-03-18 00:31:48 +01:00
|
|
|
#include "list.h"
|
|
|
|
|
2015-03-21 15:23:57 +01:00
|
|
|
void list_init(struct list *l, dtor_cb_t dtor)
|
2015-03-18 00:31:48 +01:00
|
|
|
{
|
|
|
|
pthread_mutex_init(&l->lock, NULL);
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2015-03-21 15:23:57 +01:00
|
|
|
l->destructor = dtor;
|
2015-05-06 11:40:44 +02:00
|
|
|
l->length = 0;
|
2015-10-09 12:50:35 +02:00
|
|
|
l->capacity = 0;
|
|
|
|
|
|
|
|
l->start = NULL;
|
|
|
|
l->end = NULL;
|
2015-03-18 00:31:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void list_destroy(struct list *l)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&l->lock);
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
if (l->destructor) {
|
|
|
|
for (void *e = l->start; e != l->end; e++)
|
|
|
|
l->destructor(e);
|
2015-03-18 00:31:48 +01:00
|
|
|
}
|
2015-10-09 12:50:35 +02:00
|
|
|
|
|
|
|
free(l->start);
|
|
|
|
|
|
|
|
l->start =
|
|
|
|
l->end = NULL;
|
|
|
|
|
|
|
|
l->length =
|
|
|
|
l->capacity = 0;
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2015-03-21 15:20:22 +01:00
|
|
|
pthread_mutex_unlock(&l->lock);
|
2015-03-18 00:31:48 +01:00
|
|
|
pthread_mutex_destroy(&l->lock);
|
|
|
|
}
|
|
|
|
|
2015-03-18 15:47:49 +01:00
|
|
|
void list_push(struct list *l, void *p)
|
2015-03-18 00:31:48 +01:00
|
|
|
{
|
|
|
|
pthread_mutex_lock(&l->lock);
|
2015-10-09 12:50:35 +02:00
|
|
|
|
|
|
|
/* Resize array if out of capacity */
|
|
|
|
if (l->end == l->start + l->capacity) {
|
|
|
|
l->capacity += LIST_CHUNKSIZE;
|
|
|
|
l->start = realloc(l->start, l->capacity * sizeof(void *));
|
|
|
|
}
|
|
|
|
|
|
|
|
l->start[l->length] = p;
|
2015-05-06 11:40:44 +02:00
|
|
|
l->length++;
|
2015-10-09 12:50:35 +02:00
|
|
|
l->end = &l->start[l->length];
|
2015-03-18 15:47:49 +01:00
|
|
|
|
2015-03-18 00:31:48 +01:00
|
|
|
pthread_mutex_unlock(&l->lock);
|
|
|
|
}
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
void * list_lookup(struct list *l, const char *name)
|
2015-06-10 14:56:55 +02:00
|
|
|
{
|
2015-10-09 12:50:35 +02:00
|
|
|
int cmp(const void *a, const void *b) {
|
|
|
|
return strcmp(*(char **) a, b);
|
2015-06-10 14:56:55 +02:00
|
|
|
}
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
return list_search(l, cmp, (void *) name);
|
2015-06-10 14:56:55 +02:00
|
|
|
}
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
void * list_search(struct list *l, cmp_cb_t cmp, void *ctx)
|
2015-09-19 15:26:30 +02:00
|
|
|
{
|
2015-10-09 12:50:35 +02:00
|
|
|
pthread_mutex_lock(&l->lock);
|
|
|
|
|
|
|
|
void *e;
|
|
|
|
list_foreach(e, l) {
|
|
|
|
if (!cmp(e, ctx))
|
|
|
|
goto out;
|
2015-09-19 15:26:30 +02:00
|
|
|
}
|
2015-10-09 12:50:35 +02:00
|
|
|
|
|
|
|
e = NULL; /* not found */
|
|
|
|
|
|
|
|
out: pthread_mutex_unlock(&l->lock);
|
2015-09-19 15:26:30 +02:00
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
return e;
|
2015-09-19 15:26:30 +02:00
|
|
|
}
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
void list_sort(struct list *l, cmp_cb_t cmp)
|
2015-08-07 01:11:43 +02:00
|
|
|
{
|
2015-10-09 12:50:35 +02:00
|
|
|
int cmp_helper(const void *a, const void *b) {
|
|
|
|
return cmp(*(void **) a, *(void **) b);
|
2015-03-18 00:31:48 +01:00
|
|
|
}
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
pthread_mutex_lock(&l->lock);
|
|
|
|
qsort(l->start, l->length, sizeof(void *), cmp_helper);
|
|
|
|
pthread_mutex_unlock(&l->lock);
|
|
|
|
}
|