about summary refs log tree commit diff
path: root/IrcTokens/StatefulEncoder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'IrcTokens/StatefulEncoder.cs')
-rw-r--r--IrcTokens/StatefulEncoder.cs64
1 files changed, 51 insertions, 13 deletions
diff --git a/IrcTokens/StatefulEncoder.cs b/IrcTokens/StatefulEncoder.cs
index 0c8b5f9..17295eb 100644
--- a/IrcTokens/StatefulEncoder.cs
+++ b/IrcTokens/StatefulEncoder.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 
@@ -6,30 +7,67 @@ namespace IrcTokens
 {
     public class StatefulEncoder
     {
-        private string _buffer;
-        public EncodingInfo Encoding { get; set; }
-        private List<Line> _bufferedLines;
+        private Encoding _encoding;
 
-        public string Pending => _buffer;
+        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<Line> _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()
         {
-            _buffer = "";
-            _bufferedLines.Clear();
+            PendingBytes = Array.Empty<byte>();
+            _bufferedLines = new Queue<Line>();
         }
 
         public void Push(Line line)
         {
-            _buffer += $"{line.Format()}\r\n";
-            _bufferedLines.Add(line);
+            if (line == null)
+                throw new ArgumentNullException(nameof(line));
+
+            PendingBytes = PendingBytes.Concat(Encoding.GetBytes($"{line.Format()}\r\n")).ToArray();
+            _bufferedLines.Enqueue(line);
         }
 
         public List<Line> Pop(int byteCount)
         {
-            var sent = _buffer.Substring(byteCount).Count(c => c == '\n');
-            _buffer = _buffer.Substring(byteCount);
-            _bufferedLines = _bufferedLines.Skip(sent).ToList();
-            return _bufferedLines.Take(sent).ToList();
+            var sent = PendingBytes.Take(byteCount).Count(c => c == '\n');
+
+            PendingBytes = PendingBytes.Skip(byteCount).ToArray();
+            _bufferedLines = new Queue<Line>(_bufferedLines.Skip(sent));
+
+            return Enumerable.Range(0, sent)
+                .Select(_ => _bufferedLines.Dequeue())
+                .ToList();
         }
     }
 }