idxset: Add reverse iteration functions, set comparison operations adn set contains() function

Add complementary functions to the existing idxset iterate(),
    steal_first(), first(), next() functions that work in the reverse
    direction: reverse_iterate(), steal_last(), last() and previous().

    Add isdisjoint(), issubset(), issuperset() and equals() functions that
    element-wise compare two idxsets.

    Add set contains() function, This is functionally equivalent to get_by_data(s, p, NULL) == p, but
    with a more obvious name and form because some existing code is instead
    manually iterating through idxsets to check for existence of an item.

    Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
    Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/596>
This commit is contained in:
buque 2022-12-12 15:08:57 +08:00
parent 1767c7368c
commit f352aaf393
4 changed files with 348 additions and 1 deletions

View File

@ -0,0 +1,58 @@
From fb63e589310fab20e60c46bb40c7b7acab5eeac9 Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Date: Sat, 26 Jun 2021 12:05:17 +0300
Subject: [PATCH] idxset: Add set contains() function
This is functionally equivalent to get_by_data(s, p, NULL) == p, but
with a more obvious name and form because some existing code is instead
manually iterating through idxsets to check for existence of an item.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/596>
---
src/pulsecore/idxset.c | 14 ++++++++++++++
src/pulsecore/idxset.h | 3 +++
2 files changed, 17 insertions(+)
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 5175ca217..91ac6a015 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -258,6 +258,20 @@ void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx) {
return e->data;
}
+bool pa_idxset_contains(pa_idxset *s, const void *p) {
+ unsigned hash;
+ struct idxset_entry *e;
+
+ pa_assert(s);
+
+ hash = s->hash_func(p) % NBUCKETS;
+
+ if (!(e = data_scan(s, hash, p)))
+ return false;
+
+ return e->data == p;
+}
+
void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) {
struct idxset_entry *e;
unsigned hash;
diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h
index 7acb202ff..6797852b7 100644
--- a/src/pulsecore/idxset.h
+++ b/src/pulsecore/idxset.h
@@ -66,6 +66,9 @@ void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx);
/* Get the entry by its data. The index is returned in *idx */
void* pa_idxset_get_by_data(pa_idxset*s, const void *p, uint32_t *idx);
+/* Return true if item is in idxset */
+bool pa_idxset_contains(pa_idxset *s, const void *p);
+
/* Similar to pa_idxset_get_by_index(), but removes the entry from the idxset. */
void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx);
--
2.33.0

View File

