/* File: list1d.c An implementation of the list ADT using doubly linked lists */ #include #include #include "string.h" #include "list1d.h" /* Private Function Prototypes */ static void CrashOnNull(void *, char *) ; static node *NewNode(char *) ; static void FreeNode(node *ptr) ; /* Private Function Implementations */ /* Exit if ptr is NULL. */ static void CrashOnNull(void *ptr, char *mesg) { if (ptr == NULL) { fprintf(stderr, "%s\n", mesg) ; exit(1) ; } } /* Make a new node with given item and next field set to NULL */ static node *NewNode(char *item) { node *new ; new = (node *) malloc (sizeof(node)) ; CrashOnNull(new, "cannot make new node") ; if (item == NULL) item = "" ; new->item = strdup(item) ; CrashOnNull(new->item, "cannot duplicate string") ; new->next = NULL ; new->prev = NULL ; return new ; } /* Free memory allocated to the node */ static void FreeNode(node *ptr) { if (ptr->item != NULL) free(ptr->item) ; free(ptr) ; } /* Public Functions */ /* Make a new list */ list CreateList (void) { list NewL ; NewL = (list) malloc(sizeof (*NewL)) ; CrashOnNull(NewL, "cannot make new list") ; NewL->header.item = NULL ; NewL->header.prev = &NewL->header ; NewL->header.next = &NewL->header ; NewL->count = 0 ; return NewL ; } /* Add item to the end of the list */ void Append(list L, char *item) { node *new ; new = NewNode(item) ; new->prev = L->header.prev ; new->next = &L->header ; new->prev->next = new ; L->header.prev = new ; L->count++ ; } /* Add item to the beginning of the list */ void Prepend(list L, char *item) { node *new ; new = NewNode(item) ; new->prev = &L->header ; new->next = L->header.next ; new->next->prev = new ; L->header.next = new ; L->count++ ; } /* Does item with key appear on the list? 0=No 1=Yes */ int IsMember(list L, char *key) { node *current, *end ; current = L->header.next ; end = &L->header ; while(current != end) { if (strcmp(current->item, key) == 0) return 1 ; current = current->next ; } return 0 ; } /* Return the position in the list of the item with key or NULL if no such item. Note: this time, position is a pointer to the node that contains the key, since deletion is easier in a doubly linked list. */ node *Locate(list L, char *key) { node *current, *end ; current = L->header.next ; end = &L->header ; while(current != end) { if (strcmp(current->item, key) == 0) return current ; current = current->next ; } return NULL ; } /* Remove item in given position from the list. See note regarding position in documentation for Locate(). */ void Delete(list L, node *position) { /* These should never happen. Check anyway. */ if (position == NULL) return ; if (position == &L->header) return ; position->next->prev = position->prev ; position->prev->next = position->next ; FreeNode(position) ; L->count-- ; } /* Add list L2 to the end of list L1. L2 is destroyed. */ void Concatenate(list L1, list L2) { node *h1, *h2 ; L1->count += L2->count ; h1 = &L1->header ; h2 = &L2->header ; h1->prev->next = h2->next ; h2->next->prev = h1->prev ; h1->prev = h2->prev ; h2->prev->next = h1 ; free(L2) ; } /* Duplicate of the list. All items and nodes have newly allocated memory. */ list ListDup(list L) { list NewL ; node *copyto, *copyfrom, *end, *current ; NewL = CreateList() ; NewL->count = L->count ; copyto = &NewL->header ; copyfrom = L->header.next ; end = &L->header ; /* copy data and adjust next pointers */ while(copyfrom != end) { copyto->next = NewNode(copyfrom->item) ; copyto = copyto->next ; copyfrom = copyfrom->next ; } copyto->next = end = &NewL->header ; /* Adjust prev pointers */ current = end ; do { current->next->prev = current ; current = current->next ; } while (current != end) ; return NewL ; } /* Print the contents of the list. */ void PrintList(list L) { node *current, *end ; current = L->header.next ; end = &L->header ; if (current == end) { printf("<>\n") ; return ; } printf("<") ; while (1) { printf("\"%s\"", current->item) ; current = current->next ; if (current == end) break ; printf(",") ; } printf(">\n") ; } /* Free memory allocated to the list. */ void FreeList(list L) { node *current, *end, *temp ; current = L->header.next ; end = &L->header ; while (current != end) { temp = current ; current = current->next ; FreeNode(temp) ; } free(L) ; } /* String in first item returned, or NULL if list is empty */ char *FirstItem(list L) { char *item ; if (L->count == 0) return NULL ; return L->header.next->item ; } /* String in last item returned, or NULL if list is empty */ char *LastItem(list L) { if (L->count == 0) return NULL ; return L->header.prev->item ; } /* Returns number of items in the list */ int CountList(list L) { return L->count ; }