class · System.IO
MemoryStream
public class MemoryStream : Stream
Bytes kept in an array that grows as it is written (or in a fixed array given to it).
- Kind
- class
- Namespace
- System.IO
- Assembly
- System.Core
- Access
- public
- Source file
Stream.ant
Inheritance
Constructors
Properties
How many bytes fit before it grows.
Methods
override Seek(i64 offset, SeekOrigin origin) : i64
#
override Close()
#
A copy of its bytes.
The array it keeps its bytes in (Length of them are the stream's).
Writes all its bytes into destination.
Private and internal members (13)
Inherited members (12)
Flushmethod from StreamReadmethod from StreamWritemethod from StreamReadExactlymethod from StreamReadToEndmethod from StreamCopyTomethod from StreamCopyTomethod from StreamGetTypemethod from AnyUndescribedmethod from AnyToStringmethod from AnyHashmethod from Anydestroymethod from Any
Source
MemoryStream as Antril, decompiled from its Larva HIR.
// System.IO.MemoryStream — System.Core (decompiled from Larva HIR)
import System;
into namespace System.IO
{
/// Bytes kept in an array that grows as it is written (or in a fixed array given to it).
public class MemoryStream : Stream
{
u8[] data;
i32 length;
i32 position;
bool writable;
bool growable;
bool open;
/// Where a write can go without the slow path: data.Length when open and writable, else 0.
i32 room;
/// The throw is kept out of the methods that check (so they stay small enough to inline).
[NoInline]
static Closed()
{
throw new IOError("the stream is closed");
}
[NoInline]
static ReadOnly()
{
throw new IOError("the memory stream is read-only");
}
Check()
{
if (!open)
Closed();
}
/// Room for at least `needed` bytes.
Reserve(i32 needed)
{
if (needed > data.Length)
Grow(needed);
}
[NoInline]
Grow(i32 needed)
{
if (!growable)
throw new IOError("the memory stream cannot grow");
i32 capacity = data.Length < 256 ? 256 : data.Length * 2;
if (capacity < needed)
capacity = needed;
u8[] grown = new u8[capacity];
Array.Copy(data, 0, grown, 0, length);
data = grown;
room = capacity;
}
[NoInline]
WriteByteSlow(u8 value)
{
Check();
if (!writable)
ReadOnly();
Reserve(position + 1);
loop (i32 i = length..position)
data[i] = 0;
data[position] = value;
position++;
if (position > length)
length = position;
}
public:
new() : (0)
{
}
new(i32 capacity)
{
data = new u8[capacity];
writable = true;
growable = true;
open = true;
room = capacity;
}
/// Over `buffer` (its bytes are the stream's, it does not grow).
new(u8[] buffer) : (buffer, true)
{
}
new(u8[] buffer, bool writable)
{
data = buffer;
length = buffer.Length;
this.writable = writable;
open = true;
room = writable ? buffer.Length : 0;
}
override Read(u8[] buffer, i32 offset, i32 count) : i32
{
Check();
i32 n = length - position;
if (n > count)
n = count;
if (n <= 0)
return 0;
if (n <= 16 && offset >= 0 && offset + n <= buffer.Length)
{
loop (i32 i = 0..n)
buffer[offset + i] = data[position + i];
}
else
{
Array.Copy(data, position, buffer, offset, n);
}
position += n;
return n;
}
override ReadByte() : i32
{
i32 at = position;
if (at < length && open)
{
position = at + 1;
return (i32)data[at];
}
Check();
return -1;
}
override Write(u8[] buffer, i32 offset, i32 count)
{
Check();
if (!writable)
ReadOnly();
i32 end = position + count;
Reserve(end);
loop (i32 i = length..position)
data[i] = 0;
if (count <= 16 && offset >= 0 && offset + count <= buffer.Length)
{
loop (i32 i = 0..count)
data[position + i] = buffer[offset + i];
}
else
{
Array.Copy(buffer, offset, data, position, count);
}
position = end;
if (end > length)
length = end;
}
override WriteByte(u8 value)
{
i32 at = position;
if (at < room && at <= length)
{
data[at] = value;
position = at + 1;
if (at == length)
length = at + 1;
return;
}
WriteByteSlow(value);
}
override Seek(i64 offset, SeekOrigin origin) : i64
{
Check();
i64 at = origin == SeekOrigin.Begin ? offset : origin == SeekOrigin.Current ? (i64)position + offset : (i64)length + offset;
if (at < 0 || at > 2147483647)
throw new IOError("MemoryStream.Seek: before the start");
position = (i32)at;
return at;
}
override SetLength(i64 newLength)
{
Check();
if (!writable)
throw new IOError("the memory stream is read-only");
if (newLength < 0 || newLength > 2147483647)
throw new ArgumentError("MemoryStream.SetLength: out of range");
i32 n = (i32)newLength;
Reserve(n);
loop (i32 i = length..n)
data[i] = 0;
length = n;
if (position > length)
position = length;
}
override Close()
{
open = false;
room = 0;
}
/// A copy of its bytes.
ToArray() : u8[]
{
u8[] copy = new u8[length];
Array.Copy(data, 0, copy, 0, length);
return copy;
}
/// The array it keeps its bytes in (Length of them are the stream's).
GetBuffer() : u8[] => data;
/// Writes all its bytes into `destination`.
WriteTo(Stream destination)
{
destination.Write(data, 0, length);
}
override bool CanRead
{
get => open;
}
override bool CanWrite
{
get => open && writable;
}
override bool CanSeek
{
get => open;
}
override i64 Length
{
get => length;
}
override i64 Position
{
get => position;
set
{
if (value < 0 || value > 2147483647)
throw new ArgumentError("MemoryStream.Position: out of range");
position = (i32)value;
}
}
/// How many bytes fit before it grows.
i32 Capacity
{
get => data.Length;
}
}
}