private bool ParseDocumentContent()
{
bool mangoQuirks = false;
#if FEATURE_LEGACYNETCF
// In Mango the default XmlTextReader is instantiated
// with v1Compat flag set to true. One of the effects
// of this settings is to eat any trailing nulls in the
// buffer and some apps depend on this behavior.
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
mangoQuirks = true;
#endif
for (; ;)
{
bool needMoreChars = false;
int pos = _ps.charPos;
char[] chars = _ps.chars;
// some tag
if (chars[pos] == '<')
{
needMoreChars = true;
if (_ps.charsUsed - pos < 4) // minimum "<a/>"
goto ReadData;
pos++;
switch (chars[pos])
{
// processing instruction
case '?':
_ps.charPos = pos + 1;
if (ParsePI())
{
return true;
}
continue;
case '!':
pos++;
if (_ps.charsUsed - pos < 2) // minimum characters expected "--"
goto ReadData;
// comment
if (chars[pos] == '-')
{
if (chars[pos + 1] == '-')
{
_ps.charPos = pos + 2;
if (ParseComment())
{
return true;
}
continue;
}
else
{
ThrowUnexpectedToken(pos + 1, "-");
}
}
// CDATA section
else if (chars[pos] == '[')
{
if (_fragmentType != XmlNodeType.Document)
{
pos++;
if (_ps.charsUsed - pos < 6)
{
goto ReadData;
}
if (XmlConvert.StrEqual(chars, pos, 6, "CDATA["))
{
_ps.charPos = pos + 6;
ParseCData();
if (_fragmentType == XmlNodeType.None)
{
_fragmentType = XmlNodeType.Element;
}
return true;
}
else
{
ThrowUnexpectedToken(pos, "CDATA[");
}
}
else
{
Throw(_ps.charPos, SR.Xml_InvalidRootData);
}
}
// DOCTYPE declaration
else
{
if (_fragmentType == XmlNodeType.Document || _fragmentType == XmlNodeType.None)
{
_fragmentType = XmlNodeType.Document;
_ps.charPos = pos;
if (ParseDoctypeDecl())
{
return true;
}
continue;
}
else
{
if (ParseUnexpectedToken(pos) == "DOCTYPE")
{
Throw(SR.Xml_BadDTDLocation);
}
else
{
ThrowUnexpectedToken(pos, "<!--", "<[CDATA[");
}
}
}
break;
case '/':
Throw(pos + 1, SR.Xml_UnexpectedEndTag);
break;
// document element start tag
default:
if (_rootElementParsed)
{
if (_fragmentType == XmlNodeType.Document)
{
Throw(pos, SR.Xml_MultipleRoots);
}
if (_fragmentType == XmlNodeType.None)
{
_fragmentType = XmlNodeType.Element;
}
}
_ps.charPos = pos;
_rootElementParsed = true;
ParseElement();
return true;
}
}
else if (chars[pos] == '&')
{
if (_fragmentType == XmlNodeType.Document)
{
Throw(pos, SR.Xml_InvalidRootData);
}
else
{
if (_fragmentType == XmlNodeType.None)
{
_fragmentType = XmlNodeType.Element;
}
int i;
switch (HandleEntityReference(false, EntityExpandType.OnlyGeneral, out i))
{
case EntityType.Unexpanded:
if (_parsingFunction == ParsingFunction.EntityReference)
{
_parsingFunction = _nextParsingFunction;
}
ParseEntityReference();
return true;
case EntityType.CharacterDec:
case EntityType.CharacterHex:
case EntityType.CharacterNamed:
if (ParseText())
{
return true;
}
continue;
default:
chars = _ps.chars;
pos = _ps.charPos;
continue;
}
}
}
// end of buffer
else if (pos == _ps.charsUsed || ((_v1Compat || mangoQuirks) && chars[pos] == 0x0))
{
goto ReadData;
}
// something else -> root level whitespaces
else
{
if (_fragmentType == XmlNodeType.Document)
{
if (ParseRootLevelWhitespace())
{
return true;
}
}
else
{
if (ParseText())
{
if (_fragmentType == XmlNodeType.None && _curNode.type == XmlNodeType.Text)
{
_fragmentType = XmlNodeType.Element;
}
return true;
}
}
continue;
}
Debug.Assert(pos == _ps.charsUsed && !_ps.isEof);
ReadData:
// read new characters into the buffer
if (ReadData() != 0)
{
pos = _ps.charPos;
}
else
{
if (needMoreChars)
{
Throw(SR.Xml_InvalidRootData);
}
if (InEntity)
{
if (HandleEntityEnd(true))
{
SetupEndEntityNodeInContent();
return true;
}
continue;
}
Debug.Assert(_index == 0);
if (!_rootElementParsed && _fragmentType == XmlNodeType.Document)
{
ThrowWithoutLineInfo(SR.Xml_MissingRoot);
}
if (_fragmentType == XmlNodeType.None)
{
_fragmentType = _rootElementParsed ? XmlNodeType.Document : XmlNodeType.Element;
}
OnEof();
return false;
}
pos = _ps.charPos;
chars = _ps.chars;
}
}