/// <summary> /// Given that the next character is an ampersand ('&'), attempt to interpret the /// following characters as an XML entity. On success, populate the out parameters /// with the low and high UTF-16 surrogates for the character represented by the /// entity. /// </summary> /// <param name="ch">e.g. '<' for &lt;.</param> /// <param name="surrogate">e.g. '\uDC00' for &#x10000; (ch == '\uD800').</param> /// <returns>True if a valid XML entity was consumed.</returns> /// <remarks> /// NOTE: Always advances, even on failure. /// </remarks> public bool TryScanXmlEntity(out char ch, out char surrogate) { Debug.Assert(this.PeekChar() == '&'); ch = '&'; this.AdvanceChar(); surrogate = InvalidCharacter; switch (this.PeekChar()) { case 'l': if (AdvanceIfMatches("lt;")) { ch = '<'; return(true); } break; case 'g': if (AdvanceIfMatches("gt;")) { ch = '>'; return(true); } break; case 'a': if (AdvanceIfMatches("amp;")) { ch = '&'; return(true); } else if (AdvanceIfMatches("apos;")) { ch = '\''; return(true); } break; case 'q': if (AdvanceIfMatches("quot;")) { ch = '"'; return(true); } break; case '#': { this.AdvanceChar(); //# uint uintChar = 0; if (AdvanceIfMatches("x")) { char digit; while (SyntaxFacts.IsHexDigit(digit = this.PeekChar())) { this.AdvanceChar(); // disallow overflow if (uintChar <= 0x7FFFFFF) { uintChar = (uintChar << 4) + (uint)SyntaxFacts.HexValue(digit); } else { return(false); } } } else { char digit; while (SyntaxFacts.IsDecDigit(digit = this.PeekChar())) { this.AdvanceChar(); // disallow overflow if (uintChar <= 0x7FFFFFF) { uintChar = (uintChar << 3) + (uintChar << 1) + (uint)SyntaxFacts.DecValue(digit); } else { return(false); } } } if (AdvanceIfMatches(";")) { ch = GetCharsFromUtf32(uintChar, out surrogate); return(true); } break; } } return(false); }
private char ScanUnicodeEscape(bool peek, out char surrogateCharacter, out SyntaxDiagnosticInfo info) { surrogateCharacter = InvalidCharacter; info = null; int start = this.Position; char character = this.PeekChar(); Debug.Assert(character == '\\'); this.AdvanceChar(); character = this.PeekChar(); if (character == 'U') { uint uintChar = 0; this.AdvanceChar(); if (!SyntaxFacts.IsHexDigit(this.PeekChar())) { if (!peek) { info = CreateIllegalEscapeDiagnostic(start); } } else { for (int i = 0; i < 8; i++) { character = this.PeekChar(); if (!SyntaxFacts.IsHexDigit(character)) { if (!peek) { info = CreateIllegalEscapeDiagnostic(start); } break; } uintChar = (uint)((uintChar << 4) + SyntaxFacts.HexValue(character)); this.AdvanceChar(); } if (uintChar > 0x0010FFFF) { if (!peek) { info = CreateIllegalEscapeDiagnostic(start); } } else { character = GetCharsFromUtf32(uintChar, out surrogateCharacter); } } } else { Debug.Assert(character == 'u' || character == 'x'); int intChar = 0; this.AdvanceChar(); if (!SyntaxFacts.IsHexDigit(this.PeekChar())) { if (!peek) { info = CreateIllegalEscapeDiagnostic(start); } } else { for (int i = 0; i < 4; i++) { char ch2 = this.PeekChar(); if (!SyntaxFacts.IsHexDigit(ch2)) { if (character == 'u') { if (!peek) { info = CreateIllegalEscapeDiagnostic(start); } } break; } intChar = (intChar << 4) + SyntaxFacts.HexValue(ch2); this.AdvanceChar(); } character = (char)intChar; } } return(character); }