/// <summary>
        /// Escape string with backslash sequences (e.g. \r\n -> \\r\\n)
        /// </summary>
        /// <param name="s">String to escape</param>
        /// <param name="stringEscapeOptions">String escape options</param>
        /// <param name="charEscapeOptions">Char escape options</param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequences for string</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public static string Escape(string s, StringEscapeOptions stringEscapeOptions = null, CharEscapeOptions charEscapeOptions = null, bool addQuotes = false)
        {
            if (s == null)
            {
                throw new ArgumentNullException(nameof(s));
            }
            if (stringEscapeOptions == null)
            {
                stringEscapeOptions = new StringEscapeOptions();
            }
            if (charEscapeOptions == null)
            {
                charEscapeOptions = new CharEscapeOptions();
            }

            switch (charEscapeOptions.EscapeLanguage)
            {
            case CharEscapeLanguage.CSharp:
                return(EscapeCSharp(s, stringEscapeOptions, charEscapeOptions, addQuotes));

            case CharEscapeLanguage.FSharp:
                return(EscapeFSharp(s, stringEscapeOptions, charEscapeOptions, addQuotes));

            case CharEscapeLanguage.PowerShell:
                return(EscapePowerShell(s, stringEscapeOptions, charEscapeOptions, addQuotes));

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1}.", charEscapeOptions.EscapeLanguage, nameof(charEscapeOptions.EscapeLanguage)), nameof(charEscapeOptions));
            }
        }
Example #2
0
        /// <summary>
        /// Escape char with backslash sequence (e.g. \n -> \\n)
        /// </summary>
        /// <param name="c">Char to escape</param>
        /// <param name="escapeOptions">Escape options</param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequence for char</returns>
        /// <exception cref="ArgumentException"></exception>
        public static string Escape(char c, CharEscapeOptions escapeOptions = null, bool addQuotes = false)
        {
            if (escapeOptions == null)
            {
                escapeOptions = new CharEscapeOptions();
            }

            switch (escapeOptions.EscapeLanguage)
            {
            case CharEscapeLanguage.CSharp:
                return(EscapeCSharp(c, escapeOptions, addQuotes));

            case CharEscapeLanguage.FSharp:
                return(EscapeFSharp(c, escapeOptions, addQuotes));

            case CharEscapeLanguage.PowerShell:
                throw new ArgumentException(string.Format("{0} does not have a char type.", escapeOptions.EscapeLanguage), nameof(escapeOptions));

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1}.", escapeOptions.EscapeLanguage, nameof(escapeOptions.EscapeLanguage)), nameof(escapeOptions));
            }
        }
Example #3
0
        /// <summary>
        /// Escape char with backslash sequence (e.g. \n -> \\n)
        /// </summary>
        /// <param name="c">Char to escape</param>
        /// <param name="escapeOptions">Escape options</param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequence for char</returns>
        /// <exception cref="ArgumentException"></exception>
        internal static string EscapeCSharp(char c, CharEscapeOptions escapeOptions, bool addQuotes = false)
        {
            if (escapeOptions.UseShortEscape)
            {
                switch (c)
                {
                case '\'':
                    return("\\\'");

                case '\"':
                    return("\\\"");

                case '\\':
                    return("\\\\");

                case '\0':
                    return("\\0");

                case '\a':
                    return("\\a");

                case '\b':
                    return("\\b");

                case '\f':
                    return("\\f");

                case '\n':
                    return("\\n");

                case '\r':
                    return("\\r");

                case '\t':
                    return("\\t");

                case '\v':
                    return("\\v");
                }
            }

            string xu;
            string hex;

            switch (escapeOptions.EscapeLetter)
            {
            case CharEscapeLetter.LowerCaseX1:
                xu  = "x";
                hex = escapeOptions.UseLowerCaseHex ? "x1" : "X1";
                break;

            case CharEscapeLetter.LowerCaseX2:
                xu  = "x";
                hex = escapeOptions.UseLowerCaseHex ? "x2" : "X2";
                break;

            case CharEscapeLetter.LowerCaseX3:
                xu  = "x";
                hex = escapeOptions.UseLowerCaseHex ? "x3" : "X3";
                break;

            case CharEscapeLetter.LowerCaseX4:
                xu  = "x";
                hex = escapeOptions.UseLowerCaseHex ? "x4" : "X4";
                break;

            case CharEscapeLetter.LowerCaseU4:
                xu  = "u";
                hex = escapeOptions.UseLowerCaseHex ? "x4" : "X4";
                break;

            case CharEscapeLetter.UpperCaseU8:
                xu  = "U";
                hex = escapeOptions.UseLowerCaseHex ? "x8" : "X8";
                break;

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.EscapeLetter, nameof(escapeOptions.EscapeLetter), escapeOptions.EscapeLanguage), nameof(escapeOptions));
            }

            string escaped = "\\" + xu + ((int)c).ToString(hex);

            if (addQuotes)
            {
                escaped = "\'" + escaped + "\'";
            }
            return(escaped);
        }
Example #4
0
        /// <summary>
        /// Escape surrogate pair with `u{HHHHH}
        /// </summary>
        /// <param name="highSurrogate">High surrogate</param>
        /// <param name="lowSurrogate">Low surrogate</param>
        /// <param name="escapeOptions">Char escape options</param>
        /// <returns>String with escape sequence for surrogate pair</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        internal static string EscapeSurrogatePairPowerShell(char highSurrogate, char lowSurrogate, CharEscapeOptions escapeOptions)
        {
            int codePoint = char.ConvertToUtf32(highSurrogate, lowSurrogate);

            string hex;

            switch (escapeOptions.SurrogatePairEscapeLetter)
            {
            // 1/2/3/4 will output as 5 so we can just fall through
            case CharEscapeLetter.LowerCaseU1:
            case CharEscapeLetter.LowerCaseU2:
            case CharEscapeLetter.LowerCaseU3:
            case CharEscapeLetter.LowerCaseU4:
            case CharEscapeLetter.LowerCaseU5:
                hex = escapeOptions.UseLowerCaseHex ? "x5" : "X5";
                break;

            case CharEscapeLetter.LowerCaseU6:
                hex = escapeOptions.UseLowerCaseHex ? "x6" : "X6";
                break;

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.SurrogatePairEscapeLetter, nameof(escapeOptions.SurrogatePairEscapeLetter), escapeOptions.EscapeLanguage), nameof(escapeOptions));
            }

            return("`u{" + codePoint.ToString(hex) + "}");
        }
Example #5
0
        /// <summary>
        /// Escape surrogate pair with \\UHHHHHHHH
        /// </summary>
        /// <param name="highSurrogate">High surrogate</param>
        /// <param name="lowSurrogate">Low surrogate</param>
        /// <param name="escapeOptions">Char escape options</param>
        /// <returns>String with escape sequence for surrogate pair</returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        internal static string EscapeSurrogatePairFSharp(char highSurrogate, char lowSurrogate, CharEscapeOptions escapeOptions)
        {
            int codePoint = char.ConvertToUtf32(highSurrogate, lowSurrogate);

            string hex;

            switch (escapeOptions.SurrogatePairEscapeLetter)
            {
            case CharEscapeLetter.UpperCaseU8:
                hex = escapeOptions.UseLowerCaseHex ? "x8" : "X8";
                break;

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.SurrogatePairEscapeLetter, nameof(escapeOptions.SurrogatePairEscapeLetter), escapeOptions.EscapeLanguage), nameof(escapeOptions));
            }

            return("\\U" + codePoint.ToString(hex));
        }
Example #6
0
        /// <summary>
        /// Escape char with backslash sequence (e.g. \n -> `n)
        /// </summary>
        /// <param name="c">Char to escape</param>
        /// <param name="escapeOptions">Escape options</param>
        /// <returns>String with escape sequence for char</returns>
        /// <exception cref="ArgumentException"></exception>
        internal static string EscapePowerShell(char c, CharEscapeOptions escapeOptions)
        {
            if (escapeOptions.UseShortEscape)
            {
                // escaping single quotes here doesn't make any sense
                // within double-quoted strings `' is the same as '
                // within single-quoted strings `' doesn't work, you have to double ' to ''
                switch (c)
                {
                case '\0':
                    return("`0");

                case '\a':
                    return("`a");

                case '\b':
                    return("`b");

                case '\x1B':         // escape
                    return("`e");    // this is supported in PowerShell v7, but not Windows PowerShell v5

                case '\f':
                    return("`f");

                case '\n':
                    return("`n");

                case '\r':
                    return("`r");

                case '\t':
                    return("`t");

                case '\v':
                    return("`v");

                case '`':
                    return("``");

                case '\"':
                    return("`\"");    // technically you can use either `" or "" within double-quoted strings

                case '$':
                    return("`$");     // dollar sign interpolates variables, something we can't support, so escape it
                }
            }

            string hex;

            switch (escapeOptions.EscapeLetter)
            {
            case CharEscapeLetter.LowerCaseU1:
                hex = escapeOptions.UseLowerCaseHex ? "x1" : "X1";
                break;

            case CharEscapeLetter.LowerCaseU2:
                hex = escapeOptions.UseLowerCaseHex ? "x2" : "X2";
                break;

            case CharEscapeLetter.LowerCaseU3:
                hex = escapeOptions.UseLowerCaseHex ? "x3" : "X3";
                break;

            case CharEscapeLetter.LowerCaseU4:
                hex = escapeOptions.UseLowerCaseHex ? "x4" : "X4";
                break;

            case CharEscapeLetter.LowerCaseU5:
                hex = escapeOptions.UseLowerCaseHex ? "x5" : "X5";
                break;

            case CharEscapeLetter.LowerCaseU6:
                hex = escapeOptions.UseLowerCaseHex ? "x6" : "X6";
                break;

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.EscapeLetter, nameof(escapeOptions.EscapeLetter), escapeOptions.EscapeLanguage), nameof(escapeOptions));
            }

            return("`u{" + ((int)c).ToString(hex) + "}"); // this is supported in PowerShell v7, but not Windows PowerShell v5
        }
