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);
#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;
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)