using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IrcTokens { public class StatefulEncoder { private Encoding _encoding; public Encoding Encoding { get => _encoding ?? Encoding.GetEncoding(Encoding.UTF8.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); set { if (value != null) { _encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); } } } private Queue _bufferedLines; public byte[] PendingBytes { get; private set; } public string Pending() { try { return Encoding.GetString(PendingBytes); } catch (DecoderFallbackException e) { Console.WriteLine(e); throw; } } public StatefulEncoder() { Clear(); } public void Clear() { PendingBytes = Array.Empty(); _bufferedLines = new Queue(); } public void Push(Line line) { if (line == null) { throw new ArgumentNullException(nameof(line)); } PendingBytes = PendingBytes.Concat(Encoding.GetBytes($"{line.Format()}\r\n")).ToArray(); _bufferedLines.Enqueue(line); } public List Pop(int byteCount) { var sent = PendingBytes.Take(byteCount).Count(c => c == '\n'); PendingBytes = PendingBytes.Skip(byteCount).ToArray(); _bufferedLines = new Queue(_bufferedLines.Skip(sent)); return Enumerable.Range(0, sent) .Select(_ => _bufferedLines.Dequeue()) .ToList(); } } }