skalibs

Mirror/fork of https://skarnet.org/software/skalibs/
git clone https://ccx.te2000.cz/git/skalibs
Log | Files | Refs | README | LICENSE

commit ee2aeefa170b9806e719723f94ba933c90a9ae8b
parent cdb1f983a89439ad11d51fe96fc5838cca9d1b3f
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date:   Wed,  4 Jan 2023 16:32:21 +0000

 Add siovec doc, fix siovec_trunc, credit Ermine

Signed-off-by: Laurent Bercot <ska@appnovation.com>

Diffstat:
MAUTHORS | 1+
Mdoc/libstddjb/siovec.html | 115++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/libstddjb/siovec_trunc.c | 10+++++-----
3 files changed, 120 insertions(+), 6 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -13,6 +13,7 @@ Contributors: Shengjing Zhu <zhsj@debian.org> Colin Booth <colin@heliocat.net> Petr Vanek <arkamar@atlas.cz> + Peter Shkenev <mustela@erminea.space> Thanks to: Jean Marot <jean.marot@skarnet.org> diff --git a/doc/libstddjb/siovec.html b/doc/libstddjb/siovec.html @@ -21,7 +21,120 @@ <h1> The <tt>skalibs/siovec.h</tt> header </h1> <p> - TODO: write this documentation page. (Sorry!) + The following functions are declared in the <tt>skalibs/siovec.h</tt> header +and implemented in the <tt>libskarnet.a</tt> or <tt>libskarnet.so</tt> library. +</p> + +<h2> Purpose </h2> + +<p> + These functions manipulate arrays of <tt>struct iovec</tt> containing +ranges of bytes, handling them as contiguous arrays. They're used, for +instance, in the skalibs implementation of circular buffers. +</p> + +<h2> Functions </h2> + +<p> +<code> size_t siovec_len (struct iovec const *v, unsigned int n) </code> <br> +Returns the sum of the first <em>n</em> <tt>iov_len</tt> fields of the +<em>v</em> array - i.e. the total number of bytes contained in the +array represented by <em>v</em> of length <em>n</em>. +</p> + +<p> +<code> size_t siovec_gather (struct iovec const *v, unsigned int n, char *s, size_t max) </code> <br> +Gathers all the data scattered in ranges described by <em>v</em> of length +<em>n</em> into the space pointed to by <em>s</em>. +Specifically: the first <tt>v[0].iov_len</tt> bytes pointed to by +<tt>v[0].iov_base</tt> bytes are copied to <em>s</em>, then the first +<tt>v[1].iov_len</tt> bytes pointed to by <tt>v[1].iov_base</tt> are +appended to it, and so on, <em>n</em> times. +The function copies no more than <tt>max</tt> bytes. It +returns the total amount of bytes copied. +</p> + +<p> +<code> size_t siovec_scatter (struct iovec const *v, unsigned int n, char const *s, size_t len) </code> <br> +Scatters <em>len</em> bytes of data from <em>s</em> into the byte ranges +represented by array <em>v</em> of length <em>n</em>. (This is the opposite +of the <tt>siovec_gather()</tt> function.) +The first <tt>v[0].iov_len</tt> bytes of +<tt>s</tt> are copied to <tt>v[0].iov_base</tt>, then the following +<tt>v[1].iov_len</tt> bytes of <em>s</em> are copied to +<tt>v[1].iov_base</tt>, and so on up to <em>len</em> bytes or until +if the scatter array is full, i.e. <tt>siovec_len(v, n)</tt> bytes +have been copied. The function returns the total amount of bytes copied. +</p> + +<p> +<code> size_t siovec_deal (struct iovec const *vj, unsigned int nj, struct iovec const *vi, unsigned int ni) </code> <br> +Copies the data contained in the ranges represented by the array <em>vi</em> of +length <em>ni</em> to the ranges represented by the array <em>vj</em> of length +<em>nj</em>. +The first <tt>vi[0].iov_len</tt> bytes pointed to by <tt>vi[0].iov_base</tt> +are copied to <tt>vj[0].iov_base</tt>, up to <tt>vj[0].iov_len</tt> bytes, +moving on to <tt>vj[1].iov_base</tt> if it overflows; then the bytes pointed +to by <tt>vi[1].iov_base</tt> are copied to what space remains wherever the +writing pointer is, and so on until all the bytes in the ranges described by +<em>vi</em> have been copied or there is no more room left in the ranges +described by <em>vj</em>. +The function returns the total amount of bytes copied. +</p> + +<p> +<code> size_t siovec_seek (struct iovec *v, unsigned int n, size_t len) </code> <br> +Does the equivalent of <tt>p += len;</tt> if the byte ranges represented by +array <em>v</em> of size <em>n</em> were a single byte array pointed by <tt>p</tt>. +If <tt>v[0].iov_len</tt> is lesser than <em>len</em>, then <tt>v[0]</tt> is +zeroed out (set to <tt>{ .iov_base = 0, .iov_len = 0 }</tt>), <tt>v[0].iov_len</tt> +bytes are deduced from <em>len</em>, and the same operation is repeated with +<tt>v[1]</tt>, and so on. If every iovec gets zeroed out, the operation stops; +but if a <tt>v[i].iov_len</tt> is greater than the +remaining amount of bytes to deduce, that amount is substracted from +<tt>v[i].iov_len</tt> and added to <tt>v[i].iov_base</tt>. The function returns +the total number of bytes that have been deduced. +</p> + +<p> +<code> unsigned int siovec_trunc (struct iovec *v, unsigned int n, size_t len) </code> <br> +Truncates the last fields of <em>v</em> of size <em>n</em> so that the byte +ranges it represents have a total length of <em>len</em> or less. The +<tt>iov_len</tt> field of <tt>v[n-1]</tt> is decreased by len; if it would +be negative, then it's zeroed out and the remainder is taken from <tt>v[n-2]</tt> +instead, and so on. The function returns the new size of array <em>v</em> +with the tailing zeroed out members removed. It can only return 0 if <em>len</em> +is 0, which means all of <em>v</em> has been zeroed out. +</p> + +<p> +<code> size_t siovec_bytechr (struct iovec const *v, unsigned int n, char c) </code> <br> +Looks for the first occurence of <em>c</em> among the byte ranges represented by the members +of <em>v</em>. Returns its cumulative index, i.e. the position that <em>c</em> +would have if the byte ranges pointed to by members of <em>v</em> were a +single array. If there are no occurences of <em>c</em>, the function retunrs +<tt>siovec_len(v, n)</tt>. +</p> + +<p> +<code> size_t siovec_bytein (struct iovec const *v, unsigned int n, char const *sep, size_t seplen) </code> <br> +Looks for the first occurence of any byte from the <em>sep</em> array of size +<em>seplen</em> among the byte ranges represented by the members of array <em>v</em> +of size <em>n</em>, and returns the cumulative index of the first one it finds. +</p> + +<p> +<code> size_t siovec_search (struct iovec const *v, unsigned int n, char const *needle, size_t nlen) </code> <br> +Looks for the string (as in array of bytes: null characters are supported) +<em>needle</em> of size <em>nlen</em> in the byte ranges represented by the +members of array <em>v</em> of size <em>n</em>, and returns the cumulative +index of the first occurrence it finds, or <tt>siovec_len(v, n)</tt> if it +cannot find one. Split strings <strong>are</strong> supported: if <em>needle</em> +starts at position <tt>v[i].iov_base + pos</tt> but is cut because it +reaches <tt>v[i].iov_len</tt> midstring, and the rest of <em>needle</em> +is available at <tt>v[i+1].iov_base</tt>, then the function will find it +(and return <em>pos</em> plus the sum length of all the <em>v</em> members +before <em>i</em>). </p> </body> diff --git a/src/libstddjb/siovec_trunc.c b/src/libstddjb/siovec_trunc.c @@ -6,13 +6,13 @@ unsigned int siovec_trunc (struct iovec *v, unsigned int n, size_t len) { size_t w = siovec_len(v, n) ; - unsigned int i = n ; if (w < len) return n ; len = w - len ; - while (len && i--) + while (n && len) { - w = len > v[i].iov_len ? v[i].iov_len : len ; - v[i].iov_len -= w ; len -= w ; + w = len > v[n-1].iov_len ? v[n-1].iov_len : len ; + v[n-1].iov_len -= w ; len -= w ; + if (!v[n-1].iov_len) n-- ; } - return i ; + return n ; }