]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mem-pool: add mem_pool_strfmt()
authorRené Scharfe <l.s.r@web.de>
Sun, 25 Feb 2024 11:39:44 +0000 (12:39 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 26 Feb 2024 17:35:40 +0000 (09:35 -0800)
Add a function for building a string, printf style, using a memory pool.
It uses the free space in the current block in the first attempt.  If
that suffices then the result can already be used without copying or
reformatting.

For strings that are significantly shorter on average than the block
size (ca. 1 MiB by default) this is the case most of the time, leading
to a better perfomance than a solution that doesn't access mem-pool
internals.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
mem-pool.c
mem-pool.h

index c7d62560201984db8efcb675da9b4ede933c5cbd..2078c22b097a61c97faddb6689a75e6c10ccb9ee 100644 (file)
@@ -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);
index fe7507f022bba40d74aab341e99269ead7171695..d1c66413ec322104f6199cc2248466c734cee868 100644 (file)
@@ -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