From: Willy Tarreau Date: Wed, 22 Feb 2023 14:53:52 +0000 (+0100) Subject: MINOR: buf: add b_getblk_ofs() that works relative to area and not head X-Git-Tag: v3.0-dev6~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=63242a59c486801499449e07ec6a57885661ae75;p=thirdparty%2Fhaproxy.git MINOR: buf: add b_getblk_ofs() that works relative to area and not head For some concurrently accessed buffers we can't rely on head/data etc, but sometimes the access patterns guarantees that the buffer contents are there. Let's implement a function to read contents from a fixed offset, which never checks head nor data, only the area and its size. It's the caller's job to get this offset. --- diff --git a/include/haproxy/buf.h b/include/haproxy/buf.h index c5d77e26ac..6118cc47f3 100644 --- a/include/haproxy/buf.h +++ b/include/haproxy/buf.h @@ -335,6 +335,38 @@ static inline size_t b_contig_space(const struct buffer *b) return left; } +/* b_getblk_ofs() : gets one full block of data at once from a buffer, starting + * from offset after the buffer's area, and for exactly bytes. + * 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 data at this position, otherwise undefined + * data will be returned. This is meant to be used on concurrently accessed + * buffers, so that a reader can read a known area while the buffer is being fed + * and trimmed. The function guarantees never to use ->head nor ->data. The + * buffer is left unaffected. It always returns the number of bytes copied. + */ +static inline size_t b_getblk_ofs(const 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(blk, b_orig(buf) + offset, firstblock); + + if (len > firstblock) + memcpy(blk + firstblock, b_orig(buf), len - firstblock); + return len; +} + /* b_getblk() : gets one full block of data at once from a buffer, starting * from offset after the buffer's head, and limited to no more than * bytes. The caller is responsible for ensuring that neither