1
/*
2
 * Copyright 2008-2011 Novell, Inc.
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2.1 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 */
19

            
20
/* type driven marshalling */
21
#include <glib.h>
22
#include <stdio.h>
23

            
24
#include "config.h"
25
#include "dbind-any.h"
26

            
27
#undef DEBUG
28

            
29
/*  Align a value upward to a boundary, expressed as a number of bytes.
30
 *  E.g. align to an 8-byte boundary with argument of 8.
31
 *
32
 *   (this + boundary - 1)
33
 *          &
34
 *    ~(boundary - 1)
35
 */
36
#define ALIGN_VALUE(this, boundary) \
37
  ((((gulong) (this)) + (((gulong) (boundary)) - 1)) & (~(((gulong) (boundary)) - 1)))
38

            
39
#define ALIGN_ADDRESS(this, boundary) \
40
  ((gpointer) ALIGN_VALUE (this, boundary))
41

            
42
#define PTR_PLUS(ptr, offset) \
43
  ((gpointer) (((guchar *) (ptr)) + (offset)))
44

            
45
#define DBIND_POD_CASES   \
46
  DBUS_TYPE_BYTE:         \
47
  case DBUS_TYPE_INT16:   \
48
  case DBUS_TYPE_UINT16:  \
49
  case DBUS_TYPE_INT32:   \
50
  case DBUS_TYPE_UINT32:  \
51
  case DBUS_TYPE_BOOLEAN: \
52
  case DBUS_TYPE_INT64:   \
53
  case DBUS_TYPE_UINT64:  \
54
  case DBUS_TYPE_DOUBLE
55

            
56
/*---------------------------------------------------------------------------*/
57

            
58
static void
59
warn_braces ()
60
{
61
  fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than "
62
                   " an explicit type member of 'struct'\n");
63
}
64

            
65
/*---------------------------------------------------------------------------*/
66

            
67
static unsigned int
68
488
dbind_find_c_alignment_r (const char **type)
69
{
70
488
  unsigned int retval = 1;
71

            
72
488
  char t = **type;
73
488
  (*type)++;
74

            
75
#ifdef DEBUG
76
  fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t);
77
#endif
78

            
79
488
  switch (t)
80
    {
81
49
    case DBUS_TYPE_BYTE:
82
49
      return ALIGNOF_CHAR;
83
    case DBUS_TYPE_BOOLEAN:
84
      return ALIGNOF_DBUS_BOOL_T;
85
    case DBUS_TYPE_INT16:
86
    case DBUS_TYPE_UINT16:
87
      return ALIGNOF_DBUS_INT16_T;
88
200
    case DBUS_TYPE_INT32:
89
    case DBUS_TYPE_UINT32:
90
200
      return ALIGNOF_DBUS_INT32_T;
91
    case DBUS_TYPE_INT64:
92
    case DBUS_TYPE_UINT64:
93
      return ALIGNOF_DBUS_INT64_T;
94
11
    case DBUS_TYPE_DOUBLE:
95
11
      return ALIGNOF_DOUBLE;
96
    /* ptr types */
97
149
    case DBUS_TYPE_STRING:
98
    case DBUS_TYPE_OBJECT_PATH:
99
    case DBUS_TYPE_SIGNATURE:
100
    case DBUS_TYPE_ARRAY:
101
149
      return ALIGNOF_DBIND_POINTER;
102
69
    case DBUS_STRUCT_BEGIN_CHAR:
103
      /* TODO: I think this would break with a nested struct */
104
#if ALIGNOF_DBIND_STRUCT > 1
105
      retval = MAX (retval, ALIGNOF_DBIND_STRUCT);
106
#endif
107
262
      while (**type != DBUS_STRUCT_END_CHAR)
108
        {
109
193
          int elem_align = dbind_find_c_alignment_r (type);
110
193
          retval = MAX (retval, elem_align);
111
        }
112
69
      (*type)++;
113
69
      return retval;
114
    case DBUS_DICT_ENTRY_BEGIN_CHAR:
115
#if ALIGNOF_DBIND_STRUCT > 1
116
      retval = MAX (retval, ALIGNOF_DBIND_STRUCT);
117
#endif
118
      while (**type != DBUS_DICT_ENTRY_END_CHAR)
119
        {
120
          int elem_align = dbind_find_c_alignment_r (type);
121
          retval = MAX (retval, elem_align);
122
        }
123
      (*type)++;
124
      return retval;
125
    case DBUS_TYPE_STRUCT:
126
    case DBUS_TYPE_DICT_ENTRY:
127
      warn_braces ();
128
      return ALIGNOF_DBIND_POINTER;
129
    case '\0':
130
      g_assert_not_reached ();
131
      break;
132
10
    default:
133
10
      return 1;
134
    }
