summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-10-29 19:53:43 +0100
committerLennart Poettering <lennart@poettering.net>2013-10-29 19:53:43 +0100
commit250a918dc4c8a15d927deecc3b3f6a0604657ae4 (patch)
tree18faf995d700c26c67ad500b81e7cce007bc0b95
parent7b1132f60d2a447c31556c23ea90ea31447ac557 (diff)
strv: introduce new strv_from_stdarg_alloca() macro to generate a string array from stdarg function parameters
This allows us to turn lists of strings passed in easily into string arrays without having to allocate memory.
-rw-r--r--src/core/execute.c3
-rw-r--r--src/libsystemd-bus/bus-objects.c30
-rw-r--r--src/shared/conf-files.c10
-rw-r--r--src/shared/strv.h29
-rw-r--r--src/test/test-strv.c53
5 files changed, 76 insertions, 49 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index e04f46f036..3ae28ee080 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2214,7 +2214,8 @@ int exec_command_set(ExecCommand *c, const char *path, ...) {
if (!l)
return -ENOMEM;
- if (!(p = strdup(path))) {
+ p = strdup(path);
+ if (!p) {
strv_free(l);
return -ENOMEM;
}
diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c
index c852ad6c42..31d761e215 100644
--- a/src/libsystemd-bus/bus-objects.c
+++ b/src/libsystemd-bus/bus-objects.c
@@ -1976,8 +1976,7 @@ int sd_bus_emit_properties_changed(
const char *interface,
const char *name, ...) {
- _cleanup_strv_free_ char **names = NULL;
- va_list ap;
+ char **names;
assert_return(bus, -EINVAL);
assert_return(object_path_is_valid(path), -EINVAL);
@@ -1988,12 +1987,7 @@ int sd_bus_emit_properties_changed(
if (!name)
return 0;
- va_start(ap, name);
- names = strv_new_ap(name, ap);
- va_end(ap);
-
- if (!names)
- return -ENOMEM;
+ names = strv_from_stdarg_alloca(name);
return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
}
@@ -2157,20 +2151,14 @@ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **inte
}
int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
- _cleanup_strv_free_ char **interfaces = NULL;
- va_list ap;
+ char **interfaces;
assert_return(bus, -EINVAL);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
- va_start(ap, interface);
- interfaces = strv_new_ap(interface, ap);
- va_end(ap);
-
- if (!interfaces)
- return -ENOMEM;
+ interfaces = strv_from_stdarg_alloca(interface);
return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
}
@@ -2203,20 +2191,14 @@ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **in
}
int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
- _cleanup_strv_free_ char **interfaces = NULL;
- va_list ap;
+ char **interfaces;
assert_return(bus, -EINVAL);
assert_return(object_path_is_valid(path), -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
assert_return(!bus_pid_changed(bus), -ECHILD);
- va_start(ap, interface);
- interfaces = strv_new_ap(interface, ap);
- va_end(ap);
-
- if (!interfaces)
- return -ENOMEM;
+ interfaces = strv_from_stdarg_alloca(interface);
return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
}
diff --git a/src/shared/conf-files.c b/src/shared/conf-files.c
index ed4070c662..7ba4bee43b 100644
--- a/src/shared/conf-files.c
+++ b/src/shared/conf-files.c
@@ -148,18 +148,12 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con
}
int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
- _cleanup_strv_free_ char **dirs = NULL;
- va_list ap;
+ char **dirs;
assert(strv);
assert(suffix);
- va_start(ap, dir);
- dirs = strv_new_ap(dir, ap);
- va_end(ap);
-
- if (!dirs)
- return -ENOMEM;
+ dirs = strv_from_stdarg_alloca(dir);
return conf_files_list_strv_internal(strv, suffix, root, dirs);
}
diff --git a/src/shared/strv.h b/src/shared/strv.h
index cccf2e6a92..737728a3c6 100644
--- a/src/shared/strv.h
+++ b/src/shared/strv.h
@@ -85,3 +85,32 @@ bool strv_overlap(char **a, char **b) _pure_;
char **strv_sort(char **l);
void strv_print(char **l);
+
+#define strv_from_stdarg_alloca(first) \
+ ({ \
+ char **_l; \
+ \
+ if (!first) \
+ _l = ((char*[1]) { NULL }); \
+ else { \
+ unsigned _n; \
+ va_list _ap; \
+ \
+ _n = 1; \
+ va_start(_ap, first); \
+ while (va_arg(_ap, char*)) \
+ _n++; \
+ va_end(_ap); \
+ \
+ _l = newa(char*, _n+1); \
+ _l[_n = 0] = (char*) first; \
+ va_start(_ap, first); \
+ for (;;) { \
+ _l[++_n] = va_arg(_ap, char*); \
+ if (!_l[_n]) \
+ break; \
+ } \
+ va_end(_ap); \
+ } \
+ _l; \
+ })
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index de5cef0b17..7002b8b1c0 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -283,31 +283,31 @@ static void test_strv_append(void) {
}
static void test_strv_foreach(void) {
- _cleanup_strv_free_ char **a;
- unsigned i = 0;
- char **check;
+ _cleanup_strv_free_ char **a;
+ unsigned i = 0;
+ char **check;
- a = strv_new("one", "two", "three", NULL);
+ a = strv_new("one", "two", "three", NULL);
- assert_se(a);
+ assert_se(a);
- STRV_FOREACH(check, a) {
- assert_se(streq(*check, input_table_multiple[i++]));
- }
+ STRV_FOREACH(check, a) {
+ assert_se(streq(*check, input_table_multiple[i++]));
+ }
}
static void test_strv_foreach_backwards(void) {
- _cleanup_strv_free_ char **a;
- unsigned i = 2;
- char **check;
+ _cleanup_strv_free_ char **a;
+ unsigned i = 2;
+ char **check;
- a = strv_new("one", "two", "three", NULL);
+ a = strv_new("one", "two", "three", NULL);
- assert_se(a);
+ assert_se(a);
- STRV_FOREACH_BACKWARDS(check, a) {
- assert_se(streq(*check, input_table_multiple[i--]));
- }
+ STRV_FOREACH_BACKWARDS(check, a) {
+ assert_se(streq(*check, input_table_multiple[i--]));
+ }
}
static void test_strv_foreach_pair(void) {
@@ -324,6 +324,26 @@ static void test_strv_foreach_pair(void) {
}
}
+static void test_strv_from_stdarg_alloca_one(const char **l, const char *first, ...) {
+ char **j;
+ unsigned i;
+
+ j = strv_from_stdarg_alloca(first);
+
+ for (i = 0;; i++) {
+ assert_se(streq_ptr(l[i], j[i]));
+
+ if (!l[i])
+ break;
+ }
+}
+
+static void test_strv_from_stdarg_alloca(void) {
+ test_strv_from_stdarg_alloca_one((const char*[]) { "foo", "bar", NULL }, "foo", "bar", NULL);
+ test_strv_from_stdarg_alloca_one((const char*[]) { "foo", "bar", NULL }, "foo", "bar", NULL);
+ test_strv_from_stdarg_alloca_one((const char*[]) { "foo", NULL }, "foo", NULL);
+}
+
int main(int argc, char *argv[]) {
test_specifier_printf();
test_strv_foreach();
@@ -346,6 +366,7 @@ int main(int argc, char *argv[]) {
test_strv_merge();
test_strv_merge_concat();
test_strv_append();
+ test_strv_from_stdarg_alloca();
return 0;
}