IRC parsing, tokenization, and state handling in C#
at ircrobots 71 lines 1.9 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace IRCTokens 7{ 8 public class StatefulEncoder 9 { 10 private List<Line> _bufferedLines; 11 private Encoding _encoding; 12 13 public StatefulEncoder() 14 { 15 Clear(); 16 } 17 18 public Encoding Encoding 19 { 20 get => _encoding ?? Encoding.GetEncoding(Encoding.UTF8.CodePage, EncoderFallback.ExceptionFallback, 21 DecoderFallback.ExceptionFallback); 22 set 23 { 24 if (value != null) 25 _encoding = Encoding.GetEncoding(value.CodePage, EncoderFallback.ExceptionFallback, 26 DecoderFallback.ExceptionFallback); 27 } 28 } 29 30 public byte[] PendingBytes { get; private set; } 31 32 public string Pending() 33 { 34 try 35 { 36 return Encoding.GetString(PendingBytes); 37 } 38 catch (DecoderFallbackException e) 39 { 40 Console.WriteLine(e); 41 throw; 42 } 43 } 44 45 public void Clear() 46 { 47 PendingBytes = Array.Empty<byte>(); 48 _bufferedLines = new List<Line>(); 49 } 50 51 public void Push(Line line) 52 { 53 if (line == null) throw new ArgumentNullException(nameof(line)); 54 55 PendingBytes = PendingBytes.Concat(Encoding.GetBytes($"{line.Format()}\r\n")).ToArray(); 56 _bufferedLines.Add(line); 57 } 58 59 public List<Line> Pop(int byteCount) 60 { 61 var sent = PendingBytes.Take(byteCount).Count(c => c == '\n'); 62 63 PendingBytes = PendingBytes.Skip(byteCount).ToArray(); 64 65 var sentLines = _bufferedLines.Take(sent).ToList(); 66 _bufferedLines = _bufferedLines.Skip(sent).ToList(); 67 68 return sentLines; 69 } 70 } 71}