skalibs: the bytestr header
Keywords: skalibs header bytestr byte string memory

libstddjb
libskarnet
skalibs
Software
skarnet.org

# The `skalibs/bytestr.h` header

The following functions are declared in the `skalibs/bytestr.h` header and implemented in the `libskarnet.a` or `libskarnet.so` library.

## Purpose

These functions handle arrays of bytes (strings). They are similar to their counterparts from the standard string.h header, but they return indices instead of pointers.

`byte_*` functions and macros work with strings that are not necessarily null-terminated, but require sizes of the strings to be passed. On the contary, `str_*` family accepts null-terminated strings. `case_*` functions and macros are like their `str_*` counterparts, but are case-insensitive.

## Functions

`size_t byte_chr (char const *s, size_t n, int c)`
Looks for the first occurrence of byte c in array s of size n. Returns its index, or n if there is no such byte in s.

`size_t byte_rchr (char const *s, size_t n, int c)`
Looks for the last occurrence of byte c in array s of size n. Returns its index, or n if there is no such byte in s.

`size_t byte_in (char const *s, size_t n, char const *sep, size_t len)`
Looks for the first occurrence of any byte from array sep of size len in array s of size n. Returns the index of such an occurrence, or n if there are no bytes from sep in s.

`size_t byte_count (char const *s, size_t len, char b)`
Returns the amount of occurrences of byte b in string s of size len.

`size_t byte_search (char const *haystack, size_t hlen, char const *needle, size_t nlen)`
Looks for the first occurrence of string needle of size nlen in string haystack of size hlen. Returns the index of the first byte of that occurrence, or `hlen + 1 - nlen` if needle cannot be found in haystack.

`void byte_zzero (char *s, size_t n)`
Zeroes n bytes of memory beginning with address s. Special measures are taken to prevent the compiler from optimizing out the call:

- If the `explicit_bzero` function is present on the system, it is used. Calls to this function are guaranteed not to be removed by the compiler.
- Otherwise, `byte_zzero` performs a normal `memset` followed by a special no-op function with a weak alias in order to trick the compiler.

This is useful for erasing sensitive data before returning from some function, typically in cryptography settings. Compilers usually remove `memset` calls since these have no observable effect for the rest of the code.

`size_t str_chr (char const *s, int c)`
Looks for the first occurrence of byte c in null-terminated string s. Returns the index of this occurrence, or the length of the string if there is no such byte in s.

`size_t str_rchr (char const *s, int c)`
Looks for the last occurrence of byte c in null-terminated string s. Returns the index of this occurrence, or the length of the string if there is no such byte in s.

`int str_start (char const *s, char const *t)`
Returns 1 if (null-terminated) string s begins with (null-terminated) string t, and 0 otherwise.

`size_t str_strn (char const *haystack, size_t hlen, char const *needle, size_t nlen)`
Looks for the first occurrence of string needle of size nlen in string haystack of size hlen. Returns the index of the first character in this occurrence, or hlen if needle is not present in haystack.

`void case_lowers (char *s)`
Turns all capital letters in null-terminated string s into lowercase letters. This function only works with ASCII symbols.

`void case_lowerb (char *s, size_t len)`
Turns all capital letters in string s of size len into lowercase letters. This function only works with ASCII symbols.

`void case_uppers (char *s)`
Turns all lowercase letters in null-terminated string s into capital letters. This function only works with ASCII symbols.

`void case_upperb (char *s, size_t len)`
Turns all lowercase letters in string s of size len into capital letters. This function only works with ASCII symbols.

`int case_startb (char const *s, size_t slen, char const *t)`
Returns 1 if string s of size slen begins with null-terminated string t, ignoring case, and 0 otherwise.

`size_t case_str (char const *haystack, char const *needle)`
Looks for the first occurrence of null-terminated string needle in null-terminated string haystack, ignoring case while comparing bytes. Returns the index of the first byte of this occurrence or the length of haystack if needle is not presented in haystack.

## Macros

These macros are either wrappers around functions described above or C standard library functions. They only exist for compatibility purposes. Programmers are expected to use the standard functions directly: in the rare case where a standard function interface is good, it is best to use it.

`byte_copy(to, n, from)`
`byte_copyr(to, n, from)`
Same as `memmove(to, from, n)`.

`byte_diff(a, n, b)`
Same as `memcmp(a, b, n)`.

`byte_zero(p, n)`
Same as `memset(p, 0 ,n)`. There is a caveat in zeroing memory range with `memset` — compiler may omit the call to `memset` if it is called in the end of function. If you need to destroy sensitive data, use `byte_zzero` instead.

`str_len(s)`
Same as `strlen(s)`.

`str_nlen(s)`
Same as `strnlen(s)`.

`str_diff(s1, s2)`
Same as `strcmp(s1, s2)`.

`str_diffn(s1, s2, n)`
Same as `strncmp(s1, s2, n)`.

`str_copy(to, from)`
Copies null-terminated string from, including null terminator, to buffer to. Returns the length of the string.

`case_diffs(s1, s2)`
Same as `strcasecmp(s1, s2)`.

`case_diffn(s1, s2, n)`
Same as `strcasecmp(s1, s2, n)`.

`byte_equal(s, n, t)`
Same as `!memcmp(s, t, n)`.

`str_diffb(a, n, b)`
Same as `strncmp(a, b, n)`.

`str_equal(s, t)`
Same as `!strcmp(s, t)`.

`case_diffb(a, n, b)`
Same as `strncasecmp(a, b, n)`.

`case_equals(a, b)`
Same as `!strcasecmp(a, b)`.

`case_equalb(a, n, b)`
Same as `!strncasecmp(a, b, n)`.

`case_starts(s, t)`
Same as `case_startb(s, strlen(s), t)`.