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