private bool ParsePIValue(out int outStartPos, out int outEndPos)
{
// read new characters into the buffer
if (_ps.charsUsed - _ps.charPos < 2)
{
if (ReadData() == 0)
{
Throw(_ps.charsUsed, SR.Xml_UnexpectedEOF, "PI");
}
}
int pos = _ps.charPos;
char[] chars = _ps.chars;
int rcount = 0;
int rpos = -1;
for (;;)
{
char tmpch;
unsafe
{
while (_xmlCharType.IsTextChar(tmpch = chars[pos]) && tmpch != '?')
{
pos++;
}
}
switch (chars[pos])
{
// possibly end of PI
case '?':
if (chars[pos + 1] == '>')
{
if (rcount > 0)
{
Debug.Assert(!_ps.eolNormalized);
ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
outEndPos = pos - rcount;
}
else
{
outEndPos = pos;
}
outStartPos = _ps.charPos;
_ps.charPos = pos + 2;
return true;
}
else if (pos + 1 == _ps.charsUsed)
{
goto ReturnPartial;
}
else
{
pos++;
continue;
}
// eol
case (char)0xA:
pos++;
OnNewLine(pos);
continue;
case (char)0xD:
if (chars[pos + 1] == (char)0xA)
{
if (!_ps.eolNormalized && _parsingMode == ParsingMode.Full)
{
// EOL normalization of 0xD 0xA
if (pos - _ps.charPos > 0)
{
if (rcount == 0)
{
rcount = 1;
rpos = pos;
}
else
{
ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
rpos = pos - rcount;
rcount++;
}
}
else
{
_ps.charPos++;
}
}
pos += 2;
}
else if (pos + 1 < _ps.charsUsed || _ps.isEof)
{
if (!_ps.eolNormalized)
{
chars[pos] = (char)0xA; // EOL normalization of 0xD
}
pos++;
}
else
{
goto ReturnPartial;
}
OnNewLine(pos);
continue;
case '<':
case '&':
case ']':
case (char)0x9:
pos++;
continue;
default:
// end of buffer
if (pos == _ps.charsUsed)
{
goto ReturnPartial;
}
// surrogate characters
else
{
char ch = chars[pos];
if (XmlCharType.IsHighSurrogate(ch))
{
if (pos + 1 == _ps.charsUsed)
{
goto ReturnPartial;
}
pos++;
if (XmlCharType.IsLowSurrogate(chars[pos]))
{
pos++;
continue;
}
}
ThrowInvalidChar(chars, _ps.charsUsed, pos);
break;
}
}
}
ReturnPartial:
if (rcount > 0)
{
ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
outEndPos = pos - rcount;
}
else
{
outEndPos = pos;
}
outStartPos = _ps.charPos;
_ps.charPos = pos;
return false;
}