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) 
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.