/*
* Copyright 2012 Steven Gribble
*
* This file is part of the UW CSE333 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_LINKEDLIST_H_
#define HW1_LINKEDLIST_H_
#include // for bool type (true, false)
#include // for uint64_t
// A LinkedList is a doubly-linked list. We provide the interface to the
// LinkedList here; your job is to fill in the implementation holes that we
// left in LinkedList.c.
// To hide the implementation of LinkedList, we declare the "struct ll_head"
// structure here, but we *define* the structure in the internal header
// LinkedList_priv.h. This lets us define a pointer to LinkedList as a new
// type while leaving the implementation details opaque to the customer.
struct ll_head;
typedef struct ll_head *LinkedList;
// When a customer frees a linked list, they need to pass a pointer to a
// function that frees the payload of a linked list node. We invoke the
// pointed-to function once for each node in the linked list, before the
// LinkedListPtr itself is freed.
typedef void(*LLPayloadFreeFnPtr)(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(*LLPayloadComparatorFnPtr)(void *payload_a, void *payload_b);
// Allocate and return a new linked list. The caller takes responsibility for
// eventually calling FreeLinkedList to free memory associated with the list.
//
// Arguments: none.
//
// Returns: NULL on error, non-NULL on success.
LinkedList AllocateLinkedList(void);
// Free a linked list that was previously allocated by AllocateLinkedList.
//
// Arguments:
//
// - list: the linked list to free. It is unsafe to use "list" after this
// function returns.
//
// - payload_free_function: a pointer to a payload freeing function; see above
// for details on what this is.
void FreeLinkedList(LinkedList list,
LLPayloadFreeFnPtr payload_free_function);
// Return the number of elements in the linked list.
//
// Arguments:
//
// - list: the list to query
//
// Returns:
//
// - list length
uint64_t NumElementsInLinkedList(LinkedList list);
// Adds a new element to the head of the linked list.
//
// Arguments:
//
// - list: the LinkedList to push onto
//
// - payload: the payload to push; it's up to the caller to interpret and
// manage the memory of the payload.
//
// Returns false on failure, true on success.
bool PushLinkedList(LinkedList list, void *payload);
// Pop 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 false on failure, true on success.
bool PopLinkedList(LinkedList list, void **payload_ptr);
// Adds a new element to the tail of the linked list.
//
// Arguments:
//
// - list: the LinkedList to push onto
//
// - payload: the payload to push; it's up to the caller to interpret and
// manage the memory of the payload.
//
// Returns false on failure, true on success.
bool AppendLinkedList(LinkedList list, void *payload);
// Pop an element from the tail 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 false on failure, true on success.
bool 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,
LLPayloadComparatorFnPtr 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
// to insert/remove elements from the list. You use LLMakeIterator() 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, you should only use LLIterator*()
// functions in between the manufacturing and freeing of an iterator.
struct ll_iter;
typedef struct ll_iter *LLIter; // same trick to hide implementation.
// Manufacture an iterator for the list. Customers can use the iterator to
// advance forwards or backwards through the list, kind of like a cursor.
// Caller is responsible for eventually calling LLIteratorFree to free memory
// associated with the iterator.
//
// Arguments:
//
// - list: the list from which we'll return an iterator
//
// - pos: where to start (0 = head, 1 = tail)
//
// Returns NULL on failure (out of memory, empty list) or non-NULL on success.
LLIter LLMakeIterator(LinkedList list, int pos);
// When you're done with an iterator, you must free it by calling this
// function.
//
// Arguments:
//
// - iter: the iterator to free. Don't use it after freeing it.
void LLIteratorFree(LLIter iter);
// Test whether the iterator can advance forward.
//
// Arguments:
//
// - iter: the iterator
//
// Returns:
//
// - true if the iterator can advance (is not at tail)
//
// - false if the iterator cannot advance (is at the tail)
bool LLIteratorHasNext(LLIter iter);
// Advance the iterator, i.e. move to the next node in the
// list.
//
// Arguments:
//
// - iter: the iterator
//
// Returns:
//
// true: if the iterator has been advanced to the next node
//
// false: if the iterator is at the last node and cannot
// be advanced
bool LLIteratorNext(LLIter iter);
// Test whether the iterator can advance backwards.
//
// Arguments:
//
// - iter: the iterator
//
// Returns:
//
// - true if the iterator can advance (is not at head)
//
// - false if the iterator cannot advance (is at the head)
bool LLIteratorHasPrev(LLIter iter);
// Rewind the iterator, i.e. move to the previous node in the
// list.
//
// Arguments:
//
// - iter: the iterator
//
// Returns:
//
// true: if the iterator has been shifted to the previous node
//
// false: if the iterator is at the first node and cannot be
// shifted back any more
bool LLIteratorPrev(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.
void LLIteratorGetPayload(LLIter iter, void **payload);
// Delete the node the iterator is pointing to. After deletion, the iterator:
//
// - is invalid and cannot be used (but must be freed), if there was only one
// element in the list
//
// - the successor of the deleted node, if there is one.
//
// - the predecessor of the deleted node, if the iterator was pointing at
// the tail.
//
// Arguments:
//
// - iter: the iterator to delete from
//
// - payload_free_function: invoked to free the payload
//
// Returns:
//
// - false if the deletion succeeded, but the list is now empty
//
// - true if the deletion succeeded, and the list is still non-empty
bool LLIteratorDelete(LLIter iter,
LLPayloadFreeFnPtr payload_free_function);
// Insert an element right before the node that the interator points
// to. (If you want to insert at the end of a list, use
// AppendLinkedList.)
//
// Arguments:
//
// - iter: the iterator to insert through
//
// - payload: the payload to insert
//
// Returns:
//
// - false on failure (out of memory)
//
// - true on success; the iterator still points to the same node,
// not to the inserted node.
bool LLIteratorInsertBefore(LLIter iter, void *payload);
#endif // HW1_LINKEDLIST_H_