2015-12-12 12:37:57 +01:00
|
|
|
/** A generic list implementation.
|
2015-03-18 00:31:48 +01:00
|
|
|
*
|
2015-12-12 12:37:57 +01:00
|
|
|
* This is a generic implementation of a list which can store void pointers to
|
|
|
|
* arbitrary data. The data itself is not stored or managed by the list.
|
|
|
|
*
|
|
|
|
* Internally, an array of pointers is used to store the pointers.
|
|
|
|
* If needed, this array will grow by realloc().
|
2015-03-18 00:31:48 +01:00
|
|
|
*
|
|
|
|
* @file
|
2015-06-02 21:53:04 +02:00
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2018-06-29 09:07:47 +02:00
|
|
|
* @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
*********************************************************************************/
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2017-02-16 09:04:12 -03:00
|
|
|
#pragma once
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2016-04-16 19:54:26 +02:00
|
|
|
#include <stdbool.h>
|
2018-03-26 14:33:42 +02:00
|
|
|
#include <sys/types.h>
|
2015-03-18 00:31:48 +01:00
|
|
|
#include <pthread.h>
|
|
|
|
|
2018-07-02 13:07:45 +02:00
|
|
|
#include <villas/common.h>
|
2017-03-12 17:04:43 -03:00
|
|
|
|
2018-06-28 13:42:50 +02:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"{
|
|
|
|
#endif
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
#define LIST_CHUNKSIZE 16
|
2015-03-18 00:31:48 +01:00
|
|
|
|
|
|
|
/** Static list initialization */
|
2016-04-16 19:54:26 +02:00
|
|
|
#define LIST_INIT() { \
|
2015-12-04 01:49:00 +01:00
|
|
|
.array = NULL, \
|
2015-10-09 12:50:35 +02:00
|
|
|
.length = 0, \
|
|
|
|
.capacity = 0, \
|
2017-03-12 17:04:43 -03:00
|
|
|
.lock = PTHREAD_MUTEX_INITIALIZER, \
|
|
|
|
.state = STATE_INITIALIZED \
|
2015-03-18 00:31:48 +01:00
|
|
|
}
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2017-07-02 23:53:48 +02:00
|
|
|
#define LIST_INIT_STATIC(l) \
|
2017-07-25 12:40:05 +02:00
|
|
|
__attribute__((constructor(105))) static void UNIQUE(__ctor)() {\
|
2017-07-24 19:21:57 +02:00
|
|
|
if ((l)->state == STATE_DESTROYED) \
|
|
|
|
list_init(l); \
|
2017-07-02 23:53:48 +02:00
|
|
|
} \
|
2017-07-25 12:40:05 +02:00
|
|
|
__attribute__((destructor(105))) static void UNIQUE(__dtor)() { \
|
2017-07-02 23:53:48 +02:00
|
|
|
list_destroy(l, NULL, false); \
|
|
|
|
}
|
|
|
|
|
2015-05-06 11:40:44 +02:00
|
|
|
#define list_length(list) ((list)->length)
|
2017-03-25 21:23:31 +01:00
|
|
|
#define list_at_safe(list, index) ((list)->length > index ? (list)->array[index] : NULL)
|
2017-07-02 23:53:48 +02:00
|
|
|
#define list_at(list, index) ((list)->array[index])
|
2015-10-09 12:50:35 +02:00
|
|
|
|
|
|
|
#define list_first(list) list_at(list, 0)
|
|
|
|
#define list_last(list) list_at(list, (list)->length-1)
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2017-05-05 19:24:16 +00:00
|
|
|
/** Callback to search or sort a list. */
|
2015-10-09 12:50:35 +02:00
|
|
|
typedef int (*cmp_cb_t)(const void *, const void *);
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2015-12-12 12:37:57 +01:00
|
|
|
/* The list data structure. */
|
2015-10-09 12:50:35 +02:00
|
|
|
struct list {
|
2015-12-04 01:49:00 +01:00
|
|
|
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 */
|
2015-10-09 12:50:35 +02:00
|
|
|
pthread_mutex_t lock; /**< A mutex to allow thread-safe accesses */
|
2017-03-12 17:04:43 -03:00
|
|
|
enum state state; /**< The state of this list. */
|
2015-03-18 00:31:48 +01:00
|
|
|
};
|
|
|
|
|
2015-12-12 12:37:57 +01:00
|
|
|
/** Initialize a list.
|
|
|
|
*
|
|
|
|
* @param l A pointer to the list data structure.
|
|
|
|
*/
|
2017-08-28 14:34:47 +02:00
|
|
|
int list_init(struct list *l);
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2016-04-16 19:54:26 +02:00
|
|
|
/** Destroy a list and call destructors for all list elements
|
|
|
|
*
|
|
|
|
* @param free free() all list members during when calling list_destroy()
|
|
|
|
* @param dtor A function pointer to a desctructor which will be called for every list item when the list is destroyed.
|
|
|
|
* @param l A pointer to the list data structure.
|
|
|
|
*/
|
2017-02-18 10:43:01 -05:00
|
|
|
int list_destroy(struct list *l, dtor_cb_t dtor, bool free);
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
/** Append an element to the end of the list */
|
2015-03-18 15:47:49 +01:00
|
|
|
void list_push(struct list *l, void *p);
|
2015-03-18 00:31:48 +01:00
|
|
|
|
2015-12-04 01:49:00 +01:00
|
|
|
/** Remove all occurences of a list item */
|
|
|
|
void list_remove(struct list *l, void *p);
|
|
|
|
|
2015-12-12 12:37:57 +01:00
|
|
|
/** Return the first list element which is identified by a string in its first member variable.
|
2015-12-11 18:20:04 +01:00
|
|
|
*
|
2015-12-12 12:37:57 +01:00
|
|
|
* List elements are pointers to structures of the following form:
|
2015-12-11 18:20:04 +01:00
|
|
|
*
|
|
|
|
* struct obj {
|
|
|
|
* char *name;
|
|
|
|
* // more members
|
|
|
|
* }
|
2015-09-19 15:26:30 +02:00
|
|
|
*
|
|
|
|
* @see Only possible because of §1424 of http://c0x.coding-guidelines.com/6.7.2.1.html
|
|
|
|
*/
|
2015-10-09 12:50:35 +02:00
|
|
|
void * list_lookup(struct list *l, const char *name);
|
|
|
|
|
2018-05-24 09:05:00 +02:00
|
|
|
ssize_t list_lookup_index(struct list *l, const char *name);
|
|
|
|
|
2015-11-23 16:32:24 +01:00
|
|
|
/** Return the first element of the list for which cmp returns zero */
|
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-11-23 16:32:24 +01:00
|
|
|
/** Returns the number of occurences for which cmp returns zero when called on all list elements. */
|
|
|
|
int list_count(struct list *l, cmp_cb_t cmp, void *ctx);
|
|
|
|
|
|
|
|
/** Return 0 if list contains pointer p */
|
|
|
|
int list_contains(struct list *l, void *p);
|
|
|
|
|
2015-10-09 12:50:35 +02:00
|
|
|
/** Sort the list using the quicksort algorithm of libc */
|
2017-05-23 09:56:47 +02:00
|
|
|
void list_sort(struct list *l, cmp_cb_t cmp);
|
|
|
|
|
|
|
|
/** Set single element in list */
|
2017-07-24 19:21:57 +02:00
|
|
|
int list_set(struct list *l, int index, void *value);
|
2018-03-26 12:52:04 +02:00
|
|
|
|
|
|
|
/** Return index in list for value.
|
|
|
|
*
|
|
|
|
* @retval <0 No list entry matching \p value was found.
|
|
|
|
* @retval >=0 Entry \p value was found at returned index.
|
|
|
|
*/
|
|
|
|
ssize_t list_index(struct list *l, void *value);
|
2018-06-28 13:42:50 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
2018-06-29 09:07:47 +02:00
|
|
|
#endif
|