Skip to content

Instantly share code, notes, and snippets.

Created January 17, 2013 22:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/4560647 to your computer and use it in GitHub Desktop.
Save anonymous/4560647 to your computer and use it in GitHub Desktop.
FrontLoader; immutable random access builder
using System;
using System.Collections;
using System.Collections.Generic;
namespace Living.In.Some.Namespace
{
public interface IReadOnlyWindow<T>
: IEnumerable<T>
{
int Count { get; }
T this[int index] { get; }
IFrontLoader<T> Mitosis();
}
public interface IFrontLoader<T>
{
IReadOnlyWindow<T> PushFront(T item);
IReadOnlyWindow<T> Current { get; }
T PeekFront { get; }
T PeekBack { get; }
}
public enum FrontLoaderTypes
{
Grow,
Circular,
}
public class FrontLoader<T>
: IFrontLoader<T>
{
private const int MinArraySize = 4;
private T[] _data;
private int _offset;
private readonly int _initial;
private readonly FrontLoaderTypes _type;
public FrontLoader(FrontLoaderTypes type, int initial)
{
_type = type;
_initial = initial;
var arraySize = Math.Max(MinArraySize, initial * 2);
_data = new T[arraySize];
_offset = arraySize;
}
// Used for Mitosis
private FrontLoader(T[] roData, int roOffset, int roCount, int initial)
{
_data = new T[roData.Length];
_offset = _data.Length - roCount;
_initial = initial;
Array.Copy(roData, roOffset, _data, _offset, roCount);
}
class ReadOnlyWindow
: IReadOnlyWindow<T>
, IList<T>
{
private readonly FrontLoader<T> _parent;
private readonly T[] _data;
private readonly int _offset;
private readonly int _count;
public ReadOnlyWindow(FrontLoader<T> parent, T[] data, int offset, int count)
{
_parent = parent;
_data = data;
_offset = offset;
_count = count;
}
private static Exception NotSupported() { return new NotSupportedException("Collection is read-only."); }
void IList<T>.Insert(int index, T item) { throw NotSupported(); }
void IList<T>.RemoveAt(int index) { throw NotSupported(); }
void ICollection<T>.Add(T item) { throw NotSupported(); }
void ICollection<T>.Clear() { throw NotSupported(); }
bool ICollection<T>.Remove(T item) { throw NotSupported(); }
public T this[int index]
{
get
{
if (index < 0 || index >= _count)
throw new IndexOutOfRangeException();
return _data[_offset + index];
}
set { throw NotSupported(); }
}
int IList<T>.IndexOf(T item)
{
for (int i = _offset; i < _offset + _count; ++i)
{
if (_data[i].Equals(item))
return i - _offset;
}
return -1;
}
bool ICollection<T>.Contains(T item)
{
var index = ((IList<T>)this).IndexOf(item);
return index >= 0;
}
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
Array.Copy(_data, _offset, array, 0, _count);
}
public int Count { get { return _count; } }
bool ICollection<T>.IsReadOnly { get { return true; } }
public IEnumerator<T> GetEnumerator()
{
for (int i = _offset; i < _offset + _count; ++i)
yield return _data[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IFrontLoader<T> Mitosis()
{
return new FrontLoader<T>(_data, _offset, _count, _parent._initial);
}
}
public IReadOnlyWindow<T> PushFront(T item)
{
if (--_offset < 0)
{
switch (_type)
{
case FrontLoaderTypes.Circular:
var circular = new T[_data.Length];
Array.Copy(_data, 0, circular, _data.Length - _initial, _initial);
_data = circular;
_offset = _data.Length - _initial - 1;
break;
case FrontLoaderTypes.Grow:
var grow = new T[_data.Length * 2];
Array.Copy(_data, 0, grow, _data.Length, _data.Length);
_offset = _data.Length - 1;
_data = grow;
break;
default:
throw new ApplicationException(string.Format("Unknown type {0}", _type));
}
}
_data[_offset] = item;
return Current;
}
public IReadOnlyWindow<T> Current
{
get
{
if (_type == FrontLoaderTypes.Circular)
return new ReadOnlyWindow(this, _data, _offset, Math.Min(_initial, _data.Length - _offset));
return new ReadOnlyWindow(this, _data, _offset, _data.Length - _offset);
}
}
public T PeekFront
{
get { return _data[_offset]; }
}
public T PeekBack
{
get { return _data[_data.Length - 1]; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment