public override int Read(byte[] buffer, int offset, int count) { if (_position >= _length) { return(0); } int totalRead = 0; while (totalRead < count && _position < _length) { // If current region is outside the area of interest, clean it up if (_currentExtent != null && (_position < _currentExtent.Start || _position >= _currentExtent.Start + _currentExtent.Length)) { _currentExtent.DisposeReadState(); _currentExtent = null; } // If we need to find a new region, look for it if (_currentExtent == null) { int idx = _extents.BinarySearch(new SearchExtent(_position), new ExtentRangeComparer()); if (idx >= 0) { BuilderExtent extent = _extents[idx]; extent.PrepareForRead(); _currentExtent = extent; } } int numRead = 0; // If the block is outside any known extent, defer to base stream. if (_currentExtent == null) { _baseStream.Position = _position; BuilderExtent nextExtent = FindNext(_position); if (nextExtent != null) { numRead = _baseStream.Read(buffer, offset + totalRead, (int)Math.Min(count - totalRead, nextExtent.Start - _position)); } else { numRead = _baseStream.Read(buffer, offset + totalRead, count - totalRead); } } else { numRead = _currentExtent.Read(_position, buffer, offset + totalRead, count - totalRead); } _position += numRead; totalRead += numRead; } return(totalRead); }
protected override void Dispose(bool disposing) { try { if (disposing) { if (_currentExtent != null) { _currentExtent.DisposeReadState(); _currentExtent = null; } if (_baseStream != null) { _baseStream.Dispose(); _baseStream = null; } } } finally { base.Dispose(disposing); } }