about summary refs log tree commit diff
path: root/IrcTokens/Protocol.cs
diff options
context:
space:
mode:
Diffstat (limited to 'IrcTokens/Protocol.cs')
-rw-r--r--IrcTokens/Protocol.cs74
1 files changed, 74 insertions, 0 deletions
diff --git a/IrcTokens/Protocol.cs b/IrcTokens/Protocol.cs
new file mode 100644
index 0000000..b2af6fa
--- /dev/null
+++ b/IrcTokens/Protocol.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace IrcTokens
+{
+    public class Protocol
+    {
+        private static readonly string[] TagUnescaped = new []
+        {
+            "\\", " ", ";", "\r", "\n"
+        };
+
+        private static readonly string[] TagEscaped = new []
+        {
+            "\\\\", "\\s", "\\:", "\\r", "\\n"
+        };
+
+        /// <summary>
+        /// Unescape ircv3 tag
+        /// </summary>
+        /// <param name="val">escaped string</param>
+        /// <returns>unescaped string</returns>
+        public static string UnescapeTag(string val)
+        {
+            var unescaped = new StringBuilder();
+
+            var graphemeIterator = StringInfo.GetTextElementEnumerator(val);
+            graphemeIterator.Reset();
+
+            while (graphemeIterator.MoveNext())
+            {
+                var current = graphemeIterator.GetTextElement();
+
+                if (current == @"\")
+                {
+                    try
+                    {
+                        graphemeIterator.MoveNext();
+                        var next = graphemeIterator.GetTextElement();
+                        var pair = current + next;
+                        unescaped.Append(TagEscaped.Contains(pair)
+                            ? TagUnescaped[Array.IndexOf(TagEscaped, pair)]
+                            : next);
+                    }
+                    catch (InvalidOperationException)
+                    {
+                        // ignored
+                    }
+                }
+                else
+                    unescaped.Append(current);
+            }
+
+            return unescaped.ToString();
+        }
+
+        /// <summary>
+        /// Escape strings for use in ircv3 tags
+        /// </summary>
+        /// <param name="val">string to escape</param>
+        /// <returns>escaped string</returns>
+        public static string EscapeTag(string val)
+        {
+            for (var i = 0; i < TagUnescaped.Length; ++i)
+            {
+                val = val.Replace(TagUnescaped[i], TagEscaped[i]);
+            }
+
+            return val;
+        }
+    }
+}