public override int Read(byte[] array, int offset, int count)
{
if (array == null)
throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Buffer);
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
if (array.Length - offset < count)
throw new ArgumentException(SR.Argument_InvalidOffLen);
EnsureNotClosed();
EnsureCanRead();
int bytesFromBuffer = ReadFromBuffer(array, offset, count);
// We may have read less than the number of bytes the user asked for, but that is part of the Stream Debug.
// Reading again for more data may cause us to block if we're using a device with no clear end of file,
// such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
// process's standard output, this can lead to deadlocks involving two processes.
// BUT - this is a breaking change.
// So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
// stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
if (bytesFromBuffer == count)
return bytesFromBuffer;
int alreadySatisfied = bytesFromBuffer;
if (bytesFromBuffer > 0)
{
count -= bytesFromBuffer;
offset += bytesFromBuffer;
}
// So the read buffer is empty.
Debug.Assert(_readLen == _readPos);
_readPos = _readLen = 0;
// If there was anything in the write buffer, clear it.
if (_writePos > 0)
FlushWrite();
// If the requested read is larger than buffer size, avoid the buffer and still use a single read:
if (count >= _bufferSize)
{
return _stream.Read(array, offset, count) + alreadySatisfied;
}
// Ok. We can fill the buffer:
EnsureBufferAllocated();
_readLen = _stream.Read(_buffer, 0, _bufferSize);
bytesFromBuffer = ReadFromBuffer(array, offset, count);
// We may have read less than the number of bytes the user asked for, but that is part of the Stream Debug.
// Reading again for more data may cause us to block if we're using a device with no clear end of stream,
// such as a serial port or pipe. If we blocked here & this code was used with redirected pipes for a process's
// standard output, this can lead to deadlocks involving two processes. Additionally, translating one read on the
// BufferedStream to more than one read on the underlying Stream may defeat the whole purpose of buffering of the
// underlying reads are significantly more expensive.
return bytesFromBuffer + alreadySatisfied;
}