about summary refs log blame commit diff
path: root/IrcTokens/Protocol.cs
blob: 3769ea35e848584430dcb5c11795c8b838749e9a (plain) (tree)
1
2
3
4
5
6
7
8
9






                           
                           
     
                                                       



                                      
                                                     



















































                                                                            
                                                                                            





                       
using System;
using System.Globalization;
using System.Linq;
using System.Text;

namespace IrcTokens
{
    internal class Protocol
    {
        private static readonly string[] TagUnescaped =
        {
            "\\", " ", ";", "\r", "\n"
        };

        private static readonly string[] TagEscaped =
        {
            "\\\\", "\\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], StringComparison.Ordinal);
            }

            return val;
        }
    }
}