135
}
136

            
137
/*---------------------------------------------------------------------------*/
138

            
139
/* gather immediate allocation information for this type */
140
static size_t
141
889
dbind_gather_alloc_info_r (const char **type)
142
{
143
889
  char t = **type;
144
889
  (*type)++;
145
889
  if (t == DBUS_TYPE_ARRAY)
146
    {
147
9
      switch (**type)
148
        {
149
        case DBUS_STRUCT_BEGIN_CHAR:
150
          while (**type != DBUS_STRUCT_END_CHAR && **type != '\0')
151
            (*type)++;
152
          if (**type != '\0')
153
            (*type)++;
154
          break;
155
        case DBUS_DICT_ENTRY_BEGIN_CHAR:
156
          while (**type != DBUS_DICT_ENTRY_END_CHAR && **type != '\0')
157
            (*type)++;
158
          if (**type != '\0')
159
            (*type)++;
160
          break;
161
        case '\0':
162
          break;
163
9
        default:
164
9
          (*type)++;
165
9
          break;
166
        }
167
    }
168

            
169
889
  switch (t)
170
    {
171
27
    case DBUS_TYPE_BYTE:
172
27
      return sizeof (char);
173
60
    case DBUS_TYPE_BOOLEAN:
174
60
      return sizeof (dbus_bool_t);
175
1
    case DBUS_TYPE_INT16:
176
    case DBUS_TYPE_UINT16:
177
1
      return sizeof (dbus_int16_t);
178
677
    case DBUS_TYPE_INT32:
179
    case DBUS_TYPE_UINT32:
180
677
      return sizeof (dbus_int32_t);
181
    case DBUS_TYPE_INT64:
182
    case DBUS_TYPE_UINT64:
183
      return sizeof (dbus_int64_t);
184
7
    case DBUS_TYPE_DOUBLE:
185
7
      return sizeof (double);
186
    /* ptr types */
187
101
    case DBUS_TYPE_STRING:
188
    case DBUS_TYPE_OBJECT_PATH:
189
    case DBUS_TYPE_SIGNATURE:
190
    case DBUS_TYPE_ARRAY:
191
101
      return sizeof (void *);
192
13
    case DBUS_STRUCT_BEGIN_CHAR:
193
      {
194
13
        int sum = 0, stralign;
195

            
196
13
        stralign = dbind_find_c_alignment (*type - 1);
197

            
198
44
        while (**type != DBUS_STRUCT_END_CHAR)
199
          {
200
31
            sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
201
31
            sum += dbind_gather_alloc_info_r (type);
202
          }
203
13
        sum = ALIGN_VALUE (sum, stralign);
204

            
205
13
        g_assert (**type == DBUS_STRUCT_END_CHAR);
206
13
        (*type)++;
207

            
208
13
        return sum;
209
      }
210
    case DBUS_DICT_ENTRY_BEGIN_CHAR:
211
      {
212
        int sum = 0, stralign;
213

            
214
        stralign = dbind_find_c_alignment (*type - 1);
215

            
216
        while (**type != DBUS_DICT_ENTRY_END_CHAR)
217
          {
218
            sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type));
219
            sum += dbind_gather_alloc_info_r (type);
220
          }
221
        sum = ALIGN_VALUE (sum, stralign);
222

            
223
        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
224
        (*type)++;
225

            
226
        return sum;
227
      }
