use vtable instead of flags for types only iterators
[platform/upstream/dbus.git] / dbus / dbus-marshal-recursive.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-recursive.c  Marshalling routines for recursive types
3  *
4  * Copyright (C) 2004 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-marshal-recursive.h"
25 #include "dbus-internals.h"
26
27 /**
28  * @addtogroup DBusMarshal
29  * @{
30  */
31
32 struct DBusTypeReaderClass
33 {
34   const char *name;
35   dbus_bool_t types_only; /* only iterates over types, not values */
36   void        (* recurse)          (DBusTypeReader *sub,
37                                     DBusTypeReader *parent);
38   int         (* get_current_type) (DBusTypeReader *reader);
39   void        (* next)             (DBusTypeReader *reader,
40                                     int             current_type);
41 };
42
43 static int
44 first_type_in_signature (const DBusString *str,
45                          int               pos)
46 {
47   int t;
48
49   t = _dbus_string_get_byte (str, pos);
50   
51   if (t == DBUS_STRUCT_BEGIN_CHAR)
52     return DBUS_TYPE_STRUCT;
53   else
54     return t;
55 }
56
57 static int
58 element_type_get_alignment (const DBusString *str,
59                             int               pos)
60 {
61   return _dbus_type_get_alignment (first_type_in_signature (str, pos));
62 }
63
64 static void
65 reader_init (DBusTypeReader    *reader,
66              int                byte_order,
67              const DBusString  *type_str,
68              int                type_pos,
69              const DBusString  *value_str,
70              int                value_pos)
71 {
72   reader->byte_order = byte_order;
73   reader->finished = FALSE;
74   reader->type_str = type_str;
75   reader->type_pos = type_pos;
76   reader->value_str = value_str;
77   reader->value_pos = value_pos;
78 }
79
80 static void
81 base_reader_recurse (DBusTypeReader *sub,
82                      DBusTypeReader *parent)
83 {  
84   /* point subreader at the same place as parent */
85   reader_init (sub,
86                parent->byte_order,
87                parent->type_str,
88                parent->type_pos,
89                parent->value_str,
90                parent->value_pos);
91 }
92
93 static void
94 struct_types_only_reader_recurse (DBusTypeReader *sub,
95                                   DBusTypeReader *parent)
96 {
97   base_reader_recurse (sub, parent);
98
99   _dbus_assert (_dbus_string_get_byte (sub->type_str,
100                                        sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
101   
102   sub->type_pos += 1;
103 }
104
105 static void
106 struct_reader_recurse (DBusTypeReader *sub,
107                        DBusTypeReader *parent)
108 {
109   struct_types_only_reader_recurse (sub, parent);
110   
111   /* struct has 8 byte alignment */
112   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
113 }
114
115 static void
116 array_types_only_reader_recurse (DBusTypeReader *sub,
117                                  DBusTypeReader *parent)
118 {
119   base_reader_recurse (sub, parent);
120   
121   /* point type_pos at the array element type */
122   sub->type_pos += 1;
123
124   sub->u.array.element_type = first_type_in_signature (sub->type_str,
125                                                        sub->type_pos);
126
127   /* Init with values likely to crash things if misused */
128   sub->u.array.start_pos = _DBUS_INT_MAX;
129   sub->u.array.len = _DBUS_INT_MAX;
130 }
131
132 static void
133 array_reader_recurse (DBusTypeReader *sub,
134                       DBusTypeReader *parent)
135 {
136   dbus_uint32_t array_len;
137   int alignment;
138
139   _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
140   
141   array_types_only_reader_recurse (sub, parent);
142   
143   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
144       
145   _dbus_demarshal_basic_type (sub->value_str,
146                               DBUS_TYPE_UINT32,
147                               &array_len,
148                               sub->byte_order,
149                               &sub->value_pos);
150       
151   sub->u.array.len = array_len;
152       
153   alignment = element_type_get_alignment (sub->type_str,
154                                           sub->type_pos);
155       
156   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
157   
158   sub->u.array.start_pos = sub->value_pos;
159
160   _dbus_verbose ("    type reader %p array start = %d array len = %d array element type = %s\n",
161                  sub,
162                  sub->u.array.start_pos,
163                  sub->u.array.len,
164                  _dbus_type_to_string (sub->u.array.element_type));
165 }
166
167 static void
168 variant_reader_recurse (DBusTypeReader *sub,
169                         DBusTypeReader *parent)
170 {
171   int sig_len;
172
173   _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
174   
175   base_reader_recurse (sub, parent);
176
177   /* Variant is 1 byte sig length (without nul), signature with nul,
178    * padding to 8-boundary, then values
179    */
180
181   sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
182
183   sub->type_str = sub->value_str;
184   sub->type_pos = sub->value_pos + 1;
185   
186   sub->value_pos = sub->type_pos + sig_len + 1;
187   
188   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
189
190   _dbus_verbose ("    type reader %p variant containing '%s'\n",
191                  sub,
192                  _dbus_string_get_const_data_len (sub->type_str,
193                                                   sub->type_pos, 0));
194 }
195
196 static int
197 base_reader_get_current_type (DBusTypeReader *reader)
198 {
199   int t;
200
201   t = first_type_in_signature (reader->type_str,
202                                reader->type_pos);
203
204   return t;
205 }
206
207 static int
208 struct_reader_get_current_type (DBusTypeReader *reader)
209 {
210   int t;
211   
212   if (reader->finished)
213     t = DBUS_TYPE_INVALID;
214   else
215     t = first_type_in_signature (reader->type_str,
216                                  reader->type_pos);
217
218   return t;
219 }
220
221 static int
222 array_types_only_reader_get_current_type (DBusTypeReader *reader)
223 {
224   int t;
225
226   if (reader->finished)
227     t = DBUS_TYPE_INVALID;
228   else
229     t = reader->u.array.element_type;
230
231   return t;
232 }
233
234 static int
235 array_reader_get_current_type (DBusTypeReader *reader)
236 {
237   int t;
238   int end_pos;
239       
240   /* return the array element type if elements remain, and
241    * TYPE_INVALID otherwise
242    */
243       
244   end_pos = reader->u.array.start_pos + reader->u.array.len;
245       
246   _dbus_assert (reader->value_pos <= end_pos);
247   _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
248       
249   if (reader->value_pos < end_pos)
250     t = reader->u.array.element_type;
251   else
252     t = DBUS_TYPE_INVALID;
253
254   return t;
255 }
256
257 static void
258 skip_one_complete_type (const DBusString *type_str,
259                         int              *type_pos)
260 {
261   while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
262     *type_pos += 1;
263
264   if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
265     {
266       int depth;
267       depth = 1;
268       *type_pos += 1;
269       while (depth > 0)
270         {
271           switch (_dbus_string_get_byte (type_str, *type_pos))
272             {
273             case DBUS_STRUCT_BEGIN_CHAR:
274               depth += 1;
275               break;
276             case DBUS_STRUCT_END_CHAR:
277               depth -= 1;
278               break;
279             case DBUS_TYPE_INVALID:
280               _dbus_assert_not_reached ("unbalanced parens in signature");
281               break;
282             }
283           *type_pos += 1;
284         }
285     }
286   else
287     *type_pos += 1;
288 }
289
290 static void
291 skip_array_values (int               element_type,
292                    const DBusString *value_str,
293                    int              *value_pos,
294                    int               byte_order)
295 {
296   dbus_uint32_t array_len;
297   int pos;
298   int alignment;
299   
300   pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
301   
302   _dbus_demarshal_basic_type (value_str,
303                               DBUS_TYPE_UINT32,
304                               &array_len,
305                               byte_order,
306                               &pos);
307
308   alignment = _dbus_type_get_alignment (element_type);
309
310   pos = _DBUS_ALIGN_VALUE (pos, alignment);
311   
312   *value_pos = pos + array_len;
313 }
314
315 static void
316 base_reader_next (DBusTypeReader *reader,
317                   int             current_type)
318 {
319   switch (current_type)
320     {
321     case DBUS_TYPE_STRUCT:
322       /* Scan forward over the entire container contents */
323       {
324         DBusTypeReader sub;
325         
326         /* Recurse into the struct */
327         _dbus_type_reader_recurse (reader, &sub);
328         
329         /* Skip everything in this subreader */
330         while (_dbus_type_reader_next (&sub))
331           {
332             /* nothing */;
333           }
334         
335         /* Now we are at the end of this container */
336         reader->type_pos = sub.type_pos;
337
338         if (!reader->klass->types_only)
339           reader->value_pos = sub.value_pos;
340       }
341       break;
342       
343     case DBUS_TYPE_ARRAY:
344       {        
345         if (!reader->klass->types_only)
346           skip_array_values (first_type_in_signature (reader->type_str,
347                                                       reader->type_pos + 1),
348                              reader->value_str, &reader->value_pos, reader->byte_order);
349
350         skip_one_complete_type (reader->type_str, &reader->type_pos);
351       }
352       break;
353       
354     default:
355       if (!reader->klass->types_only)
356         _dbus_marshal_skip_basic_type (reader->value_str,
357                                        current_type, reader->byte_order,
358                                        &reader->value_pos);
359       
360       reader->type_pos += 1;
361       break;
362     }
363 }
364
365 static void
366 struct_reader_next (DBusTypeReader *reader,
367                     int             current_type)
368 {
369   int t;
370   
371   base_reader_next (reader, current_type);
372   
373   /* for STRUCT containers we return FALSE at the end of the struct,
374    * for INVALID we return FALSE at the end of the signature.
375    * In both cases we arrange for get_current_type() to return INVALID
376    * which is defined to happen iff we're at the end (no more next())
377    */
378   t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
379   if (t == DBUS_STRUCT_END_CHAR)
380     {
381       reader->type_pos += 1;
382       reader->finished = TRUE;
383     }
384 }
385
386 static void
387 array_types_only_reader_next (DBusTypeReader *reader,
388                               int             current_type)
389 {
390   /* We have one "element" to be iterated over
391    * in each array, which is its element type.
392    * So the finished flag indicates whether we've
393    * iterated over it yet or not.
394    */
395   reader->finished = TRUE;
396 }
397
398 static void
399 array_reader_next (DBusTypeReader *reader,
400                    int             current_type)
401 {
402   /* Skip one array element */
403   int end_pos;
404       
405   end_pos = reader->u.array.start_pos + reader->u.array.len;
406       
407   _dbus_assert (reader->value_pos < end_pos);
408   _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
409       
410   if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
411     {
412       DBusTypeReader sub;
413           
414       /* Recurse into the struct */
415       _dbus_type_reader_recurse (reader, &sub);
416           
417       /* Skip everything in this element */
418       while (_dbus_type_reader_next (&sub))
419         {
420           /* nothing */;
421         }
422           
423       /* Now we are at the end of this element */
424       reader->value_pos = sub.value_pos;
425     }
426   else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
427     {
428       skip_array_values (first_type_in_signature (reader->type_str,
429                                                   reader->type_pos + 1),
430                          reader->value_str, &reader->value_pos, reader->byte_order);
431     }
432   else
433     {
434       _dbus_marshal_skip_basic_type (reader->value_str,
435                                      current_type, reader->byte_order,
436                                      &reader->value_pos);
437     }
438
439   _dbus_assert (reader->value_pos <= end_pos);
440       
441   if (reader->value_pos == end_pos)
442     {
443       skip_one_complete_type (reader->type_str,
444                               &reader->type_pos);
445     }
446 }
447
448 static const DBusTypeReaderClass body_reader_class = {
449   "body",
450   FALSE,
451   NULL, /* body is always toplevel, so doesn't get recursed into */
452   base_reader_get_current_type,
453   base_reader_next
454 };
455
456 static const DBusTypeReaderClass body_types_only_reader_class = {
457   "body types",
458   TRUE,
459   NULL, /* body is always toplevel, so doesn't get recursed into */
460   base_reader_get_current_type,
461   base_reader_next
462 };
463
464 static const DBusTypeReaderClass struct_reader_class = {
465   "struct",
466   FALSE,
467   struct_reader_recurse,
468   struct_reader_get_current_type,
469   struct_reader_next
470 };
471
472 static const DBusTypeReaderClass struct_types_only_reader_class = {
473   "struct types",
474   TRUE,
475   struct_types_only_reader_recurse,
476   struct_reader_get_current_type,
477   struct_reader_next
478 };
479
480 static const DBusTypeReaderClass array_reader_class = {
481   "array",
482   FALSE,
483   array_reader_recurse,
484   array_reader_get_current_type,
485   array_reader_next
486 };
487
488 static const DBusTypeReaderClass array_types_only_reader_class = {
489   "array types",
490   TRUE,
491   array_types_only_reader_recurse,
492   array_types_only_reader_get_current_type,
493   array_types_only_reader_next
494 };
495
496 static const DBusTypeReaderClass variant_reader_class = {
497   "variant",
498   FALSE,
499   variant_reader_recurse,
500   base_reader_get_current_type,
501   base_reader_next
502 };
503
504 void
505 _dbus_type_reader_init (DBusTypeReader    *reader,
506                         int                byte_order,
507                         const DBusString  *type_str,
508                         int                type_pos,
509                         const DBusString  *value_str,
510                         int                value_pos)
511 {
512   reader->klass = &body_reader_class;
513   
514   reader_init (reader, byte_order, type_str, type_pos,
515                value_str, value_pos);
516   
517   _dbus_verbose ("  type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
518                  reader, reader->type_pos, reader->value_pos,
519                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
520 }
521
522 void
523 _dbus_type_reader_init_types_only (DBusTypeReader    *reader,
524                                    const DBusString  *type_str,
525                                    int                type_pos)
526 {
527   reader->klass = &body_types_only_reader_class;
528   
529   reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
530                type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
531   
532   _dbus_verbose ("  type reader %p init types only type_pos = %d remaining sig '%s'\n",
533                  reader, reader->type_pos,
534                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
535 }
536
537 int
538 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
539 {
540   int t;
541
542   t = (* reader->klass->get_current_type) (reader);
543
544   _dbus_assert (t != DBUS_STRUCT_END_CHAR);
545   _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
546   
547 #if 0
548   _dbus_verbose ("  type reader %p current type_pos = %d type = %s\n",
549                  reader, reader->type_pos,
550                  _dbus_type_to_string (t));
551 #endif
552   
553   return t;
554 }
555
556 dbus_bool_t
557 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
558 {
559   dbus_uint32_t array_len;
560   int len_pos;
561   
562   _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
563   _dbus_assert (!reader->klass->types_only);
564
565   len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
566   
567   _dbus_demarshal_basic_type (reader->value_str,
568                               DBUS_TYPE_UINT32,
569                               &array_len,
570                               reader->byte_order,
571                               &len_pos);
572
573   return array_len == 0;
574 }
575
576 void
577 _dbus_type_reader_read_basic (DBusTypeReader    *reader,
578                               void              *value)
579 {
580   int t;
581   int next;
582
583   _dbus_assert (!reader->klass->types_only);
584   
585   t = _dbus_type_reader_get_current_type (reader);
586   
587   next = reader->value_pos;
588   _dbus_demarshal_basic_type (reader->value_str,
589                               t, value,
590                               reader->byte_order,
591                               &next);
592   
593   
594   _dbus_verbose ("  type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
595                  reader, reader->type_pos, reader->value_pos, next,
596                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
597 }
598
599 dbus_bool_t
600 _dbus_type_reader_read_array_of_basic (DBusTypeReader    *reader,
601                                        int                type,
602                                        void             **array,
603                                        int               *array_len)
604 {
605   _dbus_assert (!reader->klass->types_only);  
606   
607 }
608
609 /**
610  * Initialize a new reader pointing to the first type and
611  * corresponding value that's a child of the current container. It's
612  * an error to call this if the current type is a non-container.
613  * 
614  * Note that DBusTypeReader traverses values, not types. So if you
615  * have an empty array of array of int, you can't recurse into it. You
616  * can only recurse into each element.
617  *
618  * @param reader the reader
619  * @param sub a reader to init pointing to the first child
620  */
621 void
622 _dbus_type_reader_recurse (DBusTypeReader *reader,
623                            DBusTypeReader *sub)
624 {
625   int t;
626   
627   t = first_type_in_signature (reader->type_str, reader->type_pos);
628
629   switch (t)
630     {
631     case DBUS_TYPE_STRUCT:
632       if (reader->klass->types_only)
633         sub->klass = &struct_types_only_reader_class;
634       else
635         sub->klass = &struct_reader_class;
636       break;
637     case DBUS_TYPE_ARRAY:
638       if (reader->klass->types_only)
639         sub->klass = &array_types_only_reader_class;
640       else
641         sub->klass = &array_reader_class;
642       break;
643     case DBUS_TYPE_VARIANT:
644       if (reader->klass->types_only)
645         _dbus_assert_not_reached ("variant types are inside the variant value, not in the signature");
646       else
647         sub->klass = &variant_reader_class;
648       break;
649     default:
650       _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
651 #ifndef DBUS_DISABLE_CHECKS
652       if (t == DBUS_TYPE_INVALID)
653         _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
654 #endif /* DBUS_DISABLE_CHECKS */
655       
656       _dbus_assert_not_reached ("don't yet handle recursing into this type");
657     }
658
659   (* sub->klass->recurse) (sub, reader);
660   
661   _dbus_verbose ("  type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
662                  sub, sub->type_pos, sub->value_pos,
663                  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
664 }
665
666 /**
667  * Skip to the next value on this "level". e.g. the next field in a
668  * struct, the next value in an array, the next key or value in a
669  * dict. Returns FALSE at the end of the current container.
670  *
671  * @param reader the reader
672  * @returns FALSE if nothing more to read at or below this level
673  */
674 dbus_bool_t
675 _dbus_type_reader_next (DBusTypeReader *reader)
676 {
677   int t;
678   
679   t = _dbus_type_reader_get_current_type (reader);
680   
681   _dbus_verbose ("  type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
682                  reader, reader->type_pos, reader->value_pos,
683                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
684                  _dbus_type_to_string (t));
685
686   if (t == DBUS_TYPE_INVALID)
687     return FALSE;
688
689   (* reader->klass->next) (reader, t);
690   
691   _dbus_verbose ("  type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
692                  reader, reader->type_pos, reader->value_pos,
693                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
694                  _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
695   
696   return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
697 }
698
699
700 /*
701  *
702  *
703  *         DBusTypeWriter
704  *
705  *
706  *
707  */
708
709 void
710 _dbus_type_writer_init (DBusTypeWriter *writer,
711                         int             byte_order,
712                         DBusString     *type_str,
713                         int             type_pos,
714                         DBusString     *value_str,
715                         int             value_pos)
716 {
717   writer->byte_order = byte_order;
718   writer->type_str = type_str;
719   writer->type_pos = type_pos;
720   writer->value_str = value_str;
721   writer->value_pos = value_pos;
722   writer->container_type = DBUS_TYPE_INVALID;
723   writer->type_pos_is_expectation = FALSE;
724
725   _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
726                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
727 }
728
729 static dbus_bool_t
730 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
731                                            int             type,
732                                            const void     *value)
733 {
734   int old_value_len;
735   int bytes_written;
736
737   old_value_len = _dbus_string_get_length (writer->value_str);
738         
739   if (!_dbus_marshal_basic_type (writer->value_str,
740                                  writer->value_pos,
741                                  type,
742                                  value,
743                                  writer->byte_order))
744     return FALSE;
745
746   bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
747   
748   writer->value_pos += bytes_written;
749
750   return TRUE;
751 }
752
753 /* If our parent is an array, things are a little bit complicated.
754  *
755  * The parent must have a complete element type, such as
756  * "i" or "aai" or "(ii)" or "a(ii)". There can't be
757  * unclosed parens, or an "a" with no following type.
758  *
759  * To recurse, the only allowed operation is to recurse into the
760  * first type in the element type. So for "i" you can't recurse, for
761  * "ai" you can recurse into the array, for "(ii)" you can recurse
762  * into the struct.
763  *
764  * If you recurse into the array for "ai", then you must specify
765  * "i" for the element type of the array you recurse into.
766  * 
767  * While inside an array at any level, we need to avoid writing to
768  * type_str, since the type only appears once for the whole array,
769  * it does not appear for each array element.
770  *
771  * While inside an array type_pos points to the expected next
772  * typecode, rather than the next place we could write a typecode.
773  */
774 static void
775 writer_recurse_init_and_check (DBusTypeWriter *writer,
776                                int             container_type,
777                                DBusTypeWriter *sub)
778 {
779   _dbus_type_writer_init (sub,
780                           writer->byte_order,
781                           writer->type_str,
782                           writer->type_pos,
783                           writer->value_str,
784                           writer->value_pos);
785   
786   sub->container_type = container_type;
787
788   if (writer->type_pos_is_expectation ||
789       (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
790     sub->type_pos_is_expectation = TRUE;
791   else
792     sub->type_pos_is_expectation = FALSE;
793   
794 #ifndef DBUS_DISABLE_CHECKS
795   if (writer->type_pos_is_expectation)
796     {
797       int expected;
798
799       expected = first_type_in_signature (writer->type_str, writer->type_pos);
800       
801       if (expected != sub->container_type)
802         {
803           _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
804                       _dbus_type_to_string (sub->container_type),
805                       _dbus_type_to_string (expected));
806           _dbus_assert_not_reached ("bad array element or variant content written");
807         }
808     }
809 #endif /* DBUS_DISABLE_CHECKS */
810
811   _dbus_verbose ("  type writer %p recurse parent type_pos = %d value_pos = %d is_expectation = %d container_type = %s remaining sig '%s'\n",
812                  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
813                  _dbus_type_to_string (writer->container_type),
814                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
815   _dbus_verbose ("  type writer %p recurse sub    type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
816                  sub, sub->type_pos, sub->value_pos,
817                  sub->type_pos_is_expectation,
818                  _dbus_type_to_string (sub->container_type));
819 }
820
821 static dbus_bool_t
822 write_or_verify_typecode (DBusTypeWriter *writer,
823                           int             typecode)
824 {
825   /* A subwriter inside an array or variant will have type_pos
826    * pointing to the expected typecode; a writer not inside an array
827    * or variant has type_pos pointing to the next place to insert a
828    * typecode.
829    */
830   _dbus_verbose ("  type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
831                  writer, writer->type_pos,
832                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
833   
834   if (writer->type_pos_is_expectation)
835     {
836 #ifndef DBUS_DISABLE_CHECKS
837       {
838         int expected;
839         
840         expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
841         
842         if (expected != typecode)
843           {
844             _dbus_warn ("Array or Variant type requires that type %s be written, but %s was written\n",
845                         _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
846             _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
847           }
848       }
849 #endif /* DBUS_DISABLE_CHECKS */
850
851       /* if immediately inside an array we'd always be appending an element,
852        * so the expected type doesn't change; if inside a struct or something
853        * below an array, we need to move through said struct or something.
854        */
855       if (writer->container_type != DBUS_TYPE_ARRAY)
856         writer->type_pos += 1;
857     }
858   else
859     {
860       if (!_dbus_string_insert_byte (writer->type_str,
861                                      writer->type_pos,
862                                      typecode))
863         return FALSE;
864
865       writer->type_pos += 1;
866     }
867
868   _dbus_verbose ("  type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
869                  writer, writer->type_pos,
870                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
871   
872   return TRUE;
873 }
874
875 dbus_bool_t
876 _dbus_type_writer_recurse_struct (DBusTypeWriter *writer,
877                                   DBusTypeWriter *sub)
878 {
879   writer_recurse_init_and_check (writer, DBUS_TYPE_STRUCT, sub);
880
881   /* Ensure that we'll be able to add alignment padding and the typecode */
882   if (!_dbus_string_alloc_space (sub->value_str, 8))
883     return FALSE;
884   
885   if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
886     _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
887   
888   if (!_dbus_string_insert_bytes (sub->value_str,
889                                   sub->value_pos,
890                                   _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
891                                   '\0'))
892     _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
893   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
894   
895   return TRUE;
896 }
897
898 dbus_bool_t
899 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
900                                  const char     *element_type,
901                                  DBusTypeWriter *sub)
902 {
903   int element_type_len;
904   DBusString element_type_str;
905   dbus_uint32_t value = 0;
906   int alignment;
907   int aligned;
908   DBusString str;
909   
910   writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
911   
912 #ifndef DBUS_DISABLE_CHECKS
913   if (writer->container_type == DBUS_TYPE_ARRAY)
914     {
915       DBusString parent_elements;
916
917       _dbus_assert (element_type != NULL);
918       
919       _dbus_string_init_const (&parent_elements,
920                                _dbus_string_get_const_data_len (writer->type_str,
921                                                                 writer->u.array.element_type_pos + 1,
922                                                                 0));
923                                                                 
924       if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
925         {
926           _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
927                       element_type);
928           _dbus_assert_not_reached ("incompatible type for child array");
929         }
930     }
931 #endif /* DBUS_DISABLE_CHECKS */
932   
933   _dbus_string_init_const (&element_type_str, element_type);
934   element_type_len = _dbus_string_get_length (&element_type_str);
935
936   /* 4 bytes for the array length and 4 bytes possible padding */
937   if (!_dbus_string_alloc_space (sub->value_str, 8))
938     return FALSE;
939
940   sub->type_pos += 1; /* move to point to the element type, since type_pos
941                        * should be the expected type for further writes
942                        */
943   sub->u.array.element_type_pos = sub->type_pos;
944
945   if (!writer->type_pos_is_expectation)
946     {
947       /* sub is a toplevel/outermost array so we need to write the type data */
948       
949       /* alloc space for array typecode, element signature, possible 7
950        * bytes of padding
951        */
952       if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
953         return FALSE;
954
955       if (!_dbus_string_insert_byte (writer->type_str,
956                                      writer->type_pos,
957                                      DBUS_TYPE_ARRAY))
958         _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
959       
960       if (!_dbus_string_copy (&element_type_str, 0,
961                               sub->type_str, sub->u.array.element_type_pos))
962         _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
963     }
964
965   /* If the parent is an array, we hold type_pos pointing at the array element type;
966    * otherwise advance it to reflect the array value we just recursed into
967    */
968   if (writer->container_type != DBUS_TYPE_ARRAY)
969     writer->type_pos += 1 + element_type_len;
970   else
971     _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
972   
973   /* Write the length */
974   sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
975
976   if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
977                                                   &value))
978     _dbus_assert_not_reached ("should not have failed to insert array len");
979   
980   _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
981
982   /* Write alignment padding for array elements */
983   _dbus_string_init_const (&str, element_type);
984   alignment = element_type_get_alignment (&str, 0);
985
986   aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
987   if (aligned != sub->value_pos)
988     {
989       if (!_dbus_string_insert_bytes (sub->value_str,
990                                       sub->value_pos,
991                                       aligned - sub->value_pos,
992                                       '\0'))
993         _dbus_assert_not_reached ("should not have failed to insert alignment padding");
994       
995       sub->value_pos = aligned;
996     }
997   sub->u.array.start_pos = sub->value_pos;
998
999   _dbus_assert (sub->u.array.start_pos == sub->value_pos);
1000   _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
1001
1002   _dbus_verbose ("  type writer %p recurse array done remaining sig '%s'\n", sub,
1003                  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
1004   
1005   return TRUE;
1006 }
1007
1008 /* Variant value will normally have:
1009  *   1 byte signature length not including nul
1010  *   signature typecodes (nul terminated)
1011  *   padding to 8-boundary
1012  *   body according to signature
1013  *
1014  * The signature string can only have a single type
1015  * in it but that type may be complex/recursive.
1016  *
1017  * So a typical variant type with the integer 3 will have these
1018  * octets:
1019  *   0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
1020  *
1021  * For an array of 4-byte types stuffed into variants, the padding to
1022  * 8-boundary is only the 1 byte that is required for the 4-boundary
1023  * anyhow for all array elements after the first one. And for single
1024  * variants in isolation, wasting a few bytes is hardly a big deal.
1025  *
1026  * The main world of hurt for writing out a variant is that the type
1027  * string is the same string as the value string. Which means
1028  * inserting to the type string will move the value_pos; and it means
1029  * that inserting to the type string could break type alignment.
1030  * 
1031  * This type alignment issue is why the body of the variant is always
1032  * 8-aligned. Then we know that re-8-aligning the start of the body
1033  * will always correctly align the full contents of the variant type.
1034  */
1035 dbus_bool_t
1036 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
1037                                    const char     *contained_type,
1038                                    DBusTypeWriter *sub)
1039 {
1040   int contained_type_len;
1041   DBusString contained_type_str;
1042   
1043   writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
1044
1045   _dbus_string_init_const (&contained_type_str, contained_type);
1046   
1047   contained_type_len = _dbus_string_get_length (&contained_type_str);
1048   
1049   /* Allocate space for the worst case, which is 1 byte sig
1050    * length, nul byte at end of sig, and 7 bytes padding to
1051    * 8-boundary.
1052    */
1053   if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1054     return FALSE;
1055
1056   /* write VARIANT typecode to the parent's type string */
1057   if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
1058     return FALSE;
1059
1060   if (!_dbus_string_insert_byte (sub->value_str,
1061                                  sub->value_pos,
1062                                  contained_type_len))
1063     _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
1064
1065   sub->value_pos += 1;
1066
1067   /* Here we switch over to the expected type sig we're about to write */
1068   sub->type_str = sub->value_str;
1069   sub->type_pos = sub->value_pos;
1070   
1071   if (!_dbus_string_copy (&contained_type_str, 0,
1072                           sub->value_str, sub->value_pos))
1073     _dbus_assert_not_reached ("should not have failed to insert variant type sig");
1074
1075   sub->value_pos += contained_type_len;
1076
1077   if (!_dbus_string_insert_byte (sub->value_str,
1078                                  sub->value_pos,
1079                                  DBUS_TYPE_INVALID))
1080     _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
1081
1082   sub->value_pos += 1;
1083   
1084   if (!_dbus_string_insert_bytes (sub->value_str,
1085                                   sub->value_pos,
1086                                   _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1087                                   '\0'))
1088     _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
1089   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1090   
1091   return TRUE;
1092 }
1093
1094 dbus_bool_t
1095 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
1096                              DBusTypeWriter *sub)
1097 {
1098   _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
1099
1100   /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
1101   _dbus_assert (!writer->type_pos_is_expectation ||
1102                 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1103
1104   _dbus_verbose ("  type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1105                  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1106                  _dbus_type_to_string (writer->container_type));
1107   _dbus_verbose ("  type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1108                  sub, sub->type_pos, sub->value_pos,
1109                  sub->type_pos_is_expectation,
1110                  _dbus_type_to_string (sub->container_type));
1111   
1112   if (sub->container_type == DBUS_TYPE_STRUCT)
1113     {
1114       if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1115         return FALSE;
1116     }
1117   else if (sub->container_type == DBUS_TYPE_ARRAY)
1118     {
1119       dbus_uint32_t len;
1120
1121       /* Set the array length */
1122       len = sub->value_pos - sub->u.array.start_pos;
1123       _dbus_marshal_set_uint32 (sub->value_str,
1124                                 sub->byte_order,
1125                                 sub->u.array.len_pos,
1126                                 len);
1127       _dbus_verbose ("    filled in sub array len to %u at len_pos %d\n",
1128                      len, sub->u.array.len_pos);
1129     }
1130
1131   /* Now get type_pos right for the parent writer. Here are the cases:
1132    *
1133    * Cases !writer->type_pos_is_expectation:
1134    *   (in these cases we want to update to the new insertion point)
1135    * 
1136    * - if we recursed into a STRUCT then we didn't know in advance
1137    *   what the types in the struct would be; so we have to fill in
1138    *   that information now.
1139    *       writer->type_pos = sub->type_pos
1140    * 
1141    * - if we recursed into anything else, we knew the full array
1142    *   type, or knew the single typecode marking VARIANT, so
1143    *   writer->type_pos is already correct.
1144    *       writer->type_pos should remain as-is
1145    *
1146    * - note that the parent is never an ARRAY or VARIANT, if it were
1147    *   then type_pos_is_expectation would be TRUE. The parent
1148    *   is thus known to be a toplevel or STRUCT.
1149    *
1150    * Cases where writer->type_pos_is_expectation:
1151    *   (in these cases we want to update to next expected type to write)
1152    * 
1153    * - we recursed from STRUCT into STRUCT and we didn't increment
1154    *   type_pos in the parent just to stay consistent with the
1155    *   !writer->type_pos_is_expectation case (though we could
1156    *   special-case this in recurse_struct instead if we wanted)
1157    *       writer->type_pos = sub->type_pos
1158    *
1159    * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1160    *   for parent should have been incremented already
1161    *       writer->type_pos should remain as-is
1162    * 
1163    * - we recursed from ARRAY into a sub-element, so type_pos in the
1164    *   parent is the element type and should remain the element type
1165    *   for the benefit of the next child element
1166    *       writer->type_pos should remain as-is
1167    *
1168    * - we recursed from VARIANT into its value, so type_pos in the
1169    *   parent makes no difference since there's only one value
1170    *   and we just finished writing it and won't use type_pos again
1171    *       writer->type_pos should remain as-is
1172    */
1173   if (sub->container_type == DBUS_TYPE_STRUCT &&
1174       (writer->container_type == DBUS_TYPE_STRUCT ||
1175        writer->container_type == DBUS_TYPE_INVALID))
1176     {
1177       /* Advance the parent to the next struct field */
1178       writer->type_pos = sub->type_pos;
1179     }
1180   
1181   writer->value_pos = sub->value_pos;
1182
1183   _dbus_verbose ("  type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1184                  writer, writer->type_pos, writer->value_pos,
1185                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1186   
1187   return TRUE;
1188 }
1189
1190 dbus_bool_t
1191 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1192                                int             type,
1193                                const void     *value)
1194 {
1195   dbus_bool_t retval;
1196   
1197   /* First ensure that our type realloc will succeed */
1198   if (!_dbus_string_alloc_space (writer->type_str, 1))
1199     return FALSE;
1200
1201   retval = FALSE;
1202
1203   if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1204     goto out;
1205   
1206   if (!write_or_verify_typecode (writer, type))
1207     _dbus_assert_not_reached ("failed to write typecode after prealloc");
1208   
1209   retval = TRUE;
1210   
1211  out:
1212   _dbus_verbose ("  type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1213                  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1214   
1215   return retval;
1216 }
1217
1218 dbus_bool_t
1219 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1220                                int             type,
1221                                const void     *array,
1222                                int             array_len)
1223 {
1224
1225
1226 }
1227
1228 /** @} */ /* end of DBusMarshal group */
1229
1230 #ifdef DBUS_BUILD_TESTS
1231 #include "dbus-test.h"
1232 #include <stdio.h>
1233 #include <stdlib.h>
1234
1235 typedef struct
1236 {
1237   DBusString signature;
1238   DBusString body;
1239 } DataBlock;
1240
1241 typedef struct
1242 {
1243   int saved_sig_len;
1244   int saved_body_len;
1245 } DataBlockState;
1246
1247 static dbus_bool_t
1248 data_block_init (DataBlock *block)
1249 {
1250   if (!_dbus_string_init (&block->signature))
1251     return FALSE;
1252
1253   if (!_dbus_string_init (&block->body))
1254     {
1255       _dbus_string_free (&block->signature);
1256       return FALSE;
1257     }
1258   
1259   return TRUE;
1260 }
1261
1262 static void
1263 data_block_free (DataBlock *block)
1264 {
1265   _dbus_string_free (&block->signature);
1266   _dbus_string_free (&block->body);
1267 }
1268
1269 static void
1270 data_block_save (DataBlock      *block,
1271                  DataBlockState *state)
1272 {
1273   state->saved_sig_len = _dbus_string_get_length (&block->signature);
1274   state->saved_body_len = _dbus_string_get_length (&block->body);
1275 }
1276
1277 static void
1278 data_block_restore (DataBlock      *block,
1279                     DataBlockState *state)
1280 {
1281   /* These set_length should be shortening things so should always work */
1282   
1283   if (!_dbus_string_set_length (&block->signature,
1284                                 state->saved_sig_len))
1285     _dbus_assert_not_reached ("could not restore signature length");
1286   
1287   if (!_dbus_string_set_length (&block->body,
1288                                 state->saved_body_len))
1289     _dbus_assert_not_reached ("could not restore body length");
1290 }
1291
1292 static void
1293 data_block_init_reader_writer (DataBlock      *block,
1294                                int             byte_order,
1295                                DBusTypeReader *reader,
1296                                DBusTypeWriter *writer)
1297 {
1298   _dbus_type_reader_init (reader,
1299                           byte_order,
1300                           &block->signature,
1301                           _dbus_string_get_length (&block->signature),
1302                           &block->body,
1303                           _dbus_string_get_length (&block->body));
1304   
1305   _dbus_type_writer_init (writer,
1306                           byte_order,
1307                           &block->signature,
1308                           _dbus_string_get_length (&block->signature),
1309                           &block->body,
1310                           _dbus_string_get_length (&block->body));
1311 }
1312
1313 #define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
1314  {                                                                                      \
1315     _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
1316                               _DBUS_FUNCTION_NAME, __LINE__);                           \
1317     _dbus_assert_not_reached ("test failed");                                           \
1318  }                                                                                      \
1319 } while (0)
1320
1321 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
1322  {                                                                                      \
1323     _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
1324                               _DBUS_FUNCTION_NAME, __LINE__);                           \
1325     _dbus_assert_not_reached ("test failed");                                           \
1326  }                                                                                      \
1327  check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
1328 } while (0)
1329
1330 #define SAMPLE_INT32           12345678
1331 #define SAMPLE_INT32_ALTERNATE 53781429
1332 static dbus_bool_t
1333 write_int32 (DataBlock      *block,
1334              DBusTypeWriter *writer)
1335 {
1336   dbus_int32_t v = SAMPLE_INT32;
1337
1338   return _dbus_type_writer_write_basic (writer,
1339                                         DBUS_TYPE_INT32,
1340                                         &v);
1341 }
1342
1343 static void
1344 real_check_expected_type (DBusTypeReader *reader,
1345                           int             expected,
1346                           const char     *funcname,
1347                           int             line)
1348 {
1349   int t;
1350
1351   t = _dbus_type_reader_get_current_type (reader);
1352   
1353   if (t != expected)
1354     {
1355       _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1356                   _dbus_type_to_string (t),
1357                   _dbus_type_to_string (expected),
1358                   funcname, line);
1359       
1360       exit (1);
1361     }
1362 }
1363
1364 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1365
1366 static dbus_bool_t
1367 read_int32 (DataBlock      *block,
1368             DBusTypeReader *reader)
1369 {
1370   dbus_int32_t v;
1371
1372   check_expected_type (reader, DBUS_TYPE_INT32);
1373   
1374   _dbus_type_reader_read_basic (reader,
1375                                 (dbus_int32_t*) &v);
1376
1377   _dbus_assert (v == SAMPLE_INT32);
1378
1379   return TRUE;
1380 }
1381
1382 static dbus_bool_t
1383 write_struct_of_int32 (DataBlock      *block,
1384                        DBusTypeWriter *writer)
1385 {
1386   dbus_int32_t v;
1387   DataBlockState saved;
1388   DBusTypeWriter sub;
1389
1390   data_block_save (block, &saved);
1391   
1392   if (!_dbus_type_writer_recurse_struct (writer,
1393                                   &sub))
1394     return FALSE;
1395
1396   v = SAMPLE_INT32;
1397   if (!_dbus_type_writer_write_basic (&sub,
1398                                       DBUS_TYPE_INT32,
1399                                       &v))
1400     {
1401       data_block_restore (block, &saved);
1402       return FALSE;
1403     }
1404
1405   v = SAMPLE_INT32_ALTERNATE;
1406   if (!_dbus_type_writer_write_basic (&sub,
1407                                       DBUS_TYPE_INT32,
1408                                       &v))
1409     {
1410       data_block_restore (block, &saved);
1411       return FALSE;
1412     }
1413
1414   if (!_dbus_type_writer_unrecurse (writer, &sub))
1415     {
1416       data_block_restore (block, &saved);
1417       return FALSE;
1418     }
1419   
1420   return TRUE;
1421 }
1422
1423 static dbus_bool_t
1424 read_struct_of_int32 (DataBlock      *block,
1425                       DBusTypeReader *reader)
1426 {
1427   dbus_int32_t v;
1428   DBusTypeReader sub;
1429
1430   check_expected_type (reader, DBUS_TYPE_STRUCT);
1431   
1432   _dbus_type_reader_recurse (reader, &sub);
1433
1434   check_expected_type (&sub, DBUS_TYPE_INT32);
1435   
1436   _dbus_type_reader_read_basic (&sub,
1437                                 (dbus_int32_t*) &v);
1438
1439   _dbus_assert (v == SAMPLE_INT32);
1440
1441   NEXT_EXPECTING_TRUE (&sub);
1442   check_expected_type (&sub, DBUS_TYPE_INT32);
1443   
1444   _dbus_type_reader_read_basic (&sub,
1445                                 (dbus_int32_t*) &v);
1446
1447   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1448
1449   NEXT_EXPECTING_FALSE (&sub);
1450   
1451   return TRUE;
1452 }
1453
1454 static dbus_bool_t
1455 write_struct_of_structs (DataBlock      *block,
1456                          DBusTypeWriter *writer)
1457 {
1458   DataBlockState saved;
1459   DBusTypeWriter sub;
1460
1461   data_block_save (block, &saved);
1462   
1463   if (!_dbus_type_writer_recurse_struct (writer,
1464                                          &sub))
1465     return FALSE;
1466
1467   if (!write_struct_of_int32 (block, &sub))
1468     {
1469       data_block_restore (block, &saved);
1470       return FALSE;
1471     }
1472   if (!write_struct_of_int32 (block, &sub))
1473     {
1474       data_block_restore (block, &saved);
1475       return FALSE;
1476     }
1477   if (!write_struct_of_int32 (block, &sub))
1478     {
1479       data_block_restore (block, &saved);
1480       return FALSE;
1481     }
1482
1483   if (!_dbus_type_writer_unrecurse (writer, &sub))
1484     {
1485       data_block_restore (block, &saved);
1486       return FALSE;
1487     }
1488   
1489   return TRUE;
1490 }
1491
1492 static dbus_bool_t
1493 read_struct_of_structs (DataBlock      *block,
1494                         DBusTypeReader *reader)
1495 {
1496   DBusTypeReader sub;
1497   
1498   check_expected_type (reader, DBUS_TYPE_STRUCT);
1499   
1500   _dbus_type_reader_recurse (reader, &sub);
1501
1502   if (!read_struct_of_int32 (block, &sub))
1503     return FALSE;
1504
1505   NEXT_EXPECTING_TRUE (&sub);
1506   if (!read_struct_of_int32 (block, &sub))
1507     return FALSE;
1508
1509   NEXT_EXPECTING_TRUE (&sub);
1510   if (!read_struct_of_int32 (block, &sub))
1511     return FALSE;
1512   
1513   NEXT_EXPECTING_FALSE (&sub);
1514   
1515   return TRUE;
1516 }
1517
1518 static dbus_bool_t
1519 write_struct_of_structs_of_structs (DataBlock      *block,
1520                                     DBusTypeWriter *writer)
1521 {
1522   DataBlockState saved;
1523   DBusTypeWriter sub;
1524
1525   data_block_save (block, &saved);
1526   
1527   if (!_dbus_type_writer_recurse_struct (writer,
1528                                          &sub))
1529     return FALSE;
1530
1531   if (!write_struct_of_structs (block, &sub))
1532     {
1533       data_block_restore (block, &saved);
1534       return FALSE;
1535     }
1536   if (!write_struct_of_structs (block, &sub))
1537     {
1538       data_block_restore (block, &saved);
1539       return FALSE;
1540     }
1541
1542   if (!_dbus_type_writer_unrecurse (writer, &sub))
1543     {
1544       data_block_restore (block, &saved);
1545       return FALSE;
1546     }
1547   
1548   return TRUE;
1549 }
1550
1551 static dbus_bool_t
1552 read_struct_of_structs_of_structs (DataBlock      *block,
1553                                    DBusTypeReader *reader)
1554 {
1555   DBusTypeReader sub;
1556   
1557   check_expected_type (reader, DBUS_TYPE_STRUCT);
1558   
1559   _dbus_type_reader_recurse (reader, &sub);
1560
1561   if (!read_struct_of_structs (block, &sub))
1562     return FALSE;
1563
1564   NEXT_EXPECTING_TRUE (&sub);
1565   if (!read_struct_of_structs (block, &sub))
1566     return FALSE;
1567
1568   NEXT_EXPECTING_FALSE (&sub);
1569   
1570   return TRUE;
1571 }
1572
1573 static dbus_bool_t
1574 write_array_of_int32 (DataBlock      *block,
1575                       DBusTypeWriter *writer)
1576 {
1577   dbus_int32_t v;
1578   DataBlockState saved;
1579   DBusTypeWriter sub;
1580
1581   data_block_save (block, &saved);
1582   
1583   if (!_dbus_type_writer_recurse_array (writer,
1584                                         DBUS_TYPE_INT32_AS_STRING,
1585                                         &sub))
1586     return FALSE;
1587
1588   v = SAMPLE_INT32_ALTERNATE;
1589   if (!_dbus_type_writer_write_basic (&sub,
1590                                       DBUS_TYPE_INT32,
1591                                       &v))
1592     {
1593       data_block_restore (block, &saved);
1594       return FALSE;
1595     }
1596
1597   v = SAMPLE_INT32;
1598   if (!_dbus_type_writer_write_basic (&sub,
1599                                       DBUS_TYPE_INT32,
1600                                       &v))
1601     {
1602       data_block_restore (block, &saved);
1603       return FALSE;
1604     }
1605
1606   v = SAMPLE_INT32;
1607   if (!_dbus_type_writer_write_basic (&sub,
1608                                       DBUS_TYPE_INT32,
1609                                       &v))
1610     {
1611       data_block_restore (block, &saved);
1612       return FALSE;
1613     }
1614   
1615   if (!_dbus_type_writer_unrecurse (writer, &sub))
1616     {
1617       data_block_restore (block, &saved);
1618       return FALSE;
1619     }
1620   
1621   return TRUE;
1622 }
1623
1624 static dbus_bool_t
1625 read_array_of_int32 (DataBlock      *block,
1626                      DBusTypeReader *reader)
1627 {
1628   dbus_int32_t v;
1629   DBusTypeReader sub;
1630
1631   check_expected_type (reader, DBUS_TYPE_ARRAY);
1632   
1633   _dbus_type_reader_recurse (reader, &sub);
1634
1635   check_expected_type (&sub, DBUS_TYPE_INT32);
1636   
1637   _dbus_type_reader_read_basic (&sub,
1638                                 (dbus_int32_t*) &v);
1639
1640   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1641
1642   NEXT_EXPECTING_TRUE (&sub);
1643   check_expected_type (&sub, DBUS_TYPE_INT32);
1644   
1645   _dbus_type_reader_read_basic (&sub,
1646                                 (dbus_int32_t*) &v);
1647
1648   _dbus_assert (v == SAMPLE_INT32);
1649
1650   NEXT_EXPECTING_TRUE (&sub);
1651   check_expected_type (&sub, DBUS_TYPE_INT32);
1652   
1653   _dbus_type_reader_read_basic (&sub,
1654                                 (dbus_int32_t*) &v);
1655
1656   _dbus_assert (v == SAMPLE_INT32);
1657
1658   NEXT_EXPECTING_FALSE (&sub);
1659   
1660   return TRUE;
1661 }
1662
1663
1664 static dbus_bool_t
1665 write_array_of_int32_empty (DataBlock      *block,
1666                             DBusTypeWriter *writer)
1667 {
1668   DataBlockState saved;
1669   DBusTypeWriter sub;
1670
1671   data_block_save (block, &saved);
1672   
1673   if (!_dbus_type_writer_recurse_array (writer,
1674                                         DBUS_TYPE_INT32_AS_STRING,
1675                                         &sub))
1676     return FALSE;
1677   
1678   if (!_dbus_type_writer_unrecurse (writer, &sub))
1679     {
1680       data_block_restore (block, &saved);
1681       return FALSE;
1682     }
1683   
1684   return TRUE;
1685 }
1686
1687 static dbus_bool_t
1688 read_array_of_int32_empty (DataBlock      *block,
1689                            DBusTypeReader *reader)
1690 {
1691   check_expected_type (reader, DBUS_TYPE_ARRAY);
1692
1693   /* We are iterating over values not types. Thus we can't recurse
1694    * into the array
1695    */
1696   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1697   
1698   return TRUE;
1699 }
1700
1701 static dbus_bool_t
1702 write_array_of_array_of_int32 (DataBlock      *block,
1703                                DBusTypeWriter *writer)
1704 {
1705   DataBlockState saved;
1706   DBusTypeWriter sub;
1707
1708   data_block_save (block, &saved);
1709   
1710   if (!_dbus_type_writer_recurse_array (writer,
1711                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1712                                         &sub))
1713     return FALSE;
1714
1715   if (!write_array_of_int32 (block, &sub))
1716     {
1717       data_block_restore (block, &saved);
1718       return FALSE;
1719     }
1720
1721   if (!write_array_of_int32 (block, &sub))
1722     {
1723       data_block_restore (block, &saved);
1724       return FALSE;
1725     }
1726
1727   if (!write_array_of_int32_empty (block, &sub))
1728     {
1729       data_block_restore (block, &saved);
1730       return FALSE;
1731     }
1732   
1733   if (!write_array_of_int32 (block, &sub))
1734     {
1735       data_block_restore (block, &saved);
1736       return FALSE;
1737     }
1738   
1739   if (!_dbus_type_writer_unrecurse (writer, &sub))
1740     {
1741       data_block_restore (block, &saved);
1742       return FALSE;
1743     }
1744   
1745   return TRUE;
1746 }
1747
1748 static dbus_bool_t
1749 read_array_of_array_of_int32 (DataBlock      *block,
1750                               DBusTypeReader *reader)
1751 {
1752   DBusTypeReader sub;
1753   
1754   check_expected_type (reader, DBUS_TYPE_ARRAY);
1755   
1756   _dbus_type_reader_recurse (reader, &sub);
1757
1758   if (!read_array_of_int32 (block, &sub))
1759     return FALSE;
1760
1761   NEXT_EXPECTING_TRUE (&sub);
1762   if (!read_array_of_int32 (block, &sub))
1763     return FALSE;
1764
1765   NEXT_EXPECTING_TRUE (&sub);
1766   if (!read_array_of_int32_empty (block, &sub))
1767     return FALSE;
1768   
1769   NEXT_EXPECTING_TRUE (&sub);
1770   if (!read_array_of_int32 (block, &sub))
1771     return FALSE;
1772
1773   NEXT_EXPECTING_FALSE (&sub);
1774   
1775   return TRUE;
1776 }
1777
1778
1779 static dbus_bool_t
1780 write_array_of_array_of_int32_empty (DataBlock      *block,
1781                                      DBusTypeWriter *writer)
1782 {
1783   DataBlockState saved;
1784   DBusTypeWriter sub;
1785
1786   data_block_save (block, &saved);
1787   
1788   if (!_dbus_type_writer_recurse_array (writer,
1789                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1790                                         &sub))
1791     return FALSE;
1792
1793   if (!_dbus_type_writer_unrecurse (writer, &sub))
1794     {
1795       data_block_restore (block, &saved);
1796       return FALSE;
1797     }
1798   
1799   return TRUE;
1800 }
1801
1802 static dbus_bool_t
1803 read_array_of_array_of_int32_empty (DataBlock      *block,
1804                                     DBusTypeReader *reader)
1805 {  
1806   check_expected_type (reader, DBUS_TYPE_ARRAY);
1807
1808   /* We are iterating over values, not types. Thus
1809    * we can't recurse in here.
1810    */
1811   
1812   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1813   
1814   return TRUE;
1815 }
1816
1817 static dbus_bool_t
1818 write_array_of_array_of_array_of_int32 (DataBlock      *block,
1819                                         DBusTypeWriter *writer)
1820 {
1821   DataBlockState saved;
1822   DBusTypeWriter sub;
1823
1824   data_block_save (block, &saved);
1825   
1826   if (!_dbus_type_writer_recurse_array (writer,
1827                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1828                                         &sub))
1829     return FALSE;
1830
1831   if (!write_array_of_array_of_int32 (block, &sub))
1832     {
1833       data_block_restore (block, &saved);
1834       return FALSE;
1835     }
1836
1837   if (!write_array_of_array_of_int32 (block, &sub))
1838     {
1839       data_block_restore (block, &saved);
1840       return FALSE;
1841     }
1842
1843   if (!write_array_of_array_of_int32_empty (block, &sub))
1844     {
1845       data_block_restore (block, &saved);
1846       return FALSE;
1847     }
1848   
1849   if (!_dbus_type_writer_unrecurse (writer, &sub))
1850     {
1851       data_block_restore (block, &saved);
1852       return FALSE;
1853     }
1854   
1855   return TRUE;
1856 }
1857
1858 static dbus_bool_t
1859 read_array_of_array_of_array_of_int32 (DataBlock      *block,
1860                                        DBusTypeReader *reader)
1861 {
1862   DBusTypeReader sub;
1863   
1864   check_expected_type (reader, DBUS_TYPE_ARRAY);
1865   
1866   _dbus_type_reader_recurse (reader, &sub);
1867
1868   if (!read_array_of_array_of_int32 (block, &sub))
1869     return FALSE;
1870
1871   NEXT_EXPECTING_TRUE (&sub);
1872   if (!read_array_of_array_of_int32 (block, &sub))
1873     return FALSE;
1874
1875   NEXT_EXPECTING_TRUE (&sub);
1876   if (!read_array_of_array_of_int32_empty (block, &sub))
1877     return FALSE;
1878
1879   NEXT_EXPECTING_FALSE (&sub);
1880   
1881   return TRUE;
1882 }
1883
1884 static dbus_bool_t
1885 write_struct_of_array_of_int32 (DataBlock      *block,
1886                                 DBusTypeWriter *writer)
1887 {
1888   DataBlockState saved;
1889   DBusTypeWriter sub;
1890
1891   data_block_save (block, &saved);
1892   
1893   if (!_dbus_type_writer_recurse_struct (writer,
1894                                          &sub))
1895     return FALSE;
1896
1897   if (!write_array_of_int32 (block, &sub))
1898     {
1899       data_block_restore (block, &saved);
1900       return FALSE;
1901     }
1902
1903   if (!write_array_of_int32_empty (block, &sub))
1904     {
1905       data_block_restore (block, &saved);
1906       return FALSE;
1907     }
1908       
1909   if (!_dbus_type_writer_unrecurse (writer, &sub))
1910     {
1911       data_block_restore (block, &saved);
1912       return FALSE;
1913     }
1914   
1915   return TRUE;
1916 }
1917
1918 static dbus_bool_t
1919 read_struct_of_array_of_int32 (DataBlock      *block,
1920                                DBusTypeReader *reader)
1921 {
1922   DBusTypeReader sub;
1923
1924   check_expected_type (reader, DBUS_TYPE_STRUCT);
1925   
1926   _dbus_type_reader_recurse (reader, &sub);
1927
1928   check_expected_type (&sub, DBUS_TYPE_ARRAY);
1929
1930   if (!read_array_of_int32 (block, &sub))
1931     return FALSE;
1932
1933   NEXT_EXPECTING_TRUE (&sub);
1934   if (!read_array_of_int32_empty (block, &sub))
1935     return FALSE;
1936   
1937   NEXT_EXPECTING_FALSE (&sub);
1938   
1939   return TRUE;
1940 }
1941
1942 static dbus_bool_t
1943 write_struct_of_struct_of_array_of_int32 (DataBlock      *block,
1944                                           DBusTypeWriter *writer)
1945 {
1946   DataBlockState saved;
1947   DBusTypeWriter sub;
1948
1949   data_block_save (block, &saved);
1950   
1951   if (!_dbus_type_writer_recurse_struct (writer,
1952                                          &sub))
1953     return FALSE;
1954
1955   if (!write_struct_of_array_of_int32 (block, &sub))
1956     {
1957       data_block_restore (block, &saved);
1958       return FALSE;
1959     }
1960   if (!write_struct_of_array_of_int32 (block, &sub))
1961     {
1962       data_block_restore (block, &saved);
1963       return FALSE;
1964     }
1965   if (!write_struct_of_array_of_int32 (block, &sub))
1966     {
1967       data_block_restore (block, &saved);
1968       return FALSE;
1969     }
1970
1971   if (!_dbus_type_writer_unrecurse (writer, &sub))
1972     {
1973       data_block_restore (block, &saved);
1974       return FALSE;
1975     }
1976   
1977   return TRUE;
1978 }
1979
1980 static dbus_bool_t
1981 read_struct_of_struct_of_array_of_int32 (DataBlock      *block,
1982                                          DBusTypeReader *reader)
1983 {
1984   DBusTypeReader sub;
1985   
1986   check_expected_type (reader, DBUS_TYPE_STRUCT);
1987   
1988   _dbus_type_reader_recurse (reader, &sub);
1989
1990   if (!read_struct_of_array_of_int32 (block, &sub))
1991     return FALSE;
1992
1993   NEXT_EXPECTING_TRUE (&sub);
1994   if (!read_struct_of_array_of_int32 (block, &sub))
1995     return FALSE;
1996
1997   NEXT_EXPECTING_TRUE (&sub);
1998   if (!read_struct_of_array_of_int32 (block, &sub))
1999     return FALSE;
2000   
2001   NEXT_EXPECTING_FALSE (&sub);
2002   
2003   return TRUE;
2004 }
2005
2006 static dbus_bool_t
2007 write_array_of_struct_of_int32 (DataBlock      *block,
2008                                 DBusTypeWriter *writer)
2009 {
2010   DataBlockState saved;
2011   DBusTypeWriter sub;
2012
2013   data_block_save (block, &saved);
2014
2015   if (!_dbus_type_writer_recurse_array (writer,
2016                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2017                                         DBUS_TYPE_INT32_AS_STRING
2018                                         DBUS_TYPE_INT32_AS_STRING
2019                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2020                                         &sub))
2021     return FALSE;
2022
2023   if (!write_struct_of_int32 (block, &sub))
2024     {
2025       data_block_restore (block, &saved);
2026       return FALSE;
2027     }
2028
2029   if (!write_struct_of_int32 (block, &sub))
2030     {
2031       data_block_restore (block, &saved);
2032       return FALSE;
2033     }
2034
2035   if (!write_struct_of_int32 (block, &sub))
2036     {
2037       data_block_restore (block, &saved);
2038       return FALSE;
2039     }
2040   
2041   if (!_dbus_type_writer_unrecurse (writer, &sub))
2042     {
2043       data_block_restore (block, &saved);
2044       return FALSE;
2045     }
2046   
2047   return TRUE;
2048 }
2049
2050 static dbus_bool_t
2051 read_array_of_struct_of_int32 (DataBlock      *block,
2052                                DBusTypeReader *reader)
2053 {
2054   DBusTypeReader sub;
2055
2056   check_expected_type (reader, DBUS_TYPE_ARRAY);
2057   
2058   _dbus_type_reader_recurse (reader, &sub);
2059
2060   check_expected_type (&sub, DBUS_TYPE_STRUCT);
2061
2062   if (!read_struct_of_int32 (block, &sub))
2063     return FALSE;
2064   
2065   NEXT_EXPECTING_TRUE (&sub);
2066
2067   if (!read_struct_of_int32 (block, &sub))
2068     return FALSE;
2069   
2070   NEXT_EXPECTING_TRUE (&sub);
2071
2072   if (!read_struct_of_int32 (block, &sub))
2073     return FALSE;
2074   
2075   NEXT_EXPECTING_FALSE (&sub);
2076   
2077   return TRUE;
2078 }
2079
2080
2081 static dbus_bool_t
2082 write_array_of_array_of_struct_of_int32 (DataBlock      *block,
2083                                          DBusTypeWriter *writer)
2084 {
2085   DataBlockState saved;
2086   DBusTypeWriter sub;
2087
2088   data_block_save (block, &saved);
2089
2090   if (!_dbus_type_writer_recurse_array (writer,
2091                                         DBUS_TYPE_ARRAY_AS_STRING
2092                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2093                                         DBUS_TYPE_INT32_AS_STRING
2094                                         DBUS_TYPE_INT32_AS_STRING
2095                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2096                                         &sub))
2097     return FALSE;
2098
2099   if (!write_array_of_struct_of_int32 (block, &sub))
2100     {
2101       data_block_restore (block, &saved);
2102       return FALSE;
2103     }
2104
2105   if (!write_array_of_struct_of_int32 (block, &sub))
2106     {
2107       data_block_restore (block, &saved);
2108       return FALSE;
2109     }
2110
2111   if (!write_array_of_struct_of_int32 (block, &sub))
2112     {
2113       data_block_restore (block, &saved);
2114       return FALSE;
2115     }
2116   
2117   if (!_dbus_type_writer_unrecurse (writer, &sub))
2118     {
2119       data_block_restore (block, &saved);
2120       return FALSE;
2121     }
2122   
2123   return TRUE;
2124 }
2125
2126 static dbus_bool_t
2127 read_array_of_array_of_struct_of_int32 (DataBlock      *block,
2128                                         DBusTypeReader *reader)
2129 {
2130   DBusTypeReader sub;
2131
2132   check_expected_type (reader, DBUS_TYPE_ARRAY);
2133   
2134   _dbus_type_reader_recurse (reader, &sub);
2135
2136   check_expected_type (&sub, DBUS_TYPE_ARRAY);
2137
2138   if (!read_array_of_struct_of_int32 (block, &sub))
2139     return FALSE;
2140   
2141   NEXT_EXPECTING_TRUE (&sub);
2142
2143   if (!read_array_of_struct_of_int32 (block, &sub))
2144     return FALSE;
2145   
2146   NEXT_EXPECTING_TRUE (&sub);
2147
2148   if (!read_array_of_struct_of_int32 (block, &sub))
2149     return FALSE;
2150   
2151   NEXT_EXPECTING_FALSE (&sub);
2152   
2153   return TRUE;
2154 }
2155
2156 static dbus_bool_t
2157 write_struct_of_array_of_struct_of_int32 (DataBlock      *block,
2158                                           DBusTypeWriter *writer)
2159 {
2160   DataBlockState saved;
2161   DBusTypeWriter sub;
2162
2163   data_block_save (block, &saved);
2164   
2165   if (!_dbus_type_writer_recurse_struct (writer,
2166                                          &sub))
2167     return FALSE;
2168
2169   if (!write_array_of_struct_of_int32 (block, &sub))
2170     {
2171       data_block_restore (block, &saved);
2172       return FALSE;
2173     }
2174   if (!write_array_of_struct_of_int32 (block, &sub))
2175     {
2176       data_block_restore (block, &saved);
2177       return FALSE;
2178     }
2179   if (!write_array_of_struct_of_int32 (block, &sub))
2180     {
2181       data_block_restore (block, &saved);
2182       return FALSE;
2183     }
2184
2185   if (!_dbus_type_writer_unrecurse (writer, &sub))
2186     {
2187       data_block_restore (block, &saved);
2188       return FALSE;
2189     }
2190   
2191   return TRUE;
2192 }
2193
2194 static dbus_bool_t
2195 read_struct_of_array_of_struct_of_int32 (DataBlock      *block,
2196                                          DBusTypeReader *reader)
2197 {
2198   DBusTypeReader sub;
2199   
2200   check_expected_type (reader, DBUS_TYPE_STRUCT);
2201   
2202   _dbus_type_reader_recurse (reader, &sub);
2203   
2204   if (!read_array_of_struct_of_int32 (block, &sub))
2205     return FALSE;
2206
2207   NEXT_EXPECTING_TRUE (&sub);
2208   if (!read_array_of_struct_of_int32 (block, &sub))
2209     return FALSE;
2210
2211   NEXT_EXPECTING_TRUE (&sub);
2212   if (!read_array_of_struct_of_int32 (block, &sub))
2213     return FALSE;
2214   
2215   NEXT_EXPECTING_FALSE (&sub);
2216   
2217   return TRUE;
2218 }
2219
2220 static dbus_bool_t
2221 write_array_of_struct_of_array_of_int32 (DataBlock      *block,
2222                                          DBusTypeWriter *writer)
2223 {
2224   DataBlockState saved;
2225   DBusTypeWriter sub;
2226
2227   data_block_save (block, &saved);
2228
2229   if (!_dbus_type_writer_recurse_array (writer,
2230                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2231                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2232                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2233                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2234                                         &sub))
2235     return FALSE;
2236
2237   if (!write_struct_of_array_of_int32 (block, &sub))
2238     {
2239       data_block_restore (block, &saved);
2240       return FALSE;
2241     }
2242
2243   if (!write_struct_of_array_of_int32 (block, &sub))
2244     {
2245       data_block_restore (block, &saved);
2246       return FALSE;
2247     }
2248
2249   if (!write_struct_of_array_of_int32 (block, &sub))
2250     {
2251       data_block_restore (block, &saved);
2252       return FALSE;
2253     }
2254   
2255   if (!_dbus_type_writer_unrecurse (writer, &sub))
2256     {
2257       data_block_restore (block, &saved);
2258       return FALSE;
2259     }
2260   
2261   return TRUE;
2262 }
2263
2264 static dbus_bool_t
2265 read_array_of_struct_of_array_of_int32 (DataBlock      *block,
2266                                         DBusTypeReader *reader)
2267 {
2268   DBusTypeReader sub;
2269
2270   check_expected_type (reader, DBUS_TYPE_ARRAY);
2271   
2272   _dbus_type_reader_recurse (reader, &sub);
2273
2274   check_expected_type (&sub, DBUS_TYPE_STRUCT);
2275
2276   if (!read_struct_of_array_of_int32 (block, &sub))
2277     return FALSE;
2278   
2279   NEXT_EXPECTING_TRUE (&sub);
2280
2281   if (!read_struct_of_array_of_int32 (block, &sub))
2282     return FALSE;
2283   
2284   NEXT_EXPECTING_TRUE (&sub);
2285
2286   if (!read_struct_of_array_of_int32 (block, &sub))
2287     return FALSE;
2288   
2289   NEXT_EXPECTING_FALSE (&sub);
2290   
2291   return TRUE;
2292 }
2293
2294 typedef enum {
2295   ITEM_INVALID = -1,
2296
2297   ITEM_INT32 = 0,
2298
2299   ITEM_STRUCT_OF_INT32,
2300   ITEM_STRUCT_OF_STRUCTS,
2301   ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2302
2303   ITEM_ARRAY_OF_INT32,
2304   ITEM_ARRAY_OF_INT32_EMPTY,
2305   ITEM_ARRAY_OF_ARRAY_OF_INT32,
2306   ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2307   ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2308
2309   ITEM_STRUCT_OF_ARRAY_OF_INT32,
2310   ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2311
2312   ITEM_ARRAY_OF_STRUCT_OF_INT32,
2313   ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2314
2315   ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2316   ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2317
2318   ITEM_LAST
2319 } WhichItem;
2320
2321
2322 typedef dbus_bool_t (* WriteItemFunc) (DataBlock      *block,
2323                                        DBusTypeWriter *writer);
2324 typedef dbus_bool_t (* ReadItemFunc)  (DataBlock      *block,
2325                                        DBusTypeReader *reader);
2326
2327 typedef struct
2328 {
2329   const char *desc;
2330   WhichItem which;
2331   WriteItemFunc write_item_func;
2332   ReadItemFunc read_item_func;
2333 } CheckMarshalItem;
2334
2335 static CheckMarshalItem items[] = {
2336   { "int32",
2337     ITEM_INT32, write_int32, read_int32 },
2338   { "struct with two int32",
2339     ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2340   { "struct with three structs of two int32",
2341     ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2342   { "struct of two structs of three structs of two int32",
2343     ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2344     write_struct_of_structs_of_structs,
2345     read_struct_of_structs_of_structs },
2346   { "array of int32",
2347     ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2348   { "empty array of int32",
2349     ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2350   { "array of array of int32",
2351     ITEM_ARRAY_OF_ARRAY_OF_INT32,
2352     write_array_of_array_of_int32, read_array_of_array_of_int32 },
2353   { "empty array of array of int32",
2354     ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2355     write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2356   { "array of array of array of int32",
2357     ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2358     write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2359   { "struct of array of int32",
2360     ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2361   { "struct of struct of array of int32",
2362     ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2363     write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2364   { "array of struct of int32",
2365     ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2366   { "array of array of struct of int32",
2367     ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2368     write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2369
2370   { "struct of array of struct of int32",
2371     ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2372     write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2373   { "array of struct of array of int32",
2374     ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2375     write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2376 };
2377
2378 typedef struct
2379 {
2380   /* Array of items from the above items[]; -1 terminated */
2381   int items[20];
2382 } TestRun;
2383
2384 static TestRun runs[] = {
2385   { { ITEM_INVALID } },
2386
2387   /* INT32 */
2388   { { ITEM_INT32, ITEM_INVALID } },
2389   { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2390   { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2391
2392   /* STRUCT_OF_INT32 */
2393   { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2394   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2395   { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2396   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2397   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2398
2399   /* STRUCT_OF_STRUCTS */
2400   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2401   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2402   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2403   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2404   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2405   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2406
2407   /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2408   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2409   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2410   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2411   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2412   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2413   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2414
2415   /* ARRAY_OF_INT32 */
2416   { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2417   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2418   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2419   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2420   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2421   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2422   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2423   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2424   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2425   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2426
2427   /* ARRAY_OF_ARRAY_OF_INT32 */
2428   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2429   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2430   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2431   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2432   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2433   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2434   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2435   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2436   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2437   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2438
2439   /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2440   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2441   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2442   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2443   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2444   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2445   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2446   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2447   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2448   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2449   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2450
2451   /* STRUCT_OF_ARRAY_OF_INT32 */
2452   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2453   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2454   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2455   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2456   { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2457   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2458
2459   /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2460   { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2461   
2462   /* ARRAY_OF_STRUCT_OF_INT32 */
2463   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2464   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2465   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2466   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2467   { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2468   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2469
2470   /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2471   { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2472   
2473   /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2474   { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2475   
2476   /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2477   { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2478   
2479 };
2480
2481 static dbus_bool_t
2482 perform_one_run (DataBlock *block,
2483                  int        byte_order,
2484                  TestRun   *run)
2485 {
2486   DBusTypeReader reader;
2487   DBusTypeWriter writer;
2488   int i;
2489   DataBlockState saved;
2490   dbus_bool_t retval;
2491
2492   retval = FALSE;
2493
2494   {
2495     _dbus_verbose ("run byteorder %s items ",
2496                    byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2497     i = 0;
2498     while (run->items[i] != ITEM_INVALID)
2499       {
2500         CheckMarshalItem *item = &items[run->items[i]];
2501         
2502         _dbus_verbose ("%s ", item->desc);
2503         ++i;
2504       }
2505     _dbus_verbose (" = %d items\n", i);
2506   }
2507   
2508   data_block_save (block, &saved);
2509   
2510   data_block_init_reader_writer (block, 
2511                                  byte_order,
2512                                  &reader, &writer);
2513
2514   i = 0;
2515   while (run->items[i] != ITEM_INVALID)
2516     {
2517       CheckMarshalItem *item = &items[run->items[i]];
2518
2519       _dbus_verbose (">>writing %s\n", item->desc);
2520       
2521       if (!(* item->write_item_func) (block, &writer))
2522         goto out;
2523       ++i;
2524     }
2525
2526   i = 0;
2527   while (run->items[i] != ITEM_INVALID)
2528     {
2529       CheckMarshalItem *item = &items[run->items[i]];
2530
2531       _dbus_verbose (">>data for reading %s\n", item->desc);
2532       
2533       _dbus_verbose_bytes_of_string (reader.type_str, 0,
2534                                      _dbus_string_get_length (reader.type_str));
2535       _dbus_verbose_bytes_of_string (reader.value_str, 0,
2536                                      _dbus_string_get_length (reader.value_str));
2537       
2538       _dbus_verbose (">>reading %s\n", item->desc);
2539       
2540       if (!(* item->read_item_func) (block, &reader))
2541         goto out;
2542
2543       _dbus_type_reader_next (&reader);
2544       
2545       ++i;
2546     }
2547   
2548   retval = TRUE;
2549   
2550  out:
2551   data_block_restore (block, &saved);
2552   return retval;
2553 }
2554
2555 static dbus_bool_t
2556 perform_all_runs (int byte_order,
2557                   int initial_offset)
2558 {
2559   int i;
2560   DataBlock block;
2561   dbus_bool_t retval;
2562
2563   retval = FALSE;
2564   
2565   if (!data_block_init (&block))
2566     return FALSE;
2567
2568   if (!_dbus_string_lengthen (&block.signature, initial_offset))
2569     goto out;
2570   
2571   if (!_dbus_string_lengthen (&block.body, initial_offset))
2572     goto out;
2573   
2574   i = 0;
2575   while (i < _DBUS_N_ELEMENTS (runs))
2576     {
2577       if (!perform_one_run (&block, byte_order, &runs[i]))
2578         goto out;
2579       
2580       ++i;
2581     }
2582
2583   retval = TRUE;
2584   
2585  out:
2586   data_block_free (&block);
2587   
2588   return retval;
2589 }
2590
2591 static dbus_bool_t
2592 perform_all_items (int byte_order,
2593                    int initial_offset)
2594 {
2595   int i;
2596   DataBlock block;
2597   dbus_bool_t retval;
2598   TestRun run;
2599
2600   retval = FALSE;
2601   
2602   if (!data_block_init (&block))
2603     return FALSE;
2604
2605
2606   if (!_dbus_string_lengthen (&block.signature, initial_offset))
2607     goto out;
2608   
2609   if (!_dbus_string_lengthen (&block.body, initial_offset))
2610     goto out;
2611
2612   /* Create a run containing all the items */
2613   i = 0;
2614   while (i < _DBUS_N_ELEMENTS (items))
2615     {
2616       _dbus_assert (i == items[i].which);
2617       
2618       run.items[i] = items[i].which;
2619       
2620       ++i;
2621     }
2622   
2623   run.items[i] = ITEM_INVALID;
2624
2625   if (!perform_one_run (&block, byte_order, &run))
2626     goto out;  
2627   
2628   retval = TRUE;
2629   
2630  out:
2631   data_block_free (&block);
2632   
2633   return retval;
2634 }
2635
2636 static dbus_bool_t
2637 recursive_marshal_test_iteration (void *data)
2638 {
2639   int i;
2640
2641   i = 0;
2642   while (i < 18)
2643     {
2644       if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2645         return FALSE;
2646       if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2647         return FALSE;
2648       if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2649         return FALSE;
2650       if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2651         return FALSE;
2652       
2653       ++i;
2654     }
2655
2656   return TRUE;
2657 }
2658
2659 dbus_bool_t _dbus_marshal_recursive_test (void);
2660
2661 dbus_bool_t
2662 _dbus_marshal_recursive_test (void)
2663 {
2664   _dbus_test_oom_handling ("recursive marshaling",
2665                            recursive_marshal_test_iteration,
2666                            NULL);  
2667   
2668   return TRUE;
2669 }
2670
2671 #if 1
2672 int
2673 main (int argc, char **argv)
2674 {
2675   _dbus_marshal_recursive_test ();
2676
2677   return 0;
2678 }
2679 #endif /* main() */
2680
2681 #endif /* DBUS_BUILD_TESTS */