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