#include "config.h"
+#include <stdint.h>
+
#include "util-strings.h"
/**
return str;
}
+/**
+ * Iterate through strv, calling func with each string and its respective index.
+ * Iteration stops successfully after max elements or at the last element,
+ * whichever occurs first.
+ *
+ * If func returns non-zero, iteration stops and strv_for_each returns
+ * that value.
+ *
+ * @return zero on success, otherwise the error returned by the callback
+ */
+int strv_for_each_n(const char **strv, size_t max, strv_foreach_callback_t func, void *data)
+{
+ for (size_t i = 0; i < max && strv && strv[i]; i++) {
+ int ret = func(strv[i], i, data);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * Iterate through strv, calling func with each string and its respective index.
+ * If func returns non-zero, iteration stops and strv_for_each returns
+ * that value.
+ *
+ * @return zero on success, otherwise the error returned by the callback
+ */
+int strv_for_each(const char **strv, strv_foreach_callback_t func, void *data)
+{
+ return strv_for_each_n(strv, SIZE_MAX, func, data);
+}
+
/**
* Return a pointer to the basename within filename.
* If the filename the empty string or a directory (i.e. the last char of
char **strv_from_string(const char *in, const char *separator, size_t *num_elements);
char *strv_join(char **strv, const char *joiner);
+typedef int (*strv_foreach_callback_t)(const char *str, size_t index, void *data);
+int strv_for_each(const char **strv, strv_foreach_callback_t func, void *data);
+int strv_for_each_n(const char **strv, size_t max, strv_foreach_callback_t func, void *data);
+
static inline void
strv_free(char **strv) {
char **s = strv;
}
END_TEST
+struct strv_test_data {
+ const char *terminate_at;
+ unsigned char bitmask[1];
+};
+
+static int strv_test_set_bitmask(const char *str, size_t index, void *data)
+{
+ struct strv_test_data *td = data;
+
+ if (streq(str, td->terminate_at))
+ return index + 1;
+
+ set_bit(td->bitmask, index);
+
+ return 0;
+}
+
+START_TEST(strv_for_each_test)
+{
+ struct test_data {
+ const char *terminator;
+ int index;
+ unsigned int bitmask;
+ } test_data[] = {
+ { "one", 1, 0x0 },
+ { "two", 2, 0x1 },
+ { "three", 3, 0x3 },
+ { "four", 4, 0x7 },
+ { "five", 5, 0xf },
+ { "does-not-exist", 0, 0x1f },
+ { NULL, 0, 0x1f },
+ { NULL, 0 },
+ };
+ const char *array[] = { "one", "two", "three", "four", "five", NULL };
+ struct test_data *t = test_data;
+
+ while (t->terminator || t->bitmask) {
+ const int max = 3;
+ struct strv_test_data td = {
+ .terminate_at = t->terminator,
+ .bitmask = { 0 },
+ };
+
+ int rc = strv_for_each(array, strv_test_set_bitmask, &td);
+ ck_assert_int_eq(rc, t->index);
+ ck_assert_int_eq(td.bitmask[0], t->bitmask);
+
+ struct strv_test_data tdmax = {
+ .terminate_at = t->terminator,
+ .bitmask = { 0 },
+ };
+
+ rc = strv_for_each_n(array, max, strv_test_set_bitmask, &tdmax);
+ if (max < t->index)
+ ck_assert_int_eq(rc, 0);
+ else
+ ck_assert_int_eq(rc, t->index);
+ ck_assert_int_eq(tdmax.bitmask[0], t->bitmask & ((1 << max) - 1));
+
+ t++;
+ }
+}
+
START_TEST(double_array_from_string_test)
{
struct double_array_from_string_test {
tcase_add_test(tc, safe_atou_base_8_test);
tcase_add_test(tc, safe_atod_test);
tcase_add_test(tc, strsplit_test);
+ tcase_add_test(tc, strv_for_each_test);
tcase_add_test(tc, double_array_from_string_test);
tcase_add_test(tc, strargv_test);
tcase_add_test(tc, kvsplit_double_test);