diff options
Diffstat (limited to 'main/format_cap.c')
-rw-r--r-- | main/format_cap.c | 111 |
1 files changed, 75 insertions, 36 deletions
diff --git a/main/format_cap.c b/main/format_cap.c index 5fc110812..96c2fa3aa 100644 --- a/main/format_cap.c +++ b/main/format_cap.c @@ -38,13 +38,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$"); #include "asterisk/astobj2.h" #include "asterisk/utils.h" +#define FORMAT_STR_BUFSIZE 256 struct ast_format_cap { /* The capabilities structure is just an ao2 container of ast_formats */ struct ao2_container *formats; struct ao2_iterator it; /*! TRUE if the formats container created without a lock. */ - int nolock; + struct ast_flags flags; + unsigned int string_cache_valid; + char format_strs[0]; }; /*! format exists within capabilities structure if it is identical to @@ -67,17 +70,27 @@ static int hash_cb(const void *obj, const int flags) return format->id; } -static struct ast_format_cap *cap_alloc_helper(int nolock) +struct ast_format_cap *ast_format_cap_alloc(enum ast_format_cap_flags flags) { - struct ast_format_cap *cap = ast_calloc(1, sizeof(*cap)); + struct ast_format_cap *cap; + unsigned int alloc_size; + + alloc_size = sizeof(*cap); + if (flags & AST_FORMAT_CAP_FLAG_CACHE_STRINGS) { + alloc_size += FORMAT_STR_BUFSIZE; + } + cap = ast_calloc(1, alloc_size); if (!cap) { return NULL; } - cap->nolock = nolock; + + ast_set_flag(&cap->flags, flags); cap->formats = ao2_container_alloc_options( - nolock ? AO2_ALLOC_OPT_LOCK_NOLOCK : AO2_ALLOC_OPT_LOCK_MUTEX, - 283, hash_cb, cmp_cb); + (flags & AST_FORMAT_CAP_FLAG_NOLOCK) ? + AO2_ALLOC_OPT_LOCK_NOLOCK : + AO2_ALLOC_OPT_LOCK_MUTEX, + 11, hash_cb, cmp_cb); if (!cap->formats) { ast_free(cap); return NULL; @@ -86,16 +99,6 @@ static struct ast_format_cap *cap_alloc_helper(int nolock) return cap; } -struct ast_format_cap *ast_format_cap_alloc_nolock(void) -{ - return cap_alloc_helper(1); -} - -struct ast_format_cap *ast_format_cap_alloc(void) -{ - return cap_alloc_helper(0); -} - void *ast_format_cap_destroy(struct ast_format_cap *cap) { if (!cap) { @@ -106,7 +109,7 @@ void *ast_format_cap_destroy(struct ast_format_cap *cap) return NULL; } -void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format) +static void format_cap_add(struct ast_format_cap *cap, const struct ast_format *format) { struct ast_format *fnew; @@ -118,9 +121,16 @@ void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *for } ast_format_copy(fnew, format); ao2_link(cap->formats, fnew); + ao2_ref(fnew, -1); } +void ast_format_cap_add(struct ast_format_cap *cap, const struct ast_format *format) +{ + format_cap_add(cap, format); + cap->string_cache_valid = 0; +} + void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_type type) { int x; @@ -129,9 +139,10 @@ void ast_format_cap_add_all_by_type(struct ast_format_cap *cap, enum ast_format_ for (x = 0; x < f_len; x++) { if (AST_FORMAT_GET_TYPE(f_list[x].format.id) == type) { - ast_format_cap_add(cap, &f_list[x].format); + format_cap_add(cap, &f_list[x].format); } } + cap->string_cache_valid = 0; ast_format_list_destroy(f_list); } @@ -142,8 +153,9 @@ void ast_format_cap_add_all(struct ast_format_cap *cap) const struct ast_format_list *f_list = ast_format_list_get(&f_len); for (x = 0; x < f_len; x++) { - ast_format_cap_add(cap, &f_list[x].format); + format_cap_add(cap, &f_list[x].format); } + cap->string_cache_valid = 0; ast_format_list_destroy(f_list); } @@ -153,7 +165,7 @@ static int append_cb(void *obj, void *arg, int flag) struct ast_format *format = (struct ast_format *) obj; if (!ast_format_cap_iscompatible(result, format)) { - ast_format_cap_add(result, format); + format_cap_add(result, format); } return 0; @@ -162,6 +174,7 @@ static int append_cb(void *obj, void *arg, int flag) void ast_format_cap_append(struct ast_format_cap *dst, const struct ast_format_cap *src) { ao2_callback(src->formats, OBJ_NODATA, append_cb, dst); + dst->string_cache_valid = 0; } static int copy_cb(void *obj, void *arg, int flag) @@ -169,28 +182,32 @@ static int copy_cb(void *obj, void *arg, int flag) struct ast_format_cap *result = (struct ast_format_cap *) arg; struct ast_format *format = (struct ast_format *) obj; - ast_format_cap_add(result, format); + format_cap_add(result, format); return 0; } +static void format_cap_remove_all(struct ast_format_cap *cap) +{ + ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL); +} + void ast_format_cap_copy(struct ast_format_cap *dst, const struct ast_format_cap *src) { - ast_format_cap_remove_all(dst); + format_cap_remove_all(dst); ao2_callback(src->formats, OBJ_NODATA, copy_cb, dst); + dst->string_cache_valid = 0; } struct ast_format_cap *ast_format_cap_dup(const struct ast_format_cap *cap) { struct ast_format_cap *dst; - if (cap->nolock) { - dst = ast_format_cap_alloc_nolock(); - } else { - dst = ast_format_cap_alloc(); - } + + dst = ast_format_cap_alloc(ast_test_flag(&cap->flags, AST_FLAGS_ALL)); if (!dst) { return NULL; } ao2_callback(cap->formats, OBJ_NODATA, copy_cb, dst); + dst->string_cache_valid = 0; return dst; } @@ -217,6 +234,7 @@ int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format) fremove = ao2_callback(cap->formats, OBJ_POINTER | OBJ_UNLINK, find_exact_cb, format); if (fremove) { ao2_ref(fremove, -1); + cap->string_cache_valid = 0; return 0; } @@ -259,6 +277,7 @@ int ast_format_cap_remove_byid(struct ast_format_cap *cap, enum ast_format_id id /* match_found will be set if at least one item was removed */ if (data.match_found) { + cap->string_cache_valid = 0; return 0; } @@ -278,17 +297,20 @@ void ast_format_cap_remove_bytype(struct ast_format_cap *cap, enum ast_format_ty OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, multiple_by_type_cb, &type); + cap->string_cache_valid = 0; } void ast_format_cap_remove_all(struct ast_format_cap *cap) { - ao2_callback(cap->formats, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, NULL, NULL); + format_cap_remove_all(cap); + cap->string_cache_valid = 0; } void ast_format_cap_set(struct ast_format_cap *cap, struct ast_format *format) { - ast_format_cap_remove_all(cap); - ast_format_cap_add(cap, format); + format_cap_remove_all(cap); + format_cap_add(cap, format); + cap->string_cache_valid = 0; } int ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format, struct ast_format *result) @@ -434,7 +456,7 @@ int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast struct ast_format_cap *ast_format_cap_joint(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2) { struct ao2_iterator it; - struct ast_format_cap *result = ast_format_cap_alloc_nolock(); + struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); struct ast_format *tmp; struct find_joint_data data = { .joint_found = 0, @@ -472,7 +494,7 @@ static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast .joint_found = 0, }; if (!append) { - ast_format_cap_remove_all(result); + format_cap_remove_all(result); } it = ao2_iterator_init(cap1->formats, 0); while ((tmp = ao2_iterator_next(&it))) { @@ -485,6 +507,8 @@ static int joint_copy_helper(const struct ast_format_cap *cap1, const struct ast } ao2_iterator_destroy(&it); + result->string_cache_valid = 0; + return ao2_container_count(result->formats) ? 1 : 0; } @@ -501,7 +525,7 @@ int ast_format_cap_joint_copy(const struct ast_format_cap *cap1, const struct as struct ast_format_cap *ast_format_cap_get_type(const struct ast_format_cap *cap, enum ast_format_type ftype) { struct ao2_iterator it; - struct ast_format_cap *result = ast_format_cap_alloc_nolock(); + struct ast_format_cap *result = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK); struct ast_format *tmp; if (!result) { @@ -575,7 +599,7 @@ int ast_format_cap_iter_next(struct ast_format_cap *cap, struct ast_format *form return 0; } -char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) +static char *getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) { int x; unsigned len; @@ -611,6 +635,20 @@ char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap * return buf; } +char *ast_getformatname_multiple(char *buf, size_t size, struct ast_format_cap *cap) +{ + if (ast_test_flag(&cap->flags, AST_FORMAT_CAP_FLAG_CACHE_STRINGS)) { + if (!cap->string_cache_valid) { + getformatname_multiple(cap->format_strs, FORMAT_STR_BUFSIZE, cap); + cap->string_cache_valid = 1; + } + ast_copy_string(buf, cap->format_strs, size); + return buf; + } + + return getformatname_multiple(buf, size, cap); +} + uint64_t ast_format_cap_to_old_bitfield(const struct ast_format_cap *cap) { uint64_t res = 0; @@ -632,11 +670,12 @@ void ast_format_cap_from_old_bitfield(struct ast_format_cap *dst, uint64_t src) int x; struct ast_format tmp_format = { 0, }; - ast_format_cap_remove_all(dst); + format_cap_remove_all(dst); for (x = 0; x < 64; x++) { tmp = (1ULL << x); if (tmp & src) { - ast_format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp)); + format_cap_add(dst, ast_format_from_old_bitfield(&tmp_format, tmp)); } } + dst->string_cache_valid = 0; } |