/// <summary> /// Reads data from the stream. /// </summary> /// <param name="buffer">The buffer to fill</param> /// <param name="offset">The buffer offset to start from</param> /// <param name="count">The number of bytes to read</param> /// <returns>The number of bytes read</returns> public override int Read(byte[] buffer, int offset, int count) { int numRead; if (_diffStream == null) { _baseStream.Position = _position; numRead = _baseStream.Read(buffer, offset, count); } else { if (_position > _diffStream.Length) { throw new IOException("Attempt to read beyond end of file"); } int toRead = (int)Math.Min(count, _diffStream.Length - _position); // If the read is within the base stream's range, then touch it first to get the // (potentially) stale data. if (_position < _baseStream.Length) { int baseToRead = (int)Math.Min(toRead, _baseStream.Length - _position); _baseStream.Position = _position; int totalBaseRead = 0; while (totalBaseRead < baseToRead) { totalBaseRead += _baseStream.Read(buffer, offset + totalBaseRead, baseToRead - totalBaseRead); } } // Now overlay any data from the overlay stream (if any) IEnumerable <StreamExtent> overlayExtents = StreamExtent.Intersect(_diffExtents, new StreamExtent(_position, toRead)); foreach (var extent in overlayExtents) { _diffStream.Position = extent.Start; int overlayNumRead = 0; while (overlayNumRead < extent.Length) { overlayNumRead += _diffStream.Read( buffer, (int)(offset + (extent.Start - _position) + overlayNumRead), (int)(extent.Length - overlayNumRead)); } } numRead = toRead; } _position += numRead; return(numRead); }
/// <summary> /// Gets the parts of a stream that are stored, within a specified range. /// </summary> /// <param name="start">The offset of the first byte of interest</param> /// <param name="count">The number of bytes of interest</param> /// <returns>An enumeration of stream extents, indicating stored bytes</returns> public virtual IEnumerable <StreamExtent> GetExtentsInRange(long start, long count) { return(StreamExtent.Intersect(Extents, new StreamExtent[] { new StreamExtent(start, count) })); }