sdk/Common/Internal/PartialWrapperStream.cs (126 lines of code) (raw):

/* * Copyright (C) Alibaba Cloud Computing * All rights reserved. * */ using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; namespace Aliyun.OSS.Common.Internal { /// <summary> /// This class is used to wrap a stream for a particular segment of a stream. It /// makes that segment look like you are reading from beginning to end of the stream. /// </summary> public class PartialWrapperStream : WrapperStream { private long initialPosition; private long partSize; public PartialWrapperStream(Stream stream, long partSize) : base(stream) { if (!stream.CanSeek) throw new InvalidOperationException("Base stream of PartialWrapperStream must be seekable"); this.initialPosition = stream.Position; long remainingData = stream.Length - stream.Position; if (partSize == 0 || remainingData < partSize) { this.partSize = remainingData; } else { this.partSize = partSize; } } private long RemainingPartSize { get { long remaining = this.partSize - this.Position; return remaining; } } #region Stream overrides public override long Length { get { long length = base.Length - this.initialPosition; if (length > this.partSize) { length = this.partSize; } return length; } } public override long Position { get { return base.Position - this.initialPosition; } set { base.Position = this.initialPosition + value; } } public override int Read(byte[] buffer, int offset, int count) { int bytesToRead = count < this.RemainingPartSize ? count : (int)this.RemainingPartSize; if (bytesToRead < 0) return 0; return base.Read(buffer, offset, bytesToRead); } public override long Seek(long offset, SeekOrigin origin) { long position = 0; switch (origin) { case SeekOrigin.Begin: position = this.initialPosition + offset; break; case SeekOrigin.Current: position = base.Position + offset; break; case SeekOrigin.End: position = base.Position + this.partSize + offset; break; } if (position < this.initialPosition) { position = this.initialPosition; } else if (position > this.initialPosition + this.partSize) { position = this.initialPosition + this.partSize; } base.Position = position; return this.Position; } public override void SetLength(long value) { throw new NotSupportedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } public override void WriteByte(byte value) { throw new NotSupportedException(); } #if !PCL && !UNITY && !CORECLR public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { throw new NotSupportedException(); } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { throw new NotSupportedException(); } public override int EndRead(IAsyncResult asyncResult) { throw new NotImplementedException(); } public override void EndWrite(IAsyncResult asyncResult) { throw new NotImplementedException(); } #endif #endregion } }