SeekableReadStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Internal / SeekableReadStream.cs / 1 / SeekableReadStream.cs

                            //---------------------------------------------------------------------------- 
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//--------------------------------------------------------------------------- 

using System; 
using System.IO; 
using System.Collections.Generic;
using System.Diagnostics; 

#pragma warning disable 1634, 1691 // Allows suppression of certain PreSharp messages.

namespace System.Speech.Internal 
{
 
#pragma warning disable 56528 // Override of Dispose(bool) not needed as base stream should not be closed. 

    // Class that is used to wrap a stream that does not support Seek into one that does. 
    // While CacheDataForSeeking is true then Read data is buffered so that Seeking can be done later back into the buffer.
    // The Read call will first use the buffer and then the actual data once the buffer is read.
    // After CacheDataForSeeking is set to false data can be read from the buffer but no more Seeking can be done.
    internal class SeekableReadStream : Stream 
    {
        //******************************************************************* 
        // 
        // Constructors
        // 
        //*******************************************************************

        #region Constructors
 
        internal SeekableReadStream(Stream baseStream)
        { 
            Debug.Assert(baseStream.CanRead); 

            _canSeek = baseStream.CanSeek; // If the stream is already seekable then don't need to do anything special 
            _baseStream = baseStream;
        }

        #endregion 

        //******************************************************************** 
        // 
        // Internal Properties
        // 
        //*******************************************************************

        #region Internal Properties
 
        internal bool CacheDataForSeeking
        { 
            set 
            {
                // Currently we can switch the caching off, but not back on again. Not needed for current scenarios. 
                Debug.Assert(!value || _cacheDataForSeeking);
                _cacheDataForSeeking = value;
            }
        } 

        public override bool CanRead 
        { 
            get { return true; }
        } 

        public override bool CanSeek
        {
            get 
            {
                // Can do seeking only if we are caching data or underlying stream supports it. 
                return (_canSeek || _cacheDataForSeeking); 
            }
        } 

        public override bool CanWrite
        {
            get { return false; } 
        }
 
        public override long Length 
        {
            // Non Seekable streams may not implement this, but we don't have much choice as we can't calculate the Stream length any other way. 
            get { return _baseStream.Length; }
        }

        public override long Position 
        {
            get 
            { 
                if (_canSeek)
                { 
                    // Delegate to underlying Stream:
                    return _baseStream.Position;
                }
                else 
                {
                    return _virtualPosition; 
                } 
            }
            set 
            {
                if (_canSeek)
                {
                    // Delegate to underlying Stream: 
                    _baseStream.Position = value;
                } 
                else if (value != _virtualPosition) 
                {
                    if (value < 0) 
                    {
                        throw new ArgumentOutOfRangeException("value", SR.Get(SRID.MustBeGreaterThanZero));
                    }
                    // We can't check the length here so you can Seek beyond the end of the Stream. This will error later though. 

                    if (_cacheDataForSeeking) 
                    { 
                        if (value < _buffer.Count)
                        { 
                            // We're moving within the already buffered data so just move the position:
                            _virtualPosition = value;
                        }
                        else 
                        {
                            // We're moving beyond current position. 
                            // Thus Read the new data data and buffer it. 

                            // Read until at new position: 
                            long bytesToReadLong = value - _buffer.Count;
                            if (bytesToReadLong > int.MaxValue)
                            {
                                throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
                            }
                            byte[] readBuffer = new byte[bytesToReadLong]; 
                            Helpers.BlockingRead(_baseStream, readBuffer, 0, (int)bytesToReadLong); 

                            // Copy from readBuffer into cache: 
                            _buffer.AddRange(readBuffer);
                            _virtualPosition = value;
                        }
                    } 
                    else
                    { 
                        // No longer caching data so we can't seek around. 
                        // Limited cases of this could be supported if needed.
                        throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
                    }
                }
            }
        } 

        #endregion 
 

        //******************************************************************** 
        //
        // Internal Methods
        //
        //******************************************************************** 

        #region Internal Methods 
 
        public override int Read(byte[] buffer, int offset, int count)
        { 
            if (_canSeek)
            {
                // Delegate to underlying Stream:
                return _baseStream.Read(buffer, offset, count); 
            }
            else 
            { 
                int bytesRead = 0;
                if (_virtualPosition < _buffer.Count) 
                {
                    // if new position inside buffer then read until at end of buffer
                    int toCopy = (int)(_buffer.Count - _virtualPosition);
                    if (toCopy > count) 
                    {
                        toCopy = count; 
                    } 
                    _buffer.CopyTo((int)_virtualPosition, buffer, offset, toCopy);
                    count -= toCopy; 
                    _virtualPosition += toCopy;
                    offset += toCopy;
                    bytesRead += toCopy;
                    if (!_cacheDataForSeeking && _virtualPosition >= _buffer.Count) 
                    {
                        // Used up all the buffer, free. 
                        _buffer.Clear(); 
                    }
                } 
                if (count > 0)
                {
                    // Still data to Read so read it from the base Stream:
                    int localBytesRead = _baseStream.Read(buffer, offset, count); 
                    bytesRead += localBytesRead;
                    _virtualPosition += localBytesRead; 
                    if (_cacheDataForSeeking) 
                    {
                        // if caching then extend Stream. 
                        _buffer.Capacity += localBytesRead;
                        // Copy from buffer + offset for bytesRead
                        for (int i = 0; i < localBytesRead; i++)
                        { 
                            _buffer.Add(buffer[offset + i]);
                        } 
                    } 
                    // Even if we didn't read every requested byte we can return - that's the contract on Stream.Read.
                } 
                return bytesRead;
            }
        }
 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            long position; 

            checked // Check for integer overflow 
            {
                switch (origin)
                {
                    case SeekOrigin.Begin: 
                        position = offset;
                        break; 
 
                    case SeekOrigin.Current:
                        position = Position + offset; 
                        break;

                    case SeekOrigin.End:
                        position = Length + offset; 
                        break;
 
                    default: 
                        throw new ArgumentException(SR.Get(SRID.EnumInvalid, "SeekOrigin"), "origin");
                } 
            }

            Position = position; // Actually update position, checks for out of range
            return position; 
        }
 
        public override void SetLength(long value) 
        {
            throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
        }

        public override void Write(byte[] buffer, int offset, int count)
        { 
            throw new NotSupportedException(SR.Get(SRID.StreamMustBeWriteable));
        } 
 
        public override void Flush()
        { 
            _baseStream.Flush();
        }

        #endregion 

 
        //******************************************************************* 
        //
        // Private Fields 
        //
        //********************************************************************

        #region Private Fields 

        private long _virtualPosition; 
        private List _buffer = new List(); // Data cached from start of stream onwards. 

        private Stream _baseStream; 
        private bool _cacheDataForSeeking = true;
        private bool _canSeek;

        #endregion 
    }
#pragma warning restore 56528 
 

} 

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

using System; 
using System.IO; 
using System.Collections.Generic;
using System.Diagnostics; 

#pragma warning disable 1634, 1691 // Allows suppression of certain PreSharp messages.

namespace System.Speech.Internal 
{
 
#pragma warning disable 56528 // Override of Dispose(bool) not needed as base stream should not be closed. 

    // Class that is used to wrap a stream that does not support Seek into one that does. 
    // While CacheDataForSeeking is true then Read data is buffered so that Seeking can be done later back into the buffer.
    // The Read call will first use the buffer and then the actual data once the buffer is read.
    // After CacheDataForSeeking is set to false data can be read from the buffer but no more Seeking can be done.
    internal class SeekableReadStream : Stream 
    {
        //******************************************************************* 
        // 
        // Constructors
        // 
        //*******************************************************************

        #region Constructors
 
        internal SeekableReadStream(Stream baseStream)
        { 
            Debug.Assert(baseStream.CanRead); 

            _canSeek = baseStream.CanSeek; // If the stream is already seekable then don't need to do anything special 
            _baseStream = baseStream;
        }

        #endregion 

        //******************************************************************** 
        // 
        // Internal Properties
        // 
        //*******************************************************************

        #region Internal Properties
 
        internal bool CacheDataForSeeking
        { 
            set 
            {
                // Currently we can switch the caching off, but not back on again. Not needed for current scenarios. 
                Debug.Assert(!value || _cacheDataForSeeking);
                _cacheDataForSeeking = value;
            }
        } 

        public override bool CanRead 
        { 
            get { return true; }
        } 

        public override bool CanSeek
        {
            get 
            {
                // Can do seeking only if we are caching data or underlying stream supports it. 
                return (_canSeek || _cacheDataForSeeking); 
            }
        } 

        public override bool CanWrite
        {
            get { return false; } 
        }
 
        public override long Length 
        {
            // Non Seekable streams may not implement this, but we don't have much choice as we can't calculate the Stream length any other way. 
            get { return _baseStream.Length; }
        }

