From 2c9d1b2b0c8f6596c5255799cfe56be9519cfc56 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Mon, 2 Mar 2026 10:25:17 +0100 Subject: [PATCH] MINOR: hbuf: add a very lightweight hbuf API Add a new lightweight hbuf API to buffer formatted strings, similar to the existing buffer API (struct buffer). This is required by haterm to build its configuration in memory (fileless mode). Update haterm to use this new API. Note: hstream_str_buf_append() has been renamed to hbuf_str_append(). --- Makefile | 2 +- include/haproxy/hbuf.h | 42 +++++++++++++++++ src/haterm_init.c | 105 ++--------------------------------------- src/hbuf.c | 73 ++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 102 deletions(-) create mode 100644 include/haproxy/hbuf.h create mode 100644 src/hbuf.c diff --git a/Makefile b/Makefile index 624d58e06..8bde12828 100644 --- a/Makefile +++ b/Makefile @@ -1020,7 +1020,7 @@ ifneq ($(TRACE),) OBJS += src/calltrace.o endif -HATERM_OBJS += $(OBJS) src/haterm_init.o +HATERM_OBJS += $(OBJS) src/haterm_init.o src/hbuf.o # Used only for forced dependency checking. May be cleared during development. INCLUDES = $(wildcard include/*/*.h) diff --git a/include/haproxy/hbuf.h b/include/haproxy/hbuf.h new file mode 100644 index 000000000..373d2f042 --- /dev/null +++ b/include/haproxy/hbuf.h @@ -0,0 +1,42 @@ +#ifndef _HAPROXY_HBUF_H +#define _HAPROXY_HBUF_H + +#include + +/* Very small API similar to buffer API to carefully bufferize some strings */ +#define HBUF_NULL ((struct hbuf) { }) +#define HBUF_SIZE (16 << 10) /* bytes */ + +struct hbuf { + char *area; + size_t data; + size_t size; +}; + +static inline struct hbuf *hbuf_alloc(struct hbuf *h) +{ + h->area = malloc(HBUF_SIZE); + if (!h->area) + return NULL; + + h->size = HBUF_SIZE; + h->data = 0; + return h; +} + +static inline void free_hbuf(struct hbuf *h) +{ + free(h->area); + h->area = NULL; +} + +static inline size_t hbuf_is_null(const struct hbuf *h) +{ + return h->size == 0; +} + +__attribute__ ((format(printf, 2, 3))) +void hbuf_appendf(struct hbuf *h, char *fmt, ...); +void hbuf_str_append(struct hbuf *h, const char *line); + +#endif /* _HAPROXY_HBUF_H */ diff --git a/src/haterm_init.c b/src/haterm_init.c index a56ac3eb3..f166fa1b7 100644 --- a/src/haterm_init.c +++ b/src/haterm_init.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static int haterm_debug; @@ -58,104 +59,6 @@ static const char *haterm_cfg_traces_str = "\ttrace h3 sink stderr level user start now verbosity minimal\n" "\ttrace qmux sink stderr level user start now verbosity minimal\n"; -/* Very small API similar to buffer API to carefully build some strings */ -#define HBUF_NULL ((struct hbuf) { }) -#define HBUF_SIZE (16 << 10) /* bytes */ -struct hbuf { - char *area; - size_t data; - size_t size; -}; - -static struct hbuf *hbuf_alloc(struct hbuf *h) -{ - h->area = malloc(HBUF_SIZE); - if (!h->area) - return NULL; - - h->size = HBUF_SIZE; - h->data = 0; - return h; -} - -static inline void free_hbuf(struct hbuf *h) -{ - free(h->area); - h->area = NULL; -} - -__attribute__ ((format(printf, 2, 3))) -static void hbuf_appendf(struct hbuf *h, char *fmt, ...) -{ - va_list argp; - size_t room; - int ret; - - room = h->size - h->data; - if (!room) - return; - - va_start(argp, fmt); - ret = vsnprintf(h->area + h->data, room, fmt, argp); - if (ret >= room) - h->area[h->data] = '\0'; - else - h->data += ret; - va_end(argp); -} - -static inline size_t hbuf_is_null(const struct hbuf *h) -{ - return h->size == 0; -} - -/* Simple function, to append to without without - * trailing '\0' character. - * Take into an account the '\t' and '\n' escaped sequences. - */ -static void hstream_str_buf_append(struct hbuf *h, const char *line) -{ - const char *p, *end; - char *to = h->area + h->data; - char *wrap = h->area + h->size; - int nl = 0; /* terminal '\n' */ - - p = line; - end = line + strlen(line); - - /* prepend '\t' if missing */ - if (strncmp(line, "\\t", 2) != 0 && to < wrap) { - *to++ = '\t'; - h->data++; - } - - while (p < end && to < wrap) { - if (*p == '\\') { - if (!*++p || p >= end) - break; - if (*p == 'n') { - *to++ = '\n'; - if (p + 1 >= end) - nl = 1; - } - else if (*p == 't') - *to++ = '\t'; - p++; - h->data++; - } - else { - *to++ = *p++; - h->data++; - } - } - - /* add a terminal '\n' if not already present */ - if (to < wrap && !nl) { - *to++ = '\n'; - h->data++; - } -} - /* This function initialises the haterm HTTP benchmark server from * . This consists in building a configuration file in memory * using the haproxy configuration language. @@ -318,7 +221,7 @@ void haproxy_init_args(int argc, char **argv) hbuf_appendf(&fbuf, "\toption accept-unsafe-violations-in-http-request\n"); } - hstream_str_buf_append(&fbuf, *argv); + hbuf_str_append(&fbuf, *argv); } else if (*opt == 'G') { argv++; argc--; @@ -334,7 +237,7 @@ void haproxy_init_args(int argc, char **argv) hbuf_appendf(&gbuf, "global\n"); } - hstream_str_buf_append(&gbuf, *argv); + hbuf_str_append(&gbuf, *argv); } else if (*opt == 'T') { argv++; argc--; @@ -347,7 +250,7 @@ void haproxy_init_args(int argc, char **argv) } haterm_debug = 1; - hstream_str_buf_append(&tbuf, *argv); + hbuf_str_append(&tbuf, *argv); } else if (*opt == 'L') { /* binding */ diff --git a/src/hbuf.c b/src/hbuf.c new file mode 100644 index 000000000..6c16580b1 --- /dev/null +++ b/src/hbuf.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#include + +__attribute__ ((format(printf, 2, 3))) +void hbuf_appendf(struct hbuf *h, char *fmt, ...) +{ + va_list argp; + size_t room; + int ret; + + room = h->size - h->data; + if (!room) + return; + + va_start(argp, fmt); + ret = vsnprintf(h->area + h->data, room, fmt, argp); + if (ret >= room) + h->area[h->data] = '\0'; + else + h->data += ret; + va_end(argp); +} + +/* Simple function, to append to without without + * trailing '\0' character. + * Take into an account the '\t' and '\n' escaped sequeces. + */ +void hbuf_str_append(struct hbuf *h, const char *line) +{ + const char *p, *end; + char *to = h->area + h->data; + char *wrap = h->area + h->size; + int nl = 0; /* terminal '\n' */ + + p = line; + end = line + strlen(line); + + /* prepend '\t' if missing */ + if (strncmp(line, "\\t", 2) != 0 && to < wrap) { + *to++ = '\t'; + h->data++; + } + + while (p < end && to < wrap) { + if (*p == '\\') { + if (!*++p || p >= end) + break; + if (*p == 'n') { + *to++ = '\n'; + if (p + 1 >= end) + nl = 1; + } + else if (*p == 't') + *to++ = '\t'; + p++; + h->data++; + } + else { + *to++ = *p++; + h->data++; + } + } + + /* add a terminal '\n' if not already present */ + if (to < wrap && !nl) { + *to++ = '\n'; + h->data++; + } +} +