skalibs: the siovec header
Keywords: skalibs header siovec struct iovec scatter gather array I/O

libstddjb
libskarnet
skalibs
Software
skarnet.org

# The `skalibs/siovec.h` header

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

## Purpose

These functions manipulate arrays of `struct iovec` containing ranges of bytes, handling them as contiguous arrays. They're used, for instance, in the skalibs implementation of circular buffers.

## Functions

`size_t siovec_len (struct iovec const *v, unsigned int n)`
Returns the sum of the first n `iov_len` fields of the v array - i.e. the total number of bytes contained in the array represented by v of length n.

`size_t siovec_gather (struct iovec const *v, unsigned int n, char *s, size_t max)`
Gathers all the data scattered in ranges described by v of length n into the space pointed to by s. Specifically: the first `v[0].iov_len` bytes pointed to by `v[0].iov_base` bytes are copied to s, then the first `v[1].iov_len` bytes pointed to by `v[1].iov_base` are appended to it, and so on, n times. The function copies no more than `max` bytes. It returns the total amount of bytes copied.

`size_t siovec_scatter (struct iovec const *v, unsigned int n, char const *s, size_t len)`
Scatters len bytes of data from s into the byte ranges represented by array v of length n. (This is the opposite of the `siovec_gather()` function.) The first `v[0].iov_len` bytes of `s` are copied to `v[0].iov_base`, then the following `v[1].iov_len` bytes of s are copied to `v[1].iov_base`, and so on up to len bytes or until if the scatter array is full, i.e. `siovec_len(v, n)` bytes have been copied. The function returns the total amount of bytes copied.

`size_t siovec_deal (struct iovec const *vj, unsigned int nj, struct iovec const *vi, unsigned int ni)`
Copies the data contained in the ranges represented by the array vi of length ni to the ranges represented by the array vj of length nj. The first `vi[0].iov_len` bytes pointed to by `vi[0].iov_base` are copied to `vj[0].iov_base`, up to `vj[0].iov_len` bytes, moving on to `vj[1].iov_base` if it overflows; then the bytes pointed to by `vi[1].iov_base` are copied to what space remains wherever the writing pointer is, and so on until all the bytes in the ranges described by vi have been copied or there is no more room left in the ranges described by vj. The function returns the total amount of bytes copied.

`size_t siovec_seek (struct iovec *v, unsigned int n, size_t len)`
Does the equivalent of `p += len;` if the byte ranges represented by array v of size n were a single byte array pointed by `p`. If `v[0].iov_len` is lesser than len, then `v[0]` is zeroed out (set to `{ .iov_base = 0, .iov_len = 0 }`), `v[0].iov_len` bytes are deduced from len, and the same operation is repeated with `v[1]`, and so on. If every iovec gets zeroed out, the operation stops; but if a `v[i].iov_len` is greater than the remaining amount of bytes to deduce, that amount is substracted from `v[i].iov_len` and added to `v[i].iov_base`. The function returns the total number of bytes that have been deduced.

`unsigned int siovec_trunc (struct iovec *v, unsigned int n, size_t len)`
Truncates the last fields of v of size n so that the byte ranges it represents have a total length of len or less. The `iov_len` field of `v[n-1]` is decreased by len; if it would be negative, then it's zeroed out and the remainder is taken from `v[n-2]` instead, and so on. The function returns the new size of array v with the tailing zeroed out members removed. It can only return 0 if len is 0, which means all of v has been zeroed out.

`size_t siovec_bytechr (struct iovec const *v, unsigned int n, char c)`
Looks for the first occurence of c among the byte ranges represented by the members of v. Returns its cumulative index, i.e. the position that c would have if the byte ranges pointed to by members of v were a single array. If there are no occurences of c, the function retunrs `siovec_len(v, n)`.

`size_t siovec_bytein (struct iovec const *v, unsigned int n, char const *sep, size_t seplen)`
Looks for the first occurence of any byte from the sep array of size seplen among the byte ranges represented by the members of array v of size n, and returns the cumulative index of the first one it finds.

`size_t siovec_search (struct iovec const *v, unsigned int n, char const *needle, size_t nlen)`
Looks for the string (as in array of bytes: null characters are supported) needle of size nlen in the byte ranges represented by the members of array v of size n, and returns the cumulative index of the first occurrence it finds, or `siovec_len(v, n)` if it cannot find one. Split strings are supported: if needle starts at position `v[i].iov_base + pos` but is cut because it reaches `v[i].iov_len` midstring, and the rest of needle is available at `v[i+1].iov_base`, then the function will find it (and return pos plus the sum length of all the v members before i).