diff --git a/mem-pool.c b/mem-pool.c index c7d6256020..2078c22b09 100644 --- a/mem-pool.c +++ b/mem-pool.c @@ -107,6 +107,45 @@ void *mem_pool_alloc(struct mem_pool *pool, size_t len) return r; } +static char *mem_pool_strvfmt(struct mem_pool *pool, const char *fmt, + va_list ap) +{ + struct mp_block *block = pool->mp_block; + char *next_free = block ? block->next_free : NULL; + size_t available = block ? block->end - block->next_free : 0; + va_list cp; + int len, len2; + char *ret; + + va_copy(cp, ap); + len = vsnprintf(next_free, available, fmt, cp); + va_end(cp); + if (len < 0) + BUG("your vsnprintf is broken (returned %d)", len); + + ret = mem_pool_alloc(pool, len + 1); /* 1 for NUL */ + + /* Shortcut; relies on mem_pool_alloc() not touching buffer contents. */ + if (ret == next_free) + return ret; + + len2 = vsnprintf(ret, len + 1, fmt, ap); + if (len2 != len) + BUG("your vsnprintf is broken (returns inconsistent lengths)"); + return ret; +} + +char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = mem_pool_strvfmt(pool, fmt, ap); + va_end(ap); + return ret; +} + void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size) { size_t len = st_mult(count, size); diff --git a/mem-pool.h b/mem-pool.h index fe7507f022..d1c66413ec 100644 --- a/mem-pool.h +++ b/mem-pool.h @@ -47,6 +47,11 @@ void *mem_pool_calloc(struct mem_pool *pool, size_t count, size_t size); char *mem_pool_strdup(struct mem_pool *pool, const char *str); char *mem_pool_strndup(struct mem_pool *pool, const char *str, size_t len); +/* + * Allocate memory from the memory pool and format a string into it. + */ +char *mem_pool_strfmt(struct mem_pool *pool, const char *fmt, ...); + /* * Move the memory associated with the 'src' pool to the 'dst' pool. The 'src' * pool will be empty and not contain any memory. It still needs to be free'd