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.
This commit is contained in:
parent
7b1132f60d
commit
250a918dc4
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; \
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue