From 7cd36185d79a2940b8f99c7472149443f5367c18 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 7 Sep 2010 20:57:40 -0400 Subject: [PATCH] Fill out a closure when sending events as well --- connection.c | 127 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 41 deletions(-) diff --git a/connection.c b/connection.c index 851a7d1..530e23f 100644 --- a/connection.c +++ b/connection.c @@ -331,6 +331,32 @@ wl_connection_write(struct wl_connection *connection, connection->data); } +static int +wl_message_size_extra(const struct wl_message *message) +{ + int i, extra; + + for (i = 0, extra = 0; message->signature[i]; i++) { + + switch (message->signature[i]) { + case 's': + case 'o': + extra += sizeof (void *); + break; + case 'a': + extra += sizeof (void *) + sizeof (struct wl_array); + break; + case 'h': + extra += sizeof (uint32_t); + break; + default: + break; + } + } + + return extra; +} + void wl_connection_vmarshal(struct wl_connection *connection, struct wl_object *sender, @@ -338,36 +364,74 @@ wl_connection_vmarshal(struct wl_connection *connection, const struct wl_message *message) { struct wl_closure *closure = &connection->closure; - struct wl_object *object; - uint32_t length, *p, size; + struct wl_object **objectp, *object; + uint32_t length, *p, *start, size; int dup_fd; - struct wl_array *array; - const char *s; - int i, count, fd; + struct wl_array **arrayp, *array; + const char **sp, *s; + char *extra; + int i, count, fd, extra_size; - count = strlen(message->signature); - p = &closure->buffer[2]; - for (i = 0; i < count; i++) { - switch (message->signature[i]) { + extra_size = wl_message_size_extra(message); + closure->message = message; + count = strlen(message->signature) + 2; + extra = (char *) closure->buffer; + start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; + p = &start[2]; + for (i = 2; i < count; i++) { + switch (message->signature[i - 2]) { case 'u': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p; *p++ = va_arg(ap, uint32_t); break; case 'i': + closure->types[i] = &ffi_type_sint32; + closure->args[i] = p; *p++ = va_arg(ap, int32_t); break; case 's': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + sp = (const char **) extra; + extra += sizeof *sp; + s = va_arg(ap, const char *); length = s ? strlen(s) + 1: 0; *p++ = length; + + *sp = (const char *) p; + memcpy(p, s, length); - p += DIV_ROUNDUP(length, sizeof(*p)); + p += DIV_ROUNDUP(length, sizeof *p); break; case 'o': - case 'n': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + objectp = (struct wl_object **) extra; + extra += sizeof *objectp; + object = va_arg(ap, struct wl_object *); + *objectp = object; *p++ = object ? object->id : 0; break; + + case 'n': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p; + object = va_arg(ap, struct wl_object *); + *p++ = object->id; + break; + case 'a': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + arrayp = (struct wl_array **) extra; + extra += sizeof *arrayp; + + *arrayp = (struct wl_array *) extra; + extra += sizeof **arrayp; + array = va_arg(ap, struct wl_array *); if (array == NULL || array->size == 0) { *p++ = 0; @@ -375,8 +439,14 @@ wl_connection_vmarshal(struct wl_connection *connection, } *p++ = array->size; memcpy(p, array->data, array->size); - p = (void *) p + array->size; + + (*arrayp)->size = array->size; + (*arrayp)->alloc = array->alloc; + (*arrayp)->data = p; + + p += DIV_ROUNDUP(array->size, sizeof *p); break; + case 'h': fd = va_arg(ap, int); dup_fd = dup(fd); @@ -393,35 +463,10 @@ wl_connection_vmarshal(struct wl_connection *connection, } } - size = (p - closure->buffer) * sizeof *p; - closure->buffer[0] = sender->id; - closure->buffer[1] = opcode | (size << 16); - wl_connection_write(connection, closure->buffer, size); -} - -static int -wl_message_size_extra(const struct wl_message *message) -{ - int i, extra; - - for (i = 0, extra = 0; message->signature[i]; i++) { - - switch (message->signature[i - 2]) { - case 's': - case 'o': - extra += sizeof (void *); - break; - case 'a': - extra += sizeof (void *) + sizeof (struct wl_array); - break; - case 'h': - extra += sizeof (uint32_t); - default: - break; - } - } - - return extra; + size = (p - start) * sizeof *p; + start[0] = sender->id; + start[1] = opcode | (size << 16); + wl_connection_write(connection, start, size); } struct wl_closure * -- 2.7.4