private bool TryReadEscapeChar(ref TextPosition end) { if (_c == '\\') { end = _position; NextChar(); // 0 \ ' " a b f n r t v u0000-uFFFF x00-xFF switch (_c) { case 'b': _textBuilder.Append('\b'); end = _position; NextChar(); return(true); case 't': _textBuilder.Append('\t'); end = _position; NextChar(); return(true); case 'n': _textBuilder.Append('\n'); end = _position; NextChar(); return(true); case 'f': _textBuilder.Append('\f'); end = _position; NextChar(); return(true); case 'r': _textBuilder.Append('\r'); end = _position; NextChar(); return(true); case '"': _textBuilder.Append('"'); end = _position; NextChar(); return(true); case '\\': _textBuilder.Append('\\'); end = _position; NextChar(); return(true); // toml-specs: When the last non-whitespace character on a line is a \, // it will be trimmed along with all whitespace (including newlines) // up to the next non-whitespace character or closing delimiter. case '\r': case '\n': while (CharHelper.IsWhiteSpaceOrNewLine(_c)) { end = _position; NextChar(); } return(true); case 'u': case 'U': { var start = _position; end = _position; var maxCount = _c == 'u' ? 4 : 8; NextChar(); // Must be followed 0 to 8 hex numbers (0-FFFFFFFF) int i = 0; int value = 0; for (; CharHelper.IsHexFunc(_c) && i < maxCount; i++) { value = (value << 4) + CharHelper.HexToDecimal(_c); end = _position; NextChar(); } if (i == maxCount) { if (!CharHelper.IsValidUnicodeScalarValue(value)) { AddError($"Invalid Unicode scalar value [{value:X}]", start, start); } _textBuilder.AppendUtf32((char32)value); return(true); } } break; } AddError($"Unexpected escape character [{_c}] in string. Only b t n f r \\ \" u0000-uFFFF U00000000-UFFFFFFFF are allowed", _position, _position); return(false); } return(false); }