Skip to content

Instantly share code, notes, and snippets.

@schotime
Created July 3, 2013 04:00
Show Gist options
  • Save schotime/5915357 to your computer and use it in GitHub Desktop.
Save schotime/5915357 to your computer and use it in GitHub Desktop.
EnumerableReader
public class EnumerableReader : TextReader
{
private readonly char _separator;
private readonly IEnumerator<string> _enumerator;
private string _s;
private int _pos;
private readonly bool _useSeperator;
private bool _enumeratorDisposed = false;
public EnumerableReader(IEnumerable<string> lines) : this(lines, '\n')
{
_useSeperator = false;
}
public EnumerableReader(IEnumerable<string> lines, char separator)
{
_enumerator = lines.GetEnumerator();
_separator = separator;
_useSeperator = true;
}
private void SetNewLine()
{
_s = _enumerator.MoveNext() ? _enumerator.Current : null;
_pos = 0;
}
public override int Read()
{
CheckReaderNotClosed();
if (_s == null)
{
SetNewLine();
if (_s == null)
return -1;
}
if (_pos >= _s.Length)
{
SetNewLine();
if (_s == null)
return -1;
if (_useSeperator)
return _separator;
}
return _s[_pos++];
}
public override int Peek()
{
CheckReaderNotClosed();
if (_s == null)
{
SetNewLine();
if (_s == null)
return -1;
}
string newst = _s;
int newpos = _pos;
if (_pos >= _s.Length)
{
if (_useSeperator)
return _separator;
SetNewLine();
if (_s == null)
return -1;
newst = _s;
newpos = _pos;
}
return newst[newpos];
}
private void CheckReaderNotClosed()
{
if (_enumeratorDisposed)
throw new ObjectDisposedException(null, "The reader has already been closed");
}
public override int Read(char[] buffer, int index, int count)
{
for (int j = 0; j < index; j++)
{
//Consume chars
Read();
}
int i = 0;
while (i < count)
{
int val = Read();
if (val == -1)
{
break;
}
buffer[i] = (char) val;
i++;
}
return i;
}
public override string ReadToEnd()
{
var sb = new StringBuilder();
string line;
bool first = true;
while ((line = ReadLine()) != null)
{
sb.Append((!first && _useSeperator) ? _separator + line : line);
first = false;
}
return sb.ToString();
}
public override string ReadLine()
{
CheckReaderNotClosed();
SetNewLine();
return _s;
}
protected override void Dispose(bool disposing)
{
_enumerator.Dispose();
_enumeratorDisposed = true;
base.Dispose(disposing);
}
}
public class EnumerableReaderTests
{
private static IEnumerable<string> GetSampleData()
{
var list = new List<string>()
{
"1abcd", "2abcd", "3abcd"
};
return list;
}
[Fact]
public void ReadLine()
{
var data = GetSampleData();
var newlist = new List<string>();
using (var reader = new EnumerableReader(data))
{
string line;
while ((line = reader.ReadLine()) != null)
{
newlist.Add(line);
}
}
Assert.Equal(data, newlist);
}
[Fact]
public void Read()
{
var data = GetSampleData();
var newlist = "";
using (var reader = new EnumerableReader(data))
{
int line;
while ((line = reader.Read()) != -1)
{
newlist += (char)line;
}
}
Assert.Equal(string.Join("", data), newlist);
}
[Fact]
public void ReadWithSeparator()
{
var data = GetSampleData();
var newlist = "";
using (var reader = new EnumerableReader(data, '\n'))
{
int line;
while ((line = reader.Read()) != -1)
{
newlist += (char)line;
}
}
Assert.Equal(string.Join("\n", data), newlist);
}
[Fact]
public void PeekAndRead()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data))
{
char a1h = (char)reader.Read();
char a = (char)reader.Read();
char bpeek = (char)reader.Peek();
char b = (char)reader.Read();
char c = (char)reader.Read();
char d = (char)reader.Read();
char a2hpeek = (char)reader.Peek();
char a2hpeek2 = (char)reader.Peek();
char a2h = (char)reader.Read();
char a2 = (char)reader.Read();
char b2peek = (char)reader.Peek();
char b2peek2 = (char)reader.Peek();
char b2 = (char)reader.Read();
char c2 = (char)reader.Read();
char d2 = (char)reader.Read();
char a3h = (char)reader.Read();
char a3 = (char)reader.Read();
char b3 = (char)reader.Read();
char c3 = (char)reader.Read();
char d3 = (char)reader.Read();
int end = reader.Read();
Assert.Equal('1', a1h);
Assert.Equal('a', a);
Assert.Equal('b', b);
Assert.Equal('b', bpeek);
Assert.Equal('c', c);
Assert.Equal('d', d);
Assert.Equal('2', a2hpeek);
Assert.Equal('2', a2hpeek2);
Assert.Equal('2', a2h);
Assert.Equal('a', a2);
Assert.Equal('b', b2peek);
Assert.Equal('b', b2peek2);
Assert.Equal('b', b2);
Assert.Equal('c', c2);
Assert.Equal('d', d2);
Assert.Equal('3', a3h);
Assert.Equal('a', a3);
Assert.Equal('b', b3);
Assert.Equal('c', c3);
Assert.Equal('d', d3);
Assert.Equal(-1, end);
}
}
[Fact]
public void PeekAndReadWithSeparator()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data, '\n'))
{
char a1h = (char)reader.Read();
char a = (char)reader.Read();
char bpeek = (char)reader.Peek();
char b = (char)reader.Read();
char c = (char)reader.Read();
char d = (char)reader.Read();
char n1peek = (char)reader.Peek();
char n1 = (char) reader.Read();
char a2hpeek = (char)reader.Peek();
char a2hpeek2 = (char)reader.Peek();
char a2h = (char)reader.Read();
char a2 = (char)reader.Read();
char b2peek = (char)reader.Peek();
char b2peek2 = (char)reader.Peek();
char b2 = (char)reader.Read();
char c2 = (char)reader.Read();
char d2 = (char)reader.Read();
char n2 = (char)reader.Read();
char a3h = (char)reader.Read();
char a3 = (char)reader.Read();
char b3 = (char)reader.Read();
char c3 = (char)reader.Read();
char d3 = (char)reader.Read();
int end = reader.Read();
Assert.Equal('1', a1h);
Assert.Equal('a', a);
Assert.Equal('b', b);
Assert.Equal('b', bpeek);
Assert.Equal('c', c);
Assert.Equal('d', d);
Assert.Equal('\n', n1peek);
Assert.Equal('\n', n1);
Assert.Equal('2', a2hpeek);
Assert.Equal('2', a2hpeek2);
Assert.Equal('2', a2h);
Assert.Equal('a', a2);
Assert.Equal('b', b2peek);
Assert.Equal('b', b2peek2);
Assert.Equal('b', b2);
Assert.Equal('c', c2);
Assert.Equal('d', d2);
Assert.Equal('\n', n2);
Assert.Equal('3', a3h);
Assert.Equal('a', a3);
Assert.Equal('b', b3);
Assert.Equal('c', c3);
Assert.Equal('d', d3);
Assert.Equal(-1, end);
}
}
[Fact]
public void ReadWithBuffer()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data))
{
char[] buffer = new char[10];
var changes = reader.Read(buffer, 0, 10);
Assert.Equal(10, changes);
Assert.Equal('1', buffer[0]);
Assert.Equal('d', buffer[9]);
}
}
[Fact]
public void ReadWithBufferWhereCountIsGreaterThanChars()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data))
{
char[] buffer = new char[20];
var changes = reader.Read(buffer, 0, 20);
Assert.Equal(15, changes);
Assert.Equal('1', buffer[0]);
Assert.Equal('3', buffer[10]);
Assert.Equal('d', buffer[14]);
}
}
[Fact]
public void ReadToEnd()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data))
{
var joined = reader.ReadToEnd();
Assert.Equal("1abcd2abcd3abcd", joined);
}
}
[Fact]
public void ReadToEndWithSeparator()
{
var data = GetSampleData();
using (var reader = new EnumerableReader(data, '\n'))
{
var joined = reader.ReadToEnd();
Assert.Equal("1abcd\n2abcd\n3abcd", joined);
}
}
[Fact]
public void ReaderThrowsWhenClosed()
{
var data = GetSampleData();
var reader = new EnumerableReader(data);
reader.Dispose();
Assert.Throws(typeof (ObjectDisposedException), () =>
{
reader.ReadLine();
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment