signed_24_8 is a signed decimal type which offers a sign bit, 23 bits of integer precision, and 8 bits of decimal precision. This is converted to double on the C API side, as passing through varargs involves an implicit type promotion to double anyway.
Signed-off-by: Daniel Stone <dan...@fooishbar.org> --- src/Makefile.am | 4 ++-- src/connection.c | 29 +++++++++++++++++++++++++++++ src/scanner.c | 9 +++++++++ tests/connection-test.c | 20 ++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c685885..f93954e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ libwayland_util_la_SOURCES = \ wayland-os.h \ wayland-private.h -libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt +libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm libwayland_server_la_SOURCES = \ wayland-protocol.c \ wayland-server.c \ @@ -26,7 +26,7 @@ libwayland_server_la_SOURCES = \ data-device.c \ event-loop.c -libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt +libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm libwayland_client_la_SOURCES = \ wayland-protocol.c \ wayland-client.c diff --git a/src/connection.c b/src/connection.c index 06cc66f..15d571d 100644 --- a/src/connection.c +++ b/src/connection.c @@ -22,6 +22,7 @@ #define _GNU_SOURCE +#include <math.h> #include <stdlib.h> #include <stdint.h> #include <string.h> @@ -382,6 +383,8 @@ wl_message_size_extra(const struct wl_message *message) case 'h': extra += sizeof (int); break; + case 'f': + extra += sizeof (double); default: break; } @@ -415,6 +418,8 @@ wl_closure_vmarshal(struct wl_closure *closure, const char **sp, *s; char *extra; int i, count, fd, extra_size, *fd_ptr; + double d; + uint32_t u; extra_size = wl_message_size_extra(message); count = strlen(message->signature) + 2; @@ -428,6 +433,17 @@ wl_closure_vmarshal(struct wl_closure *closure, for (i = 2; i < count; i++) { switch (message->signature[i - 2]) { + case 'f': + closure->types[i] = &ffi_type_double; + closure->args[i] = p; + if (end - p < 1) + goto err; + d = va_arg(ap, double); + u = trunc(d); + *p = u << 8; + *p |= (uint32_t) (trunc((fabs(d - u)) * (1 << 8))) & 0xff; + p++; + break; case 'u': closure->types[i] = &ffi_type_uint32; closure->args[i] = p; @@ -567,6 +583,8 @@ wl_connection_demarshal(struct wl_connection *connection, unsigned int i, count, extra_space; struct wl_object **object; struct wl_array **array; + int32_t si; + double *d; count = strlen(message->signature) + 2; if (count > ARRAY_LENGTH(closure->types)) { @@ -611,6 +629,15 @@ wl_connection_demarshal(struct wl_connection *connection, closure->types[i] = &ffi_type_sint32; closure->args[i] = p++; break; + case 'f': + closure->types[i] = &ffi_type_double; + si = *p; + p++; + d = (double *) extra; + extra += sizeof *d; + closure->args[i] = d; + *d = (si >> 8) + (((double) (si & 0xff)) / (1 << 8)); + break; case 's': closure->types[i] = &ffi_type_pointer; length = *p++; @@ -837,6 +864,8 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) case 'i': fprintf(stderr, "%d", value->uint32); break; + case 'f': + fprintf(stderr, "%f", (float) ((value->uint32 >> 8) + ((value->uint32 & 0xff) >> 8))); case 's': fprintf(stderr, "\"%s\"", value->string); break; diff --git a/src/scanner.c b/src/scanner.c index 3fba0ad..9090aad 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -82,6 +82,7 @@ enum arg_type { NEW_ID, INT, UNSIGNED, + SIGNED_24_8, STRING, OBJECT, ARRAY, @@ -296,6 +297,8 @@ start_element(void *data, const char *element_name, const char **atts) arg->type = INT; else if (strcmp(type, "uint") == 0) arg->type = UNSIGNED; + else if (strcmp(type, "signed_24_8") == 0) + arg->type = SIGNED_24_8; else if (strcmp(type, "string") == 0) arg->type = STRING; else if (strcmp(type, "array") == 0) @@ -446,6 +449,9 @@ emit_type(struct arg *a) case UNSIGNED: printf("uint32_t "); break; + case SIGNED_24_8: + printf("double "); + break; case STRING: printf("const char *"); break; @@ -953,6 +959,9 @@ emit_messages(struct wl_list *message_list, case UNSIGNED: printf("u"); break; + case SIGNED_24_8: + printf("f"); + break; case STRING: printf("s"); break; diff --git a/tests/connection-test.c b/tests/connection-test.c index 54ac423..5f090b7 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -153,6 +154,7 @@ struct marshal_data { int32_t i; const char *s; int h; + double d; } value; }; @@ -288,6 +290,13 @@ validate_demarshal_h(struct marshal_data *data, } static void +validate_demarshal_d(struct marshal_data *data, + struct wl_object *object, double d) +{ + assert(data->value.d >= (d - 0.0025) && data->value.d <= (d + 0.0025)); +} + +static void demarshal(struct marshal_data *data, const char *format, uint32_t *msg, void (*func)(void)) { @@ -335,6 +344,13 @@ TEST(connection_demarshal) memcpy(&msg[3], data.value.s, msg[2]); demarshal(&data, "s", msg, (void *) validate_demarshal_s); + data.value.d = 5678.1234; + msg[0] = 400200; + msg[1] = 12; + msg[2] = (uint32_t) (trunc(data.value.d)) << 8; + msg[2] |= (uint32_t) (trunc((fabs(data.value.d - (msg[2] >> 8))) * (1 << 8))) & 0xff; + demarshal(&data, "f", msg, (void *) validate_demarshal_d); + release_marshal_data(&data); } @@ -400,6 +416,10 @@ TEST(connection_marshal_demarshal) marshal_demarshal(&data, (void *) validate_demarshal_h, 8, "h", data.value.h); + data.value.d = 1234.5678; + marshal_demarshal(&data, (void *) validate_demarshal_d, + 12, "f", data.value.d); + release_marshal_data(&data); } -- 1.7.10 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel