From: Willy Tarreau Date: Thu, 23 Feb 2023 11:02:05 +0000 (+0100) Subject: MINOR: buf: add b_putblk_ofs() to copy a block at a specific position X-Git-Tag: v3.0-dev6~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f28981546c6f57157d26b46e64d442f97742a31;p=thirdparty%2Fhaproxy.git MINOR: buf: add b_putblk_ofs() to copy a block at a specific position This new function b_putblk_ofs() puts one full block of data of length from into the buffer, starting from absolute offset after the buffer's area. As a convenience to avoid complex checks in callers, the offset is allowed to exceed a valid one by no more than one buffer size, and will automatically be wrapped. The caller is responsible for ensuring that doesn't exceed the known length of the available room at this position, otherwise data may be overwritten. The buffer's length is *not* updated, so generally the caller will have updated it before calling this function. This is meant to be used on concurrently accessed buffers, so that a writer can append data while a reader is blocked by other means from reaching the current area The function guarantees never to use ->head nor ->data. --- diff --git a/include/haproxy/buf.h b/include/haproxy/buf.h index d9f3a7727e..c5d77e26ac 100644 --- a/include/haproxy/buf.h +++ b/include/haproxy/buf.h @@ -557,6 +557,40 @@ static inline void b_putchr(struct buffer *b, char c) b->data++; } +/* b_putblk_ofs(): puts one full block of data of length from into + * the buffer, starting from absolute offset after the buffer's area. + * As a convenience to avoid complex checks in callers, the offset is allowed + * to exceed a valid one by no more than one buffer size, and will automatically + * be wrapped. The caller is responsible for ensuring that doesn't exceed + * the known length of the available room at this position, otherwise data may + * be overwritten. The buffer's length is *not* updated, so generally the caller + * will have updated it before calling this function. This is meant to be used + * on concurrently accessed buffers, so that a writer can append data while a + * reader is blocked by other means from reaching the current area The function + * guarantees never to use ->head nor ->data. It always returns the number of + * bytes copied. + */ +static inline size_t b_putblk_ofs(struct buffer *buf, char *blk, size_t len, size_t offset) +{ + size_t firstblock; + + if (offset >= buf->size) + offset -= buf->size; + + BUG_ON(offset >= buf->size); + + firstblock = buf->size - offset; + + if (firstblock >= len) + firstblock = len; + + memcpy(b_orig(buf) + offset, blk, firstblock); + + if (len > firstblock) + memcpy(b_orig(buf), blk + firstblock, len - firstblock); + return len; +} + /* __b_putblk() : tries to append bytes from block to the end of * buffer without checking for free space (it's up to the caller to do it). * Supports wrapping. It must not be called with len == 0.