153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  Copyright 2004-2008 Lennart Poettering
553a5a1b3Sopenharmony_ci
653a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
753a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as
853a5a1b3Sopenharmony_ci  published by the Free Software Foundation; either version 2.1 of the
953a5a1b3Sopenharmony_ci  License, or (at your option) any later version.
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1253a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1353a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1453a5a1b3Sopenharmony_ci  Lesser General Public License for more details.
1553a5a1b3Sopenharmony_ci
1653a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public
1753a5a1b3Sopenharmony_ci  License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1853a5a1b3Sopenharmony_ci***/
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2153a5a1b3Sopenharmony_ci#include <config.h>
2253a5a1b3Sopenharmony_ci#endif
2353a5a1b3Sopenharmony_ci
2453a5a1b3Sopenharmony_ci#include <string.h>
2553a5a1b3Sopenharmony_ci#include <stdlib.h>
2653a5a1b3Sopenharmony_ci
2753a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
2853a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
2953a5a1b3Sopenharmony_ci
3053a5a1b3Sopenharmony_ci#include "dynarray.h"
3153a5a1b3Sopenharmony_ci
3253a5a1b3Sopenharmony_cistruct pa_dynarray {
3353a5a1b3Sopenharmony_ci    void **data;
3453a5a1b3Sopenharmony_ci    unsigned n_allocated, n_entries;
3553a5a1b3Sopenharmony_ci    pa_free_cb_t free_cb;
3653a5a1b3Sopenharmony_ci};
3753a5a1b3Sopenharmony_ci
3853a5a1b3Sopenharmony_cipa_dynarray* pa_dynarray_new(pa_free_cb_t free_cb) {
3953a5a1b3Sopenharmony_ci    pa_dynarray *array;
4053a5a1b3Sopenharmony_ci
4153a5a1b3Sopenharmony_ci    array = pa_xnew0(pa_dynarray, 1);
4253a5a1b3Sopenharmony_ci    array->free_cb = free_cb;
4353a5a1b3Sopenharmony_ci
4453a5a1b3Sopenharmony_ci    return array;
4553a5a1b3Sopenharmony_ci}
4653a5a1b3Sopenharmony_ci
4753a5a1b3Sopenharmony_civoid pa_dynarray_free(pa_dynarray *array) {
4853a5a1b3Sopenharmony_ci    unsigned i;
4953a5a1b3Sopenharmony_ci    pa_assert(array);
5053a5a1b3Sopenharmony_ci
5153a5a1b3Sopenharmony_ci    if (array->free_cb)
5253a5a1b3Sopenharmony_ci        for (i = 0; i < array->n_entries; i++)
5353a5a1b3Sopenharmony_ci            array->free_cb(array->data[i]);
5453a5a1b3Sopenharmony_ci
5553a5a1b3Sopenharmony_ci    pa_xfree(array->data);
5653a5a1b3Sopenharmony_ci    pa_xfree(array);
5753a5a1b3Sopenharmony_ci}
5853a5a1b3Sopenharmony_ci
5953a5a1b3Sopenharmony_civoid pa_dynarray_append(pa_dynarray *array, void *p) {
6053a5a1b3Sopenharmony_ci    pa_assert(array);
6153a5a1b3Sopenharmony_ci    pa_assert(p);
6253a5a1b3Sopenharmony_ci
6353a5a1b3Sopenharmony_ci    if (array->n_entries == array->n_allocated) {
6453a5a1b3Sopenharmony_ci        unsigned n = PA_MAX(array->n_allocated * 2, 25U);
6553a5a1b3Sopenharmony_ci
6653a5a1b3Sopenharmony_ci        array->data = pa_xrealloc(array->data, sizeof(void *) * n);
6753a5a1b3Sopenharmony_ci        array->n_allocated = n;
6853a5a1b3Sopenharmony_ci    }
6953a5a1b3Sopenharmony_ci
7053a5a1b3Sopenharmony_ci    array->data[array->n_entries++] = p;
7153a5a1b3Sopenharmony_ci}
7253a5a1b3Sopenharmony_ci
7353a5a1b3Sopenharmony_civoid *pa_dynarray_get(pa_dynarray *array, unsigned i) {
7453a5a1b3Sopenharmony_ci    pa_assert(array);
7553a5a1b3Sopenharmony_ci
7653a5a1b3Sopenharmony_ci    if (i >= array->n_entries)
7753a5a1b3Sopenharmony_ci        return NULL;
7853a5a1b3Sopenharmony_ci
7953a5a1b3Sopenharmony_ci    return array->data[i];
8053a5a1b3Sopenharmony_ci}
8153a5a1b3Sopenharmony_ci
8253a5a1b3Sopenharmony_civoid *pa_dynarray_last(pa_dynarray *array) {
8353a5a1b3Sopenharmony_ci    pa_assert(array);
8453a5a1b3Sopenharmony_ci
8553a5a1b3Sopenharmony_ci    if (array->n_entries == 0)
8653a5a1b3Sopenharmony_ci        return NULL;
8753a5a1b3Sopenharmony_ci
8853a5a1b3Sopenharmony_ci    return array->data[array->n_entries - 1];
8953a5a1b3Sopenharmony_ci}
9053a5a1b3Sopenharmony_ci
9153a5a1b3Sopenharmony_ciint pa_dynarray_remove_by_index(pa_dynarray *array, unsigned i) {
9253a5a1b3Sopenharmony_ci    void *entry;
9353a5a1b3Sopenharmony_ci
9453a5a1b3Sopenharmony_ci    pa_assert(array);
9553a5a1b3Sopenharmony_ci
9653a5a1b3Sopenharmony_ci    if (i >= array->n_entries)
9753a5a1b3Sopenharmony_ci        return -PA_ERR_NOENTITY;
9853a5a1b3Sopenharmony_ci
9953a5a1b3Sopenharmony_ci    entry = array->data[i];
10053a5a1b3Sopenharmony_ci    array->data[i] = array->data[array->n_entries - 1];
10153a5a1b3Sopenharmony_ci    array->n_entries--;
10253a5a1b3Sopenharmony_ci
10353a5a1b3Sopenharmony_ci    if (array->free_cb)
10453a5a1b3Sopenharmony_ci        array->free_cb(entry);
10553a5a1b3Sopenharmony_ci
10653a5a1b3Sopenharmony_ci    return 0;
10753a5a1b3Sopenharmony_ci}
10853a5a1b3Sopenharmony_ci
10953a5a1b3Sopenharmony_ciint pa_dynarray_remove_by_data(pa_dynarray *array, void *p) {
11053a5a1b3Sopenharmony_ci    unsigned i;
11153a5a1b3Sopenharmony_ci
11253a5a1b3Sopenharmony_ci    pa_assert(array);
11353a5a1b3Sopenharmony_ci    pa_assert(p);
11453a5a1b3Sopenharmony_ci
11553a5a1b3Sopenharmony_ci    /* Iterate backwards, with the assumption that recently appended entries
11653a5a1b3Sopenharmony_ci     * are likely to be removed first. */
11753a5a1b3Sopenharmony_ci    i = array->n_entries;
11853a5a1b3Sopenharmony_ci    while (i > 0) {
11953a5a1b3Sopenharmony_ci        i--;
12053a5a1b3Sopenharmony_ci        if (array->data[i] == p) {
12153a5a1b3Sopenharmony_ci            pa_dynarray_remove_by_index(array, i);
12253a5a1b3Sopenharmony_ci            return 0;
12353a5a1b3Sopenharmony_ci        }
12453a5a1b3Sopenharmony_ci    }
12553a5a1b3Sopenharmony_ci
12653a5a1b3Sopenharmony_ci    return -PA_ERR_NOENTITY;
12753a5a1b3Sopenharmony_ci}
12853a5a1b3Sopenharmony_ci
12953a5a1b3Sopenharmony_civoid *pa_dynarray_steal_last(pa_dynarray *array) {
13053a5a1b3Sopenharmony_ci    pa_assert(array);
13153a5a1b3Sopenharmony_ci
13253a5a1b3Sopenharmony_ci    if (array->n_entries > 0)
13353a5a1b3Sopenharmony_ci        return array->data[--array->n_entries];
13453a5a1b3Sopenharmony_ci    else
13553a5a1b3Sopenharmony_ci        return NULL;
13653a5a1b3Sopenharmony_ci}
13753a5a1b3Sopenharmony_ci
13853a5a1b3Sopenharmony_ciunsigned pa_dynarray_size(pa_dynarray *array) {
13953a5a1b3Sopenharmony_ci    pa_assert(array);
14053a5a1b3Sopenharmony_ci
14153a5a1b3Sopenharmony_ci    return array->n_entries;
14253a5a1b3Sopenharmony_ci}
14353a5a1b3Sopenharmony_ci
14453a5a1b3Sopenharmony_ciint pa_dynarray_insert_by_index(pa_dynarray *array, void *p, unsigned i) {
14553a5a1b3Sopenharmony_ci    void *entry;
14653a5a1b3Sopenharmony_ci    unsigned j;
14753a5a1b3Sopenharmony_ci
14853a5a1b3Sopenharmony_ci    pa_assert(array);
14953a5a1b3Sopenharmony_ci
15053a5a1b3Sopenharmony_ci    if (i > array->n_entries)
15153a5a1b3Sopenharmony_ci        return -PA_ERR_NOENTITY;
15253a5a1b3Sopenharmony_ci
15353a5a1b3Sopenharmony_ci    if (i == array->n_entries)
15453a5a1b3Sopenharmony_ci        pa_dynarray_append(array, p);
15553a5a1b3Sopenharmony_ci    else {
15653a5a1b3Sopenharmony_ci        entry = pa_dynarray_last(array);
15753a5a1b3Sopenharmony_ci        pa_dynarray_append(array, entry);
15853a5a1b3Sopenharmony_ci        j = array->n_entries - 2;
15953a5a1b3Sopenharmony_ci        for (;j > i; j--)
16053a5a1b3Sopenharmony_ci	    array->data[j] = array->data[j-1];
16153a5a1b3Sopenharmony_ci        array->data[i] = p;
16253a5a1b3Sopenharmony_ci    }
16353a5a1b3Sopenharmony_ci
16453a5a1b3Sopenharmony_ci    return 0;
16553a5a1b3Sopenharmony_ci}
166