diff mbox series

[alsa-lib,4/6] ctl: add API to compare a pair of control element IDs by numid

Message ID 20210318103013.265264-5-o-takashi@sakamocchi.jp
State New
Headers show
Series add API of equality and comparison for a pair of control element IDs | expand

Commit Message

Takashi Sakamoto March 18, 2021, 10:30 a.m. UTC
The structure for control element ID is compound one. It means that it's
not possible to decide single algorithm to find order of a pair of
control element IDs. For convenience of application developers, it's better
to produce API to decide the order by useful algorithm.

This commit adds API for one of comparison algorithms. The value of
numid field is used for the comparison. I note that the structure includes
some 'unsigned integer' type of fields. The subtraction of the fields
brings integer overflow as long as the calculation is done in the same
storage size of the type itself.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 include/control.h      |  1 +
 src/control/control.c  | 32 +++++++++++++++++++++++++++++++
 test/lsb/ctl-elem-id.c | 43 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)
diff mbox series

Patch

diff --git a/include/control.h b/include/control.h
index 8aca67e6..36953423 100644
--- a/include/control.h
+++ b/include/control.h
@@ -426,6 +426,7 @@  void snd_ctl_elem_id_clear(snd_ctl_elem_id_t *obj);
 void snd_ctl_elem_id_copy(snd_ctl_elem_id_t *dst, const snd_ctl_elem_id_t *src);
 int snd_ctl_elem_id_equal_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
 int snd_ctl_elem_id_equal_by_tuple(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
+int snd_ctl_elem_id_compare_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r);
 int snd_ctl_elem_id_compare(snd_ctl_elem_id_t *id1, const snd_ctl_elem_id_t *id2);
 unsigned int snd_ctl_elem_id_get_numid(const snd_ctl_elem_id_t *obj);
 snd_ctl_elem_iface_t snd_ctl_elem_id_get_interface(const snd_ctl_elem_id_t *obj);
diff --git a/src/control/control.c b/src/control/control.c
index 93f8f93d..00009614 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -88,6 +88,10 @@  snd_ctl_elem_id_equal_by_numid() is available. For equality check between a pair
 of #snd_ctl_elem_id_t according to the tuple, snd_ctl_elem_id_equal_by_tuple()
 is available.
 
+Many algorithms can be defined to find ordered pair of #snd_ctl_elem_id_t.
+For one of the comparison algorithms according to the numid,
+snd_ctl_elem_id_compare_by_numid() is available.
+
 \section element_lists Element Lists
 
 An element list can be used to obtain a list of all elements of the
@@ -1861,6 +1865,34 @@  int snd_ctl_elem_id_equal_by_tuple(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
 	       (l->index == r->index);
 }
 
+static int compare_unsigned_integer(unsigned int l, unsigned int r)
+{
+	if (l == r)
+		return 0;
+	else if (l < r)
+		return -1;
+	else
+		return 1;
+}
+
+/**
+ * \brief compare two arguments as orderd items by algorithm according to numid.
+ * \param l opaque pointer to element ID structure.
+ * \param r opaque pointer to another element ID structure.
+ * \retval positive if left is greater than right, negative if left is less
+ *	   than right, zero if they equal.
+ *
+ * The structure underlying #snd_ctl_elem_id_t is compound one. The
+ * comparison algorithm for it is not single and unique. The API implements
+ * one of comparison algorithms, according to the value of numid field.
+ */
+int snd_ctl_elem_id_compare_by_numid(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	assert(l && r);
+
+	return compare_unsigned_integer(l->numid, r->numid);
+}
+
 /**
  * \brief compare one #snd_ctl_elem_id_t to another
  * \param id1 pointer to first id
diff --git a/test/lsb/ctl-elem-id.c b/test/lsb/ctl-elem-id.c
index 39060a8e..670ec252 100644
--- a/test/lsb/ctl-elem-id.c
+++ b/test/lsb/ctl-elem-id.c
@@ -16,6 +16,8 @@ 
 
 #include <unistd.h>
 
+#include <limits.h>
+
 #include "../include/asoundlib.h"
 
 static void set_elem_id_by_tuple(snd_ctl_elem_id_t *elem_id,
@@ -96,6 +98,43 @@  static void equality_by_tuple_3(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
 	assert(!snd_ctl_elem_id_equal_by_tuple(l, r));
 }
 
+// Case 2.0. The left object with less value in numid field than right object
+//	     should result in negative value.
+static void comparison_by_numid_0(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	snd_ctl_elem_id_set_numid(l, 0xdeadbeef);
+	snd_ctl_elem_id_set_numid(r, 0xfeedc0de);
+	assert(snd_ctl_elem_id_compare_by_numid(l, r) < 0);
+}
+
+// Case 2.1. The left object with the same value in numid field as right object
+//	     should result in zero.
+static void comparison_by_numid_1(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	snd_ctl_elem_id_set_numid(l, 0xfeedc0de);
+	snd_ctl_elem_id_set_numid(r, 0xfeedc0de);
+	assert(snd_ctl_elem_id_compare_by_numid(l, r) == 0);
+}
+
+// Case 2.2. The left object with greater value in numid field than right object
+//	     should result in positive.
+static void comparison_by_numid_2(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	snd_ctl_elem_id_set_numid(l, 0xfeedc0de);
+	snd_ctl_elem_id_set_numid(r, 0xdeadbeef);
+	assert(snd_ctl_elem_id_compare_by_numid(l, r) > 0);
+}
+
+// Case 2.3. The left object with lesser value in numid field than right object
+//	     should result in negative. The subtraction shoud be calculated in
+//	     storage larger than the storage of 'unsigned int'.
+static void comparison_by_numid_3(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r)
+{
+	snd_ctl_elem_id_set_numid(l, 0);
+	snd_ctl_elem_id_set_numid(r, UINT_MAX);
+	assert(snd_ctl_elem_id_compare_by_numid(l, r) < 0);
+}
+
 int main()
 {
 	void (*entries[])(snd_ctl_elem_id_t *l, snd_ctl_elem_id_t *r) = {
@@ -107,6 +146,10 @@  int main()
 		equality_by_tuple_1,
 		equality_by_tuple_2,
 		equality_by_tuple_3,
+		comparison_by_numid_0,
+		comparison_by_numid_1,
+		comparison_by_numid_2,
+		comparison_by_numid_3,
 	};
 	int count = sizeof(entries) / sizeof(*entries);
 	int fd;