bl_iot_sdk/components/utils/include/utils_list.h
Robert Lipe 3bc544d9f3 clean components/ whitespace issues
image_conf, make_scripts_riscv -  Delete trailing spaces. Change tabs to 4 space multiples.

    .c and .h get tabs expanded to four spaces for consistency, traliing whitespace whacked.
    Makefiles do NOT get tabs changed.
2020-11-08 13:56:51 -06:00

581 lines
20 KiB
C

/*
* Copyright (c) 2020 Bouffalolab.
*
* This file is part of
* *** Bouffalolab Software Dev Kit ***
* (see www.bouffalolab.com).
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UTILS_LIST_H_
#define _UTILS_LIST_H_
#include <stddef.h>
struct utils_list_hdr
{
struct utils_list_hdr *next;
};
struct utils_list
{
/// pointer to first element of the list
struct utils_list_hdr *first;
/// pointer to the last element
struct utils_list_hdr *last;
};
/*
* FUNCTION DECLARATIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Initialize a list to defaults values.
* @param[in] list Pointer to the list structure.
****************************************************************************************
*/
void utils_list_init(struct utils_list *list);
/**
****************************************************************************************
* @brief Initialize a pool to default values, and initialize the relative free list.
*
* @param[in] list Pointer to the list structure
* @param[in] pool Pointer to the pool to be initialized
* @param[in] elmt_size Size of one element of the pool
* @param[in] elmt_cnt Nb of elements available in the pool
* @param[in] default_value Pointer to the default value of each element (may be NULL)
****************************************************************************************
*/
void utils_list_pool_init(struct utils_list *list, void *pool, size_t elmt_size, unsigned int elmt_cnt, void *default_value);
/**
****************************************************************************************
* @brief Add an element as last on the list.
*
* @param[in] list Pointer to the list structure
* @param[in] list_hdr Pointer to the header to add at the end of the list
****************************************************************************************
*/
void utils_list_push_back(struct utils_list *list,
struct utils_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Add an element as first on the list.
*
* @param[in] list Pointer to the list structure
* @param[in] list_hdr Pointer to the header to add at the beginning of the list
****************************************************************************************
*/
void utils_list_push_front(struct utils_list *list, struct utils_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Extract the first element of the list.
*
* @param[in] list Pointer to the list structure
*
* @return The pointer to the element extracted, and NULL if the list is empty.
****************************************************************************************
*/
struct utils_list_hdr *utils_list_pop_front(struct utils_list *list);
/**
****************************************************************************************
* @brief Search for a given element in the list, and extract it if found.
*
* @param[in] list Pointer to the list structure
* @param[in] list_hdr Pointer to the searched element
*
* @return CO_EMPTY if the list is empty, CO_FAIL if the element not found in the list,
* CO_OK else.
****************************************************************************************
*/
void utils_list_extract(struct utils_list *list, struct utils_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Searched a given element in the list.
*
* @param[in] list Pointer to the list structure
* @param[in] list_hdr Pointer to the searched element
*
* @return true if the element is found in the list, false otherwise
****************************************************************************************
*/
int utils_list_find(struct utils_list *list, struct utils_list_hdr *list_hdr);
/**
****************************************************************************************
* @brief Insert an element in a sorted list.
*
* This primitive use a comparison function from the parameter list to select where the
* element must be inserted.
*
* @param[in] list Pointer to the list.
* @param[in] element Pointer to the element to insert.
* @param[in] cmp Comparison function (return true if first element has to be inserted
* before the second one).
*
* @return Pointer to the element found and removed (NULL otherwise).
****************************************************************************************
*/
void utils_list_insert(struct utils_list * const list, struct utils_list_hdr * const element,
int (*cmp)(struct utils_list_hdr const *elementA,
struct utils_list_hdr const *elementB));
/**
****************************************************************************************
* @brief Insert an element in a sorted list after the provided element.
*
* This primitive use a comparison function from the parameter list to select where the
* element must be inserted.
*
* @param[in] list Pointer to the list.
* @param[in] prev_element Pointer to the element to find in the list
* @param[in] element Pointer to the element to insert.
*
* If prev_element is not found, the provided element is not inserted
****************************************************************************************
*/
void utils_list_insert_after(struct utils_list * const list, struct utils_list_hdr * const prev_element, struct utils_list_hdr * const element);
/**
****************************************************************************************
* @brief Insert an element in a sorted list before the provided element.
*
* This primitive use a comparison function from the parameter list to select where the
* element must be inserted.
*
* @param[in] list Pointer to the list.
* @param[in] next_element Pointer to the element to find in the list
* @param[in] element Pointer to the element to insert.
*
* If next_element is not found, the provided element is not inserted
****************************************************************************************
*/
void utils_list_insert_before(struct utils_list * const list, struct utils_list_hdr * const next_element, struct utils_list_hdr * const element);
/**
****************************************************************************************
* @brief Concatenate two lists.
* The resulting list is the list passed as the first parameter. The second list is
* emptied.
*
* @param[in] list1 First list (will get the result of the concatenation)
* @param[in] list2 Second list (will be emptied after the concatenation)
****************************************************************************************
*/
void utils_list_concat(struct utils_list *list1, struct utils_list *list2);
/**
****************************************************************************************
* @brief Remove the element in the list after the provided element.
*
* This primitive removes an element in the list. It is assume that element is part of
* the list.
*
* @param[in] list Pointer to the list.
* @param[in] prev_element Pointer to the previous element.
* NULL if @p element is the first element in the list
* @param[in] element Pointer to the element to remove.
*
****************************************************************************************
*/
void utils_list_remove(struct utils_list *list, struct utils_list_hdr *prev_element, struct utils_list_hdr *element);
/**
****************************************************************************************
* @brief Test if the list is empty.
*
* @param[in] list Pointer to the list structure.
*
* @return true if the list is empty, false else otherwise.
****************************************************************************************
*/
static inline int utils_list_is_empty(const struct utils_list *const list)
{
return (NULL == list->first);
}
/**
****************************************************************************************
* @brief Return the number of element of the list.
*
* @param[in] list Pointer to the list structure.
*
* @return The number of elements in the list.
****************************************************************************************
*/
unsigned int utils_list_cnt(const struct utils_list *const list);
/**
****************************************************************************************
* @brief Pick the first element from the list without removing it.
*
* @param[in] list Pointer to the list structure.
*
* @return First element address. Returns NULL pointer if the list is empty.
****************************************************************************************
*/
static inline struct utils_list_hdr *utils_list_pick(const struct utils_list *const list)
{
return list->first;
}
static inline struct utils_list_hdr *utils_list_pick_last(const struct utils_list *const list)
{
return list->last;
}
static inline struct utils_list_hdr *utils_list_next(const struct utils_list_hdr *const list_hdr)
{
return list_hdr->next;
}
/*
* Get offset of a member variable.
*
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define utils_offsetof(type, member) ((size_t)&(((type *)0)->member))
/*
* Get the struct for this entry.
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define utils_container_of(ptr, type, member) \
((type *) ((char *) (ptr) - utils_offsetof(type, member)))
/* for double link list */
typedef struct utils_dlist_s {
struct utils_dlist_s *prev;
struct utils_dlist_s *next;
} utils_dlist_t;
static inline void __utils_dlist_add(utils_dlist_t *node, utils_dlist_t *prev, utils_dlist_t *next)
{
node->next = next;
node->prev = prev;
prev->next = node;
next->prev = node;
}
/*
* Get the struct for this entry.
*
* @param[in] addr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_dlist_t within the struct.
*/
#define utils_dlist_entry(addr, type, member) \
((type *)((long)addr - utils_offsetof(type, member)))
static inline void utils_dlist_add(utils_dlist_t *node, utils_dlist_t *queue)
{
__utils_dlist_add(node, queue, queue->next);
}
static inline void utils_dlist_add_tail(utils_dlist_t *node, utils_dlist_t *queue)
{
__utils_dlist_add(node, queue->prev, queue);
}
static inline void utils_dlist_del(utils_dlist_t *node)
{
utils_dlist_t *prev = node->prev;
utils_dlist_t *next = node->next;
prev->next = next;
next->prev = prev;
}
static inline void utils_dlist_init(utils_dlist_t *node)
{
node->next = node->prev = node;
}
static inline void INIT_UTILS_DLIST_HEAD(utils_dlist_t *list)
{
list->next = list;
list->prev = list;
}
static inline int utils_dlist_empty(const utils_dlist_t *head)
{
return head->next == head;
}
/*
* Initialise the list.
*
* @param[in] list the list to be inited.
*/
#define UTILS_DLIST_INIT(list) {&(list), &(list)}
/*
* Get the first element from a list
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_dlist_t within the struct.
*/
#define utils_dlist_first_entry(ptr, type, member) \
utils_dlist_entry((ptr)->next, type, member)
/*
* Iterate over a list.
*
* @param[in] pos the &struct utils_dlist_t to use as a loop cursor.
* @param[in] head he head for your list.
*/
#define utils_dlist_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/*
* Iterate over a list safe against removal of list entry.
*
* @param[in] pos the &struct utils_dlist_t to use as a loop cursor.
* @param[in] n another &struct utils_dlist_t to use as temporary storage.
* @param[in] head he head for your list.
*/
#define utils_dlist_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/*
* Iterate over list of given type.
*
* @param[in] queue he head for your list.
* @param[in] node the &struct utils_dlist_t to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_dlist_t within the struct.
*/
#define utils_dlist_for_each_entry(queue, node, type, member) \
for (node = utils_container_of((queue)->next, type, member); \
&node->member != (queue); \
node = utils_container_of(node->member.next, type, member))
/*
* Iterate over list of given type safe against removal of list entry.
*
* @param[in] queue the head for your list.
* @param[in] n the type * to use as a temp.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_dlist_t within the struct.
*/
#define utils_dlist_for_each_entry_safe(queue, n, node, type, member) \
for (node = utils_container_of((queue)->next, type, member), \
n = (queue)->next ? (queue)->next->next : NULL; \
&node->member != (queue); \
node = utils_container_of(n, type, member), n = n ? n->next : NULL)
/*
* Get the struct for this entry.
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the variable within the struct.
*/
#define utils_list_entry(ptr, type, member) \
utils_container_of(ptr, type, member)
/*
* Iterate backwards over list of given type.
*
* @param[in] pos the type * to use as a loop cursor.
* @param[in] head he head for your list.
* @param[in] member the name of the utils_dlist_t within the struct.
* @param[in] type the type of the struct this is embedded in.
*/
#define utils_dlist_for_each_entry_reverse(pos, head, member, type) \
for (pos = utils_list_entry((head)->prev, type, member); \
&pos->member != (head); \
pos = utils_list_entry(pos->member.prev, type, member))
/*
* Get the list length.
*
* @param[in] queue the head for your list.
*/
static inline int utils_dlist_entry_number(utils_dlist_t *queue)
{
int num;
utils_dlist_t *cur = queue;
for (num=0;cur->next != queue;cur=cur->next, num++)
;
return num;
}
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define UTILS_DLIST_HEAD_INIT(name) { &(name), &(name) }
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define UTILS_DLIST_HEAD(name) \
utils_dlist_t name = UTILS_DLIST_HEAD_INIT(name)
/* for single link list */
typedef struct utils_slist_s {
struct utils_slist_s *next;
} utils_slist_t;
static inline void utils_slist_add(utils_slist_t *node, utils_slist_t *head)
{
node->next = head->next;
head->next = node;
}
static inline void utils_slist_add_tail(utils_slist_t *node, utils_slist_t *head)
{
while (head->next) {
head = head->next;
}
utils_slist_add(node, head);
}
static inline void utils_slist_del(utils_slist_t *node, utils_slist_t *head)
{
while (head->next) {
if (head->next == node) {
head->next = node->next;
break;
}
head = head->next;
}
}
static inline int utils_slist_empty(const utils_slist_t *head)
{
return !head->next;
}
static inline void utils_slist_init(utils_slist_t *head)
{
head->next = 0;
}
/*
* Iterate over list of given type.
*
* @param[in] queue he head for your list.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_slist_t within the struct.
*/
#define utils_slist_for_each_entry(queue, node, type, member) \
for (node = utils_container_of((queue)->next, type, member); \
&node->member; \
node = utils_container_of(node->member.next, type, member))
/*
* Iterate over list of given type safe against removal of list entry.
*
* @param[in] queue the head for your list.
* @param[in] tmp the type * to use as a temp.
* @param[in] node the type * to use as a loop cursor.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_slist_t within the struct.
*/
#define utils_slist_for_each_entry_safe(queue, tmp, node, type, member) \
for (node = utils_container_of((queue)->next, type, member), \
tmp = (queue)->next ? (queue)->next->next : NULL; \
&node->member; \
node = utils_container_of(tmp, type, member), tmp = tmp ? tmp->next : tmp)
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define UTILS_SLIST_HEAD_INIT(name) {0}
/*
* Initialise the list.
*
* @param[in] name the list to be initialized.
*/
#define UTILS_SLIST_HEAD(name) \
utils_slist_t name = UTILS_SLIST_HEAD_INIT(name)
/*
* Get the struct for this entry.
* @param[in] addr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_slist_t within the struct.
*/
#define utils_slist_entry(addr, type, member) ( \
addr ? (type *)((long)addr - utils_offsetof(type, member)) : (type *)addr \
)
/*
* Get the first element from a list.
*
* @param[in] ptr the list head to take the element from.
* @param[in] type the type of the struct this is embedded in.
* @param[in] member the name of the utils_slist_t within the struct.
*/
#define utils_slist_first_entry(ptr, type, member) \
utils_slist_entry((ptr)->next, type, member)
/*
* Get the list length.
*
* @param[in] queue the head for your list.
*/
static inline int utils_slist_entry_number(utils_slist_t *queue)
{
int num;
utils_slist_t *cur = queue;
for (num=0;cur->next;cur=cur->next, num++)
;
return num;
}
#endif