const struct wl_message *message;
ffi_type *types[20];
ffi_cif cif;
- union {
- uint32_t uint32;
- char *string;
- void *object;
- uint32_t new_id;
- struct wl_array *array;
- } values[20];
void *args[20];
uint32_t buffer[64];
};
struct wl_closure closure;
};
+union wl_value {
+ uint32_t uint32;
+ char *string;
+ struct wl_object *object;
+ uint32_t new_id;
+ struct wl_array *array;
+};
+
static void
wl_buffer_put(struct wl_buffer *b, const void *data, size_t count)
{
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;
+}
+
struct wl_closure *
wl_connection_demarshal(struct wl_connection *connection,
uint32_t size,
struct wl_hash_table *objects,
const struct wl_message *message)
{
- uint32_t *p, *next, *end, length;
- char *extra;
- int i, count;
- struct wl_object *object;
+ uint32_t *p, *next, *end, length, *uint;
+ char *extra, **s;
+ int i, count, extra_space;
+ struct wl_object **object;
+ struct wl_array **array;
struct wl_closure *closure = &connection->closure;
count = strlen(message->signature) + 2;
assert(0);
}
- if (sizeof closure->buffer < size) {
+ extra_space = wl_message_size_extra(message);
+ if (sizeof closure->buffer < size + extra_space) {
printf("request too big, should malloc tmp buffer here\n");
assert(0);
}
closure->message = message;
closure->types[0] = &ffi_type_pointer;
- closure->args[0] = &closure->values[0];
-
closure->types[1] = &ffi_type_pointer;
- closure->args[1] = &closure->values[1];
wl_connection_copy(connection, closure->buffer, size);
p = &closure->buffer[2];
case 'u':
case 'i':
closure->types[i] = &ffi_type_uint32;
- closure->values[i].uint32 = *p++;
+ closure->args[i] = p++;
break;
case 's':
closure->types[i] = &ffi_type_pointer;
goto err;
}
+ s = (char **) extra;
+ extra += sizeof *s;
+ closure->args[i] = s;
+
if (length == 0) {
- closure->values[i].string = NULL;
+ *s = NULL;
} else {
- closure->values[i].string = (char *) p;
- if (closure->values[i].string[length - 1] != '\0') {
- printf("string not nul-terminated, "
- "message %s(%s)\n",
- message->name,
- message->signature);
- errno = EINVAL;
- goto err;
- }
+ *s = (char *) p;
+ }
+
+ if (length > 0 && (*s)[length - 1] != '\0') {
+ printf("string not nul-terminated, "
+ "message %s(%s)\n",
+ message->name, message->signature);
+ errno = EINVAL;
+ goto err;
}
p = next;
break;
case 'o':
closure->types[i] = &ffi_type_pointer;
- object = wl_hash_table_lookup(objects, *p);
- if (object == NULL && *p != 0) {
+ object = (struct wl_object **) extra;
+ extra += sizeof *object;
+ closure->args[i] = object;
+
+ *object = wl_hash_table_lookup(objects, *p);
+ if (*object == NULL && *p != 0) {
printf("unknown object (%d), message %s(%s)\n",
*p, message->name, message->signature);
errno = EINVAL;
goto err;
}
- closure->values[i].object = object;
+
p++;
break;
case 'n':
closure->types[i] = &ffi_type_uint32;
- closure->values[i].new_id = *p;
+ closure->args[i] = p;
object = wl_hash_table_lookup(objects, *p);
if (object != NULL) {
printf("not a new object (%d), "
goto err;
}
- closure->values[i].array = (struct wl_array *) extra;
- extra += sizeof *closure->values[i].array;
- closure->values[i].array->size = length;
- closure->values[i].array->alloc = 0;
- closure->values[i].array->data = p;
+ array = (struct wl_array **) extra;
+ extra += sizeof *array;
+ closure->args[i] = array;
+
+ *array = (struct wl_array *) extra;
+ extra += sizeof **array;
+
+ (*array)->size = length;
+ (*array)->alloc = 0;
+ (*array)->data = p;
p = next;
break;
case 'h':
closure->types[i] = &ffi_type_uint32;
+
+ uint = (uint32_t *) extra;
+ extra += sizeof *uint;
+ closure->args[i] = uint;
+
wl_buffer_copy(&connection->fds_in,
- &closure->values[i].uint32,
- sizeof closure->values[i].uint32);
- connection->fds_in.tail +=
- sizeof closure->values[i].uint32;
+ uint, sizeof *uint);
+ connection->fds_in.tail += sizeof *uint;
break;
default:
printf("unknown type\n");
assert(0);
break;
}
- closure->args[i] = &closure->values[i];
}
closure->count = i;
{
int result;
- closure->values[0].object = data;
- closure->values[1].object = target;
+ closure->args[0] = &data;
+ closure->args[1] = ⌖
ffi_call(&closure->cif, func, &result, closure->args);
}
void
wl_closure_print(struct wl_closure *closure, struct wl_object *target)
{
- struct wl_object *object;
+ union wl_value *value;
int i;
fprintf(stderr, "%s(%d).%s(",
for (i = 2; i < closure->count; i++) {
if (i > 2)
fprintf(stderr, ", ");
+
+ value = closure->args[i];
switch (closure->message->signature[i - 2]) {
case 'u':
- fprintf(stderr, "%u", closure->values[i].uint32);
+ fprintf(stderr, "%u", value->uint32);
break;
case 'i':
- fprintf(stderr, "%d", closure->values[i].uint32);
+ fprintf(stderr, "%d", value->uint32);
break;
case 's':
- fprintf(stderr, "\"%s\"", closure->values[i].string);
+ fprintf(stderr, "\"%s\"", value->string);
break;
case 'o':
- object = closure->values[i].object;
- fprintf(stderr, "object %u", object ? object->id : 0);
+ fprintf(stderr, "object %u",
+ value->object ? value->object->id : 0);
break;
case 'n':
- fprintf(stderr, "new id %u",
- closure->values[i].uint32);
+ fprintf(stderr, "new id %u", value->uint32);
break;
case 'a':
fprintf(stderr, "array");
break;
case 'h':
- fprintf(stderr, "fd %d", closure->values[i].uint32);
+ fprintf(stderr, "fd %d", value->uint32);
break;
}
}