1 /* type driven marshalling */
3 #include "dbind-config.h"
4 #define DBUS_API_SUBJECT_TO_CHANGE
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 unsigned int dbind_find_c_alignment_r (char **type);
30 unsigned int dbind_find_c_alignment (char *type);
35 fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
36 " an explicit type member of 'struct'\n");
39 /* gather immediate allocation information for this type */
40 size_t dbind_gather_alloc_info_r (char **type)
44 if (t == DBUS_TYPE_ARRAY) {
46 case DBUS_STRUCT_BEGIN_CHAR:
47 while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++;
48 if (**type != '\0') (*type)++;
61 case DBUS_TYPE_BOOLEAN:
62 return sizeof (dbus_bool_t);
64 case DBUS_TYPE_UINT16:
65 return sizeof (dbus_int16_t);
67 case DBUS_TYPE_UINT32:
68 return sizeof (dbus_int32_t);
70 case DBUS_TYPE_UINT64:
71 return sizeof (dbus_int64_t);
72 case DBUS_TYPE_DOUBLE:
73 return sizeof (double);
75 case DBUS_TYPE_STRING:
76 case DBUS_TYPE_OBJECT_PATH:
77 case DBUS_TYPE_SIGNATURE:
79 return sizeof (void *);
80 case DBUS_STRUCT_BEGIN_CHAR: {
81 int sum = 0, stralign;
83 stralign = dbind_find_c_alignment (*type - 1);
85 while (**type != DBUS_STRUCT_END_CHAR) {
86 sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
87 sum += dbind_gather_alloc_info_r (type);
89 sum = ALIGN_VALUE (sum, stralign);
91 g_assert (**type == DBUS_STRUCT_END_CHAR);
96 case DBUS_TYPE_STRUCT:
97 case DBUS_TYPE_DICT_ENTRY:
104 size_t dbind_gather_alloc_info (char *type)
106 return dbind_gather_alloc_info_r (&type);
110 dbind_find_c_alignment_r (char **type)
112 unsigned int retval = 1;
118 fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
123 return DBIND_ALIGNOF_CHAR;
124 case DBUS_TYPE_BOOLEAN:
125 return DBIND_ALIGNOF_DBUS_BOOL_T;
126 case DBUS_TYPE_INT16:
127 case DBUS_TYPE_UINT16:
128 return DBIND_ALIGNOF_DBUS_INT16_T;
129 case DBUS_TYPE_INT32:
130 case DBUS_TYPE_UINT32:
131 return DBIND_ALIGNOF_DBUS_INT32_T;
132 case DBUS_TYPE_INT64:
133 case DBUS_TYPE_UINT64:
134 return DBIND_ALIGNOF_DBUS_INT64_T;
135 case DBUS_TYPE_DOUBLE:
136 return DBIND_ALIGNOF_DOUBLE;
138 case DBUS_TYPE_STRING:
139 case DBUS_TYPE_OBJECT_PATH:
140 case DBUS_TYPE_SIGNATURE:
141 case DBUS_TYPE_ARRAY:
142 return DBIND_ALIGNOF_DBIND_POINTER;
143 case DBUS_STRUCT_BEGIN_CHAR:
144 #if DBIND_ALIGNOF_DBIND_STRUCT > 1
145 retval = MAX (retval, DBIND_ALIGNOF_DBIND_STRUCT);
147 while (**type != DBUS_STRUCT_END_CHAR) {
148 int elem_align = dbind_find_c_alignment_r (type);
149 retval = MAX (retval, elem_align);
153 case DBUS_TYPE_STRUCT:
154 case DBUS_TYPE_DICT_ENTRY:
156 return DBIND_ALIGNOF_DBIND_POINTER;
158 g_assert_not_reached();
166 dbind_find_c_alignment (char *type)
168 return dbind_find_c_alignment_r (&type);
171 #define DBIND_POD_CASES \
173 case DBUS_TYPE_INT16: \
174 case DBUS_TYPE_UINT16: \
175 case DBUS_TYPE_INT32: \
176 case DBUS_TYPE_UINT32: \
177 case DBUS_TYPE_BOOLEAN: \
178 case DBUS_TYPE_INT64: \
179 case DBUS_TYPE_UINT64: \
180 case DBUS_TYPE_DOUBLE
183 dbind_any_marshal (DBusMessageIter *iter,
190 fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
194 case DBIND_POD_CASES:
195 case DBUS_TYPE_STRING:
196 case DBUS_TYPE_OBJECT_PATH:
197 case DBUS_TYPE_SIGNATURE:
198 len = dbind_gather_alloc_info (*type);
199 dbus_message_iter_append_basic (iter, **type, *data);
200 *data = ((guchar *)*data) + len;
203 case DBUS_TYPE_ARRAY: {
205 GArray *vals = **(void ***)data;
206 size_t elem_size, elem_align;
208 char *saved_child_type, *child_type_string;
211 saved_child_type = *type;
213 elem_size = dbind_gather_alloc_info (*type);
214 elem_align = dbind_find_c_alignment_r (type);
216 /* wow this part of the API sucks too ... */
217 child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
218 /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
219 dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
220 child_type_string, &sub);
221 for (i = 0; i < vals->len; i++) {
222 void *ptr = vals->data + elem_size * i;
223 *type = saved_child_type; /* rewind type info */
224 ptr = ALIGN_ADDRESS (ptr, elem_align);
225 dbind_any_marshal (&sub, type, &ptr);
228 dbus_message_iter_close_container (iter, &sub);
229 g_free (child_type_string);
232 case DBUS_STRUCT_BEGIN_CHAR: {
233 gconstpointer data0 = *data;
234 int offset = 0, stralign;
237 stralign = dbind_find_c_alignment (*type);
241 dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
244 while (**type != DBUS_STRUCT_END_CHAR) {
246 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
247 *data = PTR_PLUS (data0, offset);
248 dbind_any_marshal (&sub, type, data);
249 offset += dbind_gather_alloc_info (subt);
252 offset = ALIGN_VALUE (offset, stralign);
253 *data = PTR_PLUS (data0, offset);
255 dbus_message_iter_close_container (iter, &sub);
257 g_assert (**type == DBUS_STRUCT_END_CHAR);
262 case DBUS_TYPE_STRUCT:
263 case DBUS_TYPE_DICT_ENTRY:
270 dbind_any_demarshal (DBusMessageIter *iter,
277 fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
281 case DBIND_POD_CASES:
282 len = dbind_gather_alloc_info (*type);
283 dbus_message_iter_get_basic (iter, *data);
284 *data = ((guchar *)*data) + len;
287 case DBUS_TYPE_STRING:
288 case DBUS_TYPE_OBJECT_PATH:
289 case DBUS_TYPE_SIGNATURE:
290 len = dbind_gather_alloc_info (*type);
291 dbus_message_iter_get_basic (iter, *data);
293 fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data);
295 **(void ***)data = g_strdup (**(void ***)data);
296 *data = ((guchar *)*data) + len;
299 case DBUS_TYPE_ARRAY: {
301 DBusMessageIter child;
302 size_t elem_size, elem_align;
303 char *stored_child_type;
307 stored_child_type = *type;
309 elem_size = dbind_gather_alloc_info (*type);
310 elem_align = dbind_find_c_alignment_r (type);
311 vals = g_array_new (FALSE, FALSE, elem_size);
312 (**(void ***)data) = vals;
313 *data = ((guchar *)*data) + sizeof (void *);
316 dbus_message_iter_recurse (iter, &child);
317 while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) {
319 char *subt = stored_child_type;
320 g_array_set_size (vals, i + 1);
321 ptr = vals->data + elem_size * i;
322 ptr = ALIGN_ADDRESS (ptr, elem_align);
323 dbind_any_demarshal (&child, &subt, &ptr);
328 case DBUS_STRUCT_BEGIN_CHAR: {
329 gconstpointer data0 = *data;
330 int offset = 0, stralign;
331 DBusMessageIter child;
333 stralign = dbind_find_c_alignment (*type);
337 dbus_message_iter_recurse (iter, &child);
339 while (**type != DBUS_STRUCT_END_CHAR) {
341 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
342 *data = PTR_PLUS (data0, offset);
343 dbind_any_demarshal (&child, type, data);
344 offset += dbind_gather_alloc_info (subt);
347 offset = ALIGN_VALUE (offset, stralign);
348 *data = PTR_PLUS (data0, offset);
350 g_assert (**type == DBUS_STRUCT_END_CHAR);
355 case DBUS_TYPE_STRUCT:
356 case DBUS_TYPE_DICT_ENTRY:
360 dbus_message_iter_next (iter);
364 dbind_any_free_r (char **type, void **data)
369 fprintf (stderr, "any free '%c' to %p\n", **type, *data);
373 case DBIND_POD_CASES:
374 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
377 case DBUS_TYPE_STRING:
378 case DBUS_TYPE_OBJECT_PATH:
379 case DBUS_TYPE_SIGNATURE:
381 fprintf (stderr, "string free %p\n", **(void ***)data);
383 g_free (**(void ***)data);
384 *data = ((guchar *)*data) + dbind_gather_alloc_info (*type);
387 case DBUS_TYPE_ARRAY: {
389 GArray *vals = **(void ***)data;
390 size_t elem_size, elem_align;
391 char *saved_child_type, *child_type_string;
394 saved_child_type = *type;
396 elem_size = dbind_gather_alloc_info (*type);
397 elem_align = dbind_find_c_alignment_r (type);
399 for (i = 0; i < vals->len; i++) {
400 void *ptr = vals->data + elem_size * i;
401 *type = saved_child_type; /* rewind type info */
402 ptr = ALIGN_ADDRESS (ptr, elem_align);
403 dbind_any_free_r (type, &ptr);
405 g_array_free (vals, TRUE);
408 case DBUS_STRUCT_BEGIN_CHAR: {
409 gconstpointer data0 = *data;
410 int offset = 0, stralign;
412 stralign = dbind_find_c_alignment (*type);
416 while (**type != DBUS_STRUCT_END_CHAR) {
418 offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
419 *data = PTR_PLUS (data0, offset);
420 dbind_any_free_r (type, data);
421 offset += dbind_gather_alloc_info (subt);
424 offset = ALIGN_VALUE (offset, stralign);
425 *data = PTR_PLUS (data0, offset);
427 g_assert (**type == DBUS_STRUCT_END_CHAR);
432 case DBUS_TYPE_STRUCT:
433 case DBUS_TYPE_DICT_ENTRY:
439 /* nice deep free ... */
441 dbind_any_free (char *type,
444 dbind_any_free_r (&type, &ptr);
447 /* should this be the default normalization ? */
449 dbind_any_free_ptr (char *type, void *ptr)
451 dbind_any_free (type, &ptr);