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));
93#define AST_VECTOR_RW(name, type) \
113#define AST_VECTOR_INIT(vec, size) ({ \
114 size_t __size = (size); \
115 size_t alloc_size = __size * sizeof(*((vec)->elems)); \
116 (vec)->elems = alloc_size ? ast_calloc(1, alloc_size) : NULL; \
117 (vec)->current = 0; \
118 if ((vec)->elems) { \
119 (vec)->max = __size; \
123 (alloc_size == 0 || (vec)->elems != NULL) ? 0 : -1; \
140#define AST_VECTOR_STEAL_ELEMENTS(vec) ({ \
141 typeof((vec)->elems) __elems = (vec)->elems; \
142 AST_VECTOR_INIT((vec), 0); \
158#define AST_VECTOR_RW_INIT(vec, size) ({ \
160 if (AST_VECTOR_INIT(vec, size) == 0) { \
161 res = ast_rwlock_init(&(vec)->lock); \
174#define AST_VECTOR_FREE(vec) do { \
175 ast_free((vec)->elems); \
176 (vec)->elems = NULL; \
178 (vec)->current = 0; \
189#define AST_VECTOR_PTR_FREE(vec) do { \
190 AST_VECTOR_FREE(vec); \
202#define AST_VECTOR_RW_FREE(vec) do { \
203 AST_VECTOR_FREE(vec); \
204 ast_rwlock_destroy(&(vec)->lock); \
215#define AST_VECTOR_RW_PTR_FREE(vec) do { \
216 AST_VECTOR_RW_FREE(vec); \
223#define __make_room(idx, vec) ({ \
226 if ((idx) >= (vec)->max) { \
227 size_t new_max = ((idx) + 1) * 2; \
228 typeof((vec)->elems) new_elems = ast_calloc(1, \
229 new_max * sizeof(*new_elems)); \
231 if ((vec)->elems) { \
232 memcpy(new_elems, (vec)->elems, \
233 (vec)->current * sizeof(*new_elems)); \
234 ast_free((vec)->elems); \
236 (vec)->elems = new_elems; \
237 (vec)->max = new_max; \
256#define AST_VECTOR_APPEND(vec, elem) ({ \
259 if (__make_room((vec)->current, vec) != 0) { \
263 (vec)->elems[(vec)->current++] = (elem); \
284#define AST_VECTOR_REPLACE(vec, idx, elem) ({ \
287 if (__make_room((idx), vec) != 0) { \
291 (vec)->elems[(idx)] = (elem); \
292 if (((idx) + 1) > (vec)->current) { \
293 (vec)->current = (idx) + 1; \
309#define AST_VECTOR_DEFAULT(vec, size, value) ({ \
311 typeof((size)) __size = (size) ? (size) : AST_VECTOR_SIZE(vec); \
313 for (idx = 0; idx < __size; ++idx) { \
314 res = AST_VECTOR_REPLACE(vec, idx, value); \
338#define AST_VECTOR_INSERT_AT(vec, idx, elem) ({ \
342 if (__make_room(((idx) > (vec)->current ? (idx) : (vec)->current), vec) != 0) { \
346 if ((vec)->current > 0 && (idx) < (vec)->current) { \
347 __move = ((vec)->current - (idx)) * sizeof(typeof((vec)->elems[0])); \
348 memmove(&(vec)->elems[(idx) + 1], &(vec)->elems[(idx)], __move); \
350 (vec)->elems[(idx)] = (elem); \
351 (vec)->current = ((idx) > (vec)->current ? (idx) : (vec)->current) + 1; \
371#define AST_VECTOR_ADD_SORTED(vec, elem, cmp) ({ \
373 size_t __idx = (vec)->current; \
374 typeof(elem) __elem = (elem); \
376 if (__make_room((vec)->current, vec) != 0) { \
380 while (__idx > 0 && (cmp((vec)->elems[__idx - 1], __elem) > 0)) { \
381 (vec)->elems[__idx] = (vec)->elems[__idx - 1]; \
384 (vec)->elems[__idx] = __elem; \
396#define AST_VECTOR_SORT(vec, cmp) ({ \
397 qsort((vec)->elems, (vec)->current, sizeof(typeof((vec)->elems[0])), cmp); \
412#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered) ({ \
413 typeof((vec)->elems[0]) res; \
414 size_t __idx = (idx); \
415 ast_assert(__idx < (vec)->current); \
416 res = (vec)->elems[__idx]; \
417 if ((preserve_ordered)) { \
419 __move = ((vec)->current - (__idx) - 1) * sizeof(typeof((vec)->elems[0])); \
420 memmove(&(vec)->elems[__idx], &(vec)->elems[__idx + 1], __move); \
423 (vec)->elems[__idx] = (vec)->elems[--(vec)->current]; \
438#define AST_VECTOR_REMOVE_UNORDERED(vec, idx) \
439 AST_VECTOR_REMOVE(vec, idx, 0)
448#define AST_VECTOR_REMOVE_ORDERED(vec, idx) \
449 AST_VECTOR_REMOVE(vec, idx, 1)
461#define AST_VECTOR_REMOVE_ALL_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
464 typeof(value) __value = (value); \
465 for (idx = 0; idx < (vec)->current; ) { \
466 if (cmp((vec)->elems[idx], __value)) { \
467 cleanup((vec)->elems[idx]); \
468 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
488#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup) ({ \
491 typeof(value) __value = (value); \
492 for (idx = 0; idx < (vec)->current; ++idx) { \
493 if (cmp((vec)->elems[idx], __value)) { \
494 cleanup((vec)->elems[idx]); \
495 AST_VECTOR_REMOVE_UNORDERED((vec), idx); \
513#define AST_VECTOR_REMOVE_ALL_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
516 typeof(value) __value = (value); \
517 for (idx = 0; idx < (vec)->current; ) { \
518 if (cmp((vec)->elems[idx], __value)) { \
519 cleanup((vec)->elems[idx]); \
520 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
540#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup) ({ \
543 typeof(value) __value = (value); \
544 for (idx = 0; idx < (vec)->current; ++idx) { \
545 if (cmp((vec)->elems[idx], __value)) { \
546 cleanup((vec)->elems[idx]); \
547 AST_VECTOR_REMOVE_ORDERED((vec), idx); \
564#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value) ((elem) == (value))
571#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
583#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup) ({ \
584 AST_VECTOR_REMOVE_CMP_UNORDERED((vec), (elem), \
585 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
598#define AST_VECTOR_REMOVE_ELEM_ORDERED(vec, elem, cleanup) ({ \
599 AST_VECTOR_REMOVE_CMP_ORDERED((vec), (elem), \
600 AST_VECTOR_ELEM_DEFAULT_CMP, cleanup); \
609#define AST_VECTOR_SIZE(vec) (vec)->current
617#define AST_VECTOR_MAX_SIZE(vec) (vec)->max
625#define AST_VECTOR_RESET(vec, cleanup) ({ \
626 AST_VECTOR_CALLBACK_VOID(vec, cleanup); \
627 (vec)->current = 0; \
638#define AST_VECTOR_COMPACT(vec) ({ \
641 size_t new_max = (vec)->current; \
642 if (new_max == 0) { \
643 ast_free((vec)->elems); \
644 (vec)->elems = NULL; \
646 } else if ((vec)->max > new_max) { \
647 typeof((vec)->elems) new_elems = ast_realloc( \
649 new_max * sizeof(*new_elems)); \
651 (vec)->elems = new_elems; \
652 (vec)->max = new_max; \
668#define AST_VECTOR_GET_ADDR(vec, idx) ({ \
669 size_t __idx = (idx); \
670 ast_assert(__idx < (vec)->current); \
671 &(vec)->elems[__idx]; \
680#define AST_VECTOR_GET(vec, idx) ({ \
681 size_t __idx = (idx); \
682 ast_assert(__idx < (vec)->current); \
683 (vec)->elems[__idx]; \
696#define AST_VECTOR_GET_INDEX_NTH(vec, nth, value, cmp) ({ \
699 typeof(nth) __nth = (nth); \
700 typeof(value) __value = (value); \
701 for (idx = 0; idx < (vec)->current; ++idx) { \
702 if (cmp((vec)->elems[idx], __value) && !(--__nth)) { \
719#define AST_VECTOR_GET_INDEX(vec, value, cmp) \
720 AST_VECTOR_GET_INDEX_NTH(vec, 1, value, cmp)
731#define AST_VECTOR_GET_CMP(vec, value, cmp) ({ \
734 typeof(value) __value = (value); \
735 for (idx = 0; idx < (vec)->current; ++idx) { \
736 if (cmp((vec)->elems[idx], __value)) { \
737 res = &(vec)->elems[idx]; \
751#define AST_VECTOR_MATCH_ALL(element) (CMP_MATCH)
765#define AST_VECTOR_CALLBACK(vec, callback, default_value, ...) ({ \
767 typeof((vec)->elems[0]) res = default_value; \
768 for (idx = 0; idx < (vec)->current; idx++) { \
769 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
770 if (rc & CMP_MATCH) { \
771 res = (vec)->elems[idx]; \
774 if (rc & CMP_STOP) { \
829#define AST_VECTOR_CALLBACK_MULTIPLE(vec, callback, ...) ({ \
831 typeof((vec)) new_vec; \
833 new_vec = ast_malloc(sizeof(*new_vec)); \
837 if (AST_VECTOR_INIT(new_vec, AST_VECTOR_SIZE((vec))) != 0) { \
842 for (idx = 0; idx < (vec)->current; idx++) { \
843 int rc = callback((vec)->elems[idx], ##__VA_ARGS__); \
844 if (rc & CMP_MATCH) { \
845 AST_VECTOR_APPEND(new_vec, (vec)->elems[idx]); \
847 if (rc & CMP_STOP) { \
862#define AST_VECTOR_CALLBACK_VOID(vec, callback, ...) ({ \
864 for (idx = 0; idx < (vec)->current; idx++) { \
865 callback((vec)->elems[idx], ##__VA_ARGS__); \
877#define AST_VECTOR_RW_RDLOCK(vec) ast_rwlock_rdlock(&(vec)->lock)
887#define AST_VECTOR_RW_WRLOCK(vec) ast_rwlock_wrlock(&(vec)->lock)
897#define AST_VECTOR_RW_UNLOCK(vec) ast_rwlock_unlock(&(vec)->lock)
907#define AST_VECTOR_RW_RDLOCK_TRY(vec) ast_rwlock_tryrdlock(&(vec)->lock)
917#define AST_VECTOR_RW_WRLOCK_TRY(vec) ast_rwlock_trywrlock(&(vec)->lock)
928#define AST_VECTOR_RW_RDLOCK_TIMED(vec, timespec) ast_rwlock_timedrdlock(&(vec)->lock, timespec)
939#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.
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.