Created
July 3, 2013 04:00
-
-
Save schotime/5915357 to your computer and use it in GitHub Desktop.
EnumerableReader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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