diff --git a/shared/LL.c b/shared/LL.c index 528d3f7..6856e57 100644 --- a/shared/LL.c +++ b/shared/LL.c @@ -1,3 +1,19 @@ +/** \file LL.c + * Define routines to deal with doubly linked lists + */ + +/* This file is part of LCDproc. + * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + * + * Copyright(c) 1999, William Ferrell + * (c) 2000, Guillaume Filion + * (c) 2001, Joris Robijn + * (c) 2008, Peter Marschall + * + */ + #include #include #include "LL.h" @@ -9,14 +25,16 @@ //TODO: Comment everything //TODO: Test everything? -////////////////////////////////////////////////////////////////////// -// Creates a new list... + +/** Create new linked list. + * \return Pointer to freshly created list object; \c NULL on error. + */ LinkedList * -LL_new () +LL_new() { LinkedList *list; - list = malloc (sizeof (LinkedList)); + list = malloc(sizeof(LinkedList)); if (!list) return NULL; @@ -31,12 +49,17 @@ LL_new () return list; } -////////////////////////////////////////////////////////////////////// -// TODO: test this function -// Destroys the entire list -// Warning! Does not free the list data! (only the list itself) + +/** Destroy the entire list. + * + * Note: this does not free the data, only the list itself + * + * \param list List object to be destroyed. + * \retval <0 error + * \retval 0 success + */ int -LL_Destroy (LinkedList * list) +LL_Destroy(LinkedList *list) { LL_node *node, *next; @@ -48,35 +71,46 @@ LL_Destroy (LinkedList * list) for (node = node->next; node && node->next; node = next) { // Avoid accessing "node" after it's freed.. :) next = node->next; - if (LL_node_Destroy (node) < 0) + if (LL_node_Destroy(node) < 0) return -1; } - free (list); + free(list); return 0; } -////////////////////////////////////////////////////////////////////// -// TODO: test this function -// Warning! This does not assert that the node data is free! + +/** Destroy a node. + * + * Warning! This does not assert that the node data is free! + * + * \param node Node to be destroyed. + * \retval <0 error + * \retval 0 success + */ int -LL_node_Destroy (LL_node * node) +LL_node_Destroy(LL_node *node) { if (!node) return -1; - if (LL_node_Unlink (node) < 0) + if (LL_node_Unlink(node) < 0) return -1; - free (node); + free(node); return 0; } -////////////////////////////////////////////////////////////////////// + +/** Unlink a node from the list. + * \param node Node to be unlinked. + * \retval <0 error + * \retval 0 success + */ int -LL_node_Unlink (LL_node * node) +LL_node_Unlink(LL_node *node) { LL_node *next, *prev; @@ -97,25 +131,37 @@ LL_node_Unlink (LL_node * node) return 0; } -////////////////////////////////////////////////////////////////////// -// Frees the data in a list node, if not NULL... + +/** Free the data in a list node. + * \param node Node, whose data is to be destroyed. + * \retval <0 error: illegal node, or no node data to destroy. + * \retval 0 success + */ int -LL_node_DestroyData (LL_node * node) +LL_node_DestroyData(LL_node *node) { if (!node) return -1; - if (node->data) - free (node->data); + if (node->data) { + free(node->data); + // prevent accidential double free() + node->data = NULL; + } else return -1; return 0; } -////////////////////////////////////////////////////////////////////// -// Returns to the beginning of the list... + +/* Return to the beginning of the list. + * Set list's "current" pointer to the first node in the list. + * \param list List object. + * \retval <0 error: no list given + * \retval 0 success + */ int -LL_Rewind (LinkedList * list) +LL_Rewind(LinkedList *list) { if (!list) return -1; @@ -133,10 +179,15 @@ LL_Rewind (LinkedList * list) return 0; } -////////////////////////////////////////////////////////////////////// -// Goes to the end of the list... + +/** Jump to the end of the list. + * Set list's "current" pointer to the last node in the list. + * \param list List object. + * \retval <0 error: no list given + * \retval 0 success + */ int -LL_End (LinkedList * list) +LL_End(LinkedList *list) { if (!list) return -1; @@ -149,10 +200,15 @@ LL_End (LinkedList * list) return 0; } -////////////////////////////////////////////////////////////////////// -// Go to the next node + +/** Go to the next node of the list. + * Advance list's "current" pointer to the next node in the list. + * \param list List object. + * \retval <0 error: no list given or no next node + * \retval 0 success + */ int -LL_Next (LinkedList * list) +LL_Next(LinkedList *list) { if (!list) return -1; @@ -167,10 +223,15 @@ LL_Next (LinkedList * list) } } -////////////////////////////////////////////////////////////////////// -// Go to the previous node + +/** Go to the previous node of the list. + * Set list's "current" pointer to the previous node in the list. + * \param list List object. + * \retval <0 error: no list given or no previous node + * \retval 0 success + */ int -LL_Prev (LinkedList * list) +LL_Prev(LinkedList *list) { if (!list) return -1; @@ -185,10 +246,14 @@ LL_Prev (LinkedList * list) } } -////////////////////////////////////////////////////////////////////// -// Data manipulation + +/** Access current node's data. + * \param list List object. + * \retval <0 error: no list given, or no data in current node + * \retval 0 success + */ void * -LL_Get (LinkedList * list) +LL_Get(LinkedList *list) { if (!list) return NULL; @@ -198,9 +263,15 @@ LL_Get (LinkedList * list) return list->current->data; } -////////////////////////////////////////////////////////////////////// + +/** Set/change current node's data. + * \param list List object. + * \param data Pointer to data to be set. + * \retval <0 error: no list given, or no current node + * \retval 0 success + */ int -LL_Put (LinkedList * list, void *data) +LL_Put(LinkedList *list, void *data) { if (!list) return -1; @@ -212,9 +283,13 @@ LL_Put (LinkedList * list, void *data) return 0; } -////////////////////////////////////////////////////////////////////// + +/** Get current node in list. + * \param list List object. + * \return Pointer to current node. + */ LL_node * -LL_GetNode (LinkedList * list) +LL_GetNode(LinkedList *list) { if (!list) return NULL; @@ -222,10 +297,18 @@ LL_GetNode (LinkedList * list) return list->current; } -////////////////////////////////////////////////////////////////////// -// Don't use this unless you know what you're doing. + +/** Set list's current pointr to a specific node. + * + * Warning: Don't use this unless you know what you're doing. + * + * \param list List object. + * \param list List object. + * \retval <0 error + * \retval 0 success + */ int -LL_PutNode (LinkedList * list, LL_node * node) +LL_PutNode(LinkedList *list, LL_node *node) { if (!list) return -1; @@ -237,62 +320,87 @@ LL_PutNode (LinkedList * list, LL_node * node) return 0; } -////////////////////////////////////////////////////////////////////// + +/** Access list's first node's data. + * Set list's "current" pointer to the first node and return its data. + * \param list List object. + * \return Pointer to first node's data; \c NULL on error. + */ void * -LL_GetFirst (LinkedList * list) // gets data from first node +LL_GetFirst(LinkedList *list) { if (!list) return NULL; - if (0 > LL_Rewind (list)) + if (0 > LL_Rewind(list)) return NULL; - return LL_Get (list); + return LL_Get(list); } -////////////////////////////////////////////////////////////////////// -// + +/** Access next node's data. + * Advance list's "current" pointer to the next node and return its data. + * \param list List object. + * \return Pointer to next node's data; \c NULL on error. + */ void * -LL_GetNext (LinkedList * list) // ... next node +LL_GetNext(LinkedList *list) { if (!list) return NULL; - if (0 > LL_Next (list)) + if (0 > LL_Next(list)) return NULL; - return LL_Get (list); + return LL_Get(list); } -////////////////////////////////////////////////////////////////////// + +/** Access previous node's data. + * Set list's "current" pointer to the previous node, and return its data. + * \param list List object. + * \return Pointer to previous node's data; \c NULL on error. + */ void * -LL_GetPrev (LinkedList * list) // ... prev node +LL_GetPrev(LinkedList *list) { if (!list) return NULL; - if (0 > LL_Prev (list)) + if (0 > LL_Prev(list)) return NULL; - return LL_Get (list); + return LL_Get(list); } -////////////////////////////////////////////////////////////////////// + +/** Access list's last node's data. + * Set list's "current" pointer to the last node and return its data. + * \param list List object. + * \return Pointer to last node's data; \c NULL on error. + */ void * -LL_GetLast (LinkedList * list) // ... last node +LL_GetLast(LinkedList *list) { if (!list) return NULL; - if (0 > LL_End (list)) + if (0 > LL_End(list)) return NULL; - return LL_Get (list); + return LL_Get(list); } -////////////////////////////////////////////////////////////////////// + +/** Add/append a new node after current one in the list. + * \param list List object. + * \param add Pointer to new node's data. + * \retval <0 error + * \retval 0 success + */ int -LL_AddNode (LinkedList * list, void *add) // Adds node AFTER current one +LL_AddNode(LinkedList *list, void *add) { LL_node *node; @@ -304,7 +412,7 @@ LL_AddNode (LinkedList * list, void *add) // Adds node AFTER current one //LL_dprint(list); - node = malloc (sizeof (LL_node)); + node = malloc(sizeof(LL_node)); if (!node) return -1; //printf("Allocated node\n"); @@ -346,9 +454,15 @@ LL_AddNode (LinkedList * list, void *add) // Adds node AFTER current one return 0; } -////////////////////////////////////////////////////////////////////// + +/** Add/insert a new node before current one in the list. + * \param list List object. + * \param add Pointer to new node's data. + * \retval <0 error + * \retval 0 success + */ int -LL_InsertNode (LinkedList * list, void *add) // Adds node BEFORE current one +LL_InsertNode(LinkedList *list, void *add) { LL_node *node; @@ -359,7 +473,7 @@ LL_InsertNode (LinkedList * list, void *add) // Adds node BEFORE current one if (!list->current) return -1; - node = malloc (sizeof (LL_node)); + node = malloc(sizeof(LL_node)); if (!node) return -1; @@ -384,7 +498,7 @@ LL_InsertNode (LinkedList * list, void *add) // Adds node BEFORE current one // Removes a node from the link // ... and advances one node forward void * -LL_DeleteNode (LinkedList * list) +LL_DeleteNode(LinkedList *list) { LL_node *next, *prev; void *data; @@ -399,8 +513,8 @@ LL_DeleteNode (LinkedList * list) return NULL; /* - printf ("LL_DeleteNode: Before...\n"); - LL_dprint (list); + printf("LL_DeleteNode: Before...\n"); + LL_dprint(list); */ next = list->current->next; @@ -419,42 +533,53 @@ LL_DeleteNode (LinkedList * list) //if(list->current->data) free(list->current->data); list->current->data = NULL; - free (list->current); + free(list->current); list->current = next; /* - printf ("LL_DeleteNode: After...\n"); - LL_dprint (list); + printf("LL_DeleteNode: After...\n"); + LL_dprint(list); */ return data; } -////////////////////////////////////////////////////////////////////// -// Removes a specific node... + +/** Remove a specific node from the list. + * find a node by a pointer to it's data and remove it. + * \param list List object. + * \param data Pointer to data of not to delete. + * \return Pointer to data of deleted node; \c NULL on error. + */ void * -LL_Remove (LinkedList * list, void *data) +LL_Remove(LinkedList *list, void *data) { void *find; if (!list) return NULL; - LL_Rewind (list); + LL_Rewind(list); do { - find = LL_Get (list); + find = LL_Get(list); if (find == data) - return LL_DeleteNode (list); - } while (LL_Next (list) == 0); + return LL_DeleteNode(list); + } while (LL_Next(list) == 0); return NULL; } -////////////////////////////////////////////////////////////////////// -// Stack operations + +/** Add/append a new node after the last one in the list. + * Jump to the last node in the list and append a new node. + * \param list List object. + * \param add Pointer to new node's data. + * \retval <0 error + * \retval 0 success + */ int -LL_Push (LinkedList * list, void *add) // Add node to end of list +LL_Push(LinkedList *list, void *add) // Add node to end of list { if (!list) return -1; @@ -462,69 +587,97 @@ LL_Push (LinkedList * list, void *add) // Add node to end of list return -1; // printf("Going to end of list...\n"); - LL_End (list); + LL_End(list); // printf("Adding node...\n"); - return LL_AddNode (list, add); + return LL_AddNode(list, add); } -////////////////////////////////////////////////////////////////////// + +/** Remove the last node from the list, and return its data. + * Jump to the last node in the list, remove it from the list and return its data. + * \param list List object. + * \return Pointer to data of deleted node; \c NULL on error. + */ void * -LL_Pop (LinkedList * list) // Remove node from end of list +LL_Pop(LinkedList *list) // Remove node from end of list { if (!list) return NULL; - if (0 > LL_End (list)) + if (0 > LL_End(list)) return NULL; - return LL_DeleteNode (list); + return LL_DeleteNode(list); } -////////////////////////////////////////////////////////////////////// + +/** Access list's last node's data. + * Set list's "current" pointer to the last node and return its data. + * \param list List object. + * \return Pointer to last node's data; \c NULL on error. + */ void * -LL_Top (LinkedList * list) // Peek at end node +LL_Top(LinkedList *list) // Peek at end node { - return LL_GetLast (list); + return LL_GetLast(list); } -////////////////////////////////////////////////////////////////////// + +/** Remove the first node from the list, and return its data. + * Jump to the first node in the list, remove it from the list and return its data. + * \param list List object. + * \return Pointer to data of deleted node; \c NULL on error. + */ void * -LL_Shift (LinkedList * list) // Remove node from start of list +LL_Shift(LinkedList *list) // Remove node from start of list { if (!list) return NULL; - if (0 > LL_Rewind (list)) + if (0 > LL_Rewind(list)) return NULL; - return LL_DeleteNode (list); + return LL_DeleteNode(list); } -////////////////////////////////////////////////////////////////////// + +/** Access list's first node's data. + * Set list's "current" pointer to the first node and return its data. + * \param list List object. + * \return Pointer to first node's data; \c NULL on error. + */ void * -LL_Look (LinkedList * list) // Peek at first node +LL_Look(LinkedList *list) // Peek at first node { - return LL_GetFirst (list); + return LL_GetFirst(list); } -////////////////////////////////////////////////////////////////////// + +/** Add/insert a new node before the first one in the list. + * Jump to the first node in the list and insert a new node before that one. + * \param list List object. + * \param add Pointer to new node's data. + * \retval <0 error + * \retval 0 success + */ int -LL_Unshift (LinkedList * list, void *add) // Add node to beginning of list +LL_Unshift(LinkedList *list, void *add) // Add node to beginning of list { if (!list) return -1; if (!add) return -1; - LL_Rewind (list); + LL_Rewind(list); - return LL_InsertNode (list, add); + return LL_InsertNode(list, add); } + ////////////////////////////////////////////////////////////////////// int -LL_Roll (LinkedList * list) // Make last node first +LL_Roll(LinkedList *list) // Make last node first { LL_node *node, *next; @@ -532,7 +685,7 @@ LL_Roll (LinkedList * list) // Make last node first return -1; //if(!list->current) return -1; - if (0 > LL_End (list)) + if (0 > LL_End(list)) return -1; // Avoid rolling an empty list, or unlinking the head/tail... @@ -549,9 +702,9 @@ LL_Roll (LinkedList * list) // Make last node first node = list->current; - LL_node_Unlink (node); + LL_node_Unlink(node); - if (0 > LL_Rewind (list)) + if (0 > LL_Rewind(list)) return -1; next = list->head.next; @@ -564,9 +717,10 @@ LL_Roll (LinkedList * list) // Make last node first return 0; } + ////////////////////////////////////////////////////////////////////// int -LL_UnRoll (LinkedList * list) // Roll the other way... +LL_UnRoll(LinkedList *list) // Roll the other way... { LL_node *node, *prev; @@ -574,7 +728,7 @@ LL_UnRoll (LinkedList * list) // Roll the other way... return -1; //if(!list->current) return -1; - if (0 > LL_Rewind (list)) + if (0 > LL_Rewind(list)) return -1; // Avoid rolling an empty list, or unlinking the head/tail... @@ -591,9 +745,9 @@ LL_UnRoll (LinkedList * list) // Roll the other way... node = list->current; - LL_node_Unlink (node); + LL_node_Unlink(node); - if (0 > LL_End (list)) + if (0 > LL_End(list)) return -1; prev = list->tail.prev; @@ -606,11 +760,12 @@ LL_UnRoll (LinkedList * list) // Roll the other way... return 0; } + ////////////////////////////////////////////////////////////////////// // Add an item to the end of its "priority group" // The list is assumed to be sorted already... int -LL_PriorityEnqueue (LinkedList * list, void *add, int compare (void *, void *)) +LL_PriorityEnqueue(LinkedList *list, void *add, int compare(void *, void *)) { void *data; int i; @@ -624,28 +779,29 @@ LL_PriorityEnqueue (LinkedList * list, void *add, int compare (void *, void *)) // From the end of the list, keep searching while we're "less than" // the given nodes... - LL_End (list); + LL_End(list); do { - data = LL_Get (list); + data = LL_Get(list); if (data) { - i = compare (add, data); + i = compare(add, data); if (i >= 0) // If we're in the right place, add it and exit { - LL_AddNode (list, add); + LL_AddNode(list, add); return 0; } } - } while (LL_Prev (list) == 0); + } while (LL_Prev(list) == 0); // If we're less than *everything*, put it at the beginning - LL_Unshift (list, add); + LL_Unshift(list, add); return 0; } + ////////////////////////////////////////////////////////////////////// int -LL_SwapNodes (LL_node * one, LL_node * two) // Switch two nodes positions... +LL_SwapNodes(LL_node *one, LL_node *two) // Switch two nodes positions... { LL_node *firstprev, *firstnext; LL_node *secondprev, *secondnext; @@ -687,16 +843,21 @@ LL_SwapNodes (LL_node * one, LL_node * two) // Switch two nodes positions... } + ////////////////////////////////////////////////////////////////////// int -LL_nSwapNodes (int one, int two) // Switch two nodes positions... +LL_nSwapNodes(int one, int two) // Switch two nodes positions... { return -1; } -////////////////////////////////////////////////////////////////////// + +/** Calculate the length of a list. + * \param list List object. + * \return Number of nodes in the list; \c -1 on error. + */ int -LL_Length (LinkedList * list) // Returns # of nodes in entire list +LL_Length(LinkedList *list) // Returns # of nodes in entire list { LL_node *node; int num = 0; @@ -712,6 +873,7 @@ LL_Length (LinkedList * list) // Returns # of nodes in entire list return num; } + ////////////////////////////////////////////////////////////////////// // Searching... // Goes to the list item which matches "value", and returns the @@ -722,7 +884,7 @@ LL_Length (LinkedList * list) // Returns # of nodes in entire list // Note that this does *not* rewind the list first! You should do // it yourself if you want to start from the beginning! void * -LL_Find (LinkedList * list, int compare (void *, void *), void *value) +LL_Find(LinkedList *list, int compare(void *, void *), void *value) { void *data; @@ -734,22 +896,23 @@ LL_Find (LinkedList * list, int compare (void *, void *), void *value) return NULL; do { - data = LL_Get (list); - if (0 == compare (data, value)) + data = LL_Get(list); + if (0 == compare(data, value)) return data; - } while (LL_Next (list) == 0); + } while (LL_Next(list) == 0); return NULL; } + ////////////////////////////////////////////////////////////////////// // Array like... // Goes to the nth list item, and returns the // data found there. // void * -LL_GetByIndex (LinkedList * list, int index) +LL_GetByIndex(LinkedList *list, int index) { LL_node *node; int num = 0; @@ -767,11 +930,19 @@ LL_GetByIndex (LinkedList * list, int index) return NULL; // got past the end } -////////////////////////////////////////////////////////////////////// -// Sorts the list, then rewinds it... -// + +/** Sort list by its contents. + * The list gets sorted using a comparison function for the data of its nodes. + * After the sorting, the list's current pointer is set to the first node. + * \param list List object. + * \param compare Pointer to a comparison function, that takes to void pointers + is arguments and returns an int > 0 when the first argument + is considered greater then the second. + * \retval <0 error + * \retval 0 success. + */ int -LL_Sort (LinkedList * list, int compare (void *, void *)) +LL_Sort(LinkedList *list, int compare(void *, void *)) { int i, j; // Junk / loop variables int numnodes; // number of nodes in list @@ -783,28 +954,28 @@ LL_Sort (LinkedList * list, int compare (void *, void *)) if (!compare) return -1; - numnodes = LL_Length (list); // get the number of nodes... - if (0 > LL_End (list)) + numnodes = LL_Length(list); // get the number of nodes... + if (0 > LL_End(list)) return -1; // Find the last node. - last = LL_GetNode (list); + last = LL_GetNode(list); if (numnodes < 2) return 0; for (i = numnodes - 1; i > 0; i--) { - LL_Rewind (list); // get the first node again + LL_Rewind(list); // get the first node again best = last; // reset our "best" node for (j = 0; j < i; j++) { - current = LL_GetNode (list); + current = LL_GetNode(list); // If we found a better match... - if (compare (current->data, best->data) > 0) { + if (compare(current->data, best->data) > 0) { best = current; // keep track of the "best" match } - LL_Next (list); // Go to the next node. + LL_Next(list); // Go to the next node. } - LL_SwapNodes (last, best); // Switch two nodes... + LL_SwapNodes(last, best); // Switch two nodes... if (best) last = best->prev; else @@ -814,24 +985,24 @@ LL_Sort (LinkedList * list, int compare (void *, void *)) } //return LLFindFirst(current); // return pointer to the first node. - LL_Rewind (list); + LL_Rewind(list); return 0; } void -LL_dprint (LinkedList * list) +LL_dprint(LinkedList *list) { LL_node *current; current = &list->head; - printf ("Head: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", list->head.prev, &list->head, list->head.next); + printf("Head: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", list->head.prev, &list->head, list->head.next); for (current = current->next; current != &list->tail; current = current->next) { - printf ("node: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", current->prev, current, current->next); + printf("node: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", current->prev, current, current->next); } - printf ("Tail: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", list->tail.prev, &list->tail, list->tail.next); + printf("Tail: prev:\t0x%p\taddr:\t0x%p\tnext:\t0x%p\n", list->tail.prev, &list->tail, list->tail.next); }