# `QuakeServer.Extensions.Store`
[🔗](https://github.com/jaman/quake_server/blob/v0.1.0/lib/quake_server/extensions/store.ex#L1)

FTE's builtins that keep things: hash tables, allocated memory, files, file searches and
string buffers.

Files are read from the game (`QuakeServer.Source`'s optional `read/1` and `list/1`)
and, under `data/`, from the files the program wrote; `fopen` of a name without
`data/` reads `data/name` first, then `name`. Written files are kept in the
host's `ext.written` and, when the host has a `data_dir`, also written there. Each
written file keeps the entity table of its blocks, and a file carried from an earlier
level is read with its entity numbers translated (`QuakeServer.EntityTable`).

State lives in the host's `ext`: `hashes`, `files`, `searches`, `buffers`, each a map
from handle to contents, and `next_handle`. The game's files a search pattern matches
are kept in `listings`, by pattern, for the host's life.

# `buffer_size`

```elixir
@spec buffer_size(map()) :: non_neg_integer()
```

How many places string buffer `buffer` has: one past its highest index, 0 when empty.

# `call`

```elixir
@spec call(map(), integer() | String.t(), non_neg_integer()) :: map()
```

Run storage builtin `builtin` (a number or a name).

# `entry`

```elixir
@spec entry(map(), atom(), integer()) :: term()
```

What handle `handle` of `kind` (`:files`, `:buffers`, `:searches` or `:hashes`) holds, or `nil`.

# `modified`

```elixir
@spec modified(map(), String.t()) :: integer() | nil
```

The modification time of written file `name` under the host's `data_dir`, as seconds since 1970, or `nil`.

# `new_handle`

```elixir
@spec new_handle(map()) :: {map(), pos_integer()}
```

A handle number not yet given out, and the host that has given it.

# `open_buffer`

```elixir
@spec open_buffer(map(), String.t(), binary(), non_neg_integer()) ::
  {map(), pos_integer()}
```

Open `data` as file `name` for the program to read from byte `at`, as FTE's
`PR_QCFile_From_Buffer` hands an engine buffer to the program; returns the host and
the file's handle.

# `open_output`

```elixir
@spec open_output(map(), String.t(), binary()) :: {map(), pos_integer()}
```

Open file `name` for the program to write after `data`, as FTE's `PR_QCFile_From_VFS`
hands it an engine file; closed by the program, it is kept as the program's written
files are. Returns the host and the file's handle.

# `output`

```elixir
@spec output(map(), pos_integer(), String.t()) :: binary()
```

What file `handle`, opened by `open_output/3` as `name`, holds: its text while open,
the written file `name` once the program has closed it.

# `put_entry`

```elixir
@spec put_entry(map(), atom(), integer(), term()) :: map()
```

Make handle `handle` of `kind` hold `value`.

# `read`

```elixir
@spec read(map(), String.t()) :: binary() | nil
```

The bytes of game file `name`, the program's own written files first; `nil` when there is none.

# `remove`

```elixir
@spec remove(map(), String.t()) :: map()
```

Drop the program's written file `name`, from `ext.written` and from the host's `data_dir`.

# `write`

```elixir
@spec write(map(), String.t(), binary()) :: map()
```

Keep `data` as the program's written file `name`: in the host's `ext.written` and,
when the host has a `data_dir`, under it.

# `written?`

```elixir
@spec written?(map(), String.t()) :: boolean()
```

Whether `name` is one of the program's written files, kept or under the host's `data_dir`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
