]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ncbmbuf: implement iterator bitmap utilities functions
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 16 Oct 2025 15:34:10 +0000 (17:34 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 22 Oct 2025 13:04:06 +0000 (15:04 +0200)
Extend private API for ncbmbuf type by defining an iterator type for the
buffer bitmap handling. The purpose is to provide a simple method to
iterate over the bitmap one byte at a time, with a proper bitmask set to
hide irrelevant bits.

This internal type is unused for now, but will become useful when
implementing ncb_data() and ncb_advance() functions.

As the previous patch, this commit must be backported prior to the fix
to come on QUIC CRYPTO frames parsing.

src/ncbmbuf.c

index c26b25ecaeb2a1bccc7b36f4ffcc4cd64103465d..b2f052d3e8724f908e78e51ec71b3e2733566d16 100644 (file)
@@ -60,6 +60,93 @@ static void ncbmb_set_bitmap(struct ncbmbuf *buf, ncb_sz_t off, ncb_sz_t len)
        }
 }
 
+/* Type representing a bitmap byte. */
+struct itbmap {
+       unsigned char *b;
+       ncb_sz_t off; /* offset relative to buf head */
+       unsigned char mask; /* usable bits depending on <off> and buf data storage */
+       unsigned char bits; /* count of bits set in <mask> */
+};
+
+/* Returns true if all bits masked in <it> are set. */
+static __attribute__((unused)) int itbmap_is_full(const struct itbmap *it)
+{
+       if (!it->b)
+               return 0;
+
+       return (*it->b & it->mask) == it->mask;
+}
+
+static __attribute__((unused)) void itbmap_load(struct itbmap *it, ncb_sz_t off,
+                                                const struct ncbmbuf *buf)
+{
+       const ncb_sz_t sz = ncbmb_size(buf);
+       ncb_sz_t off_abs;
+       ncb_sz_t off_bmap;
+
+       off_abs = buf->head + off;
+       if (off_abs >= sz)
+               off_abs -= sz;
+       off_bmap = off_abs / 8;
+       BUG_ON_HOT(off_bmap >= buf->size_bm);
+
+       it->b = buf->bitmap + off_bmap;
+       it->off = off;
+       it->mask = 0xff;
+       it->bits = 8;
+
+       /* Adjust mask for last bitmap byte. */
+       if (off_bmap == buf->size_bm - 1 && (sz % 8)) {
+               it->mask <<= 8 - (sz % 8);
+               it->bits -= 8 - (sz % 8);
+       }
+
+       /* Adjust mask if iterator starts unaligned. */
+       if (off_abs % 8) {
+               it->mask &= (0xff >> (off_abs % 8));
+               it->bits -= off_abs % 8;
+       }
+
+       /* Adjust mask if iterator ends unaligned. */
+       if (it->off + it->bits > sz) {
+               it->mask &= (0xff << (it->off + it->bits - sz));
+               it->bits -= it->off + it->bits - sz;
+       }
+}
+
+/* Returns an iterator on the bitmap byte corresponding to <off> offset
+ * relative to <buf> head.
+ */
+static __attribute__((unused)) struct itbmap itbmap_get(const struct ncbmbuf *buf, ncb_sz_t off)
+{
+       struct itbmap it;
+
+       BUG_ON(off >= ncbmb_size(buf));
+
+       itbmap_load(&it, off, buf);
+       return it;
+}
+
+/* Returns the next bitmap byte relative to <prev> iterator. */
+static __attribute__((unused)) struct itbmap itbmap_next(const struct ncbmbuf *buf,
+                                                         const struct itbmap *prev)
+{
+       const ncb_sz_t off_next = prev->off + prev->bits;
+       struct itbmap next;
+
+       BUG_ON_HOT(off_next > ncbmb_size(buf));
+
+       if (off_next == ncbmb_size(buf)) {
+               next.b = NULL;
+               next.off = off_next;
+       }
+       else {
+               itbmap_load(&next, prev->off + prev->bits, buf);
+       }
+
+       return next;
+}
+
 /* ******** public API ******** */
 
 /* Initialize or reset <buf> by clearing all data. Its size is untouched.