protected string ReadTextBuffer(int length)
{
if (length == 0) return string.Empty;
string peek = readBuffers.Peek().AsText(_ctx.StringEncoding);
if (peek == null) throw new InvalidOperationException(ErrResources.buffers_must_not_be_empty);
Debug.Assert(peek.Length >= readPosition);
if (peek.Length - readPosition >= length)
{
// Great! We can just take a substring.
string res = peek.Substring(readPosition, length);
readPosition += length;
if (peek.Length == readPosition)
{
// We just consumed the entire string. Dequeue it.
DropReadBuffer();
}
return res;
}
else
{
// Start building the string from the remainder in the buffer.
var sb = new StringBuilder(peek, readPosition, peek.Length - readPosition, length);
length -= peek.Length - readPosition;
// We just consumed the entire string. Dequeue it.
DropReadBuffer();
while (length > 0)
{
peek = readBuffers.Peek().AsText(_ctx.StringEncoding);
if (peek == null) throw new InvalidOperationException(ErrResources.too_little_data_buffered);
if (peek.Length > length)
{
// This string is long enough. It is the last one.
sb.Append(peek, 0, length);
readPosition = length;
length = 0;
break;
}
else
{
// Append just another whole buffer to the StringBuilder.
sb.Append(peek);
length -= peek.Length;
DropReadBuffer();
// When this is the last buffer (it's probably an EOF), return.
if (readBuffers.Count == 0)
break;
}
} // while
Debug.Assert(sb.Length > 0);
return sb.ToString();
} // else
}