228
    case DBUS_TYPE_STRUCT:
229
    case DBUS_TYPE_DICT_ENTRY:
230
      warn_braces ();
231
3
    default:
232
3
      return 0;
233
    }
234
}
235

            
236
static size_t
237
858
dbind_gather_alloc_info (const char *type)
238
{
239
858
  return dbind_gather_alloc_info_r (&type);
240
}
241

            
242
/*---------------------------------------------------------------------------*/
243

            
244
static void
245
38
dbind_any_free_r (const char **type, void **data)
246
{
247
#ifdef DEBUG
248
  fprintf (stderr, "any free '%c' to %p\n", **type, *data);
249
#endif
250

            
251
38
  switch (**type)
252
    {
253
19
    case DBIND_POD_CASES:
254
19
      *data = ((guchar *) *data) + dbind_gather_alloc_info (*type);
255
19
      (*type)++;
256
19
      break;
257
7
    case DBUS_TYPE_STRING:
258
    case DBUS_TYPE_OBJECT_PATH:
259
    case DBUS_TYPE_SIGNATURE:
260
#ifdef DEBUG
261
      fprintf (stderr, "string free %p\n", **(void ***) data);
262
#endif
263
7
      g_free (**(void ***) data);
264
7
      *data = ((guchar *) *data) + dbind_gather_alloc_info (*type);
265
7
      (*type)++;
266
7
      break;
267
5
    case DBUS_TYPE_ARRAY:
268
      {
269
        int i;
270
5
        GArray *vals = **(void ***) data;
271
        size_t elem_size, elem_align;
272
        const char *saved_child_type;
273

            
274
5
        (*type)++;
275
5
        saved_child_type = *type;
276

            
277
5
        elem_size = dbind_gather_alloc_info (*type);
278
5
        elem_align = dbind_find_c_alignment_r (type);
279

            
280
17
        for (i = 0; i < vals->len; i++)
281
          {
282
12
            void *ptr = vals->data + elem_size * i;
283
12
            *type = saved_child_type; /* rewind type info */
284
12
            ptr = ALIGN_ADDRESS (ptr, elem_align);
285
12
            dbind_any_free_r (type, &ptr);
286
          }
287
5
        g_array_free (vals, TRUE);
288
5
        break;
289
      }
290
7
    case DBUS_STRUCT_BEGIN_CHAR:
291
      {
292
7
        gconstpointer data0 = *data;
293
7
        int offset = 0, stralign;
294

            
295
7
        stralign = dbind_find_c_alignment (*type);
296
7
        (*type)++;
297

            
298
7
        offset = 0;
299
27
        while (**type != DBUS_STRUCT_END_CHAR)
300
          {
301
20
            const char *subt = *type;
302
20
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
303
20
            *data = PTR_PLUS (data0, offset);
304
20
            dbind_any_free_r (type, data);
305
20
            offset += dbind_gather_alloc_info (subt);
306
          }
307

            
308
7
        offset = ALIGN_VALUE (offset, stralign);
309
7
        *data = PTR_PLUS (data0, offset);
310

            
311
7
        g_assert (**type == DBUS_STRUCT_END_CHAR);
312
7
        (*type)++;
313

            
314
7
        break;
315
      }
316
    case DBUS_DICT_ENTRY_BEGIN_CHAR:
317
      {
318
        gconstpointer data0 = *data;
319
        int offset = 0, stralign;
320

            
321
        stralign = dbind_find_c_alignment (*type);
322
        (*type)++;
323

            
324
        offset = 0;
325
        while (**type != DBUS_DICT_ENTRY_END_CHAR)
326
          {
327
            const char *subt = *type;
328
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
329
            *data = PTR_PLUS (data0, offset);
330
            dbind_any_free_r (type, data);
331
            offset += dbind_gather_alloc_info (subt);
332
          }
333

            
334
        offset = ALIGN_VALUE (offset, stralign);
335
        *data = PTR_PLUS (data0, offset);
336

            
337
        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
338
        (*type)++;
339

            
340
        break;
341
      }
342
    case DBUS_TYPE_STRUCT:
343
    case DBUS_TYPE_DICT_ENTRY:
344
      warn_braces ();
345
      break;
346
    }
347
38
}
348

            
349
/*---------------------------------------------------------------------------*/
350

            
351
void
352
530
dbind_any_marshal (DBusMessageIter *iter,
353
                   const char **type,
354
                   void **data)
