aboutsummaryrefslogtreecommitdiffstats
path: root/utils.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-26 04:00:05 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-26 04:00:05 +0000
commitde2fd6aebf2f638dc0947778ce087529295ad3d3 (patch)
tree0aa7c1312e44030aa06217b02912d3a26f1c106c /utils.c
parent0e2d8be747fbb9454768f26c60a5e6deb89ec059 (diff)
string field manager improvements:
use multiple memory blocks, instead of realloc(), ensuring that field pointers will never become invalid or change don't run vs(n)printf twice when doing a field build unless required git-svn-id: http://svn.digium.com/svn/asterisk/trunk@8697 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c82
1 files changed, 49 insertions, 33 deletions
diff --git a/utils.c b/utils.c
index ef0246252..977f0cdd0 100644
--- a/utils.c
+++ b/utils.c
@@ -944,70 +944,86 @@ void ast_join(char *s, size_t len, char * const w[])
const char const *__ast_string_field_empty = "";
-int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
+static int add_string_pool(struct ast_string_field_mgr *mgr, size_t size)
+{
+ struct ast_string_field_pool *pool;
+
+ if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
+ return -1;
+
+ pool->prev = mgr->pool;
+ mgr->pool = pool;
+ mgr->size = size;
+ mgr->space = size;
+ mgr->used = 0;
+
+ return 0;
+}
+
+int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
ast_string_field *fields, int num_fields)
{
int index;
- pool->base = calloc(1, size);
- if (pool->base) {
- pool->size = size;
- pool->space = size;
- for (index = 0; index < num_fields; index++)
- fields[index] = __ast_string_field_empty;
- }
- return pool->base ? 0 : -1;
+ if (add_string_pool(mgr, size))
+ return -1;
+
+ for (index = 0; index < num_fields; index++)
+ fields[index] = __ast_string_field_empty;
+
+ return 0;
}
-ast_string_field __ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
+ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
ast_string_field *fields, int num_fields)
{
char *result = NULL;
- if (__builtin_expect(needed > pool->space, 0)) {
- int index;
- char *new_base;
- size_t new_size = pool->size * 2;
+ if (__builtin_expect(needed > mgr->space, 0)) {
+ size_t new_size = mgr->size * 2;
- while (new_size < (pool->used + needed))
+ while (new_size < needed)
new_size *= 2;
- if (!(new_base = realloc(pool->base, new_size)))
+ if (add_string_pool(mgr, new_size))
return NULL;
-
- for (index = 0; index < num_fields; index++) {
- if (fields[index] != __ast_string_field_empty)
- fields[index] = new_base + (fields[index] - pool->base);
- }
-
- pool->base = new_base;
- pool->space += new_size - pool->size;
- pool->size = new_size;
}
- result = pool->base + pool->used;
- pool->used += needed;
- pool->space -= needed;
+ result = mgr->pool->base + mgr->used;
+ mgr->used += needed;
+ mgr->space -= needed;
return result;
}
-void __ast_string_field_index_build(struct ast_string_field_pool *pool,
+void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
ast_string_field *fields, int num_fields,
int index, const char *format, ...)
{
- char s;
size_t needed;
va_list ap1, ap2;
va_start(ap1, format);
va_copy(ap2, ap1);
- needed = vsnprintf(&s, 1, format, ap1) + 1;
+ needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
va_end(ap1);
- if ((fields[index] = __ast_string_field_alloc_space(pool, needed, fields, num_fields)))
- vsprintf((char *) fields[index], format, ap2);
+ if (needed > mgr->space) {
+ size_t new_size = mgr->size * 2;
+
+ while (new_size < needed)
+ new_size *= 2;
+
+ if (add_string_pool(mgr, new_size))
+ return;
+
+ vsprintf(mgr->pool->base + mgr->used, format, ap2);
+ }
+
+ fields[index] = mgr->pool->base + mgr->used;
+ mgr->used += needed;
+ mgr->space -= needed;
va_end(ap2);
}