diff options
author | Luigi Rizzo <rizzo@icir.org> | 2006-12-15 22:08:46 +0000 |
---|---|---|
committer | Luigi Rizzo <rizzo@icir.org> | 2006-12-15 22:08:46 +0000 |
commit | 961754d4b12da98e84aa43992ebb2c578d94ca30 (patch) | |
tree | 2229580e652fea2c03599c4c5bd2a1a3eb38ef00 /main/utils.c | |
parent | 4a0738a665ccc856d70ad328bf28a7bd5a2d7deb (diff) |
move the dynamic string support in a better place i.e. string.h
While doing this, add a bit of documentation, and slightly
extend the functionality as follows:
+ a max_len of -1 means that we take whatever the current size
is, and never try to extend the buffer;
+ add support for alloca()-ted dynamic strings, which is very
useful for all cases where we do an ast_build_string() now.
Next step is to simplify the interface by using shorter names
(e.g. ast_str as a prefix) and removing the _thread variant
of the functions by saving the threadstorage reference into
the struct ast_str. This can be done by overloading the
'type' field.
Finally, I will do my best to remove the convoluted interface
that results from trying to support platforms without va_copy().
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@48509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/utils.c')
-rw-r--r-- | main/utils.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/main/utils.c b/main/utils.c index d374e69bf..9e51dcde1 100644 --- a/main/utils.c +++ b/main/utils.c @@ -972,33 +972,47 @@ int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed) return -1; } -int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len, +/*! + * core handler for dynamic strings. + * This is not meant to be called directly, but rather through the + * various wrapper macros + * ast_dynamic_str_set(...) + * ast_dynamic_str_append(...) + * ast_dynamic_str_thread_set(...) + * ast_dynamic_str_thread_append(...) + */ +int __ast_dyn_str_helper(struct ast_dynamic_str **buf, size_t max_len, struct ast_threadstorage *ts, int append, const char *fmt, va_list ap) { int res, need; - int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0; - + int offset = (append && (*buf)->len) ? (*buf)->used : 0; + + if (max_len < 0) + max_len = (*buf)->len; /* don't exceed the allocated space */ + /* + * Ask vsnprintf how much space we need. Remember that vsnprintf + * does not count the final '\0' so we must add 1. + */ res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap); need = res + offset + 1; - /* Check to see if there was not enough space in the string buffer to prepare - * the string. Also, if a maximum length is present, make sure the current - * length is less than the maximum before increasing the size. */ + /* + * If there is not enough space and we are below the max length, + * reallocate the buffer and return a message telling to retry. + */ if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) { - /* Set the new size of the string buffer to be the size needed - * to hold the resulting string (res) plus one byte for the - * terminating '\0'. If this size is greater than the max, set - * the new length to be the maximum allowed. */ - if (max_len && max_len < need) + if (max_len && max_len < need) /* truncate as needed */ need = max_len; + /* We can only realloc malloc'ed space. */ + if ((*buf)->type != DS_MALLOC) + return AST_DYNSTR_BUILD_FAILED; *buf = ast_realloc(*buf, need + sizeof(struct ast_dynamic_str)); - if (*buf == NULL) + if (*buf == NULL) /* XXX watch out, we leak memory here */ return AST_DYNSTR_BUILD_FAILED; (*buf)->len = need; - /* Truncate the partial write. */ - (*buf)->str[offset] = '\0'; + (*buf)->str[offset] = '\0'; /* Truncate the partial write. */ if (ts) pthread_setspecific(ts->key, *buf); @@ -1007,6 +1021,8 @@ int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len * vsnprintf() again. */ return AST_DYNSTR_BUILD_RETRY; } + /* update space used, keep in mind the truncation */ + (*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset; return res; } |