# Trimming and Translating

> StringZilla for C

`#include <stringzilla/capabilities.h>`

`#include <stringzilla/strings.h>`

## sz_kernel_strings_lookup_t

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

```c
typedef sz_status_t(*) sz_kernel_strings_lookup_t(sz_strings_view_t const *, sz_size_t const *, sz_size_t, sz_cptr_t, sz_allocator_t *, sz_strings_span_t *, sz_stream_t);
```

## sz_strings_lookup_best

Maps every byte of `strings[order[i]]`, or the first `count` strings, through a 256-entry Look-Up Table ____(LUT) into a tape, the same as `for (char &c : text) c = lut[c]`.

```c
sz_status_t sz_strings_lookup_best(
    sz_strings_view_t const *strings,
    sz_size_t const *order,
    sz_size_t count,
    char const lut,
    sz_allocator_t *allocator,
    sz_strings_span_t *tape,
    sz_capability_t capabilities,
    sz_stream_t stream);
```

- `sz_strings_lookup` backends: serial, haswell, icelake, neon, sve, rvv, v128, v128relaxed, loongsonasx, powervsx, cuda, rocm, metal

Allocates and reuses `tape` like [`sz_strings_to_tape_best`](https://www.unum.cloud/docs/stringzilla/c/sorting-and-sets.md#sz_strings_to_tape_best). The mapping keeps every length, so a span over the caller's own buffers of matching sizes needs no allocator, and a span that `strings` views is mapped in place.

Can be used to implement some form of string normalization, partially masking punctuation marks, or converting between different character sets, like uppercase or lowercase. Surprisingly, also has broad implications in image processing, where channel transformations often use LUTs.

Lowercasing a buffer in place, as a tape of one string:

```
#include  // for tolower
#include 
int main() {
     sz_capability_t capabilities;
     char to_lower_lut[256];
     for (int i = 0; i < 256; ++i) to_lower_lut[i] = tolower(i);
     char buffer[3] = {'A', 'B', 'C'};
     sz_u32_t offsets[2] = {0, 3};
     sz_strings_span_t tape;
     tape.layout = sz_strings_u32_tape_k, tape.count = 1;
     tape.data.u32_tape.data = buffer, tape.data.u32_tape.offsets = offsets;
     sz_strings_view_t strings;
     sz_strings_from_span(&tape, &strings);
     sz_capabilities_enabled_cpu(&capabilities);
     sz_strings_lookup_best(&strings, NULL, 1, to_lower_lut, NULL, &tape, capabilities, NULL);
     return buffer[0] == 'a' && buffer[1] == 'b' && buffer[2] == 'c' ? 0 : 1;
}
```

- `strings` (in): The strings to map, in any layout.
- `order` (in): Indices into `strings`, possibly repeated, or null for the first `count`.
- `count` (in): Number of strings to write.
- `lut` (in): The table to map through, exactly __256__ bytes long.
- `allocator` (in): Where the blocks of `tape` come from and return to.
- `tape` (inout): A zeroed span, one an earlier call produced, or the one `strings` views.
- `capabilities` (in): One device's capabilities, like `sz_capabilities_enabled_cpu` reports.
- `stream` (in): Null on the CPU, or the GPU stream of that device to queue on.

See also: Lookup table: [https://en.wikipedia.org/wiki/Lookup_table](https://en.wikipedia.org/wiki/Lookup_table)

## sz_strings_lookup_init_lower

Initializes a lookup table for converting ASCII characters to lowercase.

```c
void sz_strings_lookup_init_lower(char lut);
```

ASCII characters [A, Z] map to decimals [65, 90], and [a, z] map to [97, 122]. So there are 26 English letters, shifted by 32 values, meaning that a conversion can be done by flipping the 5th bit of each inappropriate character byte. This, however, breaks for extended ASCII, so a different solution is needed.

- `lut` (out): Lookup table to be initialized. Must be exactly 256 bytes long.

See also: SWAR swap case: [http://0x80.pl/notesen/2016-01-06-swar-swap-case.html](http://0x80.pl/notesen/2016-01-06-swar-swap-case.html)

## sz_strings_lookup_init_upper

Initializes a lookup table for converting ASCII characters to uppercase.

```c
void sz_strings_lookup_init_upper(char lut);
```

ASCII characters [A, Z] map to decimals [65, 90], and [a, z] map to [97, 122]. So there are 26 English letters, shifted by 32 values, meaning that a conversion can be done by flipping the 5th bit of each inappropriate character byte. This, however, breaks for extended ASCII, so a different solution is needed.

- `lut` (out): Lookup table to be initialized. Must be exactly 256 bytes long.

See also: SWAR swap case: [http://0x80.pl/notesen/2016-01-06-swar-swap-case.html](http://0x80.pl/notesen/2016-01-06-swar-swap-case.html)

## sz_strings_lookup_init_ascii

Initializes a lookup table for converting bytes to ASCII characters.

```c
void sz_strings_lookup_init_ascii(char lut);
```

- `lut` (out): Lookup table to be initialized. Must be exactly 256 bytes long.

