From: Szymon Janc <szymon.janc@codecoup.pl>
To: ell@lists.01.org
Subject: [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist
Date: Fri, 01 Dec 2017 16:06:05 +0100 [thread overview]
Message-ID: <20171201150610.9696-2-szymon.janc@codecoup.pl> (raw)
In-Reply-To: <20171201150610.9696-1-szymon.janc@codecoup.pl>
[-- Attachment #1: Type: text/plain, Size: 6541 bytes --]
This allows to build messages from va_list.
---
ell/dbus-message.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ell/dbus.h | 4 +
2 files changed, 226 insertions(+)
diff --git a/ell/dbus-message.c b/ell/dbus-message.c
index 0314a07..6e64a13 100644
--- a/ell/dbus-message.c
+++ b/ell/dbus-message.c
@@ -1930,6 +1930,228 @@ LIB_EXPORT bool l_dbus_message_builder_append_from_iter(
return true;
}
+LIB_EXPORT bool l_dbus_message_builder_append_from_valist(
+ struct l_dbus_message_builder *builder,
+ const char *signature, va_list args)
+{
+ struct builder_driver *driver;
+ char subsig[256];
+ const char *sigend;
+ /* Nesting requires an extra stack entry for the base level */
+ struct container stack[DBUS_MAX_NESTING + 1];
+ unsigned int stack_index = 0;
+
+ if (unlikely(!builder))
+ return false;
+
+ driver = builder->driver;
+
+ stack[stack_index].type = DBUS_CONTAINER_TYPE_STRUCT;
+ stack[stack_index].sig_start = signature;
+ stack[stack_index].sig_end = signature + strlen(signature);
+ stack[stack_index].n_items = 0;
+
+ while (stack_index != 0 || stack[0].sig_start != stack[0].sig_end) {
+ const char *s;
+ const char *str;
+
+ if (stack[stack_index].type == DBUS_CONTAINER_TYPE_ARRAY &&
+ stack[stack_index].n_items == 0)
+ stack[stack_index].sig_start =
+ stack[stack_index].sig_end;
+
+ if (stack[stack_index].sig_start ==
+ stack[stack_index].sig_end) {
+ bool ret;
+
+ /*
+ * Sanity check in case of an invalid signature that
+ * isn't caught elsewhere.
+ */
+ if (unlikely(stack_index == 0))
+ return false;
+
+ switch (stack[stack_index].type) {
+ case DBUS_CONTAINER_TYPE_STRUCT:
+ ret = driver->leave_struct(builder->builder);
+ break;
+ case DBUS_CONTAINER_TYPE_DICT_ENTRY:
+ ret = driver->leave_dict(builder->builder);
+ break;
+ case DBUS_CONTAINER_TYPE_VARIANT:
+ ret = driver->leave_variant(builder->builder);
+ break;
+ case DBUS_CONTAINER_TYPE_ARRAY:
+ ret = driver->leave_array(builder->builder);
+ break;
+ default:
+ ret = false;
+ }
+
+ if (!ret)
+ return false;
+
+ stack_index -= 1;
+ continue;
+ }
+
+ s = stack[stack_index].sig_start;
+
+ if (stack[stack_index].type != DBUS_CONTAINER_TYPE_ARRAY)
+ stack[stack_index].sig_start += 1;
+ else
+ stack[stack_index].n_items -= 1;
+
+ switch (*s) {
+ case 'o':
+ case 's':
+ case 'g':
+ str = va_arg(args, const char *);
+
+ if (!driver->append_basic(builder->builder, *s, str))
+ return false;
+ break;
+ case 'b':
+ case 'y':
+ {
+ uint8_t y = (uint8_t) va_arg(args, int);
+
+ if (!driver->append_basic(builder->builder, *s, &y))
+ return false;
+
+ break;
+ }
+ case 'n':
+ case 'q':
+ {
+ uint16_t n = (uint16_t) va_arg(args, int);
+
+ if (!driver->append_basic(builder->builder, *s, &n))
+ return false;
+
+ break;
+ }
+ case 'i':
+ case 'u':
+ {
+ uint32_t u = va_arg(args, uint32_t);
+
+ if (!driver->append_basic(builder->builder, *s, &u))
+ return false;
+
+ break;
+ }
+ case 'h':
+ {
+ int fd = va_arg(args, int);
+ struct l_dbus_message *message = builder->message;
+
+ if (!driver->append_basic(builder->builder, *s,
+ &message->num_fds))
+ return false;
+
+ if (message->num_fds < L_ARRAY_SIZE(message->fds))
+ message->fds[message->num_fds++] =
+ fcntl(fd, F_DUPFD_CLOEXEC, 3);
+
+ break;
+ }
+ case 'x':
+ case 't':
+ {
+ uint64_t x = va_arg(args, uint64_t);
+
+ if (!driver->append_basic(builder->builder, *s, &x))
+ return false;
+ break;
+ }
+ case 'd':
+ {
+ double d = va_arg(args, double);
+
+ if (!driver->append_basic(builder->builder, *s, &d))
+ return false;
+ break;
+ }
+ case '(':
+ case '{':
+ if (stack_index == DBUS_MAX_NESTING)
+ return false;
+
+ sigend = _dbus_signature_end(s);
+ memcpy(subsig, s + 1, sigend - s - 1);
+ subsig[sigend - s - 1] = '\0';
+
+ if (*s == '(' && !driver->enter_struct(builder->builder,
+ subsig))
+ return false;
+
+ if (*s == '{' && !driver->enter_dict(builder->builder,
+ subsig))
+ return false;
+
+ if (stack[stack_index].type !=
+ DBUS_CONTAINER_TYPE_ARRAY)
+ stack[stack_index].sig_start = sigend + 1;
+
+ stack_index += 1;
+ stack[stack_index].sig_start = s + 1;
+ stack[stack_index].sig_end = sigend;
+ stack[stack_index].n_items = 0;
+ stack[stack_index].type = *s == '(' ?
+ DBUS_CONTAINER_TYPE_STRUCT :
+ DBUS_CONTAINER_TYPE_DICT_ENTRY;
+
+ break;
+ case 'v':
+ if (stack_index == DBUS_MAX_NESTING)
+ return false;
+
+ str = va_arg(args, const char *);
+
+ if (!str)
+ return false;
+
+ if (!driver->enter_variant(builder->builder, str))
+ return false;
+
+ stack_index += 1;
+ stack[stack_index].type = DBUS_CONTAINER_TYPE_VARIANT;
+ stack[stack_index].sig_start = str;
+ stack[stack_index].sig_end = str + strlen(str);
+ stack[stack_index].n_items = 0;
+
+ break;
+ case 'a':
+ if (stack_index == DBUS_MAX_NESTING)
+ return false;
+
+ sigend = _dbus_signature_end(s + 1) + 1;
+ memcpy(subsig, s + 1, sigend - s - 1);
+ subsig[sigend - s - 1] = '\0';
+
+ if (!driver->enter_array(builder->builder, subsig))
+ return false;
+
+ if (stack[stack_index].type !=
+ DBUS_CONTAINER_TYPE_ARRAY)
+ stack[stack_index].sig_start = sigend;
+
+ stack_index += 1;
+ stack[stack_index].sig_start = s + 1;
+ stack[stack_index].sig_end = sigend;
+ stack[stack_index].n_items = va_arg(args, unsigned int);
+ stack[stack_index].type = DBUS_CONTAINER_TYPE_ARRAY;
+
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
LIB_EXPORT struct l_dbus_message *l_dbus_message_builder_finalize(
struct l_dbus_message_builder *builder)
{
diff --git a/ell/dbus.h b/ell/dbus.h
index 5c7879f..1b1ec2b 100644
--- a/ell/dbus.h
+++ b/ell/dbus.h
@@ -214,6 +214,10 @@ bool l_dbus_message_builder_append_from_iter(
struct l_dbus_message_builder *builder,
struct l_dbus_message_iter *from);
+bool l_dbus_message_builder_append_from_valist(
+ struct l_dbus_message_builder *builder,
+ const char *signature, va_list args);
+
struct l_dbus_message *l_dbus_message_builder_finalize(
struct l_dbus_message_builder *builder);
--
2.14.3
next prev parent reply other threads:[~2017-12-01 15:06 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-01 15:06 [PATCH 0/6] D-Bus client and proxy API Szymon Janc
2017-12-01 15:06 ` Szymon Janc [this message]
2017-12-04 18:25 ` [PATCH 1/6] dbus: Add l_dbus_message_builder_append_from_valist Denis Kenzior
2017-12-01 15:06 ` [PATCH 2/6] dbus: Use l_dbus_message_builder_append_from_valist in append_arguments Szymon Janc
2017-12-04 18:25 ` Denis Kenzior
2017-12-01 15:06 ` [PATCH 3/6] dbus: Add support for proxy interface Szymon Janc
2017-12-04 18:40 ` Denis Kenzior
2017-12-05 17:05 ` Szymon Janc
2017-12-01 15:06 ` [PATCH 4/6] dbus: Add support for setting properties on D-Bus " Szymon Janc
2017-12-01 15:06 ` [PATCH 5/6] dbus: Add convenient API for calling method on " Szymon Janc
2017-12-01 15:06 ` [PATCH 6/6] examples: Extend dbus-client example Szymon Janc
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171201150610.9696-2-szymon.janc@codecoup.pl \
--to=szymon.janc@codecoup.pl \
--cc=ell@lists.01.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.