CompressEmulationStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / CompressEmulationStream.cs / 1305600 / CompressEmulationStream.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  Abstract base class that provides a fully functional Stream on top of different 
//  various compression implementations.
// 
// History:
//  07/14/2004: BruceMac: Initial implementation.
//  12/06/2005: BruceMac: Split into abstract base class and move DeflateStream
//              specific implementation into ManagedEmulationStream 
//  12/16/2005: BruceMac: Reworked to move functionality into IDeflateTransform
//              interface to avoid calling virtuals from constructor (FxCop rule) 
//----------------------------------------------------------------------------- 

using System; 
using System.IO;
using System.IO.Compression;                // for DeflateStream
using System.Diagnostics;
 
using System.IO.Packaging;
using System.Windows; 
using MS.Internal.WindowsBase; 

namespace MS.Internal.IO.Packaging 
{
    //-----------------------------------------------------
    //
    //  Internal Members 
    //
    //----------------------------------------------------- 
    ///  
    /// Interface for Deflate transform object that we use to decompress and compress the actual bytes
    ///  
    interface IDeflateTransform
    {
        void Decompress(Stream source, Stream sink);
        void Compress(Stream source, Stream sink); 
    }
 
    ///  
    /// Emulates a fully functional stream using restricted functionality DeflateStream and a temp file
    ///  
    internal class CompressEmulationStream : Stream
    {
        //------------------------------------------------------
        // 
        //  Public Methods
        // 
        //----------------------------------------------------- 
        #region Stream Methods
        ///  
        /// Return the bytes requested from the container
        /// 
        /// destination buffer
        /// offset to write into that buffer 
        /// how many bytes requested
        /// how many bytes were written into . 
        ///  
        /// The underlying stream, expected to be an IsolatedStorageFileStream,
        /// is trusted to leave the IO position unchanged in case of an exception. 
        /// 
        public override int Read(byte[] buffer, int offset, int count)
        {
            CheckDisposed(); 

            PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); 
 
            return _tempStream.Read(buffer, offset, count);
        } 

        /// 
        /// Seek
        ///  
        /// offset
        /// origin 
        /// zero 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            CheckDisposed();

            long temp = 0;
            switch (origin) 
            {
                case SeekOrigin.Begin: 
                    { 
                        temp = offset;
                        break; 
                    }
                case SeekOrigin.Current:
                    {
                        checked { temp = _tempStream.Position + offset; } 
                        break;
                    } 
                case SeekOrigin.End: 
                    {
                        checked { temp = _tempStream.Length + offset; } 
                        break;
                    }
                default:
                    { 
                        throw new ArgumentOutOfRangeException("origin", SR.Get(SRID.SeekOriginInvalid));
                    } 
            } 

            if (temp < 0) 
            {
                throw new ArgumentException(SR.Get(SRID.SeekNegative));
            }
 
