using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IrcTokens { public class StatefulDecoder { private byte[] _buffer; private Encoding _encoding; private Encoding _fallback; public StatefulDecoder() { Clear(); } 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.ReplacementFallback); } } public Encoding Fallback { get => _fallback ?? Encoding.GetEncoding(Encoding.GetEncoding("iso-8859-1").CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); set { if (value != null) _fallback = Encoding.GetEncoding(value.CodePage, EncoderFallback.ReplacementFallback, DecoderFallback.ReplacementFallback); } } public string Pending => Encoding.GetString(_buffer); public void Clear() { _buffer = Array.Empty(); } public List Push(string data) { var bytes = Encoding.GetBytes(data); return Push(bytes, bytes.Length); } public List Push(byte[] data, int bytesReceived) { if (data == null) return null; _buffer = _buffer == null ? Array.Empty() : _buffer.Concat(data.Take(bytesReceived)).ToArray(); var listLines = _buffer.Split((byte) '\n').Select(l => l.Trim((byte) '\r')).ToList(); _buffer = listLines.LastOrDefault() ?? Array.Empty(); var decodeLines = new List(); foreach (var line in listLines.SkipLast(1).Select(l => l.ToArray())) try { decodeLines.Add(new Line(Encoding.GetString(line))); } catch (DecoderFallbackException) { decodeLines.Add(new Line(Fallback.GetString(line))); } return decodeLines; } } }