From f8e013f8bf476e6d61fb2e218c85e23032a46302 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 10 May 2013 01:12:15 +0200 Subject: [PATCH] bus: add sd_bus_message_append_string_space() for zero-copy string appending --- src/libsystemd-bus/bus-message.c | 58 ++++++++++++++++++++++++++- src/libsystemd-bus/test-bus-marshal.c | 9 +++++ src/systemd/sd-bus.h | 9 ++--- 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index afd4551b4..fdc3ac681 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -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; diff --git a/src/libsystemd-bus/test-bus-marshal.c b/src/libsystemd-bus/test-bus-marshal.c index ac519531f..ef1a77f5f 100644 --- a/src/libsystemd-bus/test-bus-marshal.c +++ b/src/libsystemd-bus/test-bus-marshal.c @@ -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)); diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 2dab93d91..28c853699 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -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, ...); -- 2.30.2