From add250cdcb1b8ba826704755b3d5686d7156aed4 Mon Sep 17 00:00:00 2001 From: Gatsby Van Date: Sun, 21 Jan 2024 13:38:45 +0800 Subject: [PATCH] merge clist from datalink_repo --- df_datalink_sp/src/include/clist.h | 118 ++++++++++ df_datalink_sp/src/util/clist.c | 342 +++++++++++++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 df_datalink_sp/src/include/clist.h create mode 100644 df_datalink_sp/src/util/clist.c diff --git a/df_datalink_sp/src/include/clist.h b/df_datalink_sp/src/include/clist.h new file mode 100644 index 0000000..8a2e925 --- /dev/null +++ b/df_datalink_sp/src/include/clist.h @@ -0,0 +1,118 @@ + +// +// clist.h +// +// Copyright (c) 2010 TJ Holowaychuk +// + +#ifndef __CLIST_H__ +#define __CLIST_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + + /* + * clist_t iterator direction. + */ + + typedef enum + { + LIST_HEAD, + LIST_TAIL + } clist_direction_t; + + /* + * clist_t node struct. + */ + + typedef struct clist_node + { + struct clist_node *prev; + struct clist_node *next; + void *val; + } clist_node_t; + + /* + * clist_t struct. + */ + + typedef struct + { + clist_node_t *head; + clist_node_t *tail; + uint32_t len; + void (*free)(void *val); + int8_t (*compare)(void *a, void *b); + } clist_t; + + /* + * clist_t iterator struct. + */ + + typedef struct + { + clist_node_t *next; + clist_direction_t direction; + } clist_iterator_t; + + // Node prototypes. + + clist_node_t * + clist_node_new(void *val); + + // clist_t prototypes. + + clist_t * + clist_new(void); + + clist_node_t * + clist_rpush(clist_t *self, clist_node_t *node); + + clist_node_t * + clist_lpush(clist_t *self, clist_node_t *node); + + clist_node_t * + clist_find(clist_t *self, void *val); + + clist_node_t * + clist_at(clist_t *self, int index); + + clist_node_t * + clist_rpop(clist_t *self); + + clist_node_t * + clist_lpop(clist_t *self); + + void + clist_remove(clist_t *self, clist_node_t *node); + + void + clist_clear(clist_t *self); + + void + clist_destroy(clist_t *self); + + // clist_t iterator prototypes. + + clist_iterator_t * + clist_iterator_new(clist_t *list, clist_direction_t direction); + + clist_iterator_t * + clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction); + + clist_node_t * + clist_iterator_next(clist_iterator_t *self); + + void + clist_iterator_destroy(clist_iterator_t *self); + +#ifdef __cplusplus +} +#endif + +#endif /* __CLIBS_LIST_H__ */ diff --git a/df_datalink_sp/src/util/clist.c b/df_datalink_sp/src/util/clist.c new file mode 100644 index 0000000..33c2382 --- /dev/null +++ b/df_datalink_sp/src/util/clist.c @@ -0,0 +1,342 @@ +#ifndef LIST_MALLOC +#define LIST_MALLOC malloc +#endif + +#ifndef LIST_FREE +#define LIST_FREE free +#endif + +// +// list.c +// +// Copyright (c) 2010 TJ Holowaychuk +// + +#include +#include "clist.h" + +/* + * Allocates a new clist_node_t. NULL on failure. + */ + +clist_node_t * +clist_node_new(void *val) +{ + clist_node_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_node_t)))) + return NULL; + self->prev = NULL; + self->next = NULL; + self->val = val; + return self; +} + +/* + * Allocate a new clist_t. NULL on failure. + */ + +clist_t * +clist_new(void) +{ + clist_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_t)))) + return NULL; + self->head = NULL; + self->tail = NULL; + self->free = NULL; + self->compare = NULL; + self->len = 0; + return self; +} + +/* + * Remove all the node in list. + * @self: Pointer to the list + */ + +void clist_clear(clist_t *self) +{ + uint32_t len = self->len; + clist_node_t *next; + clist_node_t *curr = self->head; + + while (len) + { + next = curr->next; + if (self->free) + self->free(curr->val); + LIST_FREE(curr); + curr = next; + len--; + } +} + +/* + * Free the list. + * @self: Pointer to the list + */ + +void clist_destroy(clist_t *self) +{ + clist_clear(self); + LIST_FREE(self); +} + +/* + * Append the given node to the list + * and return the node, NULL on failure. + * @self: Pointer to the list for popping node + * @node: the node to push + */ + +clist_node_t * +clist_rpush(clist_t *self, clist_node_t *node) +{ + if (!node) + return NULL; + + if (self->len) + { + node->prev = self->tail; + node->next = NULL; + self->tail->next = node; + self->tail = node; + } + else + { + self->head = self->tail = node; + node->prev = node->next = NULL; + } + + ++self->len; + return node; +} + +/* + * Return / detach the last node in the list, or NULL. + * @self: Pointer to the list for popping node + */ + +clist_node_t * +clist_rpop(clist_t *self) +{ + if (!self->len) + return NULL; + + clist_node_t *node = self->tail; + + if (--self->len) + { + (self->tail = node->prev)->next = NULL; + } + else + { + self->tail = self->head = NULL; + } + + node->next = node->prev = NULL; + return node; +} + +/* + * Return / detach the first node in the list, or NULL. + * @self: Pointer to the list for popping node + */ + +clist_node_t * +clist_lpop(clist_t *self) +{ + if (!self->len) + return NULL; + + clist_node_t *node = self->head; + + if (--self->len) + { + (self->head = node->next)->prev = NULL; + } + else + { + self->head = self->tail = NULL; + } + + node->next = node->prev = NULL; + return node; +} + +/* + * Prepend the given node to the list + * and return the node, NULL on failure. + * @self: Pointer to the list for pushing node + * @node: the node to push + */ + +clist_node_t * +clist_lpush(clist_t *self, clist_node_t *node) +{ + if (!node) + return NULL; + + if (self->len) + { + node->next = self->head; + node->prev = NULL; + self->head->prev = node; + self->head = node; + } + else + { + self->head = self->tail = node; + node->prev = node->next = NULL; + } + + ++self->len; + return node; +} + +/* + * Return the node associated to val or NULL. + * @self: Pointer to the list for finding given value + * @val: Value to find + */ + +clist_node_t * +clist_find(clist_t *self, void *val) +{ + clist_iterator_t *it = clist_iterator_new(self, LIST_HEAD); + clist_node_t *node; + + while ((node = clist_iterator_next(it))) + { + if (self->compare) + { + if (self->compare(val, node->val) == 0) + { + clist_iterator_destroy(it); + return node; + } + } + else + { + if (val == node->val) + { + clist_iterator_destroy(it); + return node; + } + } + } + + clist_iterator_destroy(it); + return NULL; +} + +/* + * Return the node at the given index or NULL. + * @self: Pointer to the list for finding given index + * @index: the index of node in the list + */ + +clist_node_t * +clist_at(clist_t *self, int index) +{ + clist_direction_t direction = LIST_HEAD; + + if (index < 0) + { + direction = LIST_TAIL; + index = ~index; + } + + if ((unsigned)index < self->len) + { + clist_iterator_t *it = clist_iterator_new(self, direction); + clist_node_t *node = clist_iterator_next(it); + while (index--) + node = clist_iterator_next(it); + clist_iterator_destroy(it); + return node; + } + + return NULL; +} + +/* + * Remove the given node from the list, freeing it and it's value. + * @self: Pointer to the list to delete a node + * @node: Pointer the node to be deleted + */ + +void clist_remove(clist_t *self, clist_node_t *node) +{ + node->prev + ? (node->prev->next = node->next) + : (self->head = node->next); + + node->next + ? (node->next->prev = node->prev) + : (self->tail = node->prev); + + if (self->free) + self->free(node->val); + + LIST_FREE(node); + --self->len; +} + +/* + * Allocate a new clist_iterator_t. NULL on failure. + * Accepts a direction, which may be LIST_HEAD or LIST_TAIL. + */ + +clist_iterator_t * +clist_iterator_new(clist_t *list, clist_direction_t direction) +{ + clist_node_t *node = direction == LIST_HEAD + ? list->head + : list->tail; + return clist_iterator_new_from_node(node, direction); +} + +/* + * Allocate a new clist_iterator_t with the given start + * node. NULL on failure. + */ + +clist_iterator_t * +clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction) +{ + clist_iterator_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_iterator_t)))) + return NULL; + self->next = node; + self->direction = direction; + return self; +} + +/* + * Return the next clist_node_t or NULL when no more + * nodes remain in the list. + */ + +clist_node_t * +clist_iterator_next(clist_iterator_t *self) +{ + clist_node_t *curr = self->next; + if (curr) + { + self->next = self->direction == LIST_HEAD + ? curr->next + : curr->prev; + } + return curr; +} + +/* + * Free the list iterator. + */ + +void clist_iterator_destroy(clist_iterator_t *self) +{ + LIST_FREE(self); + self = NULL; +}