355
{
356
  size_t len;
357

            
358
#ifdef DEBUG
359
  fprintf (stderr, "any marshal '%c' to %p\n", **type, *data);
360
#endif
361

            
362
530
  switch (**type)
363
    {
364
516
    case DBIND_POD_CASES:
365
    case DBUS_TYPE_STRING:
366
    case DBUS_TYPE_OBJECT_PATH:
367
    case DBUS_TYPE_SIGNATURE:
368
516
      len = dbind_gather_alloc_info (*type);
369
516
      dbus_message_iter_append_basic (iter, **type, *data);
370
516
      *data = ((guchar *) *data) + len;
371
516
      (*type)++;
372
516
      break;
373
7
    case DBUS_TYPE_ARRAY:
374
      {
375
        int i;
376
7
        GArray *vals = **(void ***) data;
377
        size_t elem_size, elem_align;
378
        DBusMessageIter sub;
379
        const char *saved_child_type;
380
        char *child_type_string;
381

            
382
7
        (*type)++;
383
7
        saved_child_type = *type;
384

            
385
7
        elem_size = dbind_gather_alloc_info (*type);
386
7
        elem_align = dbind_find_c_alignment_r (type);
387

            
388
        /* wow this part of the API sucks too ... */
389
7
        child_type_string = g_strndup (saved_child_type, *type - saved_child_type);
390
        /* fprintf (stderr, "array child type '%s'\n", child_type_string); */
391
7
        dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY,
392
                                          child_type_string, &sub);
393
19
        for (i = 0; i < vals->len; i++)
394
          {
395
12
            void *ptr = vals->data + elem_size * i;
396
12
            *type = saved_child_type; /* rewind type info */
397
12
            ptr = ALIGN_ADDRESS (ptr, elem_align);
398
12
            dbind_any_marshal (&sub, type, &ptr);
399
          }
400

            
401
7
        dbus_message_iter_close_container (iter, &sub);
402
7
        g_free (child_type_string);
403
7
        break;
404
      }
405
7
    case DBUS_STRUCT_BEGIN_CHAR:
406
      {
407
7
        gconstpointer data0 = *data;
408
7
        int offset = 0, stralign;
409
        DBusMessageIter sub;
410

            
411
7
        stralign = dbind_find_c_alignment (*type);
412

            
413
7
        (*type)++;
414

            
415
7
        dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub);
416

            
417
7
        offset = 0;
418
27
        while (**type != DBUS_STRUCT_END_CHAR)
419
          {
420
20
            const char *subt = *type;
421
20
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
422
20
            *data = PTR_PLUS (data0, offset);
423
20
            dbind_any_marshal (&sub, type, data);
424
20
            offset += dbind_gather_alloc_info (subt);
425
          }
426

            
427
7
        offset = ALIGN_VALUE (offset, stralign);
428
7
        *data = PTR_PLUS (data0, offset);
429

            
430
7
        dbus_message_iter_close_container (iter, &sub);
431

            
432
7
        g_assert (**type == DBUS_STRUCT_END_CHAR);
433
7
        (*type)++;
434

            
435
7
        break;
436
      }
437
    case DBUS_DICT_ENTRY_BEGIN_CHAR:
438
      {
439
        gconstpointer data0 = *data;
440
        int offset = 0, stralign;
441
        DBusMessageIter sub;
442

            
443
        stralign = dbind_find_c_alignment (*type);
444

            
445
        (*type)++;
446

            
447
        dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub);
448

            
449
        offset = 0;
450
        while (**type != DBUS_DICT_ENTRY_END_CHAR)
451
          {
452
            const char *subt = *type;
453
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
454
            *data = PTR_PLUS (data0, offset);
455
            dbind_any_marshal (&sub, type, data);
456
            offset += dbind_gather_alloc_info (subt);
457
          }
458

            
459
        offset = ALIGN_VALUE (offset, stralign);
460
        *data = PTR_PLUS (data0, offset);
461

            
462
        dbus_message_iter_close_container (iter, &sub);
463

            
464
        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
465
        (*type)++;
466

            
467
        break;
468
      }
469
    case DBUS_TYPE_STRUCT:
470
    case DBUS_TYPE_DICT_ENTRY:
471
      warn_braces ();
472
      break;
473
    }
474
530
}
475

            
476
/*---------------------------------------------------------------------------*/
477

            
478
void
479
605
dbind_any_marshal_va (DBusMessageIter *iter,
480
                      const char **arg_types,
481
                      va_list args)
482
{
483
605
  const char *p = *arg_types;
484

            
485
  /* Guard against null arg types
486
     Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027
487
   */
488
605
  if (p == NULL)
489
    p = "";
490

            
491
  {
492
    /* special case base-types since we need to walk the stack worse-luck */
493
1096
    for (; *p != '\0' && *p != '=';)
494
      {
495
        int intarg;
496
        void *ptrarg;
497
        double doublearg;
498
        dbus_int64_t int64arg;
499
491
        void *arg = NULL;
500

            
501
491
        switch (*p)
502
          {
503
478
          case DBUS_TYPE_BYTE:
504
          case DBUS_TYPE_BOOLEAN:
505
          case DBUS_TYPE_INT16:
506
          case DBUS_TYPE_UINT16:
507
          case DBUS_TYPE_INT32:
508
          case DBUS_TYPE_UINT32:
509
478
            intarg = va_arg (args, int);
510
478
            arg = &intarg;
511
478
            break;
512
          case DBUS_TYPE_INT64:
513
          case DBUS_TYPE_UINT64:
514
            int64arg = va_arg (args, dbus_int64_t);
515
            arg = &int64arg;
516
            break;
517
          case DBUS_TYPE_DOUBLE:
518
            doublearg = va_arg (args, double);
519
            arg = &doublearg;
520
            break;
521
          /* ptr types */
522
13
          case DBUS_TYPE_STRING:
523
          case DBUS_TYPE_OBJECT_PATH:
524
          case DBUS_TYPE_SIGNATURE:
525
          case DBUS_TYPE_ARRAY:
526
          case DBUS_TYPE_DICT_ENTRY:
527
13
            ptrarg = va_arg (args, void *);
528
13
            arg = &ptrarg;
529
13
            break;
530
          case DBUS_STRUCT_BEGIN_CHAR:
531
            ptrarg = va_arg (args, void *);
532
            arg = ptrarg;
533
            break;
534
          case DBUS_DICT_ENTRY_BEGIN_CHAR:
535
            ptrarg = va_arg (args, void *);
536
            arg = ptrarg;
537
            break;
538

            
539
          case DBUS_TYPE_VARIANT:
540
            fprintf (stderr, "No variant support yet - very toolkit specific\n");
541
            ptrarg = va_arg (args, void *);
542
            arg = &ptrarg;
543
            break;
544
          default:
545
            fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
546
            break;
547
          }
548
491
        if (arg != NULL)
549
491
          dbind_any_marshal (iter, &p, &arg);
550
      }
551
605
    if (*arg_types)
552
605
      *arg_types = p;
553
  }
554
605
}
555

            
556
/*---------------------------------------------------------------------------*/
557

            
558
void
559
235
dbind_any_demarshal (DBusMessageIter *iter,
560
                     const char **type,
561
                     void **data)
562
{
563
  size_t len;
564

            
565
#ifdef DEBUG
566
  fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data);
567
#endif
568

            
569
235
  switch (**type)
