private static IEnumerable DecodeChars()

in TeamCity.ServiceMessages/ServiceMessageReplacements.cs [82:185]


        private static IEnumerable<char> DecodeChars([NotNull] IEnumerable<char> value)
        {
            var isEscaping = false;
            var unicodeCounter = 0;
            var unicodeSb = new StringBuilder();
            foreach (var ch in value)
            {
                if (unicodeCounter > 0)
                {
                    if (unicodeCounter-- == 5)
                    {
                        if (ch != 'x')
                        {
                            unicodeCounter = 0;
                        }
                    }
                    else
                    {
                        unicodeSb.Append(ch);
                    }
                }

                if (unicodeCounter != 0)
                {
                    continue;
                }

                if (unicodeSb.Length == 4)
                {
                    var unicodeStr = "" + InvalidChar;
                    try
                    {
                        unicodeStr = char.ConvertFromUtf32(int.Parse(unicodeSb.ToString(), NumberStyles.HexNumber));
                    }
                    catch (FormatException)
                    {
                    }

                    unicodeSb.Length = 0;
                    foreach (var c in unicodeStr)
                    {
                        yield return c;
                    }

                    continue;
                }

                if (isEscaping)
                {
                    isEscaping = false;
                    switch (ch)
                    {
                        case '|':
                            yield return '|';
                            break; //
                        case '\'':
                            yield return '\'';
                            break; //
                        case 'n':
                            yield return '\n';
                            break; //
                        case 'r':
                            yield return '\r';
                            break; //
                        case '[':
                            yield return '[';
                            break; //
                        case ']':
                            yield return ']';
                            break; //
                        case 'x':
                            yield return '\u0085';
                            break; //\u0085 (next line)=>|x
                        case 'l':
                            yield return '\u2028';
                            break; //\u2028 (line separator)=>|l
                        case 'p':
                            yield return '\u2029';
                            break; //
                        case '0':
                            unicodeCounter = 5;
                            break;
                        default:
                            yield return InvalidChar;
                            break; // do not throw any exception to make it faster //TODO: no exception on illegal format
                    }

                    continue;
                }

                if (ch == '|')
                {
                    isEscaping = true;
                    continue;
                }

                yield return ch;
            }

            if (isEscaping || unicodeCounter > 0)
            {
                yield return InvalidChar;
            }
        }