# Splitting and Partitioning

> StringZilla for C

`#include <stringzilla/strings.h>`

## sz_split_kind_t

How a split ends its parts.

```c
enum sz_split_kind_t
```

- `sz_split_each_k` = `0`: Every delimiter ends a part, so neighbouring delimiters leave empty parts, as `str.split(sep)` does.
- `sz_split_runs_k` = `1`: A run of delimiters ends one part and empty parts are skipped, as `str.split()` does.

## sz_kernel_strings_split_t

Signature of the [`sz_strings_split_best`](#sz_strings_split_best) kernels, kept beside the enum it takes.

```c
typedef sz_status_t(*) sz_kernel_strings_split_t(sz_cptr_t, sz_size_t, sz_byteset_t const *, sz_split_kind_t, sz_allocator_t *, sz_strings_span_t *, sz_stream_t);
```

## sz_kernel_strings_split_lines_t

Signature of the [`sz_strings_split_lines_best`](#sz_strings_split_lines_best) kernels.

```c
typedef sz_status_t(*) sz_kernel_strings_split_lines_t(sz_cptr_t, sz_size_t, sz_allocator_t *, sz_strings_span_t *, sz_stream_t);
```

## sz_kernel_strings_join_t

Signature of the [`sz_strings_join_best`](#sz_strings_join_best) kernels.

```c
typedef sz_status_t(*) sz_kernel_strings_join_t(sz_strings_view_t const *, sz_size_t, sz_size_t, sz_string_view_t const *, sz_string_view_t, sz_ptr_t, sz_size_t *, sz_stream_t);
```

## sz_strings_split_best

Splits `text` at the bytes of `delimiters` into a tape of the parts between them.

```c
sz_status_t sz_strings_split_best(
    sz_cptr_t text,
    sz_size_t length,
    sz_byteset_t const *delimiters,
    sz_split_kind_t kind,
    sz_allocator_t *allocator,
    sz_strings_span_t *tape,
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_strings_split` backends: serial, icelake, neon

With [`sz_split_each_k`](#sz_split_each_k) a text of `n` delimiters always makes `n` + 1 parts, like Python's `bytes.split(sep)` for a one-byte `sep`, generalized to a set. With [`sz_split_runs_k`](#sz_split_runs_k) leading and trailing runs make no parts, like `bytes.split()` when the set is ASCII whitespace. Measures the parts first, then writes blocks of exactly their sizes, reusing those of `tape` like [`sz_strings_to_tape_best`](https://www.unum.cloud/docs/stringzilla/c/sorting-and-sets.md#sz_strings_to_tape_best) unless `text` lies in them; like every collection verb it is atomic.

- `text` (in): The bytes to split, null only when `length` is zero.
- `length` (in): Number of bytes in `text`.
- `delimiters` (in): The bytes that separate the parts.
- `kind` (in): Whether every delimiter ends a part, or every run of them.
- `allocator` (in): Where the blocks of `tape` come from and return to.
- `tape` (inout): A zeroed span, or one an earlier call produced.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null, as only CPUs split.

## sz_strings_split_lines_best

Splits `text` at Unicode line breaks, CR LF as one, into a tape of lines without breaks.

```c
sz_status_t sz_strings_split_lines_best(
    sz_cptr_t text,
    sz_size_t length,
    sz_allocator_t *allocator,
    sz_strings_span_t *tape,
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_strings_split_lines` backends: serial, icelake, neon

The breaks are those of Python's `str.splitlines()` over UTF-8: LF, VT, FF, CR, FS, GS, RS, CR LF, NEL, LS and PS, and a final break leaves no empty line after it. Allocates and reuses `tape` like [`sz_strings_split_best`](#sz_strings_split_best), and like every collection verb it is atomic.

- `text` (in): The UTF-8 bytes to split, null only when `length` is zero.
- `length` (in): Number of bytes in `text`.
- `allocator` (in): Where the blocks of `tape` come from and return to.
- `tape` (inout): A zeroed span, or one an earlier call produced.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null, as only CPUs split.

See also: Python's `str.splitlines`: [https://docs.python.org/3/library/stdtypes.html](https://docs.python.org/3/library/stdtypes.html)

## sz_strings_join_best

Writes row r of `columns` as `frames[0] + columns[0][r] + frames[1] + … + columns[n-1][r] + frames[n]`, with `between` written between rows, into `output`; a null `output` only measures into `length`.

```c
sz_status_t sz_strings_join_best(
    sz_strings_view_t const *columns,
    sz_size_t columns_count,
    sz_size_t rows,
    sz_string_view_t const *frames,
    sz_string_view_t between,
    sz_ptr_t output,
    sz_size_t *length,
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_strings_join` backends: serial, icelake, neon

Serializes columns as CSV lines, JSON arrays or SQL value lists without a string per cell, and joins one column with an empty frame on each side like Python's `str.join`.

- `columns` (in): The `columns_count` columns of `rows` strings each, in any layouts.
- `columns_count` (in): Number of columns, one less than the number of `frames`.
- `rows` (in): Number of strings in every column.
- `frames` (in): The strings written before, between and after the cells of every row.
- `between` (in): The string written between consecutive rows.
- `output` (out): Room for exactly `length` bytes, or null to measure them.
- `length` (inout): The bytes the join takes: written when `output` is null, read otherwise.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null, as only CPUs join.

Statuses: - [`sz_bad_alloc_k`](https://www.unum.cloud/docs/stringzilla/c/types.md#sz_bad_alloc_k) Measuring overflows the length.

