checkpoint with array-of-struct working
[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 static int
33 first_type_in_signature (const DBusString *str,
34                          int               pos)
35 {
36   int t;
37
38   t = _dbus_string_get_byte (str, pos);
39   
40   if (t == DBUS_STRUCT_BEGIN_CHAR)
41     return DBUS_TYPE_STRUCT;
42   else
43     return t;
44 }
45
46 static int
47 element_type_get_alignment (const DBusString *str,
48                             int               pos)
49 {
50   return _dbus_type_get_alignment (first_type_in_signature (str, pos));
51 }
52
53 void
54 _dbus_type_reader_init (DBusTypeReader    *reader,
55                         int                byte_order,
56                         const DBusString  *type_str,
57                         int                type_pos,
58                         const DBusString  *value_str,
59                         int                value_pos)
60 {
61   reader->byte_order = byte_order;
62   reader->type_str = type_str;
63   reader->type_pos = type_pos;
64   reader->value_str = value_str;
65   reader->value_pos = value_pos;
66   reader->container_type = DBUS_TYPE_INVALID;
67
68   _dbus_verbose ("  type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
69                  reader, reader->type_pos, reader->value_pos,
70                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
71 }
72
73 int
74 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
75 {
76   int t;
77
78   /* for INVALID t will == DBUS_TYPE_INVALID when we
79    * reach the end of type_str, for STRUCT we have to
80    * check the finished flag
81    */
82   if (reader->container_type == DBUS_TYPE_INVALID)
83     {
84       t = first_type_in_signature (reader->type_str,
85                                    reader->type_pos);
86     }
87   else if (reader->container_type == DBUS_TYPE_STRUCT)
88     {
89       if (reader->u.strct.finished)
90         t = DBUS_TYPE_INVALID;
91       else
92         t = first_type_in_signature (reader->type_str,
93                                      reader->type_pos);
94     }
95   else if (reader->container_type == DBUS_TYPE_ARRAY)
96     {
97       /* return the array element type if elements remain, and
98        * TYPE_INVALID otherwise
99        */
100       int end_pos;
101
102       end_pos = reader->u.array.start_pos + reader->u.array.len;
103
104       _dbus_assert (reader->value_pos <= end_pos);
105       _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
106
107       if (reader->value_pos < end_pos)
108         t = reader->u.array.element_type;
109       else
110         t = DBUS_TYPE_INVALID;
111     }
112   else
113     {
114       _dbus_assert_not_reached ("reader->container_type should not be set to this");
115       t = DBUS_TYPE_INVALID; /* quiet gcc */
116     }
117
118   _dbus_assert (t != DBUS_STRUCT_END_CHAR);
119   _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
120   
121 #if 0
122   _dbus_verbose ("  type reader %p current type_pos = %d type = %s\n",
123                  reader, reader->type_pos,
124                  _dbus_type_to_string (t));
125 #endif
126   
127   return t;
128 }
129
130 dbus_bool_t
131 _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
132 {
133   dbus_uint32_t array_len;
134   int len_pos;
135   
136   _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
137                             TRUE);
138
139   len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
140   
141   _dbus_demarshal_basic_type (reader->value_str,
142                               DBUS_TYPE_UINT32,
143                               &array_len,
144                               reader->byte_order,
145                               &len_pos);
146
147   return array_len == 0;
148 }
149
150 void
151 _dbus_type_reader_read_basic (DBusTypeReader    *reader,
152                               void              *value)
153 {
154   if (reader->container_type == DBUS_TYPE_INVALID ||
155       reader->container_type == DBUS_TYPE_STRUCT ||
156       reader->container_type == DBUS_TYPE_ARRAY)
157     {
158       int t;
159       int next;
160       
161       t = _dbus_type_reader_get_current_type (reader);
162
163       next = reader->value_pos;
164       _dbus_demarshal_basic_type (reader->value_str,
165                                   t, value,
166                                   reader->byte_order,
167                                   &next);
168
169
170       _dbus_verbose ("  type reader %p read basic type_pos = %d value_pos = %d next = %d remaining sig '%s'\n",
171                      reader, reader->type_pos, reader->value_pos, next,
172                      _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
173     }
174   else
175     {
176       _dbus_assert_not_reached ("reader->container_type should not be set to this");
177     }
178 }
179
180 dbus_bool_t
181 _dbus_type_reader_read_array_of_basic (DBusTypeReader    *reader,
182                                        int                type,
183                                        void             **array,
184                                        int               *array_len)
185 {
186   
187   
188 }
189
190 /**
191  * Initialize a new reader pointing to the first type and
192  * corresponding value that's a child of the current container. It's
193  * an error to call this if the current type is a non-container.
194  * 
195  * Note that DBusTypeReader traverses values, not types. So if you
196  * have an empty array of array of int, you can't recurse into it. You
197  * can only recurse into each element.
198  *
199  * @param reader the reader
200  * @param sub a reader to init pointing to the first child
201  */
202 void
203 _dbus_type_reader_recurse (DBusTypeReader *reader,
204                            DBusTypeReader *sub)
205 {
206   int t;
207   
208   t = first_type_in_signature (reader->type_str, reader->type_pos);
209   
210   /* point subreader at the same place as reader */
211   _dbus_type_reader_init (sub,
212                           reader->byte_order,
213                           reader->type_str,
214                           reader->type_pos,
215                           reader->value_str,
216                           reader->value_pos);
217
218   if (t == DBUS_TYPE_STRUCT)
219     {
220       sub->container_type = DBUS_TYPE_STRUCT;
221       
222       sub->type_pos += 1;
223
224       /* struct has 8 byte alignment */
225       sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
226
227       sub->u.strct.finished = FALSE;
228     }
229   else if (t == DBUS_TYPE_ARRAY)
230     {
231       dbus_uint32_t array_len;
232       int alignment;
233
234       _dbus_return_if_fail (!_dbus_type_reader_array_is_empty (reader));
235       
236       sub->container_type = DBUS_TYPE_ARRAY;
237       
238       /* point type_pos at the array element type */
239       sub->type_pos += 1;
240
241       sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
242       
243       _dbus_demarshal_basic_type (sub->value_str,
244                                   DBUS_TYPE_UINT32,
245                                   &array_len,
246                                   sub->byte_order,
247                                   &sub->value_pos);
248       
249       sub->u.array.len = array_len;
250       
251       alignment = element_type_get_alignment (sub->type_str,
252                                               sub->type_pos);
253       
254       sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
255
256       sub->u.array.element_type = first_type_in_signature (sub->type_str,
257                                                            sub->type_pos);
258       sub->u.array.start_pos = sub->value_pos;
259
260       _dbus_verbose ("    type reader %p array start = %d array len = %d array element type = %s\n",
261                      reader,
262                      sub->u.array.start_pos,
263                      sub->u.array.len,
264                      _dbus_type_to_string (sub->u.array.element_type));
265     }
266   else
267     {
268       _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
269 #ifndef DBUS_DISABLE_CHECKS
270       if (t == DBUS_TYPE_INVALID)
271         _dbus_warn ("You can't recurse into an empty array or off the end of a message body\n");
272 #endif /* DBUS_DISABLE_CHECKS */
273       
274       _dbus_assert_not_reached ("don't yet handle recursing into this type");
275     }
276
277   _dbus_verbose ("  type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
278                  sub, sub->type_pos, sub->value_pos,
279                  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
280 }
281
282 static void
283 skip_one_complete_type (const DBusString *type_str,
284                         int              *type_pos)
285 {
286   while (_dbus_string_get_byte (type_str, *type_pos) == DBUS_TYPE_ARRAY)
287     *type_pos += 1;
288
289   if (_dbus_string_get_byte (type_str, *type_pos) == DBUS_STRUCT_BEGIN_CHAR)
290     {
291       int depth;
292       depth = 1;
293       *type_pos += 1;
294       while (depth > 0)
295         {
296           switch (_dbus_string_get_byte (type_str, *type_pos))
297             {
298             case DBUS_STRUCT_BEGIN_CHAR:
299               depth += 1;
300               break;
301             case DBUS_STRUCT_END_CHAR:
302               depth -= 1;
303               break;
304             case DBUS_TYPE_INVALID:
305               _dbus_assert_not_reached ("unbalanced parens in signature");
306               break;
307             }
308           *type_pos += 1;
309         }
310     }
311   else
312     *type_pos += 1;
313 }
314
315 static void
316 skip_array_values (int               element_type,
317                    const DBusString *value_str,
318                    int              *value_pos,
319                    int               byte_order)
320 {
321   dbus_uint32_t array_len;
322   int pos;
323   int alignment;
324   
325   pos = _DBUS_ALIGN_VALUE (*value_pos, 4);
326   
327   _dbus_demarshal_basic_type (value_str,
328                               DBUS_TYPE_UINT32,
329                               &array_len,
330                               byte_order,
331                               &pos);
332
333   alignment = _dbus_type_get_alignment (element_type);
334
335   pos = _DBUS_ALIGN_VALUE (pos, alignment);
336   
337   *value_pos = pos + array_len;
338 }
339
340 /**
341  * Skip to the next value on this "level". e.g. the next field in a
342  * struct, the next value in an array, the next key or value in a
343  * dict. Returns FALSE at the end of the current container.
344  *
345  * @param reader the reader
346  * @returns FALSE if nothing more to read at or below this level
347  */
348 dbus_bool_t
349 _dbus_type_reader_next (DBusTypeReader *reader)
350 {
351   int t;
352   
353   t = _dbus_type_reader_get_current_type (reader);
354   
355   _dbus_verbose ("  type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
356                  reader, reader->type_pos, reader->value_pos,
357                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
358                  _dbus_type_to_string (t));
359
360   if (t == DBUS_TYPE_INVALID)
361     return FALSE;
362   
363   if (reader->container_type == DBUS_TYPE_INVALID ||
364       reader->container_type == DBUS_TYPE_STRUCT)
365     {
366       switch (t)
367         {
368         case DBUS_TYPE_STRUCT:
369           /* Scan forward over the entire container contents */
370           {
371             DBusTypeReader sub;
372
373             /* Recurse into the struct */
374             _dbus_type_reader_recurse (reader, &sub);
375
376             /* Skip everything in this subreader */
377             while (_dbus_type_reader_next (&sub))
378               {
379                 /* nothing */;
380               }
381
382             /* Now we are at the end of this container */
383             reader->type_pos = sub.type_pos;
384             reader->value_pos = sub.value_pos;
385           }
386           break;
387           
388         case DBUS_TYPE_ARRAY:
389           {
390             skip_array_values (first_type_in_signature (reader->type_str,
391                                                         reader->type_pos + 1),
392                                reader->value_str, &reader->value_pos, reader->byte_order);
393             skip_one_complete_type (reader->type_str, &reader->type_pos);
394           }
395           break;
396
397         default:
398           _dbus_marshal_skip_basic_type (reader->value_str,
399                                          t, reader->byte_order,
400                                          &reader->value_pos);
401           reader->type_pos += 1;
402           break;
403         }
404
405       /* for STRUCT containers we return FALSE at the end of the struct,
406        * for INVALID we return FALSE at the end of the signature.
407        * In both cases we arrange for get_current_type() to return INVALID
408        * which is defined to happen iff we're at the end (no more next())
409        */
410       if (reader->container_type == DBUS_TYPE_STRUCT)
411         {
412           t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
413           if (t == DBUS_STRUCT_END_CHAR)
414             {
415               reader->type_pos += 1;
416               reader->u.strct.finished = TRUE;
417             }
418         }
419     }
420   else if (reader->container_type == DBUS_TYPE_ARRAY)
421     {
422       /* Skip one array element */
423       int end_pos;
424
425       end_pos = reader->u.array.start_pos + reader->u.array.len;
426
427       _dbus_assert (reader->value_pos < end_pos);
428       _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
429
430       if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
431         {
432           DBusTypeReader sub;
433           
434           /* Recurse into the struct */
435           _dbus_type_reader_recurse (reader, &sub);
436
437             /* Skip everything in this element */
438           while (_dbus_type_reader_next (&sub))
439             {
440               /* nothing */;
441             }
442
443           /* Now we are at the end of this element */
444           reader->value_pos = sub.value_pos;
445         }
446       else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
447         {
448           skip_array_values (first_type_in_signature (reader->type_str,
449                                                       reader->type_pos + 1),
450                              reader->value_str, &reader->value_pos, reader->byte_order);
451         }
452       else
453         {
454           _dbus_marshal_skip_basic_type (reader->value_str,
455                                          t, reader->byte_order,
456                                          &reader->value_pos);
457         }
458
459       _dbus_assert (reader->value_pos <= end_pos);
460       
461       if (reader->value_pos == end_pos)
462         {
463           skip_one_complete_type (reader->type_str,
464                                   &reader->type_pos);
465         }
466     }
467   else
468     {
469       _dbus_assert_not_reached ("reader->container_type should not be set to this");
470     }
471   
472   _dbus_verbose ("  type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
473                  reader, reader->type_pos, reader->value_pos,
474                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
475                  _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
476   
477   return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
478 }
479
480 void
481 _dbus_type_writer_init (DBusTypeWriter *writer,
482                         int             byte_order,
483                         DBusString     *type_str,
484                         int             type_pos,
485                         DBusString     *value_str,
486                         int             value_pos)
487 {
488   writer->byte_order = byte_order;
489   writer->type_str = type_str;
490   writer->type_pos = type_pos;
491   writer->value_str = value_str;
492   writer->value_pos = value_pos;
493   writer->container_type = DBUS_TYPE_INVALID;
494   writer->inside_array = FALSE;
495
496   _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
497                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
498 }
499
500 static dbus_bool_t
501 _dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
502                                            int             type,
503                                            const void     *value)
504 {
505   int old_value_len;
506   int bytes_written;
507
508   old_value_len = _dbus_string_get_length (writer->value_str);
509         
510   if (!_dbus_marshal_basic_type (writer->value_str,
511                                  writer->value_pos,
512                                  type,
513                                  value,
514                                  writer->byte_order))
515     return FALSE;
516
517   bytes_written = _dbus_string_get_length (writer->value_str) - old_value_len;
518   
519   writer->value_pos += bytes_written;
520
521   return TRUE;
522 }
523
524 /* If our parent is an array, things are a little bit complicated.
525  *
526  * The parent must have a complete element type, such as
527  * "i" or "aai" or "(ii)" or "a(ii)". There can't be
528  * unclosed parens, or an "a" with no following type.
529  *
530  * To recurse, the only allowed operation is to recurse into the
531  * first type in the element type. So for "i" you can't recurse, for
532  * "ai" you can recurse into the array, for "(ii)" you can recurse
533  * into the struct.
534  *
535  * If you recurse into the array for "ai", then you must specify
536  * "i" for the element type of the array you recurse into.
537  * 
538  * While inside an array at any level, we need to avoid writing to
539  * type_str, since the type only appears once for the whole array,
540  * it does not appear for each array element.
541  *
542  * While inside an array type_pos points to the expected next
543  * typecode, rather than the next place we could write a typecode.
544  */
545 static void
546 writer_recurse_init_and_check (DBusTypeWriter *writer,
547                                int             container_type,
548                                DBusTypeWriter *sub)
549 {
550   _dbus_type_writer_init (sub,
551                           writer->byte_order,
552                           writer->type_str,
553                           writer->type_pos,
554                           writer->value_str,
555                           writer->value_pos);
556   
557   sub->container_type = container_type;
558
559   if (writer->inside_array || sub->container_type == DBUS_TYPE_ARRAY)
560     sub->inside_array = TRUE;
561   else
562     sub->inside_array = FALSE;
563   
564 #ifndef DBUS_DISABLE_CHECKS
565   if (writer->inside_array)
566     {
567       int expected;
568
569       expected = first_type_in_signature (writer->type_str, writer->type_pos);
570       
571       if (expected != sub->container_type)
572         {
573           _dbus_warn ("Writing an element of type %s, but the expected type here is %s\n",
574                       _dbus_type_to_string (sub->container_type),
575                       _dbus_type_to_string (expected));
576           _dbus_assert_not_reached ("bad array element written");
577         }
578     }
579 #endif /* DBUS_DISABLE_CHECKS */
580
581   _dbus_verbose ("  type writer %p recurse parent type_pos = %d value_pos = %d inside_array = %d container_type = %s remaining sig '%s'\n",
582                  writer, writer->type_pos, writer->value_pos, writer->inside_array,
583                  _dbus_type_to_string (writer->container_type),
584                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
585   _dbus_verbose ("  type writer %p recurse sub    type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
586                  sub, sub->type_pos, sub->value_pos,
587                  sub->inside_array,
588                  _dbus_type_to_string (sub->container_type));
589 }
590
591 static dbus_bool_t
592 write_or_verify_typecode (DBusTypeWriter *writer,
593                           int             typecode)
594 {
595   /* A subwriter inside an array will have type_pos pointing to the
596    * expected typecode; a writer not inside an array has type_pos
597    * pointing to the next place to insert a typecode.
598    */
599   _dbus_verbose ("  type writer %p write_or_verify start type_pos = %d remaining sig '%s'\n",
600                  writer, writer->type_pos,
601                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
602   
603   if (writer->inside_array)
604     {
605 #ifndef DBUS_DISABLE_CHECKS
606       {
607         int expected;
608         
609         expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
610         
611         if (expected != typecode)
612           {
613             _dbus_warn ("Array type requires that type %s be written, but %s was written\n",
614                         _dbus_type_to_string (expected), _dbus_type_to_string (typecode));
615             _dbus_assert_not_reached ("bad type inserted somewhere inside an array");
616           }
617       }
618 #endif /* DBUS_DISABLE_CHECKS */
619
620       /* if immediately inside an array we'd always be appending an element,
621        * so the expected type doesn't change; if inside a struct or something
622        * below an array, we need to move through said struct or something.
623        */
624       if (writer->container_type != DBUS_TYPE_ARRAY)
625         writer->type_pos += 1;
626     }
627   else
628     {
629       if (!_dbus_string_insert_byte (writer->type_str,
630                                      writer->type_pos,
631                                      typecode))
632         return FALSE;
633
634       writer->type_pos += 1;
635     }
636
637   _dbus_verbose ("  type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
638                  writer, writer->type_pos,
639                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
640   
641   return TRUE;
642 }
643
644 dbus_bool_t
645 _dbus_type_writer_recurse (DBusTypeWriter *writer,
646                            int             container_type,
647                            DBusTypeWriter *sub)
648 {
649   writer_recurse_init_and_check (writer, container_type, sub);
650   
651   switch (container_type)
652     {
653     case DBUS_TYPE_STRUCT:
654       {
655         /* Ensure that we'll be able to add alignment padding and the typecode */
656         if (!_dbus_string_alloc_space (sub->value_str, 8))
657           return FALSE;
658
659         if (!write_or_verify_typecode (sub, DBUS_STRUCT_BEGIN_CHAR))
660           _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
661         
662         if (!_dbus_string_insert_bytes (sub->value_str,
663                                         sub->value_pos,
664                                         _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
665                                         '\0'))
666           _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
667         sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
668       }
669       break;
670     case DBUS_TYPE_ARRAY:
671       _dbus_assert_not_reached ("use recurse_array() for arrays");
672       break;
673     default:
674       _dbus_assert_not_reached ("container_type unhandled");
675       break;
676     }
677   
678   return TRUE;
679 }
680
681 dbus_bool_t
682 _dbus_type_writer_recurse_array (DBusTypeWriter *writer,
683                                  const char     *element_type,
684                                  DBusTypeWriter *sub)
685 {
686   int element_type_len;
687   DBusString element_type_str;
688   dbus_uint32_t value = 0;
689   int alignment;
690   int aligned;
691   DBusString str;
692   
693   writer_recurse_init_and_check (writer, DBUS_TYPE_ARRAY, sub);
694   
695 #ifndef DBUS_DISABLE_CHECKS
696   if (writer->container_type == DBUS_TYPE_ARRAY)
697     {
698       DBusString parent_elements;
699
700       _dbus_assert (element_type != NULL);
701       
702       _dbus_string_init_const (&parent_elements,
703                                _dbus_string_get_const_data_len (writer->type_str,
704                                                                 writer->u.array.element_type_pos + 1,
705                                                                 0));
706                                                                 
707       if (!_dbus_string_starts_with_c_str (&parent_elements, element_type))
708         {
709           _dbus_warn ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
710                       element_type);
711           _dbus_assert_not_reached ("incompatible type for child array");
712         }
713     }
714 #endif /* DBUS_DISABLE_CHECKS */
715   
716   _dbus_string_init_const (&element_type_str, element_type);
717   element_type_len = _dbus_string_get_length (&element_type_str);
718
719   /* 4 bytes for the array length and 4 bytes possible padding */
720   if (!_dbus_string_alloc_space (sub->value_str, 8))
721     return FALSE;
722
723   sub->type_pos += 1; /* move to point to the element type, since type_pos
724                        * should be the expected type for further writes
725                        */
726   sub->u.array.element_type_pos = sub->type_pos;
727   sub->u.array.element_type_len = element_type_len;
728
729   if (!writer->inside_array)
730     {
731       /* sub is a toplevel/outermost array so we need to write the type data */
732       
733       /* alloc space for array typecode, element signature, possible 7
734        * bytes of padding
735        */
736       if (!_dbus_string_alloc_space (writer->type_str, 1 + element_type_len + 7))
737         return FALSE;
738
739       if (!_dbus_string_insert_byte (writer->type_str,
740                                      writer->type_pos,
741                                      DBUS_TYPE_ARRAY))
742         _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
743
744       if (!_dbus_string_copy (&element_type_str, 0,
745                               sub->type_str, sub->u.array.element_type_pos))
746         _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
747     }
748
749   /* Write the length */
750   sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
751
752   if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
753                                                   &value))
754     _dbus_assert_not_reached ("should not have failed to insert array len");
755   
756   _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
757
758   /* Write alignment padding for array elements */
759   _dbus_string_init_const (&str, element_type);
760   alignment = element_type_get_alignment (&str, 0);
761
762   aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
763   if (aligned != sub->value_pos)
764     {
765       if (!_dbus_string_insert_bytes (sub->value_str,
766                                       sub->value_pos,
767                                       aligned - sub->value_pos,
768                                       '\0'))
769         _dbus_assert_not_reached ("should not have failed to insert alignment padding");
770       
771       sub->value_pos = aligned;
772     }
773   sub->u.array.start_pos = sub->value_pos;
774
775   _dbus_assert (sub->u.array.start_pos == sub->value_pos);
776   _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
777
778   _dbus_verbose ("  type writer %p recurse array done remaining sig '%s'\n", sub,
779                  _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
780   
781   return TRUE;
782 }
783
784 dbus_bool_t
785 _dbus_type_writer_unrecurse (DBusTypeWriter *writer,
786                              DBusTypeWriter *sub)
787 {
788   _dbus_assert (sub->type_pos > 0); /* can't be recursed if this fails */
789
790   _dbus_verbose ("  type writer %p unrecurse type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
791                  writer, writer->type_pos, writer->value_pos, writer->inside_array,
792                  _dbus_type_to_string (writer->container_type));
793   _dbus_verbose ("  type writer %p unrecurse sub type_pos = %d value_pos = %d inside_array = %d container_type = %s\n",
794                  sub, sub->type_pos, sub->value_pos,
795                  sub->inside_array,
796                  _dbus_type_to_string (sub->container_type));
797   
798   if (sub->container_type == DBUS_TYPE_STRUCT)
799     {
800       if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
801         return FALSE;
802     }
803   else if (sub->container_type == DBUS_TYPE_ARRAY)
804     {
805       dbus_uint32_t len;
806
807       /* Set the array length */
808       len = sub->value_pos - sub->u.array.start_pos;
809       _dbus_marshal_set_uint32 (sub->value_str,
810                                 sub->byte_order,
811                                 sub->u.array.len_pos,
812                                 len);
813       _dbus_verbose ("    filled in sub array len to %u at len_pos %d\n",
814                      len, sub->u.array.len_pos);
815     }
816
817   /* Jump the parent writer to the new location */
818   if (!writer->inside_array)
819     {
820       if (sub->inside_array)
821         {
822           /* Transition back to type_pos = insertion point from type_pos = expected */
823           
824           _dbus_assert (sub->container_type == DBUS_TYPE_ARRAY);
825           writer->type_pos = sub->u.array.element_type_pos + sub->u.array.element_type_len;
826         }
827       else
828         {
829           writer->type_pos = sub->type_pos;
830         }
831     }
832   writer->value_pos = sub->value_pos;
833
834
835   _dbus_verbose ("  type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
836                  writer, writer->type_pos, writer->value_pos,
837                  _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
838   
839   return TRUE;
840 }
841
842 dbus_bool_t
843 _dbus_type_writer_write_basic (DBusTypeWriter *writer,
844                                int             type,
845                                const void     *value)
846 {
847   dbus_bool_t retval;
848   
849   /* First ensure that our type realloc will succeed */
850   if (!_dbus_string_alloc_space (writer->type_str, 1))
851     return FALSE;
852
853   retval = FALSE;
854
855   if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
856     goto out;
857   
858   if (!write_or_verify_typecode (writer, type))
859     _dbus_assert_not_reached ("failed to write typecode after prealloc");
860   
861   retval = TRUE;
862   
863  out:
864   _dbus_verbose ("  type writer %p basic type_pos = %d value_pos = %d inside_array = %d\n",
865                  writer, writer->type_pos, writer->value_pos, writer->inside_array);
866   
867   return retval;
868 }
869
870 dbus_bool_t
871 _dbus_type_writer_write_array (DBusTypeWriter *writer,
872                                int             type,
873                                const void     *array,
874                                int             array_len)
875 {
876
877
878 }
879
880 /** @} */ /* end of DBusMarshal group */
881
882 #ifdef DBUS_BUILD_TESTS
883 #include "dbus-test.h"
884 #include <stdio.h>
885 #include <stdlib.h>
886
887 typedef struct
888 {
889   DBusString signature;
890   DBusString body;
891 } DataBlock;
892
893 typedef struct
894 {
895   int saved_sig_len;
896   int saved_body_len;
897 } DataBlockState;
898
899 static dbus_bool_t
900 data_block_init (DataBlock *block)
901 {
902   if (!_dbus_string_init (&block->signature))
903     return FALSE;
904
905   if (!_dbus_string_init (&block->body))
906     {
907       _dbus_string_free (&block->signature);
908       return FALSE;
909     }
910   
911   return TRUE;
912 }
913
914 static void
915 data_block_free (DataBlock *block)
916 {
917   _dbus_string_free (&block->signature);
918   _dbus_string_free (&block->body);
919 }
920
921 static void
922 data_block_save (DataBlock      *block,
923                  DataBlockState *state)
924 {
925   state->saved_sig_len = _dbus_string_get_length (&block->signature);
926   state->saved_body_len = _dbus_string_get_length (&block->body);
927 }
928
929 static void
930 data_block_restore (DataBlock      *block,
931                     DataBlockState *state)
932 {
933   /* These set_length should be shortening things so should always work */
934   
935   if (!_dbus_string_set_length (&block->signature,
936                                 state->saved_sig_len))
937     _dbus_assert_not_reached ("could not restore signature length");
938   
939   if (!_dbus_string_set_length (&block->body,
940                                 state->saved_body_len))
941     _dbus_assert_not_reached ("could not restore body length");
942 }
943
944 static void
945 data_block_init_reader_writer (DataBlock      *block,
946                                int             byte_order,
947                                DBusTypeReader *reader,
948                                DBusTypeWriter *writer)
949 {
950   _dbus_type_reader_init (reader,
951                           byte_order,
952                           &block->signature,
953                           _dbus_string_get_length (&block->signature),
954                           &block->body,
955                           _dbus_string_get_length (&block->body));
956   
957   _dbus_type_writer_init (writer,
958                           byte_order,
959                           &block->signature,
960                           _dbus_string_get_length (&block->signature),
961                           &block->body,
962                           _dbus_string_get_length (&block->body));
963 }
964
965 #define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
966  {                                                                                      \
967     _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
968                               _DBUS_FUNCTION_NAME, __LINE__);                           \
969     _dbus_assert_not_reached ("test failed");                                           \
970  }                                                                                      \
971 } while (0)
972
973 #define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
974  {                                                                                      \
975     _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
976                               _DBUS_FUNCTION_NAME, __LINE__);                           \
977     _dbus_assert_not_reached ("test failed");                                           \
978  }                                                                                      \
979  check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
980 } while (0)
981
982 #define SAMPLE_INT32           12345678
983 #define SAMPLE_INT32_ALTERNATE 53781429
984 static dbus_bool_t
985 write_int32 (DataBlock      *block,
986              DBusTypeWriter *writer)
987 {
988   dbus_int32_t v = SAMPLE_INT32;
989
990   return _dbus_type_writer_write_basic (writer,
991                                         DBUS_TYPE_INT32,
992                                         &v);
993 }
994
995 static void
996 real_check_expected_type (DBusTypeReader *reader,
997                           int             expected,
998                           const char     *funcname,
999                           int             line)
1000 {
1001   int t;
1002
1003   t = _dbus_type_reader_get_current_type (reader);
1004   
1005   if (t != expected)
1006     {
1007       _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
1008                   _dbus_type_to_string (t),
1009                   _dbus_type_to_string (expected),
1010                   funcname, line);
1011       
1012       exit (1);
1013     }
1014 }
1015
1016 #define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
1017
1018 static dbus_bool_t
1019 read_int32 (DataBlock      *block,
1020             DBusTypeReader *reader)
1021 {
1022   dbus_int32_t v;
1023
1024   check_expected_type (reader, DBUS_TYPE_INT32);
1025   
1026   _dbus_type_reader_read_basic (reader,
1027                                 (dbus_int32_t*) &v);
1028
1029   _dbus_assert (v == SAMPLE_INT32);
1030
1031   return TRUE;
1032 }
1033
1034 static dbus_bool_t
1035 write_struct_of_int32 (DataBlock      *block,
1036                        DBusTypeWriter *writer)
1037 {
1038   dbus_int32_t v;
1039   DataBlockState saved;
1040   DBusTypeWriter sub;
1041
1042   data_block_save (block, &saved);
1043   
1044   if (!_dbus_type_writer_recurse (writer,
1045                                   DBUS_TYPE_STRUCT,
1046                                   &sub))
1047     return FALSE;
1048
1049   v = SAMPLE_INT32;
1050   if (!_dbus_type_writer_write_basic (&sub,
1051                                       DBUS_TYPE_INT32,
1052                                       &v))
1053     {
1054       data_block_restore (block, &saved);
1055       return FALSE;
1056     }
1057
1058   v = SAMPLE_INT32_ALTERNATE;
1059   if (!_dbus_type_writer_write_basic (&sub,
1060                                       DBUS_TYPE_INT32,
1061                                       &v))
1062     {
1063       data_block_restore (block, &saved);
1064       return FALSE;
1065     }
1066
1067   if (!_dbus_type_writer_unrecurse (writer, &sub))
1068     {
1069       data_block_restore (block, &saved);
1070       return FALSE;
1071     }
1072   
1073   return TRUE;
1074 }
1075
1076 static dbus_bool_t
1077 read_struct_of_int32 (DataBlock      *block,
1078                       DBusTypeReader *reader)
1079 {
1080   dbus_int32_t v;
1081   DBusTypeReader sub;
1082
1083   check_expected_type (reader, DBUS_TYPE_STRUCT);
1084   
1085   _dbus_type_reader_recurse (reader, &sub);
1086
1087   check_expected_type (&sub, DBUS_TYPE_INT32);
1088   
1089   _dbus_type_reader_read_basic (&sub,
1090                                 (dbus_int32_t*) &v);
1091
1092   _dbus_assert (v == SAMPLE_INT32);
1093
1094   NEXT_EXPECTING_TRUE (&sub);
1095   check_expected_type (&sub, DBUS_TYPE_INT32);
1096   
1097   _dbus_type_reader_read_basic (&sub,
1098                                 (dbus_int32_t*) &v);
1099
1100   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1101
1102   NEXT_EXPECTING_FALSE (&sub);
1103   
1104   return TRUE;
1105 }
1106
1107 static dbus_bool_t
1108 write_struct_of_structs (DataBlock      *block,
1109                          DBusTypeWriter *writer)
1110 {
1111   DataBlockState saved;
1112   DBusTypeWriter sub;
1113
1114   data_block_save (block, &saved);
1115   
1116   if (!_dbus_type_writer_recurse (writer,
1117                                   DBUS_TYPE_STRUCT,
1118                                   &sub))
1119     return FALSE;
1120
1121   if (!write_struct_of_int32 (block, &sub))
1122     {
1123       data_block_restore (block, &saved);
1124       return FALSE;
1125     }
1126   if (!write_struct_of_int32 (block, &sub))
1127     {
1128       data_block_restore (block, &saved);
1129       return FALSE;
1130     }
1131   if (!write_struct_of_int32 (block, &sub))
1132     {
1133       data_block_restore (block, &saved);
1134       return FALSE;
1135     }
1136
1137   if (!_dbus_type_writer_unrecurse (writer, &sub))
1138     {
1139       data_block_restore (block, &saved);
1140       return FALSE;
1141     }
1142   
1143   return TRUE;
1144 }
1145
1146 static dbus_bool_t
1147 read_struct_of_structs (DataBlock      *block,
1148                         DBusTypeReader *reader)
1149 {
1150   DBusTypeReader sub;
1151   
1152   check_expected_type (reader, DBUS_TYPE_STRUCT);
1153   
1154   _dbus_type_reader_recurse (reader, &sub);
1155
1156   if (!read_struct_of_int32 (block, &sub))
1157     return FALSE;
1158
1159   NEXT_EXPECTING_TRUE (&sub);
1160   if (!read_struct_of_int32 (block, &sub))
1161     return FALSE;
1162
1163   NEXT_EXPECTING_TRUE (&sub);
1164   if (!read_struct_of_int32 (block, &sub))
1165     return FALSE;
1166   
1167   NEXT_EXPECTING_FALSE (&sub);
1168   
1169   return TRUE;
1170 }
1171
1172 static dbus_bool_t
1173 write_struct_of_structs_of_structs (DataBlock      *block,
1174                                     DBusTypeWriter *writer)
1175 {
1176   DataBlockState saved;
1177   DBusTypeWriter sub;
1178
1179   data_block_save (block, &saved);
1180   
1181   if (!_dbus_type_writer_recurse (writer,
1182                                   DBUS_TYPE_STRUCT,
1183                                   &sub))
1184     return FALSE;
1185
1186   if (!write_struct_of_structs (block, &sub))
1187     {
1188       data_block_restore (block, &saved);
1189       return FALSE;
1190     }
1191   if (!write_struct_of_structs (block, &sub))
1192     {
1193       data_block_restore (block, &saved);
1194       return FALSE;
1195     }
1196
1197   if (!_dbus_type_writer_unrecurse (writer, &sub))
1198     {
1199       data_block_restore (block, &saved);
1200       return FALSE;
1201     }
1202   
1203   return TRUE;
1204 }
1205
1206 static dbus_bool_t
1207 read_struct_of_structs_of_structs (DataBlock      *block,
1208                                    DBusTypeReader *reader)
1209 {
1210   DBusTypeReader sub;
1211   
1212   check_expected_type (reader, DBUS_TYPE_STRUCT);
1213   
1214   _dbus_type_reader_recurse (reader, &sub);
1215
1216   if (!read_struct_of_structs (block, &sub))
1217     return FALSE;
1218
1219   NEXT_EXPECTING_TRUE (&sub);
1220   if (!read_struct_of_structs (block, &sub))
1221     return FALSE;
1222
1223   NEXT_EXPECTING_FALSE (&sub);
1224   
1225   return TRUE;
1226 }
1227
1228 static dbus_bool_t
1229 write_array_of_int32 (DataBlock      *block,
1230                       DBusTypeWriter *writer)
1231 {
1232   dbus_int32_t v;
1233   DataBlockState saved;
1234   DBusTypeWriter sub;
1235
1236   data_block_save (block, &saved);
1237   
1238   if (!_dbus_type_writer_recurse_array (writer,
1239                                         DBUS_TYPE_INT32_AS_STRING,
1240                                         &sub))
1241     return FALSE;
1242
1243   v = SAMPLE_INT32_ALTERNATE;
1244   if (!_dbus_type_writer_write_basic (&sub,
1245                                       DBUS_TYPE_INT32,
1246                                       &v))
1247     {
1248       data_block_restore (block, &saved);
1249       return FALSE;
1250     }
1251
1252   v = SAMPLE_INT32;
1253   if (!_dbus_type_writer_write_basic (&sub,
1254                                       DBUS_TYPE_INT32,
1255                                       &v))
1256     {
1257       data_block_restore (block, &saved);
1258       return FALSE;
1259     }
1260
1261   v = SAMPLE_INT32;
1262   if (!_dbus_type_writer_write_basic (&sub,
1263                                       DBUS_TYPE_INT32,
1264                                       &v))
1265     {
1266       data_block_restore (block, &saved);
1267       return FALSE;
1268     }
1269   
1270   if (!_dbus_type_writer_unrecurse (writer, &sub))
1271     {
1272       data_block_restore (block, &saved);
1273       return FALSE;
1274     }
1275   
1276   return TRUE;
1277 }
1278
1279 static dbus_bool_t
1280 read_array_of_int32 (DataBlock      *block,
1281                      DBusTypeReader *reader)
1282 {
1283   dbus_int32_t v;
1284   DBusTypeReader sub;
1285
1286   check_expected_type (reader, DBUS_TYPE_ARRAY);
1287   
1288   _dbus_type_reader_recurse (reader, &sub);
1289
1290   check_expected_type (&sub, DBUS_TYPE_INT32);
1291   
1292   _dbus_type_reader_read_basic (&sub,
1293                                 (dbus_int32_t*) &v);
1294
1295   _dbus_assert (v == SAMPLE_INT32_ALTERNATE);
1296
1297   NEXT_EXPECTING_TRUE (&sub);
1298   check_expected_type (&sub, DBUS_TYPE_INT32);
1299   
1300   _dbus_type_reader_read_basic (&sub,
1301                                 (dbus_int32_t*) &v);
1302
1303   _dbus_assert (v == SAMPLE_INT32);
1304
1305   NEXT_EXPECTING_TRUE (&sub);
1306   check_expected_type (&sub, DBUS_TYPE_INT32);
1307   
1308   _dbus_type_reader_read_basic (&sub,
1309                                 (dbus_int32_t*) &v);
1310
1311   _dbus_assert (v == SAMPLE_INT32);
1312
1313   NEXT_EXPECTING_FALSE (&sub);
1314   
1315   return TRUE;
1316 }
1317
1318
1319 static dbus_bool_t
1320 write_array_of_int32_empty (DataBlock      *block,
1321                             DBusTypeWriter *writer)
1322 {
1323   DataBlockState saved;
1324   DBusTypeWriter sub;
1325
1326   data_block_save (block, &saved);
1327   
1328   if (!_dbus_type_writer_recurse_array (writer,
1329                                         DBUS_TYPE_INT32_AS_STRING,
1330                                         &sub))
1331     return FALSE;
1332   
1333   if (!_dbus_type_writer_unrecurse (writer, &sub))
1334     {
1335       data_block_restore (block, &saved);
1336       return FALSE;
1337     }
1338   
1339   return TRUE;
1340 }
1341
1342 static dbus_bool_t
1343 read_array_of_int32_empty (DataBlock      *block,
1344                            DBusTypeReader *reader)
1345 {
1346   check_expected_type (reader, DBUS_TYPE_ARRAY);
1347
1348   /* We are iterating over values not types. Thus we can't recurse
1349    * into the array
1350    */
1351   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1352   
1353   return TRUE;
1354 }
1355
1356 static dbus_bool_t
1357 write_array_of_array_of_int32 (DataBlock      *block,
1358                                DBusTypeWriter *writer)
1359 {
1360   DataBlockState saved;
1361   DBusTypeWriter sub;
1362
1363   data_block_save (block, &saved);
1364   
1365   if (!_dbus_type_writer_recurse_array (writer,
1366                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1367                                         &sub))
1368     return FALSE;
1369
1370   if (!write_array_of_int32 (block, &sub))
1371     {
1372       data_block_restore (block, &saved);
1373       return FALSE;
1374     }
1375
1376   if (!write_array_of_int32 (block, &sub))
1377     {
1378       data_block_restore (block, &saved);
1379       return FALSE;
1380     }
1381
1382   if (!write_array_of_int32_empty (block, &sub))
1383     {
1384       data_block_restore (block, &saved);
1385       return FALSE;
1386     }
1387   
1388   if (!write_array_of_int32 (block, &sub))
1389     {
1390       data_block_restore (block, &saved);
1391       return FALSE;
1392     }
1393   
1394   if (!_dbus_type_writer_unrecurse (writer, &sub))
1395     {
1396       data_block_restore (block, &saved);
1397       return FALSE;
1398     }
1399   
1400   return TRUE;
1401 }
1402
1403 static dbus_bool_t
1404 read_array_of_array_of_int32 (DataBlock      *block,
1405                               DBusTypeReader *reader)
1406 {
1407   DBusTypeReader sub;
1408   
1409   check_expected_type (reader, DBUS_TYPE_ARRAY);
1410   
1411   _dbus_type_reader_recurse (reader, &sub);
1412
1413   if (!read_array_of_int32 (block, &sub))
1414     return FALSE;
1415
1416   NEXT_EXPECTING_TRUE (&sub);
1417   if (!read_array_of_int32 (block, &sub))
1418     return FALSE;
1419
1420   NEXT_EXPECTING_TRUE (&sub);
1421   if (!read_array_of_int32_empty (block, &sub))
1422     return FALSE;
1423   
1424   NEXT_EXPECTING_TRUE (&sub);
1425   if (!read_array_of_int32 (block, &sub))
1426     return FALSE;
1427
1428   NEXT_EXPECTING_FALSE (&sub);
1429   
1430   return TRUE;
1431 }
1432
1433
1434 static dbus_bool_t
1435 write_array_of_array_of_int32_empty (DataBlock      *block,
1436                                      DBusTypeWriter *writer)
1437 {
1438   DataBlockState saved;
1439   DBusTypeWriter sub;
1440
1441   data_block_save (block, &saved);
1442   
1443   if (!_dbus_type_writer_recurse_array (writer,
1444                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1445                                         &sub))
1446     return FALSE;
1447
1448   if (!_dbus_type_writer_unrecurse (writer, &sub))
1449     {
1450       data_block_restore (block, &saved);
1451       return FALSE;
1452     }
1453   
1454   return TRUE;
1455 }
1456
1457 static dbus_bool_t
1458 read_array_of_array_of_int32_empty (DataBlock      *block,
1459                                     DBusTypeReader *reader)
1460 {  
1461   check_expected_type (reader, DBUS_TYPE_ARRAY);
1462
1463   /* We are iterating over values, not types. Thus
1464    * we can't recurse in here.
1465    */
1466   
1467   _dbus_assert (_dbus_type_reader_array_is_empty (reader));
1468   
1469   return TRUE;
1470 }
1471
1472 static dbus_bool_t
1473 write_array_of_array_of_array_of_int32 (DataBlock      *block,
1474                                         DBusTypeWriter *writer)
1475 {
1476   DataBlockState saved;
1477   DBusTypeWriter sub;
1478
1479   data_block_save (block, &saved);
1480   
1481   if (!_dbus_type_writer_recurse_array (writer,
1482                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING,
1483                                         &sub))
1484     return FALSE;
1485
1486   if (!write_array_of_array_of_int32 (block, &sub))
1487     {
1488       data_block_restore (block, &saved);
1489       return FALSE;
1490     }
1491
1492   if (!write_array_of_array_of_int32 (block, &sub))
1493     {
1494       data_block_restore (block, &saved);
1495       return FALSE;
1496     }
1497
1498   if (!write_array_of_array_of_int32_empty (block, &sub))
1499     {
1500       data_block_restore (block, &saved);
1501       return FALSE;
1502     }
1503   
1504   if (!_dbus_type_writer_unrecurse (writer, &sub))
1505     {
1506       data_block_restore (block, &saved);
1507       return FALSE;
1508     }
1509   
1510   return TRUE;
1511 }
1512
1513 static dbus_bool_t
1514 read_array_of_array_of_array_of_int32 (DataBlock      *block,
1515                                        DBusTypeReader *reader)
1516 {
1517   DBusTypeReader sub;
1518   
1519   check_expected_type (reader, DBUS_TYPE_ARRAY);
1520   
1521   _dbus_type_reader_recurse (reader, &sub);
1522
1523   if (!read_array_of_array_of_int32 (block, &sub))
1524     return FALSE;
1525
1526   NEXT_EXPECTING_TRUE (&sub);
1527   if (!read_array_of_array_of_int32 (block, &sub))
1528     return FALSE;
1529
1530   NEXT_EXPECTING_TRUE (&sub);
1531   if (!read_array_of_array_of_int32_empty (block, &sub))
1532     return FALSE;
1533
1534   NEXT_EXPECTING_FALSE (&sub);
1535   
1536   return TRUE;
1537 }
1538
1539 static dbus_bool_t
1540 write_struct_of_array_of_int32 (DataBlock      *block,
1541                                 DBusTypeWriter *writer)
1542 {
1543   DataBlockState saved;
1544   DBusTypeWriter sub;
1545
1546   data_block_save (block, &saved);
1547   
1548   if (!_dbus_type_writer_recurse (writer,
1549                                   DBUS_TYPE_STRUCT,
1550                                   &sub))
1551     return FALSE;
1552
1553   if (!write_array_of_int32 (block, &sub))
1554     {
1555       data_block_restore (block, &saved);
1556       return FALSE;
1557     }
1558
1559   if (!write_array_of_int32_empty (block, &sub))
1560     {
1561       data_block_restore (block, &saved);
1562       return FALSE;
1563     }
1564       
1565   if (!_dbus_type_writer_unrecurse (writer, &sub))
1566     {
1567       data_block_restore (block, &saved);
1568       return FALSE;
1569     }
1570   
1571   return TRUE;
1572 }
1573
1574 static dbus_bool_t
1575 read_struct_of_array_of_int32 (DataBlock      *block,
1576                                DBusTypeReader *reader)
1577 {
1578   DBusTypeReader sub;
1579
1580   check_expected_type (reader, DBUS_TYPE_STRUCT);
1581   
1582   _dbus_type_reader_recurse (reader, &sub);
1583
1584   check_expected_type (&sub, DBUS_TYPE_ARRAY);
1585
1586   if (!read_array_of_int32 (block, &sub))
1587     return FALSE;
1588
1589   NEXT_EXPECTING_TRUE (&sub);
1590   if (!read_array_of_int32_empty (block, &sub))
1591     return FALSE;
1592   
1593   NEXT_EXPECTING_FALSE (&sub);
1594   
1595   return TRUE;
1596 }
1597
1598 static dbus_bool_t
1599 write_array_of_struct_of_int32 (DataBlock      *block,
1600                                 DBusTypeWriter *writer)
1601 {
1602   DataBlockState saved;
1603   DBusTypeWriter sub;
1604
1605   data_block_save (block, &saved);
1606
1607   if (!_dbus_type_writer_recurse_array (writer,
1608                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
1609                                         DBUS_TYPE_INT32_AS_STRING
1610                                         DBUS_TYPE_INT32_AS_STRING
1611                                         DBUS_STRUCT_END_CHAR_AS_STRING,
1612                                         &sub))
1613     return FALSE;
1614
1615   if (!write_struct_of_int32 (block, &sub))
1616     {
1617       data_block_restore (block, &saved);
1618       return FALSE;
1619     }
1620
1621   if (!write_struct_of_int32 (block, &sub))
1622     {
1623       data_block_restore (block, &saved);
1624       return FALSE;
1625     }
1626
1627   if (!write_struct_of_int32 (block, &sub))
1628     {
1629       data_block_restore (block, &saved);
1630       return FALSE;
1631     }
1632   
1633   if (!_dbus_type_writer_unrecurse (writer, &sub))
1634     {
1635       data_block_restore (block, &saved);
1636       return FALSE;
1637     }
1638   
1639   return TRUE;
1640 }
1641
1642 static dbus_bool_t
1643 read_array_of_struct_of_int32 (DataBlock      *block,
1644                                DBusTypeReader *reader)
1645 {
1646   DBusTypeReader sub;
1647
1648   check_expected_type (reader, DBUS_TYPE_ARRAY);
1649   
1650   _dbus_type_reader_recurse (reader, &sub);
1651
1652   check_expected_type (&sub, DBUS_TYPE_STRUCT);
1653
1654   if (!read_struct_of_int32 (block, &sub))
1655     return FALSE;
1656   
1657   NEXT_EXPECTING_TRUE (&sub);
1658
1659   if (!read_struct_of_int32 (block, &sub))
1660     return FALSE;
1661   
1662   NEXT_EXPECTING_TRUE (&sub);
1663
1664   if (!read_struct_of_int32 (block, &sub))
1665     return FALSE;
1666   
1667   NEXT_EXPECTING_FALSE (&sub);
1668   
1669   return TRUE;
1670 }
1671
1672 typedef enum {
1673   ITEM_INVALID = -1,
1674   ITEM_INT32 = 0,
1675   ITEM_STRUCT_OF_INT32,
1676   ITEM_STRUCT_OF_STRUCTS,
1677   ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
1678   ITEM_ARRAY_OF_INT32,
1679   ITEM_ARRAY_OF_INT32_EMPTY,
1680   ITEM_ARRAY_OF_ARRAY_OF_INT32,
1681   ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
1682   ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
1683   ITEM_STRUCT_OF_ARRAY_OF_INT32,
1684   ITEM_ARRAY_OF_STRUCT_OF_INT32,
1685   ITEM_LAST
1686 } WhichItem;
1687
1688
1689 typedef dbus_bool_t (* WriteItemFunc) (DataBlock      *block,
1690                                        DBusTypeWriter *writer);
1691 typedef dbus_bool_t (* ReadItemFunc)  (DataBlock      *block,
1692                                        DBusTypeReader *reader);
1693
1694 typedef struct
1695 {
1696   const char *desc;
1697   WhichItem which;
1698   WriteItemFunc write_item_func;
1699   ReadItemFunc read_item_func;
1700 } CheckMarshalItem;
1701
1702 static CheckMarshalItem items[] = {
1703   { "int32",
1704     ITEM_INT32, write_int32, read_int32 },
1705   { "struct with two int32",
1706     ITEM_STRUCT_OF_INT32, write_struct_of_int32, read_struct_of_int32 },
1707   { "struct with three structs of two int32",
1708     ITEM_STRUCT_OF_STRUCTS, write_struct_of_structs, read_struct_of_structs },
1709   { "struct of two structs of three structs of two int32",
1710     ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS,
1711     write_struct_of_structs_of_structs,
1712     read_struct_of_structs_of_structs },
1713   { "array of int32",
1714     ITEM_ARRAY_OF_INT32, write_array_of_int32, read_array_of_int32 },
1715   { "empty array of int32",
1716     ITEM_ARRAY_OF_INT32_EMPTY, write_array_of_int32_empty, read_array_of_int32_empty },
1717   { "array of array of int32",
1718     ITEM_ARRAY_OF_ARRAY_OF_INT32,
1719     write_array_of_array_of_int32, read_array_of_array_of_int32 },
1720   { "empty array of array of int32",
1721     ITEM_ARRAY_OF_ARRAY_OF_INT32_EMPTY,
1722     write_array_of_array_of_int32_empty, read_array_of_array_of_int32_empty },
1723   { "array of array of array of int32",
1724     ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32,
1725     write_array_of_array_of_array_of_int32, read_array_of_array_of_array_of_int32 },
1726   { "struct of array of int32",
1727     ITEM_STRUCT_OF_ARRAY_OF_INT32, write_struct_of_array_of_int32, read_struct_of_array_of_int32 },
1728   { "array of struct of int32",
1729     ITEM_ARRAY_OF_STRUCT_OF_INT32, write_array_of_struct_of_int32, read_array_of_struct_of_int32 },
1730 };
1731
1732 typedef struct
1733 {
1734   /* Array of items from the above items[]; -1 terminated */
1735   int items[20];
1736 } TestRun;
1737
1738 static TestRun runs[] = {
1739   { { ITEM_INVALID } },
1740
1741   /* INT32 */
1742   { { ITEM_INT32, ITEM_INVALID } },
1743   { { ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
1744   { { ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_INVALID } },
1745
1746   /* STRUCT_OF_INT32 */
1747   { { ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
1748   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
1749   { { ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
1750   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
1751   { { ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INT32, ITEM_INT32, ITEM_INT32, ITEM_STRUCT_OF_INT32, ITEM_INVALID } },
1752
1753   /* STRUCT_OF_STRUCTS */
1754   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1755   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1756   { { ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1757   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1758   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1759   { { ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS, ITEM_INVALID } },
1760
1761   /* STRUCT_OF_STRUCTS_OF_STRUCTS */
1762   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1763   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1764   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1765   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1766   { { ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1767   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1768
1769   /* ARRAY_OF_INT32 */
1770   { { ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1771   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1772   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1773   { { ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
1774   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
1775   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1776   { { ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1777   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1778   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1779   { { ITEM_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_INT32, ITEM_INVALID } },
1780
1781   /* ARRAY_OF_ARRAY_OF_INT32 */
1782   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1783   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1784   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1785   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
1786   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
1787   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1788   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1789   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1790   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1791   { { ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1792
1793   /* ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32 */
1794   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1795   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1796   { { 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 } },
1797   { { 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 } },
1798   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_INVALID } },
1799   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1800   { { ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1801   { { ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_STRUCTS_OF_STRUCTS, ITEM_INVALID } },
1802   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1803   { { ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_ARRAY_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1804
1805   /* STRUCT_OF_ARRAY_OF_INT32 */
1806   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1807   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1808   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1809   { { ITEM_STRUCT_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1810   { { ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1811   { { ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_STRUCT_OF_ARRAY_OF_INT32, ITEM_INVALID } },
1812
1813   /* ARRAY_OF_STRUCT_OF_INT32 */
1814   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
1815   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
1816   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
1817   { { ITEM_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
1818   { { ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } },
1819   { { ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_ARRAY_OF_STRUCT_OF_INT32, ITEM_INVALID } }
1820   
1821 };
1822
1823 static dbus_bool_t
1824 perform_one_run (DataBlock *block,
1825                  int        byte_order,
1826                  TestRun   *run)
1827 {
1828   DBusTypeReader reader;
1829   DBusTypeWriter writer;
1830   int i;
1831   DataBlockState saved;
1832   dbus_bool_t retval;
1833
1834   retval = FALSE;
1835
1836   {
1837     _dbus_verbose ("run byteorder %s items ",
1838                    byte_order == DBUS_LITTLE_ENDIAN ? "little" : "big");
1839     i = 0;
1840     while (run->items[i] != ITEM_INVALID)
1841       {
1842         CheckMarshalItem *item = &items[run->items[i]];
1843         
1844         _dbus_verbose ("%s ", item->desc);
1845         ++i;
1846       }
1847     _dbus_verbose (" = %d items\n", i);
1848   }
1849   
1850   data_block_save (block, &saved);
1851   
1852   data_block_init_reader_writer (block, 
1853                                  byte_order,
1854                                  &reader, &writer);
1855
1856   i = 0;
1857   while (run->items[i] != ITEM_INVALID)
1858     {
1859       CheckMarshalItem *item = &items[run->items[i]];
1860
1861       _dbus_verbose (">>writing %s\n", item->desc);
1862       
1863       if (!(* item->write_item_func) (block, &writer))
1864         goto out;
1865       ++i;
1866     }
1867
1868   i = 0;
1869   while (run->items[i] != ITEM_INVALID)
1870     {
1871       CheckMarshalItem *item = &items[run->items[i]];
1872
1873       _dbus_verbose (">>data for reading %s\n", item->desc);
1874       
1875       _dbus_verbose_bytes_of_string (reader.type_str, 0,
1876                                      _dbus_string_get_length (reader.type_str));
1877       _dbus_verbose_bytes_of_string (reader.value_str, 0,
1878                                      _dbus_string_get_length (reader.value_str));
1879       
1880       _dbus_verbose (">>reading %s\n", item->desc);
1881       
1882       if (!(* item->read_item_func) (block, &reader))
1883         goto out;
1884
1885       _dbus_type_reader_next (&reader);
1886       
1887       ++i;
1888     }
1889   
1890   retval = TRUE;
1891   
1892  out:
1893   data_block_restore (block, &saved);
1894   return retval;
1895 }
1896
1897 static dbus_bool_t
1898 perform_all_runs (int byte_order,
1899                   int initial_offset)
1900 {
1901   int i;
1902   DataBlock block;
1903   dbus_bool_t retval;
1904
1905   retval = FALSE;
1906   
1907   if (!data_block_init (&block))
1908     return FALSE;
1909
1910   if (!_dbus_string_lengthen (&block.signature, initial_offset))
1911     goto out;
1912   
1913   if (!_dbus_string_lengthen (&block.body, initial_offset))
1914     goto out;
1915   
1916   i = 0;
1917   while (i < _DBUS_N_ELEMENTS (runs))
1918     {
1919       if (!perform_one_run (&block, byte_order, &runs[i]))
1920         goto out;
1921       
1922       ++i;
1923     }
1924
1925   retval = TRUE;
1926   
1927  out:
1928   data_block_free (&block);
1929   
1930   return retval;
1931 }
1932
1933 static dbus_bool_t
1934 perform_all_items (int byte_order,
1935                    int initial_offset)
1936 {
1937   int i;
1938   DataBlock block;
1939   dbus_bool_t retval;
1940   TestRun run;
1941
1942   retval = FALSE;
1943   
1944   if (!data_block_init (&block))
1945     return FALSE;
1946
1947
1948   if (!_dbus_string_lengthen (&block.signature, initial_offset))
1949     goto out;
1950   
1951   if (!_dbus_string_lengthen (&block.body, initial_offset))
1952     goto out;
1953
1954   /* Create a run containing all the items */
1955   i = 0;
1956   while (i < _DBUS_N_ELEMENTS (items))
1957     {
1958       _dbus_assert (i == items[i].which);
1959       
1960       run.items[i] = items[i].which;
1961       
1962       ++i;
1963     }
1964   
1965   run.items[i] = ITEM_INVALID;
1966
1967   if (!perform_one_run (&block, byte_order, &run))
1968     goto out;  
1969   
1970   retval = TRUE;
1971   
1972  out:
1973   data_block_free (&block);
1974   
1975   return retval;
1976 }
1977
1978 static dbus_bool_t
1979 recursive_marshal_test_iteration (void *data)
1980 {
1981   int i;
1982
1983   i = 0;
1984   while (i < 18)
1985     {
1986       if (!perform_all_runs (DBUS_LITTLE_ENDIAN, i))
1987         return FALSE;
1988       if (!perform_all_runs (DBUS_BIG_ENDIAN, i))
1989         return FALSE;
1990       if (!perform_all_items (DBUS_LITTLE_ENDIAN, i))
1991         return FALSE;
1992       if (!perform_all_items (DBUS_BIG_ENDIAN, i))
1993         return FALSE;
1994       
1995       ++i;
1996     }
1997
1998   return TRUE;
1999 }
2000
2001 dbus_bool_t _dbus_marshal_recursive_test (void);
2002
2003 dbus_bool_t
2004 _dbus_marshal_recursive_test (void)
2005 {
2006   _dbus_test_oom_handling ("recursive marshaling",
2007                            recursive_marshal_test_iteration,
2008                            NULL);  
2009   
2010   return TRUE;
2011 }
2012
2013 #if 1
2014 int
2015 main (int argc, char **argv)
2016 {
2017   _dbus_marshal_recursive_test ();
2018
2019   return 0;
2020 }
2021 #endif /* main() */
2022
2023 #endif /* DBUS_BUILD_TESTS */