From cf3772b2b7dd91ae8f0815d28cc7ed26e462d938 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy <kevin@8t8.us> Date: Sat, 6 Oct 2018 13:53:33 -0700 Subject: [PATCH] Add buffer pool functions. Also add a few helper functions: mutt_buffer_clear(), mutt_buffer_strcpy(), and a macro mutt_b2s to grab the buffer data as a const char *. --- init.c | 1 + main.c | 1 + mutt/buffer.c | 131 +++++++++++++++++++++++++++++++++++++++++--------- mutt/buffer.h | 35 +++++++++----- 4 files changed, 133 insertions(+), 35 deletions(-) diff --git a/init.c b/init.c index d7dba3514..4dfad56bf 100644 --- a/init.c +++ b/init.c @@ -2870,6 +2870,7 @@ int mutt_init(bool skip_sys_rc, struct ListHead *commands) TagFormats = mutt_hash_create(64, 0); mutt_menu_init(); + mutt_buffer_pool_init(); snprintf(AttachmentMarker, sizeof(AttachmentMarker), "\033]9;%" PRIu64 "\a", mutt_rand64()); diff --git a/main.c b/main.c index cc6546361..0b0c740ca 100644 --- a/main.c +++ b/main.c @@ -1240,6 +1240,7 @@ main_exit: mutt_list_free(&queries); crypto_module_free(); mutt_window_free(); + mutt_buffer_pool_free(); mutt_envlist_free(); mutt_free_opts(); mutt_free_keys(); diff --git a/mutt/buffer.c b/mutt/buffer.c index c0f10bf5d..58c37e2fc 100644 --- a/mutt/buffer.c +++ b/mutt/buffer.c @@ -33,9 +33,14 @@ #include <stdio.h> #include <string.h> #include "buffer.h" +#include "logging.h" #include "memory.h" #include "string2.h" +static size_t BufferPoolCount = 0; +static size_t BufferPoolLen = 0; +static struct Buffer **BufferPool = NULL; + /** * mutt_buffer_new - Create and initialise a Buffer * @retval ptr New Buffer @@ -53,32 +58,32 @@ struct Buffer *mutt_buffer_new(void) /** * mutt_buffer_init - Initialise a new Buffer - * @param b Buffer to initialise + * @param buf Buffer to initialise * @retval ptr Initialised Buffer * * This must not be called on a Buffer that already contains data. */ -struct Buffer *mutt_buffer_init(struct Buffer *b) +struct Buffer *mutt_buffer_init(struct Buffer *buf) { - if (!b) + if (!buf) return NULL; - memset(b, 0, sizeof(struct Buffer)); - return b; + memset(buf, 0, sizeof(struct Buffer)); + return buf; } /** * mutt_buffer_reset - Reset an existing Buffer - * @param b Buffer to reset + * @param buf Buffer to reset * * This can be called on a Buffer to reset the pointers, * effectively emptying it. */ -void mutt_buffer_reset(struct Buffer *b) +void mutt_buffer_reset(struct Buffer *buf) { - if (!b) + if (!buf) return; - memset(b->data, 0, b->dsize); - b->dptr = b->data; + memset(buf->data, 0, buf->dsize); + buf->dptr = buf->data; } /** @@ -117,12 +122,7 @@ size_t mutt_buffer_add(struct Buffer *buf, const char *s, size_t len) return 0; if ((buf->dptr + len + 1) > (buf->data + buf->dsize)) - { - size_t offset = buf->dptr - buf->data; - buf->dsize += (len < 128) ? 128 : len + 1; - mutt_mem_realloc(&buf->data, buf->dsize); - buf->dptr = buf->data + offset; - } + mutt_buffer_increase_size(buf, buf->dsize + (len < 128 ? 128 : len + 1)); if (!buf->dptr) return 0; memcpy(buf->dptr, s, len); @@ -172,9 +172,7 @@ int mutt_buffer_printf(struct Buffer *buf, const char *fmt, ...) if (blen == 0) { blen = 128; - buf->dsize += blen; - mutt_mem_realloc(&buf->data, buf->dsize); - buf->dptr = buf->data + doff; + mutt_buffer_increase_size(buf, buf->dsize + blen); } len = vsnprintf(buf->dptr, blen, fmt, ap); if (len >= blen) @@ -182,9 +180,7 @@ int mutt_buffer_printf(struct Buffer *buf, const char *fmt, ...) blen = ++len - blen; if (blen < 128) blen = 128; - buf->dsize += blen; - mutt_mem_realloc(&buf->data, buf->dsize); - buf->dptr = buf->data + doff; + mutt_buffer_increase_size(buf, buf->dsize + blen); len = vsnprintf(buf->dptr, len, fmt, ap_retry); } if (len > 0) @@ -255,6 +251,19 @@ struct Buffer *mutt_buffer_alloc(size_t size) return b; } +/** + * mutt_buffer_strcpy - Copy a string into a Buffer + * @param buf Buffer to overwrite + * @param s String to copy + * + * Overwrites any existing content. + */ +void mutt_buffer_strcpy(struct Buffer *buf, const char *s) +{ + mutt_buffer_reset(buf); + mutt_buffer_addstr(buf, s); +} + /** * mutt_buffer_increase_size - Increase the allocated size of a buffer * @param buf Buffer to change @@ -273,3 +282,81 @@ void mutt_buffer_increase_size(struct Buffer *buf, size_t new_size) mutt_mem_realloc(&buf->data, buf->dsize); buf->dptr = buf->data + offset; } + +/** + * increase_buffer_pool - Increase the size of the Buffer pool + */ +static void increase_buffer_pool(void) +{ + struct Buffer *newbuf; + + BufferPoolLen += 5; + mutt_mem_realloc(&BufferPool, BufferPoolLen * sizeof(struct Buffer *)); + while (BufferPoolCount < 5) + { + newbuf = mutt_buffer_alloc(LONG_STRING); + BufferPool[BufferPoolCount++] = newbuf; + } +} + +/** + * mutt_buffer_pool_init - Initialise the Buffer pool + */ +void mutt_buffer_pool_init(void) +{ + increase_buffer_pool(); +} + +/** + * mutt_buffer_pool_free - Release the Buffer pool + */ +void mutt_buffer_pool_free(void) +{ + if (BufferPoolCount != BufferPoolLen) + { + mutt_debug(1, "Buffer pool leak: %zu/%zu\n", BufferPoolCount, BufferPoolLen); + } + while (BufferPoolCount) + mutt_buffer_free(&BufferPool[--BufferPoolCount]); + FREE(&BufferPool); + BufferPoolLen = 0; +} + +/** + * mutt_buffer_pool_get - Get a Buffer from the pool + * @retval ptr Buffer + */ +struct Buffer *mutt_buffer_pool_get(void) +{ + if (BufferPoolCount == 0) + increase_buffer_pool(); + return BufferPool[--BufferPoolCount]; +} + +/** + * mutt_buffer_pool_release - Free a Buffer from the pool + * @param pbuf Buffer to free + */ +void mutt_buffer_pool_release(struct Buffer **pbuf) +{ + if (!pbuf || !*pbuf) + return; + + if (BufferPoolCount >= BufferPoolLen) + { + mutt_debug(1, "Internal buffer pool error\n"); + mutt_buffer_free(pbuf); + return; + } + + struct Buffer *buf = *pbuf; + if (buf->dsize > (LONG_STRING * 2)) + { + buf->dsize = LONG_STRING; + mutt_mem_realloc(&buf->data, buf->dsize); + } + mutt_buffer_reset(buf); + BufferPool[BufferPoolCount++] = buf; + + *pbuf = NULL; +} diff --git a/mutt/buffer.h b/mutt/buffer.h index 32892621d..2c0fbdaf6 100644 --- a/mutt/buffer.h +++ b/mutt/buffer.h @@ -38,19 +38,28 @@ struct Buffer int destroy; /**< destroy 'data' when done? */ }; -#define MoreArgs(p) (*p->dptr && (*p->dptr != ';') && (*p->dptr != '#')) - -size_t mutt_buffer_add(struct Buffer *buf, const char *s, size_t len); -size_t mutt_buffer_addch(struct Buffer *buf, char c); -size_t mutt_buffer_addstr(struct Buffer *buf, const char *s); -struct Buffer *mutt_buffer_alloc(size_t size); -void mutt_buffer_free(struct Buffer **p); -struct Buffer *mutt_buffer_from(const char *seed); +/* Convert a buffer to a const char * "string" */ +#define mutt_b2s(buf) (buf->data ? (const char *) buf->data : "") + +#define MoreArgs(buf) (*buf->dptr && (*buf->dptr != ';') && (*buf->dptr != '#')) + +size_t mutt_buffer_add (struct Buffer *buf, const char *s, size_t len); +size_t mutt_buffer_addch (struct Buffer *buf, char c); +size_t mutt_buffer_addstr (struct Buffer *buf, const char *s); +struct Buffer *mutt_buffer_alloc (size_t size); +void mutt_buffer_free (struct Buffer **p); +struct Buffer *mutt_buffer_from (const char *seed); void mutt_buffer_increase_size(struct Buffer *buf, size_t new_size); -struct Buffer *mutt_buffer_init(struct Buffer *b); -bool mutt_buffer_is_empty(const struct Buffer *buf); -struct Buffer *mutt_buffer_new(void); -int mutt_buffer_printf(struct Buffer *buf, const char *fmt, ...); -void mutt_buffer_reset(struct Buffer *b); +struct Buffer *mutt_buffer_init (struct Buffer *buf); +bool mutt_buffer_is_empty (const struct Buffer *buf); +struct Buffer *mutt_buffer_new (void); +int mutt_buffer_printf (struct Buffer *buf, const char *fmt, ...); +void mutt_buffer_reset (struct Buffer *buf); +void mutt_buffer_strcpy (struct Buffer *buf, const char *s); + +void mutt_buffer_pool_free (void); +struct Buffer *mutt_buffer_pool_get (void); +void mutt_buffer_pool_init (void); +void mutt_buffer_pool_release (struct Buffer **pbuf); #endif /* MUTT_LIB_BUFFER_H */ -- 2.40.0