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,
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;
}
*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);
}
}
- 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 *