        public override long Position 
        {
            get 
            { 
                if (_canSeek)
                { 
                    // Delegate to underlying Stream:
                    return _baseStream.Position;
                }
                else 
                {
                    return _virtualPosition; 
                } 
            }
            set 
            {
                if (_canSeek)
                {
                    // Delegate to underlying Stream: 
                    _baseStream.Position = value;
                } 
                else if (value != _virtualPosition) 
                {
                    if (value < 0) 
                    {
                        throw new ArgumentOutOfRangeException("value", SR.Get(SRID.MustBeGreaterThanZero));
                    }
                    // We can't check the length here so you can Seek beyond the end of the Stream. This will error later though. 

                    if (_cacheDataForSeeking) 
                    { 
                        if (value < _buffer.Count)
                        { 
                            // We're moving within the already buffered data so just move the position:
                            _virtualPosition = value;
                        }
                        else 
                        {
                            // We're moving beyond current position. 
                            // Thus Read the new data data and buffer it. 

                            // Read until at new position: 
                            long bytesToReadLong = value - _buffer.Count;
                            if (bytesToReadLong > int.MaxValue)
                            {
                                throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
                            }
                            byte[] readBuffer = new byte[bytesToReadLong]; 
                            Helpers.BlockingRead(_baseStream, readBuffer, 0, (int)bytesToReadLong); 

                            // Copy from readBuffer into cache: 
                            _buffer.AddRange(readBuffer);
                            _virtualPosition = value;
                        }
                    } 
                    else
                    { 
                        // No longer caching data so we can't seek around. 
                        // Limited cases of this could be supported if needed.
                        throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
                    }
                }
            }
        } 

        #endregion 
 

        //******************************************************************** 
        //
        // Internal Methods
        //
        //******************************************************************** 

        #region Internal Methods 
 
        public override int Read(byte[] buffer, int offset, int count)
        { 
            if (_canSeek)
            {
                // Delegate to underlying Stream:
                return _baseStream.Read(buffer, offset, count); 
            }
            else 
            { 
                int bytesRead = 0;
                if (_virtualPosition < _buffer.Count) 
                {
                    // if new position inside buffer then read until at end of buffer
                    int toCopy = (int)(_buffer.Count - _virtualPosition);
                    if (toCopy > count) 
                    {
                        toCopy = count; 
                    } 
                    _buffer.CopyTo((int)_virtualPosition, buffer, offset, toCopy);
                    count -= toCopy; 
                    _virtualPosition += toCopy;
                    offset += toCopy;
                    bytesRead += toCopy;
                    if (!_cacheDataForSeeking && _virtualPosition >= _buffer.Count) 
                    {
                        // Used up all the buffer, free. 
                        _buffer.Clear(); 
                    }
                } 
                if (count > 0)
                {
                    // Still data to Read so read it from the base Stream:
                    int localBytesRead = _baseStream.Read(buffer, offset, count); 
                    bytesRead += localBytesRead;
                    _virtualPosition += localBytesRead; 
                    if (_cacheDataForSeeking) 
                    {
                        // if caching then extend Stream. 
                        _buffer.Capacity += localBytesRead;
                        // Copy from buffer + offset for bytesRead
                        for (int i = 0; i < localBytesRead; i++)
                        { 
                            _buffer.Add(buffer[offset + i]);
                        } 
                    } 
                    // Even if we didn't read every requested byte we can return - that's the contract on Stream.Read.
                } 
                return bytesRead;
            }
        }
 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            long position; 

            checked // Check for integer overflow 
            {
                switch (origin)
                {
                    case SeekOrigin.Begin: 
                        position = offset;
                        break; 
 
                    case SeekOrigin.Current:
                        position = Position + offset; 
                        break;

                    case SeekOrigin.End:
                        position = Length + offset; 
                        break;
 
                    default: 
                        throw new ArgumentException(SR.Get(SRID.EnumInvalid, "SeekOrigin"), "origin");
                } 
            }

            Position = position; // Actually update position, checks for out of range
            return position; 
        }
 
        public override void SetLength(long value) 
        {
            throw new NotSupportedException(SR.Get(SRID.SeekNotSupported)); 
        }

        public override void Write(byte[] buffer, int offset, int count)
        { 
            throw new NotSupportedException(SR.Get(SRID.StreamMustBeWriteable));
        } 
 
        public override void Flush()
        { 
            _baseStream.Flush();
        }

        #endregion 

 
        //******************************************************************* 
        //
        // Private Fields 
        //
        //********************************************************************

        #region Private Fields 

        private long _virtualPosition; 
        private List _buffer = new List(); // Data cached from start of stream onwards. 

        private Stream _baseStream; 
        private bool _cacheDataForSeeking = true;
        private bool _canSeek;

        #endregion 
    }
#pragma warning restore 56528 
 

} 

// 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