public override int ReadValueChunk(char[] buffer, int index, int count)
{
// throw on elements
if (!XmlReader.HasValueInternal(_curNode.type))
{
throw new InvalidOperationException(SR.Format(SR.Xml_InvalidReadValueChunk, _curNode.type));
}
// check arguments
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
if (buffer.Length - index < count)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
// first call of ReadValueChunk -> initialize incremental read state
if (_parsingFunction != ParsingFunction.InReadValueChunk)
{
if (_readState != ReadState.Interactive)
{
return 0;
}
if (_parsingFunction == ParsingFunction.PartialTextValue)
{
_incReadState = IncrementalReadState.ReadValueChunk_OnPartialValue;
}
else
{
_incReadState = IncrementalReadState.ReadValueChunk_OnCachedValue;
_nextNextParsingFunction = _nextParsingFunction;
_nextParsingFunction = _parsingFunction;
}
_parsingFunction = ParsingFunction.InReadValueChunk;
_readValueOffset = 0;
}
if (count == 0)
{
return 0;
}
// read what is already cached in curNode
int readCount = 0;
int read = _curNode.CopyTo(_readValueOffset, buffer, index + readCount, count - readCount);
readCount += read;
_readValueOffset += read;
if (readCount == count)
{
// take care of surrogate pairs spanning between buffers
char ch = buffer[index + count - 1];
if (XmlCharType.IsHighSurrogate(ch))
{
readCount--;
_readValueOffset--;
if (readCount == 0)
{
Throw(SR.Xml_NotEnoughSpaceForSurrogatePair);
}
}
return readCount;
}
// if on partial value, read the rest of it
if (_incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue)
{
_curNode.SetValue(string.Empty);
// read next chunk of text
bool endOfValue = false;
int startPos = 0;
int endPos = 0;
while (readCount < count && !endOfValue)
{
int orChars = 0;
endOfValue = ParseText(out startPos, out endPos, ref orChars);
int copyCount = count - readCount;
if (copyCount > endPos - startPos)
{
copyCount = endPos - startPos;
}
BlockCopyChars(_ps.chars, startPos, buffer, (index + readCount), copyCount);
readCount += copyCount;
startPos += copyCount;
}
_incReadState = endOfValue ? IncrementalReadState.ReadValueChunk_OnCachedValue : IncrementalReadState.ReadValueChunk_OnPartialValue;
if (readCount == count)
{
char ch = buffer[index + count - 1];
if (XmlCharType.IsHighSurrogate(ch))
{
readCount--;
startPos--;
if (readCount == 0)
{
Throw(SR.Xml_NotEnoughSpaceForSurrogatePair);
}
}
}
_readValueOffset = 0;
_curNode.SetValue(_ps.chars, startPos, endPos - startPos);
}
return readCount;
}