Beispiel #1
0
        /// <summary>
        /// Reads an attribute value and returns it.
        /// </summary>
        private string _readAttributeValue()
        {
            char quote = m_str[m_pos];

            if (quote != '"' && quote != '\'')
            {
                throw _error(ErrorCode.XML_PARSER_ELEMENT_MALFORMED);
            }

            m_pos++;

            ReadOnlySpan <char> span        = m_str.AsSpan(m_pos);
            int  charsLeft                  = m_str.Length - m_pos;
            char newline                    = s_newLineChar;
            ReadOnlySpan <char> searchChars = stackalloc char[] { quote, '&', '<', newline };

            bool mayHaveEntities = false;

            while (true)
            {
                int index = span.IndexOfAny(searchChars);
                if (index == -1)
                {
                    throw _error(ErrorCode.XML_PARSER_UNTERMINATED_ATTR);
                }

                char charAtIndex = span[index];
                if (charAtIndex == quote)
                {
                    span = span.Slice(index);
                    break;
                }
                else if (charAtIndex == '&')
                {
                    span            = span.Slice(index);
                    mayHaveEntities = true;
                    break;
                }
                else if (charAtIndex == newline)
                {
                    m_curLine++;
                    span = span.Slice(index + 1);
                }
                else
                {
                    // Attributes cannot contain '<'.
                    throw _error(ErrorCode.XML_PARSER_ELEMENT_MALFORMED);
                }
            }

            int charsRead = charsLeft - span.Length;

            if (!mayHaveEntities)
            {
                int startPos = m_pos;
                m_pos += charsRead + 1;     // +1 for the closing quote
                return(m_str.Substring(startPos, charsRead));
            }

            char[] textBuffer = m_buffer;

            if (textBuffer.Length < charsRead)
            {
                DataStructureUtil.resizeArray(ref textBuffer, textBuffer.Length, charsRead);
            }

            m_str.CopyTo(m_pos, textBuffer, 0, charsRead);
            m_pos += charsRead;
            int textBufPos = charsRead;

            while (true)
            {
                char ch = m_str[m_pos];
                if (ch == '&')
                {
                    int entityCode = _readEntity();
                    _writeCodePoint(ref textBuffer, ref textBufPos, entityCode);
                }
                else if (ch == quote)
                {
                    break;
                }
                else if (ch == '<')
                {
                    throw _error(ErrorCode.XML_PARSER_ELEMENT_MALFORMED);
                }
                else if (ch == newline)
                {
                    m_curLine++;
                    m_pos++;
                }

                span = m_str.AsSpan(m_pos);
                int nextIndex = span.IndexOfAny(searchChars);

                if (nextIndex == -1)
                {
                    throw _error(ErrorCode.XML_PARSER_UNTERMINATED_ATTR);
                }

                if (textBuffer.Length - textBufPos < nextIndex)
                {
                    DataStructureUtil.resizeArray(ref textBuffer, textBufPos, textBufPos + nextIndex);
                }

                span.Slice(0, nextIndex).CopyTo(textBuffer.AsSpan(textBufPos));
                textBufPos += nextIndex;

                m_pos += nextIndex;
            }

            m_pos++;    // For closing quote
            m_buffer = textBuffer;

            return((textBufPos == 0) ? "" : new string(textBuffer, 0, textBufPos));
        }
Beispiel #2
0
        /// <summary>
        /// Reads a text node and adds it as a child to the element currently being processed.
        /// </summary>
        private void _readText()
        {
            ReadOnlySpan <char> span        = m_str.AsSpan(m_pos);
            int  charsLeft                  = m_str.Length - m_pos;
            char newline                    = s_newLineChar;
            ReadOnlySpan <char> searchChars = stackalloc char[3] {
                '<', '&', newline
            };

            bool mayHaveEntities = false;

            while (!span.IsEmpty)
            {
                int  index       = span.IndexOfAny(searchChars);
                char charAtIndex = (index == -1) ? '\0' : span[index];

                if (charAtIndex == '<')
                {
                    span = span.Slice(index);
                    break;
                }
                else if (charAtIndex == '&')
                {
                    span            = span.Slice(index);
                    mayHaveEntities = true;
                    break;
                }
                else if (charAtIndex == newline)
                {
                    m_curLine++;
                    span = span.Slice(index + 1);
                }
                else
                {
                    span = default;
                }
            }

            int    charsRead = charsLeft - span.Length;
            string text;

            if (!mayHaveEntities)
            {
                text = ((m_parserFlags & FLAG_IGNORE_SPACE) != 0)
                    ? XMLHelper.stripWhitespace(m_str, m_pos, charsRead)
                    : m_str.Substring(m_pos, charsRead);

                if (text.Length != 0)
                {
                    m_nodeStack.add(ASXML.createTextNode(text));
                }

                m_pos += charsRead;
                return;
            }

            char[] textBuffer = m_buffer;
            if (charsRead > textBuffer.Length)
            {
                DataStructureUtil.resizeArray(ref textBuffer, textBuffer.Length, charsRead);
            }

            m_str.CopyTo(m_pos, textBuffer, 0, charsRead);
            int textBufPos = charsRead;

            m_pos += charsRead;

            while (true)
            {
                char ch = m_str[m_pos];
                if (ch == '&')
                {
                    int entityCode = _readEntity();
                    _writeCodePoint(ref textBuffer, ref textBufPos, entityCode);
                }
                else if (ch == '<')
                {
                    break;
                }
                else if (ch == newline)
                {
                    m_curLine++;
                    m_pos++;
                }

                span = m_str.AsSpan(m_pos);
                int nextIndex   = span.IndexOfAny(searchChars);
                int charsToCopy = (nextIndex == -1) ? span.Length : nextIndex;

                if (textBuffer.Length - textBufPos < charsToCopy)
                {
                    DataStructureUtil.resizeArray(ref textBuffer, textBufPos, textBufPos + charsToCopy);
                }

                span.Slice(0, charsToCopy).CopyTo(textBuffer.AsSpan(textBufPos));
                textBufPos += charsToCopy;
                m_pos      += charsToCopy;

                if (nextIndex == -1)
                {
                    break;
                }
            }

            m_buffer = textBuffer;

            if (textBufPos == 0)
            {
                return;
            }

            text = ((m_parserFlags & FLAG_IGNORE_SPACE) != 0)
                ? XMLHelper.stripWhitespace(textBuffer, 0, textBufPos)
                : new string(textBuffer, 0, textBufPos);

            if (text.Length != 0)
            {
                m_nodeStack.add(ASXML.createTextNode(text));
            }
        }