about summary refs log tree commit diff
path: root/IrcTokens
diff options
context:
space:
mode:
Diffstat (limited to 'IrcTokens')
-rw-r--r--IrcTokens/Extensions.cs59
-rw-r--r--IrcTokens/Line.cs4
-rw-r--r--IrcTokens/StatefulDecoder.cs37
3 files changed, 64 insertions, 36 deletions
diff --git a/IrcTokens/Extensions.cs b/IrcTokens/Extensions.cs
new file mode 100644
index 0000000..2eee7dc
--- /dev/null
+++ b/IrcTokens/Extensions.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace IrcTokens
+{
+    public static class Extensions
+    {
+        public static IEnumerable<byte[]> Split(this byte[] bytes, byte separator)
+        {
+            if (bytes == null || bytes.Length == 0) return new List<byte[]>();
+
+            var newLineIndices = bytes.Select((b, i) => b == separator ? i : -1).Where(i => i != -1).ToArray();
+            var lines          = new byte[newLineIndices.Length + 1][];
+            var currentIndex   = 0;
+            var arrIndex       = 0;
+
+            for (var i = 0; i < newLineIndices.Length && currentIndex < bytes.Length; ++i)
+            {
+                var n = new byte[newLineIndices[i] - currentIndex];
+                Array.Copy(bytes, currentIndex, n, 0, newLineIndices[i] - currentIndex);
+                currentIndex      = newLineIndices[i] + 1;
+                lines[arrIndex++] = n;
+            }
+
+            // Handle the last string at the end of the array if there is one.
+            if (currentIndex < bytes.Length)
+                lines[arrIndex] = bytes.Skip(currentIndex).ToArray();
+            else if (arrIndex == newLineIndices.Length)
+                // We had a separator character at the end of a string.  Rather than just allowing
+                // a null character, we'll replace the last element in the array with an empty string.
+                lines[arrIndex] = Array.Empty<byte>();
+
+            return lines.ToArray();
+        }
+
+        public static byte[] Trim(this IEnumerable<byte> bytes, byte separator)
+        {
+            if (bytes == null || !bytes.Any()) return Array.Empty<byte>();
+            var byteList = new List<byte>(bytes);
+            var i        = 0;
+
+            while (byteList[i] == separator)
+            {
+                byteList.RemoveAt(i);
+                i++;
+            }
+
+            i = byteList.Count - 1;
+            while (byteList[i] == separator)
+            {
+                byteList.RemoveAt(i);
+                i--;
+            }
+
+            return byteList.ToArray();
+        }
+    }
+}
diff --git a/IrcTokens/Line.cs b/IrcTokens/Line.cs
index f574e4e..d1a8286 100644
--- a/IrcTokens/Line.cs
+++ b/IrcTokens/Line.cs
@@ -104,7 +104,7 @@ namespace IrcTokens
         /// </summary>
         /// <param name="val">escaped string</param>
         /// <returns>unescaped string</returns>
-        public static string UnescapeTag(string val)
+        private static string UnescapeTag(string val)
         {
             var unescaped = new StringBuilder();
 
@@ -141,7 +141,7 @@ namespace IrcTokens
         /// </summary>
         /// <param name="val">string to escape</param>
         /// <returns>escaped string</returns>
-        public static string EscapeTag(string val)
+        private static string EscapeTag(string val)
         {
             for (var i = 0; i < TagUnescaped.Length; ++i)
                 val = val?.Replace(TagUnescaped[i], TagEscaped[i], StringComparison.Ordinal);
diff --git a/IrcTokens/StatefulDecoder.cs b/IrcTokens/StatefulDecoder.cs
index 2db32f2..62d1703 100644
--- a/IrcTokens/StatefulDecoder.cs
+++ b/IrcTokens/StatefulDecoder.cs
@@ -56,41 +56,10 @@ namespace IrcTokens
         {
             if (data == null || data.Length == 0) return null;
 
-            _buffer = _buffer.Concat(data).ToArray();
+            _buffer = _buffer == null ? Array.Empty<byte>() : _buffer.Concat(data).ToArray();
 
-            // simulate string.Split('\n') before decoding
-            var newLineIndices = _buffer.Select((b, i) => b == '\n' ? i : -1).Where(i => i != -1).ToArray();
-            var lines          = new List<byte[]>();
-
-            for (int i = 0, currentIndex = 0; i < newLineIndices.Length; ++i)
-            {
-                var n = new byte[newLineIndices[i] - currentIndex];
-                Array.Copy(_buffer, currentIndex, n, 0, newLineIndices[i] - currentIndex);
-                currentIndex = newLineIndices[i] + 1;
-                lines.Add(n);
-            }
-
-            var listLines = lines.Select(l => l.ToList()).ToList();
-
-            // simulate string.Trim('\r') before decoding
-            foreach (var line in listLines)
-            {
-                var i = 0;
-                while (line[i] == '\r')
-                {
-                    line.RemoveAt(i);
-                    i++;
-                }
-
-                i = line.Count - 1;
-                while (line[i] == '\r')
-                {
-                    line.RemoveAt(i);
-                    i--;
-                }
-            }
-
-            _buffer = listLines[^1].ToArray();
+            var listLines = _buffer.Split((byte) '\n').Select(l => l.Trim((byte) '\r')).ToList();
+            _buffer = listLines.Last();
 
             var decodeLines = new List<Line>();
             foreach (var line in listLines.SkipLast(1).Select(l => l.ToArray()))