further extend tests
[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 ("can't recurse into variant typecode");
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 (!_dbus_string_alloc_space (sub->type_str, 1))
886     return FALSE;
887   
888   if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
889     _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
890   
891   if (!_dbus_string_insert_bytes (sub->value_str,
892                                   sub->value_pos,
893                                   _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
894                                   '\0'))
895     _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
896   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
897   
898   return TRUE;
899 }
900
901 dbus_bool_t
902 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
903                                  const char     *element_type,
904                                  DBusTypeWriter *sub)
905 {
906   int element_type_len;
907   DBusString element_type_str;
908   dbus_uint32_t value = 0;
909   int alignment;
910   int aligned;
911   DBusString str;
912   
913   writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
914
915   _dbus_string_init_const (&element_type_str, element_type);
916   element_type_len = _dbus_string_get_length (&element_type_str);
917   
918 #ifndef DBUS_DISABLE_CHECKS
919   if (writer->container_type == DBUS_TYPE_ARRAY)
920     {
921       if (!_dbus_string_equal_substring (&element_type_str, 0, element_type_len,
922                                          writer->type_str, writer->u.array.element_type_pos + 1))
923         {
924           _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
925                       element_type);
926           _dbus_assert_not_reached ("incompatible type for child array");
927         }
928     }
929 #endif /* DBUS_DISABLE_CHECKS */  
930
931   /* 4 bytes for the array length and 4 bytes possible padding */
932   if (!_dbus_string_alloc_space (sub->value_str, 8))
933     return FALSE;
934
935   sub->type_pos += 1; /* move to point to the element type, since type_pos
936                        * should be the expected type for further writes
937                        */
938   sub->u.array.element_type_pos = sub->type_pos;
939
940   if (!writer->type_pos_is_expectation)
941     {
942       /* sub is a toplevel/outermost array so we need to write the type data */
943       
944       /* alloc space for array typecode, element signature, possible 7
945        * bytes of padding
946        */
947       if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
948         return FALSE;
949
950       if (!_dbus_string_insert_byte (writer->type_str,
951                                      writer->type_pos,
952                                      DBUS_TYPE_ARRAY))
953         _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
954       
955       if (!_dbus_string_copy (&element_type_str, 0,
956                               sub->type_str, sub->u.array.element_type_pos))
957         _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
958     }
959
960   /* If the parent is an array, we hold type_pos pointing at the array element type;
961    * otherwise advance it to reflect the array value we just recursed into
962    */
963   if (writer->container_type != DBUS_TYPE_ARRAY)
964     writer->type_pos += 1 + element_type_len;
965   else
966     _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
967   
968   /* Write the length */
969   sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
970
971   if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
972                                                   &value))
973     _dbus_assert_not_reached ("should not have failed to insert array len");
974   
975   _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
976
977   /* Write alignment padding for array elements */
978   _dbus_string_init_const (&str, element_type);
979   alignment = element_type_get_alignment (&str, 0);
980
981   aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
982   if (aligned != sub->value_pos)
983     {
984       if (!_dbus_string_insert_bytes (sub->value_str,
985                                       sub->value_pos,
986                                       aligned - sub->value_pos,
987                                       '\0'))
988         _dbus_assert_not_reached ("should not have failed to insert alignment padding");
989       
990       sub->value_pos = aligned;
991     }
992   sub->u.array.start_pos = sub->value_pos;
993
994   _dbus_assert (sub->u.array.start_pos == sub->value_pos);
995   _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
996
997   _dbus_verbose ("  type writer %p recurse array done remaining sig '%s'\n", sub,
998                  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
999   
1000   return TRUE;
1001 }
1002
1003 /* Variant value will normally have:
1004  *   1 byte signature length not including nul
1005  *   signature typecodes (nul terminated)
1006  *   padding to 8-boundary
1007  *   body according to signature
1008  *
1009  * The signature string can only have a single type
1010  * in it but that type may be complex/recursive.
1011  *
1012  * So a typical variant type with the integer 3 will have these
1013  * octets:
1014  *   0x1 'i' '\0' [padding to 8-boundary] 0x0 0x0 0x0 0x3
1015  *
1016  * For an array of 4-byte types stuffed into variants, the padding to
1017  * 8-boundary is only the 1 byte that is required for the 4-boundary
1018  * anyhow for all array elements after the first one. And for single
1019  * variants in isolation, wasting a few bytes is hardly a big deal.
1020  *
1021  * The main world of hurt for writing out a variant is that the type
1022  * string is the same string as the value string. Which means
1023  * inserting to the type string will move the value_pos; and it means
1024  * that inserting to the type string could break type alignment.
1025  * 
1026  * This type alignment issue is why the body of the variant is always
1027  * 8-aligned. Then we know that re-8-aligning the start of the body
1028  * will always correctly align the full contents of the variant type.
1029  */
1030 dbus_bool_t
1031 _dbus_type_writer_recurse_variant (DBusTypeWriter *writer,
1032                                    const char     *contained_type,
1033                                    DBusTypeWriter *sub)
1034 {
1035   int contained_type_len;
1036   DBusString contained_type_str;
1037   
1038   writer_recurse_init_and_check (writer, DBUS_TYPE_VARIANT, sub);
1039
1040   _dbus_string_init_const (&contained_type_str, contained_type);
1041   
1042   contained_type_len = _dbus_string_get_length (&contained_type_str);
1043   
1044   /* Allocate space for the worst case, which is 1 byte sig
1045    * length, nul byte at end of sig, and 7 bytes padding to
1046    * 8-boundary.
1047    */
1048   if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
1049     return FALSE;
1050
1051   /* write VARIANT typecode to the parent's type string */
1052   if (!write_or_verify_typecode (sub, DBUS_TYPE_VARIANT))
1053     return FALSE;
1054
1055   if (!_dbus_string_insert_byte (sub->value_str,
1056                                  sub->value_pos,
1057                                  contained_type_len))
1058     _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
1059
1060   sub->value_pos += 1;
1061
1062   /* Here we switch over to the expected type sig we're about to write */
1063   sub->type_str = sub->value_str;
1064   sub->type_pos = sub->value_pos;
1065   
1066   if (!_dbus_string_copy (&contained_type_str, 0,
1067                           sub->value_str, sub->value_pos))
1068     _dbus_assert_not_reached ("should not have failed to insert variant type sig");
1069
1070   sub->value_pos += contained_type_len;
1071
1072   if (!_dbus_string_insert_byte (sub->value_str,
1073                                  sub->value_pos,
1074                                  DBUS_TYPE_INVALID))
1075     _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
1076
1077   sub->value_pos += 1;
1078   
1079   if (!_dbus_string_insert_bytes (sub->value_str,
1080                                   sub->value_pos,
1081                                   _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
1082                                   '\0'))
1083     _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
1084   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
1085   
1086   return TRUE;
1087 }
1088
1089 dbus_bool_t
1090 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
1091                              DBusTypeWriter *sub)
1092 {
1093   _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
1094
1095   /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
1096   _dbus_assert (!writer->type_pos_is_expectation ||
1097                 (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
1098
1099   _dbus_verbose ("  type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1100                  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
1101                  _dbus_type_to_string (writer->container_type));
1102   _dbus_verbose ("  type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
1103                  sub, sub->type_pos, sub->value_pos,
1104                  sub->type_pos_is_expectation,
1105                  _dbus_type_to_string (sub->container_type));
1106   
1107   if (sub->container_type == DBUS_TYPE_STRUCT)
1108     {
1109       if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
1110         return FALSE;
1111     }
1112   else if (sub->container_type == DBUS_TYPE_ARRAY)
1113     {
1114       dbus_uint32_t len;
1115
1116       /* Set the array length */
1117       len = sub->value_pos - sub->u.array.start_pos;
1118       _dbus_marshal_set_uint32 (sub->value_str,
1119                                 sub->byte_order,
1120                                 sub->u.array.len_pos,
1121                                 len);
1122       _dbus_verbose ("    filled in sub array len to %u at len_pos %d\n",
1123                      len, sub->u.array.len_pos);
1124     }
1125
1126   /* Now get type_pos right for the parent writer. Here are the cases:
1127    *
1128    * Cases !writer->type_pos_is_expectation:
1129    *   (in these cases we want to update to the new insertion point)
1130    * 
1131    * - if we recursed into a STRUCT then we didn't know in advance
1132    *   what the types in the struct would be; so we have to fill in
1133    *   that information now.
1134    *       writer->type_pos = sub->type_pos
1135    * 
1136    * - if we recursed into anything else, we knew the full array
1137    *   type, or knew the single typecode marking VARIANT, so
1138    *   writer->type_pos is already correct.
1139    *       writer->type_pos should remain as-is
1140    *
1141    * - note that the parent is never an ARRAY or VARIANT, if it were
1142    *   then type_pos_is_expectation would be TRUE. The parent
1143    *   is thus known to be a toplevel or STRUCT.
1144    *
1145    * Cases where writer->type_pos_is_expectation:
1146    *   (in these cases we want to update to next expected type to write)
1147    * 
1148    * - we recursed from STRUCT into STRUCT and we didn't increment
1149    *   type_pos in the parent just to stay consistent with the
1150    *   !writer->type_pos_is_expectation case (though we could
1151    *   special-case this in recurse_struct instead if we wanted)
1152    *       writer->type_pos = sub->type_pos
1153    *
1154    * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
1155    *   for parent should have been incremented already
1156    *       writer->type_pos should remain as-is
1157    * 
1158    * - we recursed from ARRAY into a sub-element, so type_pos in the
1159    *   parent is the element type and should remain the element type
1160    *   for the benefit of the next child element
1161    *       writer->type_pos should remain as-is
1162    *
1163    * - we recursed from VARIANT into its value, so type_pos in the
1164    *   parent makes no difference since there's only one value
1165    *   and we just finished writing it and won't use type_pos again
1166    *       writer->type_pos should remain as-is
1167    */
1168   if (sub->container_type == DBUS_TYPE_STRUCT &&
1169       (writer->container_type == DBUS_TYPE_STRUCT ||
1170        writer->container_type == DBUS_TYPE_INVALID))
1171     {
1172       /* Advance the parent to the next struct field */
1173       writer->type_pos = sub->type_pos;
1174     }
1175   
1176   writer->value_pos = sub->value_pos;
1177
1178   _dbus_verbose ("  type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
1179                  writer, writer->type_pos, writer->value_pos,
1180                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
1181   
1182   return TRUE;
1183 }
1184
1185 dbus_bool_t
1186 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
1187                                int             type,
1188                                const void     *value)
1189 {
1190   dbus_bool_t retval;
1191   
1192   /* First ensure that our type realloc will succeed */
1193   if (!_dbus_string_alloc_space (writer->type_str, 1))
1194     return FALSE;
1195
1196   retval = FALSE;
1197
1198   if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
1199     goto out;
1200   
1201   if (!write_or_verify_typecode (writer, type))
1202     _dbus_assert_not_reached ("failed to write typecode after prealloc");
1203   
1204   retval = TRUE;
1205   
1206  out:
1207   _dbus_verbose ("  type writer %p basic type_pos = %d value_pos = %d is_expectation = %d\n",
1208                  writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation);
1209   
1210   return retval;
1211 }
1212
1213 dbus_bool_t
1214 _dbus_type_writer_write_array (DBusTypeWriter *writer,
1215                                int             type,
1216                                const void     *array,
1217                                int             array_len)
1218 {
1219
1220
1221 }
1222
1223 /** @} */ /* end of DBusMarshal group */
1224
1225 #ifdef DBUS_BUILD_TESTS
1226 #include "dbus-test.h"
1227 #include "dbus-list.h"
1228 #include <stdio.h>
1229 #include <stdlib.h>
1230
1231 typedef struct
1232 {
1233   DBusString signature;
1234   DBusString body;
1235 } DataBlock;
1236
1237 typedef struct
1238 {
1239   int saved_sig_len;
1240   int saved_body_len;
1241 } DataBlockState;
1242
1243 static dbus_bool_t
1244 data_block_init (DataBlock *block)
1245 {
1246   if (!_dbus_string_init (&block->signature))
1247     return FALSE;
1248
1249   if (!_dbus_string_init (&block->body))
1250     {
1251       _dbus_string_free (&block->signature);
1252       return FALSE;
1253     }
1254   
1255   return TRUE;
1256 }
1257
1258 static void
1259 data_block_free (DataBlock *block)
1260 {
1261   _dbus_string_free (&block->signature);
1262   _dbus_string_free (&block->body);
1263 }
1264
1265 static void
1266 data_block_save (DataBlock      *block,
1267                  DataBlockState *state)
1268 {
1269   state->saved_sig_len = _dbus_string_get_length (&block->signature);
1270   state->saved_body_len = _dbus_string_get_length (&block->body);
1271 }
1272
1273 static void
1274 data_block_restore (DataBlock      *block,
1275                     DataBlockState *state)
1276 {
1277   /* These set_length should be shortening things so should always work */
1278   
1279   if (!_dbus_string_set_length (&block->signature,
1280                                 state->saved_sig_len))
1281     _dbus_assert_not_reached ("could not restore signature length");
1282   
1283   if (!_dbus_string_set_length (&block->body,
1284                                 state->saved_body_len))
1285     _dbus_assert_not_reached ("could not restore body length");
1286 }
1287
1288 static void
1289 data_block_init_reader_writer (DataBlock      *block,
1290                                int             byte_order,
1291                                DBusTypeReader *reader,
1292                                DBusTypeWriter *writer)
1293 {
1294   _dbus_type_reader_init (reader,
1295                           byte_order,
1296                           &block->signature,
1297                           _dbus_string_get_length (&block->signature),
1298                           &block->body,
1299                           _dbus_string_get_length (&block->body));
1300   
1301   _dbus_type_writer_init (writer,
1302                           byte_order,
1303                           &block->signature,
1304                           _dbus_string_get_length (&block->signature),
1305                           &block->body,
1306                           _dbus_string_get_length (&block->body));
1307 }
1308
1309 static void
1310 real_check_expected_type (DBusTypeReader *reader,
1311                           int             expected,
1312                           const char     *funcname,
1313                           int             line)
1314 {
1315   int t;
1316
1317   t = _dbus_type_reader_get_current_type (reader);
1318   
1319   if (t != expected)
1320     {
1321       _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1322                   _dbus_type_to_string (t),
1323                   _dbus_type_to_string (expected),
1324                   funcname, line);
1325       
1326       exit (1);
1327     }
1328 }
1329
1330 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1331
1332 #define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
1333  {                                                                                      \
1334     _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
1335                               _DBUS_FUNCTION_NAME, __LINE__);                           \
1336     _dbus_assert_not_reached ("test failed");                                           \
1337  }                                                                                      \
1338 } while (0)
1339
1340 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
1341  {                                                                                      \
1342     _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
1343                               _DBUS_FUNCTION_NAME, __LINE__);                           \
1344     _dbus_assert_not_reached ("test failed");                                           \
1345  }                                                                                      \
1346  check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
1347 } while (0)
1348
1349 #define SAMPLE_INT32           12345678
1350 #define SAMPLE_INT32_ALTERNATE 53781429
1351 static dbus_bool_t
1352 write_int32 (DataBlock      *block,
1353              DBusTypeWriter *writer)
1354 {
1355   dbus_int32_t v = SAMPLE_INT32;
1356
1357   return _dbus_type_writer_write_basic (writer,
1358                                         DBUS_TYPE_INT32,
1359                                         &v);
1360 }
1361
1362 static dbus_bool_t
1363 read_int32 (DataBlock      *block,
1364             DBusTypeReader *reader)
1365 {
1366   dbus_int32_t v;
1367
1368   check_expected_type (reader, DBUS_TYPE_INT32);
1369   
1370   _dbus_type_reader_read_basic (reader,
1371                                 (dbus_int32_t*) &v);
1372
1373   _dbus_assert (v == SAMPLE_INT32);
1374
1375   return TRUE;
1376 }
1377
1378 static dbus_bool_t
1379 write_struct_of_int32 (DataBlock      *block,
1380                        DBusTypeWriter *writer)
1381 {
1382   dbus_int32_t v;
1383   DataBlockState saved;
1384   DBusTypeWriter sub;
1385
1386   data_block_save (block, &saved);
1387   
1388   if (!_dbus_type_writer_recurse_struct (writer,
1389                                   &sub))
1390     return FALSE;
1391
1392   v = SAMPLE_INT32;
1393   if (!_dbus_type_writer_write_basic (&sub,
1394                                       DBUS_TYPE_INT32,
1395                                       &v))
1396     {
1397       data_block_restore (block, &saved);
1398       return FALSE;
1399     }
1400
1401   v = SAMPLE_INT32_ALTERNATE;
1402   if (!_dbus_type_writer_write_basic (&sub,
1403                                       DBUS_TYPE_INT32,
1404                                       &v))
1405     {
1406       data_block_restore (block, &saved);
1407       return FALSE;
1408     }
1409
1410   if (!_dbus_type_writer_unrecurse (writer, &sub))
1411     {
1412       data_block_restore (block, &saved);
1413       return FALSE;
1414     }
1415   
1416   return TRUE;
1417 }
1418
1419 static dbus_bool_t
1420 read_struct_of_int32 (DataBlock      *block,
1421                       DBusTypeReader *reader)
1422 {
1423   dbus_int32_t v;
1424   DBusTypeReader sub;
1425
1426   check_expected_type (reader, DBUS_TYPE_STRUCT);
1427   
1428   _dbus_type_reader_recurse (reader, &sub);
1429
1430   check_expected_type (&sub, DBUS_TYPE_INT32);
1431   
1432   _dbus_type_reader_read_basic (&sub,
1433                                 (dbus_int32_t*) &v);
1434
1435   _dbus_assert (v == SAMPLE_INT32);
1436
1437   NEXT_EXPECTING_TRUE (&sub);
1438   check_expected_type (&sub, DBUS_TYPE_INT32);
1439   
1440   _dbus_type_reader_read_basic (&sub,
1441                                 (dbus_int32_t*) &v);
1442
1443   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1444
1445   NEXT_EXPECTING_FALSE (&sub);
1446   
1447   return TRUE;
1448 }
1449
1450 static dbus_bool_t
1451 write_struct_of_structs (DataBlock      *block,
1452                          DBusTypeWriter *writer)
1453 {
1454   DataBlockState saved;
1455   DBusTypeWriter sub;
1456
1457   data_block_save (block, &saved);
1458   
1459   if (!_dbus_type_writer_recurse_struct (writer,
1460                                          &sub))
1461     return FALSE;
1462
1463   if (!write_struct_of_int32 (block, &sub))
1464     {
1465       data_block_restore (block, &saved);
1466       return FALSE;
1467     }
1468   if (!write_struct_of_int32 (block, &sub))
1469     {
1470       data_block_restore (block, &saved);
1471       return FALSE;
1472     }
1473   if (!write_struct_of_int32 (block, &sub))
1474     {
1475       data_block_restore (block, &saved);
1476       return FALSE;
1477     }
1478
1479   if (!_dbus_type_writer_unrecurse (writer, &sub))
1480     {
1481       data_block_restore (block, &saved);
1482       return FALSE;
1483     }
1484   
1485   return TRUE;
1486 }
1487
1488 static dbus_bool_t
1489 read_struct_of_structs (DataBlock      *block,
1490                         DBusTypeReader *reader)
1491 {
1492   DBusTypeReader sub;
1493   
1494   check_expected_type (reader, DBUS_TYPE_STRUCT);
1495   
1496   _dbus_type_reader_recurse (reader, &sub);
1497
1498   if (!read_struct_of_int32 (block, &sub))
1499     return FALSE;
1500
1501   NEXT_EXPECTING_TRUE (&sub);
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_FALSE (&sub);
1510   
1511   return TRUE;
1512 }
1513
1514 static dbus_bool_t
1515 write_struct_of_structs_of_structs (DataBlock      *block,
1516                                     DBusTypeWriter *writer)
1517 {
1518   DataBlockState saved;
1519   DBusTypeWriter sub;
1520
1521   data_block_save (block, &saved);
1522   
1523   if (!_dbus_type_writer_recurse_struct (writer,
1524                                          &sub))
1525     return FALSE;
1526
1527   if (!write_struct_of_structs (block, &sub))
1528     {
1529       data_block_restore (block, &saved);
1530       return FALSE;
1531     }
1532   if (!write_struct_of_structs (block, &sub))
1533     {
1534       data_block_restore (block, &saved);
1535       return FALSE;
1536     }
1537
1538   if (!_dbus_type_writer_unrecurse (writer, &sub))
1539     {
1540       data_block_restore (block, &saved);
1541       return FALSE;
1542     }
1543   
1544   return TRUE;
1545 }
1546
1547 static dbus_bool_t
1548 read_struct_of_structs_of_structs (DataBlock      *block,
1549                                    DBusTypeReader *reader)
1550 {
1551   DBusTypeReader sub;
1552   
1553   check_expected_type (reader, DBUS_TYPE_STRUCT);
1554   
1555   _dbus_type_reader_recurse (reader, &sub);
1556
1557   if (!read_struct_of_structs (block, &sub))
1558     return FALSE;
1559
1560   NEXT_EXPECTING_TRUE (&sub);
1561   if (!read_struct_of_structs (block, &sub))
1562     return FALSE;
1563
1564   NEXT_EXPECTING_FALSE (&sub);
1565   
1566   return TRUE;
1567 }
1568
1569 static dbus_bool_t
1570 write_array_of_int32 (DataBlock      *block,
1571                       DBusTypeWriter *writer)
1572 {
1573   dbus_int32_t v;
1574   DataBlockState saved;
1575   DBusTypeWriter sub;
1576
1577   data_block_save (block, &saved);
1578   
1579   if (!_dbus_type_writer_recurse_array (writer,
1580                                         DBUS_TYPE_INT32_AS_STRING,
1581                                         &sub))
1582     return FALSE;
1583
1584   v = SAMPLE_INT32_ALTERNATE;
1585   if (!_dbus_type_writer_write_basic (&sub,
1586                                       DBUS_TYPE_INT32,
1587                                       &v))
1588     {
1589       data_block_restore (block, &saved);
1590       return FALSE;
1591     }
1592
1593   v = SAMPLE_INT32;
1594   if (!_dbus_type_writer_write_basic (&sub,
1595                                       DBUS_TYPE_INT32,
1596                                       &v))
1597     {
1598       data_block_restore (block, &saved);
1599       return FALSE;
1600     }
1601
1602   v = SAMPLE_INT32;
1603   if (!_dbus_type_writer_write_basic (&sub,
1604                                       DBUS_TYPE_INT32,
1605                                       &v))
1606     {
1607       data_block_restore (block, &saved);
1608       return FALSE;
1609     }
1610   
1611   if (!_dbus_type_writer_unrecurse (writer, &sub))
1612     {
1613       data_block_restore (block, &saved);
1614       return FALSE;
1615     }
1616   
1617   return TRUE;
1618 }
1619
1620 static dbus_bool_t
1621 read_array_of_int32 (DataBlock      *block,
1622                      DBusTypeReader *reader)
1623 {
1624   dbus_int32_t v;
1625   DBusTypeReader sub;
1626
1627   check_expected_type (reader, DBUS_TYPE_ARRAY);
1628   
1629   _dbus_type_reader_recurse (reader, &sub);
1630
1631   check_expected_type (&sub, DBUS_TYPE_INT32);
1632   
1633   _dbus_type_reader_read_basic (&sub,
1634                                 (dbus_int32_t*) &v);
1635
1636   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1637
1638   NEXT_EXPECTING_TRUE (&sub);
1639   check_expected_type (&sub, DBUS_TYPE_INT32);
1640   
1641   _dbus_type_reader_read_basic (&sub,
1642                                 (dbus_int32_t*) &v);
1643
1644   _dbus_assert (v == SAMPLE_INT32);
1645
1646   NEXT_EXPECTING_TRUE (&sub);
1647   check_expected_type (&sub, DBUS_TYPE_INT32);
1648   
1649   _dbus_type_reader_read_basic (&sub,
1650                                 (dbus_int32_t*) &v);
1651
1652   _dbus_assert (v == SAMPLE_INT32);
1653
1654   NEXT_EXPECTING_FALSE (&sub);
1655   
1656   return TRUE;
1657 }
1658
1659
1660 static dbus_bool_t
1661 write_array_of_int32_empty (DataBlock      *block,
1662                             DBusTypeWriter *writer)
1663 {
1664   DataBlockState saved;
1665   DBusTypeWriter sub;
1666
1667   data_block_save (block, &saved);
1668   
1669   if (!_dbus_type_writer_recurse_array (writer,
1670                                         DBUS_TYPE_INT32_AS_STRING,
1671                                         &sub))
1672     return FALSE;
1673   
1674   if (!_dbus_type_writer_unrecurse (writer, &sub))
1675     {
1676       data_block_restore (block, &saved);
1677       return FALSE;
1678     }
1679   
1680   return TRUE;
1681 }
1682
1683 static dbus_bool_t
1684 read_array_of_int32_empty (DataBlock      *block,
1685                            DBusTypeReader *reader)
1686 {
1687   check_expected_type (reader, DBUS_TYPE_ARRAY);
1688
1689   /* We are iterating over values not types. Thus we can't recurse
1690    * into the array
1691    */
1692   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1693   
1694   return TRUE;
1695 }
1696
1697 static dbus_bool_t
1698 write_array_of_array_of_int32 (DataBlock      *block,
1699                                DBusTypeWriter *writer)
1700 {
1701   DataBlockState saved;
1702   DBusTypeWriter sub;
1703
1704   data_block_save (block, &saved);
1705   
1706   if (!_dbus_type_writer_recurse_array (writer,
1707                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1708                                         &sub))
1709     return FALSE;
1710
1711   if (!write_array_of_int32 (block, &sub))
1712     {
1713       data_block_restore (block, &saved);
1714       return FALSE;
1715     }
1716
1717   if (!write_array_of_int32 (block, &sub))
1718     {
1719       data_block_restore (block, &saved);
1720       return FALSE;
1721     }
1722
1723   if (!write_array_of_int32_empty (block, &sub))
1724     {
1725       data_block_restore (block, &saved);
1726       return FALSE;
1727     }
1728   
1729   if (!write_array_of_int32 (block, &sub))
1730     {
1731       data_block_restore (block, &saved);
1732       return FALSE;
1733     }
1734   
1735   if (!_dbus_type_writer_unrecurse (writer, &sub))
1736     {
1737       data_block_restore (block, &saved);
1738       return FALSE;
1739     }
1740   
1741   return TRUE;
1742 }
1743
1744 static dbus_bool_t
1745 read_array_of_array_of_int32 (DataBlock      *block,
1746                               DBusTypeReader *reader)
1747 {
1748   DBusTypeReader sub;
1749   
1750   check_expected_type (reader, DBUS_TYPE_ARRAY);
1751   
1752   _dbus_type_reader_recurse (reader, &sub);
1753
1754   if (!read_array_of_int32 (block, &sub))
1755     return FALSE;
1756
1757   NEXT_EXPECTING_TRUE (&sub);
1758   if (!read_array_of_int32 (block, &sub))
1759     return FALSE;
1760
1761   NEXT_EXPECTING_TRUE (&sub);
1762   if (!read_array_of_int32_empty (block, &sub))
1763     return FALSE;
1764   
1765   NEXT_EXPECTING_TRUE (&sub);
1766   if (!read_array_of_int32 (block, &sub))
1767     return FALSE;
1768
1769   NEXT_EXPECTING_FALSE (&sub);
1770   
1771   return TRUE;
1772 }
1773
1774
1775 static dbus_bool_t
1776 write_array_of_array_of_int32_empty (DataBlock      *block,
1777                                      DBusTypeWriter *writer)
1778 {
1779   DataBlockState saved;
1780   DBusTypeWriter sub;
1781
1782   data_block_save (block, &saved);
1783   
1784   if (!_dbus_type_writer_recurse_array (writer,
1785                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1786                                         &sub))
1787     return FALSE;
1788
1789   if (!_dbus_type_writer_unrecurse (writer, &sub))
1790     {
1791       data_block_restore (block, &saved);
1792       return FALSE;
1793     }
1794   
1795   return TRUE;
1796 }
1797
1798 static dbus_bool_t
1799 read_array_of_array_of_int32_empty (DataBlock      *block,
1800                                     DBusTypeReader *reader)
1801 {  
1802   check_expected_type (reader, DBUS_TYPE_ARRAY);
1803
1804   /* We are iterating over values, not types. Thus
1805    * we can't recurse in here.
1806    */
1807   
1808   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1809   
1810   return TRUE;
1811 }
1812
1813 static dbus_bool_t
1814 write_array_of_array_of_array_of_int32 (DataBlock      *block,
1815                                         DBusTypeWriter *writer)
1816 {
1817   DataBlockState saved;
1818   DBusTypeWriter sub;
1819
1820   data_block_save (block, &saved);
1821   
1822   if (!_dbus_type_writer_recurse_array (writer,
1823                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1824                                         &sub))
1825     return FALSE;
1826
1827   if (!write_array_of_array_of_int32 (block, &sub))
1828     {
1829       data_block_restore (block, &saved);
1830       return FALSE;
1831     }
1832
1833   if (!write_array_of_array_of_int32 (block, &sub))
1834     {
1835       data_block_restore (block, &saved);
1836       return FALSE;
1837     }
1838
1839   if (!write_array_of_array_of_int32_empty (block, &sub))
1840     {
1841       data_block_restore (block, &saved);
1842       return FALSE;
1843     }
1844   
1845   if (!_dbus_type_writer_unrecurse (writer, &sub))
1846     {
1847       data_block_restore (block, &saved);
1848       return FALSE;
1849     }
1850   
1851   return TRUE;
1852 }
1853
1854 static dbus_bool_t
1855 read_array_of_array_of_array_of_int32 (DataBlock      *block,
1856                                        DBusTypeReader *reader)
1857 {
1858   DBusTypeReader sub;
1859   
1860   check_expected_type (reader, DBUS_TYPE_ARRAY);
1861   
1862   _dbus_type_reader_recurse (reader, &sub);
1863
1864   if (!read_array_of_array_of_int32 (block, &sub))
1865     return FALSE;
1866
1867   NEXT_EXPECTING_TRUE (&sub);
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_empty (block, &sub))
1873     return FALSE;
1874
1875   NEXT_EXPECTING_FALSE (&sub);
1876   
1877   return TRUE;
1878 }
1879
1880 static dbus_bool_t
1881 write_struct_of_array_of_int32 (DataBlock      *block,
1882                                 DBusTypeWriter *writer)
1883 {
1884   DataBlockState saved;
1885   DBusTypeWriter sub;
1886
1887   data_block_save (block, &saved);
1888   
1889   if (!_dbus_type_writer_recurse_struct (writer,
1890                                          &sub))
1891     return FALSE;
1892
1893   if (!write_array_of_int32 (block, &sub))
1894     {
1895       data_block_restore (block, &saved);
1896       return FALSE;
1897     }
1898
1899   if (!write_array_of_int32_empty (block, &sub))
1900     {
1901       data_block_restore (block, &saved);
1902       return FALSE;
1903     }
1904       
1905   if (!_dbus_type_writer_unrecurse (writer, &sub))
1906     {
1907       data_block_restore (block, &saved);
1908       return FALSE;
1909     }
1910   
1911   return TRUE;
1912 }
1913
1914 static dbus_bool_t
1915 read_struct_of_array_of_int32 (DataBlock      *block,
1916                                DBusTypeReader *reader)
1917 {
1918   DBusTypeReader sub;
1919
1920   check_expected_type (reader, DBUS_TYPE_STRUCT);
1921   
1922   _dbus_type_reader_recurse (reader, &sub);
1923
1924   check_expected_type (&sub, DBUS_TYPE_ARRAY);
1925
1926   if (!read_array_of_int32 (block, &sub))
1927     return FALSE;
1928
1929   NEXT_EXPECTING_TRUE (&sub);
1930   if (!read_array_of_int32_empty (block, &sub))
1931     return FALSE;
1932   
1933   NEXT_EXPECTING_FALSE (&sub);
1934   
1935   return TRUE;
1936 }
1937
1938 static dbus_bool_t
1939 write_struct_of_struct_of_array_of_int32 (DataBlock      *block,
1940                                           DBusTypeWriter *writer)
1941 {
1942   DataBlockState saved;
1943   DBusTypeWriter sub;
1944
1945   data_block_save (block, &saved);
1946   
1947   if (!_dbus_type_writer_recurse_struct (writer,
1948                                          &sub))
1949     return FALSE;
1950
1951   if (!write_struct_of_array_of_int32 (block, &sub))
1952     {
1953       data_block_restore (block, &saved);
1954       return FALSE;
1955     }
1956   if (!write_struct_of_array_of_int32 (block, &sub))
1957     {
1958       data_block_restore (block, &saved);
1959       return FALSE;
1960     }
1961   if (!write_struct_of_array_of_int32 (block, &sub))
1962     {
1963       data_block_restore (block, &saved);
1964       return FALSE;
1965     }
1966
1967   if (!_dbus_type_writer_unrecurse (writer, &sub))
1968     {
1969       data_block_restore (block, &saved);
1970       return FALSE;
1971     }
1972   
1973   return TRUE;
1974 }
1975
1976 static dbus_bool_t
1977 read_struct_of_struct_of_array_of_int32 (DataBlock      *block,
1978                                          DBusTypeReader *reader)
1979 {
1980   DBusTypeReader sub;
1981   
1982   check_expected_type (reader, DBUS_TYPE_STRUCT);
1983   
1984   _dbus_type_reader_recurse (reader, &sub);
1985
1986   if (!read_struct_of_array_of_int32 (block, &sub))
1987     return FALSE;
1988
1989   NEXT_EXPECTING_TRUE (&sub);
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_FALSE (&sub);
1998   
1999   return TRUE;
2000 }
2001
2002 static dbus_bool_t
2003 write_array_of_struct_of_int32 (DataBlock      *block,
2004                                 DBusTypeWriter *writer)
2005 {
2006   DataBlockState saved;
2007   DBusTypeWriter sub;
2008
2009   data_block_save (block, &saved);
2010
2011   if (!_dbus_type_writer_recurse_array (writer,
2012                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2013                                         DBUS_TYPE_INT32_AS_STRING
2014                                         DBUS_TYPE_INT32_AS_STRING
2015                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2016                                         &sub))
2017     return FALSE;
2018
2019   if (!write_struct_of_int32 (block, &sub))
2020     {
2021       data_block_restore (block, &saved);
2022       return FALSE;
2023     }
2024
2025   if (!write_struct_of_int32 (block, &sub))
2026     {
2027       data_block_restore (block, &saved);
2028       return FALSE;
2029     }
2030
2031   if (!write_struct_of_int32 (block, &sub))
2032     {
2033       data_block_restore (block, &saved);
2034       return FALSE;
2035     }
2036   
2037   if (!_dbus_type_writer_unrecurse (writer, &sub))
2038     {
2039       data_block_restore (block, &saved);
2040       return FALSE;
2041     }
2042   
2043   return TRUE;
2044 }
2045
2046 static dbus_bool_t
2047 read_array_of_struct_of_int32 (DataBlock      *block,
2048                                DBusTypeReader *reader)
2049 {
2050   DBusTypeReader sub;
2051
2052   check_expected_type (reader, DBUS_TYPE_ARRAY);
2053   
2054   _dbus_type_reader_recurse (reader, &sub);
2055
2056   check_expected_type (&sub, DBUS_TYPE_STRUCT);
2057
2058   if (!read_struct_of_int32 (block, &sub))
2059     return FALSE;
2060   
2061   NEXT_EXPECTING_TRUE (&sub);
2062
2063   if (!read_struct_of_int32 (block, &sub))
2064     return FALSE;
2065   
2066   NEXT_EXPECTING_TRUE (&sub);
2067
2068   if (!read_struct_of_int32 (block, &sub))
2069     return FALSE;
2070   
2071   NEXT_EXPECTING_FALSE (&sub);
2072   
2073   return TRUE;
2074 }
2075
2076
2077 static dbus_bool_t
2078 write_array_of_array_of_struct_of_int32 (DataBlock      *block,
2079                                          DBusTypeWriter *writer)
2080 {
2081   DataBlockState saved;
2082   DBusTypeWriter sub;
2083
2084   data_block_save (block, &saved);
2085
2086   if (!_dbus_type_writer_recurse_array (writer,
2087                                         DBUS_TYPE_ARRAY_AS_STRING
2088                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2089                                         DBUS_TYPE_INT32_AS_STRING
2090                                         DBUS_TYPE_INT32_AS_STRING
2091                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2092                                         &sub))
2093     return FALSE;
2094
2095   if (!write_array_of_struct_of_int32 (block, &sub))
2096     {
2097       data_block_restore (block, &saved);
2098       return FALSE;
2099     }
2100
2101   if (!write_array_of_struct_of_int32 (block, &sub))
2102     {
2103       data_block_restore (block, &saved);
2104       return FALSE;
2105     }
2106
2107   if (!write_array_of_struct_of_int32 (block, &sub))
2108     {
2109       data_block_restore (block, &saved);
2110       return FALSE;
2111     }
2112   
2113   if (!_dbus_type_writer_unrecurse (writer, &sub))
2114     {
2115       data_block_restore (block, &saved);
2116       return FALSE;
2117     }
2118   
2119   return TRUE;
2120 }
2121
2122 static dbus_bool_t
2123 read_array_of_array_of_struct_of_int32 (DataBlock      *block,
2124                                         DBusTypeReader *reader)
2125 {
2126   DBusTypeReader sub;
2127
2128   check_expected_type (reader, DBUS_TYPE_ARRAY);
2129   
2130   _dbus_type_reader_recurse (reader, &sub);
2131
2132   check_expected_type (&sub, DBUS_TYPE_ARRAY);
2133
2134   if (!read_array_of_struct_of_int32 (block, &sub))
2135     return FALSE;
2136   
2137   NEXT_EXPECTING_TRUE (&sub);
2138
2139   if (!read_array_of_struct_of_int32 (block, &sub))
2140     return FALSE;
2141   
2142   NEXT_EXPECTING_TRUE (&sub);
2143
2144   if (!read_array_of_struct_of_int32 (block, &sub))
2145     return FALSE;
2146   
2147   NEXT_EXPECTING_FALSE (&sub);
2148   
2149   return TRUE;
2150 }
2151
2152 static dbus_bool_t
2153 write_struct_of_array_of_struct_of_int32 (DataBlock      *block,
2154                                           DBusTypeWriter *writer)
2155 {
2156   DataBlockState saved;
2157   DBusTypeWriter sub;
2158
2159   data_block_save (block, &saved);
2160   
2161   if (!_dbus_type_writer_recurse_struct (writer,
2162                                          &sub))
2163     return FALSE;
2164
2165   if (!write_array_of_struct_of_int32 (block, &sub))
2166     {
2167       data_block_restore (block, &saved);
2168       return FALSE;
2169     }
2170   if (!write_array_of_struct_of_int32 (block, &sub))
2171     {
2172       data_block_restore (block, &saved);
2173       return FALSE;
2174     }
2175   if (!write_array_of_struct_of_int32 (block, &sub))
2176     {
2177       data_block_restore (block, &saved);
2178       return FALSE;
2179     }
2180
2181   if (!_dbus_type_writer_unrecurse (writer, &sub))
2182     {
2183       data_block_restore (block, &saved);
2184       return FALSE;
2185     }
2186   
2187   return TRUE;
2188 }
2189
2190 static dbus_bool_t
2191 read_struct_of_array_of_struct_of_int32 (DataBlock      *block,
2192                                          DBusTypeReader *reader)
2193 {
2194   DBusTypeReader sub;
2195   
2196   check_expected_type (reader, DBUS_TYPE_STRUCT);
2197   
2198   _dbus_type_reader_recurse (reader, &sub);
2199   
2200   if (!read_array_of_struct_of_int32 (block, &sub))
2201     return FALSE;
2202
2203   NEXT_EXPECTING_TRUE (&sub);
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_FALSE (&sub);
2212   
2213   return TRUE;
2214 }
2215
2216 static dbus_bool_t
2217 write_array_of_struct_of_array_of_int32 (DataBlock      *block,
2218                                          DBusTypeWriter *writer)
2219 {
2220   DataBlockState saved;
2221   DBusTypeWriter sub;
2222
2223   data_block_save (block, &saved);
2224
2225   if (!_dbus_type_writer_recurse_array (writer,
2226                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
2227                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2228                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING
2229                                         DBUS_STRUCT_END_CHAR_AS_STRING,
2230                                         &sub))
2231     return FALSE;
2232
2233   if (!write_struct_of_array_of_int32 (block, &sub))
2234     {
2235       data_block_restore (block, &saved);
2236       return FALSE;
2237     }
2238
2239   if (!write_struct_of_array_of_int32 (block, &sub))
2240     {
2241       data_block_restore (block, &saved);
2242       return FALSE;
2243     }
2244
2245   if (!write_struct_of_array_of_int32 (block, &sub))
2246     {
2247       data_block_restore (block, &saved);
2248       return FALSE;
2249     }
2250   
2251   if (!_dbus_type_writer_unrecurse (writer, &sub))
2252     {
2253       data_block_restore (block, &saved);
2254       return FALSE;
2255     }
2256   
2257   return TRUE;
2258 }
2259
2260 static dbus_bool_t
2261 read_array_of_struct_of_array_of_int32 (DataBlock      *block,
2262                                         DBusTypeReader *reader)
2263 {
2264   DBusTypeReader sub;
2265
2266   check_expected_type (reader, DBUS_TYPE_ARRAY);
2267   
2268   _dbus_type_reader_recurse (reader, &sub);
2269
2270   check_expected_type (&sub, DBUS_TYPE_STRUCT);
2271
2272   if (!read_struct_of_array_of_int32 (block, &sub))
2273     return FALSE;
2274   
2275   NEXT_EXPECTING_TRUE (&sub);
2276
2277   if (!read_struct_of_array_of_int32 (block, &sub))
2278     return FALSE;
2279   
2280   NEXT_EXPECTING_TRUE (&sub);
2281
2282   if (!read_struct_of_array_of_int32 (block, &sub))
2283     return FALSE;
2284   
2285   NEXT_EXPECTING_FALSE (&sub);
2286   
2287   return TRUE;
2288 }
2289
2290 typedef enum {
2291   ITEM_INVALID = -1,
2292
2293   ITEM_INT32 = 0,
2294
2295   ITEM_STRUCT_OF_INT32,
2296   ITEM_STRUCT_OF_STRUCTS,
2297   ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2298
2299   ITEM_ARRAY_OF_INT32,
2300   ITEM_ARRAY_OF_INT32_EMPTY,
2301   ITEM_ARRAY_OF_ARRAY_OF_INT32,
2302   ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2303   ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2304
2305   ITEM_STRUCT_OF_ARRAY_OF_INT32,
2306   ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2307
2308   ITEM_ARRAY_OF_STRUCT_OF_INT32,
2309   ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2310
2311   ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2312   ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2313
2314   ITEM_LAST
2315 } WhichItem;
2316
2317
2318 typedef dbus_bool_t (* WriteItemFunc) (DataBlock      *block,
2319                                        DBusTypeWriter *writer);
2320 typedef dbus_bool_t (* ReadItemFunc)  (DataBlock      *block,
2321                                        DBusTypeReader *reader);
2322
2323 typedef struct
2324 {
2325   const char *desc;
2326   WhichItem which;
2327   WriteItemFunc write_item_func;
2328   ReadItemFunc read_item_func;
2329 } CheckMarshalItem;
2330
2331 static CheckMarshalItem items[] = {
2332   { "int32",
2333     ITEM_INT32, write_int32, read_int32 },
2334   { "struct with two int32",
2335     ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
2336   { "struct with three structs of two int32",
2337     ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
2338   { "struct of two structs of three structs of two int32",
2339     ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
2340     write_struct_of_structs_of_structs,
2341     read_struct_of_structs_of_structs },
2342   { "array of int32",
2343     ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
2344   { "empty array of int32",
2345     ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
2346   { "array of array of int32",
2347     ITEM_ARRAY_OF_ARRAY_OF_INT32,
2348     write_array_of_array_of_int32, read_array_of_array_of_int32 },
2349   { "empty array of array of int32",
2350     ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
2351     write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
2352   { "array of array of array of int32",
2353     ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
2354     write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
2355   { "struct of array of int32",
2356     ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
2357   { "struct of struct of array of int32",
2358     ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32,
2359     write_struct_of_struct_of_array_of_int32, read_struct_of_struct_of_array_of_int32 },
2360   { "array of struct of int32",
2361     ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
2362   { "array of array of struct of int32",
2363     ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32,
2364     write_array_of_array_of_struct_of_int32, read_array_of_array_of_struct_of_int32 },
2365
2366   { "struct of array of struct of int32",
2367     ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32,
2368     write_struct_of_array_of_struct_of_int32, read_struct_of_array_of_struct_of_int32 },
2369   { "array of struct of array of int32",
2370     ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32,
2371     write_array_of_struct_of_array_of_int32, read_array_of_struct_of_array_of_int32 },
2372 };
2373
2374 typedef struct
2375 {
2376   /* Array of items from the above items[]; -1 terminated */
2377   int items[20];
2378 } TestRun;
2379
2380 static TestRun runs[] = {
2381   { { ITEM_INVALID } },
2382
2383   /* INT32 */
2384   { { ITEM_INT32, ITEM_INVALID } },
2385   { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2386   { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
2387
2388   /* STRUCT_OF_INT32 */
2389   { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2390   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2391   { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2392   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2393   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
2394
2395   /* STRUCT_OF_STRUCTS */
2396   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2397   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2398   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2399   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2400   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2401   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
2402
2403   /* STRUCT_OF_STRUCTS_OF_STRUCTS */
2404   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2405   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2406   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2407   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2408   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2409   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2410
2411   /* ARRAY_OF_INT32 */
2412   { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2413   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2414   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2415   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2416   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2417   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2418   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2419   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2420   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2421   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
2422
2423   /* ARRAY_OF_ARRAY_OF_INT32 */
2424   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2425   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2426   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2427   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2428   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2429   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2430   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2431   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2432   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2433   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2434
2435   /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
2436   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2437   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2438   { { 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 } },
2439   { { 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 } },
2440   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
2441   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2442   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2443   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
2444   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2445   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2446
2447   /* STRUCT_OF_ARRAY_OF_INT32 */
2448   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2449   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2450   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2451   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2452   { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2453   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2454
2455   /* STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32 */
2456   { { ITEM_STRUCT_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2457   
2458   /* ARRAY_OF_STRUCT_OF_INT32 */
2459   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2460   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2461   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2462   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2463   { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2464   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2465
2466   /* ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32 */
2467   { { ITEM_ARRAY_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2468   
2469   /* STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32 */
2470   { { ITEM_STRUCT_OF_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
2471   
2472   /* ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32 */
2473   { { ITEM_ARRAY_OF_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
2474   
2475 };
2476
2477 static dbus_bool_t
2478 perform_one_run (DataBlock *block,
2479                  int        byte_order,
2480                  TestRun   *run)
2481 {
2482   DBusTypeReader reader;
2483   DBusTypeWriter writer;
2484   int i;
2485   DataBlockState saved;
2486   dbus_bool_t retval;
2487
2488   retval = FALSE;
2489
2490   {
2491     _dbus_verbose ("run byteorder %s items ",
2492                    byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
2493     i = 0;
2494     while (run->items[i] != ITEM_INVALID)
2495       {
2496         CheckMarshalItem *item = &items[run->items[i]];
2497         
2498         _dbus_verbose ("%s ", item->desc);
2499         ++i;
2500       }
2501     _dbus_verbose (" = %d items\n", i);
2502   }
2503   
2504   data_block_save (block, &saved);
2505   
2506   data_block_init_reader_writer (block, 
2507                                  byte_order,
2508                                  &reader, &writer);
2509
2510   i = 0;
2511   while (run->items[i] != ITEM_INVALID)
2512     {
2513       CheckMarshalItem *item = &items[run->items[i]];
2514
2515       _dbus_verbose (">>writing %s\n", item->desc);
2516       
2517       if (!(* item->write_item_func) (block, &writer))
2518         goto out;
2519       ++i;
2520     }
2521
2522   i = 0;
2523   while (run->items[i] != ITEM_INVALID)
2524     {
2525       CheckMarshalItem *item = &items[run->items[i]];
2526
2527       _dbus_verbose (">>data for reading %s\n", item->desc);
2528       
2529       _dbus_verbose_bytes_of_string (reader.type_str, 0,
2530                                      _dbus_string_get_length (reader.type_str));
2531       _dbus_verbose_bytes_of_string (reader.value_str, 0,
2532                                      _dbus_string_get_length (reader.value_str));
2533       
2534       _dbus_verbose (">>reading %s\n", item->desc);
2535       
2536       if (!(* item->read_item_func) (block, &reader))
2537         goto out;
2538
2539       _dbus_type_reader_next (&reader);
2540       
2541       ++i;
2542     }
2543   
2544   retval = TRUE;
2545   
2546  out:
2547   data_block_restore (block, &saved);
2548   return retval;
2549 }
2550
2551 static dbus_bool_t
2552 perform_all_runs (int byte_order,
2553                   int initial_offset)
2554 {
2555   int i;
2556   DataBlock block;
2557   dbus_bool_t retval;
2558
2559   retval = FALSE;
2560   
2561   if (!data_block_init (&block))
2562     return FALSE;
2563
2564   if (!_dbus_string_lengthen (&block.signature, initial_offset))
2565     goto out;
2566   
2567   if (!_dbus_string_lengthen (&block.body, initial_offset))
2568     goto out;
2569   
2570   i = 0;
2571   while (i < _DBUS_N_ELEMENTS (runs))
2572     {
2573       if (!perform_one_run (&block, byte_order, &runs[i]))
2574         goto out;
2575       
2576       ++i;
2577     }
2578
2579   retval = TRUE;
2580   
2581  out:
2582   data_block_free (&block);
2583   
2584   return retval;
2585 }
2586
2587 static dbus_bool_t
2588 perform_all_items (int byte_order,
2589                    int initial_offset)
2590 {
2591   int i;
2592   DataBlock block;
2593   dbus_bool_t retval;
2594   TestRun run;
2595
2596   retval = FALSE;
2597   
2598   if (!data_block_init (&block))
2599     return FALSE;
2600
2601
2602   if (!_dbus_string_lengthen (&block.signature, initial_offset))
2603     goto out;
2604   
2605   if (!_dbus_string_lengthen (&block.body, initial_offset))
2606     goto out;
2607
2608   /* Create a run containing all the items */
2609   i = 0;
2610   while (i < _DBUS_N_ELEMENTS (items))
2611     {
2612       _dbus_assert (i == items[i].which);
2613       
2614       run.items[i] = items[i].which;
2615       
2616       ++i;
2617     }
2618   
2619   run.items[i] = ITEM_INVALID;
2620
2621   if (!perform_one_run (&block, byte_order, &run))
2622     goto out;  
2623   
2624   retval = TRUE;
2625   
2626  out:
2627   data_block_free (&block);
2628   
2629   return retval;
2630 }
2631
2632 static dbus_bool_t
2633 recursive_marshal_test_iteration (void *data)
2634 {
2635   int i;
2636
2637   i = 0;
2638   while (i < 18)
2639     {
2640       if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
2641         return FALSE;
2642       if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
2643         return FALSE;
2644       if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
2645         return FALSE;
2646       if (!perform_all_items (DBUS_BIG_ENDIAN, i))
2647         return FALSE;
2648       
2649       ++i;
2650     }
2651
2652   return TRUE;
2653 }
2654
2655 typedef struct TestTypeNode               TestTypeNode;
2656 typedef struct TestTypeNodeClass          TestTypeNodeClass;
2657 typedef struct TestTypeNodeContainer      TestTypeNodeContainer;
2658 typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
2659
2660 struct TestTypeNode
2661 {
2662   const TestTypeNodeClass *klass;
2663   void *data; /* some data, such as the particular value we wrote that we expect to read again */
2664 };
2665
2666 struct TestTypeNodeContainer
2667 {
2668   TestTypeNode base;
2669   DBusList    *children;
2670 };
2671
2672 struct TestTypeNodeClass
2673 {
2674   int typecode;
2675
2676   int instance_size;
2677   
2678   dbus_bool_t   (* construct)     (TestTypeNode   *node);
2679   void          (* destroy)       (TestTypeNode   *node);
2680   
2681   dbus_bool_t (* write_value)     (TestTypeNode   *node,
2682                                    DataBlock      *block,
2683                                    DBusTypeWriter *writer);
2684   dbus_bool_t (* read_value)      (TestTypeNode   *node,
2685                                    DataBlock      *block,
2686                                    DBusTypeReader *reader);
2687   dbus_bool_t (* build_signature) (TestTypeNode   *node,
2688                                    DBusString     *str);
2689 };
2690
2691 struct TestTypeNodeContainerClass
2692 {
2693   TestTypeNodeClass base;
2694 };
2695
2696 static dbus_bool_t int32_write_value        (TestTypeNode   *node,
2697                                              DataBlock      *block,
2698                                              DBusTypeWriter *writer);
2699 static dbus_bool_t int32_read_value         (TestTypeNode   *node,
2700                                              DataBlock      *block,
2701                                              DBusTypeReader *reader);
2702 static dbus_bool_t struct_1_write_value     (TestTypeNode   *node,
2703                                              DataBlock      *block,
2704                                              DBusTypeWriter *writer);
2705 static dbus_bool_t struct_1_read_value      (TestTypeNode   *node,
2706                                              DataBlock      *block,
2707                                              DBusTypeReader *reader);
2708 static dbus_bool_t struct_1_build_signature (TestTypeNode   *node,
2709                                              DBusString     *str);
2710 static dbus_bool_t struct_2_write_value     (TestTypeNode   *node,
2711                                              DataBlock      *block,
2712                                              DBusTypeWriter *writer);
2713 static dbus_bool_t struct_2_read_value      (TestTypeNode   *node,
2714                                              DataBlock      *block,
2715                                              DBusTypeReader *reader);
2716 static dbus_bool_t struct_2_build_signature (TestTypeNode   *node,
2717                                              DBusString     *str);
2718 static dbus_bool_t array_build_signature    (TestTypeNode   *node,
2719                                              DBusString     *str);
2720 static dbus_bool_t array_1_write_value      (TestTypeNode   *node,
2721                                              DataBlock      *block,
2722                                              DBusTypeWriter *writer);
2723 static dbus_bool_t array_1_read_value       (TestTypeNode   *node,
2724                                              DataBlock      *block,
2725                                              DBusTypeReader *reader);
2726 static dbus_bool_t array_0_write_value      (TestTypeNode   *node,
2727                                              DataBlock      *block,
2728                                              DBusTypeWriter *writer);
2729 static dbus_bool_t array_0_read_value       (TestTypeNode   *node,
2730                                              DataBlock      *block,
2731                                              DBusTypeReader *reader);
2732 static dbus_bool_t array_2_write_value      (TestTypeNode   *node,
2733                                              DataBlock      *block,
2734                                              DBusTypeWriter *writer);
2735 static dbus_bool_t array_2_read_value       (TestTypeNode   *node,
2736                                              DataBlock      *block,
2737                                              DBusTypeReader *reader);
2738
2739 static void        container_destroy        (TestTypeNode   *node);
2740
2741
2742 static const TestTypeNodeClass int32_class = {
2743   DBUS_TYPE_INT32,
2744   sizeof (TestTypeNode),
2745   NULL,
2746   NULL,
2747   int32_write_value,
2748   int32_read_value,
2749   NULL
2750 };
2751
2752 static const TestTypeNodeClass uint32_class = {
2753   DBUS_TYPE_UINT32,
2754   sizeof (TestTypeNode),
2755   NULL,
2756   NULL,
2757   int32_write_value, /* recycle from int32 */
2758   int32_read_value,  /* recycle from int32 */
2759   NULL
2760 };
2761
2762 static const TestTypeNodeClass struct_1_class = {
2763   DBUS_TYPE_STRUCT,
2764   sizeof (TestTypeNodeContainer),
2765   NULL,
2766   container_destroy,
2767   struct_1_write_value,
2768   struct_1_read_value,
2769   struct_1_build_signature
2770 };
2771
2772 static const TestTypeNodeClass struct_2_class = {
2773   DBUS_TYPE_STRUCT,
2774   sizeof (TestTypeNodeContainer),
2775   NULL,
2776   container_destroy,
2777   struct_2_write_value,
2778   struct_2_read_value,
2779   struct_2_build_signature
2780 };
2781
2782 static const TestTypeNodeClass array_0_class = {
2783   DBUS_TYPE_ARRAY,
2784   sizeof (TestTypeNodeContainer),
2785   NULL,
2786   container_destroy,
2787   array_0_write_value,
2788   array_0_read_value,
2789   array_build_signature
2790 };
2791
2792 static const TestTypeNodeClass array_1_class = {
2793   DBUS_TYPE_ARRAY,
2794   sizeof (TestTypeNodeContainer),
2795   NULL,
2796   container_destroy,
2797   array_1_write_value,
2798   array_1_read_value,
2799   array_build_signature
2800 };
2801
2802 static const TestTypeNodeClass array_2_class = {
2803   DBUS_TYPE_ARRAY,
2804   sizeof (TestTypeNodeContainer),
2805   NULL,
2806   container_destroy,
2807   array_2_write_value,
2808   array_2_read_value,
2809   array_build_signature
2810 };
2811
2812 static const TestTypeNodeClass* const
2813 basic_nodes[] = {
2814   &int32_class,
2815   &uint32_class
2816 };
2817
2818 static const TestTypeNodeClass* const
2819 container_nodes[] = {
2820   &struct_1_class,
2821   &array_1_class,
2822   &struct_2_class,
2823   &array_0_class,
2824   &array_2_class
2825 };
2826
2827 static TestTypeNode*
2828 node_new (const TestTypeNodeClass *klass)
2829 {
2830   TestTypeNode *node;
2831
2832   node = dbus_malloc0 (klass->instance_size);
2833   if (node == NULL)
2834     return NULL;
2835
2836   node->klass = klass;
2837   
2838   if (klass->construct)
2839     {
2840       if (!(* klass->construct) (node))
2841         {
2842           dbus_free (node);
2843           return FALSE;
2844         }
2845     }
2846
2847   return node;
2848 }
2849
2850 static void
2851 node_destroy (TestTypeNode *node)
2852 {
2853   if (node->klass->destroy)
2854     (* node->klass->destroy) (node);
2855   dbus_free (node);
2856 }
2857
2858 static dbus_bool_t
2859 node_write_value (TestTypeNode   *node,
2860                   DataBlock      *block,
2861                   DBusTypeWriter *writer)
2862 {
2863   return (* node->klass->write_value) (node, block, writer);
2864 }
2865
2866 static dbus_bool_t
2867 node_read_value (TestTypeNode   *node,
2868                  DataBlock      *block,
2869                  DBusTypeReader *reader)
2870 {
2871   return (* node->klass->read_value) (node, block, reader);
2872 }
2873
2874 static dbus_bool_t
2875 node_build_signature (TestTypeNode *node,
2876                       DBusString   *str)
2877 {
2878   if (node->klass->build_signature)
2879     return (* node->klass->build_signature) (node, str);
2880   else
2881     return _dbus_string_append_byte (str, node->klass->typecode);
2882 }
2883
2884 static dbus_bool_t
2885 node_append_child (TestTypeNode *node,
2886                    TestTypeNode *child)
2887 {
2888   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
2889
2890   _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
2891
2892   return _dbus_list_append (&container->children, child);
2893 }
2894
2895 typedef struct
2896 {
2897   const DBusString   *signature;
2898   DataBlock          *block;
2899   int                 type_offset;
2900   int                 byte_order;
2901   TestTypeNode      **nodes;
2902   int                 n_nodes;
2903 } NodeIterationData;
2904
2905 static dbus_bool_t
2906 run_test_nodes_iteration (void *data)
2907 {
2908   NodeIterationData *nid = data;
2909   DBusTypeReader reader;
2910   DBusTypeWriter writer;
2911   int i;
2912
2913   /* Stuff to do:
2914    * 1. write the value
2915    * 2. strcmp-compare with the signature we built
2916    * 3. read the value
2917    * 4. type-iterate the signature and the value and see if they are the same type-wise
2918    */
2919   data_block_init_reader_writer (nid->block,
2920                                  nid->byte_order,
2921                                  &reader, &writer);
2922
2923   i = 0;
2924   while (i < nid->n_nodes)
2925     {
2926       if (!node_write_value (nid->nodes[i], nid->block, &writer))
2927         return FALSE;
2928
2929       ++i;
2930     }
2931
2932   if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
2933                                      &nid->block->signature, nid->type_offset))
2934     {
2935       _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
2936                   _dbus_string_get_const_data (nid->signature),
2937                   _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
2938                   nid->type_offset);
2939       _dbus_assert_not_reached ("wrong signature");
2940     }
2941
2942   i = 0;
2943   while (i < nid->n_nodes)
2944     {
2945       if (!node_read_value (nid->nodes[i], nid->block, &reader))
2946         return FALSE;
2947
2948       if (i + 1 == nid->n_nodes)
2949         NEXT_EXPECTING_FALSE (&reader);
2950       else
2951         NEXT_EXPECTING_TRUE (&reader);
2952
2953       ++i;
2954     }
2955
2956   /* FIXME type-iterate both signature and value */
2957   
2958   return TRUE;
2959 }
2960
2961 static void
2962 run_test_nodes_in_one_configuration (TestTypeNode    **nodes,
2963                                      int               n_nodes,
2964                                      const DBusString *signature,
2965                                      int               byte_order,
2966                                      int               initial_offset)
2967 {
2968   DataBlock block;
2969   NodeIterationData nid;
2970
2971   if (!data_block_init (&block))
2972     _dbus_assert_not_reached ("no memory");
2973
2974   if (!_dbus_string_lengthen (&block.signature, initial_offset))
2975     _dbus_assert_not_reached ("no memory");
2976   
2977   if (!_dbus_string_lengthen (&block.body, initial_offset))
2978     _dbus_assert_not_reached ("no memory");
2979
2980   nid.signature = signature;
2981   nid.block = &block;
2982   nid.type_offset = initial_offset;
2983   nid.nodes = nodes;
2984   nid.n_nodes = n_nodes;
2985   nid.byte_order = byte_order;
2986   
2987   _dbus_test_oom_handling ("running test node",
2988                            run_test_nodes_iteration,
2989                            &nid);
2990
2991   data_block_free (&block);
2992 }
2993
2994 static void
2995 run_test_nodes (TestTypeNode **nodes,
2996                 int            n_nodes)
2997 {
2998   int i;
2999   DBusString signature;
3000
3001   if (!_dbus_string_init (&signature))
3002     _dbus_assert_not_reached ("no memory");
3003
3004   i = 0;
3005   while (i < n_nodes)
3006     {
3007       if (! node_build_signature (nodes[i], &signature))
3008         _dbus_assert_not_reached ("no memory");
3009
3010       ++i;
3011     }
3012       
3013   _dbus_verbose (">>> test nodes with signature '%s'\n",
3014                  _dbus_string_get_const_data (&signature));
3015   
3016   i = 0;
3017   while (i < 18)
3018     {
3019       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3020                                            DBUS_LITTLE_ENDIAN, i);
3021       run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
3022                                            DBUS_BIG_ENDIAN, i);
3023       
3024       ++i;
3025     }
3026
3027   _dbus_string_free (&signature);
3028 }
3029
3030 #define N_VALUES (_DBUS_N_ELEMENTS (basic_nodes) * _DBUS_N_ELEMENTS (container_nodes) + _DBUS_N_ELEMENTS (basic_nodes))
3031
3032 static TestTypeNode*
3033 value_generator (int *ip)
3034 {
3035   int i = *ip;
3036   const TestTypeNodeClass *child_klass;
3037   const TestTypeNodeClass *container_klass;
3038   TestTypeNode *child;
3039   TestTypeNode *node;
3040   
3041   if (i == N_VALUES)
3042     {
3043       return NULL;
3044     }
3045   else if (i < _DBUS_N_ELEMENTS (basic_nodes))
3046     {
3047       node = node_new (basic_nodes[i]);
3048     }
3049   else
3050     {      
3051       /* imagine an array:
3052        * container 0 of basic 0
3053        * container 0 of basic 1
3054        * container 0 of basic 2
3055        * container 1 of basic 0
3056        * container 1 of basic 1
3057        * container 1 of basic 2
3058        */
3059       i -= _DBUS_N_ELEMENTS (basic_nodes);
3060
3061       container_klass = container_nodes[i / _DBUS_N_ELEMENTS (basic_nodes)];
3062       child_klass = basic_nodes[i % _DBUS_N_ELEMENTS (basic_nodes)];
3063       
3064       node = node_new (container_klass);
3065       child = node_new (child_klass);
3066       
3067       node_append_child (node, child);
3068     }
3069   
3070   *ip += 1; /* increment the generator */
3071
3072   return node;
3073 }
3074
3075 static void
3076 make_and_run_test_nodes (void)
3077 {
3078   int i, j;
3079   
3080   /* We try to do this in order of "complicatedness" so that test
3081    * failures tend to show up in the simplest test case that
3082    * demonstrates the failure.  There are also some tests that run
3083    * more than once for this reason, first while going through simple
3084    * cases, second while going through a broader range of complex
3085    * cases.
3086    */
3087   /* Each basic node. The basic nodes should include:
3088    *
3089    * - each fixed-size type (in such a way that it has different values each time,
3090    *                         so we can tell if we mix two of them up)
3091    * - strings of length 0-9
3092    * - object path
3093    * - signature
3094    */
3095   /* Each container node. The container nodes should include:
3096    *
3097    *  struct with 1 and 2 copies of the contained item
3098    *  array with 0, 1, 2 copies of the contained item
3099    *  variant
3100    */
3101   /*  Let a "value" be a basic node, or a container containing a single basic node.
3102    *  Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
3103    *  When iterating through all values to make combinations, do the basic types
3104    *  first and the containers second.
3105    */
3106   /* Each item is shown with its number of iterations so we can keep a handle
3107    * on this unit test
3108    */
3109   
3110   /* n_basic iterations */
3111   _dbus_verbose (">>> >>> Each basic node by itself\n");
3112   for (i = 0; i < _DBUS_N_ELEMENTS (basic_nodes); i++)
3113     {
3114       const TestTypeNodeClass *klass = basic_nodes[i];
3115       TestTypeNode *node;
3116       
3117       node = node_new (klass);
3118
3119       run_test_nodes (&node, 1);
3120
3121       node_destroy (node);
3122     }
3123   
3124   /* n_container * n_basic iterations */
3125   _dbus_verbose (">>> >>> Each container of each basic (redundant with later tests)\n");
3126   for (i = 0; i < _DBUS_N_ELEMENTS (container_nodes); i++)
3127     {
3128       const TestTypeNodeClass *container_klass = container_nodes[i];
3129       for (j = 0; j < _DBUS_N_ELEMENTS (basic_nodes); j++)
3130         {
3131           const TestTypeNodeClass *child_klass = basic_nodes[j];
3132           TestTypeNode *child;
3133           TestTypeNode *container;
3134       
3135           container = node_new (container_klass);
3136           child = node_new (child_klass);
3137
3138           node_append_child (container, child);
3139           
3140           run_test_nodes (&container, 1);
3141
3142           node_destroy (container);
3143         }
3144     }
3145   
3146   /* n_values * n_values * 2 iterations */
3147   _dbus_verbose (">>> >>> Each value,value pair combination as toplevel, in both orders\n");
3148   {
3149     TestTypeNode *nodes[2];
3150
3151     i = 0;
3152     while ((nodes[0] = value_generator (&i)))
3153       {
3154         j = 0;
3155         while ((nodes[1] = value_generator (&j)))
3156           {
3157             run_test_nodes (nodes, 2);
3158
3159             node_destroy (nodes[1]);
3160           }
3161
3162         node_destroy (nodes[0]);
3163       }
3164   }
3165
3166   /* 1 iteration */
3167   _dbus_verbose (">>> >>> All values in one big toplevel\n");
3168   {
3169     TestTypeNode *nodes[N_VALUES];
3170
3171     i = 0;
3172     while ((nodes[i] = value_generator (&i)))
3173       ;
3174
3175     run_test_nodes (nodes, N_VALUES);
3176
3177     for (i = 0; i < N_VALUES; i++)
3178       node_destroy (nodes[i]);
3179   }
3180   
3181   /* n_container * n_values iterations */
3182   _dbus_verbose (">>> >>> Each container containing each value\n");
3183   for (i = 0; i < _DBUS_N_ELEMENTS (container_nodes); i++)
3184     {
3185       const TestTypeNodeClass *container_klass = container_nodes[i];
3186       TestTypeNode *child;
3187       
3188       j = 0;
3189       while ((child = value_generator (&j)))
3190         {
3191           TestTypeNode *container;
3192           
3193           container = node_new (container_klass);
3194
3195           node_append_child (container, child);
3196           
3197           run_test_nodes (&container, 1);
3198           
3199           node_destroy (container);
3200         }
3201     }
3202   
3203   /* n_container * n_values - container of same container of values */
3204   
3205   /* n_container * n_values - container of same container of same container of values */
3206
3207   /* n_container * n_container * n_values - container of container of values */
3208   /* n_container * n_container * n_container * n_values - container of container of container of values */
3209
3210   /* n_values * n_values * n_values * 6 - each trio of value,value,value in all orders */
3211   
3212   /* n_values * n_values * 2 - each value,value pair inside STRUCT, in both orders */
3213
3214   /* 1 - all values in one big STRUCT */
3215 }
3216
3217 dbus_bool_t _dbus_marshal_recursive_test (void);
3218
3219 dbus_bool_t
3220 _dbus_marshal_recursive_test (void)
3221 {
3222   /* The new comprehensive tests */
3223
3224 #if 1
3225   make_and_run_test_nodes ();
3226 #endif
3227   
3228 #if 0
3229   /* The old tests */
3230   _dbus_test_oom_handling ("recursive marshaling",
3231                            recursive_marshal_test_iteration,
3232                            NULL);  
3233 #endif
3234   
3235   return TRUE;
3236 }
3237
3238 #if 1
3239 int
3240 main (int argc, char **argv)
3241 {
3242   _dbus_marshal_recursive_test ();
3243
3244   return 0;
3245 }
3246 #endif /* main() */
3247
3248
3249 /*
3250  *
3251  *
3252  *         Implementations of each type node class
3253  *
3254  *
3255  *
3256  */
3257
3258 static dbus_bool_t
3259 int32_write_value (TestTypeNode   *node,
3260                    DataBlock      *block,
3261                    DBusTypeWriter *writer)
3262 {
3263   /* also used for uint32 */
3264   dbus_int32_t v = _DBUS_POINTER_TO_INT (node->data);
3265   
3266   return _dbus_type_writer_write_basic (writer,
3267                                         node->klass->typecode,
3268                                         &v);
3269 }
3270
3271 static dbus_bool_t
3272 int32_read_value (TestTypeNode   *node,
3273                   DataBlock      *block,
3274                   DBusTypeReader *reader)
3275 {
3276   /* also used for uint32 */
3277   dbus_int32_t v;
3278
3279   check_expected_type (reader, node->klass->typecode);
3280   
3281   _dbus_type_reader_read_basic (reader,
3282                                 (dbus_int32_t*) &v);
3283   
3284   _dbus_assert (v == _DBUS_POINTER_TO_INT (node->data));
3285
3286   return TRUE;
3287 }
3288
3289 static dbus_bool_t
3290 struct_N_write_value (TestTypeNode   *node,
3291                       DataBlock      *block,
3292                       DBusTypeWriter *writer,
3293                       int             n_copies)
3294 {
3295   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3296   DataBlockState saved;
3297   DBusTypeWriter sub;
3298   int i;
3299
3300   _dbus_assert (container->children != NULL);
3301   
3302   data_block_save (block, &saved);
3303   
3304   if (!_dbus_type_writer_recurse_struct (writer,
3305                                          &sub))
3306     return FALSE;
3307
3308   i = 0;
3309   while (i < n_copies)
3310     {
3311       DBusList *link;
3312       
3313       link = _dbus_list_get_first_link (&container->children);
3314       while (link != NULL)
3315         {
3316           TestTypeNode *child = link->data;
3317           DBusList *next = _dbus_list_get_next_link (&container->children, link);
3318
3319           if (!node_write_value (child, block, &sub))
3320             {
3321               data_block_restore (block, &saved);
3322               return FALSE;
3323             }
3324           
3325           link = next;
3326         }
3327
3328       ++i;
3329     }
3330   
3331   if (!_dbus_type_writer_unrecurse (writer, &sub))
3332     {
3333       data_block_restore (block, &saved);
3334       return FALSE;
3335     }
3336   
3337   return TRUE;
3338 }
3339
3340 static dbus_bool_t
3341 struct_N_read_value (TestTypeNode   *node,
3342                      DataBlock      *block,
3343                      DBusTypeReader *reader,
3344                      int             n_copies)
3345 {
3346   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3347   DBusTypeReader sub;
3348   int i;
3349   
3350   check_expected_type (reader, DBUS_TYPE_STRUCT);
3351   
3352   _dbus_type_reader_recurse (reader, &sub);
3353
3354   i = 0;
3355   while (i < n_copies)
3356     {
3357       DBusList *link;
3358       
3359       link = _dbus_list_get_first_link (&container->children);
3360       while (link != NULL)
3361         {
3362           TestTypeNode *child = link->data;
3363           DBusList *next = _dbus_list_get_next_link (&container->children, link);
3364
3365           node_read_value (child, block, &sub);
3366
3367           if (i == (n_copies - 1) && next == NULL)
3368             NEXT_EXPECTING_FALSE (&sub);
3369           else
3370             NEXT_EXPECTING_TRUE (&sub);
3371           
3372           link = next;
3373         }
3374
3375       ++i;
3376     }
3377   
3378   return TRUE;
3379 }
3380
3381 static dbus_bool_t
3382 struct_N_build_signature (TestTypeNode   *node,
3383                           DBusString     *str,
3384                           int             n_copies)
3385 {
3386   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3387   int i;
3388   int orig_len;
3389
3390   orig_len = _dbus_string_get_length (str);
3391
3392   if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
3393     goto oom;
3394   
3395   i = 0;
3396   while (i < n_copies)
3397     {
3398       DBusList *link;
3399       
3400       link = _dbus_list_get_first_link (&container->children);
3401       while (link != NULL)
3402         {
3403           TestTypeNode *child = link->data;
3404           DBusList *next = _dbus_list_get_next_link (&container->children, link);
3405
3406           if (!node_build_signature (child, str))
3407             goto oom;
3408           
3409           link = next;
3410         }
3411
3412       ++i;
3413     }
3414
3415   if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
3416     goto oom;
3417   
3418   return TRUE;
3419   
3420  oom:
3421   _dbus_string_set_length (str, orig_len);
3422   return FALSE;
3423 }
3424
3425 static dbus_bool_t
3426 struct_1_write_value (TestTypeNode   *node,
3427                       DataBlock      *block,
3428                       DBusTypeWriter *writer)
3429 {
3430   return struct_N_write_value (node, block, writer, 1);
3431 }
3432
3433 static dbus_bool_t
3434 struct_1_read_value (TestTypeNode   *node,
3435                      DataBlock      *block,
3436                      DBusTypeReader *reader)
3437 {
3438   return struct_N_read_value (node, block, reader, 1);
3439 }
3440
3441 static dbus_bool_t
3442 struct_1_build_signature (TestTypeNode   *node,
3443                           DBusString     *str)
3444 {
3445   return struct_N_build_signature (node, str, 1);
3446 }
3447
3448
3449 static dbus_bool_t
3450 struct_2_write_value (TestTypeNode   *node,
3451                       DataBlock      *block,
3452                       DBusTypeWriter *writer)
3453 {
3454   return struct_N_write_value (node, block, writer, 2);
3455 }
3456
3457 static dbus_bool_t
3458 struct_2_read_value (TestTypeNode   *node,
3459                      DataBlock      *block,
3460                      DBusTypeReader *reader)
3461 {
3462   return struct_N_read_value (node, block, reader, 2);
3463 }
3464
3465 static dbus_bool_t
3466 struct_2_build_signature (TestTypeNode   *node,
3467                           DBusString     *str)
3468 {
3469   return struct_N_build_signature (node, str, 2);
3470 }
3471
3472 static dbus_bool_t
3473 array_N_write_value (TestTypeNode   *node,
3474                      DataBlock      *block,
3475                      DBusTypeWriter *writer,
3476                      int             n_copies)
3477 {
3478   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3479   DataBlockState saved;
3480   DBusTypeWriter sub;
3481   DBusString element_signature;
3482   int i;
3483
3484   _dbus_assert (container->children != NULL);
3485
3486   data_block_save (block, &saved);
3487   
3488   if (!_dbus_string_init (&element_signature))
3489     return FALSE;
3490
3491   if (!node_build_signature (_dbus_list_get_first (&container->children),
3492                              &element_signature))
3493     goto oom;
3494   
3495   if (!_dbus_type_writer_recurse_array (writer,
3496                                         _dbus_string_get_const_data (&element_signature),
3497                                         &sub))
3498     goto oom;
3499
3500   i = 0;
3501   while (i < n_copies)
3502     {
3503       DBusList *link;
3504       
3505       link = _dbus_list_get_first_link (&container->children);
3506       while (link != NULL)
3507         {
3508           TestTypeNode *child = link->data;
3509           DBusList *next = _dbus_list_get_next_link (&container->children, link);
3510
3511           if (!node_write_value (child, block, &sub))
3512             goto oom;
3513           
3514           link = next;
3515         }
3516
3517       ++i;
3518     }
3519   
3520   if (!_dbus_type_writer_unrecurse (writer, &sub))
3521     goto oom;
3522   
3523   return TRUE;
3524
3525  oom:
3526   data_block_restore (block, &saved);
3527   _dbus_string_free (&element_signature);
3528   return FALSE;
3529 }
3530
3531 static dbus_bool_t
3532 array_N_read_value (TestTypeNode   *node,
3533                     DataBlock      *block,
3534                     DBusTypeReader *reader,
3535                     int             n_copies)
3536 {
3537   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3538   DBusTypeReader sub;
3539   int i;
3540   
3541   check_expected_type (reader, DBUS_TYPE_ARRAY);
3542
3543   if (n_copies > 0)
3544     {
3545       _dbus_assert (!_dbus_type_reader_array_is_empty (reader));
3546       
3547       _dbus_type_reader_recurse (reader, &sub);
3548
3549       i = 0;
3550       while (i < n_copies)
3551         {
3552           DBusList *link;
3553           
3554           link = _dbus_list_get_first_link (&container->children);
3555           while (link != NULL)
3556             {
3557               TestTypeNode *child = link->data;
3558               DBusList *next = _dbus_list_get_next_link (&container->children, link);
3559               
3560               node_read_value (child, block, &sub);
3561               
3562               if (i == (n_copies - 1) && next == NULL)
3563                 NEXT_EXPECTING_FALSE (&sub);
3564               else
3565                 NEXT_EXPECTING_TRUE (&sub);
3566               
3567               link = next;
3568             }
3569           
3570           ++i;
3571         }
3572     }
3573   else
3574     {
3575       _dbus_assert (_dbus_type_reader_array_is_empty (reader));
3576     }
3577     
3578   return TRUE;
3579 }
3580
3581 static dbus_bool_t
3582 array_build_signature (TestTypeNode   *node,
3583                        DBusString     *str)
3584 {
3585   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3586   int orig_len;
3587   
3588   orig_len = _dbus_string_get_length (str);
3589
3590   if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
3591     goto oom;
3592
3593   if (!node_build_signature (_dbus_list_get_first (&container->children),
3594                              str))
3595     goto oom;
3596   
3597   return TRUE;
3598   
3599  oom:
3600   _dbus_string_set_length (str, orig_len);
3601   return FALSE;
3602 }
3603
3604 static dbus_bool_t
3605 array_0_write_value (TestTypeNode   *node,
3606                      DataBlock      *block,
3607                      DBusTypeWriter *writer)
3608 {
3609   return array_N_write_value (node, block, writer, 0);
3610 }
3611
3612 static dbus_bool_t
3613 array_0_read_value (TestTypeNode   *node,
3614                     DataBlock      *block,
3615                     DBusTypeReader *reader)
3616 {
3617   return array_N_read_value (node, block, reader, 0);
3618 }
3619
3620
3621 static dbus_bool_t
3622 array_1_write_value (TestTypeNode   *node,
3623                      DataBlock      *block,
3624                      DBusTypeWriter *writer)
3625 {
3626   return array_N_write_value (node, block, writer, 1);
3627 }
3628
3629 static dbus_bool_t
3630 array_1_read_value (TestTypeNode   *node,
3631                     DataBlock      *block,
3632                     DBusTypeReader *reader)
3633 {
3634   return array_N_read_value (node, block, reader, 1);
3635 }
3636
3637 static dbus_bool_t
3638 array_2_write_value (TestTypeNode   *node,
3639                      DataBlock      *block,
3640                      DBusTypeWriter *writer)
3641 {
3642   return array_N_write_value (node, block, writer, 2);
3643 }
3644
3645 static dbus_bool_t
3646 array_2_read_value (TestTypeNode   *node,
3647                     DataBlock      *block,
3648                     DBusTypeReader *reader)
3649 {
3650   return array_N_read_value (node, block, reader, 2);
3651 }
3652
3653 static void
3654 container_destroy (TestTypeNode *node)
3655 {
3656   TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
3657   DBusList *link;
3658   
3659   link = _dbus_list_get_first_link (&container->children);
3660   while (link != NULL)
3661     {
3662       TestTypeNode *child = link->data;
3663       DBusList *next = _dbus_list_get_next_link (&container->children, link);
3664
3665       node_destroy (child);
3666
3667       _dbus_list_free_link (link);
3668       
3669       link = next;
3670     }
3671 }
3672
3673 #endif /* DBUS_BUILD_TESTS */