@ -0,0 +1,86 @@
From ec668ac44bc6e666123f22f2696745dcdce98fed Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Date: Wed, 23 Jun 2021 17:50:50 +0300
Subject: [PATCH] idxset: Add set comparison operations
Add isdisjoint(), issubset(), issuperset() and equals() functions that
element-wise compare two idxsets.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/596>
---
src/pulsecore/idxset.c | 34 ++++++++++++++++++++++++++++++++++
src/pulsecore/idxset.h | 12 ++++++++++++
2 files changed, 46 insertions(+)
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 91ac6a015..b5dd9b3e1 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -470,6 +470,40 @@ bool pa_idxset_isempty(pa_idxset *s) {
return s->n_entries == 0;
}
+bool pa_idxset_isdisjoint(pa_idxset *s, pa_idxset *t) {
+ struct idxset_entry *i;
+
+ pa_assert(s);
+ pa_assert(t);
+
+ for (i = s->iterate_list_head; i; i = i->iterate_next)
+ if (pa_idxset_contains(t, i->data))
+ return false;
+
+ return true;
+}
+
+bool pa_idxset_issubset(pa_idxset *s, pa_idxset *t) {
+ struct idxset_entry *i;
+
+ pa_assert(s);
+ pa_assert(t);
+
+ for (i = s->iterate_list_head; i; i = i->iterate_next)
+ if (!pa_idxset_contains(t, i->data))
+ return false;
+
+ return true;
+}
+
+bool pa_idxset_issuperset(pa_idxset *s, pa_idxset *t) {
+ return pa_idxset_issubset(t, s);
+}
+
+bool pa_idxset_equals(pa_idxset *s, pa_idxset *t) {
+ return pa_idxset_issubset(s, t) && pa_idxset_issuperset(s, t);
+}
+
pa_idxset *pa_idxset_copy(pa_idxset *s, pa_copy_func_t copy_func) {
pa_idxset *copy;
struct idxset_entry *i;
diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h
index 6797852b7..ee530bf2b 100644
--- a/src/pulsecore/idxset.h
+++ b/src/pulsecore/idxset.h
@@ -107,6 +107,18 @@ unsigned pa_idxset_size(pa_idxset*s);
/* Return true of the idxset is empty */
bool pa_idxset_isempty(pa_idxset *s);
+/* Return true if s and t have no entries in common */
+bool pa_idxset_isdisjoint(pa_idxset *s, pa_idxset *t);
+
+/* Return true if all entries in s are also in t */
+bool pa_idxset_issubset(pa_idxset *s, pa_idxset *t);
+
+/* Return true if all entries in t are also in s */
+bool pa_idxset_issuperset(pa_idxset *s, pa_idxset *t);
+
+/* Return true if s and t have all entries in common */
+bool pa_idxset_equals(pa_idxset *s, pa_idxset *t);
+
/* Duplicate the idxset. This will not copy the actual indexes. If copy_func is
* set, each entry is copied using the provided function, otherwise a shallow
* copy will be made. */
--
2.33.0

View File

@ -0,0 +1,197 @@
From 97d9c28579c7c7400969fd93f911e7745fb483ef Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Date: Wed, 23 Jun 2021 17:58:37 +0300
Subject: [PATCH] idxset: Add reverse iteration functions
Add complementary functions to the existing idxset iterate(),
steal_first(), first(), next() functions that work in the reverse
direction: reverse_iterate(), steal_last(), last() and previous().
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/596>
---
src/pulsecore/idxset.c | 110 +++++++++++++++++++++++++++++++++++++++++
src/pulsecore/idxset.h | 19 ++++---
2 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index b5dd9b3e1..324894d01 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -381,6 +381,39 @@ at_end:
return NULL;
}
+void *pa_idxset_reverse_iterate(pa_idxset *s, void **state, uint32_t *idx) {
+ struct idxset_entry *e;
+
+ pa_assert(s);
+ pa_assert(state);
+
+ if (*state == (void*) -1)
+ goto at_end;
+
+ if ((!*state && !s->iterate_list_tail))
+ goto at_end;
+
+ e = *state ? *state : s->iterate_list_tail;
+
+ if (e->iterate_previous)
+ *state = e->iterate_previous;
+ else
+ *state = (void*) -1;
+
+ if (idx)
+ *idx = e->idx;
+
+ return e->data;
+
+at_end:
+ *state = (void *) -1;
+
+ if (idx)
+ *idx = PA_IDXSET_INVALID;
+
+ return NULL;
+}
+
void* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx) {
void *data;
@@ -399,6 +432,24 @@ void* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx) {
return data;
}
+void* pa_idxset_steal_last(pa_idxset *s, uint32_t *idx) {
+ void *data;
+
+ pa_assert(s);
+
+ if (!s->iterate_list_tail)
+ return NULL;
+
+ data = s->iterate_list_tail->data;
+
+ if (idx)
+ *idx = s->iterate_list_tail->idx;
+
+ remove_entry(s, s->iterate_list_tail);
+
+ return data;
+}
+
void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
pa_assert(s);
@@ -414,6 +465,21 @@ void* pa_idxset_first(pa_idxset *s, uint32_t *idx) {
return s->iterate_list_head->data;
}
+void* pa_idxset_last(pa_idxset *s, uint32_t *idx) {
+ pa_assert(s);
+
+ if (!s->iterate_list_tail) {
+ if (idx)
+ *idx = PA_IDXSET_INVALID;
+ return NULL;
+ }
+
+ if (idx)
+ *idx = s->iterate_list_tail->idx;
+
+ return s->iterate_list_tail->data;
+}
+
void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
struct idxset_entry *e;
unsigned hash;
@@ -458,6 +524,50 @@ void *pa_idxset_next(pa_idxset *s, uint32_t *idx) {
}
}
+void *pa_idxset_previous(pa_idxset *s, uint32_t *idx) {
+ struct idxset_entry *e;
+ unsigned hash;
+
+ pa_assert(s);
+ pa_assert(idx);
+
+ if (*idx == PA_IDXSET_INVALID)
+ return NULL;
+
+ hash = *idx % NBUCKETS;
+
+ if ((e = index_scan(s, hash, *idx))) {
+
+ e = e->iterate_previous;
+
+ if (e) {
+ *idx = e->idx;
+ return e->data;
+ } else {
+ *idx = PA_IDXSET_INVALID;
+ return NULL;
+ }
+
+ } else {
+
+ /* If the entry passed doesn't exist anymore we try to find
+ * the preceding one. */
+
+ for ((*idx)--; *idx < s->current_index; (*idx)--) {
+
+ hash = *idx % NBUCKETS;
+
+ if ((e = index_scan(s, hash, *idx))) {
+ *idx = e->idx;
+ return e->data;
+ }
+ }
+
+ *idx = PA_IDXSET_INVALID;
+ return NULL;
+ }
+}
+
unsigned pa_idxset_size(pa_idxset*s) {
pa_assert(s);
diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h
index ee530bf2b..dbc4187d9 100644
--- a/src/pulsecore/idxset.h
+++ b/src/pulsecore/idxset.h
@@ -88,18 +88,25 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx);
/* Iterate through the idxset. At first iteration state should be NULL */
void *pa_idxset_iterate(pa_idxset *s, void **state, uint32_t *idx);
+void *pa_idxset_reverse_iterate(pa_idxset *s, void **state, uint32_t *idx);
-/* Return the oldest entry in the idxset and remove it. If idx is not NULL fill in its index in *idx */
+/* Return the oldest or newest entry in the idxset and remove it.
+ * If idx is not NULL fill in its index in *idx */
void* pa_idxset_steal_first(pa_idxset *s, uint32_t *idx);
+void* pa_idxset_steal_last(pa_idxset *s, uint32_t *idx);
-/* Return the oldest entry in the idxset. Fill in its index in *idx. */
+/* Return the oldest or newest entry in the idxset.
+ * Fill in its index in *idx. */
void* pa_idxset_first(pa_idxset *s, uint32_t *idx);
+void* pa_idxset_last(pa_idxset *s, uint32_t *idx);
-/* Return the entry following the entry indexed by *idx. After the
- * call *index contains the index of the returned
- * object. pa_idxset_first() and pa_idxset_next() may be used to
- * iterate through the set.*/
+/* Return the entry following or preceding the entry indexed by *idx.
+ * After the call *index contains the index of the returned object.
+ * pa_idxset_first() and pa_idxset_next() may be used to iterate through
+ * the set. pa_idxset_last() and pa_idxset_previous() may be used to
+ * iterate through the set in reverse. */
void *pa_idxset_next(pa_idxset *s, uint32_t *idx);
+void *pa_idxset_previous(pa_idxset *s, uint32_t *idx);
/* Return the current number of entries in the idxset */
unsigned pa_idxset_size(pa_idxset*s);
--
2.33.0

