What do you think of this?
#region EnumerableSegment
public class EnumerableSegment<T> : IEnumerable<T>, IEnumerator<T>
{
bool m_Disposed;
T t;
internal protected readonly int VirtualIndex, VirtualCount;
public int Index { get; protected set;}
public int Count { get { return VirtualCount; } }
public virtual T Current
{
get { if (Index == -1) throw new InvalidOperationException("Enumeration has not started call MoveNext"); return t; }
internal protected set { t = value; }
}
void IDisposable.Dispose()
{
m_Disposed = true;
}
public virtual bool MoveNext()
{
if (m_Disposed) return false;
else return ++Index <= VirtualCount;
}
object System.Collections.IEnumerator.Current
{
get { if (Index == -1) throw new InvalidOperationException("Enumeration has not started call MoveNext"); return t; }
}
bool System.Collections.IEnumerator.MoveNext()
{
if (m_Disposed) return false;
else return MoveNext();
}
void System.Collections.IEnumerator.Reset()
{
if (m_Disposed) return;
Index = VirtualIndex;
t = default(T);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
if (m_Disposed) return null; return this;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
if (m_Disposed) return null; return this;
}
public virtual int Remaining
{
get { if (m_Disposed) return 0; return Index > VirtualCount ? 0 : VirtualCount - Index; }
}
public EnumerableSegment(IEnumerable<T> enumerable, int start = 0, int count = -1)
{
Index = VirtualIndex = start;
VirtualCount = count;
}
public EnumerableSegment(T item)
{
VirtualIndex = Index = 0;
VirtualCount = 1;
}
public EnumerableSegment() { Index = -1; }
public virtual void Reset() { Index = VirtualIndex; }
public static void ForAll(IEnumerable<T> enumerable, Action<T> action, int index = 0, int count = -1)
{
foreach (T t in new EnumerableSegment<T>(enumerable, index, count))
action(t);
}
public static bool Any(IEnumerable<T> enumerable, Func<T, bool> predicate, int index = 0, int count = -1)
{
foreach (T t in new EnumerableSegment<T>(enumerable, index, count))
if (predicate(t)) return true;
return false;
}
}
#endregion
#region Stream Classes
#region EnumerableByteStream
public class EnumerableByteStream : EnumerableSegment<byte>, IEnumerable<byte>, IEnumerator<byte>, IList<byte>
{
protected int m_Current;
internal protected System.IO.Stream m_Stream;
internal protected bool m_Disposed;
internal EnumerableByteStream m_Self;
bool Initialized { get { return CurrentInt != -1; } }
public int CurrentInt { get { return Current; } }
public EnumerableByteStream(byte Byte) : this(Byte.Yield()) { }
public EnumerableByteStream(IEnumerable<byte> bytes, int? index = null, int? count = null)
: base(bytes, index ?? 0, (int)(count.HasValue ? count - index : -1)){}
public EnumerableByteStream(System.IO.Stream stream, int? index = null, int? count = null)
: this(null as IEnumerable<byte>, index ?? (int)stream.Position, count ?? (int)stream.Length)
{
m_Stream = stream;
m_Current = Current;
}
public IEnumerable<byte> ToArray(int offset, int count, byte[] buffer)
{
if (offset < 0) throw new ArgumentOutOfRangeException("offset must refer to a location within the buffer.");
else if (count + offset > Length) throw new ArgumentOutOfRangeException("count must refer to a location within the buffer with respect to offset.");
if (count == 0) return Enumerable.Empty<byte>();
buffer = buffer ?? new byte[count];
int len = count;
while ((len -= m_Stream.Read(buffer, offset, count)) > 0
&&
Remaining > 0)
{
}
return buffer;
}
public IEnumerator<byte> GetEnumerator()
{
if (CurrentInt == -1) MoveNext();
while (!m_Disposed && MoveNext()) yield return Current = (byte)m_Current;
}
public override bool MoveNext()
{
if (base.MoveNext()) return CoreGetEnumerator() != -1;
return false;
}
int CoreGetEnumerator(long direction = 1)
{
if (!m_Disposed && m_Stream.Position < Count) return Current = (byte)(m_Current = m_Stream.ReadByte());
else unchecked { return Current = (byte)(m_Current = -1); }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
internal protected long CoreIndexOf(IEnumerable<byte> items, int start = -1, int count = -1)
{
if (m_Stream == null || m_Disposed || items == null || items == Enumerable.Empty<byte>() || count == 0) return -1;
if (count == -1) count = items.Count();
if (!Initialized && !MoveNext()) return -1;
if (start != -1 && start + count > Count) return -1;
else if (start != -1 && start != Position) if (m_Stream.CanSeek) m_Stream.Seek(start, System.IO.SeekOrigin.Begin);
else return -1;
using (IEnumerator<byte> itemPointer = items.Skip(start).Take(count).GetEnumerator())
{
if (!itemPointer.MoveNext()) return -1;
long position = Position;
if (start == -1 && m_Stream.CanSeek && m_Stream.Position != 0 && itemPointer.Current != Current)
{
Reset();
}
else start = (int)m_Stream.Position;
while (itemPointer != null)
{
int j = count;
while (itemPointer.Current == Current && (--j > 0))
{
if (!itemPointer.MoveNext()) break;
}
if (j == 0)
{
return m_Stream.Position - 1;
}
if (!MoveNext()) break;
}
if (start == -1 && m_Stream.CanSeek && position != Position) m_Stream.Seek(position, System.IO.SeekOrigin.Begin);
return -1;
}
}
internal protected int CoreIndexOf(byte item, int start, int count) { return (int)CoreIndexOf(item.Yield(), start, count); }
public virtual int IndexOf(byte item)
{
return CoreIndexOf(item, -1, 1);
}
public virtual void Insert(int index, byte item)
{
EnumerableByteStream newPointer =new EnumerableByteStream((new EnumerableByteStream(m_Stream, 0, index - 1) as IEnumerable<byte>).
Concat(item.Yield()).
Concat(new EnumerableByteStream(m_Stream, index - 1, Count - index + 1) as IEnumerable<byte>));
m_Self = newPointer;
}
public virtual void RemoveAt(int index)
{
m_Stream = LinkedStream.LinkAll(new EnumerableByteStream(m_Stream, 0, index), new EnumerableByteStream(m_Stream, ++index, Count - index));
}
public virtual byte this[int index]
{
get
{
if (index < 1) index = 0;
if (index != m_Stream.Position)
{
if (m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can only move the index if the underlying stream CanSeek");
}
return (byte)m_Stream.ReadByte();
}
set
{
if (m_Stream.CanWrite && m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite and CanSeek");
m_Stream.Write(value.Yield().ToArray(), 0, 1);
}
}
public virtual void Add(byte item)
{
if (m_Stream.CanWrite) m_Stream.Write(item.Yield().ToArray(), 0, 1);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite");
}
public virtual void Clear()
{
m_Stream = new System.IO.MemoryStream();
return;
}
public virtual bool Contains(byte item)
{
return CoreIndexOf(item, 0, 1) != -1;
}
public virtual void CopyTo(byte[] array, int arrayIndex)
{
CoreCopyTo(array, arrayIndex);
}
public virtual void CopyTo(System.IO.Stream stream, int? bufferSize = null)
{
m_Stream.CopyTo(stream, (int)(stream.Length - stream.Position));
}
public virtual void CoreCopyTo(byte[] array, int arrayIndex, int length = -1)
{
if (length <= 0) return;
if (length == -1) length = array.Length - arrayIndex;
else if (length > m_Stream.Length) throw new ArgumentOutOfRangeException("Can't copy more bytes then are availble from the stream");
m_Stream.Read(array, arrayIndex, length);
}
public long Position { get { return Index; } }
public virtual long Length
{
get { return Count; }
}
public virtual bool IsReadOnly
{
get { return m_Stream.CanWrite; }
}
public virtual bool Remove(byte item)
{
return false;
}
public static implicit operator System.IO.Stream(EnumerableByteStream eByteStream) { return eByteStream.m_Stream; }
object System.Collections.IEnumerator.Current
{
get { return GetEnumerator().Current; }
}
public override void Reset()
{
m_Current = -1;
if (m_Stream.CanSeek) m_Stream.Seek(VirtualIndex, System.IO.SeekOrigin.Begin);
base.Reset();
}
public long Seek(long offset, System.IO.SeekOrigin origin) { if (m_Stream.CanSeek) return m_Stream.Seek(offset, origin); return m_Stream.Position; }
}
#endregion
#region CachingEnumerableByteStream
public class CachingEnumerableByteStream : EnumerableByteStream
{
List<byte> m_ReadCache = new List<byte>(), m_WriteCache = new List<byte>();
public CachingEnumerableByteStream(System.IO.Stream stream)
: base(stream)
{
}
internal void EnsureCache(int index)
{
try
{
if (index > m_ReadCache.Count)
{
byte[] buffer = new byte[index - m_Stream.Position];
CopyTo(buffer, 0);
m_ReadCache.AddRange(buffer);
}
}
catch { throw; }
}
public override byte this[int index]
{
get
{
EnsureCache(index);
return m_ReadCache[index];
}
set
{
EnsureCache(index);
base[index] = m_ReadCache[index] = value;
}
}
}
#endregion
#region LinkedStream
public class LinkedStream :
System.IO.Stream,
IEnumerable<EnumerableByteStream>,
IEnumerator<EnumerableByteStream>,
IEnumerable<byte>,
IEnumerator<byte>
{
#region Fields
internal protected IEnumerable<EnumerableByteStream> m_Streams;
internal protected ulong m_AbsolutePosition;
internal protected IEnumerator<EnumerableByteStream> m_Enumerator;
internal EnumerableByteStream m_CurrentStream;
internal int m_StreamIndex = 0;
internal protected bool m_Disposed;
#endregion
#region Propeties
public System.IO.Stream CurrentStream
{
get
{
if (m_Disposed) return null;
if (m_CurrentStream == null) m_CurrentStream = m_Enumerator.Current;
return m_CurrentStream;
}
}
public override bool CanRead
{
get { return !m_Disposed && CurrentStream.CanRead; }
}
public override bool CanSeek
{
get { return !m_Disposed && CurrentStream.CanSeek; }
}
public override bool CanWrite
{
get { return !m_Disposed && CurrentStream.CanWrite; }
}
public override void Flush()
{
if (!m_Disposed) CurrentStream.Flush();
}
public override long Length
{
get { return (long)TotalLength; }
}
public ulong TotalLength
{
get
{
if (m_Disposed) return 0;
ulong totalLength = 0;
foreach (EnumerableByteStream stream in this as IEnumerable<EnumerableByteStream>) totalLength += (ulong)(stream.Count);
return totalLength;
}
}
public override long Position
{
get
{
return (long)TotalPosition;
}
set
{
if (!m_Disposed) SeekAbsolute(value, System.IO.SeekOrigin.Current);
}
}
public ulong TotalPosition
{
get { return m_Disposed ? 0 : m_AbsolutePosition + (ulong)m_CurrentStream.Position; }
protected internal set { if (m_Disposed) return; m_AbsolutePosition = value; }
}
#endregion
#region Constructors
public LinkedStream(IEnumerable<EnumerableByteStream> streams)
{
if (streams == null) streams = Enumerable.Empty<EnumerableByteStream>();
m_Streams = streams;
m_Enumerator = GetEnumerator();
m_Enumerator.MoveNext();
}
public LinkedStream(EnumerableByteStream stream) : this(stream.Yield()) { }
public static LinkedStream LinkAll(params EnumerableByteStream[] streams) { return new LinkedStream(streams); }
#endregion
#region Methods
public System.IO.MemoryStream Flatten()
{
System.IO.MemoryStream memory = new System.IO.MemoryStream((int)TotalLength);
foreach (System.IO.Stream stream in m_Streams) stream.CopyTo(memory);
return memory;
}
public LinkedStream Link(params EnumerableByteStream[] streams) { return new LinkedStream(m_Streams.Concat(streams)); }
public LinkedStream Link(EnumerableByteStream stream) { return Link(stream.Yield().ToArray()); }
public LinkedStream Unlink(int streamIndex, bool reverse = false)
{
if (streamIndex > m_Streams.Count()) throw new ArgumentOutOfRangeException("index cannot be greater than the amount of contained streams");
IEnumerable<EnumerableByteStream> streams = m_Streams;
if (reverse) streams.Reverse();
return new LinkedStream(m_Streams.Skip(streamIndex));
}
public LinkedStream SubStream(ulong absoluteIndex, ulong count)
{
LinkedStream result = new LinkedStream(new EnumerableByteStream(new System.IO.MemoryStream()));
if (count == 0) return result;
while (absoluteIndex > 0)
{
}
return result;
}
internal void SelectStream(int logicalIndex)
{
if (m_Disposed) return;
if (m_StreamIndex == logicalIndex) return;
else if (logicalIndex < m_StreamIndex) m_Enumerator.Reset();
while (logicalIndex > m_StreamIndex) MoveNext();
}
internal void SelectStream(ulong absolutePosition)
{
if (m_Disposed) return;
if (TotalPosition == absolutePosition) return;
else if (absolutePosition < TotalPosition) m_Enumerator.Reset();
while (TotalPosition < absolutePosition)
{
if (!MoveNext()) return;
if (CurrentStream.Length > 0) absolutePosition -= (ulong)CurrentStream.Length;
}
}
#endregion
#region Wrappers
public override int ReadByte()
{
return CurrentStream.ReadByte();
}
public override int Read(byte[] buffer, int offset, int count)
{
return CoreRead(buffer, offset, count);
}
internal protected int CoreRead(byte[] buffer, long offset, long count, System.IO.SeekOrigin readOrigin = System.IO.SeekOrigin.Current)
{
switch (readOrigin)
{
case System.IO.SeekOrigin.Begin:
{
Seek(offset, System.IO.SeekOrigin.Begin);
goto case System.IO.SeekOrigin.Current;
}
case System.IO.SeekOrigin.End:
{
MoveToEnd();
goto case System.IO.SeekOrigin.Current;
}
case System.IO.SeekOrigin.Current:
{
int read = 0;
while (read < count)
{
if (CurrentStream.Position < offset && CurrentStream.CanSeek) CurrentStream.Seek(offset, System.IO.SeekOrigin.Begin);
read += CurrentStream.Read(buffer, (int)offset, (int)count - (int)read);
if (CurrentStream.Position >= CurrentStream.Length && read < count) if (!MoveNext()) break;
}
return read;
}
default:
{
Utility.BreakIfAttached();
break;
}
}
return 0;
}
bool MoveNext()
{
if (m_Disposed || m_Streams == null || m_Enumerator == null) return false;
m_AbsolutePosition += (ulong)(m_CurrentStream.Count - m_CurrentStream.Position);
++m_StreamIndex;
return m_Enumerator.MoveNext();
}
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
switch (origin)
{
case System.IO.SeekOrigin.End:
case System.IO.SeekOrigin.Begin:
return (long)SeekAbsolute(offset, System.IO.SeekOrigin.Begin);
case System.IO.SeekOrigin.Current:
return m_CurrentStream.Seek(offset, origin);
default: return m_CurrentStream.Position;
}
}
public void MoveToEnd()
{
while (MoveNext())
{
CurrentStream.Position = CurrentStream.Length;
}
}
public ulong SeekAbsolute(long offset, System.IO.SeekOrigin origin)
{
switch (origin)
{
case System.IO.SeekOrigin.Current:
{
long offsetPosition = (long)TotalPosition - offset;
if (offsetPosition < 0) CurrentStream.Seek(offsetPosition, System.IO.SeekOrigin.Current);
else CurrentStream.Position = offsetPosition;
return TotalPosition;
}
case System.IO.SeekOrigin.Begin:
{
SelectStream((ulong)offset);
goto case System.IO.SeekOrigin.Current;
}
case System.IO.SeekOrigin.End:
{
MoveToEnd();
goto case System.IO.SeekOrigin.Current;
}
default:
{
Utility.BreakIfAttached();
break;
}
}
return m_AbsolutePosition;
}
IEnumerator<EnumerableByteStream> GetEnumerator() { return m_Disposed ? null : m_Streams.GetEnumerator(); }
public override void SetLength(long value)
{
if (value < Length) Position = (long)m_AbsolutePosition + value;
CurrentStream.SetLength(value);
m_AbsolutePosition = (ulong)value;
}
public override void Write(byte[] buffer, int offset, int count)
{
if (count < CoreWrite(buffer, (ulong)offset, (ulong)count))
{
#if DEBUG
Utility.BreakIfAttached();
#endif
}
}
internal protected int CoreWrite(byte[] buffer, ulong offset, ulong count, System.IO.SeekOrigin readOrigin = System.IO.SeekOrigin.Current)
{
SelectStream((ulong)offset);
switch (readOrigin)
{
case System.IO.SeekOrigin.Current:
{
return (this as IEnumerator<System.IO.Stream>).Current.Read(buffer, (int)offset, (int)count);
}
case System.IO.SeekOrigin.Begin:
{
return (this as IEnumerator<System.IO.Stream>).Current.Read(buffer, (int)offset, (int)count);
}
case System.IO.SeekOrigin.End:
{
return (this as IEnumerator<System.IO.Stream>).Current.Read(buffer, (int)offset, (int)count);
}
default:
{
#if DEBUG
Utility.BreakIfAttached();
#endif
break;
}
}
return 0;
}
IEnumerator<EnumerableByteStream> IEnumerable<EnumerableByteStream>.GetEnumerator()
{
return m_Streams.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return m_Streams.GetEnumerator();
}
EnumerableByteStream IEnumerator<EnumerableByteStream>.Current
{
get { return GetEnumerator().Current; }
}
void IDisposable.Dispose()
{
m_Disposed = true;
if (m_Streams != null) m_Streams = null;
m_StreamIndex = -1;
base.Dispose();
}
void System.Collections.IEnumerator.Reset()
{
foreach (EnumerableByteStream stream in m_Streams) if (stream.m_Stream.CanSeek) stream.Seek(0, System.IO.SeekOrigin.Begin);
GetEnumerator().Reset();
}
object System.Collections.IEnumerator.Current
{
get { return CurrentStream; }
}
bool System.Collections.IEnumerator.MoveNext()
{
return MoveNext();
}
IEnumerator<byte> IEnumerable<byte>.GetEnumerator() { return new EnumerableByteStream(this as IEnumerable<byte>).GetEnumerator(); }
byte IEnumerator<byte>.Current { get { return (this as IEnumerable<byte>).GetEnumerator().Current; } }
#endregion
}
#endregion
#endregion
I think its a unique use of the concept and I am wondering what others think!
|