//http://isotopescreencapture.codeplex.com/
//The MIT License (MIT)
using System.Collections.Generic;
namespace Isotope.Collections
{
public class ChunkedList : IEnumerable.RowEnumerator>
{
private readonly List data;
private readonly int _chunkSize;
public ChunkedList(int chunksize, int capacity)
{
if (chunksize < 1)
{
throw new System.ArgumentOutOfRangeException("chunksize", "must be at least 1");
}
this._chunkSize = chunksize;
this.data = new List(chunksize * capacity);
}
public T[] ToArray()
{
return this.data.ToArray();
}
public void Add(params T[] items)
{
this.AddChunk(items);
}
public void AddChunk(ICollection items)
{
if (items.Count != _chunkSize)
{
string msg = string.Format("must add exactly {0} items", items.Count);
throw new System.ArgumentOutOfRangeException(msg);
}
this.data.AddRange(items);
if (this.data.Count % this._chunkSize != 0)
{
throw new System.Exception("Did not maintain consistency of chunked list");
}
}
public int Count
{
get
{
return this.data.Count / this._chunkSize;
}
}
public int ChunkSize
{
get { return _chunkSize; }
}
public void GetRow(int r, T[] row_array)
{
int startindex = r * this._chunkSize;
for (int c = 0; c < this._chunkSize; c++)
{
row_array[c] = this.data[startindex + c];
}
}
public T[] GetRow(int r)
{
var a = new T[this._chunkSize];
this.GetRow(r, a);
return a;
}
public T this[int row, int col]
{
get
{
if (row < 0)
{
throw new System.ArgumentOutOfRangeException("row", "must be greater than zero");
}
if (col < 0)
{
throw new System.ArgumentOutOfRangeException("col", "must be greater than zero");
}
if (row >= this.Count)
{
throw new System.ArgumentOutOfRangeException("row");
}
if (col >= this._chunkSize)
{
throw new System.ArgumentOutOfRangeException("col");
}
return this.data[(row * this._chunkSize) + col];
}
}
// Implement IEnumerable
System.Collections.Generic.IEnumerator
System.Collections.Generic.IEnumerable.GetEnumerator()
{
return this.AsEnumerable().GetEnumerator();
}
// Implement IEnumerable
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.AsEnumerable().GetEnumerator();
}
private T[] CreateRowBuffer()
{
var row = new T[this._chunkSize];
return row;
}
private IEnumerable AsEnumerable()
{
var row_array = this.CreateRowBuffer();
for (int r = 0; r < this.Count; r++)
{
this.GetRow(r, row_array);
yield return new RowEnumerator(r, row_array);
}
}
public struct RowEnumerator
{
public readonly int Index;
public readonly T[] ItemArray;
internal RowEnumerator(int index, T[] itemarray)
{
this.Index = index;
this.ItemArray = itemarray;
}
}
}
}