From: Frieder Schrempf <[email protected]>

In order to make it possible to auto select a default entry by
matching the data of the menu entries by an external matching
function, we add some helpers and expose the
menu_set_default_by_item_data_match() function.

Signed-off-by: Frieder Schrempf <[email protected]>
---
Changes in v3:
* Add a full function comment to describe menu_set_default_by_item_data_match().

Changes in v2:
* Keep the menu structs private and instead only expose one additional
  function, that sets the default by calling an external matching
  function on each entry.
* Change the title and commit message to reflect the changes.
---
 common/menu.c  | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/menu.h |  3 +++
 2 files changed, 57 insertions(+)

diff --git a/common/menu.c b/common/menu.c
index 7b66d199a9..6110b2396c 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -160,6 +160,60 @@ static inline struct menu_item *menu_item_by_key(struct 
menu *m,
        return menu_items_iter(m, menu_item_key_match, item_key);
 }
 
+/*
+ * Find the first matching item, if any exists by calling a matching function
+ * on the items data field.
+ */
+static inline struct menu_item *menu_item_by_matching_fn(struct menu *m,
+                       int match(void *, void *), void * extra)
+{
+       struct list_head *pos, *n;
+       struct menu_item *item;
+       int ret;
+
+       list_for_each_safe(pos, n, &m->items) {
+               item = list_entry(pos, struct menu_item, list);
+               if (item->key) {
+                       ret = match(item->data, extra);
+                       if (ret == 1)
+                               return item;
+               }
+       }
+
+       return NULL;
+}
+
+/*
+ * menu_set_default_by_item_data_match() - sets a menu default option by 
calling
+ * a matching function on each of the menu items data field.
+ *
+ * m - Points to a menu created by menu_create().
+ *
+ * match - Points to a function that is passed a pointer to the items data 
field
+ *         and a pointer to extra data to compare with. It should return 1 on a
+ *         match.
+ *
+ * extra - Points to some data that is passed as a second parameter to the
+ *         matching function.
+ *
+ * key - Points to a char array that will be set to hold the key of the matched
+ *       menu item.
+ *
+ * Returns 0 if successful, or -ENOENT if no matching item was found.
+ */
+int menu_set_default_by_item_data_match(struct menu *m,
+                       int match(void *, void *), void *extra, char **key)
+{
+       struct menu_item *item = menu_item_by_matching_fn(m, match, extra);
+
+       if (!item)
+               return -ENOENT;
+
+       *key = item->key;
+       m->default_item = item;
+       return 0;
+}
+
 /*
  * Set *choice to point to the default item's data, if any default item was
  * set, and returns 1. If no default item was set, returns -ENOENT.
diff --git a/include/menu.h b/include/menu.h
index 2d227c20bd..0a8b41a905 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -18,6 +18,9 @@ int menu_item_add(struct menu *m, char *item_key, void 
*item_data);
 int menu_destroy(struct menu *m);
 void menu_display_statusline(struct menu *m);
 int menu_default_choice(struct menu *m, void **choice);
+int menu_set_default_by_item_data_match(struct menu *m,
+                                       int match(void *, void *), void *extra,
+                                       char **key);
 
 /**
  * menu_show() Show a boot menu
-- 
2.17.1

Reply via email to