[PATCH wayland v2 5/6] Add support for signed 24.8 decimal numbers
Daniel Stone
daniel at fooishbar.org
Wed May 2 08:53:34 PDT 2012
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 <daniel at fooishbar.org>
---
src/Makefile.am | 4 ++--
src/connection.c | 33 ++++++++++++++++++++++++++++++++-
src/scanner.c | 9 +++++++++
tests/connection-test.c | 43 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 86 insertions(+), 3 deletions(-)
v2: Fix up broken negative numbers.
Add test cases for large and negative numbers.
Add test case for too-large numbers to fail in marshalling.
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..0369fbe 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,7 @@ wl_closure_vmarshal(struct wl_closure *closure,
const char **sp, *s;
char *extra;
int i, count, fd, extra_size, *fd_ptr;
+ double d;
extra_size = wl_message_size_extra(message);
count = strlen(message->signature) + 2;
@@ -428,6 +432,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);
+ if (fabs(trunc(d)) > (1 << 23) - 1)
+ goto err;
+ *p = (int32_t) round(d * 256.0);
+ p++;
+ break;
case 'u':
closure->types[i] = &ffi_type_uint32;
closure->args[i] = p;
@@ -567,6 +582,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 +628,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 = (int32_t) *p;
+ p++;
+ d = (double *) extra;
+ extra += sizeof *d;
+ *d = si / 256.0;
+ closure->args[i] = d;
+ break;
case 's':
closure->types[i] = &ffi_type_pointer;
length = *p++;
@@ -812,6 +838,7 @@ void
wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
{
union wl_value *value;
+ int32_t si;
int i;
struct timespec tp;
unsigned int time;
@@ -835,8 +862,12 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
fprintf(stderr, "%u", value->uint32);
break;
case 'i':
- fprintf(stderr, "%d", value->uint32);
+ si = (int32_t) value->uint32;
+ fprintf(stderr, "%d", si);
break;
+ case 'f':
+ si = (int32_t) value->uint32;
+ fprintf(stderr, "%f", (double) si / 256.0);
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 d17a456..11d085b 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(fabs(data->value.d - d) <= 1.0 / 256.0);
+}
+
+static void
demarshal(struct marshal_data *data, const char *format,
uint32_t *msg, void (*func)(void))
{
@@ -335,6 +344,24 @@ 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] = (int32_t) trunc(data.value.d * 256.0);
+ demarshal(&data, "f", msg, (void *) validate_demarshal_d);
+
+ data.value.d = -90000.2390;
+ msg[0] = 400200;
+ msg[1] = 12;
+ msg[2] = (int32_t) trunc(data.value.d * 256.0);
+ demarshal(&data, "f", msg, (void *) validate_demarshal_d);
+
+ data.value.d = (1 << 23) - 1 + 0.0941;
+ msg[0] = 400200;
+ msg[1] = 12;
+ msg[2] = (int32_t) trunc(data.value.d * 256.0);
+ demarshal(&data, "f", msg, (void *) validate_demarshal_d);
+
release_marshal_data(&data);
}
@@ -405,6 +432,22 @@ TEST(connection_marshal_demarshal)
marshal_demarshal(0, &data, (void *) validate_demarshal_h,
8, "h", data.value.h);
+ data.value.d = 1234.5678;
+ marshal_demarshal(0, &data, (void *) validate_demarshal_d,
+ 12, "f", data.value.d);
+
+ data.value.d = -90000.2390;
+ marshal_demarshal(0, &data, (void *) validate_demarshal_d,
+ 12, "f", data.value.d);
+
+ data.value.d = (1 << 23) - 1 + 0.0941;
+ marshal_demarshal(0, &data, (void *) validate_demarshal_d,
+ 12, "f", data.value.d);
+
+ data.value.d = (1 << 23);
+ marshal_demarshal(1, &data, (void *) validate_demarshal_d,
+ 12, "f", data.value.d);
+
release_marshal_data(&data);
}
--
1.7.10
More information about the wayland-devel
mailing list