# Buffers

The type `core.io.Buffer` is used to store and transfer binary data in the IO library. In particular, it plays a central role when reading from and writing to streams. In addition to this, it can also be used in other contexts where it is necessary to store binary data without attaching a particular meaning to any of the bytes.

A `core.io.Buffer` is a value and is therefore handled by value. To avoid repeatedly copying large amounts of data, the `Buffer` implements by-reference semantics internally. This means that making a copy of a `Buffer` object creates two instances that refer to the same data, just as a class type would behave. Data is, however, copied whenever a buffer is passed between threads in order to avoid shared data. Because of these properties, it is typically a good idea to design interfaces that operate on `Buffer`s to accept a buffer, and return a modified copy of the buffer. If the interface internally operates on and returns the same buffer, no copies will be made. The interface will, however, still function correctly if the system needs to copy data at any point. The `IStream` and `OStream` classes are designed according to this idea.

Each `Buffer` instance stores three things: a buffer large enough for a pre-determined number of bytes, the size of said buffer, and how many bytes are considered used. The number of bytes is ignored by the `Buffer` itself in most cases, and is rather designed as a convenient ways for other parts of the system to communicate how much of the buffer was actually filled.

The `Buffer` type has the following members. Note that some of them are implemented as free functions due to technicalities in the interface between Storm and C++. In languages like Basic Storm it is, however, possible to treat them as if they were members anyway.

## Member Functions

- `init()`

  Default constructor. Create an empty buffer. Use the free function `buffer` to create a buffer with a non-zero size.

- `core.Nat count()`

  Get the number of bytes in the buffer in total.

- `core.Nat filled()`

  Get how many bytes from the beginning are used in the buffer. The buffer itself generally does not use the value. Rather, it is used as a universal marker for how much of the buffer is used for actual data, and how much is free.

- `void filled(core.Nat p)`

  Set the number of bytes that are used. Limits the value to be maximum `count`. Marked as an assign functions, so that `filled` can be used as a member variable in languages like Basic Storm.

- `core.Nat free()`

  Get the number of free bytes in the buffer, based on the `filled` member.

- `core.Byte& [](core.Nat id)`

  Access individual bytes.

- `core.Bool empty()`

  Is the buffer empty, according to the `filled` member?

- `core.Bool full()`

  Is the buffer full, according to the `filled` member?

- `core.Bool push(core.Byte data)`

  Put a single byte at the end of the buffer and increases `filled`. Returns `false` if there is no room for the data.

- `void shift(core.Nat n)`

  Shift data `n` locations towards the front of the buffer. This effectively removes the first `n` bytes in the buffer. Assumes that only data up until `filled` are relevant and updates `filled` accordingly. Note that this requires copying bytes in the buffer. Removing small amounts of data frequently is therefore expensive.

- `void toS(core.StrBuf to)`

  Output the buffer to a string buffer. Since a buffer is an unformatted sequence of bytes, it is outputted as a hex dump. The location of filled is marked with a pipe (`|`). As such, buffers are a convenient way to output data in hexadecimal form.

  The system provides an overload of `toS` for buffers, so it is possible to call `Buffer().toS()`.

- `void outputMark(core.StrBuf to, core.Nat markAt)`

  Output the buffer, like `toS`, but including a second mark at the specified location. This location is indicated with a `>` character.

## Free Functions

The following functions are implemented outside of `Buffer` for technical reasons. Most of them can be considered proper member functions of the `Buffer` type.

- `core.io.Buffer buffer(core.Nat count)`

  Create a buffer with room for `count` bytes. It will be initially empty.

- `core.io.Buffer cut(core.io.Buffer src, core.Nat from)`

  Analogous to the `cut` functions in `Str`. Extracts a range of bytes from a buffer.

- `core.io.Buffer cut(core.io.Buffer src, core.Nat from, core.Nat to)`

  Analogous to the `cut` functions in `Str`. Extracts a range of bytes from a buffer.

- `core.io.Buffer grow(core.io.Buffer src, core.Nat newCount)`

  Grow a buffer to the specified size. Copies the content and the `filled` member from `src`.

- `core.io.Buffer toUtf8(core.Str str)`

  Encode a string into UTF-8. It is also possible to use text streams for this, and they may be more convenient in certain situations.

- `core.Str fromUtf8(core.io.Buffer b)`

  Interpret a buffer as UTF-8 and convert it into a string. It is also possible to use text streams for this, and they may be more convenient in certain situations.