mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Including C headers inside of `extern "C"` breaks use from C++. Hoist the includes of standard C headers above the block so we don't try to mangle the stdlib. I initially tried to scope this with a targeted change but it's too hard to do correctly that way. This way, we avoid whack-a-mole. Firefox is working around this in their e21461b7b8b39cc31ba53c47d4f6f310c673ff2f commit. Bug: https://bugzilla.mozilla.org/1953080
		
			
				
	
	
		
			199 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* ALSA Card Profile */
 | 
						|
/* SPDX-FileCopyrightText: Copyright © 2020 Wim Taymans */
 | 
						|
/* SPDX-License-Identifier: MIT */
 | 
						|
 | 
						|
#ifndef PA_HASHMAP_H
 | 
						|
#define PA_HASHMAP_H
 | 
						|
 | 
						|
#include "array.h"
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
extern "C" {
 | 
						|
#endif
 | 
						|
 | 
						|
typedef unsigned (*pa_hash_func_t)(const void *p);
 | 
						|
typedef int (*pa_compare_func_t)(const void *a, const void *b);
 | 
						|
 | 
						|
typedef struct pa_hashmap_item {
 | 
						|
	void *key;
 | 
						|
	void *value;
 | 
						|
} pa_hashmap_item;
 | 
						|
 | 
						|
typedef struct pa_hashmap {
 | 
						|
	pa_array array;
 | 
						|
	pa_hash_func_t hash_func;
 | 
						|
	pa_compare_func_t compare_func;
 | 
						|
	pa_free_cb_t key_free_func;
 | 
						|
	pa_free_cb_t value_free_func;
 | 
						|
} pa_hashmap;
 | 
						|
 | 
						|
static inline pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func)
 | 
						|
{
 | 
						|
        pa_hashmap *m = calloc(1, sizeof(pa_hashmap));
 | 
						|
        pa_array_init(&m->array, 16);
 | 
						|
	m->hash_func = hash_func;
 | 
						|
	m->compare_func = compare_func;
 | 
						|
	return m;
 | 
						|
}
 | 
						|
 | 
						|
static inline pa_hashmap *pa_hashmap_new_full(pa_hash_func_t hash_func, pa_compare_func_t compare_func,
 | 
						|
		pa_free_cb_t key_free_func, pa_free_cb_t value_free_func)
 | 
						|
{
 | 
						|
	pa_hashmap *m = pa_hashmap_new(hash_func, compare_func);
 | 
						|
	m->key_free_func = key_free_func;
 | 
						|
	m->value_free_func = value_free_func;
 | 
						|
	return m;
 | 
						|
}
 | 
						|
 | 
						|
static inline void pa_hashmap_item_free(pa_hashmap *h, pa_hashmap_item *item)
 | 
						|
{
 | 
						|
	if (h->key_free_func && item->key)
 | 
						|
		h->key_free_func(item->key);
 | 
						|
	if (h->value_free_func && item->value)
 | 
						|
		h->value_free_func(item->value);
 | 
						|
}
 | 
						|
 | 
						|
static inline void pa_hashmap_remove_all(pa_hashmap *h)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item;
 | 
						|
	pa_array_for_each(item, &h->array)
 | 
						|
		pa_hashmap_item_free(h, item);
 | 
						|
	pa_array_reset(&h->array);
 | 
						|
}
 | 
						|
 | 
						|
static inline void pa_hashmap_free(pa_hashmap *h)
 | 
						|
{
 | 
						|
	pa_hashmap_remove_all(h);
 | 
						|
	pa_array_clear(&h->array);
 | 
						|
	free(h);
 | 
						|
}
 | 
						|
 | 
						|
static inline pa_hashmap_item* pa_hashmap_find_free(pa_hashmap *h)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item;
 | 
						|
	pa_array_for_each(item, &h->array) {
 | 
						|
		if (item->key == NULL)
 | 
						|
			return item;
 | 
						|
	}
 | 
						|
	return pa_array_add(&h->array, sizeof(*item));
 | 
						|
}
 | 
						|
 | 
						|
static inline pa_hashmap_item* pa_hashmap_find(const pa_hashmap *h, const void *key)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item = NULL;
 | 
						|
	pa_array_for_each(item, &h->array) {
 | 
						|
		if (item->key != NULL && h->compare_func(item->key, key) == 0)
 | 
						|
			return item;
 | 
						|
	}
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static inline void* pa_hashmap_get(const pa_hashmap *h, const void *key)
 | 
						|
{
 | 
						|
	const pa_hashmap_item *item = pa_hashmap_find(h, key);
 | 
						|
	if (item == NULL)
 | 
						|
		return NULL;
 | 
						|
	return item->value;
 | 
						|
}
 | 
						|
 | 
						|
