private void ReadPartialUnicodeText(bool withEndElement, int length)
{
// The maxBytesPerRead includes the quota for the XmlBinaryNodeType.TextNode, so we need
// to account for that.
const int maxTextNodeLength = 5;
int maxLength = Math.Max(_maxBytesPerRead - maxTextNodeLength, 0);
if (length <= maxLength)
{
if (withEndElement)
ReadText(MoveToAtomicTextWithEndElement(), ValueHandleType.Unicode, length);
else
ReadText(MoveToComplexText(), ValueHandleType.Unicode, length);
}
else
{
// We also need to make sure we have enough room to insert a new XmlBinaryNodeType.TextNode
// for the split data.
int actual = Math.Max(maxLength - maxTextNodeLength, 0);
// Make sure we break on a char boundary
if ((actual & 1) != 0)
actual--;
int offset = BufferReader.ReadBytes(actual);
// We need to make sure we don't split a Unicode surrogate character
int byteCount = 0;
char ch = (char)BufferReader.GetInt16(offset + actual - sizeof(char));
// If the last char is a high surrogate char, then move back
if (ch >= 0xD800 && ch < 0xDC00)
byteCount = sizeof(char);
// Include the split characters in the count
BufferReader.Offset = BufferReader.Offset - byteCount;
actual -= byteCount;
MoveToComplexText().Value.SetValue(ValueHandleType.Unicode, offset, actual);
if (this.OutsideRootElement)
VerifyWhitespace();
XmlBinaryNodeType nodeType = (withEndElement ? XmlBinaryNodeType.UnicodeChars32TextWithEndElement : XmlBinaryNodeType.UnicodeChars32Text);
InsertNode(nodeType, length - actual);
}
}