// Copyright (c) 2014 Robert Rouhani and other contributors (see CONTRIBUTORS file). // Licensed under the MIT License - https://raw.github.com/Robmaister/SharpNav/master/LICENSE using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace SharpNav.Collections.Generic { /// /// Typical LIFO generic queue container that stores data inside of /// a fixed-size internal buffer (array). /// /// Type of element that given BufferedQueue object stores. public class BufferedQueue : ICollection { private const int SIZE = 100; // Fixed internal size of the data array private T[] data; // Internal data array private int first; // Index of first element in queue private int last; // Index of last element in queue /// /// Initializes a new instance of the class. /// /// The maximum number of items that will be stored. public BufferedQueue(int size) { this.data = new T[SIZE]; this.first = this.last = -1; } /// /// Initializes a new instance of the class as a copy of an /// of the same type. /// /// The collection to copy from. public BufferedQueue(ICollection items) { if (items.Count <= SIZE) { this.data = new T[SIZE]; items.CopyTo(data, 0); this.first = 0; } else { this.data = items.Skip(items.Count - SIZE).ToArray(); this.first = 0; } } /// /// Gets the number of elements in the queue. /// public int Count { get { return (last >= 0 && first >= 0) ? last - first : 0; } } /// /// Gets a value indicating whether the queue is read-only (False for now) /// bool ICollection.IsReadOnly { get { return false; } } /// /// Gets the value at specified index (valid ranges are from 0 to size-1) /// /// Index value /// The value at the index public T this[int index] { get { return data[index]; } } /// /// Adds a new element to the front of the queue. /// /// The element to be added to the queue /// True if element was added to queue, False otherwise public bool Enqueue(T item) { if (last == data.Length) return false; if (first < 0) first = 0; data[++last] = item; return true; } /// /// Removes bottom element from queue and returns it (and updates "first" index) /// /// Bottom element public T Dequeue() { if (first < 0) throw new InvalidOperationException("The queue is empty."); return data[first++]; } /// /// Returns last element in the queue /// /// size element public T Peek() { if (last == 0) throw new InvalidOperationException("The queue is empty."); return data[last]; } /// /// Resets queue pointer back to default, essentially clearing the queue. /// public void Clear() { first = last = -1; } /// /// Returns whether the queue contains a given item. /// /// Item to search for /// True if item exists in queue, False if not public bool Contains(T item) { for (int i = 0; i <= last; i++) if (item.Equals(data[i])) return true; return false; } /// /// Copies the contents of the to an array. /// /// The array to copy to. /// The index within the array to start copying to. public void CopyTo(T[] array, int arrayIndex) { throw new NotImplementedException(); } /// /// Gets the 's enumerator. /// /// The enumerator. public IEnumerator GetEnumerator() { if (last < 0 || first < 0) yield break; //TODO handle wrap-arounds. for (int i = 0; i <= last; i++) yield return data[i]; } /// /// Calls . /// /// The item to add. void ICollection.Add(T item) { Enqueue(item); } /// /// Unsupported, but necessary to implement . /// /// An item. /// Nothing. This method will always throw . /// Will always be thrown. This is not a valid operation. bool ICollection.Remove(T item) { throw new InvalidOperationException("Cannot remove from an arbitrary index in a queue"); } /// /// The non-generic version of . /// /// A non-generic enumerator. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }