chiark / gitweb /
bus: add sd_bus_message_append_string_space() for zero-copy string appending
authorLennart Poettering <lennart@poettering.net>
Thu, 9 May 2013 23:12:15 +0000 (01:12 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 10 May 2013 01:38:11 +0000 (03:38 +0200)
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/test-bus-marshal.c
src/systemd/sd-bus.h

index afd4551..fdc3ac6 100644 (file)
@@ -1207,6 +1207,60 @@ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
         return message_append_basic(m, type, p, NULL);
 }
 
+int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) {
+        struct bus_container *c;
+        char *e;
+        void *a;
+        int r;
+
+        if (!m)
+                return -EINVAL;
+        if (!s)
+                return -EINVAL;
+        if (m->sealed)
+                return -EPERM;
+
+        c = message_get_container(m);
+
+        if (c->signature && c->signature[c->index]) {
+                /* Container signature is already set */
+
+                if (c->signature[c->index] != SD_BUS_TYPE_STRING)
+                        return -ENXIO;
+        } else {
+                /* Maybe we can append to the signature? But only if this is the top-level container*/
+                if (c->enclosing != 0)
+                        return -ENXIO;
+
+                e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
+                if (!e)
+                        return -ENOMEM;
+        }
+
+
+        a = message_extend_body(m, 4, 4 + size + 1);
+        if (!a) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        *(uint32_t*) a = size;
+        *s = (char*) a + 4;
+
+        (*s)[size] = 0;
+
+        if (c->enclosing != SD_BUS_TYPE_ARRAY)
+                c->index++;
+
+        return 0;
+
+fail:
+        if (e)
+                c->signature[c->index] = 0;
+
+        return r;
+}
+
 static int bus_message_open_array(
                 sd_bus_message *m,
                 struct bus_container *c,
@@ -1799,7 +1853,7 @@ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
         return r;
 }
 
-int sd_bus_message_append_array_ptr(sd_bus_message *m, char type, size_t size, void **ptr) {
+int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr) {
         ssize_t align, sz;
         void *a;
         int r;
@@ -1851,7 +1905,7 @@ int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, s
         if (!ptr && size > 0)
                 return -EINVAL;
 
-        r = sd_bus_message_append_array_ptr(m, type, size, &p);
+        r = sd_bus_message_append_array_space(m, type, size, &p);
         if (r < 0)
                 return r;
 
index ac51953..ef1a77f 100644 (file)
@@ -44,6 +44,7 @@ int main(int argc, char *argv[]) {
         size_t sz;
         char *h;
         const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
+        char *s;
 
         r = sd_bus_message_new_method_call(NULL, "foobar.waldo", "/", "foobar.waldo", "Piep", &m);
         assert_se(r >= 0);
@@ -78,6 +79,10 @@ int main(int argc, char *argv[]) {
         r = sd_bus_message_close_container(m);
         assert_se(r >= 0);
 
+        r = sd_bus_message_append_string_space(m, 5, &s);
+        assert_se(r >= 0);
+        strcpy(s, "hallo");
+
         r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
         assert_se(r >= 0);
 
@@ -172,6 +177,10 @@ int main(int argc, char *argv[]) {
         assert_se(streq(x, "foobar"));
         assert_se(streq(y, "waldo"));
 
+        r = sd_bus_message_read_basic(m, 's', &s);
+        assert_se(r > 0);
+        assert_se(streq(s, "hallo"));
+
         r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
         assert_se(r > 0);
         assert_se(sz == sizeof(integer_array));
index 2dab93d..28c8536 100644 (file)
@@ -158,21 +158,20 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination);
 
 int sd_bus_message_append(sd_bus_message *m, const char *types, ...);
 int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p);
+int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
+int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr);
+int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s);
 int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
 int sd_bus_message_close_container(sd_bus_message *m);
 
 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_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);
 int sd_bus_message_rewind(sd_bus_message *m, int complete);
 
-int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
-int sd_bus_message_append_array_ptr(sd_bus_message *m, char type, size_t size, void **ptr);
-
-int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size);
-
 /* Convenience calls */
 
 int sd_bus_emit_signal(sd_bus *bus, const char *path, const char *interface, const char *member, const char *types, ...);