The original docstring of the __sysfs_match_string() and match_string()
helper, implied that -1 could be used to search through NULL terminated
arrays, and positive 'n' could be used to go through arrays that may have
NULL elements in the middle of the array.
This isn't true. Regardless of the value of 'n', the first NULL element in
the array will stop the search, even if the element may be after a NULL
element.
To allow for a behavior where we can use the __sysfs_match_string() to
search over arrays with NULL elements in the middle, the
__sysfs_match_string_with_gaps() helper is added.
If n > 0, the search will continue until the element is found or n is
reached.
If n < 0, the search will continue until the element is found or a NULL
character is found.
Signed-off-by: Alexandru Ardelean <[email protected]>
---
FWIW (from my side): I am not fully sure yet that implementing a
new helper is the best idea. It's also not a bad idea.
It's one of those "this could be useful for others as well later", but
right now we would have only one user (IIO) for this.
I'm also fine with just implementing it in IIO first, and the someone
else can move it to lib/string.c if needed.
For now, this patch serves mostly as a notifier, in case there is more
interest out there for something like this.
I might do a V8, with this implemented in IIO core, and then have it
there, until others would find it useful.
Changelog v6 -> v7:
* https://patchwork.kernel.org/project/linux-iio/patch/[email protected]/
* added standalone __sysfs_match_string_with_gaps() function
include/linux/string.h | 1 +
lib/string.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/include/linux/string.h b/include/linux/string.h
index b1f3894a0a3e..d7999e50dae1 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -191,6 +191,7 @@ static inline int strtobool(const char *s, bool *res)
int match_string(const char * const *array, size_t n, const char *string);
int __sysfs_match_string(const char * const *array, size_t n, const char *s);
+int __sysfs_match_string_with_gaps(const char * const *array, ssize_t n, const char *s);
/**
* sysfs_match_string - matches given string in an array
diff --git a/lib/string.c b/lib/string.c
index 4288e0158d47..bb99313ad4c1 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -785,6 +785,42 @@ int __sysfs_match_string(const char * const *array, size_t n, const char *str)
}
EXPORT_SYMBOL(__sysfs_match_string);
+/**
+ * __sysfs_match_string_with_gaps - matches given string in an array with gaps
+ * @array: array of strings
+ * @n: number of strings in the array or negative for NULL terminated arrays
+ * @str: string to match with
+ *
+ * Returns index of @str in the @array or -EINVAL, similar to match_string().
+ * Uses sysfs_streq instead of strcmp for matching.
+ *
+ * This routine will look for a string in an array of strings.
+ * If n > 0, then the search will continue until the element is found or
+ * the n-th element is reached, regardless of any NULL elements in the array.
+ * If n < 0, then the search will continue until the element is found or
+ * until the first NULL element.
+ */
+int __sysfs_match_string_with_gaps(const char * const *array, ssize_t n,
+ const char *str)
+{
+ const char *item;
+ int index;
+
+ for (index = 0; index < n; index++) {
+ item = array[index];
+ if (!item) {
+ if (n < 0)
+ break;
+ continue;
+ }
+ if (sysfs_streq(item, str))
+ return index;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(__sysfs_match_string_with_gaps);
+
#ifndef __HAVE_ARCH_MEMSET
/**
* memset - Fill a region of memory with the given value
--
2.17.1
From: Lars-Peter Clausen <[email protected]>
Some enums might have gaps or reserved values in the middle of their value
range. E.g. consider a 2-bit enum where the values 0, 1 and 3 have a
meaning, but 2 is a reserved value and can not be used.
Add support for such enums to the IIO enum helper functions. A reserved
values is marked by setting its entry in the items array to NULL rather
than the normal descriptive string value.
Signed-off-by: Lars-Peter Clausen <[email protected]>
Signed-off-by: Alexandru Ardelean <[email protected]>
---
drivers/iio/industrialio-core.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index e9ee9363fed0..5f6211bfb428 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -470,8 +470,11 @@ ssize_t iio_enum_available_read(struct iio_dev *indio_dev,
if (!e->num_items)
return 0;
- for (i = 0; i < e->num_items; ++i)
+ for (i = 0; i < e->num_items; ++i) {
+ if (!e->items[i])
+ continue;
len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]);
+ }
/* replace last space with a newline */
buf[len - 1] = '\n';
@@ -492,7 +495,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev,
i = e->get(indio_dev, chan);
if (i < 0)
return i;
- else if (i >= e->num_items)
+ else if (i >= e->num_items || !e->items[i])
return -EINVAL;
return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
@@ -509,7 +512,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
if (!e->set)
return -EINVAL;
- ret = __sysfs_match_string(e->items, e->num_items, buf);
+ ret = __sysfs_match_string_with_gaps(e->items, e->num_items, buf);
if (ret < 0)
return ret;
--
2.17.1
On Thu, Jan 7, 2021 at 10:41 AM Alexandru Ardelean
<[email protected]> wrote:
>
> The original docstring of the __sysfs_match_string() and match_string()
> helper, implied that -1 could be used to search through NULL terminated
> arrays, and positive 'n' could be used to go through arrays that may have
> NULL elements in the middle of the array.
>
> This isn't true. Regardless of the value of 'n', the first NULL element in
> the array will stop the search, even if the element may be after a NULL
> element.
>
> To allow for a behavior where we can use the __sysfs_match_string() to
> search over arrays with NULL elements in the middle, the
> __sysfs_match_string_with_gaps() helper is added.
> If n > 0, the search will continue until the element is found or n is
> reached.
...
> If n < 0, the search will continue until the element is found or a NULL
> character is found.
And this is what I think is not needed.
...
> FWIW (from my side): I am not fully sure yet that implementing a
> new helper is the best idea. It's also not a bad idea.
> It's one of those "this could be useful for others as well later", but
> right now we would have only one user (IIO) for this.
Taking into account the failure of bitmap_set_clump() promotion, I
suggest to reduce scope to IIO for now.
> I'm also fine with just implementing it in IIO first, and the someone
> else can move it to lib/string.c if needed.
Yes, please do.
...
> + * If n < 0, then the search will continue until the element is found or
> + * until the first NULL element.
...
> + if (n < 0)
> + break;
And drop these.
--
With Best Regards,
Andy Shevchenko