class · System.IO

StreamReader

public class StreamReader : TextReader

Text read from a stream as UTF-8 (a byte order mark at the start is skipped), through a buffer.

Tipo
class
Espacio de nombres
System.IO
Ensamblado
System.Core
Acceso
public
Archivo fuente
TextIO.ant

Herencia

Clases base
Any TextReader StreamReader

Constructores

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

Propiedades

Stream BaseStream { get; }
#

read-only

The stream it reads from.

bool EndOfStream { get; }
#

read-only

Whether everything has been read.

Métodos

override Peek() : i32
#

override

override Read() : i32
#

override

override ReadLine() : str?
#

override

override ReadToEnd() : str
#

override

override Close()
#

override

Miembros privados e internos (10)

Stream stream
#

private

u8[] buffer
#

private

i32 at
#

private

i32 end
#

private

bool started
#

private

u8[] pending
#

private

A line that does not fit in what is buffered gathers here.

i32 pendingLength
#

private

Fill() : bool
#

private

Whether there are bytes to read (reading more when the buffer is used up).

Keep(i32 from, i32 count)
#

private

Decode(bool take) : i32
#

private

The code point starting at the next byte, taken when take.

Miembros heredados (5)

Código fuente

StreamReader en Antril, descompilado a partir de su Larva HIR.

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

import System;
import System.Text;

into namespace System.IO
{
	/// Text read from a stream as UTF-8 (a byte order mark at the start is skipped), through a buffer.
	public class StreamReader : TextReader
	{
		Stream stream;
		u8[] buffer;
		i32 at;
		i32 end;
		bool started;

		/// A line that does not fit in what is buffered gathers here.
		u8[] pending;
		i32 pendingLength;

		/// Whether there are bytes to read (reading more when the buffer is used up).
		Fill() : bool
		{
			if (at < end)
				return true;
			at = 0;
			end = stream.Read(buffer, 0, buffer.Length);
			if (!started)
			{
				started = true;
				if (end >= 3 && buffer[0] == 239 && buffer[1] == 187 && buffer[2] == 191)
					at = 3;
			}
			return at < end;
		}

		Keep(i32 from, i32 count)
		{
			if (pendingLength + count > pending.Length)
			{
				i32 capacity = pending.Length * 2;
				if (capacity < pendingLength + count)
					capacity = pendingLength + count;
				u8[] grown = new u8[capacity];
				Array.Copy(pending, 0, grown, 0, pendingLength);
				pending = grown;
			}
			Array.Copy(buffer, from, pending, pendingLength, count);
			pendingLength += count;
		}

		/// The code point starting at the next byte, taken when `take`.
		Decode(bool take) : i32
		{
			if (!Fill())
				return -1;
			i32 b = (i32)buffer[at];
			if (b < 128)
			{
				if (take)
					at++;
				return b;
			}
			i32 extra = b >= 245 ? 0 : b >= 240 ? 3 : b >= 224 ? 2 : b >= 194 ? 1 : 0;
			if (extra == 0)
			{
				if (take)
					at++;
				return 65533;
			}
			if (at + extra >= end)
			{
				i32 left = end - at;
				Array.Copy(buffer, at, buffer, 0, left);
				at = 0;
				end = left;
				i32 read = stream.Read(buffer, end, buffer.Length - end);
				loop (read > 0 && end + read <= extra)
				{
					end += read;
					read = stream.Read(buffer, end, buffer.Length - end);
				}
				end += read;
				if (extra >= end)
				{
					if (take)
						at++;
					return 65533;
				}
			}
			i32 point = b & (extra == 1 ? 31 : extra == 2 ? 15 : 7);
			loop (i32 k = 1..=extra)
			{
				i32 next = (i32)buffer[at + k];
				if ((next & 192) != 128)
				{
					if (take)
						at++;
					return 65533;
				}
				point = point << 6 | next & 63;
			}
			if (take)
				at += extra + 1;
			return point;
		}

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

			new(Stream stream, i32 bufferSize)
			{
				if (!stream.CanRead)
					throw new ArgumentError("StreamReader: the stream cannot be read");
				this.stream = stream;
				buffer = new u8[bufferSize < 16 ? 16 : bufferSize];
				pending = new u8[0];
			}

			new(str path) : (new FileStream(path, FileMode.Open, FileAccess.Read))
			{
			}

			override Peek() : i32 => Decode(false);

			override Read() : i32 => Decode(true);

			override ReadLine() : str?
			{
				if (!Fill())
					return null;
				pendingLength = 0;
				loop (true)
				{
					i32 i = at;
					loop (i < end && buffer[i] != 10)
						i++;
					if (i < end)
					{
						i32 start = at;
						at = i + 1;
						if (pendingLength == 0)
							return Encoding.UTF8.GetString(buffer, start, i > start && buffer[i - 1] == 13 ? i - start - 1 : i - start);
						Keep(start, i - start);
						return Encoding.UTF8.GetString(pending, 0, pending[pendingLength - 1] == 13 ? pendingLength - 1 : pendingLength);
					}
					Keep(at, end - at);
					at = end;
					if (!Fill())
					{
						i32 count = pendingLength > 0 && pending[pendingLength - 1] == 13 ? pendingLength - 1 : pendingLength;
						return Encoding.UTF8.GetString(pending, 0, count);
					}
				}
				return null;
			}

			override ReadToEnd() : str
			{
				pendingLength = 0;
				loop (Fill())
				{
					Keep(at, end - at);
					at = end;
				}
				return Encoding.UTF8.GetString(pending, 0, pendingLength);
			}

			override Close()
			{
				stream.Close();
			}

			/// The stream it reads from.
			Stream BaseStream
			{
				get => stream;
			}

			/// Whether everything has been read.
			bool EndOfStream
			{
				get => !Fill();
			}
	}
}
Esc