1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2008 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <string.h> 25#include <stdlib.h> 26 27#include <pulse/xmalloc.h> 28#include <pulsecore/macro.h> 29 30#include "dynarray.h" 31 32struct pa_dynarray { 33 void **data; 34 unsigned n_allocated, n_entries; 35 pa_free_cb_t free_cb; 36}; 37 38pa_dynarray* pa_dynarray_new(pa_free_cb_t free_cb) { 39 pa_dynarray *array; 40 41 array = pa_xnew0(pa_dynarray, 1); 42 array->free_cb = free_cb; 43 44 return array; 45} 46 47void pa_dynarray_free(pa_dynarray *array) { 48 unsigned i; 49 pa_assert(array); 50 51 if (array->free_cb) 52 for (i = 0; i < array->n_entries; i++) 53 array->free_cb(array->data[i]); 54 55 pa_xfree(array->data); 56 pa_xfree(array); 57} 58 59void pa_dynarray_append(pa_dynarray *array, void *p) { 60 pa_assert(array); 61 pa_assert(p); 62 63 if (array->n_entries == array->n_allocated) { 64 unsigned n = PA_MAX(array->n_allocated * 2, 25U); 65 66 array->data = pa_xrealloc(array->data, sizeof(void *) * n); 67 array->n_allocated = n; 68 } 69 70 array->data[array->n_entries++] = p; 71} 72 73void *pa_dynarray_get(pa_dynarray *array, unsigned i) { 74 pa_assert(array); 75 76 if (i >= array->n_entries) 77 return NULL; 78 79 return array->data[i]; 80} 81 82void *pa_dynarray_last(pa_dynarray *array) { 83 pa_assert(array); 84 85 if (array->n_entries == 0) 86 return NULL; 87 88 return array->data[array->n_entries - 1]; 89} 90 91int pa_dynarray_remove_by_index(pa_dynarray *array, unsigned i) { 92 void *entry; 93 94 pa_assert(array); 95 96 if (i >= array->n_entries) 97 return -PA_ERR_NOENTITY; 98 99 entry = array->data[i]; 100 array->data[i] = array->data[array->n_entries - 1]; 101 array->n_entries--; 102 103 if (array->free_cb) 104 array->free_cb(entry); 105 106 return 0; 107} 108 109int pa_dynarray_remove_by_data(pa_dynarray *array, void *p) { 110 unsigned i; 111 112 pa_assert(array); 113 pa_assert(p); 114 115 /* Iterate backwards, with the assumption that recently appended entries 116 * are likely to be removed first. */ 117 i = array->n_entries; 118 while (i > 0) { 119 i--; 120 if (array->data[i] == p) { 121 pa_dynarray_remove_by_index(array, i); 122 return 0; 123 } 124 } 125 126 return -PA_ERR_NOENTITY; 127} 128 129void *pa_dynarray_steal_last(pa_dynarray *array) { 130 pa_assert(array); 131 132 if (array->n_entries > 0) 133 return array->data[--array->n_entries]; 134 else 135 return NULL; 136} 137 138unsigned pa_dynarray_size(pa_dynarray *array) { 139 pa_assert(array); 140 141 return array->n_entries; 142} 143 144int pa_dynarray_insert_by_index(pa_dynarray *array, void *p, unsigned i) { 145 void *entry; 146 unsigned j; 147 148 pa_assert(array); 149 150 if (i > array->n_entries) 151 return -PA_ERR_NOENTITY; 152 153 if (i == array->n_entries) 154 pa_dynarray_append(array, p); 155 else { 156 entry = pa_dynarray_last(array); 157 pa_dynarray_append(array, entry); 158 j = array->n_entries - 2; 159 for (;j > i; j--) 160 array->data[j] = array->data[j-1]; 161 array->data[i] = p; 162 } 163 164 return 0; 165} 166