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); \
423#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered) ({ \
424 typeof((vec)->elems[0]) res; \
425 size_t __idx = (idx); \
426 ast_assert(__idx < (vec)->current); \
427 res = (vec)->elems[__idx]; \
428 if ((preserve_ordered)) { \
430 __move = ((vec)->current - (__idx) - 1) * sizeof(typeof((vec)->elems[0])); \
431 memmove(&(vec)->elems[__idx], &(vec)->elems[__idx + 1], __move); \
434 (vec)->elems[__idx] = (vec)->elems[--(vec)->current]; \
449#define AST_VECTOR_REMOVE_UNORDERED(vec, idx) \
450 AST_VECTOR_REMOVE(vec, idx, 0)
459#define AST_VECTOR_REMOVE_ORDERED(vec, idx) \
460 AST_VECTOR_REMOVE(vec, idx, 1)
472#define AST_VECTOR_REMOVE_ALL_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
475 typeof(value) __value = (value); \
476 for (idx = 0; idx < (vec)->current; ) { \
477 if (cmp((vec)->elems[idx], __value)) { \
478 cleanup((vec)->elems[idx]); \
479 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
499#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
502 typeof(value) __value = (value); \
503 for (idx = 0; idx < (vec)->current; ++idx) { \
504 if (cmp((vec)->elems[idx], __value)) { \
505 cleanup((vec)->elems[idx]); \
506 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
524#define AST_VECTOR_REMOVE_ALL_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
527 typeof(value) __value = (value); \
528 for (idx = 0; idx < (vec)->current; ) { \
529 if (cmp((vec)->elems[idx], __value)) { \
530 cleanup((vec)->elems[idx]); \
531 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
551#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
554 typeof(value) __value = (value); \
555 for (idx = 0; idx < (vec)->current; ++idx) { \
556 if (cmp((vec)->elems[idx], __value)) { \
557 cleanup((vec)->elems[idx]); \
558 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
575#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value) ((elem) == (value))
582#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
594#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup) ({ \
595 AST_VECTOR_REMOVE_CMP_UNORDERED((vec), (elem), \
596 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
609#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup) ({ \
610 AST_VECTOR_REMOVE_CMP_ORDERED((vec), (elem), \
611 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
620#define AST_VECTOR_SIZE(vec) (vec)->current
628#define AST_VECTOR_MAX_SIZE(vec) (vec)->max
636#define AST_VECTOR_RESET(vec, cleanup) ({ \
637 AST_VECTOR_CALLBACK_VOID(vec, cleanup); \
638 (vec)->current = 0; \
649#define AST_VECTOR_COMPACT(vec) ({ \
652 size_t new_max = (vec)->current; \
653 if (new_max == 0) { \
654 ast_free((vec)->elems); \
655 (vec)->elems = NULL; \
657 } else if ((vec)->max > new_max) { \
658 typeof((vec)->elems) new_elems = ast_realloc( \
660 new_max * sizeof(*new_elems)); \
662 (vec)->elems = new_elems; \
663 (vec)->max = new_max; \
679#define AST_VECTOR_GET_ADDR(vec, idx) ({ \
680 size_t __idx = (idx); \
681 ast_assert(__idx < (vec)->current); \
682 &(vec)->elems[__idx]; \
691#define AST_VECTOR_GET(vec, idx) ({ \
692 size_t __idx = (idx); \
693 ast_assert(__idx < (vec)->current); \
694 (vec)->elems[__idx]; \
707#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp) ({ \
710 typeof(nth) __nth = (nth); \
711 typeof(value) __value = (value); \
712 for (idx = 0; idx < (vec)->current; ++idx) { \
713 if (cmp((vec)->elems[idx], __value) && !(--__nth)) { \
730#define AST_VECTOR_GET_INDEX(vec, value, cmp) \
731 AST_VECTOR_GET_INDEX_NTH(vec, 1, value, cmp)
742#define AST_VECTOR_GET_CMP(vec, value, cmp) ({ \
745 typeof(value) __value = (value); \
746 for (idx = 0; idx < (vec)->current; ++idx) { \
747 if (cmp((vec)->elems[idx], __value)) { \
748 res = &(vec)->elems[idx]; \
762#define AST_VECTOR_MATCH_ALL(element) (CMP_MATCH)
776#define AST_VECTOR_CALLBACK(vec, callback, default_value, ...) ({ \
778 typeof((vec)->elems[0]) res = default_value; \
779 for (idx = 0; idx < (vec)->current; idx++) { \
780 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
781 if (rc & CMP_MATCH) { \
782 res = (vec)->elems[idx]; \
785 if (rc & CMP_STOP) { \
840#define AST_VECTOR_CALLBACK_MULTIPLE(vec, callback, ...) ({ \
842 typeof((vec)) new_vec; \
844 new_vec = ast_malloc(sizeof(*new_vec)); \
848 if (AST_VECTOR_INIT(new_vec, AST_VECTOR_SIZE((vec))) != 0) { \
853 for (idx = 0; idx < (vec)->current; idx++) { \
854 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
855 if (rc & CMP_MATCH) { \
856 AST_VECTOR_APPEND(new_vec, (vec)->elems[idx]); \
858 if (rc & CMP_STOP) { \
873#define AST_VECTOR_CALLBACK_VOID(vec, callback, ...) ({ \
875 for (idx = 0; idx < (vec)->current; idx++) { \
876 callback((vec)->elems[idx], ##__VA_ARGS__); \
888#define AST_VECTOR_RW_RDLOCK(vec) ast_rwlock_rdlock(&(vec)->lock)
898#define AST_VECTOR_RW_WRLOCK(vec) ast_rwlock_wrlock(&(vec)->lock)
908#define AST_VECTOR_RW_UNLOCK(vec) ast_rwlock_unlock(&(vec)->lock)
918#define AST_VECTOR_RW_RDLOCK_TRY(vec) ast_rwlock_tryrdlock(&(vec)->lock)
928#define AST_VECTOR_RW_WRLOCK_TRY(vec) ast_rwlock_trywrlock(&(vec)->lock)
939#define AST_VECTOR_RW_RDLOCK_TIMED(vec, timespec) ast_rwlock_timedrdlock(&(vec)->lock, timespec)
950#define AST_VECTOR_RW_WRLOCK_TIMED(vec, timespec) ast_rwlock_timedwrlock(&(vec)->lock, timespec)
static int input(yyscan_t yyscanner)
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.