dovecot: Implement str_vprintfa() by making vsnprintf() write di...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Jul 2 23:25:40 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/092b9d3b7f97
changeset: 5866:092b9d3b7f97
user: Timo Sirainen <tss at iki.fi>
date: Mon Jul 02 23:24:34 2007 +0300
description:
Implement str_vprintfa() by making vsnprintf() write directly to the string.
This also avoids excessive memory usage with strings allocated from data
stack.
diffstat:
1 file changed, 28 insertions(+), 7 deletions(-)
src/lib/str.c | 35 ++++++++++++++++++++++++++++-------
diffs (47 lines):
diff -r 22b300677807 -r 092b9d3b7f97 src/lib/str.c
--- a/src/lib/str.c Mon Jul 02 23:11:46 2007 +0300
+++ b/src/lib/str.c Mon Jul 02 23:24:34 2007 +0300
@@ -102,15 +102,36 @@ void str_printfa(string_t *str, const ch
void str_vprintfa(string_t *str, const char *fmt, va_list args)
{
- const char *tmp;
- unsigned int size;
+#define SNPRINTF_INITIAL_EXTRA_SIZE 256
+ va_list args2;
+ char *tmp;
+ unsigned int init_size;
+ size_t pos = str->used;
+ int ret, ret2;
- tmp = t_noalloc_strdup_vprintf(fmt, args, &size);
- if (buffer_get_pool(str)->datastack_pool) {
- /* appending to buffer may allocate more data from data stack */
- t_buffer_alloc(size);
+ VA_COPY(args2, args);
+
+ /* the format string is modified only if %m exists in it. it happens
+ only in error conditions, so don't try to t_push() here since it'll
+ just slow down the normal code path. */
+ fmt = printf_format_fix_get_len(fmt, &init_size);
+ init_size += SNPRINTF_INITIAL_EXTRA_SIZE;
+
+ /* @UNSAFE */
+ tmp = buffer_get_space_unsafe(str, pos, init_size);
+ ret = vsnprintf(tmp, init_size, fmt, args);
+ i_assert(ret >= 0);
+
+ if ((unsigned int)ret >= init_size) {
+ /* didn't fit with the first guess. now we know the size,
+ so try again. */
+ tmp = buffer_get_space_unsafe(str, pos, ret + 1);
+ ret2 = vsnprintf(tmp, ret + 1, fmt, args2);
+ i_assert(ret2 == ret);
}
- buffer_append(str, tmp, size - 1);
+
+ /* drop the unused data, including terminating NUL */
+ buffer_set_used_size(str, pos + ret);
}
void str_insert(string_t *str, size_t pos, const char *cstr)
More information about the dovecot-cvs
mailing list