PSI sics-cvs-psi-2008-10-02
This commit is contained in:
177
mclist.h
Normal file
177
mclist.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/** \file
|
||||
* \brief Type safe list handling
|
||||
*
|
||||
* The definition and implementation make use of macros extensively to create
|
||||
* a list type and related functions for any node type.
|
||||
* <b>However, accessing the list does not use macros.</b>
|
||||
* The list is implemented as a singly linked list. Sequential appending
|
||||
* to the tail is fast, because the list structure contains
|
||||
* a pointer to the anchor of the last accessed node.
|
||||
*
|
||||
* For a local list, mclist.c must be included after
|
||||
* the declaration of the node type and after defining the macro MC_NAME
|
||||
* and optionally MC_TYPE and MC_NEXT.
|
||||
*
|
||||
* For a public list, in the header file mclist.h must be included after
|
||||
* the declaration of the node type and after defining the macro MC_NAME
|
||||
* and optionally MC_TYPE. In the implementation mclist.c
|
||||
* must be included after defining the macro MC_NAME and MC_IMPLEMENTATION
|
||||
* and optionally MC_TYPE and MC_NEXT.
|
||||
*
|
||||
* MC_NAME has one parameter and describes how to combine the list name
|
||||
* with the function names.
|
||||
*
|
||||
* MC_TYPE defines the node type. If undeclared it defaults to a pointer
|
||||
* to the name.
|
||||
*
|
||||
* MC_NEXT indicates the name of the link. It defaults to 'next'.
|
||||
*
|
||||
* MC_IMPLEMENTATION has no value and must be defined when the list type
|
||||
* was already declared. Typically this is done in a header file including mclist.h.
|
||||
*
|
||||
* The macros MC_NAME, MC_TYPE, MC_NEXT and MC_IMPLEMENTATION are undefined
|
||||
* within mclist.c and mclist.h and must be redefined for every list.
|
||||
*
|
||||
* \par Usage example
|
||||
* \code
|
||||
* // declare the Node type
|
||||
* typedef struct Node {
|
||||
* struct Node *next;
|
||||
* char *name;
|
||||
* } Node;
|
||||
*
|
||||
* // this declaration leads to a list type 'NodeList' and fucntions names 'Node<fun>'
|
||||
* #define MC_NAME(T) Node##T
|
||||
* // the following line is not needed as 'next' is the default for the link
|
||||
* #define MC_NEXT next
|
||||
* // the following line is not needed as 'Node *' is the default for the type in this case
|
||||
* #define MC_TYPE Node *
|
||||
* // inside mclist.c, the list type is declared and the related functions are implemented
|
||||
* #include "mclist.c"
|
||||
*
|
||||
* int main(void) {
|
||||
* // declare and init the list
|
||||
* NodeList list={NULL};
|
||||
*
|
||||
* // create a node
|
||||
* Node *node;
|
||||
* node = malloc(sizeof(*node));
|
||||
* node->name = "First";
|
||||
*
|
||||
* // add node at the end of the list
|
||||
* NodeAdd(&list, node);
|
||||
*
|
||||
* // print the names of all list nodes
|
||||
* for (node = NodeFirst(&list); node != NULL; node = NodeNext(&list)) {
|
||||
* printf("%s\n", node->name);
|
||||
* }
|
||||
*
|
||||
* // alternative form not touching the list position
|
||||
* // only for the case, where no insert or take function is used inside the loop
|
||||
* for (node = list.head; node != NULL; node = node->next) {
|
||||
* printf("%s\n", node->name);
|
||||
* }
|
||||
*
|
||||
* // remove the node with the name "First"
|
||||
* for (node = NodeFirst(&list); node != NULL; node = NodeNext(&list)) {
|
||||
* if (strcmp(node->name, "First") == 0) {
|
||||
* free(NodeTake(&list));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
#ifndef MC_TYPE
|
||||
/** \brief default node type
|
||||
*/
|
||||
#define MC_TYPE MC_NAME()*
|
||||
#endif
|
||||
|
||||
#ifndef MC_List_TYPE
|
||||
#define MC_List_TYPE MC_NAME(List)
|
||||
#define MC_First_FUN MC_NAME(First)
|
||||
#define MC_This_FUN MC_NAME(This)
|
||||
#define MC_Next_FUN MC_NAME(Next)
|
||||
#define MC_End_FUN MC_NAME(End)
|
||||
#define MC_Insert_FUN MC_NAME(Insert)
|
||||
#define MC_Add_FUN MC_NAME(Add)
|
||||
#define MC_Take_FUN MC_NAME(Take)
|
||||
#define MC_Delete_FUN MC_NAME(Delete)
|
||||
#endif
|
||||
|
||||
typedef struct MC_List_TYPE {
|
||||
MC_TYPE head;
|
||||
MC_TYPE *ptr;
|
||||
} MC_List_TYPE;
|
||||
|
||||
/** \brief move to first node and get it
|
||||
* \param list the list
|
||||
* \return the node or NULL when the list is empty
|
||||
*
|
||||
* Actual position on return: at the first node
|
||||
*/
|
||||
MC_TYPE MC_First_FUN(MC_List_TYPE *list);
|
||||
|
||||
/** \brief get the node at the current position
|
||||
* \param list the list
|
||||
* \return the node or NULL when the list is empty or the position is at end
|
||||
*
|
||||
* Actual position on return: not changed (= at the returned node)
|
||||
*/
|
||||
MC_TYPE MC_This_FUN(MC_List_TYPE *list);
|
||||
|
||||
/** \brief get the node after the current node
|
||||
* \param list the list
|
||||
* \return the node or NULL when the list is empty or the position is at end
|
||||
*
|
||||
* Actual position on return: incremented (= at the returned node or at end)
|
||||
*/
|
||||
MC_TYPE MC_Next_FUN(MC_List_TYPE *list);
|
||||
|
||||
/** \brief move the position to the end
|
||||
* \param list the list
|
||||
*
|
||||
* Actual position on return: at end
|
||||
*/
|
||||
void MC_End_FUN(MC_List_TYPE *list);
|
||||
|
||||
/** \brief insert at the current position, i.e. before the current node
|
||||
* \param list the list
|
||||
* \param node the node to be inserted
|
||||
*
|
||||
* Actual position on return: at the inserted node
|
||||
*/
|
||||
void MC_Insert_FUN(MC_List_TYPE *list, MC_TYPE node);
|
||||
|
||||
/** \brief add at the end of the list
|
||||
* \param list the list
|
||||
* \param node the node to be added
|
||||
*
|
||||
* Actual position on return: at the inserted node (before the last node, not at end!)
|
||||
*/
|
||||
void MC_Add_FUN(MC_List_TYPE *list, MC_TYPE node);
|
||||
|
||||
/** \brief remove the node at the current position
|
||||
* \param list the list
|
||||
* \return the removed node or NULL when the list is empty or the position is at end
|
||||
*
|
||||
* Actual position on return: after the taken node
|
||||
*
|
||||
* Note: it is the responsibility of the caller to free the node if it is not used
|
||||
* anymore
|
||||
*/
|
||||
MC_TYPE MC_Take_FUN(MC_List_TYPE *list);
|
||||
|
||||
/** \brief remove and delete all nodes
|
||||
* \param list the list
|
||||
* \param deleteFunc the kill function of the node
|
||||
*
|
||||
* Calls the kill function for every node. The list is
|
||||
* empty on return.
|
||||
*/
|
||||
void MC_Delete_FUN(MC_List_TYPE *list, void (*deleteFunc)(MC_TYPE node));
|
||||
|
||||
#ifndef MC_DO_NOT_UNDEF
|
||||
#undef MC_NAME
|
||||
#undef MC_TYPE
|
||||
#endif
|
||||
Reference in New Issue
Block a user