// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System; using System.Collections.Generic; using System.IO; using System.Text; namespace osu.Game.IO { /// /// A -like decorator (with more limited API) for s /// that allows lines to be peeked without consuming. /// public class LineBufferedReader : IDisposable { private readonly StreamReader streamReader; private readonly Queue lineBuffer; public LineBufferedReader(Stream stream, bool leaveOpen = false) { streamReader = new StreamReader(stream, Encoding.UTF8, true, 1024, leaveOpen); lineBuffer = new Queue(); } /// /// Reads the next line from the stream without consuming it. /// Subsequent calls to without a will return the same string. /// public string PeekLine() { if (lineBuffer.Count > 0) return lineBuffer.Peek(); string line = streamReader.ReadLine(); if (line != null) lineBuffer.Enqueue(line); return line; } /// /// Reads the next line from the stream and consumes it. /// If a line was peeked, that same line will then be consumed and returned. /// public string ReadLine() => lineBuffer.Count > 0 ? lineBuffer.Dequeue() : streamReader.ReadLine(); /// /// Reads the stream to its end and returns the text read. /// This includes any peeked but unconsumed lines. /// public string ReadToEnd() { string remainingText = streamReader.ReadToEnd(); if (lineBuffer.Count == 0) return remainingText; var builder = new StringBuilder(); // this might not be completely correct due to varying platform line endings while (lineBuffer.Count > 0) builder.AppendLine(lineBuffer.Dequeue()); builder.Append(remainingText); return builder.ToString(); } public void Dispose() { streamReader?.Dispose(); } } }