/// <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 (StreamExtent 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); }
public void TestIntersect1() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(4, 8) }; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2)); }
public void TestUnion4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4), new StreamExtent(4, 4) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0, 8) }; Compare(r, StreamExtent.Union(s1)); }
public void TestUnion3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(2, 8) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(0, 10) }; Compare(r, StreamExtent.Union(s1, s2)); }
public void TestIntersect5() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 10) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 5) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3, 5) }; Compare(r, StreamExtent.Intersect(s1, s2)); }
public void TestIntersect4() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 8) }; StreamExtent[] s3 = new StreamExtent[] { new StreamExtent(10, 10) }; StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Intersect(s1, s2, s3)); }
public void TestIntersect3() { StreamExtent[] s1 = new StreamExtent[] { new StreamExtent(0, 4), new StreamExtent(10, 10) }; StreamExtent[] s2 = new StreamExtent[] { new StreamExtent(3, 8) }; StreamExtent[] r = new StreamExtent[] { new StreamExtent(3, 1), new StreamExtent(10, 1) }; Compare(r, StreamExtent.Intersect(s1, s2)); }
/// <summary> /// Writes data to the stream at the current location. /// </summary> /// <param name="buffer">The data to write</param> /// <param name="offset">The first byte to write from buffer</param> /// <param name="count">The number of bytes to write</param> public override void Write(byte[] buffer, int offset, int count) { CheckFrozen(); if (_diffStream != null) { _diffStream.Position = _position; _diffStream.Write(buffer, offset, count); // Beware of Linq's delayed model - force execution now by placing into a list. // Without this, large execution chains can build up (v. slow) and potential for stack overflow. _diffExtents = new List <StreamExtent>(StreamExtent.Union(_diffExtents, new StreamExtent(_position, count))); _position += count; } else { _baseStream.Position = _position; _baseStream.Write(buffer, offset, count); _position += count; } }
public void TestBlocks() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(11, 4) }; List <Range <long, long> > ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.AreEqual(1, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(9, 8) }; ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.AreEqual(1, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(2, ranges[0].Count); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; ranges = new List <Range <long, long> >(StreamExtent.Blocks(s, 10)); Assert.AreEqual(2, ranges.Count); Assert.AreEqual(0, ranges[0].Offset); Assert.AreEqual(3, ranges[0].Count); Assert.AreEqual(4, ranges[1].Offset); Assert.AreEqual(1, ranges[1].Count); }
public void TestBlockCount() { StreamExtent[] s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(11, 4) }; Assert.AreEqual(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(0, 8), new StreamExtent(9, 8) }; Assert.AreEqual(2, StreamExtent.BlockCount(s, 10)); s = new StreamExtent[] { new StreamExtent(3, 4), new StreamExtent(19, 4), new StreamExtent(44, 4) }; Assert.AreEqual(4, StreamExtent.BlockCount(s, 10)); }
/// <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[] { new StreamExtent(start, count) })); }
public void TestUnion5() { StreamExtent[] r = new StreamExtent[] { }; Compare(r, StreamExtent.Union()); }