bus: add sd_bus_message_skip() to skip over multiple fields

This commit is contained in:
Lennart Poettering
2013-11-05 02:26:48 +01:00
parent 0dcd14b940
commit 9b07511d65
3 changed files with 176 additions and 7 deletions
+145 -7
View File
@@ -3324,7 +3324,6 @@ static int message_read_ap(
r = sd_bus_message_read_basic(m, *t, p);
if (r < 0)
return r;
if (r == 0) {
if (n_loop <= 1)
return 0;
@@ -3453,12 +3452,9 @@ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
va_list ap;
int r;
if (!m)
return -EINVAL;
if (!m->sealed)
return -EPERM;
if (!types)
return -EINVAL;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(types, -EINVAL);
va_start(ap, types);
r = message_read_ap(m, types, ap);
@@ -3467,6 +3463,148 @@ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
return r;
}
int sd_bus_message_skip(sd_bus_message *m, const char *types) {
int r;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(types, -EINVAL);
if (isempty(types))
return 0;
switch (*types) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD:
r = sd_bus_message_read_basic(m, *types, NULL);
if (r <= 0)
return r;
r = sd_bus_message_skip(m, types + 1);
if (r < 0)
return r;
return 1;
case SD_BUS_TYPE_ARRAY: {
size_t k;
r = signature_element_length(types + 1, &k);
if (r < 0)
return r;
{
char s[k+1];
memcpy(s, types+1, k);
s[k] = 0;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
if (r <= 0)
return r;
for (;;) {
r = sd_bus_message_skip(m, s);
if (r < 0)
return r;
if (r == 0)
break;
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
}
r = sd_bus_message_skip(m, types + 1 + k);
if (r < 0)
return r;
return 1;
}
case SD_BUS_TYPE_VARIANT: {
const char *contents;
char x;
r = sd_bus_message_peek_type(m, &x, &contents);
if (r <= 0)
return r;
if (x != SD_BUS_TYPE_VARIANT)
return -ENXIO;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
if (r <= 0)
return r;
r = sd_bus_message_skip(m, contents);
if (r < 0)
return r;
assert(r != 0);
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
r = sd_bus_message_skip(m, types + 1);
if (r < 0)
return r;
return 1;
}
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = signature_element_length(types, &k);
if (r < 0)
return r;
{
char s[k-1];
memcpy(s, types+1, k-2);
s[k-2] = 0;
r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
if (r <= 0)
return r;
r = sd_bus_message_skip(m, s);
if (r < 0)
return r;
assert(r != 0);
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
}
r = sd_bus_message_skip(m, types + k);
if (r < 0)
return r;
return 1;
}
default:
return -EINVAL;
}
}
int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size) {
struct bus_container *c;
void *p;
+30
View File
@@ -232,5 +232,35 @@ int main(int argc, char *argv[]) {
assert_se(first_size == third_size);
assert_se(memcmp(first, third, third_size) == 0);
r = sd_bus_message_rewind(m, true);
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
r = sd_bus_message_skip(m, "sas");
assert_se(r > 0);
assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
r = sd_bus_message_skip(m, "sass");
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
r = sd_bus_message_skip(m, "a{yv}");
assert_se(r >= 0);
assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
assert_se(r > 0);
assert_se(boolean);
assert_se(streq(x, "aaa"));
assert_se(streq(y, "1"));
assert_se(streq(a, "bbb"));
assert_se(streq(b, "2"));
assert_se(streq(c, "ccc"));
assert_se(streq(d, "3"));
return 0;
}
+1
View File
@@ -197,6 +197,7 @@ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all);
int sd_bus_message_read(sd_bus_message *m, const char *types, ...);
int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p);
int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size);
int sd_bus_message_skip(sd_bus_message *m, const char *types);
int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_exit_container(sd_bus_message *m);
int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents);