1 /* type driven marshalling */
6 #include "dbind-config.h"
11 /* Align a value upward to a boundary, expressed as a number of bytes.
12 E.g. align to an 8-byte boundary with argument of 8. */
15 * (this + boundary - 1)
20 #define ALIGN_VALUE(this, boundary) \
21 (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1)))
23 #define ALIGN_ADDRESS(this, boundary) \
24 ((gpointer)ALIGN_VALUE(this, boundary))
26 #define PTR_PLUS(ptr, offset) \
27 ((gpointer) (((guchar *)(ptr)) + (offset)))
29 #define DBIND_POD_CASES \
31 case DBUS_TYPE_INT16: \
32 case DBUS_TYPE_UINT16: \
33 case DBUS_TYPE_INT32: \
34 case DBUS_TYPE_UINT32: \
35 case DBUS_TYPE_BOOLEAN: \
36 case DBUS_TYPE_INT64: \
37 case DBUS_TYPE_UINT64: \
40 /*---------------------------------------------------------------------------*/
45 fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
46 " an explicit type member of 'struct'\n");
49 /*---------------------------------------------------------------------------*/
52 dbind_find_c_alignment_r (char **type)
54 unsigned int retval = 1;
60 fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
65 return DBIND_ALIGNOF_CHAR;
66 case DBUS_TYPE_BOOLEAN:
67 return DBIND_ALIGNOF_DBUS_BOOL_T;
69 case DBUS_TYPE_UINT16:
70 return DBIND_ALIGNOF_DBUS_INT16_T;
72 case DBUS_TYPE_UINT32:
73 return DBIND_ALIGNOF_DBUS_INT32_T;
75 case DBUS_TYPE_UINT64:
76 return DBIND_ALIGNOF_DBUS_INT64_T;
77 case DBUS_TYPE_DOUBLE:
78 return DBIND_ALIGNOF_DOUBLE;
80 case DBUS_TYPE_STRING:
81 case DBUS_TYPE_OBJECT_PATH:
82 case DBUS_TYPE_SIGNATURE:
84 return DBIND_ALIGNOF_DBIND_POINTER;
85 case DBUS_STRUCT_BEGIN_CHAR:
86 #if DBIND_ALIGNOF_DBIND_STRUCT > 1
87 retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
89 while (**type != DBUS_STRUCT_END_CHAR) {
90 int elem_align = dbind_find_c_alignment_r (type);
91 retval = MAX (retval, elem_align);
95 case DBUS_TYPE_STRUCT:
96 case DBUS_TYPE_DICT_ENTRY:
98 return DBIND_ALIGNOF_DBIND_POINTER;
100 g_assert_not_reached();
107 /*---------------------------------------------------------------------------*/
109 /* gather immediate allocation information for this type */
111 dbind_gather_alloc_info_r (char **type)
115 if (t == DBUS_TYPE_ARRAY) {
117 case DBUS_STRUCT_BEGIN_CHAR:
118 while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
119 if (**type != '\0') (*type)++;
131 return sizeof (char);
132 case DBUS_TYPE_BOOLEAN:
133 return sizeof (dbus_bool_t);
134 case DBUS_TYPE_INT16:
135 case DBUS_TYPE_UINT16:
136 return sizeof (dbus_int16_t);
137 case DBUS_TYPE_INT32:
138 case DBUS_TYPE_UINT32:
139 return sizeof (dbus_int32_t);
140 case DBUS_TYPE_INT64:
141 case DBUS_TYPE_UINT64:
142 return sizeof (dbus_int64_t);
143 case DBUS_TYPE_DOUBLE:
144 return sizeof (double);
146 case DBUS_TYPE_STRING:
147 case DBUS_TYPE_OBJECT_PATH:
148 case DBUS_TYPE_SIGNATURE:
149 case DBUS_TYPE_ARRAY:
150 return sizeof (void *);
151 case DBUS_STRUCT_BEGIN_CHAR: {
152 int sum = 0, stralign;
154 stralign = dbind_find_c_alignment (*type - 1);
156 while (**type != DBUS_STRUCT_END_CHAR) {
157 sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
158 sum += dbind_gather_alloc_info_r (type);
160 sum = ALIGN_VALUE (sum, stralign);
162 g_assert (**type == DBUS_STRUCT_END_CHAR);
167 case DBUS_TYPE_STRUCT:
168 case DBUS_TYPE_DICT_ENTRY:
176 dbind_gather_alloc_info (char *type)
178 return dbind_gather_alloc_info_r (&type);
181 /*---------------------------------------------------------------------------*/
184 dbind_any_free_r (char **type, void **data)
189 fprintf (stderr, "any free '%c' to %p\n", **type, *data);
193 case DBIND_POD_CASES:
194 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
197 case DBUS_TYPE_STRING:
198 case DBUS_TYPE_OBJECT_PATH:
199 case DBUS_TYPE_SIGNATURE:
201 fprintf (stderr, "string free %p\n", **(void ***)data);
203 g_free (**(void ***)data);
204 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
207 case DBUS_TYPE_ARRAY: {
209 GArray *vals = **(void ***)data;
210 size_t elem_size, elem_align;
211 char *saved_child_type, *child_type_string;
214 saved_child_type = *type;
216 elem_size = dbind_gather_alloc_info (*type);
217 elem_align = dbind_find_c_alignment_r (type);
219 for (i = 0; i < vals->len; i++) {
220 void *ptr = vals->data + elem_size * i;
221 *type = saved_child_type; /* rewind type info */
222 ptr = ALIGN_ADDRESS (ptr, elem_align);
223 dbind_any_free_r (type, &ptr);
225 g_array_free (vals, TRUE);
228 case DBUS_STRUCT_BEGIN_CHAR: {
229 gconstpointer data0 = *data;
230 int offset = 0, stralign;
232 stralign = dbind_find_c_alignment (*type);
236 while (**type != DBUS_STRUCT_END_CHAR) {
238 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
239 *data = PTR_PLUS (data0, offset);
240 dbind_any_free_r (type, data);
241 offset += dbind_gather_alloc_info (subt);
244 offset = ALIGN_VALUE (offset, stralign);
245 *data = PTR_PLUS (data0, offset);
247 g_assert (**type == DBUS_STRUCT_END_CHAR);
252 case DBUS_TYPE_STRUCT:
253 case DBUS_TYPE_DICT_ENTRY:
259 /*---------------------------------------------------------------------------*/
262 dbind_any_marshal (DBusMessageIter *iter,
269 fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
273 case DBIND_POD_CASES:
274 case DBUS_TYPE_STRING:
275 case DBUS_TYPE_OBJECT_PATH:
276 case DBUS_TYPE_SIGNATURE:
277 len = dbind_gather_alloc_info (*type);
278 dbus_message_iter_append_basic (iter, **type, *data);
279 *data = ((guchar *)*data) + len;
282 case DBUS_TYPE_ARRAY: {
284 GArray *vals = **(void ***)data;
285 size_t elem_size, elem_align;
287 char *saved_child_type, *child_type_string;
290 saved_child_type = *type;
292 elem_size = dbind_gather_alloc_info (*type);
293 elem_align = dbind_find_c_alignment_r (type);
295 /* wow this part of the API sucks too ... */
296 child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
297 /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
298 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
299 child_type_string, &sub);
300 for (i = 0; i < vals->len; i++) {
301 void *ptr = vals->data + elem_size * i;
302 *type = saved_child_type; /* rewind type info */
303 ptr = ALIGN_ADDRESS (ptr, elem_align);
304 dbind_any_marshal (&sub, type, &ptr);
307 dbus_message_iter_close_container (iter, &sub);
308 g_free (child_type_string);
311 case DBUS_STRUCT_BEGIN_CHAR: {
312 gconstpointer data0 = *data;
313 int offset = 0, stralign;
316 stralign = dbind_find_c_alignment (*type);
320 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
323 while (**type != DBUS_STRUCT_END_CHAR) {
325 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
326 *data = PTR_PLUS (data0, offset);
327 dbind_any_marshal (&sub, type, data);
328 offset += dbind_gather_alloc_info (subt);
331 offset = ALIGN_VALUE (offset, stralign);
332 *data = PTR_PLUS (data0, offset);
334 dbus_message_iter_close_container (iter, &sub);
336 g_assert (**type == DBUS_STRUCT_END_CHAR);
341 case DBUS_TYPE_STRUCT:
342 case DBUS_TYPE_DICT_ENTRY:
348 /*---------------------------------------------------------------------------*/
351 dbind_any_marshal_va (DBusMessageIter *iter,
355 char *p = *arg_types;
357 /* special case base-types since we need to walk the stack worse-luck */
358 for (;*p != '\0' && *p != '=';) {
362 dbus_int64_t int64arg;
367 case DBUS_TYPE_BOOLEAN:
368 case DBUS_TYPE_INT16:
369 case DBUS_TYPE_UINT16:
370 case DBUS_TYPE_INT32:
371 case DBUS_TYPE_UINT32:
372 intarg = va_arg (args, int);
375 case DBUS_TYPE_INT64:
376 case DBUS_TYPE_UINT64:
377 int64arg = va_arg (args, dbus_int64_t);
380 case DBUS_TYPE_DOUBLE:
381 doublearg = va_arg (args, double);
385 case DBUS_TYPE_STRING:
386 case DBUS_TYPE_OBJECT_PATH:
387 case DBUS_TYPE_SIGNATURE:
388 case DBUS_TYPE_ARRAY:
389 case DBUS_TYPE_DICT_ENTRY:
390 ptrarg = va_arg (args, void *);
393 case DBUS_STRUCT_BEGIN_CHAR:
394 ptrarg = va_arg (args, void *);
398 case DBUS_TYPE_VARIANT:
399 fprintf (stderr, "No variant support yet - very toolkit specific\n");
400 ptrarg = va_arg (args, void *);
404 fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
408 dbind_any_marshal (iter, &p, &arg);
413 /*---------------------------------------------------------------------------*/
416 dbind_any_demarshal (DBusMessageIter *iter,
423 fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
427 case DBIND_POD_CASES:
428 len = dbind_gather_alloc_info (*type);
429 dbus_message_iter_get_basic (iter, *data);
430 *data = ((guchar *)*data) + len;
433 case DBUS_TYPE_STRING:
434 case DBUS_TYPE_OBJECT_PATH:
435 case DBUS_TYPE_SIGNATURE:
436 len = dbind_gather_alloc_info (*type);
437 dbus_message_iter_get_basic (iter, *data);
439 fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data);
441 **(void ***)data = g_strdup (**(void ***)data);
442 *data = ((guchar *)*data) + len;
445 case DBUS_TYPE_ARRAY: {
447 DBusMessageIter child;
448 size_t elem_size, elem_align;
449 char *stored_child_type;
453 stored_child_type = *type;
455 elem_size = dbind_gather_alloc_info (*type);
456 elem_align = dbind_find_c_alignment_r (type);
457 vals = g_array_new (FALSE, FALSE, elem_size);
458 (**(void ***)data) = vals;
459 *data = ((guchar *)*data) + sizeof (void *);
462 dbus_message_iter_recurse (iter, &child);
463 while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
465 char *subt = stored_child_type;
466 g_array_set_size (vals, i + 1);
467 ptr = vals->data + elem_size * i;
468 ptr = ALIGN_ADDRESS (ptr, elem_align);
469 dbind_any_demarshal (&child, &subt, &ptr);
474 case DBUS_STRUCT_BEGIN_CHAR: {
475 gconstpointer data0 = *data;
476 int offset = 0, stralign;
477 DBusMessageIter child;
479 stralign = dbind_find_c_alignment (*type);
483 dbus_message_iter_recurse (iter, &child);
485 while (**type != DBUS_STRUCT_END_CHAR) {
487 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
488 *data = PTR_PLUS (data0, offset);
489 dbind_any_demarshal (&child, type, data);
490 offset += dbind_gather_alloc_info (subt);
493 offset = ALIGN_VALUE (offset, stralign);
494 *data = PTR_PLUS (data0, offset);
496 g_assert (**type == DBUS_STRUCT_END_CHAR);
501 case DBUS_TYPE_STRUCT:
502 case DBUS_TYPE_DICT_ENTRY:
506 dbus_message_iter_next (iter);
509 /*---------------------------------------------------------------------------*/
512 dbind_any_demarshal_va (DBusMessageIter *iter,
516 char *p = *arg_types;
518 void *arg = va_arg (args, void *);
519 dbind_any_demarshal (iter, &p, &arg);
523 /*---------------------------------------------------------------------------*/
525 /* nice deep free ... */
527 dbind_any_free (char *type,
530 dbind_any_free_r (&type, &ptr);
533 /* should this be the default normalization ? */
535 dbind_any_free_ptr (char *type, void *ptr)
537 dbind_any_free (type, &ptr);
540 /*---------------------------------------------------------------------------*/
543 dbind_find_c_alignment (char *type)
545 return dbind_find_c_alignment_r (&type);
548 /*END------------------------------------------------------------------------*/