std/core/buffer
std/core/src/buffer.trb
Buffer, the heap storage primitive: a growable sequence whose writes happen in place while the storage has one
owner.
It lives in std/core next to Array for the same reason: a collection is a data structure written on top of a
storage primitive, and Buffer is that primitive for everything that grows. It implements only what std/core owns
Iterate,Length,MutableIndexandMutableSlice- and leaves theListvocabulary tostd/collections, which declares that aBufferis aList: it is accepted wherever aListis asked for.
Related
type Buffer
native type Buffer<Item> with Iterate<Item>, Length, MutableIndex<Int, Item>, MutableSlice, From<Iterate<Item>>
A growable sequence on the heap, with an in-place promise and an O(1) Buffer.swapRemove.
The in-place promise. buffer[index] = value, Buffer.set, Buffer.append, Buffer.insert,
Buffer.removeAt, Buffer.swapRemove, Buffer.replace, Buffer.reverse and Buffer.clear change the storage in
place whenever it has one owner. They copy it once (copy on write) only when the Buffer value has been copied -
const other = buffer, passed or captured by value - and is then written. Nothing stronger is promised: a copy that
is alive makes the next write O(n), so keep a big buffer in one var owner and pass it as a var parameter.
It is a value like every other: a copy never sees a later write to the original, and the other way round.
Examples
var column: Buffer<Int> = Buffer.withCapacity 4
column.append 10
column.append 20
column.append 30
column.append 40
column[0] = 11
print column.swapRemove(1)
print column
Pitfalls
Buffer.slice copies. A slice of an ArrayList shares its storage, which turns the next write to either side into a
copy; a Buffer is the type for code that cannot afford that, so its slice owns storage of its own.
Related
Array- the inline storage primitive.List.slice- the shared slice aBufferdoes not have.
fn from
static fn from(items: Iterate<Item>): Self
The buffer holding items in the order they are iterated.
Ordinary TorbScript for the reason ArrayList.from gives: items is a trait-typed value of the program, which a
function of the runtime cannot walk.
Examples
const buffer: Buffer<Int> = Buffer.from([1, 2, 3])
print buffer
fn withCapacity
native static fn withCapacity(capacity: Int): Self
An empty buffer, with room for capacity items before it has to grow again. The capacity is a hint.
fn holdsClose
native static fn holdsClose(): Bool
Whether an item of this buffer may hold a Close value. It is a constant of the instantiated item type, so a
branch on it for an item that cannot hold one is removed from the program.
fn length
native fn length(): Int
How many items there are.
fn get
native fn get(index: Int): Item?
The item at index, or None if it is out of bounds, a negative index included. buffer[index] panics instead;
see Buffer.at.
fn at
fn at(index: Int): Item
The item at index. This is buffer[index].
Panics
When index is out of bounds, with index <index> is out of bounds for a length of <count> - the message of
ArrayList.at. Buffer.get is the same question with an Option for an answer.
fn set
native var fn set(index: Int, value: Item)
Changes the item at index, in place while the storage has one owner. buffer[index] = value goes through this;
see MutableIndex.set.
Panics
When index is out of bounds, with the message of Buffer.at.
fn update
var fn update(index: Int, change: (var element: Item) => Void)
Runs change on the item at index, in the buffer's own storage: no copy of the item is made and none is held
while change runs.
Panics
When index is out of bounds, with the message of Buffer.at, before change runs.
fn append
native var fn append(value: Item)
Appends an item at the end, in place while the storage has one owner.
fn insert
native var fn insert(index: Int, value: Item)
Inserts value at index and shifts everything at or after it one position on. index may be the length, which
appends.
Panics
When index is negative or after the end, with the message of Buffer.at.
fn removeAt
native var fn removeAt(index: Int): Item?
Removes the item at index, shifts everything after it one position back and answers it, or None if index is
out of range. Buffer.swapRemove is the O(1) twin that does not keep the order.
fn swapRemove
var fn swapRemove(index: Int): Item?
Removes the item at index and answers it, by moving the last item into its slot: O(1), the order is not kept,
and nothing ever shifts. Reach for it where the order of the items does not matter - an ECS column, a pool - and
for Buffer.removeAt where it does.
It answers None, and changes nothing, where index is out of range. On the last index it is
removeAt(length() - 1).
Examples
var numbers = Buffer.from([10, 20, 30, 40])
print numbers.swapRemove(1)
print numbers
print numbers.swapRemove(3)
print numbers
Panics
Never: the index is checked first, so the set it ends in is always in range.
fn slice
fn slice(range: Bounds<Int>): Self
The items the range covers, as a buffer of their own: buffer[1..3]. The result is a copy, so writing the
original afterwards does not touch the slice and the other way round, and neither write is a second copy.
Examples
var numbers = Buffer.from([1, 2, 3, 4, 5])
const middle = numbers[1..4]
numbers[2] = 0
print middle
print numbers
Panics
When the range reaches outside the buffer, or starts after it ends, with the messages of List.slice.
fn replace
var fn replace(range: Bounds<Int>, values: Self)
Replaces the items of range with values, in place while the storage has one owner; the two need not be the same
length. What buffer[from..to] = values goes through; see MutableSlice.replace.
Panics
When the range reaches outside the buffer, or starts after it ends, with the messages of List.slice.
fn reverse
native var fn reverse()
Reverses the order, in place while the storage has one owner.
fn clear
native var fn clear()
Removes every item, in place while the storage has one owner.
fn iterate
fn iterate(): Iterator<Item>
A cursor over the items, front to back: see BufferIterator.
fn keys
fn keys(): Iterate<Int>
The indices of the items, 0..length(): what for var item in items visits to change every item in place.