private bool ParseText()
{
int startPos;
int endPos;
int orChars = 0;
// skip over the text if not in full parsing mode
if (_parsingMode != ParsingMode.Full)
{
while (!ParseText(out startPos, out endPos, ref orChars)) ;
goto IgnoredNode;
}
_curNode.SetLineInfo(_ps.LineNo, _ps.LinePos);
Debug.Assert(_stringBuilder.Length == 0);
// the whole value is in buffer
if (ParseText(out startPos, out endPos, ref orChars))
{
if (endPos - startPos == 0)
{
goto IgnoredNode;
}
XmlNodeType nodeType = GetTextNodeType(orChars);
if (nodeType == XmlNodeType.None)
{
goto IgnoredNode;
}
Debug.Assert(endPos - startPos > 0);
_curNode.SetValueNode(nodeType, _ps.chars, startPos, endPos - startPos);
return true;
}
// only piece of the value was returned
else
{
// V1 compatibility mode -> cache the whole value
if (_v1Compat)
{
do
{
if (endPos - startPos > 0)
{
_stringBuilder.Append(_ps.chars, startPos, endPos - startPos);
}
} while (!ParseText(out startPos, out endPos, ref orChars));
if (endPos - startPos > 0)
{
_stringBuilder.Append(_ps.chars, startPos, endPos - startPos);
}
Debug.Assert(_stringBuilder.Length > 0);
XmlNodeType nodeType = GetTextNodeType(orChars);
if (nodeType == XmlNodeType.None)
{
_stringBuilder.Length = 0;
goto IgnoredNode;
}
_curNode.SetValueNode(nodeType, _stringBuilder.ToString());
_stringBuilder.Length = 0;
return true;
}
// V2 reader -> do not cache the whole value yet, read only up to 4kB to decide whether the value is a whitespace
else
{
bool fullValue = false;
// if it's a partial text value, not a whitespace -> return
if (orChars > 0x20)
{
Debug.Assert(endPos - startPos > 0);
_curNode.SetValueNode(XmlNodeType.Text, _ps.chars, startPos, endPos - startPos);
_nextParsingFunction = _parsingFunction;
_parsingFunction = ParsingFunction.PartialTextValue;
return true;
}
// partial whitespace -> read more data (up to 4kB) to decide if it is a whitespace or a text node
if (endPos - startPos > 0)
{
_stringBuilder.Append(_ps.chars, startPos, endPos - startPos);
}
do
{
fullValue = ParseText(out startPos, out endPos, ref orChars);
if (endPos - startPos > 0)
{
_stringBuilder.Append(_ps.chars, startPos, endPos - startPos);
}
} while (!fullValue && orChars <= 0x20 && _stringBuilder.Length < MinWhitespaceLookahedCount);
// determine the value node type
XmlNodeType nodeType = (_stringBuilder.Length < MinWhitespaceLookahedCount) ? GetTextNodeType(orChars) : XmlNodeType.Text;
if (nodeType == XmlNodeType.None)
{
// ignored whitespace -> skip over the rest of the value unless we already read it all
_stringBuilder.Length = 0;
if (!fullValue)
{
while (!ParseText(out startPos, out endPos, ref orChars)) ;
}
goto IgnoredNode;
}
// set value to curNode
_curNode.SetValueNode(nodeType, _stringBuilder.ToString());
_stringBuilder.Length = 0;
// change parsing state if the full value was not parsed
if (!fullValue)
{
_nextParsingFunction = _parsingFunction;
_parsingFunction = ParsingFunction.PartialTextValue;
}
return true;
}
}
IgnoredNode:
// ignored whitespace at the end of manually resolved entity
if (_parsingFunction == ParsingFunction.ReportEndEntity)
{
SetupEndEntityNodeInContent();
_parsingFunction = _nextParsingFunction;
return true;
}
else if (_parsingFunction == ParsingFunction.EntityReference)
{
_parsingFunction = _nextNextParsingFunction;
ParseEntityReference();
return true;
}
return false;
}