19#ifndef _ASTERISK_VECTOR_H
20#define _ASTERISK_VECTOR_H
44#define AST_VECTOR(name, type) \
84 const char *input,
const char *delim,
int flags,
85 int (*excludes_cmp)(
const char *s1,
const char *s2));
104#define AST_VECTOR_RW(name, type) \
124#define AST_VECTOR_INIT(vec, size) ({ \
125 size_t __size = (size); \
126 size_t alloc_size = __size * sizeof(*((vec)->elems)); \
127 (vec)->elems = alloc_size ? ast_calloc(1, alloc_size) : NULL; \
128 (vec)->current = 0; \
129 if ((vec)->elems) { \
130 (vec)->max = __size; \
134 (alloc_size == 0 || (vec)->elems != NULL) ? 0 : -1; \
151#define AST_VECTOR_STEAL_ELEMENTS(vec) ({ \
152 typeof((vec)->elems) __elems = (vec)->elems; \
153 AST_VECTOR_INIT((vec), 0); \
169#define AST_VECTOR_RW_INIT(vec, size) ({ \
171 if (AST_VECTOR_INIT(vec, size) == 0) { \
172 res = ast_rwlock_init(&(vec)->lock); \
185#define AST_VECTOR_FREE(vec) do { \
186 ast_free((vec)->elems); \
187 (vec)->elems = NULL; \
189 (vec)->current = 0; \
200#define AST_VECTOR_PTR_FREE(vec) do { \
201 AST_VECTOR_FREE(vec); \
213#define AST_VECTOR_RW_FREE(vec) do { \
214 AST_VECTOR_FREE(vec); \
215 ast_rwlock_destroy(&(vec)->lock); \
226#define AST_VECTOR_RW_PTR_FREE(vec) do { \
227 AST_VECTOR_RW_FREE(vec); \
234#define __make_room(idx, vec) ({ \
237 if ((idx) >= (vec)->max) { \
238 size_t new_max = ((idx) + 1) * 2; \
239 typeof((vec)->elems) new_elems = ast_calloc(1, \
240 new_max * sizeof(*new_elems)); \
242 if ((vec)->elems) { \
243 memcpy(new_elems, (vec)->elems, \
244 (vec)->current * sizeof(*new_elems)); \
245 ast_free((vec)->elems); \
247 (vec)->elems = new_elems; \
248 (vec)->max = new_max; \
267#define AST_VECTOR_APPEND(vec, elem) ({ \
270 if (__make_room((vec)->current, vec) != 0) { \
274 (vec)->elems[(vec)->current++] = (elem); \
295#define AST_VECTOR_REPLACE(vec, idx, elem) ({ \
298 if (__make_room((idx), vec) != 0) { \
302 (vec)->elems[(idx)] = (elem); \
303 if (((idx) + 1) > (vec)->current) { \
304 (vec)->current = (idx) + 1; \
320#define AST_VECTOR_DEFAULT(vec, size, value) ({ \
322 typeof((size)) __size = (size) ? (size) : AST_VECTOR_SIZE(vec); \
324 for (idx = 0; idx < __size; ++idx) { \
325 res = AST_VECTOR_REPLACE(vec, idx, value); \
349#define AST_VECTOR_INSERT_AT(vec, idx, elem) ({ \
353 if (__make_room(((idx) > (vec)->current ? (idx) : (vec)->current), vec) != 0) { \
357 if ((vec)->current > 0 && (idx) < (vec)->current) { \
358 __move = ((vec)->current - (idx)) * sizeof(typeof((vec)->elems[0])); \
359 memmove(&(vec)->elems[(idx) + 1], &(vec)->elems[(idx)], __move); \
361 (vec)->elems[(idx)] = (elem); \
362 (vec)->current = ((idx) > (vec)->current ? (idx) : (vec)->current) + 1; \
382#define AST_VECTOR_ADD_SORTED(vec, elem, cmp) ({ \
384 size_t __idx = (vec)->current; \
385 typeof(elem) __elem = (elem); \
387 if (__make_room((vec)->current, vec) != 0) { \
391 while (__idx > 0 && (cmp((vec)->elems[__idx - 1], __elem) > 0)) { \
392 (vec)->elems[__idx] = (vec)->elems[__idx - 1]; \
395 (vec)->elems[__idx] = __elem; \
407#define AST_VECTOR_SORT(vec, cmp) ({ \
408 qsort((vec)->elems, (vec)->current, sizeof(typeof((vec)->elems[0])), cmp); \
422#define AST_VECTOR_BSEARCH(vec, key, cmp) ({ \
423 typeof(key) __key = (key); \
424 bsearch(&__key, (vec)->elems, (vec)->current, \
425 sizeof(typeof((vec)->elems[0])), cmp); \
440#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered) ({ \
441 typeof((vec)->elems[0]) res; \
442 size_t __idx = (idx); \
443 ast_assert(__idx < (vec)->current); \
444 res = (vec)->elems[__idx]; \
445 if ((preserve_ordered)) { \
447 __move = ((vec)->current - (__idx) - 1) * sizeof(typeof((vec)->elems[0])); \
448 memmove(&(vec)->elems[__idx], &(vec)->elems[__idx + 1], __move); \
451 (vec)->elems[__idx] = (vec)->elems[--(vec)->current]; \
466#define AST_VECTOR_REMOVE_UNORDERED(vec, idx) \
467 AST_VECTOR_REMOVE(vec, idx, 0)
476#define AST_VECTOR_REMOVE_ORDERED(vec, idx) \
477 AST_VECTOR_REMOVE(vec, idx, 1)
489#define AST_VECTOR_REMOVE_ALL_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
492 typeof(value) __value = (value); \
493 for (idx = 0; idx < (vec)->current; ) { \
494 if (cmp((vec)->elems[idx], __value)) { \
495 cleanup((vec)->elems[idx]); \
496 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
516#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
519 typeof(value) __value = (value); \
520 for (idx = 0; idx < (vec)->current; ++idx) { \
521 if (cmp((vec)->elems[idx], __value)) { \
522 cleanup((vec)->elems[idx]); \
523 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
541#define AST_VECTOR_REMOVE_ALL_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
544 typeof(value) __value = (value); \
545 for (idx = 0; idx < (vec)->current; ) { \
546 if (cmp((vec)->elems[idx], __value)) { \
547 cleanup((vec)->elems[idx]); \
548 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
568#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
571 typeof(value) __value = (value); \
572 for (idx = 0; idx < (vec)->current; ++idx) { \
573 if (cmp((vec)->elems[idx], __value)) { \
574 cleanup((vec)->elems[idx]); \
575 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
592#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value) ((elem) == (value))
599#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
611#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup) ({ \
612 AST_VECTOR_REMOVE_CMP_UNORDERED((vec), (elem), \
613 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
626#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup) ({ \
627 AST_VECTOR_REMOVE_CMP_ORDERED((vec), (elem), \
628 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
637#define AST_VECTOR_SIZE(vec) (vec)->current
645#define AST_VECTOR_MAX_SIZE(vec) (vec)->max
653#define AST_VECTOR_RESET(vec, cleanup) ({ \
654 AST_VECTOR_CALLBACK_VOID(vec, cleanup); \
655 (vec)->current = 0; \
666#define AST_VECTOR_COMPACT(vec) ({ \
669 size_t new_max = (vec)->current; \
670 if (new_max == 0) { \
671 ast_free((vec)->elems); \
672 (vec)->elems = NULL; \
674 } else if ((vec)->max > new_max) { \
675 typeof((vec)->elems) new_elems = ast_realloc( \
677 new_max * sizeof(*new_elems)); \
679 (vec)->elems = new_elems; \
680 (vec)->max = new_max; \
696#define AST_VECTOR_GET_ADDR(vec, idx) ({ \
697 size_t __idx = (idx); \
698 ast_assert(__idx < (vec)->current); \
699 &(vec)->elems[__idx]; \
708#define AST_VECTOR_GET(vec, idx) ({ \
709 size_t __idx = (idx); \
710 ast_assert(__idx < (vec)->current); \
711 (vec)->elems[__idx]; \
724#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp) ({ \
727 typeof(nth) __nth = (nth); \
728 typeof(value) __value = (value); \
729 for (idx = 0; idx < (vec)->current; ++idx) { \
730 if (cmp((vec)->elems[idx], __value) && !(--__nth)) { \
747#define AST_VECTOR_GET_INDEX(vec, value, cmp) \
748 AST_VECTOR_GET_INDEX_NTH(vec, 1, value, cmp)
759#define AST_VECTOR_GET_CMP(vec, value, cmp) ({ \
762 typeof(value) __value = (value); \
763 for (idx = 0; idx < (vec)->current; ++idx) { \
764 if (cmp((vec)->elems[idx], __value)) { \
765 res = &(vec)->elems[idx]; \
779#define AST_VECTOR_MATCH_ALL(element) (CMP_MATCH)
793#define AST_VECTOR_CALLBACK(vec, callback, default_value, ...) ({ \
795 typeof((vec)->elems[0]) res = default_value; \
796 for (idx = 0; idx < (vec)->current; idx++) { \
797 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
798 if (rc & CMP_MATCH) { \
799 res = (vec)->elems[idx]; \
802 if (rc & CMP_STOP) { \
857#define AST_VECTOR_CALLBACK_MULTIPLE(vec, callback, ...) ({ \
859 typeof((vec)) new_vec; \
861 new_vec = ast_malloc(sizeof(*new_vec)); \
865 if (AST_VECTOR_INIT(new_vec, AST_VECTOR_SIZE((vec))) != 0) { \
870 for (idx = 0; idx < (vec)->current; idx++) { \
871 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
872 if (rc & CMP_MATCH) { \
873 AST_VECTOR_APPEND(new_vec, (vec)->elems[idx]); \
875 if (rc & CMP_STOP) { \
890#define AST_VECTOR_CALLBACK_VOID(vec, callback, ...) ({ \
892 for (idx = 0; idx < (vec)->current; idx++) { \
893 callback((vec)->elems[idx], ##__VA_ARGS__); \
905#define AST_VECTOR_RW_RDLOCK(vec) ast_rwlock_rdlock(&(vec)->lock)
915#define AST_VECTOR_RW_WRLOCK(vec) ast_rwlock_wrlock(&(vec)->lock)
925#define AST_VECTOR_RW_UNLOCK(vec) ast_rwlock_unlock(&(vec)->lock)
935#define AST_VECTOR_RW_RDLOCK_TRY(vec) ast_rwlock_tryrdlock(&(vec)->lock)
945#define AST_VECTOR_RW_WRLOCK_TRY(vec) ast_rwlock_trywrlock(&(vec)->lock)
956#define AST_VECTOR_RW_RDLOCK_TIMED(vec, timespec) ast_rwlock_timedrdlock(&(vec)->lock, timespec)
967#define AST_VECTOR_RW_WRLOCK_TIMED(vec, timespec) ast_rwlock_timedwrlock(&(vec)->lock, timespec)
Asterisk locking-related definitions:
Integer vector definition.
String vector definitions.
char * ast_vector_string_join(struct ast_vector_string *vec, const char *delim)
Join the elements of a string vector into a single string.
ast_vector_string_split_flags
@ AST_VECTOR_STRING_SPLIT_NO_TRIM
@ AST_VECTOR_STRING_SPLIT_ALLOW_EMPTY
int ast_vector_string_split(struct ast_vector_string *dest, const char *input, const char *delim, int flags, int(*excludes_cmp)(const char *s1, const char *s2))
Append a string vector by splitting a string.
#define AST_VECTOR(name, type)
Define a vector structure.