570
    {
571
179
    case DBIND_POD_CASES:
572
179
      len = dbind_gather_alloc_info (*type);
573
179
      dbus_message_iter_get_basic (iter, *data);
574
179
      *data = ((guchar *) *data) + len;
575
179
      (*type)++;
576
179
      break;
577
32
    case DBUS_TYPE_STRING:
578
    case DBUS_TYPE_OBJECT_PATH:
579
    case DBUS_TYPE_SIGNATURE:
580
32
      len = dbind_gather_alloc_info (*type);
581
32
      dbus_message_iter_get_basic (iter, *data);
582
#ifdef DEBUG
583
      fprintf (stderr, "dup string '%s' (%p)\n", **(void ***) data, **(void ***) data);
584
#endif
585
32
      **(void ***) data = g_strdup (**(void ***) data);
586
32
      *data = ((guchar *) *data) + len;
587
32
      (*type)++;
588
32
      break;
589
9
    case DBUS_TYPE_ARRAY:
590
      {
591
        GArray *vals;
592
        DBusMessageIter child;
593
        size_t elem_size, elem_align;
594
        const char *stored_child_type;
595
        int i;
596

            
597
9
        (*type)++;
598
9
        stored_child_type = *type;
599

            
600
9
        elem_size = dbind_gather_alloc_info (*type);
601
9
        elem_align = dbind_find_c_alignment_r (type);
602
9
        vals = g_array_new (FALSE, FALSE, elem_size);
603
9
        (**(void ***) data) = vals;
604
9
        *data = ((guchar *) *data) + sizeof (void *);
605

            
606
9
        i = 0;
607
9
        dbus_message_iter_recurse (iter, &child);
608
28
        while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID)
609
          {
610
            void *ptr;
611
19
            const char *subt = stored_child_type;
612
19
            g_array_set_size (vals, i + 1);
613
19
            ptr = vals->data + elem_size * i;
614
19
            ptr = ALIGN_ADDRESS (ptr, elem_align);
615
19
            dbind_any_demarshal (&child, &subt, &ptr);
616
19
            i++;
617
          };
618
9
        break;
619
      }
620
13
    case DBUS_STRUCT_BEGIN_CHAR:
621
      {
622
13
        gconstpointer data0 = *data;
623
13
        int offset = 0, stralign;
624
        DBusMessageIter child;
625

            
626
13
        stralign = dbind_find_c_alignment (*type);
627

            
628
13
        (*type)++;
629

            
630
13
        dbus_message_iter_recurse (iter, &child);
631

            
632
57
        while (**type != DBUS_STRUCT_END_CHAR)
633
          {
634
44
            const char *subt = *type;
635
44
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
636
44
            *data = PTR_PLUS (data0, offset);
637
44
            dbind_any_demarshal (&child, type, data);
638
44
            offset += dbind_gather_alloc_info (subt);
639
          }
640

            
641
13
        offset = ALIGN_VALUE (offset, stralign);
642
13
        *data = PTR_PLUS (data0, offset);
643

            
644
13
        g_assert (**type == DBUS_STRUCT_END_CHAR);
645
13
        (*type)++;
646

            
647
13
        break;
648
      }
649
    case DBUS_DICT_ENTRY_BEGIN_CHAR:
650
      {
651
        gconstpointer data0 = *data;
652
        int offset = 0, stralign;
653
        DBusMessageIter child;
654

            
655
        stralign = dbind_find_c_alignment (*type);
656

            
657
        (*type)++;
658

            
659
        dbus_message_iter_recurse (iter, &child);
660

            
661
        while (**type != DBUS_DICT_ENTRY_END_CHAR)
662
          {
663
            const char *subt = *type;
664
            offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type));
665
            *data = PTR_PLUS (data0, offset);
666
            dbind_any_demarshal (&child, type, data);
667
            offset += dbind_gather_alloc_info (subt);
668
          }
669

            
670
        offset = ALIGN_VALUE (offset, stralign);
671
        *data = PTR_PLUS (data0, offset);
672

            
673
        g_assert (**type == DBUS_DICT_ENTRY_END_CHAR);
674
        (*type)++;
675

            
676
        break;
677
2
      case DBUS_TYPE_VARIANT:
678
        /* skip; unimplemented for now */
679
2
        (*type)++;
680
2
        break;
681
      }
682
    case DBUS_TYPE_STRUCT:
683
    case DBUS_TYPE_DICT_ENTRY:
