153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2008 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as 953a5a1b3Sopenharmony_ci published by the Free Software Foundation; either version 2.1 of the 1053a5a1b3Sopenharmony_ci License, or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci Lesser General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public 1853a5a1b3Sopenharmony_ci License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <stdio.h> 2653a5a1b3Sopenharmony_ci#include <stdlib.h> 2753a5a1b3Sopenharmony_ci#include <string.h> 2853a5a1b3Sopenharmony_ci 2953a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h> 3053a5a1b3Sopenharmony_ci#include <pulsecore/flist.h> 3153a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3253a5a1b3Sopenharmony_ci 3353a5a1b3Sopenharmony_ci#include "idxset.h" 3453a5a1b3Sopenharmony_ci 3553a5a1b3Sopenharmony_ci#define NBUCKETS 127 3653a5a1b3Sopenharmony_ci 3753a5a1b3Sopenharmony_cistruct idxset_entry { 3853a5a1b3Sopenharmony_ci uint32_t idx; 3953a5a1b3Sopenharmony_ci void *data; 4053a5a1b3Sopenharmony_ci 4153a5a1b3Sopenharmony_ci struct idxset_entry *data_next, *data_previous; 4253a5a1b3Sopenharmony_ci struct idxset_entry *index_next, *index_previous; 4353a5a1b3Sopenharmony_ci struct idxset_entry *iterate_next, *iterate_previous; 4453a5a1b3Sopenharmony_ci}; 4553a5a1b3Sopenharmony_ci 4653a5a1b3Sopenharmony_cistruct pa_idxset { 4753a5a1b3Sopenharmony_ci pa_hash_func_t hash_func; 4853a5a1b3Sopenharmony_ci pa_compare_func_t compare_func; 4953a5a1b3Sopenharmony_ci 5053a5a1b3Sopenharmony_ci uint32_t current_index; 5153a5a1b3Sopenharmony_ci 5253a5a1b3Sopenharmony_ci struct idxset_entry *iterate_list_head, *iterate_list_tail; 5353a5a1b3Sopenharmony_ci unsigned n_entries; 5453a5a1b3Sopenharmony_ci}; 5553a5a1b3Sopenharmony_ci 5653a5a1b3Sopenharmony_ci#define BY_DATA(i) ((struct idxset_entry**) ((uint8_t*) (i) + PA_ALIGN(sizeof(pa_idxset)))) 5753a5a1b3Sopenharmony_ci#define BY_INDEX(i) (BY_DATA(i) + NBUCKETS) 5853a5a1b3Sopenharmony_ci 5953a5a1b3Sopenharmony_ciPA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree); 6053a5a1b3Sopenharmony_ci 6153a5a1b3Sopenharmony_ciunsigned pa_idxset_string_hash_func(const void *p) { 6253a5a1b3Sopenharmony_ci unsigned hash = 0; 6353a5a1b3Sopenharmony_ci const char *c; 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_ci for (c = p; *c; c++) 6653a5a1b3Sopenharmony_ci hash = 31 * hash + (unsigned) *c; 6753a5a1b3Sopenharmony_ci 6853a5a1b3Sopenharmony_ci return hash; 6953a5a1b3Sopenharmony_ci} 7053a5a1b3Sopenharmony_ci 7153a5a1b3Sopenharmony_ciint pa_idxset_string_compare_func(const void *a, const void *b) { 7253a5a1b3Sopenharmony_ci return strcmp(a, b); 7353a5a1b3Sopenharmony_ci} 7453a5a1b3Sopenharmony_ci 7553a5a1b3Sopenharmony_ciunsigned pa_idxset_trivial_hash_func(const void *p) { 7653a5a1b3Sopenharmony_ci return PA_PTR_TO_UINT(p); 7753a5a1b3Sopenharmony_ci} 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ciint pa_idxset_trivial_compare_func(const void *a, const void *b) { 8053a5a1b3Sopenharmony_ci return a < b ? -1 : (a > b ? 1 : 0); 8153a5a1b3Sopenharmony_ci} 8253a5a1b3Sopenharmony_ci 8353a5a1b3Sopenharmony_cipa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) { 8453a5a1b3Sopenharmony_ci pa_idxset *s; 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_ci s = pa_xmalloc0(PA_ALIGN(sizeof(pa_idxset)) + NBUCKETS*2*sizeof(struct idxset_entry*)); 8753a5a1b3Sopenharmony_ci 8853a5a1b3Sopenharmony_ci s->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func; 8953a5a1b3Sopenharmony_ci s->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func; 9053a5a1b3Sopenharmony_ci 9153a5a1b3Sopenharmony_ci s->current_index = 0; 9253a5a1b3Sopenharmony_ci s->n_entries = 0; 9353a5a1b3Sopenharmony_ci s->iterate_list_head = s->iterate_list_tail = NULL; 9453a5a1b3Sopenharmony_ci 9553a5a1b3Sopenharmony_ci return s; 9653a5a1b3Sopenharmony_ci} 9753a5a1b3Sopenharmony_ci 9853a5a1b3Sopenharmony_cistatic void remove_entry(pa_idxset *s, struct idxset_entry *e) { 9953a5a1b3Sopenharmony_ci pa_assert(s); 10053a5a1b3Sopenharmony_ci pa_assert(e); 10153a5a1b3Sopenharmony_ci 10253a5a1b3Sopenharmony_ci /* Remove from iteration linked list */ 10353a5a1b3Sopenharmony_ci if (e->iterate_next) 10453a5a1b3Sopenharmony_ci e->iterate_next->iterate_previous = e->iterate_previous; 10553a5a1b3Sopenharmony_ci else 10653a5a1b3Sopenharmony_ci s->iterate_list_tail = e->iterate_previous; 10753a5a1b3Sopenharmony_ci 10853a5a1b3Sopenharmony_ci if (e->iterate_previous) 10953a5a1b3Sopenharmony_ci e->iterate_previous->iterate_next = e->iterate_next; 11053a5a1b3Sopenharmony_ci else 11153a5a1b3Sopenharmony_ci s->iterate_list_head = e->iterate_next; 11253a5a1b3Sopenharmony_ci 11353a5a1b3Sopenharmony_ci /* Remove from data hash table */ 11453a5a1b3Sopenharmony_ci if (e->data_next) 11553a5a1b3Sopenharmony_ci e->data_next->data_previous = e->data_previous; 11653a5a1b3Sopenharmony_ci 11753a5a1b3Sopenharmony_ci if (e->data_previous) 11853a5a1b3Sopenharmony_ci e->data_previous->data_next = e->data_next; 11953a5a1b3Sopenharmony_ci else { 12053a5a1b3Sopenharmony_ci unsigned hash = s->hash_func(e->data) % NBUCKETS; 12153a5a1b3Sopenharmony_ci BY_DATA(s)[hash] = e->data_next; 12253a5a1b3Sopenharmony_ci } 12353a5a1b3Sopenharmony_ci 12453a5a1b3Sopenharmony_ci /* Remove from index hash table */ 12553a5a1b3Sopenharmony_ci if (e->index_next) 12653a5a1b3Sopenharmony_ci e->index_next->index_previous = e->index_previous; 12753a5a1b3Sopenharmony_ci 12853a5a1b3Sopenharmony_ci if (e->index_previous) 12953a5a1b3Sopenharmony_ci e->index_previous->index_next = e->index_next; 13053a5a1b3Sopenharmony_ci else 13153a5a1b3Sopenharmony_ci BY_INDEX(s)[e->idx % NBUCKETS] = e->index_next; 13253a5a1b3Sopenharmony_ci 13353a5a1b3Sopenharmony_ci if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0) 13453a5a1b3Sopenharmony_ci pa_xfree(e); 13553a5a1b3Sopenharmony_ci 13653a5a1b3Sopenharmony_ci pa_assert(s->n_entries >= 1); 13753a5a1b3Sopenharmony_ci s->n_entries--; 13853a5a1b3Sopenharmony_ci} 13953a5a1b3Sopenharmony_ci 14053a5a1b3Sopenharmony_civoid pa_idxset_free(pa_idxset *s, pa_free_cb_t free_cb) { 14153a5a1b3Sopenharmony_ci pa_assert(s); 14253a5a1b3Sopenharmony_ci 14353a5a1b3Sopenharmony_ci pa_idxset_remove_all(s, free_cb); 14453a5a1b3Sopenharmony_ci pa_xfree(s); 14553a5a1b3Sopenharmony_ci} 14653a5a1b3Sopenharmony_ci 14753a5a1b3Sopenharmony_cistatic struct idxset_entry* data_scan(pa_idxset *s, unsigned hash, const void *p) { 14853a5a1b3Sopenharmony_ci struct idxset_entry *e; 14953a5a1b3Sopenharmony_ci pa_assert(s); 15053a5a1b3Sopenharmony_ci pa_assert(hash < NBUCKETS); 15153a5a1b3Sopenharmony_ci pa_assert(p); 15253a5a1b3Sopenharmony_ci 15353a5a1b3Sopenharmony_ci for (e = BY_DATA(s)[hash]; e; e = e->data_next) 15453a5a1b3Sopenharmony_ci if (s->compare_func(e->data, p) == 0) 15553a5a1b3Sopenharmony_ci return e; 15653a5a1b3Sopenharmony_ci 15753a5a1b3Sopenharmony_ci return NULL; 15853a5a1b3Sopenharmony_ci} 15953a5a1b3Sopenharmony_ci 16053a5a1b3Sopenharmony_cistatic struct idxset_entry* index_scan(pa_idxset *s, unsigned hash, uint32_t idx) { 16153a5a1b3Sopenharmony_ci struct idxset_entry *e; 16253a5a1b3Sopenharmony_ci pa_assert(s); 16353a5a1b3Sopenharmony_ci pa_assert(hash < NBUCKETS); 16453a5a1b3Sopenharmony_ci 16553a5a1b3Sopenharmony_ci for (e = BY_INDEX(s)[hash]; e; e = e->index_next) 16653a5a1b3Sopenharmony_ci if (e->idx == idx) 16753a5a1b3Sopenharmony_ci return e; 16853a5a1b3Sopenharmony_ci 16953a5a1b3Sopenharmony_ci return NULL; 17053a5a1b3Sopenharmony_ci} 17153a5a1b3Sopenharmony_ci 17253a5a1b3Sopenharmony_ciint pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) { 17353a5a1b3Sopenharmony_ci unsigned hash; 17453a5a1b3Sopenharmony_ci struct idxset_entry *e; 17553a5a1b3Sopenharmony_ci 17653a5a1b3Sopenharmony_ci pa_assert(s); 17753a5a1b3Sopenharmony_ci 17853a5a1b3Sopenharmony_ci hash = s->hash_func(p) % NBUCKETS; 17953a5a1b3Sopenharmony_ci 18053a5a1b3Sopenharmony_ci if ((e = data_scan(s, hash, p))) { 18153a5a1b3Sopenharmony_ci if (idx) 18253a5a1b3Sopenharmony_ci *idx = e->idx; 18353a5a1b3Sopenharmony_ci 18453a5a1b3Sopenharmony_ci return -1; 18553a5a1b3Sopenharmony_ci } 18653a5a1b3Sopenharmony_ci 18753a5a1b3Sopenharmony_ci if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries)))) 18853a5a1b3Sopenharmony_ci e = pa_xnew(struct idxset_entry, 1); 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_ci e->data = p; 19153a5a1b3Sopenharmony_ci e->idx = s->current_index++; 19253a5a1b3Sopenharmony_ci 19353a5a1b3Sopenharmony_ci /* Insert into data hash table */ 19453a5a1b3Sopenharmony_ci e->data_next = BY_DATA(s)[hash]; 19553a5a1b3Sopenharmony_ci e->data_previous = NULL; 19653a5a1b3Sopenharmony_ci if (BY_DATA(s)[hash]) 19753a5a1b3Sopenharmony_ci BY_DATA(s)[hash]->data_previous = e; 19853a5a1b3Sopenharmony_ci BY_DATA(s)[hash] = e; 19953a5a1b3Sopenharmony_ci 20053a5a1b3Sopenharmony_ci hash = e->idx % NBUCKETS; 20153a5a1b3Sopenharmony_ci 20253a5a1b3Sopenharmony_ci /* Insert into index hash table */ 20353a5a1b3Sopenharmony_ci e->index_next = BY_INDEX(s)[hash]; 20453a5a1b3Sopenharmony_ci e->index_previous = NULL; 20553a5a1b3Sopenharmony_ci if (BY_INDEX(s)[hash]) 20653a5a1b3Sopenharmony_ci BY_INDEX(s)[hash]->index_previous = e; 20753a5a1b3Sopenharmony_ci BY_INDEX(s)[hash] = e; 20853a5a1b3Sopenharmony_ci 20953a5a1b3Sopenharmony_ci /* Insert into iteration list */ 21053a5a1b3Sopenharmony_ci e->iterate_previous = s->iterate_list_tail; 21153a5a1b3Sopenharmony_ci e->iterate_next = NULL; 21253a5a1b3Sopenharmony_ci if (s->iterate_list_tail) { 21353a5a1b3Sopenharmony_ci pa_assert(s->iterate_list_head); 21453a5a1b3Sopenharmony_ci s->iterate_list_tail->iterate_next = e; 21553a5a1b3Sopenharmony_ci } else { 21653a5a1b3Sopenharmony_ci pa_assert(!s->iterate_list_head); 21753a5a1b3Sopenharmony_ci s->iterate_list_head = e; 21853a5a1b3Sopenharmony_ci } 21953a5a1b3Sopenharmony_ci s->iterate_list_tail = e; 22053a5a1b3Sopenharmony_ci 22153a5a1b3Sopenharmony_ci s->n_entries++; 22253a5a1b3Sopenharmony_ci pa_assert(s->n_entries >= 1); 22353a5a1b3Sopenharmony_ci 22453a5a1b3Sopenharmony_ci if (idx) 22553a5a1b3Sopenharmony_ci *idx = e->idx; 22653a5a1b3Sopenharmony_ci 22753a5a1b3Sopenharmony_ci return 0; 22853a5a1b3Sopenharmony_ci} 22953a5a1b3Sopenharmony_ci 23053a5a1b3Sopenharmony_civoid* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) { 23153a5a1b3Sopenharmony_ci unsigned hash; 23253a5a1b3Sopenharmony_ci struct idxset_entry *e; 23353a5a1b3Sopenharmony_ci 23453a5a1b3Sopenharmony_ci pa_assert(s); 23553a5a1b3Sopenharmony_ci 23653a5a1b3Sopenharmony_ci hash = idx % NBUCKETS; 23753a5a1b3Sopenharmony_ci 23853a5a1b3Sopenharmony_ci if (!(e = index_scan(s, hash, idx))) 23953a5a1b3Sopenharmony_ci return NULL; 24053a5a1b3Sopenharmony_ci 24153a5a1b3Sopenharmony_ci return e->data; 24253a5a1b3Sopenharmony_ci} 24353a5a1b3Sopenharmony_ci 24453a5a1b3Sopenharmony_civoid* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) { 24553a5a1b3Sopenharmony_ci unsigned hash; 24653a5a1b3Sopenharmony_ci struct idxset_entry *e; 24753a5a1b3Sopenharmony_ci 24853a5a1b3Sopenharmony_ci pa_assert(s); 24953a5a1b3Sopenharmony_ci 25053a5a1b3Sopenharmony_ci hash = s->hash_func(p) % NBUCKETS; 25153a5a1b3Sopenharmony_ci 25253a5a1b3Sopenharmony_ci if (!(e = data_scan(s, hash, p))) 25353a5a1b3Sopenharmony_ci return NULL; 25453a5a1b3Sopenharmony_ci 25553a5a1b3Sopenharmony_ci if (idx) 25653a5a1b3Sopenharmony_ci *idx = e->idx; 25753a5a1b3Sopenharmony_ci 25853a5a1b3Sopenharmony_ci return e->data; 25953a5a1b3Sopenharmony_ci} 26053a5a1b3Sopenharmony_ci 26153a5a1b3Sopenharmony_civoid* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) { 26253a5a1b3Sopenharmony_ci struct idxset_entry *e; 26353a5a1b3Sopenharmony_ci unsigned hash; 26453a5a1b3Sopenharmony_ci void *data; 26553a5a1b3Sopenharmony_ci 26653a5a1b3Sopenharmony_ci pa_assert(s); 26753a5a1b3Sopenharmony_ci 26853a5a1b3Sopenharmony_ci hash = idx % NBUCKETS; 26953a5a1b3Sopenharmony_ci 27053a5a1b3Sopenharmony_ci if (!(e = index_scan(s, hash, idx))) 27153a5a1b3Sopenharmony_ci return NULL; 27253a5a1b3Sopenharmony_ci 27353a5a1b3Sopenharmony_ci data = e->data; 27453a5a1b3Sopenharmony_ci remove_entry(s, e); 27553a5a1b3Sopenharmony_ci 27653a5a1b3Sopenharmony_ci return data; 27753a5a1b3Sopenharmony_ci} 27853a5a1b3Sopenharmony_ci 27953a5a1b3Sopenharmony_civoid* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) { 28053a5a1b3Sopenharmony_ci struct idxset_entry *e; 28153a5a1b3Sopenharmony_ci unsigned hash; 28253a5a1b3Sopenharmony_ci void *r; 28353a5a1b3Sopenharmony_ci 28453a5a1b3Sopenharmony_ci pa_assert(s); 28553a5a1b3Sopenharmony_ci 28653a5a1b3Sopenharmony_ci hash = s->hash_func(data) % NBUCKETS; 28753a5a1b3Sopenharmony_ci 28853a5a1b3Sopenharmony_ci if (!(e = data_scan(s, hash, data))) 28953a5a1b3Sopenharmony_ci return NULL; 29053a5a1b3Sopenharmony_ci 29153a5a1b3Sopenharmony_ci r = e->data; 29253a5a1b3Sopenharmony_ci 29353a5a1b3Sopenharmony_ci if (idx) 29453a5a1b3Sopenharmony_ci *idx = e->idx; 29553a5a1b3Sopenharmony_ci 29653a5a1b3Sopenharmony_ci remove_entry(s, e); 29753a5a1b3Sopenharmony_ci 29853a5a1b3Sopenharmony_ci return r; 29953a5a1b3Sopenharmony_ci} 30053a5a1b3Sopenharmony_ci 30153a5a1b3Sopenharmony_civoid pa_idxset_remove_all(pa_idxset *s, pa_free_cb_t free_cb) { 30253a5a1b3Sopenharmony_ci pa_assert(s); 30353a5a1b3Sopenharmony_ci 30453a5a1b3Sopenharmony_ci while (s->iterate_list_head) { 30553a5a1b3Sopenharmony_ci void *data = s->iterate_list_head->data; 30653a5a1b3Sopenharmony_ci 30753a5a1b3Sopenharmony_ci remove_entry(s, s->iterate_list_head); 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ci if (free_cb) 31053a5a1b3Sopenharmony_ci free_cb(data); 31153a5a1b3Sopenharmony_ci } 31253a5a1b3Sopenharmony_ci} 31353a5a1b3Sopenharmony_ci 31453a5a1b3Sopenharmony_civoid* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) { 31553a5a1b3Sopenharmony_ci unsigned hash; 31653a5a1b3Sopenharmony_ci struct idxset_entry *e; 31753a5a1b3Sopenharmony_ci 31853a5a1b3Sopenharmony_ci pa_assert(s); 31953a5a1b3Sopenharmony_ci pa_assert(idx); 32053a5a1b3Sopenharmony_ci 32153a5a1b3Sopenharmony_ci hash = *idx % NBUCKETS; 32253a5a1b3Sopenharmony_ci 32353a5a1b3Sopenharmony_ci e = index_scan(s, hash, *idx); 32453a5a1b3Sopenharmony_ci 32553a5a1b3Sopenharmony_ci if (e && e->iterate_next) 32653a5a1b3Sopenharmony_ci e = e->iterate_next; 32753a5a1b3Sopenharmony_ci else 32853a5a1b3Sopenharmony_ci e = s->iterate_list_head; 32953a5a1b3Sopenharmony_ci 33053a5a1b3Sopenharmony_ci if (!e) 33153a5a1b3Sopenharmony_ci return NULL; 33253a5a1b3Sopenharmony_ci 33353a5a1b3Sopenharmony_ci *idx = e->idx; 33453a5a1b3Sopenharmony_ci return e->data; 33553a5a1b3Sopenharmony_ci} 33653a5a1b3Sopenharmony_ci 33753a5a1b3Sopenharmony_civoid *pa_idxset_iterate(pa_idxset *s, void **state, uint32_t *idx) { 33853a5a1b3Sopenharmony_ci struct idxset_entry *e; 33953a5a1b3Sopenharmony_ci 34053a5a1b3Sopenharmony_ci pa_assert(s); 34153a5a1b3Sopenharmony_ci pa_assert(state); 34253a5a1b3Sopenharmony_ci 34353a5a1b3Sopenharmony_ci if (*state == (void*) -1) 34453a5a1b3Sopenharmony_ci goto at_end; 34553a5a1b3Sopenharmony_ci 34653a5a1b3Sopenharmony_ci if ((!*state && !s->iterate_list_head)) 34753a5a1b3Sopenharmony_ci goto at_end; 34853a5a1b3Sopenharmony_ci 34953a5a1b3Sopenharmony_ci e = *state ? *state : s->iterate_list_head; 35053a5a1b3Sopenharmony_ci 35153a5a1b3Sopenharmony_ci if (e->iterate_next) 35253a5a1b3Sopenharmony_ci *state = e->iterate_next; 35353a5a1b3Sopenharmony_ci else 35453a5a1b3Sopenharmony_ci *state = (void*) -1; 35553a5a1b3Sopenharmony_ci 35653a5a1b3Sopenharmony_ci if (idx) 35753a5a1b3Sopenharmony_ci *idx = e->idx; 35853a5a1b3Sopenharmony_ci 35953a5a1b3Sopenharmony_ci return e->data; 36053a5a1b3Sopenharmony_ci 36153a5a1b3Sopenharmony_ciat_end: 36253a5a1b3Sopenharmony_ci *state = (void *) -1; 36353a5a1b3Sopenharmony_ci 36453a5a1b3Sopenharmony_ci if (idx) 36553a5a1b3Sopenharmony_ci *idx = PA_IDXSET_INVALID; 36653a5a1b3Sopenharmony_ci 36753a5a1b3Sopenharmony_ci return NULL; 36853a5a1b3Sopenharmony_ci} 36953a5a1b3Sopenharmony_ci 37053a5a1b3Sopenharmony_civoid* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx) { 37153a5a1b3Sopenharmony_ci void *data; 37253a5a1b3Sopenharmony_ci 37353a5a1b3Sopenharmony_ci pa_assert(s); 37453a5a1b3Sopenharmony_ci 37553a5a1b3Sopenharmony_ci if (!s->iterate_list_head) 37653a5a1b3Sopenharmony_ci return NULL; 37753a5a1b3Sopenharmony_ci 37853a5a1b3Sopenharmony_ci data = s->iterate_list_head->data; 37953a5a1b3Sopenharmony_ci 38053a5a1b3Sopenharmony_ci if (idx) 38153a5a1b3Sopenharmony_ci *idx = s->iterate_list_head->idx; 38253a5a1b3Sopenharmony_ci 38353a5a1b3Sopenharmony_ci remove_entry(s, s->iterate_list_head); 38453a5a1b3Sopenharmony_ci 38553a5a1b3Sopenharmony_ci return data; 38653a5a1b3Sopenharmony_ci} 38753a5a1b3Sopenharmony_ci 38853a5a1b3Sopenharmony_civoid* pa_idxset_first(pa_idxset *s, uint32_t *idx) { 38953a5a1b3Sopenharmony_ci pa_assert(s); 39053a5a1b3Sopenharmony_ci 39153a5a1b3Sopenharmony_ci if (!s->iterate_list_head) { 39253a5a1b3Sopenharmony_ci if (idx) 39353a5a1b3Sopenharmony_ci *idx = PA_IDXSET_INVALID; 39453a5a1b3Sopenharmony_ci return NULL; 39553a5a1b3Sopenharmony_ci } 39653a5a1b3Sopenharmony_ci 39753a5a1b3Sopenharmony_ci if (idx) 39853a5a1b3Sopenharmony_ci *idx = s->iterate_list_head->idx; 39953a5a1b3Sopenharmony_ci 40053a5a1b3Sopenharmony_ci return s->iterate_list_head->data; 40153a5a1b3Sopenharmony_ci} 40253a5a1b3Sopenharmony_ci 40353a5a1b3Sopenharmony_civoid *pa_idxset_next(pa_idxset *s, uint32_t *idx) { 40453a5a1b3Sopenharmony_ci struct idxset_entry *e; 40553a5a1b3Sopenharmony_ci unsigned hash; 40653a5a1b3Sopenharmony_ci 40753a5a1b3Sopenharmony_ci pa_assert(s); 40853a5a1b3Sopenharmony_ci pa_assert(idx); 40953a5a1b3Sopenharmony_ci 41053a5a1b3Sopenharmony_ci if (*idx == PA_IDXSET_INVALID) 41153a5a1b3Sopenharmony_ci return NULL; 41253a5a1b3Sopenharmony_ci 41353a5a1b3Sopenharmony_ci hash = *idx % NBUCKETS; 41453a5a1b3Sopenharmony_ci 41553a5a1b3Sopenharmony_ci if ((e = index_scan(s, hash, *idx))) { 41653a5a1b3Sopenharmony_ci 41753a5a1b3Sopenharmony_ci e = e->iterate_next; 41853a5a1b3Sopenharmony_ci 41953a5a1b3Sopenharmony_ci if (e) { 42053a5a1b3Sopenharmony_ci *idx = e->idx; 42153a5a1b3Sopenharmony_ci return e->data; 42253a5a1b3Sopenharmony_ci } else { 42353a5a1b3Sopenharmony_ci *idx = PA_IDXSET_INVALID; 42453a5a1b3Sopenharmony_ci return NULL; 42553a5a1b3Sopenharmony_ci } 42653a5a1b3Sopenharmony_ci 42753a5a1b3Sopenharmony_ci } else { 42853a5a1b3Sopenharmony_ci 42953a5a1b3Sopenharmony_ci /* If the entry passed doesn't exist anymore we try to find 43053a5a1b3Sopenharmony_ci * the next following */ 43153a5a1b3Sopenharmony_ci 43253a5a1b3Sopenharmony_ci for ((*idx)++; *idx < s->current_index; (*idx)++) { 43353a5a1b3Sopenharmony_ci 43453a5a1b3Sopenharmony_ci hash = *idx % NBUCKETS; 43553a5a1b3Sopenharmony_ci 43653a5a1b3Sopenharmony_ci if ((e = index_scan(s, hash, *idx))) { 43753a5a1b3Sopenharmony_ci *idx = e->idx; 43853a5a1b3Sopenharmony_ci return e->data; 43953a5a1b3Sopenharmony_ci } 44053a5a1b3Sopenharmony_ci } 44153a5a1b3Sopenharmony_ci 44253a5a1b3Sopenharmony_ci *idx = PA_IDXSET_INVALID; 44353a5a1b3Sopenharmony_ci return NULL; 44453a5a1b3Sopenharmony_ci } 44553a5a1b3Sopenharmony_ci} 44653a5a1b3Sopenharmony_ci 44753a5a1b3Sopenharmony_ciunsigned pa_idxset_size(pa_idxset*s) { 44853a5a1b3Sopenharmony_ci pa_assert(s); 44953a5a1b3Sopenharmony_ci 45053a5a1b3Sopenharmony_ci return s->n_entries; 45153a5a1b3Sopenharmony_ci} 45253a5a1b3Sopenharmony_ci 45353a5a1b3Sopenharmony_cibool pa_idxset_isempty(pa_idxset *s) { 45453a5a1b3Sopenharmony_ci pa_assert(s); 45553a5a1b3Sopenharmony_ci 45653a5a1b3Sopenharmony_ci return s->n_entries == 0; 45753a5a1b3Sopenharmony_ci} 45853a5a1b3Sopenharmony_ci 45953a5a1b3Sopenharmony_cipa_idxset *pa_idxset_copy(pa_idxset *s, pa_copy_func_t copy_func) { 46053a5a1b3Sopenharmony_ci pa_idxset *copy; 46153a5a1b3Sopenharmony_ci struct idxset_entry *i; 46253a5a1b3Sopenharmony_ci 46353a5a1b3Sopenharmony_ci pa_assert(s); 46453a5a1b3Sopenharmony_ci 46553a5a1b3Sopenharmony_ci copy = pa_idxset_new(s->hash_func, s->compare_func); 46653a5a1b3Sopenharmony_ci 46753a5a1b3Sopenharmony_ci for (i = s->iterate_list_head; i; i = i->iterate_next) 46853a5a1b3Sopenharmony_ci pa_idxset_put(copy, copy_func ? copy_func(i->data) : i->data, NULL); 46953a5a1b3Sopenharmony_ci 47053a5a1b3Sopenharmony_ci return copy; 47153a5a1b3Sopenharmony_ci} 472