Fifo Stream : Stream Read Write « File Stream « C# / C Sharp






Fifo Stream

  
///////////////////////////////////////////////////////////////////////////////////////////////
//
//    This File is Part of the CallButler Open Source PBX (http://www.codeplex.com/callbutler
//
//    Copyright (c) 2005-2008, Jim Heising
//    All rights reserved.
//
//    Redistribution and use in source and binary forms, with or without modification,
//    are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation and/or
//      other materials provided with the distribution.
//
//    * Neither the name of Jim Heising nor the names of its contributors may be
//      used to endorse or promote products derived from this software without specific prior
//      written permission.
//
//    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
//    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//    POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.IO;
using System.Collections;

namespace WOSI.Utilities
{
    public class FifoStream : Stream
    {
        private const int BlockSize = 65536;
        private const int MaxBlocksInCache = (3 * 1024 * 1024) / BlockSize;

        private int m_Size;
        private int m_RPos;
        private int m_WPos;
        private Stack m_UsedBlocks = new Stack();
        private ArrayList m_Blocks = new ArrayList();

        private byte[] AllocBlock()
        {
            byte[] Result = null;
            Result = m_UsedBlocks.Count > 0 ? (byte[])m_UsedBlocks.Pop() : new byte[BlockSize];
            return Result;
        }
        private void FreeBlock(byte[] block)
        {
            if (m_UsedBlocks.Count < MaxBlocksInCache)
                m_UsedBlocks.Push(block);
        }
        private byte[] GetWBlock()
        {
            byte[] Result = null;
            if (m_WPos < BlockSize && m_Blocks.Count > 0)
                Result = (byte[])m_Blocks[m_Blocks.Count - 1];
            else
            {
                Result = AllocBlock();
                m_Blocks.Add(Result);
                m_WPos = 0;
            }
            return Result;
        }

        // Stream members
        public override bool CanRead
        {
            get { return true; }
        }
        public override bool CanSeek
        {
            get { return false; }
        }
        public override bool CanWrite
        {
            get { return true; }
        }
        public override long Length
        {
            get
            {
                lock (this)
                    return m_Size;
            }
        }
        public override long Position
        {
            get { throw new InvalidOperationException(); }
            set { throw new InvalidOperationException(); }
        }
        public override void Close()
        {
            Flush();
        }
        public override void Flush()
        {
            lock (this)
            {
                foreach (byte[] block in m_Blocks)
                    FreeBlock(block);
                m_Blocks.Clear();
                m_RPos = 0;
                m_WPos = 0;
                m_Size = 0;
            }
        }
        public override void SetLength(long len)
        {
            throw new InvalidOperationException();
        }
        public override long Seek(long pos, SeekOrigin o)
        {
            throw new InvalidOperationException();
        }
        public override int Read(byte[] buf, int ofs, int count)
        {
            lock (this)
            {
                int Result = Peek(buf, ofs, count);
                Advance(Result);
                return Result;
            }
        }
        public override void Write(byte[] buf, int ofs, int count)
        {
            lock (this)
            {
                int Left = count;
                while (Left > 0)
                {
                    int ToWrite = Math.Min(BlockSize - m_WPos, Left);
                    Array.Copy(buf, ofs + count - Left, GetWBlock(), m_WPos, ToWrite);
                    m_WPos += ToWrite;
                    Left -= ToWrite;
                }
                m_Size += count;
            }
        }

        // extra stuff
        public int Advance(int count)
        {
            lock (this)
            {
                int SizeLeft = count;
                while (SizeLeft > 0 && m_Size > 0)
                {
                    if (m_RPos == BlockSize)
                    {
                        m_RPos = 0;
                        FreeBlock((byte[])m_Blocks[0]);
                        m_Blocks.RemoveAt(0);
                    }
                    int ToFeed = m_Blocks.Count == 1 ? Math.Min(m_WPos - m_RPos, SizeLeft) : Math.Min(BlockSize - m_RPos, SizeLeft);
                    m_RPos += ToFeed;
                    SizeLeft -= ToFeed;
                    m_Size -= ToFeed;
                }
                return count - SizeLeft;
            }
        }
        public int Peek(byte[] buf, int ofs, int count)
        {
            lock (this)
            {
                int SizeLeft = count;
                int TempBlockPos = m_RPos;
                int TempSize = m_Size;

                int CurrentBlock = 0;
                while (SizeLeft > 0 && TempSize > 0)
                {
                    if (TempBlockPos == BlockSize)
                    {
                        TempBlockPos = 0;
                        CurrentBlock++;
                    }
                    int Upper = CurrentBlock < m_Blocks.Count - 1 ? BlockSize : m_WPos;
                    int ToFeed = Math.Min(Upper - TempBlockPos, SizeLeft);
                    Array.Copy((byte[])m_Blocks[CurrentBlock], TempBlockPos, buf, ofs + count - SizeLeft, ToFeed);
                    SizeLeft -= ToFeed;
                    TempBlockPos += ToFeed;
                    TempSize -= ToFeed;
                }
                return count - SizeLeft;
            }
        }
    }
}

   
    
  








Related examples in the same category

1.Use StreamWriter to create a text file
2.Reading from a text file line by line
3.Read data in line by line
4.StreamReader.ReadLine
5.Catch file read exception and retry
6.Construct StreamWriter from FileSream
7.Create a StreamWriter in UTF8 mode
8.StreamReader And Writer
9.illustrates reading and writing text dataillustrates reading and writing text data
10.Asynchronously reads a streamAsynchronously reads a stream
11.The use of a buffered stream to serve as intermediate data holder for another streamThe use of a buffered stream to serve as intermediate data holder for another stream
12.Demonstrates attaching a StreamReader object to a stream
13.Demonstrates attaching a StreamWriter object to a stream
14.A simple key-to-disk utility that demonstrates a StreamWriterA simple key-to-disk utility that 
   demonstrates a StreamWriter
15.Open a file using StreamWriterOpen a file using StreamWriter
16.A help program that uses a disk file to store help informationA help program that uses a disk file 
   to store help information
17.Try and catch exceptions for StreamWriter
18.Using StreamWriter 3
19.Utility class that provides methods to manipulate stream of data.
20.Reads a stream into a byte array.
21.Copies one stream into another.
22.Copy Stream from fromStream to toStream
23.Enumerate Lines for StreamReader
24.Enumerate non-empty Lines for StreamReader
25.Read from stream
26.Read from a Stream ensuring all the required data is read.
27.Serializes and object to a stream. It will flush and close the underlying stream.
28.Add OutputStream and InputStream to IDbCommand
29.Read Stream to End
30.Copy Stream and close
31.Stream Converter
32.Buffered InputStream
33.Page Filter Stream
34.Copies an Stream into another Stream.