private Task ParseEndElementAsync_CheckEndTag(int nameLen, NodeData startTagNode, LineInfo endTagLineInfo)
        {
            int pos;
            char[] chars;
            for (; ;)
            {
                pos = _ps.charPos + nameLen;
                chars = _ps.chars;

                if (pos == _ps.charsUsed)
                {
                    _parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData;
                    return Task.CompletedTask;
                }

                bool tagMismatch = false;

                unsafe
                {
                    if (_xmlCharType.IsNCNameSingleChar(chars[pos]) || (chars[pos] == ':')
#if XML10_FIFTH_EDITION
                         || xmlCharType.IsNCNameHighSurrogateChar(chars[pos])
#endif
)
                    {
                        tagMismatch = true;
                    }
                }

                if (tagMismatch)
                {
                    return ThrowTagMismatchAsync(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)
                {
                    _parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData;
                    return Task.CompletedTask;
                }
                else
                {
                    ThrowUnexpectedToken(pos, ">");
                }

                Debug.Assert(false, "We should never get to this point.");
            }

            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;

            _parseEndElement_NextFunc = ParseEndElementParseFunction.Done;
            return Task.CompletedTask;
        }
 private async Task ParseEndElementAsync_ReadData()
 {
     if (await ReadDataAsync().ConfigureAwait(false) == 0)
     {
         ThrowUnclosedElements();
     }
     _parseEndElement_NextFunc = ParseEndElementParseFunction.CheckEndTag;
     return;
 }
        private Task ParseEndElementAsync_CheckEndTag(int nameLen, NodeData startTagNode, LineInfo endTagLineInfo) {

            int pos;
            char[] chars;
            for (; ; ) {
                pos = ps.charPos + nameLen;
                chars = ps.chars;

                if (pos == ps.charsUsed) {
                    parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData;
                    return AsyncHelper.DoneTask;
                }

                bool tagMismatch = false;

                unsafe {
#if SILVERLIGHT
                    if ( xmlCharType.IsNCNameSingleChar( chars[pos] ) ||
#else // Optimization due to the lack of inlining when a method uses byte*
                    if (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCNameSC) != 0) ||
#endif
 (chars[pos] == ':')
#if XML10_FIFTH_EDITION
                         || xmlCharType.IsNCNameHighSurrogateChar( chars[pos] ) 
#endif
) {
                        tagMismatch = true;
                    }
                }
                                
                if (tagMismatch) {
                    return ThrowTagMismatchAsync(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) {
                    parseEndElement_NextFunc = ParseEndElementParseFunction.ReadData;
                    return AsyncHelper.DoneTask;
                }
                else {
                    ThrowUnexpectedToken(pos, ">");
                }

                Debug.Assert(false, "We should never get to this point.");
            }

            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;

            parseEndElement_NextFunc = ParseEndElementParseFunction.Done;
            return AsyncHelper.DoneTask;
        }