using System;
namespace System.IO
{
public class BufferedStream : Stream, Closable
{
public BufferedStream(Stream stream) : this(stream, 4096)
{
}
public BufferedStream(Stream stream, int bufferSize)
{
if (stream == null)
{
throw new ArgumentNullException("provided stream is null");
}
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("invalid bufferSize");
}
this.baseStream = stream;
this.buf = new byte[bufferSize];
this.pos = buf.Length;
this.bytesAvailable = 0;
this.end = 0;
}
public override void Close()
{
Flush();
baseStream.Close();
}
public override void WriteByte(byte value)
{
if (end >= buf.Length)
{
Flush();
}
buf[end] = value;
++end;
}
public override void Write(byte[] buffer, int count)
{
if (buffer == null)
{
throw new ArgumentNullException("provided buffer is null");
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("invalid count");
}
for (int i = 0; i < count; ++i)
{
WriteByte(buffer[i]);
}
}
public override int ReadByte()
{
Flush();
if (bytesAvailable == 0)
{
FillBuf();
if (bytesAvailable == 0)
{
return -1;
}
}
byte value = buf[pos];
++pos;
--bytesAvailable;
return value;
}
public override int Read(byte[] buffer)
{
if (buffer == null)
{
throw new ArgumentNullException("provided buffer is null");
}
Flush();
if (bytesAvailable == 0)
{
FillBuf();
}
int bytesRead = 0;
int n = Math.Min(bytesAvailable, buffer.Length);
for (int i = 0; i < n; ++i)
{
buffer[i] = buf[pos];
++pos;
++bytesRead;
--bytesAvailable;
}
return bytesRead;
}
public override void Flush()
{
if (end != 0)
{
baseStream.Write(buf, end);
end = 0;
}
}
public override void Seek(int pos, Origin origin)
{
Flush();
bytesAvailable = 0;
baseStream.Seek(pos, origin);
}
public override int Tell()
{
Flush();
return baseStream.Tell() - bytesAvailable;
}
public Stream BaseStream
{
get { return baseStream; }
}
private void FillBuf()
{
bytesAvailable = baseStream.Read(buf);
pos = 0;
}
private Stream baseStream;
private byte[] buf;
private int pos;
private int bytesAvailable;
private int end;
}
}