void EnsureBufferSize(int reqSize, bool copyContents, int copyOffset)
{
byte[] newBuf = _data;
if (reqSize > _data.Length)
{
if (reqSize > _maxSize)
{
if (_wrapper.Source.CanSeek || reqSize - _discardCount <= _maxSize)
{
// lose some of the earlier data...
var ofs = reqSize - _maxSize;
copyOffset += ofs;
reqSize = _maxSize;
}
else
{
throw new InvalidOperationException("Not enough room in the buffer! Increase the maximum size and try again.");
}
}
else
{
// find the new size
var size = _data.Length;
while (size < reqSize)
{
size *= 2;
}
reqSize = size;
}
// if we discarded some bytes above, don't resize the buffer unless we have to...
if (reqSize > _data.Length)
{
newBuf = new byte[reqSize];
}
}
if (copyContents)
{
// adjust the position of the data
if ((copyOffset > 0 && copyOffset < _end) || (copyOffset == 0 && newBuf != _data))
{
// copy forward
Buffer.BlockCopy(_data, copyOffset, newBuf, 0, _end - copyOffset);
// adjust our discard count
if ((_discardCount -= copyOffset) < 0) _discardCount = 0;
}
else if (copyOffset < 0 && -copyOffset < _end)
{
// copy backward
// be clever... if we're moving to a new buffer or the ranges don't overlap, just use a block copy
if (newBuf != _data || _end <= -copyOffset)
{
Buffer.BlockCopy(_data, 0, newBuf, -copyOffset, Math.Max(_end, Math.Min(_end, _data.Length + copyOffset)));
}
else
{
// this shouldn't happen often, so we can get away with a full buffer refill
_end = copyOffset;
}
// adjust our discard count
_discardCount = 0;
}
else
{
_end = copyOffset;
_discardCount = 0;
}
// adjust our markers
_baseOffset += copyOffset;
_end -= copyOffset;
if (_end > newBuf.Length) _end = newBuf.Length;
}
else
{
_discardCount = 0;
// we can't set _baseOffset since our caller hasn't told us what it should be...
_end = 0;
}
_data = newBuf;
}