]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: buf: add b_getblk_ofs() that works relative to area and not head
authorWilly Tarreau <w@1wt.eu>
Wed, 22 Feb 2023 14:53:52 +0000 (15:53 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 25 Mar 2024 17:34:19 +0000 (17:34 +0000)
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.

include/haproxy/buf.h

index c5d77e26ac05a48441266c098d09f54d60e5714b..6118cc47f3a7f75d880584ec33004b941ac22676 100644 (file)
@@ -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 <offset> after the buffer's area, and for exactly <len> 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 <len> 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 <offset> after the buffer's head, and limited to no more than
  * <len> bytes. The caller is responsible for ensuring that neither <offset>