chiark / gitweb /
bus: add sd_bus_message_skip() to skip over multiple fields
authorLennart Poettering <lennart@poettering.net>
Tue, 5 Nov 2013 01:25:24 +0000 (02:25 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 5 Nov 2013 01:26:48 +0000 (02:26 +0100)
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/test-bus-marshal.c
src/systemd/sd-bus.h

index 8cf273c3809c1512ce2b2a12a55e92530d5edb3e..78adf11ae832214e942393f9c383b8c7ec6b7503 100644 (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;
index baa269c9aa051dd1fb8118160ad64ee7fc3382e6..8f270896a8b767a6ba4c132e5f43783afc674909 100644 (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;
 }
index affd309054ed806fa1e09969d6a5477ff087a61b..e0a604111dab772cadee27bfa8f154f61dce7ee0 100644 (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);