class · System.IO

BufferedStream

public class BufferedStream : Stream

A buffer in front of another stream: small reads and writes become few large ones.

Kind
class
Namespace
System.IO
Assembly
System.Core
Access
public
Source file
Stream.ant

Inheritance

Base classes
Any Stream BufferedStream

Constructors

new(Stream stream)
#
new(Stream stream, i32 bufferSize)
#

Properties

Stream UnderlyingStream { get; }
#

read-only

The stream behind the buffer.

i32 BufferSize { get; }
#

read-only

override bool CanRead { get; }
#

read-only

override bool CanWrite { get; }
#

read-only

override bool CanSeek { get; }
#

read-only

override i64 Length { get; }
#

read-only

override i64 Position { get; set; }
#

Methods

override Read(u8[] target, i32 offset, i32 count) : i32
#

override

override ReadByte() : i32
#

override

override Write(u8[] source, i32 offset, i32 count)
#

override

override WriteByte(u8 value)
#

override

override Seek(i64 offset, SeekOrigin origin) : i64
#

override

override SetLength(i64 length)
#

override

override Flush()
#

override

override Close()
#

override

Private and internal members (7)

Stream inner
#

private

u8[] buffer
#

private

i32 readAt
#

private

Bytes read ahead: buffer[readAt..readEnd].

i32 readEnd
#

private

i32 writeEnd
#

private

Bytes not written yet: buffer[0..writeEnd].

FlushWrites()
#

private

DropReads()
#

private

Gives back the bytes read ahead (moving the inner stream back to where this one is).

Inherited members (11)

Source

BufferedStream as Antril, decompiled from its Larva HIR.

System.IO.BufferedStream.ant
// System.IO.BufferedStream — System.Core (decompiled from Larva HIR)

import System;

into namespace System.IO
{
	/// A buffer in front of another stream: small reads and writes become few large ones.
	public class BufferedStream : Stream
	{
		Stream inner;
		u8[] buffer;

		/// Bytes read ahead: buffer[readAt..readEnd].
		i32 readAt;
		i32 readEnd;

		/// Bytes not written yet: buffer[0..writeEnd].
		i32 writeEnd;

		FlushWrites()
		{
			if (writeEnd > 0)
			{
				inner.Write(buffer, 0, writeEnd);
				writeEnd = 0;
			}
		}

		/// Gives back the bytes read ahead (moving the inner stream back to where this one is).
		DropReads()
		{
			if (readAt < readEnd && inner.CanSeek)
				inner.Seek((i64)readAt - (i64)readEnd, SeekOrigin.Current);
			readAt = 0;
			readEnd = 0;
		}

		public:
			new(Stream stream) : (stream, 4096)
			{
			}

			new(Stream stream, i32 bufferSize)
			{
				if (bufferSize <= 0)
					throw new ArgumentError("BufferedStream: the buffer size must be positive");
				inner = stream;
				buffer = new u8[bufferSize];
			}

			override Read(u8[] target, i32 offset, i32 count) : i32
			{
				i32 buffered = readEnd - readAt;
				if (buffered == 0)
				{
					FlushWrites();
					if (count >= buffer.Length)
						return inner.Read(target, offset, count);
					readAt = 0;
					readEnd = inner.Read(buffer, 0, buffer.Length);
					buffered = readEnd;
					if (buffered == 0)
						return 0;
				}
				i32 n = buffered < count ? buffered : count;
				Array.Copy(buffer, readAt, target, offset, n);
				readAt += n;
				return n;
			}

			override ReadByte() : i32
			{
				if (readAt < readEnd)
				{
					readAt++;
					return (i32)buffer[readAt - 1];
				}
				FlushWrites();
				readAt = 0;
				readEnd = inner.Read(buffer, 0, buffer.Length);
				if (readEnd == 0)
					return -1;
				readAt = 1;
				return (i32)buffer[0];
			}

			override Write(u8[] source, i32 offset, i32 count)
			{
				if (readEnd > 0)
					DropReads();
				if (writeEnd == 0 && count >= buffer.Length)
				{
					inner.Write(source, offset, count);
					return;
				}
				if (writeEnd + count <= buffer.Length)
				{
					Array.Copy(source, offset, buffer, writeEnd, count);
					writeEnd += count;
					return;
				}
				FlushWrites();
				if (count >= buffer.Length)
				{
					inner.Write(source, offset, count);
					return;
				}
				Array.Copy(source, offset, buffer, 0, count);
				writeEnd = count;
			}

			override WriteByte(u8 value)
			{
				if (readEnd == 0 && writeEnd < buffer.Length)
				{
					buffer[writeEnd] = value;
					writeEnd++;
					return;
				}
				if (readEnd > 0)
					DropReads();
				if (writeEnd == buffer.Length)
					FlushWrites();
				buffer[writeEnd] = value;
				writeEnd++;
			}

			override Seek(i64 offset, SeekOrigin origin) : i64
			{
				if (!inner.CanSeek)
					throw new IOError("the stream cannot seek");
				FlushWrites();
				if (origin == SeekOrigin.Current)
					offset -= (i64)readEnd - (i64)readAt;
				readAt = 0;
				readEnd = 0;
				return inner.Seek(offset, origin);
			}

			override SetLength(i64 length)
			{
				FlushWrites();
				DropReads();
				inner.SetLength(length);
			}

			override Flush()
			{
				FlushWrites();
				inner.Flush();
			}

			override Close()
			{
				FlushWrites();
				inner.Close();
			}

			/// The stream behind the buffer.
			Stream UnderlyingStream
			{
				get => inner;
			}

			i32 BufferSize
			{
				get => buffer.Length;
			}

			override bool CanRead
			{
				get => inner.CanRead;
			}

			override bool CanWrite
			{
				get => inner.CanWrite;
			}

			override bool CanSeek
			{
				get => inner.CanSeek;
			}

			override i64 Length
			{
				get
				{
					FlushWrites();
					return inner.Length;
				}
			}

			override i64 Position
			{
				get => inner.Position - ((i64)readEnd - (i64)readAt) + (i64)writeEnd;
				set
				{
					Seek(value, SeekOrigin.Begin);
				}
			}
	}
}
Esc