diff options
Diffstat (limited to 'IrcTokens')
-rw-r--r-- | IrcTokens/Extensions.cs | 59 | ||||
-rw-r--r-- | IrcTokens/Line.cs | 4 | ||||
-rw-r--r-- | IrcTokens/StatefulDecoder.cs | 37 |
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())) |