private int ReadContentAsBinary(byte[] buffer, int index, int count)
{
Debug.Assert(_incReadDecoder != null);
if (_incReadState == IncrementalReadState.ReadContentAsBinary_End)
{
return 0;
}
_incReadDecoder.SetNextOutputBuffer(buffer, index, count);
for (; ;)
{
// read what is already cached in curNode
int charsRead = 0;
try
{
charsRead = _curNode.CopyToBinary(_incReadDecoder, _readValueOffset);
}
// add line info to the exception
catch (XmlException e)
{
_curNode.AdjustLineInfo(_readValueOffset, _ps.eolNormalized, ref _incReadLineInfo);
ReThrow(e, _incReadLineInfo.lineNo, _incReadLineInfo.linePos);
}
_readValueOffset += charsRead;
if (_incReadDecoder.IsFull)
{
return _incReadDecoder.DecodedCount;
}
// if on partial value, read the rest of it
if (_incReadState == IncrementalReadState.ReadContentAsBinary_OnPartialValue)
{
_curNode.SetValue(string.Empty);
// read next chunk of text
bool endOfValue = false;
int startPos = 0;
int endPos = 0;
while (!_incReadDecoder.IsFull && !endOfValue)
{
int orChars = 0;
// store current line info and parse more text
_incReadLineInfo.Set(_ps.LineNo, _ps.LinePos);
endOfValue = ParseText(out startPos, out endPos, ref orChars);
try
{
charsRead = _incReadDecoder.Decode(_ps.chars, startPos, endPos - startPos);
}
// add line info to the exception
catch (XmlException e)
{
ReThrow(e, _incReadLineInfo.lineNo, _incReadLineInfo.linePos);
}
startPos += charsRead;
}
_incReadState = endOfValue ? IncrementalReadState.ReadContentAsBinary_OnCachedValue : IncrementalReadState.ReadContentAsBinary_OnPartialValue;
_readValueOffset = 0;
if (_incReadDecoder.IsFull)
{
_curNode.SetValue(_ps.chars, startPos, endPos - startPos);
// adjust line info for the chunk that has been already decoded
AdjustLineInfo(_ps.chars, startPos - charsRead, startPos, _ps.eolNormalized, ref _incReadLineInfo);
_curNode.SetLineInfo(_incReadLineInfo.lineNo, _incReadLineInfo.linePos);
return _incReadDecoder.DecodedCount;
}
}
// reset to normal state so we can call Read() to move forward
ParsingFunction tmp = _parsingFunction;
_parsingFunction = _nextParsingFunction;
_nextParsingFunction = _nextNextParsingFunction;
// move to next textual node in the element content; throw on sub elements
if (!MoveToNextContentNode(true))
{
SetupReadContentAsBinaryState(tmp);
_incReadState = IncrementalReadState.ReadContentAsBinary_End;
return _incReadDecoder.DecodedCount;
}
SetupReadContentAsBinaryState(tmp);
_incReadLineInfo.Set(_curNode.LineNo, _curNode.LinePos);
}
}