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;
}
}