123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /*******************************************************************************
- * Copyright (c) 2009, 2013 IBM Corp.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- *
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Ian Craggs - initial API and implementation and/or initial documentation
- * Ian Craggs - updates for the async client
- *******************************************************************************/
- /**
- * @file
- * \brief functions which apply to linked list structures.
- *
- * These linked lists can hold data of any sort, pointed to by the content pointer of the
- * ListElement structure. ListElements hold the points to the next and previous items in the
- * list.
- * */
- #include "LinkedList.h"
- #include <stdlib.h>
- #include <string.h>
- #include "Heap.h"
- static int ListUnlink(List* aList, void* content, int(*callback)(void*, void*), int freeContent);
- /**
- * Sets a list structure to empty - all null values. Does not remove any items from the list.
- * @param newl a pointer to the list structure to be initialized
- */
- void ListZero(List* newl)
- {
- memset(newl, '\0', sizeof(List));
- /*newl->first = NULL;
- newl->last = NULL;
- newl->current = NULL;
- newl->count = newl->size = 0;*/
- }
- /**
- * Allocates and initializes a new list structure.
- * @return a pointer to the new list structure
- */
- List* ListInitialize(void)
- {
- List* newl = malloc(sizeof(List));
- ListZero(newl);
- return newl;
- }
- /**
- * Append an already allocated ListElement and content to a list. Can be used to move
- * an item from one list to another.
- * @param aList the list to which the item is to be added
- * @param content the list item content itself
- * @param newel the ListElement to be used in adding the new item
- * @param size the size of the element
- */
- void ListAppendNoMalloc(List* aList, void* content, ListElement* newel, size_t size)
- { /* for heap use */
- newel->content = content;
- newel->next = NULL;
- newel->prev = aList->last;
- if (aList->first == NULL)
- aList->first = newel;
- else
- aList->last->next = newel;
- aList->last = newel;
- ++(aList->count);
- aList->size += size;
- }
- /**
- * Append an item to a list.
- * @param aList the list to which the item is to be added
- * @param content the list item content itself
- * @param size the size of the element
- */
- void ListAppend(List* aList, void* content, size_t size)
- {
- ListElement* newel = malloc(sizeof(ListElement));
- ListAppendNoMalloc(aList, content, newel, size);
- }
- /**
- * Insert an item to a list at a specific position.
- * @param aList the list to which the item is to be added
- * @param content the list item content itself
- * @param size the size of the element
- * @param index the position in the list. If NULL, this function is equivalent
- * to ListAppend.
- */
- void ListInsert(List* aList, void* content, size_t size, ListElement* index)
- {
- ListElement* newel = malloc(sizeof(ListElement));
- if ( index == NULL )
- ListAppendNoMalloc(aList, content, newel, size);
- else
- {
- newel->content = content;
- newel->next = index;
- newel->prev = index->prev;
- index->prev = newel;
- if ( newel->prev != NULL )
- newel->prev->next = newel;
- else
- aList->first = newel;
- ++(aList->count);
- aList->size += size;
- }
- }
- /**
- * Finds an element in a list by comparing the content pointers, rather than the contents
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the list item content itself
- * @return the list item found, or NULL
- */
- ListElement* ListFind(List* aList, void* content)
- {
- return ListFindItem(aList, content, NULL);
- }
- /**
- * Finds an element in a list by comparing the content or pointer to the content. A callback
- * function is used to define the method of comparison for each element.
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the content to look for
- * @param callback pointer to a function which compares each element (NULL means compare by content pointer)
- * @return the list element found, or NULL
- */
- ListElement* ListFindItem(List* aList, void* content, int(*callback)(void*, void*))
- {
- ListElement* rc = NULL;
- if (aList->current != NULL && ((callback == NULL && aList->current->content == content) ||
- (callback != NULL && callback(aList->current->content, content))))
- rc = aList->current;
- else
- {
- ListElement* current = NULL;
- /* find the content */
- while (ListNextElement(aList, ¤t) != NULL)
- {
- if (callback == NULL)
- {
- if (current->content == content)
- {
- rc = current;
- break;
- }
- }
- else
- {
- if (callback(current->content, content))
- {
- rc = current;
- break;
- }
- }
- }
- if (rc != NULL)
- aList->current = rc;
- }
- return rc;
- }
- /**
- * Removes and optionally frees an element in a list by comparing the content.
- * A callback function is used to define the method of comparison for each element.
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the content to look for
- * @param callback pointer to a function which compares each element
- * @param freeContent boolean value to indicate whether the item found is to be freed
- * @return 1=item removed, 0=item not removed
- */
- static int ListUnlink(List* aList, void* content, int(*callback)(void*, void*), int freeContent)
- {
- ListElement* next = NULL;
- ListElement* saved = aList->current;
- int saveddeleted = 0;
- if (!ListFindItem(aList, content, callback))
- return 0; /* false, did not remove item */
- if (aList->current->prev == NULL)
- /* so this is the first element, and we have to update the "first" pointer */
- aList->first = aList->current->next;
- else
- aList->current->prev->next = aList->current->next;
- if (aList->current->next == NULL)
- aList->last = aList->current->prev;
- else
- aList->current->next->prev = aList->current->prev;
- next = aList->current->next;
- if (freeContent)
- {
- free(aList->current->content);
- aList->current->content = NULL;
- }
- if (saved == aList->current)
- saveddeleted = 1;
- free(aList->current);
- if (saveddeleted)
- aList->current = next;
- else
- aList->current = saved;
- --(aList->count);
- return 1; /* successfully removed item */
- }
- /**
- * Removes but does not free an item in a list by comparing the pointer to the content.
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the content to look for
- * @return 1=item removed, 0=item not removed
- */
- int ListDetach(List* aList, void* content)
- {
- return ListUnlink(aList, content, NULL, 0);
- }
- /**
- * Removes and frees an item in a list by comparing the pointer to the content.
- * @param aList the list from which the item is to be removed
- * @param content pointer to the content to look for
- * @return 1=item removed, 0=item not removed
- */
- int ListRemove(List* aList, void* content)
- {
- return ListUnlink(aList, content, NULL, 1);
- }
- /**
- * Removes and frees an the first item in a list.
- * @param aList the list from which the item is to be removed
- * @return 1=item removed, 0=item not removed
- */
- void* ListDetachHead(List* aList)
- {
- void *content = NULL;
- if (aList->count > 0)
- {
- ListElement* first = aList->first;
- if (aList->current == first)
- aList->current = first->next;
- if (aList->last == first) /* i.e. no of items in list == 1 */
- aList->last = NULL;
- content = first->content;
- aList->first = aList->first->next;
- if (aList->first)
- aList->first->prev = NULL;
- free(first);
- --(aList->count);
- }
- return content;
- }
- /**
- * Removes and frees an the first item in a list.
- * @param aList the list from which the item is to be removed
- * @return 1=item removed, 0=item not removed
- */
- int ListRemoveHead(List* aList)
- {
- free(ListDetachHead(aList));
- return 0;
- }
- /**
- * Removes but does not free the last item in a list.
- * @param aList the list from which the item is to be removed
- * @return the last item removed (or NULL if none was)
- */
- void* ListPopTail(List* aList)
- {
- void* content = NULL;
- if (aList->count > 0)
- {
- ListElement* last = aList->last;
- if (aList->current == last)
- aList->current = last->prev;
- if (aList->first == last) /* i.e. no of items in list == 1 */
- aList->first = NULL;
- content = last->content;
- aList->last = aList->last->prev;
- if (aList->last)
- aList->last->next = NULL;
- free(last);
- --(aList->count);
- }
- return content;
- }
- /**
- * Removes but does not free an element in a list by comparing the content.
- * A callback function is used to define the method of comparison for each element.
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the content to look for
- * @param callback pointer to a function which compares each element
- * @return 1=item removed, 0=item not removed
- */
- int ListDetachItem(List* aList, void* content, int(*callback)(void*, void*))
- { /* do not free the content */
- return ListUnlink(aList, content, callback, 0);
- }
- /**
- * Removes and frees an element in a list by comparing the content.
- * A callback function is used to define the method of comparison for each element
- * @param aList the list in which the search is to be conducted
- * @param content pointer to the content to look for
- * @param callback pointer to a function which compares each element
- * @return 1=item removed, 0=item not removed
- */
- int ListRemoveItem(List* aList, void* content, int(*callback)(void*, void*))
- { /* remove from list and free the content */
- return ListUnlink(aList, content, callback, 1);
- }
- /**
- * Removes and frees all items in a list, leaving the list ready for new items.
- * @param aList the list to which the operation is to be applied
- */
- void ListEmpty(List* aList)
- {
- while (aList->first != NULL)
- {
- ListElement* first = aList->first;
- if (first->content != NULL)
- {
- free(first->content);
- first->content = NULL;
- }
- aList->first = first->next;
- free(first);
- }
- aList->count = 0;
- aList->size = 0;
- aList->current = aList->first = aList->last = NULL;
- }
- /**
- * Removes and frees all items in a list, and frees the list itself
- * @param aList the list to which the operation is to be applied
- */
- void ListFree(List* aList)
- {
- ListEmpty(aList);
- free(aList);
- }
- /**
- * Removes and but does not free all items in a list, and frees the list itself
- * @param aList the list to which the operation is to be applied
- */
- void ListFreeNoContent(List* aList)
- {
- while (aList->first != NULL)
- {
- ListElement* first = aList->first;
- aList->first = first->next;
- free(first);
- }
- free(aList);
- }
- /**
- * Forward iteration through a list
- * @param aList the list to which the operation is to be applied
- * @param pos pointer to the current position in the list. NULL means start from the beginning of the list
- * This is updated on return to the same value as that returned from this function
- * @return pointer to the current list element
- */
- ListElement* ListNextElement(List* aList, ListElement** pos)
- {
- return *pos = (*pos == NULL) ? aList->first : (*pos)->next;
- }
- /**
- * Backward iteration through a list
- * @param aList the list to which the operation is to be applied
- * @param pos pointer to the current position in the list. NULL means start from the end of the list
- * This is updated on return to the same value as that returned from this function
- * @return pointer to the current list element
- */
- ListElement* ListPrevElement(List* aList, ListElement** pos)
- {
- return *pos = (*pos == NULL) ? aList->last : (*pos)->prev;
- }
- /**
- * List callback function for comparing integers
- * @param a first integer value
- * @param b second integer value
- * @return boolean indicating whether a and b are equal
- */
- int intcompare(void* a, void* b)
- {
- return *((int*)a) == *((int*)b);
- }
- /**
- * List callback function for comparing C strings
- * @param a first integer value
- * @param b second integer value
- * @return boolean indicating whether a and b are equal
- */
- int stringcompare(void* a, void* b)
- {
- return strcmp((char*)a, (char*)b) == 0;
- }
- #if defined(UNIT_TESTS)
- int main(int argc, char *argv[])
- {
- int i, *ip, *todelete;
- ListElement* current = NULL;
- List* l = ListInitialize();
- printf("List initialized\n");
- for (i = 0; i < 10; i++)
- {
- ip = malloc(sizeof(int));
- *ip = i;
- ListAppend(l, (void*)ip, sizeof(int));
- if (i==5)
- todelete = ip;
- printf("List element appended %d\n", *((int*)(l->last->content)));
- }
- printf("List contents:\n");
- current = NULL;
- while (ListNextElement(l, ¤t) != NULL)
- printf("List element: %d\n", *((int*)(current->content)));
- printf("List contents in reverse order:\n");
- current = NULL;
- while (ListPrevElement(l, ¤t) != NULL)
- printf("List element: %d\n", *((int*)(current->content)));
- /* if ListFindItem(l, *ip, intcompare)->content */
- printf("List contents having deleted element %d:\n", *todelete);
- ListRemove(l, todelete);
- current = NULL;
- while (ListNextElement(l, ¤t) != NULL)
- printf("List element: %d\n", *((int*)(current->content)));
- i = 9;
- ListRemoveItem(l, &i, intcompare);
- printf("List contents having deleted another element, %d, size now %d:\n", i, l->size);
- current = NULL;
- while (ListNextElement(l, ¤t) != NULL)
- printf("List element: %d\n", *((int*)(current->content)));
- ListFree(l);
- printf("List freed\n");
- }
- #endif
|