Files
sics/mclist.h
koennecke 91d4af0541 - Adapted indenation to new agreed upon system
- Added support for second generation scriptcontext based counter
2009-02-13 09:00:03 +00:00

178 lines
5.5 KiB
C

/** \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