IRC parsing, tokenization, and state handling in C#
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}