in src/Elastic.Apm/Libraries/Newtonsoft.Json/JsonTextReader.cs [1048:1202]
private void ReadStringIntoBuffer(char quote)
{
MiscellaneousUtils.Assert(CharBuffer != null);
var charPos = CharPos;
var initialPosition = CharPos;
var lastWritePosition = CharPos;
_stringBuffer.Position = 0;
while (true)
{
switch (CharBuffer[charPos++])
{
case '\0':
if (_charsUsed == charPos - 1)
{
charPos--;
if (ReadData(true) == 0)
{
CharPos = charPos;
throw JsonReaderException.Create(this,
"Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
}
}
break;
case '\\':
CharPos = charPos;
if (!EnsureChars(0, true))
throw JsonReaderException.Create(this,
"Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
// start of escape sequence
var escapeStartPos = charPos - 1;
var currentChar = CharBuffer[charPos];
charPos++;
char writeChar;
switch (currentChar)
{
case 'b':
writeChar = '\b';
break;
case 't':
writeChar = '\t';
break;
case 'n':
writeChar = '\n';
break;
case 'f':
writeChar = '\f';
break;
case 'r':
writeChar = '\r';
break;
case '\\':
writeChar = '\\';
break;
case '"':
case '\'':
case '/':
writeChar = currentChar;
break;
case 'u':
CharPos = charPos;
writeChar = ParseUnicode();
if (StringUtils.IsLowSurrogate(writeChar))
{
// low surrogate with no preceding high surrogate; this char is replaced
writeChar = UnicodeReplacementChar;
}
else if (StringUtils.IsHighSurrogate(writeChar))
{
bool anotherHighSurrogate;
// loop for handling situations where there are multiple consecutive high surrogates
do
{
anotherHighSurrogate = false;
// potential start of a surrogate pair
if (EnsureChars(2, true) && CharBuffer[CharPos] == '\\' && CharBuffer[CharPos + 1] == 'u')
{
var highSurrogate = writeChar;
CharPos += 2;
writeChar = ParseUnicode();
if (StringUtils.IsLowSurrogate(writeChar))
{
// a valid surrogate pair!
}
else if (StringUtils.IsHighSurrogate(writeChar))
{
// another high surrogate; replace current and start check over
highSurrogate = UnicodeReplacementChar;
anotherHighSurrogate = true;
}
else
{
// high surrogate not followed by low surrogate; original char is replaced
highSurrogate = UnicodeReplacementChar;
}
EnsureBufferNotEmpty();
WriteCharToBuffer(highSurrogate, lastWritePosition, escapeStartPos);
lastWritePosition = CharPos;
}
else
{
// there are not enough remaining chars for the low surrogate or is not follow by unicode sequence
// replace high surrogate and continue on as usual
writeChar = UnicodeReplacementChar;
}
} while (anotherHighSurrogate);
}
charPos = CharPos;
break;
default:
CharPos = charPos;
throw JsonReaderException.Create(this,
"Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar));
}
EnsureBufferNotEmpty();
WriteCharToBuffer(writeChar, lastWritePosition, escapeStartPos);
lastWritePosition = charPos;
break;
case StringUtils.CarriageReturn:
CharPos = charPos - 1;
ProcessCarriageReturn(true);
charPos = CharPos;
break;
case StringUtils.LineFeed:
CharPos = charPos - 1;
ProcessLineFeed();
charPos = CharPos;
break;
case '"':
case '\'':
if (CharBuffer[charPos - 1] == quote)
{
FinishReadStringIntoBuffer(charPos - 1, initialPosition, lastWritePosition);
return;
}
break;
}
}
}