#region Copyright 2010-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0 /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion using System; namespace CSharpTest.Net.Collections { /// /// A typed node, used similiarly to LinkedListNode<T>. Can belong to single list /// at a time, the type of list is usually LListNode<T>.LList /// /// public class LListNode : LListNode { /// Constructs a node without a value public LListNode() { } /// Constructs a node with a value public LListNode(T value) { Value = value; } /// Gets/Sets the value of this node public T Value; /// Returns the previous item in the list or null public new LListNode Previous { get { return (LListNode)base.Previous; } } /// Returns the next item in the list or null public new LListNode Next { get { return (LListNode)base.Next; } } /// Provides a linked list of nodes of type T public new class LList : LList> { /// Adds the node to the front of the list public void AddFirst(T value) { AddFirst(new LListNode(value)); } /// Adds the node to the end of the list public void AddLast(T value) { AddLast(new LListNode(value)); } } } /// /// The basic Linked-list node, untyped, use LListNode<T> for strong typed nodes and lists. /// public class LListNode { private LListNode _prev, _next; /// /// You may derive an instance class from LListNode and use it in a single list, or you /// may construct a node<T> with the value that the node should contain. /// protected LListNode() { } /// Returns the previous item in the list or null public LListNode Previous { get { return _prev; } } /// Returns the next item in the list or null public LListNode Next { get { return _next; } } /// Provides a linked list of nodes of type T public class LList : LList { } /// Provides a linked list of nodes of type T public class LList : System.Collections.Generic.ICollection where TNode : LListNode { int _count; TNode _head, _tail; /// Returns the number of items in the list public int Count { get { return _count; } } /// Returns true if the list is empty public bool IsEmpty { get { return _head == null; } } /// Returns the first node in the list public TNode First { get { return _head; } } /// Returns the last node in the list public TNode Last { get { return _tail; } } /// Adds the node to the front of the list public void AddFirst(TNode value) { Check.Assert(value._prev == null && value._next == null); value._prev = null; value._next = _head; if (_head != null) _head._prev = value; _head = value; _tail = _tail ?? value; _count++; } /// Adds the node to the end of the list public void AddLast(TNode value) { Check.Assert(value._prev == null && value._next == null); value._next = null; value._prev = _tail; if (_tail != null) _tail._next = value; _tail = value; _head = _head ?? value; _count++; } /// Remvoes the node from the list public bool Remove(TNode value) { int removed = 0; if (ReferenceEquals(_head, value) && ++removed > 0) _head = (TNode)value._next; if (value._next != null && ++removed > 0) value._next._prev = value._prev; if (ReferenceEquals(_tail, value) && ++removed > 0) _tail = (TNode)value._prev; if (value._prev != null && ++removed > 0) value._prev._next = value._next; value._next = value._prev = null; _count--; return removed > 0; } /// Remvoes all the nodes from the list public void Clear() { foreach (TNode item in this) item._next = item._prev = null; _head = _tail = null; _count = 0; } /// Returns an enumerator that iterates through the collection. public System.Collections.Generic.IEnumerator GetEnumerator() { return new Enumerator, TNode>(this); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new Enumerator, TNode>(this); } void System.Collections.Generic.ICollection.Add(TNode item) { AddLast(item); } bool System.Collections.Generic.ICollection.Contains(TNode item) { while (item._prev != null) item = (TNode)item._prev; return item == _head; } void System.Collections.Generic.ICollection.CopyTo(TNode[] array, int arrayIndex) { foreach (TNode node in this) array[arrayIndex++] = node; } bool System.Collections.Generic.ICollection.IsReadOnly { get { return false; } } } /// Provides a enumeration of the list where it is acceptable to remove current private class Enumerator : System.Collections.Generic.IEnumerator where TList : LList where TNode : LListNode { TList _list; TNode _current, _next; /// Creates the enumeration on a list public Enumerator(TList list) { _list = list; _next = _list.First; _current = null; } object System.Collections.IEnumerator.Current { get { return Current; } } /// Returns the current node public TNode Current { get { if (_list == null) throw new ObjectDisposedException(GetType().FullName); if (_current == null) throw new InvalidOperationException(); return _current; } } /// Disposes of the enumeration public void Dispose() { _list = null; _next = _current = null; } /// Moves to the next element or returns false public bool MoveNext() { if (_list == null) throw new ObjectDisposedException(GetType().FullName); _current = _next; if (_current == null) return false; _next = (TNode)_current._next; return true; } /// Resets the enumeration back to the beginning of the list public void Reset() { if (_list == null) throw new ObjectDisposedException(GetType().FullName); _next = _list.First; _current = null; } } } }