using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Lilium.Collections
{
public class CyclicQueue: IEnumerable
{
public CyclicQueue(int length)
{
if (length < 0)
throw new InvalidOperationException("Queue length can't be less then zero");
m_Queue = new T[length];
}
public void Enqueue(T item)
{
var length = Queue.Length ;
if (length == 0)
return;
Queue[Tail] = item;
Tail = (Tail + 1) % length;
if (Count == length)
Head = (Head + 1) % length;
else
Count++;
}
public T Dequeue()
{
if (Count == 0)
throw new InvalidOperationException("Queue is empty");
T local = Queue[Head];
Queue[Head] = default(T);
Head = (Head + 1) % Queue.Length;
return local;
}
///
/// Returns enumerator which enumerates from queue tail to the head.
///
///
public IEnumerator GetReversedEnumerator()
{
var length = Count;
if (length == 0)
yield break;
if (Tail > Head)
for (int i = Tail - 1; i >= Head; i--)
yield return Queue[i];
else
{
for (int i = Tail - 1; i >= 0; i--)
yield return Queue[i];
for (int i = length - 1; i >= Head; i--)
yield return Queue[i];
}
}
public bool TryPeekLast(out T item)
{
if (Count != 0)
{
item = Queue[Tail != 0 ? Tail - 1 : Queue.Length - 1];
return true;
}
else
{
item = default(T);
return false;
}
}
#region public int Count
private int m_Count;
public int Count
{
get
{
return m_Count;
}
private set
{
m_Count = value;
}
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
var length = Queue.Length;
if (length == 0)
yield break;
if (Tail > Head)
for (int i = Head; i < Tail; i++)
yield return Queue[i];
else
{
for (int i = Head; i < length; i++)
yield return Queue[i];
for (int i = 0; i < Tail - 1; i++)
yield return Queue[i];
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region private T[] Queue
private readonly T[] m_Queue;
private T[] Queue
{
get
{
return m_Queue;
}
}
#endregion
#region private int Head
private int m_Head;
private int Head
{
get
{
return m_Head;
}
set
{
m_Head = value;
}
}
#endregion
#region private int Tail
private int m_Tail;
private int Tail
{
get
{
return m_Tail;
}
set
{
m_Tail = value;
}
}
#endregion
}
}