/* * Copyright 2011 Steven Gribble * * This file is part of the UW CSE 333 course project sequence * (333proj). * * 333proj is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 333proj is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 333proj. If not, see . */ #ifndef _HW1_LL_H_ #define _HW1_LL_H_ // A LinkedList is a doubly-linked list. We provide the interface to // the LinkedList; your job is to fill in the implementation. // To hide the implementation of LinkedList, we'll just define it to // be a (void *), i.e., a pointer of generic type void. In ll.c, // we'll actually declare what the structure contains and we'll use // casting back and forth between (void *) and the actual structure. // // By using this trick, customers of the ll.h package don't see // needless implementation details of our linked list. typedef void *LinkedList; // Customers of ll.h occasionally need to pass a function pointer as // an argument to one of our functions. // // When freeing a LinkedList, they need to pass a pointer to a // function that frees the payload of a linked list node. The // pointed-to function is invoked once for each node in the // linked list before the LinkedList itself is freed. typedef void(*PayloadFreeFnPtr)(void *payload); // When sorting a linked list or comparing two elements of a linked // list, customers must pass in a comparator function. The // function accepts two payload pointers as arguments, and returns // an integer that is: // -1 if payload_a < payload_b // 0 if payload_a == payload_b // 1 if payload_a > payload_b typedef int(*PayloadComparatorFnPtr)(void *payload_a, void *payload_b); // Allocate and return a new linked list. // // Arguments: none. // // Returns NULL on error, non-NULL on success. LinkedList AllocateLinkedList(void); // Free a linked list. // // Arguments: // // - list: the LinkedList to free. It is unsafe to use list // after this function returns. // // - payload_free_function: this argument is a pointer to a payload // freeing function; see above for details. void FreeLinkedList(LinkedList list, PayloadFreeFnPtr payload_free_function); // Figure out the number of elements in the linked list. // // Arguments: // // - list: the list to query // // Returns: // // - list length (>=0) for a valid list // // - -1 on error unsigned int NumElementsInLinkedList(LinkedList list); // Inserts a payload as a new element on the head of the linked list. // // Arguments: // // - list: the LinkedList to push onto // // - payload: the payload to add; it's up to the caller to // interpret and manage the memory of the payload. // // Returns 0 on failure, +1 on success. int PushLinkedList(LinkedList list, void *payload); // Pops an element from the head of the linked list. // // Arguments: // // - list: the LinkedList to pop from // // - payload_ptr: a return parameter that is set by the callee; // on success, the payload is returned through this parameter. // // Returns 0 on failure, +1 on success. int PopLinkedList(LinkedList list, void **payload_ptr); // Inserts a payload as a new element on the tail of the linked list. // // Arguments: // // - list: the LinkedList to append to // // - payload: the payload to add; it's up to the caller to // interpret and manage the memory of the payload. // // Returns 0 on failure, +1 on success. int AppendLinkedList(LinkedList list, void *payload); // Slices an element off the tail of the linked list. // // Arguments: // // - list: the LinkedList to slice from // // - payload_ptr: a return parameter that is set by the callee; // on success, the payload is returned through this parameter. // // Returns 0 on failure, +1 on success. int SliceLinkedList(LinkedList list, void **payload_ptr); // Sorts a LinkedList in place. // // Arguments: // // - list: the list to sort // // - ascending: if 0, sorts descending, else sorts ascending. // // - comparator_function: this argument is a pointer to // a payload comparator function; see above. void SortLinkedList(LinkedList list, unsigned int ascending, PayloadComparatorFnPtr comparator_function); // Linked lists support the notion of an iterator, similar to // Java iterators. You use an iterator to navigate back and // forth through the linked list and insert/remove elements // from the list. You use LinkedListMakeIterator() to // manufacture a new iterator, and LLIteratorFree() to // free an iterator when you're done with it. // // If you use a LinkedList*() function to mutate // a linked list, any iterators you have on that list become dangerous // to use (so dangerous that arbitrary memory corruption // can occur). Thus, we recommend that you only use LLIterator*() // functions in between the manufacturing and freeing of an iterator. typedef void *LLIter; // same trick to hide implementation. // Manufacture an iterator for the list. Customers can // use an iterator to navigate through the list; an // iterator has the ability to both advance and // to go backwards. // // Arguments: // // - list: the list from which to return an iterator // // - pos: where the iterator should start. 0: head. +1: tail. // // Returns NULL on failure, non-NULL on success. LLIter LinkedListMakeIterator(LinkedList list, int pos); // When you're done with an iterator, you need to free it // by calling this function. // // Arguments: // // - iter: the iterator to free. It is not safe to use // the iterator after freeing it. void LLIteratorFree(LLIter iter); // Move the iterator to the next element of the list. // // Arguments: // // - iter: the iterator to move // // Returns: // // - +1 on success // // - 0 if the iterator is already at the tail end of the list; if so, // the iterator is not modified and can still be used. int LLIteratorNext(LLIter iter); // Tests to see whether the iterator is at the tail // end of the list. // // Arguments: // // - iter: the iterator to test // // Returns: // // - +1 if iter is at the tail of the list or the list is empty. // // - 0 if iter is not at the tail of the list (and therefore the list // is non-empty). int LLIteratorAtTail(LLIter iter); // Move the iterator to the previous element of the list. // // Arguments: // // - iter: the iterator to move // // Returns: // // - +1 on success // // - 0 if the iterator is already at the head end of the list; if so, // the iterator is not modified and can still be used. int LLIteratorPrev(LLIter iter); // Tests to see whether the iterator is at the head // end of the list. // // Arguments: // // - iter: the iterator to test // // Returns: // // - +1 if iter is at the head of the list or the list is empty. // // - 0 if iter is not at the head of the list (and therefore the list // is non-empty). int LLIteratorAtHead(LLIter iter); // Returns the payload of the list node that the iterator currently // points at. // // Arguments: // // - iter: the iterator to fetch the payload from. // // - payload: a "return parameter" through which the payload // is returned. // // Returns: // // - 0 if the list is empty and therefore there is no payload. // // - +1 on success. int LLIteratorGetPayload(LLIter iter, void **payload); // Deletes the node the iterator is currently pointing to. // After deletion, the iterator points to: // - the remaining element, if only one element remains // - the successor of the deleted node, if there is a // successor // - the predecessor of the deleted node, if the iterator // was pointing at the tail (i.e., there is no successor) // // If there is only a single element in the list, then after // invoking this deletion function, that element is deleted // and the iterator is no longer usable. // // Arguments: // // - iter: the iterator to delete from // // - payload_free_function: invoked to free the payload // // Returns: // // - -1 if the list is empty and the delete failed. // // - 0 if the delete succeeded and the modified list is now empty. // // - +1 if the delete succeeded and the modified list is non-empty. int LLIteratorDelete(LLIter iter, PayloadFreeFnPtr payload_free_function); // Inserts a new element before the node the iterator points at. // If the list is empty, inserts the first element. // // Arguments: // // - iter: the iterator to insert before // // - payload: the payload to insert // // Returns: // // - 0 on failure // // - +1 on success; the iterator still points to the current // node, not the inserted node. int LLIteratorInsertBefore(LLIter iter, void *payload); #endif // _HW1_LL_H_