示例#1
0
        /// <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);
        }
示例#2
0
        /// <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;
            }
        }
示例#3
0
 /// <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) }));
 }