684
      warn_braces ();
685
      break;
686
    }
687
235
  dbus_message_iter_next (iter);
688
235
}
689

            
690
static const char *
691
pass_complex_arg (const char *p, char begin, char end)
692
{
693
  int level = 1;
694

            
695
  p++;
696
  while (*p && level > 0)
697
    {
698
      if (*p == begin)
699
        level++;
700
      else if (*p == end)
701
        level--;
702
      p++;
703
    }
704
  if (*p == end)
705
    p++;
706
  return p;
707
}
708

            
709
static const char *
710
152
pass_arg (const char *p)
711
{
712
152
  switch (*p)
713
    {
714
    case '(':
715
      return pass_complex_arg (p, '(', ')');
716
    case '{':
717
      return pass_complex_arg (p, '{', '}');
718
    case 'a':
719
      return pass_arg (p + 1);
720
152
    default:
721
152
      return p + 1;
722
    }
723
}
724

            
725
/*---------------------------------------------------------------------------*/
726

            
727
void
728
135
dbind_any_demarshal_va (DBusMessageIter *iter,
729
                        const char **arg_types,
730
                        va_list args)
731
{
732
135
  const char *p = *arg_types;
733

            
734
  /* Just consume the in args without doing anything to them */
735
287
  for (; *p != '\0' && *p != '=';)
736
    {
737
152
      switch (*p)
738
        {
739
147
        case DBUS_TYPE_BYTE:
740
        case DBUS_TYPE_BOOLEAN:
741
        case DBUS_TYPE_INT16:
742
        case DBUS_TYPE_UINT16:
743
        case DBUS_TYPE_INT32:
744
        case DBUS_TYPE_UINT32:
745
147
          va_arg (args, int);
746
147
          break;
747
        case DBUS_TYPE_INT64:
748
        case DBUS_TYPE_UINT64:
749
          va_arg (args, dbus_int64_t);
750
          break;
751
        case DBUS_TYPE_DOUBLE:
752
          va_arg (args, double);
753
          break;
754
        /* ptr types */
755
5
        case DBUS_TYPE_STRING:
756
        case DBUS_TYPE_OBJECT_PATH:
757
        case DBUS_TYPE_SIGNATURE:
758
        case DBUS_TYPE_ARRAY:
759
        case DBUS_TYPE_DICT_ENTRY:
760
5
          va_arg (args, void *);
761
5
          break;
762
        case DBUS_STRUCT_BEGIN_CHAR:
763
          va_arg (args, void *);
764
          break;
765
        case DBUS_DICT_ENTRY_BEGIN_CHAR:
766
          va_arg (args, void *);
767
          break;
768

            
769
        case DBUS_TYPE_VARIANT:
770
          fprintf (stderr, "No variant support yet - very toolkit specific\n");
771
          va_arg (args, void *);
772
          break;
773
        default:
774
          fprintf (stderr, "Unknown / invalid arg type %c\n", *p);
775
          break;
776
        }
777
152
      p = pass_arg (p);
778
    }
779

            
780
135
  if (p[0] == '=' && p[1] == '>')
781
135
    p += 2;
782

            
783
300
  for (; *p != '\0';)
784
    {
785
165
      void *arg = va_arg (args, void *);
786
165
      dbind_any_demarshal (iter, &p, &arg);
787
    }
788
135
}
789

            
790
/*---------------------------------------------------------------------------*/
791

            
792
/* nice deep free ... */
793
void
794
6
dbind_any_free (const char *type,
795
                void *ptr)
796
{
797
6
  dbind_any_free_r (&type, &ptr);
798
6
}
799

            
800
/* should this be the default normalization ? */
801
void
802
dbind_any_free_ptr (const char *type, void *ptr)
803
{
804
  dbind_any_free (type, &ptr);
805
}
806

            
807
/*---------------------------------------------------------------------------*/
808

            
809
unsigned int
810
274
dbind_find_c_alignment (const char *type)
811
{
812
274
  return dbind_find_c_alignment_r (&type);
813
}
814

            
815
/*END------------------------------------------------------------------------*/