using System;
using System.Collections.Generic;
namespace TradeHelp.Utilities
{
///
/// Sequence is an abstraction of a data reseqeuncer
///
public class Sequencer
{
private int? _curNum;
private int _subIndex;
private readonly List _data = new List();
///
/// Takes as input data of type T and returns all data as a contiguous
/// block of reseqeunced data.
///
/// the data to be re-sequenced
/// the seqence number associated with the data
/// indicates if this sequenceNum is the first in the sequence
/// contiguous sequence of data
public IEnumerable Resequence(T data, int sequenceNum, bool initial)
{
if (initial)
{
if (_curNum.HasValue)
throw new Exception();
_curNum = sequenceNum;
}
else if (sequenceNum < _curNum)
{
throw new ArgumentOutOfRangeException();
}
var temp = new Data(data, sequenceNum, ++_subIndex);
var index = _data.BinarySearch(temp);
if (index > 0)
throw new Exception();
_data.Insert(~index, temp);
return Enumerate();
}
///
/// Takes as input a collection of data of type T and returns all data as a contiguous
/// block of reseqeunced data.
///
/// the data to be re-sequenced
/// the seqence number associated with the data
/// indicates if this sequenceNum is the first in the sequence
/// contiguous sequence of data
public IEnumerable Resequence(ICollection collection, int sequenceNum, bool initial)
{
Invariant.CheckIsNull(collection, "collection");
if (initial)
{
if (_curNum.HasValue)
throw new Exception();
_curNum = sequenceNum;
}
else if (sequenceNum < _curNum)
{
throw new ArgumentOutOfRangeException();
}
if (collection.Count == 0)
{
var temp = new Data(sequenceNum, ++_subIndex);
var index = _data.BinarySearch(temp);
if (index > 0)
throw new Exception();
_data.Insert(~index, temp);
}
else
{
foreach (var data in collection)
{
var temp = new Data(data, sequenceNum, ++_subIndex);
var index = _data.BinarySearch(temp);
if (index > 0)
throw new Exception();
_data.Insert(~index, temp);
}
}
return Enumerate();
}
private IEnumerable Enumerate()
{
while (_data.Count > 0 && _data[0].Index1 == _curNum)
{
while (_data.Count > 0 && _data[0].Index1 == _curNum)
{
if (_data[0].HasData)
{
yield return _data[0].TData;
}
_data.RemoveAt(0);
}
_curNum++;
}
}
private struct Data : IComparable
{
public Data(int index1, int index2)
{
Index1 = index1;
Index2 = index2;
HasData = false;
TData = default(T);
}
public Data(T data, int index1, int index2)
{
TData = data;
Index1 = index1;
Index2 = index2;
HasData = true;
}
public readonly T TData;
public readonly int Index1;
public readonly int Index2;
public readonly bool HasData;
public int CompareTo(Data other)
{
if (Index1 == other.Index1)
{
return Comparer.Default.Compare(Index2, other.Index2);
}
return Comparer.Default.Compare(Index1, other.Index1);
}
}
}
}