private void ParseEndElement()
{
// check if the end tag name equals start tag name
NodeData startTagNode = _nodes[_index - 1];
int prefLen = startTagNode.prefix.Length;
int locLen = startTagNode.localName.Length;
while (_ps.charsUsed - _ps.charPos < prefLen + locLen + 1)
{
if (ReadData() == 0)
{
break;
}
}
int nameLen;
char[] chars = _ps.chars;
if (startTagNode.prefix.Length == 0)
{
if (!XmlConvert.StrEqual(chars, _ps.charPos, locLen, startTagNode.localName))
{
ThrowTagMismatch(startTagNode);
}
nameLen = locLen;
}
else
{
int colonPos = _ps.charPos + prefLen;
if (!XmlConvert.StrEqual(chars, _ps.charPos, prefLen, startTagNode.prefix) ||
chars[colonPos] != ':' ||
!XmlConvert.StrEqual(chars, colonPos + 1, locLen, startTagNode.localName))
{
ThrowTagMismatch(startTagNode);
}
nameLen = locLen + prefLen + 1;
}
LineInfo endTagLineInfo = new LineInfo(_ps.lineNo, _ps.LinePos);
int pos;
for (;;)
{
pos = _ps.charPos + nameLen;
chars = _ps.chars;
if (pos == _ps.charsUsed)
{
goto ReadData;
}
unsafe
{
if (_xmlCharType.IsNCNameSingleChar(chars[pos]) || (chars[pos] == ':')
#if XML10_FIFTH_EDITION
|| xmlCharType.IsNCNameHighSurrogateChar(chars[pos])
#endif
)
{
ThrowTagMismatch(startTagNode);
}
}
// eat whitespaces
if (chars[pos] != '>')
{
char tmpCh;
while (_xmlCharType.IsWhiteSpace(tmpCh = chars[pos]))
{
pos++;
switch (tmpCh)
{
case (char)0xA:
OnNewLine(pos);
continue;
case (char)0xD:
if (chars[pos] == (char)0xA)
{
pos++;
}
else if (pos == _ps.charsUsed && !_ps.isEof)
{
break;
}
OnNewLine(pos);
continue;
}
}
}
if (chars[pos] == '>')
{
break;
}
else if (pos == _ps.charsUsed)
{
goto ReadData;
}
else
{
ThrowUnexpectedToken(pos, ">");
}
Debug.Assert(false, "We should never get to this point.");
ReadData:
if (ReadData() == 0)
{
ThrowUnclosedElements();
}
}
Debug.Assert(_index > 0);
_index--;
_curNode = _nodes[_index];
// set the element data
Debug.Assert(_curNode == startTagNode);
startTagNode.lineInfo = endTagLineInfo;
startTagNode.type = XmlNodeType.EndElement;
_ps.charPos = pos + 1;
// set next parsing function
_nextParsingFunction = (_index > 0) ? _parsingFunction : ParsingFunction.DocumentContent;
_parsingFunction = ParsingFunction.PopElementContext;
}