using CanonSharp.Common.Abstractions; namespace CanonSharp.Common.Reader; public class SourceReader : ISourceReader { private readonly StreamReader _reader; private char? _lookAhead; public SourceReader(string filename) { FileInfo source = new(filename); if (!source.Exists) { throw new InvalidOperationException(); } _reader = new StreamReader(filename); } public char Read() { if (_lookAhead.HasValue) { char result = _lookAhead.Value; _lookAhead = null; return result; } if (!TryFetchChar(out char c)) { throw new InvalidOperationException(); } return c; } public bool TryPeek(out char c) { if (_lookAhead.HasValue) { c = _lookAhead.Value; return true; } if (!TryFetchChar(out c)) { return false; } _lookAhead = c; return true; } private readonly char[] _buffer = new char[1024]; private int _length; private int _count; private bool TryFetchChar(out char c) { if (_length == _count) { _length = _reader.Read(_buffer); _count = 0; } if (_length == 0) { c = char.MinValue; return false; } c = _buffer[_count]; _count += 1; return true; } }