/* $Id$ * */ #ifndef __PJ_LIST_H__ #define __PJ_LIST_H__ /** * @file list.h * @brief Linked List data structure. */ #include PJ_BEGIN_DECL /* * @defgroup PJ_DS Data Structure. * @ingroup PJ */ /** * @defgroup PJ_LIST Linked List * @ingroup PJ_DS * @{ * * List in PJLIB is implemented as doubly-linked list, and it won't require * dynamic memory allocation (just as all PJLIB data structures). The list here * should be viewed more like a low level C list instead of high level C++ list * (which normally are easier to use but require dynamic memory allocations), * therefore all caveats with C list apply here too (such as you can NOT put * a node in more than one lists). * * \section pj_list_example_sec Examples * * See below for examples on how to manipulate linked list: * - @ref page_pjlib_samples_list_c * - @ref page_pjlib_list_test */ /** * Use this macro in the start of the structure declaration to declare that * the structure can be used in the linked list operation. This macro simply * declares additional member @a prev and @a next to the structure. * @hideinitializer */ #define PJ_DECL_LIST_MEMBER(type) type *prev; /** List @a prev. */ \ type *next /** List @a next. */ /** * This structure describes generic list node and list. The owner of this list * must initialize the 'value' member to an appropriate value (typically the * owner itself). */ struct pj_list { PJ_DECL_LIST_MEMBER(void); }; /** * Initialize the list. * Initially, the list will have no member, and function pj_list_empty() will * always return nonzero (which indicates TRUE) for the newly initialized * list. * * @param node The list head. */ PJ_INLINE(void) pj_list_init(pj_list_type * node) { ((pj_list*)node)->next = ((pj_list*)node)->prev = node; } /** * Check that the list is empty. * * @param node The list head. * * @return Non-zero if the list is not-empty, or zero if it is empty. * */ PJ_INLINE(int) pj_list_empty(const pj_list_type * node) { return ((pj_list*)node)->next == node; } /** * Insert the node to the list before the specified element position. * * @param pos The element to which the node will be inserted before. * @param node The element to be inserted. * * @return void. */ PJ_IDECL(void) pj_list_insert_before(pj_list_type *pos, pj_list_type *node); /** * Inserts all nodes in \a nodes to the target list. * * @param lst The target list. * @param nodes Nodes list. */ PJ_IDECL(void) pj_list_insert_nodes_before(pj_list_type *lst, pj_list_type *nodes); /** * Insert a node to the list after the specified element position. * * @param pos The element in the list which will precede the inserted * element. * @param node The element to be inserted after the position element. * * @return void. */ PJ_IDECL(void) pj_list_insert_after(pj_list_type *pos, pj_list_type *node); /** * Insert all nodes in \a nodes to the target list. * * @param lst The target list. * @param nodes Nodes list. */ PJ_IDECL(void) pj_list_insert_nodes_after(pj_list_type *lst, pj_list_type *nodes); /** * Remove elements from the source list, and insert them to the destination * list. The elements of the source list will occupy the * front elements of the target list. Note that the node pointed by \a list2 * itself is not considered as a node, but rather as the list descriptor, so * it will not be inserted to the \a list1. The elements to be inserted starts * at \a list2->next. If \a list2 is to be included in the operation, use * \a pj_list_insert_nodes_before. * * @param list1 The destination list. * @param list2 The source list. * * @return void. */ PJ_IDECL(void) pj_list_merge_first(pj_list_type *list1, pj_list_type *list2); /** * Remove elements from the second list argument, and insert them to the list * in the first argument. The elements from the second list will be appended * to the first list. Note that the node pointed by \a list2 * itself is not considered as a node, but rather as the list descriptor, so * it will not be inserted to the \a list1. The elements to be inserted starts * at \a list2->next. If \a list2 is to be included in the operation, use * \a pj_list_insert_nodes_before. * * @param list1 The element in the list which will precede the inserted * element. * @param list2 The element in the list to be inserted. * * @return void. */ PJ_IDECL(void) pj_list_merge_last( pj_list_type *list1, pj_list_type *list2); /** * Erase the node from the list it currently belongs. * * @param node The element to be erased. */ PJ_IDECL(void) pj_list_erase(pj_list_type *node); /** * Find node in the list. * * @param list The list head. * @param node The node element to be searched. * * @return The node itself if it is found in the list, or NULL if it is not * found in the list. */ PJ_IDECL(pj_list_type*) pj_list_find_node(pj_list_type *list, pj_list_type *node); /** * Search the list for the specified value, using the specified comparison * function. This function iterates on nodes in the list, started with the * first node, and call the user supplied comparison function until the * comparison function returns ZERO. * * @param list The list head. * @param value The user defined value to be passed in the comparison * function * @param comp The comparison function, which should return ZERO to * indicate that the searched value is found. * * @return The first node that matched, or NULL if it is not found. */ PJ_IDECL(pj_list_type*) pj_list_search(pj_list_type *list, void *value, int (*comp)(void *value, const pj_list_type *node) ); /** * @} */ #if PJ_FUNCTIONS_ARE_INLINED # include "list_i.h" #endif PJ_END_DECL #endif /* __PJ_LIST_H__ */