diff options
Diffstat (limited to 'libnetdata/buffer')
-rw-r--r-- | libnetdata/buffer/buffer.c | 47 | ||||
-rw-r--r-- | libnetdata/buffer/buffer.h | 26 |
2 files changed, 43 insertions, 30 deletions
diff --git a/libnetdata/buffer/buffer.c b/libnetdata/buffer/buffer.c index 488e7dd24f..64f9cce47c 100644 --- a/libnetdata/buffer/buffer.c +++ b/libnetdata/buffer/buffer.c @@ -81,6 +81,7 @@ void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) va_list args; va_start(args, fmt); + // vsnprintfz() returns the number of bytes actually written - after possible truncation wb->len += vsnprintfz(&wb->buffer[wb->len], len, fmt, args); va_end(args); @@ -89,53 +90,39 @@ void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) // the buffer is \0 terminated by vsnprintfz } -void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args) -{ +inline void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args) { if(unlikely(!fmt || !*fmt)) return; - size_t wrote = 0, need = 2, space_remaining = 0; + size_t full_size_bytes = 0, need = 2, space_remaining = 0; do { - need += space_remaining * 2; + need += full_size_bytes + 2; - netdata_log_debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu, by %zu bytes (wrote = %zu)\n", wb->len, wb->size, need, wrote); buffer_need_bytes(wb, need); space_remaining = wb->size - wb->len - 1; - wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], space_remaining, fmt, args); + // Use the copy of va_list for vsnprintf + va_list args_copy; + va_copy(args_copy, args); + // vsnprintf() returns the number of bytes required, even if bigger than the buffer provided + full_size_bytes = (size_t) vsnprintf(&wb->buffer[wb->len], space_remaining, fmt, args_copy); + va_end(args_copy); - } while(wrote >= space_remaining); + } while(full_size_bytes >= space_remaining); - wb->len += wrote; + wb->len += full_size_bytes; - // the buffer is \0 terminated by vsnprintf + wb->buffer[wb->len] = '\0'; + buffer_overflow_check(wb); } void buffer_sprintf(BUFFER *wb, const char *fmt, ...) { - if(unlikely(!fmt || !*fmt)) return; - va_list args; - size_t wrote = 0, need = 2, space_remaining = 0; - - do { - need += space_remaining * 2; - - netdata_log_debug(D_WEB_BUFFER, "web_buffer_sprintf(): increasing web_buffer at position %zu, size = %zu, by %zu bytes (wrote = %zu)\n", wb->len, wb->size, need, wrote); - buffer_need_bytes(wb, need); - - space_remaining = wb->size - wb->len - 1; - - va_start(args, fmt); - wrote = (size_t) vsnprintfz(&wb->buffer[wb->len], space_remaining, fmt, args); - va_end(args); - - } while(wrote >= space_remaining); - - wb->len += wrote; - - // the buffer is \0 terminated by vsnprintf + va_start(args, fmt); + buffer_vsprintf(wb, fmt, args); + va_end(args); } // generate a javascript date, the fastest possible way... diff --git a/libnetdata/buffer/buffer.h b/libnetdata/buffer/buffer.h index e5dd9992d1..88d3f0282a 100644 --- a/libnetdata/buffer/buffer.h +++ b/libnetdata/buffer/buffer.h @@ -94,6 +94,8 @@ typedef struct web_buffer { } json; } BUFFER; +#define CLEAN_BUFFER _cleanup_(buffer_freep) BUFFER + #define buffer_cacheable(wb) do { (wb)->options |= WB_CONTENT_CACHEABLE; if((wb)->options & WB_CONTENT_NO_CACHEABLE) (wb)->options &= ~WB_CONTENT_NO_CACHEABLE; } while(0) #define buffer_no_cacheable(wb) do { (wb)->options |= WB_CONTENT_NO_CACHEABLE; if((wb)->options & WB_CONTENT_CACHEABLE) (wb)->options &= ~WB_CONTENT_CACHEABLE; (wb)->expires = 0; } while(0) @@ -135,6 +137,10 @@ BUFFER *buffer_create(size_t size, size_t *statistics); void buffer_free(BUFFER *b); void buffer_increase(BUFFER *b, size_t free_size_required); +static inline void buffer_freep(BUFFER **bp) { + if(bp) buffer_free(*bp); +} + void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) PRINTFLIKE(3, 4); void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args); void buffer_sprintf(BUFFER *wb, const char *fmt, ...) PRINTFLIKE(2,3); @@ -210,6 +216,13 @@ static inline void buffer_fast_rawcat(BUFFER *wb, const char *txt, size_t len) { buffer_overflow_check(wb); } +static inline void buffer_putc(BUFFER *wb, char c) { + buffer_need_bytes(wb, 2); + wb->buffer[wb->len++] = c; + wb->buffer[wb->len] = '\0'; + buffer_overflow_check(wb); +} + static inline void buffer_fast_strcat(BUFFER *wb, const char *txt, size_t len) { if(unlikely(!txt || !*txt || !len)) return; @@ -283,6 +296,19 @@ static inline void buffer_strncat(BUFFER *wb, const char *txt, size_t len) { buffer_overflow_check(wb); } +static inline void buffer_memcat(BUFFER *wb, const void *mem, size_t bytes) { + if(unlikely(!mem)) return; + + buffer_need_bytes(wb, bytes + 1); + + memcpy(&wb->buffer[wb->len], mem, bytes); + + wb->len += bytes; + wb->buffer[wb->len] = '\0'; + + buffer_overflow_check(wb); +} + static inline void buffer_json_strcat(BUFFER *wb, const char *txt) { if(unlikely(!txt || !*txt)) return; |