diff --git a/src/hulk/list.d b/src/hulk/list.d index 541df60..88b1bbf 100644 --- a/src/hulk/list.d +++ b/src/hulk/list.d @@ -10,55 +10,119 @@ import hulk.hurl.a1; */ struct List(T) { - /** - * Linked list item. - */ - T item; + struct Node + { + /** + * Linked list node. + */ + T item; + alias item this; + + /** + * Next node. + */ + Node * next; + + /** + * Previous node. + */ + Node * prev; + } /** - * Next list entry. + * Head node. */ - List!T * next; + public Node * head; + + /** + * Tail node. + */ + public Node * tail; /** * Add an item to this linked list. */ - public void add(T item) + public void add(T)(auto ref T item) { - List!T * last_entry = last_entry(); - List!T * new_entry = A1.allocate!(List!T)(); - last_entry.item = item; - last_entry.next = new_entry; + Node * new_node = A1.allocate!Node(); + new_node.item = item; + new_node.next = null; + new_node.prev = tail; + if (tail != null) + { + tail.next = new_node; + } + tail = new_node; + if (head == null) + { + head = new_node; + } + } + + /** + * Remove an item from this linked list. + */ + public void remove(ref Node node) + { + if (node.prev != null) + { + node.prev.next = node.next; + } + else + { + /* Removing the first list node. */ + head = node.next; + } + if (node.next != null) + { + node.next.prev = node.prev; + } + else + { + /* Removing the last list node. */ + tail = node.prev; + } + } + + /** + * Remove an item from this linked list. + */ + public void remove(Node * node) + { + remove(*node); + } + + /** + * Get the number of nodes in this list. + */ + public @property size_t count() const + { + size_t count; + const(Node) * node = head; + while (node != null) + { + count++; + node = node.next; + } + return count; } /** * Allow foreach iteration across a List. */ - public int opApply(scope int delegate(ref T) dg) + public int opApply(scope int delegate(ref Node) dg) { - List!T * entry = &this; - while (entry.next != null) + Node * node = head; + while (node != null) { - int result = dg(entry.item); + Node * current = node; + node = node.next; + int result = dg(*current); if (result != 0) { return result; } - entry = entry.next; } return 0; } - - /** - * Get the last linked list entry. - */ - private @property List!T * last_entry() - { - List!T * result = &this; - while (result.next != null) - { - result = result.next; - } - return result; - } }