            return _tempStream.Seek(offset, origin);
        } 
 
        /// 
        /// SetLength 
        /// 
        public override void SetLength(long newLength)
        {
            CheckDisposed(); 

            _tempStream.SetLength(newLength); 
 
            // truncation always involves change of stream pointer
            if (newLength < _tempStream.Position) 
                _tempStream.Position = newLength;

            _dirty = true;
        } 

        ///  
        /// Write 
        /// 
        public override void Write(byte[] buffer, int offset, int count) 
        {
            CheckDisposed();

            PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); 

            // no-op 
            if (count == 0) 
                return;
 
            _tempStream.Write(buffer, offset, count);
            _dirty = true;
        }
 
        /// 
        /// Flush 
        ///  
        /// Flushes to stream (if necessary)
        public override void Flush() 
        {
            CheckDisposed();

            if (_dirty) 
            {
                // don't disturb our current position 
                long tempPosition = _tempStream.Position; 

                // compress 
                _tempStream.Position = 0;
                _baseStream.Position = 0;
                _transformer.Compress(_tempStream, _baseStream);
 
                // restore
                _tempStream.Position = tempPosition; 
 
                _baseStream.Flush();
                _dirty = false; 
            }
        }
        #endregion Stream Methods
 
        #region Stream Properties
        ///  
        /// Current logical position within the stream 
        /// 
        public override long Position 
        {
            get
            {
                CheckDisposed(); 
                return _tempStream.Position;
            } 
            set 
            {
                CheckDisposed(); 

                if (value < 0)
                    throw new ArgumentException(SR.Get(SRID.SeekNegative));
 
                _tempStream.Position = value;
            } 
        } 

        ///  
        /// Length
        /// 
        public override long Length
        { 
            get
            { 
                CheckDisposed(); 
                return _tempStream.Length;
            } 
        }

        /// 
        /// Is stream readable? 
        /// 
        /// returns false when called on disposed stream 
        public override bool CanRead 
        {
            get 
            {
                return (!_disposed && _baseStream.CanRead);
            }
        } 

        ///  
        /// Is stream seekable - should be handled by our owner 
        /// 
        /// returns false when called on disposed stream 
        public override bool CanSeek
        {
            get
            { 
                return (!_disposed &&  _baseStream.CanSeek);
            } 
        } 

        ///  
        /// Is stream writeable?
        /// 
        /// returns false when called on disposed stream
        public override bool CanWrite 
        {
            get 
            { 
                return (!_disposed && _baseStream.CanWrite);
            } 
        }
        #endregion

        #region Internal 
        //------------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 
        /// 
        /// Constructor
        /// 
        /// part stream - not closed - caller determines lifetime 
        /// current logical stream position
        /// should be an IsolatedStorageFileStream - not closed - caller determines lifetime 
        /// class that does the compression/decompression 
        /// This class should only invoked when emulation is required.
        /// Does not close any given stream, even when Close is called. This means that it requires 
        /// another wrapper Stream class.
        internal CompressEmulationStream(Stream baseStream, Stream tempStream, long position, IDeflateTransform transformer)
        {
            if (position < 0) 
                throw new ArgumentOutOfRangeException("position");
 
            if (baseStream == null) 
                throw new ArgumentNullException("baseStream");
 
            // seek and read required for emulation
            if (!baseStream.CanSeek)
                throw new InvalidOperationException(SR.Get(SRID.SeekNotSupported));
 
            if (!baseStream.CanRead)
                throw new InvalidOperationException(SR.Get(SRID.ReadNotSupported)); 
 
            if (tempStream == null)
                throw new ArgumentNullException("tempStream"); 

            if (transformer == null)
                throw new ArgumentNullException("transformer");
 
            _baseStream = baseStream;
            _tempStream = tempStream; 
            _transformer = transformer; 

            // extract to temporary stream 
            _baseStream.Position = 0;
            _tempStream.Position = 0;
            _transformer.Decompress(baseStream, tempStream);
 
            // seek to the current logical position
            _tempStream.Position = position; 
        } 
        #endregion
 
        //-----------------------------------------------------
        //
        //  Protected Methods
        // 
        //------------------------------------------------------
        ///  
        /// Dispose(bool) 
        /// 
        ///  
        /// We implement this because we want a consistent experience (essentially Flush our data) if the user chooses to
        /// call Dispose() instead of Close().
        protected override void Dispose(bool disposing)
        { 
            try
            { 
                if (disposing) 
                {
                    if (!_disposed) 
                    {
                        Flush();

                        _tempStream.Close(); 
                        _tempStream = null;
 
                        // never close base stream - we don't own it 
//                        _baseStream.Close();
                        _baseStream = null; 

                        _disposed = true;
                    }
                } 
            }
            finally 
            { 
                base.Dispose(disposing);
            } 
        }

        /// 
        /// Call this before accepting any public API call (except some Stream calls that 
        /// are allowed to respond even when Closed
        ///  
        protected void CheckDisposed() 
        {
            if (_disposed) 
                throw new ObjectDisposedException(null, SR.Get(SRID.StreamObjectDisposed));
        }

        #region Private 
        //-----------------------------------------------------
        // 
        //  Private Variables 
        //
        //----------------------------------------------------- 
        private bool    _disposed;          // disposed?
        private bool    _dirty;             // do we need to recompress?
        protected Stream  _baseStream;      // stream we ultimately decompress from and to in the container
        protected Stream _tempStream;       // temporary storage for the uncompressed stream 
        IDeflateTransform _transformer;   // does the actual compress/decompress for us
        #endregion 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK