]>
code.delx.au - pulseaudio/blob - src/idxset.c
13 struct idxset_entry
*hash_prev
, *hash_next
;
14 struct idxset_entry
* iterate_prev
, *iterate_next
;
18 unsigned (*hash_func
) (void *p
);
19 int (*compare_func
)(void *a
, void *b
);
21 unsigned hash_table_size
, n_entries
;
22 struct idxset_entry
**hash_table
, **array
, *iterate_list_head
, *iterate_list_tail
;
23 uint32_t index
, start_index
, array_size
;
26 static unsigned trivial_hash_func(void *p
) {
30 static int trivial_compare_func(void *a
, void *b
) {
34 struct idxset
* idxset_new(unsigned (*hash_func
) (void *p
), int (*compare_func
) (void*a
, void*b
)) {
37 s
= malloc(sizeof(struct idxset
));
39 s
->hash_func
= hash_func
? hash_func
: trivial_hash_func
;
40 s
->compare_func
= compare_func
? compare_func
: trivial_compare_func
;
41 s
->hash_table_size
= 1023;
42 s
->hash_table
= malloc(sizeof(struct idxset_entry
*)*s
->hash_table_size
);
43 assert(s
->hash_table
);
44 memset(s
->hash_table
, 0, sizeof(struct idxset_entry
*)*s
->hash_table_size
);
51 s
->iterate_list_head
= s
->iterate_list_tail
= NULL
;
56 void idxset_free(struct idxset
*s
, void (*free_func
) (void *p
, void *userdata
), void *userdata
) {
60 while (s
->iterate_list_head
) {
61 struct idxset_entry
*e
= s
->iterate_list_head
;
62 s
->iterate_list_head
= s
->iterate_list_head
->iterate_next
;
65 free_func(e
->data
, userdata
);
75 static struct idxset_entry
* hash_scan(struct idxset
*s
, struct idxset_entry
* e
, void *p
) {
78 assert(s
->compare_func
);
79 for (; e
; e
= e
->hash_next
)
80 if (s
->compare_func(e
->data
, p
) == 0)
86 static void extend_array(struct idxset
*s
, uint32_t index
) {
88 struct idxset_entry
** n
;
89 assert(index
>= s
->start_index
);
91 if (index
< s
->start_index
+ s
->array_size
)
94 for (i
= 0; i
< s
->array_size
; i
++)
98 l
= index
- s
->start_index
- i
+ 100;
99 n
= malloc(sizeof(struct hash_table_entry
*)*l
);
101 memset(n
, 0, sizeof(struct hash_table_entry
*)*l
);
103 for (j
= 0; j
< s
->array_size
-i
; j
++)
104 n
[j
] = s
->array
[i
+j
];
113 static struct idxset_entry
** array_index(struct idxset
*s
, uint32_t index
) {
114 if (index
>= s
->start_index
+ s
->array_size
)
117 if (index
< s
->start_index
)
120 return s
->array
+ (index
- s
->start_index
);
123 int idxset_put(struct idxset
*s
, void *p
, uint32_t *index
) {
125 struct idxset_entry
*e
, **a
;
128 assert(s
->hash_func
);
129 h
= s
->hash_func(p
) % s
->hash_table_size
;
131 assert(s
->hash_table
);
132 if ((e
= hash_scan(s
, s
->hash_table
[h
], p
))) {
139 e
= malloc(sizeof(struct idxset_entry
));
143 e
->index
= s
->index
++;
146 /* Insert into hash table */
147 e
->hash_next
= s
->hash_table
[h
];
149 if (s
->hash_table
[h
])
150 s
->hash_table
[h
]->hash_prev
= e
;
151 s
->hash_table
[h
] = e
;
153 /* Insert into array */
154 extend_array(s
, e
->index
);
155 a
= array_index(s
, e
->index
);
159 /* Insert into linked list */
160 e
->iterate_next
= NULL
;
161 e
->iterate_prev
= s
->iterate_list_tail
;
162 if (s
->iterate_list_tail
) {
163 assert(s
->iterate_list_head
);
164 s
->iterate_list_tail
->iterate_next
= e
;
166 assert(!s
->iterate_list_head
);
167 s
->iterate_list_head
= e
;
169 s
->iterate_list_tail
= e
;
172 assert(s
->n_entries
>= 1);
180 void* idxset_get_by_index(struct idxset
*s
, uint32_t index
) {
181 struct idxset_entry
**a
;
184 if (!(a
= array_index(s
, index
)))
193 void* idxset_get_by_data(struct idxset
*s
, void *p
, uint32_t *index
) {
195 struct idxset_entry
*e
;
198 assert(s
->hash_func
);
199 h
= s
->hash_func(p
) % s
->hash_table_size
;
201 assert(s
->hash_table
);
202 if (!(e
= hash_scan(s
, s
->hash_table
[h
], p
)))
211 static void remove_entry(struct idxset
*s
, struct idxset_entry
*e
) {
212 struct idxset_entry
**a
;
215 /* Remove from array */
216 a
= array_index(s
, e
->index
);
217 assert(a
&& *a
&& *a
== e
);
220 /* Remove from linked list */
222 e
->iterate_next
->iterate_prev
= e
->iterate_prev
;
224 s
->iterate_list_tail
= e
->iterate_prev
;
227 e
->iterate_prev
->iterate_next
= e
->iterate_next
;
229 s
->iterate_list_head
= e
->iterate_next
;
231 /* Remove from hash table */
233 e
->hash_next
->hash_prev
= e
->hash_prev
;
236 e
->hash_prev
->hash_next
= e
->hash_next
;
238 s
->hash_table
[e
->hash_value
] = e
->hash_next
;
242 assert(s
->n_entries
>= 1);
246 void* idxset_remove_by_index(struct idxset
*s
, uint32_t index
) {
247 struct idxset_entry
**a
;
252 if (!(a
= array_index(s
, index
)))
261 void* idxset_remove_by_data(struct idxset
*s
, void *data
, uint32_t *index
) {
262 struct idxset_entry
*e
;
265 assert(s
->hash_func
);
266 h
= s
->hash_func(data
) % s
->hash_table_size
;
268 assert(s
->hash_table
);
269 if (!(e
= hash_scan(s
, s
->hash_table
[h
], data
)))
281 void* idxset_rrobin(struct idxset
*s
, uint32_t *index
) {
282 struct idxset_entry
**a
, *e
= NULL
;
285 if ((a
= array_index(s
, *index
)) && *a
)
286 e
= (*a
)->iterate_next
;
289 e
= s
->iterate_list_head
;
298 void* idxset_first(struct idxset
*s
, uint32_t *index
) {
301 if (!s
->iterate_list_head
)
305 *index
= s
->iterate_list_head
->index
;
306 return s
->iterate_list_head
->data
;
309 void *idxset_next(struct idxset
*s
, uint32_t *index
) {
310 struct idxset_entry
**a
, *e
= NULL
;
313 if ((a
= array_index(s
, *index
)) && *a
)
314 e
= (*a
)->iterate_next
;
320 *index
= IDXSET_INVALID
;
326 int idxset_foreach(struct idxset
*s
, int (*func
)(void *p
, uint32_t index
, int *del
, void*userdata
), void *userdata
) {
327 struct idxset_entry
*e
;
330 e
= s
->iterate_list_head
;
333 struct idxset_entry
*n
= e
->iterate_next
;
335 r
= func(e
->data
, e
->index
, &del
, userdata
);
349 unsigned idxset_ncontents(struct idxset
*s
) {
354 int idxset_isempty(struct idxset
*s
) {
356 return s
->n_entries
== 0;