dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/IO BufferedStream.cs,


From: Gopal.V <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/IO BufferedStream.cs,NONE,1.1
Date: Sun, 26 Jan 2003 13:08:04 -0500

Update of /cvsroot/dotgnu-pnet/pnetlib/runtime/System/IO
In directory subversions:/tmp/cvs-serv7806/runtime/System/IO

Added Files:
        BufferedStream.cs 
Log Message:
BufferedStream implementation


--- NEW FILE ---
/*
 * BufferedStream.cs - Implementation of "System.IO.BufferedStream" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 * 
 * contributed by Gopal.V
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;

namespace System.IO
{
#if !ECMA_COMPAT

        public sealed class BufferedStream: Stream
        {
                private Stream stream;
                private int             bufferSize;
                private byte[]          inBuffer;
                private int             inBufferPosn;
                private int             inBufferLen;
                private byte[]          outBuffer;
                private int             outBufferPosn;
                private int             outBufferLen;
                private bool            sawEOF;

                private bool            readMode;

                // Default and minimum buffer sizes to use for streams.
                private const int STREAM_BUFSIZ = 1024;
                private const int MIN_BUFSIZ    = 128;
                
                public BufferedStream(Stream stream) : 
this(stream,STREAM_BUFSIZ)
                {
                }

                public BufferedStream(Stream stream, int bufferSize)
                {
                                // Validate the parameters.
                        if(stream == null)
                        {
                                throw new ArgumentNullException("stream");
                        }
                        if(bufferSize <= 0)
                        {
                                throw new ArgumentOutOfRangeException
                                        ("bufferSize", 
_("ArgRange_BufferSize"));
                        }
                        if(bufferSize < MIN_BUFSIZ)
                        {
                                bufferSize = MIN_BUFSIZ;
                        }

                        this.stream = stream;
                        this.bufferSize = bufferSize;
                        this.inBuffer = new byte [bufferSize];
                        this.inBufferPosn = 0;
                        this.inBufferLen = 0;
                        this.outBuffer = new byte [bufferSize];
                        this.outBufferPosn = 0;
                        this.outBufferLen = 0;
                        this.sawEOF = false;
                        this.readMode=false;
                }

                public override void Close()
                {
                        Flush();
                        stream.Close();
                }

                public override void Flush()
                {
                        if(readMode)
                        {
                                /* data will be lost if I cannot seek back ? */
                                if(CanSeek && stream.Position != this.Position)
                                {
                                        
stream.Seek(inBufferLen-inBufferPosn,SeekOrigin.Current);
                                        inBufferPosn=0;
                                        inBufferLen=0;
                                }
                        }
                        else
                        {
                                if(stream.Position == this.Position)
                                {
                                        if((outBufferLen - outBufferPosn) !=0)
                                        {
                                                
stream.Write(outBuffer,outBufferPosn,
                                                                                
(outBufferLen-outBufferPosn));
                                                stream.Flush();
                                                outBufferLen=0;
                                                outBufferPosn=0;
                                        }
                                }
                                else
                                {
                                        /* a dirty write .. by design all reads 
are flushed
                                           before writing , so this is a bug or 
mistake by
                                           the application dev */
                                        throw new 
NotSupportedException(_("IO_NotSupp_Seek"));
                                }
                        }
                }

                private void FillBuffer()
                {
                        int len, outLen;
                        
                        /* this is lifted off StreamReader */
                        while(inBufferPosn >= inBufferLen && !sawEOF)
                        {
                                // Move the previous left-over buffer contents 
down.
                                if((inBufferLen - inBufferPosn) < bufferSize)
                                {
                                        if(inBufferPosn < inBufferLen)
                                        {
                                                Array.Copy
                                                        (inBuffer, inBufferPosn,
                                                     inBuffer, 0, inBufferLen - 
inBufferPosn);
                                                inBufferLen -= inBufferPosn;
                                        }
                                        else
                                        {
                                                inBufferLen = 0;
                                        }
                                        inBufferPosn = 0;
                                        // Read new bytes into the buffer.
                                        if(stream == null)
                                        {
                                                throw new 
IOException(_("IO_StreamClosed"));
                                        }
                                        len = stream.Read(inBuffer, 
inBufferPosn,
                                                                          
bufferSize - inBufferPosn);
                                        if(len <= 0)
                                        {
                                                sawEOF = true;
                                        }
                                        else
                                        {
                                                inBufferLen += len;
                                        }
                                }
                        }
                }

                public override int Read(byte[] buffer, int offset, int count)
                {
                        // Validate the parameters.
                        if(buffer == null)
                        {
                                throw new ArgumentNullException("buffer");
                        }
                        if(offset < 0)
                        {
                                throw new ArgumentOutOfRangeException
                                        ("offset", _("ArgRange_Array"));
                        }
                        if(count < 0)
                        {
                                throw new ArgumentOutOfRangeException
                                        ("count", _("ArgRange_Array"));
                        }
                        if((buffer.Length - offset) < count)
                        {
                                throw new ArgumentException
                                        (_("Arg_InvalidArrayRange"));
                        }
                        if(!readMode)
                        {
                                Flush(); /* flush previous writes for avoiding 
dirty stuff */
                                readMode=true;
                        }
                        // Read data from the input stream into the buffer.
                        int len = 0;
                        int templen;
                        while(count > 0)
                        {
                                // Re-fill the buffer
                                if(inBufferPosn >= inBufferLen)
                                {
                                        FillBuffer();
                                        if(inBufferPosn >= inBufferLen)
                                        {
                                                break;
                                        }
                                }
                                // Copy data to the result buffer.
                                templen = inBufferLen - inBufferPosn;
                                if(templen > count)
                                {
                                        templen = count;
                                }
                                Array.Copy(inBuffer, inBufferPosn,
                                                   buffer, offset, templen);
                                inBufferPosn += templen;
                                offset += templen;
                                count -= templen;
                                len += templen;
                        }
                        return len;
                }

                public override int ReadByte()
                {
                        /* note: I've taken the easy way out here */
                        byte[] buf = new byte[1];
                        if(Read(buf,0,1) == 1)
                        {
                                return buf[0];
                        }
                        return -1;
                }

                public override long Seek(long offset, SeekOrigin origin)
                {
                        Flush();
                        return stream.Seek(offset,origin);
                }

                public override void SetLength(long value)
                {
                        Flush();
                        stream.SetLength(value);
                }

                public override void Write(byte[] array, int offset, int count)
                {
                        if(array == null)
                        {
                                throw new ArgumentNullException("array");
                        }
                        if(offset < 0)
                        {
                                throw new ArgumentOutOfRangeException
                                        ("offset", _("ArgRange_Array"));
                        }
                        if(count < 0)
                        {
                                throw new ArgumentOutOfRangeException
                                        ("count", _("ArgRange_Array"));
                        }
                        if((array.Length - offset) < count)
                        {
                                throw new ArgumentException
                                        (_("Arg_InvalidArrayRange"));
                        }

                        if(readMode)
                        {
                                Flush(); /* seek back if possible */
                                readMode=false;
                        }

                        int spaceInBuffer=bufferSize-outBufferLen;
                        int dataLen = offset - count;
                        /* simple cases first ;) */
                        if(spaceInBuffer > dataLen)
                        {
                                
Array.Copy(outBuffer,outBufferPosn,array,offset, dataLen);
                                outBufferLen+=dataLen;
                                return;
                        }
                        // so we have more data than we can store directly , 
try making
                        // room by moving to the front.
                        if(outBufferPosn < outBufferLen)
                        {
                                Array.Copy(outBuffer, outBufferPosn, outBuffer, 
0, 
                                                        
outBufferLen-outBufferPosn);
                                outBufferLen -= outBufferPosn;  
                        }
                        else
                        {
                                /* empty buffer */
                                outBufferLen=0;
                        }
                        spaceInBuffer=bufferSize-outBufferLen;
                        if(spaceInBuffer > dataLen)
                        {
                                Array.Copy(outBuffer, outBufferPosn, outBuffer, 
0, 
                                                        
outBufferLen-outBufferPosn);
                                outBufferLen+=dataLen;
                                return;
                        }
                        // now we know that the data is too large to fit in the 
                        // buffer in anyway, so flush
                        Flush();
                        // calculate what will be left in the buffer
                        int keptData= count % bufferSize;
                        if(keptData!=0)
                        {
                                stream.Write(array,offset,count-keptData);
                                Array.Copy(outBuffer, outBufferPosn, array, 
                                                        offset + count - 
keptData, keptData);
                                outBufferLen+=keptData;
                        }
                        else
                        {
                                /* we have got full chunks to write , yay ! 
                                   and we have a Flushed buffer 
                                 */
                                stream.Write(array,offset,count);
                        }
                }

                public override void WriteByte(byte value)
                {
                        byte []buf=new byte[1];
                        buf[0]=value;
                
                        Write(buf,0,1);
                }

                public override bool CanRead 
                {
                        get
                        {
                                return stream.CanRead;
                        }
                }

                public override bool CanSeek 
                {
                        get
                        {
                                return stream.CanSeek;
                        }
                }

                public override bool CanWrite 
                {
                        get
                        {
                                return stream.CanWrite;
                        }
                }

                public override long Length 
                {
                        get
                        {
                                return stream.Length;
                        }
                }

                public override long Position 
                {
                        get
                        {
                                /* note : virtual position ? */
                                return stream.Position - 
(inBufferLen-inBufferPosn);
                        }
                        set
                        {
                                Flush();
                                stream.Position = value;
                        }
                }

        }
#endif
}//namespace





reply via email to

[Prev in Thread] Current Thread [Next in Thread]