From: "Marek Behún" <kabel@kernel.org>
To: "Simon Glass" <sjg@chromium.org>, "Pali Rohár" <pali@kernel.org>
Cc: u-boot@lists.denx.de, "Marek Behún" <marek.behun@nic.cz>
Subject: [PATCH v2 08/12] sysinfo: Add support for iterating string list
Date: Thu, 4 Nov 2021 00:23:28 +0100 [thread overview]
Message-ID: <20211103232332.2737-9-kabel@kernel.org> (raw)
In-Reply-To: <20211103232332.2737-1-kabel@kernel.org>
From: Marek Behún <marek.behun@nic.cz>
Add function
sysinfo_get_str_list_max_len()
to determine length of the longest string in a string list, functions
sysinfo_str_list_first() and
sysinfo_str_list_next()
to support iteration over string list elements and macro
for_each_sysinfo_str_list()
to make the iteration simple to use.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
drivers/sysinfo/sysinfo-uclass.c | 79 +++++++++++++++++++++++++
include/sysinfo.h | 99 ++++++++++++++++++++++++++++++++
test/dm/sysinfo.c | 35 +++++++++++
3 files changed, 213 insertions(+)
diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c
index d945f073c5..78035a95aa 100644
--- a/drivers/sysinfo/sysinfo-uclass.c
+++ b/drivers/sysinfo/sysinfo-uclass.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <sysinfo.h>
struct sysinfo_priv {
@@ -104,6 +105,84 @@ int sysinfo_get_str_list(struct udevice *dev, int id, unsigned idx, size_t size,
return ops->get_str_list(dev, id, idx, size, val);
}
+int sysinfo_get_str_list_max_len(struct udevice *dev, int id)
+{
+ int maxlen = 0;
+ unsigned i;
+
+ /* first find out length of the longest string in the list */
+ for (i = 0; ; ++i) {
+ char dummy[1];
+ int len;
+
+ len = sysinfo_get_str_list(dev, id, i, 0, dummy);
+ if (len == -ERANGE)
+ break;
+ else if (len < 0)
+ return len;
+ else if (len > maxlen)
+ maxlen = len;
+ }
+
+ return maxlen;
+}
+
+struct sysinfo_str_list_iter {
+ struct udevice *dev;
+ int id;
+ size_t size;
+ unsigned idx;
+ char value[];
+};
+
+char *sysinfo_str_list_first(struct udevice *dev, int id, void *_iter)
+{
+ struct sysinfo_str_list_iter *iter, **iterp = _iter;
+ int maxlen, res;
+
+ maxlen = sysinfo_get_str_list_max_len(dev, id);
+ if (maxlen < 0)
+ return NULL;
+
+ iter = malloc(sizeof(struct sysinfo_str_list_iter) + maxlen + 1);
+ if (!iter) {
+ printf("No memory for sysinfo string list iterator\n");
+ return NULL;
+ }
+
+ iter->dev = dev;
+ iter->id = id;
+ iter->size = maxlen + 1;
+ iter->idx = 0;
+
+ res = sysinfo_get_str_list(dev, id, 0, iter->size, iter->value);
+ if (res < 0) {
+ *iterp = NULL;
+ free(iter);
+ return NULL;
+ }
+
+ *iterp = iter;
+
+ return iter->value;
+}
+
+char *sysinfo_str_list_next(void *_iter)
+{
+ struct sysinfo_str_list_iter **iterp = _iter, *iter = *iterp;
+ int res;
+
+ res = sysinfo_get_str_list(iter->dev, iter->id, ++iter->idx, iter->size,
+ iter->value);
+ if (res < 0) {
+ *iterp = NULL;
+ free(iter);
+ return NULL;
+ }
+
+ return iter->value;
+}
+
UCLASS_DRIVER(sysinfo) = {
.id = UCLASS_SYSINFO,
.name = "sysinfo",
diff --git a/include/sysinfo.h b/include/sysinfo.h
index 0d8a2d1676..d32bf3e808 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -218,6 +218,61 @@ int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val);
int sysinfo_get_str_list(struct udevice *dev, int id, unsigned idx, size_t size,
char *val);
+/**
+ * sysinfo_get_str_list_max_len() - Get length of longest string in a string
+ * list that describes hardware setup.
+ * @dev: The sysinfo instance to gather the data.
+ * @id: A unique identifier for the string list to read from.
+ *
+ * Return: Length (excluding the terminating NULL-byte) of the longest string in
+ * the string list, or -ve on error.
+ */
+int sysinfo_get_str_list_max_len(struct udevice *dev, int id);
+
+/**
+ * sysinfo_str_list_first() - Start iterating a string list.
+ * @dev: The sysinfo instance to gather the data.
+ * @id: A unique identifier for the string list to read from.
+ * @_iter: Pointer where iterator data will be stored.
+ *
+ * Pass a reference to a void * pointer as @_iter, i.e.
+ * void *iter;
+ * first = sysinfo_str_list_first(dev, id, &iter);
+ *
+ * The function will allocate space for the value. You need to iterate all
+ * elements with sysinfo_str_list_next() for the space to be freed, or free
+ * the pointer stored in @_iter, i.e.
+ * void *iter;
+ * first = sysinfo_str_list_first(dev, id, &iter);
+ * if (first)
+ * free(iter);
+ *
+ * Return: First string in the string list, or NULL on error.
+ */
+char *sysinfo_str_list_first(struct udevice *dev, int id, void *_iter);
+
+/**
+ * sysinfo_str_list_next() - Get next string in the string string list.
+ * @_iter: Pointer to iterator, filled in by sysinfo_str_list_first().
+ *
+ * Pass a reference to a void * pointer as @_iter, i.e.
+ * void *iter;
+ * first = sysinfo_str_list_first(dev, id, &iter);
+ * next = sysinfo_str_list_next(&iter);
+ *
+ * All elements must be iterated until the function returns NULL for the
+ * resources allocated for the iteration to be freed, or pointer stored in
+ * @_iter must be freed, i.e.:
+ * void *iter;
+ * first = sysinfo_str_list_first(dev, id, &iter);
+ * next = sysinfo_str_list_next(&iter);
+ * if (next)
+ * free(iter);
+ *
+ * Return: Next string in the string list, NULL on end of list or NULL on error.
+ */
+char *sysinfo_str_list_next(void *_iter);
+
/**
* sysinfo_get() - Return the sysinfo device for the sysinfo in question.
* @devp: Pointer to structure to receive the sysinfo device.
@@ -279,6 +334,22 @@ static inline int sysinfo_get_str_list(struct udevice *dev, int id,
return -ENOSYS;
}
+static inline int sysinfo_get_str_list_max_len(struct udevice *dev, int id)
+{
+ return -ENOSYS;
+}
+
+static inline char *sysinfo_str_list_first(struct udevice *dev, int id,
+ void *_iter)
+{
+ return NULL;
+}
+
+static inline char *sysinfo_str_list_next(void *_iter)
+{
+ return NULL;
+}
+
static inline int sysinfo_get(struct udevice **devp)
{
return -ENOSYS;
@@ -291,4 +362,32 @@ static inline int sysinfo_get_fit_loadable(struct udevice *dev, int index,
}
#endif
+
+/**
+ * for_each_sysinfo_str_list - Iterate a sysinfo string list
+ * @dev: The sysinfo instance to gather the data.
+ * @id: A unique identifier for the string list to read from.
+ * @val: String pointer for the value.
+ * @iter: Pointer where iteration data are stored.
+ *
+ * Important: all elements of the list must be iterated for the iterator
+ * resources to be freed automatically. If you need to break from the for cycle,
+ * you need to free the iterator.
+ *
+ * Example:
+ * char *value;
+ * void *iter;
+ * for_each_sysinfo_str_list(dev, MY_STR_LIST, value, iter) {
+ * printf("Value: %s\n", value);
+ * if (!strcmp(value, "needle")) {
+ * free(iter);
+ * break;
+ * }
+ * }
+ */
+#define for_each_sysinfo_str_list(dev, id, val, iter) \
+ for ((val) = sysinfo_str_list_first((dev), (id), &(iter)); \
+ (val); \
+ (val) = sysinfo_str_list_next(&(iter)))
+
#endif
diff --git a/test/dm/sysinfo.c b/test/dm/sysinfo.c
index a6b246f2df..e9b70d8e1a 100644
--- a/test/dm/sysinfo.c
+++ b/test/dm/sysinfo.c
@@ -75,3 +75,38 @@ static int dm_test_sysinfo(struct unit_test_state *uts)
}
DM_TEST(dm_test_sysinfo, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_sysinfo_str_list_iter(struct unit_test_state *uts)
+{
+ struct udevice *sysinfo;
+ char *value;
+ void *iter;
+ int idx;
+
+ ut_assertok(sysinfo_get(&sysinfo));
+ ut_assert(sysinfo);
+
+ sysinfo_detect(sysinfo);
+
+ idx = 0;
+ for_each_sysinfo_str_list(sysinfo, STR_VACATIONSPOT, value, iter) {
+ switch (idx) {
+ case 0:
+ ut_asserteq_str(value, "R'lyeh");
+ break;
+ case 2:
+ ut_asserteq_str(value, "Plateau of Leng");
+ break;
+ case 3:
+ ut_asserteq_str(value, "Carcosa");
+ break;
+ }
+ ++idx;
+ }
+
+ ut_assert(NULL == iter);
+
+ return 0;
+}
+
+DM_TEST(dm_test_sysinfo_str_list_iter, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
--
2.32.0
next prev parent reply other threads:[~2021-11-03 23:24 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-03 23:23 [PATCH v2 00/12] Board specific runtime determined default env Marek Behún
2021-11-03 23:23 ` [PATCH v2 01/12] env: Don't set ready flag if import failed in env_set_default() Marek Behún
2021-11-14 0:34 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 02/12] env: Fix env_get() when returning empty string using env_get_f() Marek Behún
2021-11-14 0:34 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 03/12] env: Simplify env_get_default() Marek Behún
2021-11-14 0:34 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 04/12] sysinfo: Make sysinfo_get_str() behave like snprintf() Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-05 11:19 ` Marek Behún
2021-11-05 16:12 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 05/12] test: Use ut_asserteq_str() instead of ut_assertok(strcmp()) Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 06/12] sysinfo: Add get_str_list() method Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-05 11:20 ` Marek Behún
2021-11-05 16:12 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 07/12] sysinfo: Make .detect() non-mandatory Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-03 23:23 ` Marek Behún [this message]
2021-11-05 2:02 ` [PATCH v2 08/12] sysinfo: Add support for iterating string list Simon Glass
2021-11-05 11:24 ` Marek Behún
2021-11-05 16:12 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 09/12] env: Change return behaviour of env_set_default_vars() Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 10/12] env: Add support for overwriting default environment via sysinfo Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-03 23:23 ` [PATCH v2 11/12] arm: mvebu: Espressobin: Use new API for setting default env at runtime Marek Behún
2021-11-05 2:02 ` Simon Glass
2021-11-05 8:50 ` Pali Rohár
2021-11-09 15:37 ` Pali Rohár
2021-11-03 23:23 ` [PATCH v2 12/12] env: Remove support for read-write default_environment[] Marek Behún
2021-11-05 2:02 ` Simon Glass
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211103232332.2737-9-kabel@kernel.org \
--to=kabel@kernel.org \
--cc=marek.behun@nic.cz \
--cc=pali@kernel.org \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.