View File

@ -6,7 +6,7 @@
Name: pulseaudio
Summary: Improved Linux Sound Server
Version: 16.1
Release: 6
Release: 7
License: LGPLv2+
URL: https://www.freedesktop.org/wiki/Software/PulseAudio
Source0: https://freedesktop.org/software/pulseaudio/releases/pulseaudio-%{version}.tar.xz
@ -17,6 +17,9 @@ Patch201: pulseaudio-autostart.patch
Patch1001: 0001-Fix-the-problem-that-the-description-field-of-pa_als.patch
Patch1002: 0001-alsa-mixer-avoid-assertion-at-alsa-lib-mixer-API-whe.patch
Patch1003: 0001-alsa-mixer-allow-to-re-attach-the-mixer-control-elem.patch
Patch1004: 0001-idxset-Add-set-contains-function.patch
Patch1005: 0002-idxset-Add-set-comparison-operations.patch
Patch1006: 0003-idxset-Add-reverse-iteration-functions.patch
BuildRequires: meson
BuildRequires: automake libtool gcc-c++ bash-completion
@ -244,6 +247,9 @@ exit 0
%{_mandir}/man*/*
%changelog
* Mon Dec 12 2022 wuxu <wuxu.wu@huawei.com> - 16.1-7
- idxset: Add reverse iteration functions, set comparison operations adn set contains() function
* Mon Dec 12 2022 wuxu <wuxu.wu@huawei.com> - 16.1-6
- alsa-mixer: allow to re-attach the mixer control element