Example #7
0
        /// <summary>
        /// Escape char with backslash sequence (e.g. \n -> \\n)
        /// </summary>
        /// <param name="c">Char to escape</param>
        /// <param name="escapeOptions">Escape options</param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequence for char</returns>
        /// <exception cref="ArgumentException"></exception>
        internal static string EscapeFSharp(char c, CharEscapeOptions escapeOptions, bool addQuotes = false)
        {
            if (escapeOptions.UseShortEscape)
            {
                // FSharp doesn't define \0, the closest is \000
                switch (c)
                {
                case '\a':
                    return("\\a");

                case '\b':
                    return("\\b");

                case '\f':
                    return("\\f");

                case '\n':
                    return("\\n");

                case '\r':
                    return("\\r");

                case '\t':
                    return("\\t");

                case '\v':
                    return("\\v");

                case '\\':
                    return("\\\\");

                case '\'':
                    return("\\\'");

                case '\"':
                    return("\\\"");
                }
            }

            string xu  = null;
            string hex = null;

            switch (escapeOptions.EscapeLetter)
            {
            case CharEscapeLetter.None3:
                if (c <= 255)
                {
                    xu  = "";
                    hex = "D3";
                }
                break;

            case CharEscapeLetter.LowerCaseX2:
                if (c <= 0xFF)
                {
                    xu  = "x";
                    hex = escapeOptions.UseLowerCaseHex ? "x2" : "X2";
                }
                break;

            case CharEscapeLetter.LowerCaseU4:
                xu  = "u";
                hex = escapeOptions.UseLowerCaseHex ? "x4" : "X4";
                break;

            case CharEscapeLetter.UpperCaseU8:
                xu  = "U";
                hex = escapeOptions.UseLowerCaseHex ? "x8" : "X8";
                break;

            default:
                throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.EscapeLetter, nameof(escapeOptions.EscapeLetter), escapeOptions.EscapeLanguage), nameof(escapeOptions));
            }

            if (xu == null || hex == null)
            {
                switch (escapeOptions.EscapeLetterFallback)
                {
                case CharEscapeLetter.LowerCaseU4:
                    xu  = "u";
                    hex = escapeOptions.UseLowerCaseHex ? "x4" : "X4";
                    break;

                case CharEscapeLetter.UpperCaseU8:
                    xu  = "U";
                    hex = escapeOptions.UseLowerCaseHex ? "x8" : "X8";
                    break;

                default:
                    throw new ArgumentException(string.Format("{0} is not a valid {1} for {2}.", escapeOptions.EscapeLetterFallback, nameof(escapeOptions.EscapeLetterFallback), escapeOptions.EscapeLanguage), nameof(escapeOptions));
                }
            }

            string escaped = "\\" + xu + ((int)c).ToString(hex);

            if (addQuotes)
            {
                escaped = "\'" + escaped + "\'";
            }
            return(escaped);
        }
        /// <summary>
        /// Escape string with backslash sequences (e.g. \r\n -> \\r\\n)
        /// </summary>
        /// <param name="s">String to escape</param>
        /// <param name="stringEscapeOptions">String escape options</param>
        /// <param name="charEscapeOptions"></param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequences for string</returns>
        /// <exception cref="ArgumentException"></exception>
        private static string EscapeCSharp(string s, StringEscapeOptions stringEscapeOptions, CharEscapeOptions charEscapeOptions, bool addQuotes)
        {
            CharEscapeOptions charEscapeOptionsLowerCaseX4 = new CharEscapeOptions(
                escapeLanguage: charEscapeOptions.EscapeLanguage,
                escapeLetter: CharEscapeLetter.LowerCaseX4,
                escapeLetterFallback: charEscapeOptions.EscapeLetterFallback,
                surrogatePairEscapeLetter: charEscapeOptions.SurrogatePairEscapeLetter,
                useLowerCaseHex: charEscapeOptions.UseLowerCaseHex,
                useShortEscape: charEscapeOptions.UseShortEscape
                );

            StringBuilder sb = new StringBuilder(s.Length);

            for (int i = 0; i < s.Length; i++)
            {
                if (stringEscapeOptions.EscapeSurrogatePairs && i + 1 < s.Length && char.IsSurrogatePair(s[i], s[i + 1]))
                {
                    sb.Append(CharUtils.EscapeSurrogatePairCSharp(s[i], s[++i], charEscapeOptions));
                }
                else
                {
                    switch (stringEscapeOptions.EscapeKind)
                    {
                    case StringEscapeKind.EscapeAll:
                        sb.Append(CharUtils.EscapeCSharp(s[i], charEscapeOptions));
                        break;

                    case StringEscapeKind.EscapeNonAscii:
                        if (s[i].IsPrintAscii() && !s[i].IsBackslash() && !s[i].IsDoubleQuote())
                        {
                            sb.Append(s[i]);
                        }
                        else
                        {
                            // pay special attention here because \x is variable length: H, HH, HHH, HHHH
                            // if the next char is hex then we don't want to insert it in any of the 'H' spaces
                            // instead we have to output the full fixed length \xHHHH so the next char doesn't become part of this \x sequence
                            if ((charEscapeOptions.EscapeLetter == CharEscapeLetter.LowerCaseX1 || charEscapeOptions.EscapeLetter == CharEscapeLetter.LowerCaseX2 || charEscapeOptions.EscapeLetter == CharEscapeLetter.LowerCaseX3) && i + 1 < s.Length && s[i + 1].IsHex())
                            {
                                sb.Append(CharUtils.EscapeCSharp(s[i], charEscapeOptionsLowerCaseX4));
                            }
                            else
                            {
                                sb.Append(CharUtils.EscapeCSharp(s[i], charEscapeOptions));
                            }
                        }
                        break;

                    default:
                        throw new ArgumentException(string.Format("{0} is not a valid {1}.", stringEscapeOptions.EscapeKind, nameof(stringEscapeOptions.EscapeKind)), nameof(stringEscapeOptions));
                    }
                }
            }

            if (addQuotes)
            {
                sb.Insert(0, '\"');
                sb.Append('\"');
            }
            return(sb.ToString());
        }
        /// <summary>
        /// Escape string with backslash sequences (e.g. \r\n -> `r`n)
        /// </summary>
        /// <param name="s">String to escape</param>
        /// <param name="stringEscapeOptions">String escape options</param>
        /// <param name="charEscapeOptions">Char escape options</param>
        /// <param name="addQuotes">Add quotes after escaping</param>
        /// <returns>String with escape sequences for string</returns>
        /// <exception cref="ArgumentException"></exception>
        private static string EscapePowerShell(string s, StringEscapeOptions stringEscapeOptions, CharEscapeOptions charEscapeOptions, bool addQuotes)
        {
            StringBuilder sb = new StringBuilder(s.Length);

            for (int i = 0; i < s.Length; i++)
            {
                if (stringEscapeOptions.EscapeSurrogatePairs && i + 1 < s.Length && char.IsSurrogatePair(s[i], s[i + 1]))
                {
                    sb.Append(CharUtils.EscapeSurrogatePairPowerShell(s[i], s[++i], charEscapeOptions));
                }
                else
                {
                    switch (stringEscapeOptions.EscapeKind)
                    {
                    case StringEscapeKind.EscapeAll:
                        sb.Append(CharUtils.EscapePowerShell(s[i], charEscapeOptions));
                        break;

                    case StringEscapeKind.EscapeNonAscii:
                        if (s[i].IsPrintAscii() && !s[i].IsBacktick() && !s[i].IsDoubleQuote() && !s[i].IsDollarSign())
                        {
                            sb.Append(s[i]);
                        }
                        else
                        {
                            sb.Append(CharUtils.EscapePowerShell(s[i], charEscapeOptions));
                        }
                        break;

                    default:
                        throw new ArgumentException(string.Format("{0} is not a valid {1}.", stringEscapeOptions.EscapeKind, nameof(stringEscapeOptions.EscapeKind)), nameof(stringEscapeOptions));
                    }
                }
            }

            if (addQuotes)
            {
                sb.Insert(0, '\"');
                sb.Append('\"');
            }
            return(sb.ToString());
        }