Add support for signed 24.8 decimal numbers

'fixed' is a signed decimal type which offers a sign bit, 23 bits of
integer precision, and 8 bits of decimal precision.  This is exposed as
an opaque struct with conversion helpers to and from double and int on
the C API side.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
This commit is contained in:
Daniel Stone 2012-05-08 17:17:25 +01:00 committed by Kristian Høgsberg
parent c49f632dae
commit c5aba11acc
6 changed files with 81 additions and 3 deletions

View file

@ -18,7 +18,7 @@ libwayland_util_la_SOURCES = \
wayland-os.h \ wayland-os.h \
wayland-private.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 = \ libwayland_server_la_SOURCES = \
wayland-protocol.c \ wayland-protocol.c \
wayland-server.c \ wayland-server.c \
@ -26,7 +26,7 @@ libwayland_server_la_SOURCES = \
data-device.c \ data-device.c \
event-loop.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 = \ libwayland_client_la_SOURCES = \
wayland-protocol.c \ wayland-protocol.c \
wayland-client.c wayland-client.c

View file

@ -22,6 +22,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -428,6 +429,13 @@ wl_closure_vmarshal(struct wl_closure *closure,
for (i = 2; i < count; i++) { for (i = 2; i < count; i++) {
switch (message->signature[i - 2]) { switch (message->signature[i - 2]) {
case 'f':
closure->types[i] = &ffi_type_sint32;
closure->args[i] = p;
if (end - p < 1)
goto err;
*p++ = va_arg(ap, wl_fixed_t);
break;
case 'u': case 'u':
closure->types[i] = &ffi_type_uint32; closure->types[i] = &ffi_type_uint32;
closure->args[i] = p; closure->args[i] = p;
@ -611,6 +619,10 @@ wl_connection_demarshal(struct wl_connection *connection,
closure->types[i] = &ffi_type_sint32; closure->types[i] = &ffi_type_sint32;
closure->args[i] = p++; closure->args[i] = p++;
break; break;
case 'f':
closure->types[i] = &ffi_type_sint32;
closure->args[i] = p++;
break;
case 's': case 's':
closure->types[i] = &ffi_type_pointer; closure->types[i] = &ffi_type_pointer;
length = *p++; length = *p++;
@ -812,6 +824,7 @@ void
wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
{ {
union wl_value *value; union wl_value *value;
int32_t si;
int i; int i;
struct timespec tp; struct timespec tp;
unsigned int time; unsigned int time;
@ -835,7 +848,12 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
fprintf(stderr, "%u", value->uint32); fprintf(stderr, "%u", value->uint32);
break; break;
case 'i': 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);
break; break;
case 's': case 's':
fprintf(stderr, "\"%s\"", value->string); fprintf(stderr, "\"%s\"", value->string);

View file

@ -83,6 +83,7 @@ enum arg_type {
NEW_ID, NEW_ID,
INT, INT,
UNSIGNED, UNSIGNED,
FIXED,
STRING, STRING,
OBJECT, OBJECT,
ARRAY, ARRAY,
@ -334,6 +335,8 @@ start_element(void *data, const char *element_name, const char **atts)
arg->type = INT; arg->type = INT;
else if (strcmp(type, "uint") == 0) else if (strcmp(type, "uint") == 0)
arg->type = UNSIGNED; arg->type = UNSIGNED;
else if (strcmp(type, "fixed") == 0)
arg->type = FIXED;
else if (strcmp(type, "string") == 0) else if (strcmp(type, "string") == 0)
arg->type = STRING; arg->type = STRING;
else if (strcmp(type, "array") == 0) else if (strcmp(type, "array") == 0)
@ -484,6 +487,9 @@ emit_type(struct arg *a)
case UNSIGNED: case UNSIGNED:
printf("uint32_t "); printf("uint32_t ");
break; break;
case FIXED:
printf("wl_fixed_t ");
break;
case STRING: case STRING:
printf("const char *"); printf("const char *");
break; break;
@ -972,6 +978,9 @@ emit_messages(struct wl_list *message_list,
case UNSIGNED: case UNSIGNED:
printf("u"); printf("u");
break; break;
case FIXED:
printf("f");
break;
case STRING: case STRING:
printf("s"); printf("s");
break; break;

View file

@ -281,6 +281,7 @@ struct wl_input_device {
* The variable arguments' types are: * The variable arguments' types are:
* - type=uint: uint32_t * - type=uint: uint32_t
* - type=int: int32_t * - type=int: int32_t
* - type=fixed: wl_fixed_t
* - type=string: (const char *) to a nil-terminated string * - type=string: (const char *) to a nil-terminated string
* - type=array: (struct wl_array *) * - type=array: (struct wl_array *)
* - type=fd: int, that is an open file descriptor * - type=fd: int, that is an open file descriptor

View file

@ -27,6 +27,7 @@
extern "C" { extern "C" {
#endif #endif
#include <math.h>
#include <stddef.h> #include <stddef.h>
#include <inttypes.h> #include <inttypes.h>
@ -165,6 +166,29 @@ void wl_array_release(struct wl_array *array);
void *wl_array_add(struct wl_array *array, size_t size); void *wl_array_add(struct wl_array *array, size_t size);
void wl_array_copy(struct wl_array *array, struct wl_array *source); void wl_array_copy(struct wl_array *array, struct wl_array *source);
typedef int32_t wl_fixed_t;
#define WL_FIXED_INVALID_VALUE ~0L
static inline double wl_fixed_to_double(wl_fixed_t f)
{
return (double) f / 256.0;
};
static inline wl_fixed_t wl_fixed_from_double(double d)
{
if (d >= (1 << 23))
return WL_FIXED_INVALID_VALUE;
return (wl_fixed_t) round (d * 256.0);
};
static inline int wl_fixed_to_int(wl_fixed_t f)
{
return f / 256;
}
static inline wl_fixed_t wl_fixed_from_int(int i)
{
return wl_fixed_from_double(i);
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -20,6 +20,7 @@
* OF THIS SOFTWARE. * OF THIS SOFTWARE.
*/ */
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
@ -287,6 +288,13 @@ validate_demarshal_h(struct marshal_data *data,
close(data->value.h); close(data->value.h);
} }
static void
validate_demarshal_f(struct marshal_data *data,
struct wl_object *object, wl_fixed_t f)
{
assert(data->value.i == f);
}
static void static void
demarshal(struct marshal_data *data, const char *format, demarshal(struct marshal_data *data, const char *format,
uint32_t *msg, void (*func)(void)) uint32_t *msg, void (*func)(void))
@ -335,6 +343,12 @@ TEST(connection_demarshal)
memcpy(&msg[3], data.value.s, msg[2]); memcpy(&msg[3], data.value.s, msg[2]);
demarshal(&data, "s", msg, (void *) validate_demarshal_s); demarshal(&data, "s", msg, (void *) validate_demarshal_s);
data.value.i = wl_fixed_from_double(-90000.2390);
msg[0] = 400200;
msg[1] = 12;
msg[2] = data.value.i;
demarshal(&data, "f", msg, (void *) validate_demarshal_f);
release_marshal_data(&data); release_marshal_data(&data);
} }
@ -400,6 +414,18 @@ TEST(connection_marshal_demarshal)
marshal_demarshal(&data, (void *) validate_demarshal_h, marshal_demarshal(&data, (void *) validate_demarshal_h,
8, "h", data.value.h); 8, "h", data.value.h);
data.value.i = wl_fixed_from_double(1234.5678);
marshal_demarshal(&data, (void *) validate_demarshal_f,
12, "f", data.value.i);
data.value.i = wl_fixed_from_double(-90000.2390);
marshal_demarshal(&data, (void *) validate_demarshal_f,
12, "f", data.value.i);
data.value.i = wl_fixed_from_double((1 << 23) - 1 + 0.0941);
marshal_demarshal(&data, (void *) validate_demarshal_f,
12, "f", data.value.i);
release_marshal_data(&data); release_marshal_data(&data);
} }