using System.Globalization; using System.Text; namespace IRCTokens; public static class TagEscape { private static readonly string[] TagUnescaped = ["\\", " ", ";", "\r", "\n"]; private static readonly string[] TagEscaped = [@"\\", "\\s", "\\:", "\\r", "\\n"]; /// Unescape ircv3 tag /// escaped string /// unescaped string public static string Unescape(string val) { StringBuilder unescaped = new(); 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(); } /// Escape strings for use in ircv3 tags /// string to escape /// escaped string public static string Escape(string val) { StringBuilder sb = new(val); for (var i = 0; i < TagUnescaped.Length; ++i) { sb.Replace(TagUnescaped[i], TagEscaped[i]); } return sb.ToString(); } }