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.
14 * (this + boundary - 1)
18 #define ALIGN_VALUE(this, boundary) \
19 (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1)))
21 #define ALIGN_ADDRESS(this, boundary) \
22 ((gpointer)ALIGN_VALUE(this, boundary))
24 #define PTR_PLUS(ptr, offset) \
25 ((gpointer) (((guchar *)(ptr)) + (offset)))
27 #define DBIND_POD_CASES \
29 case DBUS_TYPE_INT16: \
30 case DBUS_TYPE_UINT16: \
31 case DBUS_TYPE_INT32: \
32 case DBUS_TYPE_UINT32: \
33 case DBUS_TYPE_BOOLEAN: \
34 case DBUS_TYPE_INT64: \
35 case DBUS_TYPE_UINT64: \
38 /*---------------------------------------------------------------------------*/
43 fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
44 " an explicit type member of 'struct'\n");
47 /*---------------------------------------------------------------------------*/
50 dbind_find_c_alignment_r (char **type)
52 unsigned int retval = 1;
58 fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
63 return DBIND_ALIGNOF_CHAR;
64 case DBUS_TYPE_BOOLEAN:
65 return DBIND_ALIGNOF_DBUS_BOOL_T;
67 case DBUS_TYPE_UINT16:
68 return DBIND_ALIGNOF_DBUS_INT16_T;
70 case DBUS_TYPE_UINT32:
71 return DBIND_ALIGNOF_DBUS_INT32_T;
73 case DBUS_TYPE_UINT64:
74 return DBIND_ALIGNOF_DBUS_INT64_T;
75 case DBUS_TYPE_DOUBLE:
76 return DBIND_ALIGNOF_DOUBLE;
78 case DBUS_TYPE_STRING:
79 case DBUS_TYPE_OBJECT_PATH:
80 case DBUS_TYPE_SIGNATURE:
82 return DBIND_ALIGNOF_DBIND_POINTER;
83 case DBUS_STRUCT_BEGIN_CHAR:
84 #if DBIND_ALIGNOF_DBIND_STRUCT > 1
85 retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
87 while (**type != DBUS_STRUCT_END_CHAR) {
88 int elem_align = dbind_find_c_alignment_r (type);
89 retval = MAX (retval, elem_align);
93 case DBUS_TYPE_STRUCT:
94 case DBUS_TYPE_DICT_ENTRY:
96 return DBIND_ALIGNOF_DBIND_POINTER;
98 g_assert_not_reached();
105 /*---------------------------------------------------------------------------*/
107 /* gather immediate allocation information for this type */
109 dbind_gather_alloc_info_r (char **type)
113 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)
187 fprintf (stderr, "any free '%c' to %p\n", **type, *data);
191 case DBIND_POD_CASES:
192 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
195 case DBUS_TYPE_STRING:
196 case DBUS_TYPE_OBJECT_PATH:
197 case DBUS_TYPE_SIGNATURE:
199 fprintf (stderr, "string free %p\n", **(void ***)data);
201 g_free (**(void ***)data);
202 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
205 case DBUS_TYPE_ARRAY: {
207 GArray *vals = **(void ***)data;
208 size_t elem_size, elem_align;
209 char *saved_child_type;
212 saved_child_type = *type;
214 elem_size = dbind_gather_alloc_info (*type);
215 elem_align = dbind_find_c_alignment_r (type);
217 for (i = 0; i < vals->len; i++) {
218 void *ptr = vals->data + elem_size * i;
219 *type = saved_child_type; /* rewind type info */
220 ptr = ALIGN_ADDRESS (ptr, elem_align);
221 dbind_any_free_r (type, &ptr);
223 g_array_free (vals, TRUE);
226 case DBUS_STRUCT_BEGIN_CHAR: {
227 gconstpointer data0 = *data;
228 int offset = 0, stralign;
230 stralign = dbind_find_c_alignment (*type);
234 while (**type != DBUS_STRUCT_END_CHAR) {
236 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
237 *data = PTR_PLUS (data0, offset);
238 dbind_any_free_r (type, data);
239 offset += dbind_gather_alloc_info (subt);
242 offset = ALIGN_VALUE (offset, stralign);
243 *data = PTR_PLUS (data0, offset);
245 g_assert (**type == DBUS_STRUCT_END_CHAR);
250 case DBUS_TYPE_STRUCT:
251 case DBUS_TYPE_DICT_ENTRY:
257 /*---------------------------------------------------------------------------*/
260 dbind_any_marshal (DBusMessageIter *iter,
267 fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
271 case DBIND_POD_CASES:
272 case DBUS_TYPE_STRING:
273 case DBUS_TYPE_OBJECT_PATH:
274 case DBUS_TYPE_SIGNATURE:
275 len = dbind_gather_alloc_info (*type);
276 dbus_message_iter_append_basic (iter, **type, *data);
277 *data = ((guchar *)*data) + len;
280 case DBUS_TYPE_ARRAY: {
282 GArray *vals = **(void ***)data;
283 size_t elem_size, elem_align;
285 char *saved_child_type, *child_type_string;
288 saved_child_type = *type;
290 elem_size = dbind_gather_alloc_info (*type);
291 elem_align = dbind_find_c_alignment_r (type);
293 /* wow this part of the API sucks too ... */
294 child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
295 /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
296 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
297 child_type_string, &sub);
298 for (i = 0; i < vals->len; i++) {
299 void *ptr = vals->data + elem_size * i;
300 *type = saved_child_type; /* rewind type info */
301 ptr = ALIGN_ADDRESS (ptr, elem_align);
302 dbind_any_marshal (&sub, type, &ptr);
305 dbus_message_iter_close_container (iter, &sub);
306 g_free (child_type_string);
309 case DBUS_STRUCT_BEGIN_CHAR: {
310 gconstpointer data0 = *data;
311 int offset = 0, stralign;
314 stralign = dbind_find_c_alignment (*type);
318 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
321 while (**type != DBUS_STRUCT_END_CHAR) {
323 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
324 *data = PTR_PLUS (data0, offset);
325 dbind_any_marshal (&sub, type, data);
326 offset += dbind_gather_alloc_info (subt);
329 offset = ALIGN_VALUE (offset, stralign);
330 *data = PTR_PLUS (data0, offset);
332 dbus_message_iter_close_container (iter, &sub);
334 g_assert (**type == DBUS_STRUCT_END_CHAR);
339 case DBUS_TYPE_STRUCT:
340 case DBUS_TYPE_DICT_ENTRY:
346 /*---------------------------------------------------------------------------*/
349 dbind_any_marshal_va (DBusMessageIter *iter,
353 char *p = *arg_types;
355 /* Guard against null arg types
356 Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027
362 /* special case base-types since we need to walk the stack worse-luck */
363 for (;*p != '\0' && *p != '=';) {
367 dbus_int64_t int64arg;
372 case DBUS_TYPE_BOOLEAN:
373 case DBUS_TYPE_INT16:
374 case DBUS_TYPE_UINT16:
375 case DBUS_TYPE_INT32:
376 case DBUS_TYPE_UINT32:
377 intarg = va_arg (args, int);
380 case DBUS_TYPE_INT64:
381 case DBUS_TYPE_UINT64:
382 int64arg = va_arg (args, dbus_int64_t);
385 case DBUS_TYPE_DOUBLE:
386 doublearg = va_arg (args, double);
390 case DBUS_TYPE_STRING:
391 case DBUS_TYPE_OBJECT_PATH:
392 case DBUS_TYPE_SIGNATURE:
393 case DBUS_TYPE_ARRAY:
394 case DBUS_TYPE_DICT_ENTRY:
395 ptrarg = va_arg (args, void *);
398 case DBUS_STRUCT_BEGIN_CHAR:
399 ptrarg = va_arg (args, void *);
403 case DBUS_TYPE_VARIANT:
404 fprintf (stderr, "No variant support yet - very toolkit specific\n");
405 ptrarg = va_arg (args, void *);
409 fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
413 dbind_any_marshal (iter, &p, &arg);
418 /*---------------------------------------------------------------------------*/
421 dbind_any_demarshal (DBusMessageIter *iter,
428 fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
432 case DBIND_POD_CASES:
433 len = dbind_gather_alloc_info (*type);
434 dbus_message_iter_get_basic (iter, *data);
435 *data = ((guchar *)*data) + len;
438 case DBUS_TYPE_STRING:
439 case DBUS_TYPE_OBJECT_PATH:
440 case DBUS_TYPE_SIGNATURE:
441 len = dbind_gather_alloc_info (*type);
442 dbus_message_iter_get_basic (iter, *data);
444 fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data);
446 **(void ***)data = g_strdup (**(void ***)data);
447 *data = ((guchar *)*data) + len;
450 case DBUS_TYPE_ARRAY: {
452 DBusMessageIter child;
453 size_t elem_size, elem_align;
454 char *stored_child_type;
458 stored_child_type = *type;
460 elem_size = dbind_gather_alloc_info (*type);
461 elem_align = dbind_find_c_alignment_r (type);
462 vals = g_array_new (FALSE, FALSE, elem_size);
463 (**(void ***)data) = vals;
464 *data = ((guchar *)*data) + sizeof (void *);
467 dbus_message_iter_recurse (iter, &child);
468 while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
470 char *subt = stored_child_type;
471 g_array_set_size (vals, i + 1);
472 ptr = vals->data + elem_size * i;
473 ptr = ALIGN_ADDRESS (ptr, elem_align);
474 dbind_any_demarshal (&child, &subt, &ptr);
479 case DBUS_STRUCT_BEGIN_CHAR: {
480 gconstpointer data0 = *data;
481 int offset = 0, stralign;
482 DBusMessageIter child;
484 stralign = dbind_find_c_alignment (*type);
488 dbus_message_iter_recurse (iter, &child);
490 while (**type != DBUS_STRUCT_END_CHAR) {
492 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
493 *data = PTR_PLUS (data0, offset);
494 dbind_any_demarshal (&child, type, data);
495 offset += dbind_gather_alloc_info (subt);
498 offset = ALIGN_VALUE (offset, stralign);
499 *data = PTR_PLUS (data0, offset);
501 g_assert (**type == DBUS_STRUCT_END_CHAR);
506 case DBUS_TYPE_STRUCT:
507 case DBUS_TYPE_DICT_ENTRY:
511 dbus_message_iter_next (iter);
514 /*---------------------------------------------------------------------------*/
517 dbind_any_demarshal_va (DBusMessageIter *iter,
521 char *p = *arg_types;
523 void *arg = va_arg (args, void *);
524 dbind_any_demarshal (iter, &p, &arg);
528 /*---------------------------------------------------------------------------*/
530 /* nice deep free ... */
532 dbind_any_free (char *type,
535 dbind_any_free_r (&type, &ptr);
538 /* should this be the default normalization ? */
540 dbind_any_free_ptr (char *type, void *ptr)
542 dbind_any_free (type, &ptr);
545 /*---------------------------------------------------------------------------*/
548 dbind_find_c_alignment (char *type)
550 return dbind_find_c_alignment_r (&type);
553 /*END------------------------------------------------------------------------*/