static inline int pa_hashmap_put(pa_hashmap *h, void *key, void *value)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item = pa_hashmap_find(h, key);
 | 
						|
	if (item != NULL)
 | 
						|
		return -1;
 | 
						|
	item = pa_hashmap_find_free(h);
 | 
						|
	item->key = key;
 | 
						|
	item->value = value;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static inline void* pa_hashmap_remove(pa_hashmap *h, const void *key)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item = pa_hashmap_find(h, key);
 | 
						|
	void *value;
 | 
						|
	if (item == NULL)
 | 
						|
		return NULL;
 | 
						|
	value = item->value;
 | 
						|
	if (h->key_free_func)
 | 
						|
		h->key_free_func(item->key);
 | 
						|
	item->key = NULL;
 | 
						|
	item->value = NULL;
 | 
						|
	return value;
 | 
						|
}
 | 
						|
 | 
						|
static inline int pa_hashmap_remove_and_free(pa_hashmap *h, const void *key)
 | 
						|
{
 | 
						|
	void *val = pa_hashmap_remove(h, key);
 | 
						|
	if (val && h->value_free_func)
 | 
						|
		h->value_free_func(val);
 | 
						|
	return val ? 0 : -1;
 | 
						|
}
 | 
						|
 | 
						|
static inline void *pa_hashmap_first(const pa_hashmap *h)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item;
 | 
						|
	pa_array_for_each(item, &h->array) {
 | 
						|
		if (item->key != NULL)
 | 
						|
			return item->value;
 | 
						|
	}
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static inline void *pa_hashmap_iterate(const pa_hashmap *h, void **state, const void **key)
 | 
						|
{
 | 
						|
	pa_hashmap_item *it = *state;
 | 
						|
	if (it == NULL)
 | 
						|
		*state = pa_array_first(&h->array);
 | 
						|
	do {
 | 
						|
		it = *state;
 | 
						|
		if (!pa_array_check(&h->array, it))
 | 
						|
			return NULL;
 | 
						|
		*state = it + 1;
 | 
						|
	} while (it->key == NULL);
 | 
						|
	if (key)
 | 
						|
		*key = it->key;
 | 
						|
	return it->value;
 | 
						|
}
 | 
						|
 | 
						|
static inline bool pa_hashmap_isempty(const pa_hashmap *h)
 | 
						|
{
 | 
						|
	pa_hashmap_item *item;
 | 
						|
	pa_array_for_each(item, &h->array)
 | 
						|
		if (item->key != NULL)
 | 
						|
			return false;
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
static inline unsigned pa_hashmap_size(const pa_hashmap *h)
 | 
						|
{
 | 
						|
	unsigned count = 0;
 | 
						|
	pa_hashmap_item *item;
 | 
						|
	pa_array_for_each(item, &h->array)
 | 
						|
		if (item->key != NULL)
 | 
						|
			count++;
 | 
						|
	return count;
 | 
						|
}
 | 
						|
 | 
						|
static inline void pa_hashmap_sort(pa_hashmap *h,
 | 
						|
		int (*compar)(const void *, const void *))
 | 
						|
{
 | 
						|
        qsort((void*)h->array.data,
 | 
						|
			pa_array_get_len(&h->array, pa_hashmap_item),
 | 
						|
			sizeof(pa_hashmap_item), compar);
 | 
						|
}
 | 
						|
 | 
						|
#define PA_HASHMAP_FOREACH(e, h, state) \
 | 
						|
	for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), NULL);	\
 | 
						|
	    (e); (e) = pa_hashmap_iterate((h), &(state), NULL))
 | 
						|
 | 
						|
/* A macro to ease iteration through all key, value pairs */
 | 
						|
#define PA_HASHMAP_FOREACH_KV(k, e, h, state) \
 | 
						|
	for ((state) = NULL, (e) = pa_hashmap_iterate((h), &(state), (const void **) &(k));	\
 | 
						|
	    (e); (e) = pa_hashmap_iterate((h), &(state), (const void **) &(k)))
 | 
						|
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
}  /* extern "C" */
 | 
						|
#endif
 | 
						|
 | 
						|
#endif /* PA_HASHMAP_H */
 |