sdk/Common/Internal/WrapperStream.cs (152 lines of code) (raw):

/* * Copyright (C) Alibaba Cloud Computing * All rights reserved. * */ using System; using System.IO; using Aliyun.OSS.Util; namespace Aliyun.OSS.Common.Internal { /// <summary> /// A wrapper stream. /// </summary> public class WrapperStream : Stream { /// <summary> /// Base stream. /// </summary> protected Stream BaseStream { get; private set; } /// <summary> /// Initializes WrapperStream with a base stream. /// </summary> /// <param name="baseStream"></param> public WrapperStream(Stream baseStream) { if (baseStream == null) throw new ArgumentNullException("baseStream"); BaseStream = baseStream; } /// <summary> /// Returns the first base non-WrapperStream. /// </summary> /// <returns>First base stream that is non-WrapperStream.</returns> public Stream GetNonWrapperBaseStream() { Stream baseStream = this; do { var partialStream = baseStream as PartialWrapperStream; if (partialStream != null) return partialStream; baseStream = (baseStream as WrapperStream).BaseStream; } while (baseStream is WrapperStream); return baseStream; } /// <summary> /// Returns the first base non-WrapperStream. /// </summary> /// <returns>First base stream that is non-WrapperStream.</returns> public Stream GetSeekableBaseStream() { Stream baseStream = this; do { if (baseStream.CanSeek) return baseStream; baseStream = (baseStream as WrapperStream).BaseStream; } while (baseStream is WrapperStream); if (!baseStream.CanSeek) throw new InvalidOperationException("Unable to find seekable stream"); return baseStream; } /// <summary> /// Returns the first base non-WrapperStream. /// </summary> /// <param name="stream">Potential WrapperStream</param> /// <returns>Base non-WrapperStream.</returns> public static Stream GetNonWrapperBaseStream(Stream stream) { WrapperStream wrapperStream = stream as WrapperStream; if (wrapperStream == null) return stream; return wrapperStream.GetNonWrapperBaseStream(); } public Stream SearchWrappedStream(OssFunc<Stream, bool> condition) { Stream baseStream = this; do { if (condition(baseStream)) return baseStream; if (!(baseStream is WrapperStream)) return null; baseStream = (baseStream as WrapperStream).BaseStream; } while (baseStream != null); return baseStream; } public static Stream SearchWrappedStream(Stream stream, OssFunc<Stream, bool> condition) { WrapperStream wrapperStream = stream as WrapperStream; if (wrapperStream == null) return condition(stream) ? stream : null; return wrapperStream.SearchWrappedStream(condition); } #region Stream overrides /// <summary> /// Gets a value indicating whether the current stream supports reading. /// True if the stream supports reading; otherwise, false. /// </summary> public override bool CanRead { get { return BaseStream.CanRead; } } /// <summary> /// Gets a value indicating whether the current stream supports seeking. /// True if the stream supports seeking; otherwise, false. /// </summary> public override bool CanSeek { get { return BaseStream.CanSeek; } } /// <summary> /// Gets a value indicating whether the current stream supports writing. /// True if the stream supports writing; otherwise, false. /// </summary> public override bool CanWrite { get { return BaseStream.CanWrite; } } /// <summary> /// Closes the current stream and releases any resources (such as sockets and /// file handles) associated with the current stream. /// </summary> #if !PCL && !CORECLR public override void Close() { BaseStream.Close(); } #else protected override void Dispose(bool disposing) { base.Dispose(disposing); BaseStream.Dispose(); } #endif /// <summary> /// Gets the length in bytes of the stream. /// </summary> public override long Length { get { return BaseStream.Length; } } /// <summary> /// Gets or sets the position within the current stream. /// </summary> public override long Position { get { return BaseStream.Position; } set { BaseStream.Position = value; } } /// <summary> /// Gets or sets a value, in miliseconds, that determines how long the stream /// will attempt to read before timing out. /// </summary> public override int ReadTimeout { get { return BaseStream.ReadTimeout; } set { BaseStream.ReadTimeout = value; } } /// <summary> /// Gets or sets a value, in miliseconds, that determines how long the stream /// will attempt to write before timing out. /// </summary> public override int WriteTimeout { get { return BaseStream.WriteTimeout; } set { BaseStream.WriteTimeout = value; } } /// <summary> /// Clears all buffers for this stream and causes any buffered data to be written /// to the underlying device. /// </summary> public override void Flush() { BaseStream.Flush(); } /// <summary> /// Reads a sequence of bytes from the current stream and advances the position /// within the stream by the number of bytes read. /// </summary> /// <param name="buffer"> /// An array of bytes. When this method returns, the buffer contains the specified /// byte array with the values between offset and (offset + count - 1) replaced /// by the bytes read from the current source. /// </param> /// <param name="offset"> /// The zero-based byte offset in buffer at which to begin storing the data read /// from the current stream. /// </param> /// <param name="count"> /// The maximum number of bytes to be read from the current stream. /// </param> /// <returns> /// The total number of bytes read into the buffer. This can be less than the /// number of bytes requested if that many bytes are not currently available, /// or zero (0) if the end of the stream has been reached. /// </returns> public override int Read(byte[] buffer, int offset, int count) { return BaseStream.Read(buffer, offset, count); } /// <summary> /// Sets the position within the current stream. /// </summary> /// <param name="offset">A byte offset relative to the origin parameter.</param> /// <param name="origin"> /// A value of type System.IO.SeekOrigin indicating the reference point used /// to obtain the new position.</param> /// <returns>The new position within the current stream.</returns> public override long Seek(long offset, SeekOrigin origin) { return BaseStream.Seek(offset, origin); } /// <summary> /// Sets the length of the current stream. /// </summary> /// <param name="value">The desired length of the current stream in bytes.</param> public override void SetLength(long value) { BaseStream.SetLength(value); } /// <summary> /// Writes a sequence of bytes to the current stream and advances the current /// position within this stream by the number of bytes written. /// </summary> /// <param name="buffer"> /// An array of bytes. This method copies count bytes from buffer to the current stream. /// </param> /// <param name="offset"> /// The zero-based byte offset in buffer at which to begin copying bytes to the /// current stream. /// </param> /// <param name="count">The number of bytes to be written to the current stream.</param> public override void Write(byte[] buffer, int offset, int count) { BaseStream.Write(buffer, offset, count); } #endregion } }