]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ncbuf2: support wrapping during add operation
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 15 Oct 2025 09:03:56 +0000 (11:03 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 17 Oct 2025 09:06:07 +0000 (11:06 +0200)
include/haproxy/ncbuf2.h
src/ncbuf2.c

index f7ead782f56b7e6da8ded3b52477b3016cde6511..5838b95c66d2fb7abb571982be0a72f626a368e7 100644 (file)
@@ -6,6 +6,20 @@
 
 struct ncbuf2 ncb2_make(char *area, ncb2_sz_t size, ncb2_sz_t head);
 
+static inline char *ncb2_orig(const struct ncbuf2 *buf)
+{
+       return buf->area;
+}
+
+static inline char *ncb2_head(const struct ncbuf2 *buf)
+{
+       return buf->area + buf->head;
+}
+
+static inline char *ncb2_wrap(const struct ncbuf2 *buf)
+{
+       return buf->area + buf->size;
+}
 
 enum ncb_ret ncb2_add(struct ncbuf2 *buf, ncb2_sz_t off,
                       const char *data, ncb2_sz_t len, enum ncb_add_mode mode);
index 448fbd9a2334c442f79003f344e87dae004d22c3..267d8ae03b8cafdcd0758cd993e6fb445f772d30 100644 (file)
@@ -2,10 +2,50 @@
 
 #include <string.h>
 
-#include <haproxy/bug.h>
 
 /* ******** internal API ******** */
 
+static char *ncb2_peek(const struct ncbuf2 *buf, ncb2_sz_t off)
+{
+       char *ptr = ncb2_head(buf) + off;
+       if (ptr >= buf->area + buf->size)
+               ptr -= buf->size;
+       return ptr;
+}
+
+static void ncb2_set_bitmap(struct ncbuf2 *buf, ncb2_sz_t off, ncb2_sz_t len)
+{
+       const ncb2_sz_t sz = ncb2_size(buf);
+       ncb2_sz_t off_abs;
+       unsigned char mod;
+       char *b;
+
+       off_abs = off < sz ? off : off - sz;
+       b = buf->bitmap + (off_abs / 8);
+
+       mod = off_abs % 8;
+       if (mod) {
+               /* adjust first bitmap byte bit by bit if not aligned on 8 */
+               size_t to_copy = len < 8 - mod ? len : 8 - mod;
+               *b |= (0xff << (8 - to_copy)) >> mod;
+               len -= to_copy;
+               ++b;
+       }
+
+       if (len) {
+               size_t to_copy = len / 8;
+               /* bulk set bitmap as many as possible */
+               memset(b, 0xff, to_copy);
+               len -= 8 * to_copy;
+               b += to_copy;
+
+               if (len) {
+                       /* adjust last bitmap byte shifted by remaining len */
+                       *b |= 0xff << (8 - len);
+               }
+       }
+}
+
 struct itbmap {
        char *b;
        ncb2_sz_t off;
@@ -136,33 +176,25 @@ ncb2_sz_t ncb2_data(const struct ncbuf2 *buf, ncb2_sz_t off)
 enum ncb_ret ncb2_add(struct ncbuf2 *buf, ncb2_sz_t off,
                       const char *data, ncb2_sz_t len, enum ncb_add_mode mode)
 {
-       char *b;
+       char *ptr = ncb2_peek(buf, off);
 
        BUG_ON_HOT(off + len > buf->size);
-       /* first copy data into buffer */
-       memcpy(&buf->area[off], data, len);
-
-       /* adjust bitmap to reflect newly filled content */
-       b = buf->bitmap + (off / 8);
-       if (off % 8) {
-               size_t to_copy = len < 8 - (off % 8) ? len : 8 - (off % 8);
-               /* adjust first bitmap byte relative shifted by offset */
-               *b++ |= ((unsigned char)(0xff << (8 - to_copy))) >> (off % 8);
-               len -= to_copy;
-       }
 
-       if (len) {
-               size_t to_copy = len / 8;
-               /* bulk set bitmap as many as possible */
-               memset(b, 0xff, to_copy);
-               len -= 8 * to_copy;
-               b += to_copy;
+       if (ptr + len >= ncb2_wrap(buf)) {
+               ncb2_sz_t sz1 = ncb2_wrap(buf) - ptr;
 
-               if (len) {
-                       /* adjust last bitmap byte shifted by remaining len */
-                       *b |= 0xff << (8 - len);
-               }
+               memcpy(ptr, data, sz1);
+               ncb2_set_bitmap(buf, buf->head + off, sz1);
+
+               memcpy(ncb2_orig(buf), data + sz1, len - sz1);
+               ncb2_set_bitmap(buf, 0, len - sz1);
+       }
+       else {
+               memcpy(ptr, data, len);
+               ncb2_set_bitmap(buf, buf->head + off, len);
        }
+
+       return NCB_RET_OK;
 }
 
 enum ncb_ret ncb2_advance(struct ncbuf2 *buf, ncb2_sz_t adv)